Fixed up file indent, comments, and eol-type.

This commit is contained in:
skarg
2009-05-13 03:46:02 +00:00
parent 85c9efd2b5
commit 0c4edb33d9
49 changed files with 6758 additions and 6805 deletions
+3 -3
View File
@@ -153,7 +153,7 @@ void Send_Initialize_Routing_Table(
BACNET_NPDU_DATA npdu_data;
uint8_t number_of_ports = 0;
BACNET_ROUTER_PORT *router_port;
uint8_t i = 0; /* counter */
uint8_t i = 0; /* counter */
npdu_encode_npdu_network(&npdu_data, NETWORK_MESSAGE_INIT_RT_TABLE, true,
MESSAGE_PRIORITY_NORMAL);
@@ -203,8 +203,8 @@ void Send_Initialize_Routing_Table_Ack(
BACNET_ADDRESS dest;
int bytes_sent = 0;
BACNET_NPDU_DATA npdu_data;
/* FIXME: is this parameter needed? */
router_port_list = router_port_list;
/* setup packet for sending */
+2 -1
View File
@@ -325,7 +325,8 @@ static void address_parse(BACNET_ADDRESS * dst,
dst->mac_len = 6;
for (index = 0; index < 4; index++) {
dst->mac[index] = mac[index];
} encode_unsigned16(&dst->mac[4],
}
encode_unsigned16(&dst->mac[4],
port);
} else {
count =
+2 -3
View File
@@ -137,7 +137,7 @@ BACNET_DATE Local_Date; /* rely on OS, if there is one */
If your UTC offset is -5hours of GMT,
then BACnet UTC offset is +5hours.
BACnet UTC offset is expressed in minutes. */
static int32_t UTC_Offset = 5*60;
static int32_t UTC_Offset = 5 * 60;
static bool Daylight_Savings_Status = false; /* rely on OS */
/* List_Of_Session_Keys */
/* Time_Synchronization_Recipients */
@@ -680,8 +680,7 @@ int Device_Encode_Property_APDU(
case PROP_LOCATION:
characterstring_init_ansi(&char_string, Location);
apdu_len =
encode_application_character_string(&apdu[0],
&char_string);
encode_application_character_string(&apdu[0], &char_string);
break;
/* FIXME: if you support time */
case PROP_LOCAL_TIME:
+1 -2
View File
@@ -230,8 +230,7 @@ void cleanup(void) {
old_rpm_property = rpm_property;
rpm_property = rpm_property->next;
free(old_rpm_property);
}
old_rpm_object = rpm_object;
} old_rpm_object = rpm_object;
rpm_object = rpm_object->next;
free(old_rpm_object);
}
+2 -2
View File
@@ -212,8 +212,8 @@ int main(int argc, char *argv[]) {
filename_remove_path(argv[0]), filename_remove_path(argv[0]));
return 0;
}
/* decode the command line parameters */
cov_data.subscriberProcessIdentifier = strtol(argv[1], NULL, 0);
/* decode the command line parameters */ cov_data.
subscriberProcessIdentifier = strtol(argv[1], NULL, 0);
cov_data.initiatingDeviceIdentifier = strtol(argv[2], NULL, 0);
cov_data.monitoredObjectIdentifier.type = strtol(argv[3], NULL, 0);
cov_data.monitoredObjectIdentifier.instance = strtol(argv[4], NULL, 0);
+1 -1
View File
@@ -396,7 +396,7 @@ typedef enum {
BINARY_INACTIVE = 0,
BINARY_ACTIVE = 1,
MAX_BINARY_PV = 1, /* for validating incoming values */
BINARY_NULL = 255 /* our homemade way of storing this info */
BINARY_NULL = 255 /* our homemade way of storing this info */
} BACNET_BINARY_PV;
typedef enum {
+3 -2
View File
@@ -35,8 +35,9 @@
extern "C" {
#endif /* __cplusplus */
void Binary_Output_Init(void);
void Binary_Output_Init(
void);
void Binary_Output_Property_Lists(
const int **pRequired,
const int **pOptional,
+4 -3
View File
@@ -44,9 +44,10 @@
extern "C" {
#endif /* __cplusplus */
void Device_Init(void);
void Device_Init(
void);
void Device_Property_Lists(
const int **pRequired,
const int **pOptional,
+1 -1
View File
@@ -438,7 +438,7 @@ int Device_Encode_Property_APDU(
case PROP_UTC_OFFSET:
/* Note: BACnet Time Zone is offset of local time and UTC,
rather than offset of GMT. It is expressed in minutes */
apdu_len = encode_application_signed(&apdu[0], 5*60 /* EST */ );
apdu_len = encode_application_signed(&apdu[0], 5 * 60 /* EST */ );
break;
case PROP_LOCAL_DATE:
/* FIXME: if you support date */
+97 -94
View File
@@ -1,94 +1,97 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include "hardware.h"
/* stack checking */
#if defined(__GNUC__)
extern uint8_t _end;
extern uint8_t __stack;
#endif
#if defined(__GNUC__)
#define STACK_CANARY (0xC5)
void stack_init(
void) __attribute__ ((naked)) __attribute__ ((section(".init1")));
#endif
void stack_init(
void)
{
#if defined(__GNUC__)
#if 0
uint8_t *p = &_end;
while (p <= &__stack) {
*p = STACK_CANARY;
p++;
}
#else
__asm volatile (
" ldi r30,lo8(_end)\n" " ldi r31,hi8(_end)\n" " ldi r24,lo8(0xc5)\n" /* STACK_CANARY = 0xc5 */
" ldi r25,hi8(__stack)\n" " rjmp .cmp\n" ".loop:\n"
" st Z+,r24\n" ".cmp:\n" " cpi r30,lo8(__stack)\n"
" cpc r31,r25\n" " brlo .loop\n" " breq .loop"::);
#endif
#endif
}
unsigned stack_size(void)
{
#if defined(__GNUC__)
return (&__stack) - (&_end);
#else
return 0;
#endif
}
uint8_t stack_byte(unsigned offset)
{
#if defined(__GNUC__)
return *(&_end + offset);
#else
offset = offset;
return 0;
#endif
}
unsigned stack_unused(void)
{
unsigned count = 0;
#if defined(__GNUC__)
uint8_t *p = &_end;
while (p <= &__stack) {
if ((*p) != STACK_CANARY) {
count = p - (&_end);
break;
}
p++;
}
#endif
return count;
}
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include "hardware.h"
/* stack checking */
#if defined(__GNUC__)
extern uint8_t _end;
extern uint8_t __stack;
#endif
#if defined(__GNUC__)
#define STACK_CANARY (0xC5)
void stack_init(
void) __attribute__ ((naked)) __attribute__ ((section(".init1")));
#endif
void stack_init(
void)
{
#if defined(__GNUC__)
#if 0
uint8_t *p = &_end;
while (p <= &__stack) {
*p = STACK_CANARY;
p++;
}
#else
__asm volatile (
" ldi r30,lo8(_end)\n" " ldi r31,hi8(_end)\n" " ldi r24,lo8(0xc5)\n" /* STACK_CANARY = 0xc5 */
" ldi r25,hi8(__stack)\n" " rjmp .cmp\n" ".loop:\n"
" st Z+,r24\n" ".cmp:\n" " cpi r30,lo8(__stack)\n"
" cpc r31,r25\n" " brlo .loop\n" " breq .loop"::);
#endif
#endif
}
unsigned stack_size(
void)
{
#if defined(__GNUC__)
return (&__stack) - (&_end);
#else
return 0;
#endif
}
uint8_t stack_byte(
unsigned offset)
{
#if defined(__GNUC__)
return *(&_end + offset);
#else
offset = offset;
return 0;
#endif
}
unsigned stack_unused(
void)
{
unsigned count = 0;
#if defined(__GNUC__)
uint8_t *p = &_end;
while (p <= &__stack) {
if ((*p) != STACK_CANARY) {
count = p - (&_end);
break;
}
p++;
}
#endif
return count;
}
+51 -48
View File
@@ -1,48 +1,51 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef STACK_H
#define STACK_H
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* C stack checking */
void stack_init(void);
unsigned stack_size(void);
uint8_t stack_byte(unsigned offset);
unsigned stack_unused(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef STACK_H
#define STACK_H
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* C stack checking */
void stack_init(
void);
unsigned stack_size(
void);
uint8_t stack_byte(
unsigned offset);
unsigned stack_unused(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+228 -228
View File
@@ -1,229 +1,229 @@
###############################################################################
# Makefile for LM Room Controller - AVR
###############################################################################
## General Flags
MCU = atmega644p
AVRDUDE_MCU = m644p
# ATmega644 bootload is at word address 7000h, 7800h, 7C00h, or 7E00h
# Double that value to get the byte address
BOOTLOAD = 0xF800
TARGET = bacnet
## Tools
CC = avr-gcc
AR = avr-ar
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
AVRDUDE = avrdude
LINT = splint
# programmer id--check the avrdude for complete list
# of available opts. These should include stk500,
# avr910, avrisp, bsd, pony and more. Set this to
# one of the valid "-c PROGRAMMER-ID" values
# described in the avrdude info page.
# jtag2fast = Atmel JTAG ICE mkII, running at 115200 Bd
###############################################################################
# Makefile for LM Room Controller - AVR
###############################################################################
## General Flags
MCU = atmega644p
AVRDUDE_MCU = m644p
# ATmega644 bootload is at word address 7000h, 7800h, 7C00h, or 7E00h
# Double that value to get the byte address
BOOTLOAD = 0xF800
TARGET = bacnet
## Tools
CC = avr-gcc
AR = avr-ar
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
AVRDUDE = avrdude
LINT = splint
# programmer id--check the avrdude for complete list
# of available opts. These should include stk500,
# avr910, avrisp, bsd, pony and more. Set this to
# one of the valid "-c PROGRAMMER-ID" values
# described in the avrdude info page.
# jtag2fast = Atmel JTAG ICE mkII, running at 115200 Bd
# jtag2slow = Atmel JTAG ICE mkII, running at 19200 Bd
# avrispmkII = AVR ISP MKII
AVRDUDE_PROGRAMMERID = avrispmkII
#
# # port--serial or parallel port to which your
# # hardware programmer is attached
# # usb can just be usb
AVRDUDE_PORT = usb
# Source locations
BACNET_CORE = ../../src
BACNET_INCLUDE = ../../include
BACNET_DEMO = ../../demo
# local files for this project
CSRC = main.c \
init.c \
stack.c \
input.c \
serial.c \
rs485.c \
timer2.c \
led.c \
eeprom.c \
seeprom.c \
dlmstp.c \
h_wp.c \
h_rp.c \
h_rpm.c \
h_rd.c \
device.c \
ai.c \
bi.c \
bo.c
# common demo files needed
DEMOSRC = $(BACNET_DEMO)/handler/txbuf.c \
$(BACNET_DEMO)/handler/h_npdu.c \
$(BACNET_DEMO)/handler/h_whois.c \
$(BACNET_DEMO)/handler/h_dcc.c \
$(BACNET_DEMO)/handler/s_iam.c \
$(BACNET_DEMO)/handler/noserv.c
# core BACnet stack files
CORESRC = \
$(BACNET_CORE)/fifo.c \
$(BACNET_CORE)/memcopy.c \
$(BACNET_CORE)/crc.c \
$(BACNET_CORE)/apdu.c \
$(BACNET_CORE)/npdu.c \
$(BACNET_CORE)/bacdcode.c \
$(BACNET_CORE)/bacint.c \
$(BACNET_CORE)/bacreal.c \
$(BACNET_CORE)/bacstr.c \
$(BACNET_CORE)/iam.c \
$(BACNET_CORE)/dcc.c \
$(BACNET_CORE)/rp.c \
$(BACNET_CORE)/rd.c \
$(BACNET_CORE)/rpm.c \
$(BACNET_CORE)/wp.c \
$(BACNET_CORE)/whois.c \
$(BACNET_CORE)/bacaddr.c \
$(BACNET_CORE)/abort.c \
$(BACNET_CORE)/reject.c \
$(BACNET_CORE)/bacerror.c \
$(BACNET_CORE)/bacapp.c
# $(BACNET_CORE)/version.c
# $(BACNET_CORE)/bacprop.c \
# $(BACNET_CORE)/bactext.c \
# $(BACNET_CORE)/datetime.c \
# $(BACNET_CORE)/indtext.c \
# $(BACNET_CORE)/bigend.c \
# $(BACNET_CORE)/arf.c \
# $(BACNET_CORE)/awf.c \
# $(BACNET_CORE)/cov.c \
# $(BACNET_CORE)/iam/iam_client.c \
# $(BACNET_CORE)/ihave.c \
# $(BACNET_CORE)/timesync.c \
# $(BACNET_CORE)/whohas.c \
# $(BACNET_CORE)/filename.c \
# $(BACNET_CORE)/tsm.c \
# $(BACNET_CORE)/address.c \
## Include Directories
INCLUDES = -I. -I$(BACNET_INCLUDE)
# Source to Object conversion
COBJ = $(CSRC:%.c=%.o)
DEMOOBJ = $(DEMOSRC:.c=.o)
COREOBJ = $(CORESRC:.c=.o)
LIBRARY = lib$(TARGET).a
## Options common to compile, link and assembly rules
COMMON = -mmcu=$(MCU)
OPTIMIZE_FLAGS = -mcall-prologues
OPTIMIZE_FLAGS += -finline-functions-called-once
# default optimization is for debugging from AVR Studio
OPTIMIZATION = -O0
#OPTIMIZATION = -Os $(OPTIMIZE_FLAGS)
DEBUGGING = -g
# define something from the Makefile or batch file
DEFINES =
## Compile options common for all C compilation units.
BFLAGS = -DBACDL_MSTP
BFLAGS += -DMAX_APDU=128
BFLAGS += -DBIG_ENDIAN=0
BFLAGS += -DMAX_TSM_TRANSACTIONS=0
#BFLAGS += -DCRC_USE_TABLE
BFLAGS += -DBACAPP_BOOLEAN
BFLAGS += -DBACAPP_REAL
BFLAGS += -DBACAPP_OBJECT_ID
BFLAGS += -DBACAPP_UNSIGNED
BFLAGS += -DBACAPP_ENUMERATED
BFLAGS += -DBACAPP_CHARACTER_STRING
BFLAGS += -DWRITE_PROPERTY
CFLAGS = $(COMMON)
CFLAGS += $(DEFINES)
CFLAGS += $(DEBUGGING)
# dead code removal
CFLAGS += -ffunction-sections -fdata-sections
CFLAGS += -Wall -gdwarf-2 $(BFLAGS) $(OPTIMIZATION) -fsigned-char
CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d
## Assembly specific flags
ASMFLAGS = $(COMMON)
ASMFLAGS += $(CFLAGS)
ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
## Linker flags
LDFLAGS = $(COMMON)
#dead code removal
#LDFLAGS += -Wl,-nostartfiles,-nostdlib
LDFLAGS += -Wl,--gc-sections,-static
LDFLAGS += -Wl,--section-start=.bootloader=$(BOOTLOAD)
LDFLAGS += -Wl,-Map=$(TARGET).map
LDFLAGS += -Wl,-L=.,-l$(TARGET)
## Intel Hex file production flags
HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature
HEX_EEPROM_FLAGS = -j .eeprom
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings
## Objects that must be built in order to link
OBJECTS = $(COBJ) $(DEMOOBJ)
## Build
TARGET_ELF=$(TARGET).elf
all: $(LIBRARY) \
$(TARGET_ELF) \
$(TARGET).hex \
$(TARGET).eep \
$(TARGET).lst \
size Makefile
##Link
$(TARGET_ELF): $(OBJECTS) $(LIBRARY)
$(CC) $(OBJECTS) $(LDFLAGS) -o $@
%.hex: $(TARGET_ELF)
$(OBJCOPY) -O ihex $(HEX_FLASH_FLAGS) $< $@
%.eep: $(TARGET_ELF)
-$(OBJCOPY) $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0
%.lst: $(TARGET_ELF)
$(OBJDUMP) -h -S $< > $@
lib: $(LIBRARY)
$(LIBRARY): $(COREOBJ) Makefile
$(AR) rcs $@ $(COREOBJ)
$(OBJDUMP) --syms $@ > $(LIBRARY:.a=.lst)
%.o: %.c
$(CC) -c $(INCLUDES) $(CFLAGS) $*.c -o $@
size: ${TARGET_ELF}
@echo
@${SIZE} ${TARGET_ELF}
lint:
$(LINT) $(BFLAGS) $(CSRC)
install: $(TARGET_ELF)
$(AVRDUDE) -c $(AVRDUDE_PROGRAMMERID) \
-p $(AVRDUDE_MCU) -P $(AVRDUDE_PORT) -e \
-U flash:w:$(TARGET).hex
## Clean target
.PHONY: clean
clean:
-rm -rf $(OBJECTS) $(TARGET_ELF) dep/*
-rm -rf $(LIBRARY) $(COREOBJ) $(LIBRARY:.a=.lst)
-rm -rf $(TARGET).hex $(TARGET).eep $(TARGET).lst $(TARGET).map
## Other dependencies
-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)
# avrispmkII = AVR ISP MKII
AVRDUDE_PROGRAMMERID = avrispmkII
#
# # port--serial or parallel port to which your
# # hardware programmer is attached
# # usb can just be usb
AVRDUDE_PORT = usb
# Source locations
BACNET_CORE = ../../src
BACNET_INCLUDE = ../../include
BACNET_DEMO = ../../demo
# local files for this project
CSRC = main.c \
init.c \
stack.c \
input.c \
serial.c \
rs485.c \
timer2.c \
led.c \
eeprom.c \
seeprom.c \
dlmstp.c \
h_wp.c \
h_rp.c \
h_rpm.c \
h_rd.c \
device.c \
ai.c \
bi.c \
bo.c
# common demo files needed
DEMOSRC = $(BACNET_DEMO)/handler/txbuf.c \
$(BACNET_DEMO)/handler/h_npdu.c \
$(BACNET_DEMO)/handler/h_whois.c \
$(BACNET_DEMO)/handler/h_dcc.c \
$(BACNET_DEMO)/handler/s_iam.c \
$(BACNET_DEMO)/handler/noserv.c
# core BACnet stack files
CORESRC = \
$(BACNET_CORE)/fifo.c \
$(BACNET_CORE)/memcopy.c \
$(BACNET_CORE)/crc.c \
$(BACNET_CORE)/apdu.c \
$(BACNET_CORE)/npdu.c \
$(BACNET_CORE)/bacdcode.c \
$(BACNET_CORE)/bacint.c \
$(BACNET_CORE)/bacreal.c \
$(BACNET_CORE)/bacstr.c \
$(BACNET_CORE)/iam.c \
$(BACNET_CORE)/dcc.c \
$(BACNET_CORE)/rp.c \
$(BACNET_CORE)/rd.c \
$(BACNET_CORE)/rpm.c \
$(BACNET_CORE)/wp.c \
$(BACNET_CORE)/whois.c \
$(BACNET_CORE)/bacaddr.c \
$(BACNET_CORE)/abort.c \
$(BACNET_CORE)/reject.c \
$(BACNET_CORE)/bacerror.c \
$(BACNET_CORE)/bacapp.c
# $(BACNET_CORE)/version.c
# $(BACNET_CORE)/bacprop.c \
# $(BACNET_CORE)/bactext.c \
# $(BACNET_CORE)/datetime.c \
# $(BACNET_CORE)/indtext.c \
# $(BACNET_CORE)/bigend.c \
# $(BACNET_CORE)/arf.c \
# $(BACNET_CORE)/awf.c \
# $(BACNET_CORE)/cov.c \
# $(BACNET_CORE)/iam/iam_client.c \
# $(BACNET_CORE)/ihave.c \
# $(BACNET_CORE)/timesync.c \
# $(BACNET_CORE)/whohas.c \
# $(BACNET_CORE)/filename.c \
# $(BACNET_CORE)/tsm.c \
# $(BACNET_CORE)/address.c \
## Include Directories
INCLUDES = -I. -I$(BACNET_INCLUDE)
# Source to Object conversion
COBJ = $(CSRC:%.c=%.o)
DEMOOBJ = $(DEMOSRC:.c=.o)
COREOBJ = $(CORESRC:.c=.o)
LIBRARY = lib$(TARGET).a
## Options common to compile, link and assembly rules
COMMON = -mmcu=$(MCU)
OPTIMIZE_FLAGS = -mcall-prologues
OPTIMIZE_FLAGS += -finline-functions-called-once
# default optimization is for debugging from AVR Studio
OPTIMIZATION = -O0
#OPTIMIZATION = -Os $(OPTIMIZE_FLAGS)
DEBUGGING = -g
# define something from the Makefile or batch file
DEFINES =
## Compile options common for all C compilation units.
BFLAGS = -DBACDL_MSTP
BFLAGS += -DMAX_APDU=128
BFLAGS += -DBIG_ENDIAN=0
BFLAGS += -DMAX_TSM_TRANSACTIONS=0
#BFLAGS += -DCRC_USE_TABLE
BFLAGS += -DBACAPP_BOOLEAN
BFLAGS += -DBACAPP_REAL
BFLAGS += -DBACAPP_OBJECT_ID
BFLAGS += -DBACAPP_UNSIGNED
BFLAGS += -DBACAPP_ENUMERATED
BFLAGS += -DBACAPP_CHARACTER_STRING
BFLAGS += -DWRITE_PROPERTY
CFLAGS = $(COMMON)
CFLAGS += $(DEFINES)
CFLAGS += $(DEBUGGING)
# dead code removal
CFLAGS += -ffunction-sections -fdata-sections
CFLAGS += -Wall -gdwarf-2 $(BFLAGS) $(OPTIMIZATION) -fsigned-char
CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d
## Assembly specific flags
ASMFLAGS = $(COMMON)
ASMFLAGS += $(CFLAGS)
ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
## Linker flags
LDFLAGS = $(COMMON)
#dead code removal
#LDFLAGS += -Wl,-nostartfiles,-nostdlib
LDFLAGS += -Wl,--gc-sections,-static
LDFLAGS += -Wl,--section-start=.bootloader=$(BOOTLOAD)
LDFLAGS += -Wl,-Map=$(TARGET).map
LDFLAGS += -Wl,-L=.,-l$(TARGET)
## Intel Hex file production flags
HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature
HEX_EEPROM_FLAGS = -j .eeprom
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings
## Objects that must be built in order to link
OBJECTS = $(COBJ) $(DEMOOBJ)
## Build
TARGET_ELF=$(TARGET).elf
all: $(LIBRARY) \
$(TARGET_ELF) \
$(TARGET).hex \
$(TARGET).eep \
$(TARGET).lst \
size Makefile
##Link
$(TARGET_ELF): $(OBJECTS) $(LIBRARY)
$(CC) $(OBJECTS) $(LDFLAGS) -o $@
%.hex: $(TARGET_ELF)
$(OBJCOPY) -O ihex $(HEX_FLASH_FLAGS) $< $@
%.eep: $(TARGET_ELF)
-$(OBJCOPY) $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0
%.lst: $(TARGET_ELF)
$(OBJDUMP) -h -S $< > $@
lib: $(LIBRARY)
$(LIBRARY): $(COREOBJ) Makefile
$(AR) rcs $@ $(COREOBJ)
$(OBJDUMP) --syms $@ > $(LIBRARY:.a=.lst)
%.o: %.c
$(CC) -c $(INCLUDES) $(CFLAGS) $*.c -o $@
size: ${TARGET_ELF}
@echo
@${SIZE} ${TARGET_ELF}
lint:
$(LINT) $(BFLAGS) $(CSRC)
install: $(TARGET_ELF)
$(AVRDUDE) -c $(AVRDUDE_PROGRAMMERID) \
-p $(AVRDUDE_MCU) -P $(AVRDUDE_PORT) -e \
-U flash:w:$(TARGET).hex
## Clean target
.PHONY: clean
clean:
-rm -rf $(OBJECTS) $(TARGET_ELF) dep/*
-rm -rf $(LIBRARY) $(COREOBJ) $(LIBRARY:.a=.lst)
-rm -rf $(TARGET).hex $(TARGET).eep $(TARGET).lst $(TARGET).map
## Other dependencies
-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)
+196 -196
View File
@@ -1,196 +1,196 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Analog Input Objects customize for your use */
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "config.h"
/* Analog Input */
#define MAX_ANALOG_INPUTS 2
#if (MAX_ANALOG_INPUTS > 9)
#error Modify the Analog_Input_Name to handle multiple digits
#endif
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Analog_Input_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_UNITS,
-1
};
static const int Analog_Input_Properties_Optional[] = {
PROP_DESCRIPTION,
-1
};
static const int Analog_Input_Properties_Proprietary[] = {
-1
};
void Analog_Input_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Analog_Input_Properties_Required;
if (pOptional)
*pOptional = Analog_Input_Properties_Optional;
if (pProprietary)
*pProprietary = Analog_Input_Properties_Proprietary;
return;
}
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)
{
if (object_instance < MAX_ANALOG_INPUTS)
return true;
return false;
}
/* we simply have 0-n object instances. */
unsigned Analog_Input_Count(
void)
{
return MAX_ANALOG_INPUTS;
}
/* we simply have 0-n object instances. */
uint32_t Analog_Input_Index_To_Instance(
unsigned index)
{
return index;
}
char *Analog_Input_Name(
uint32_t object_instance)
{
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;
return text_string;
}
return NULL;
}
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;
}
/* return apdu length, or -1 on error */
/* assumption - object has already exists */
int Analog_Input_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
(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;
}
return apdu_len;
}
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Analog Input Objects customize for your use */
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "config.h"
/* Analog Input */
#define MAX_ANALOG_INPUTS 2
#if (MAX_ANALOG_INPUTS > 9)
#error Modify the Analog_Input_Name to handle multiple digits
#endif
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Analog_Input_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_UNITS,
-1
};
static const int Analog_Input_Properties_Optional[] = {
PROP_DESCRIPTION,
-1
};
static const int Analog_Input_Properties_Proprietary[] = {
-1
};
void Analog_Input_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Analog_Input_Properties_Required;
if (pOptional)
*pOptional = Analog_Input_Properties_Optional;
if (pProprietary)
*pProprietary = Analog_Input_Properties_Proprietary;
return;
}
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)
{
if (object_instance < MAX_ANALOG_INPUTS)
return true;
return false;
}
/* we simply have 0-n object instances. */
unsigned Analog_Input_Count(
void)
{
return MAX_ANALOG_INPUTS;
}
/* we simply have 0-n object instances. */
uint32_t Analog_Input_Index_To_Instance(
unsigned index)
{
return index;
}
char *Analog_Input_Name(
uint32_t object_instance)
{
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;
return text_string;
}
return NULL;
}
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;
}
/* return apdu length, or -1 on error */
/* assumption - object has already exists */
int Analog_Input_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
(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;
}
return apdu_len;
}
+232 -232
View File
@@ -1,232 +1,232 @@
/**************************************************************************
*
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Binary Input Objects customize for your use */
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "config.h"
#define MAX_BINARY_INPUTS 8
#if (MAX_BINARY_INPUTS > 9)
#error Modify the Binary_Input_Name to handle multiple digits
#endif
static BACNET_BINARY_PV Present_Value[MAX_BINARY_INPUTS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Binary_Input_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_POLARITY,
-1
};
static const int Binary_Input_Properties_Optional[] = {
PROP_DESCRIPTION,
-1
};
static const int Binary_Input_Properties_Proprietary[] = {
-1
};
void Binary_Input_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (pRequired) {
*pRequired = Binary_Input_Properties_Required;
}
if (pOptional) {
*pOptional = Binary_Input_Properties_Optional;
}
if (pProprietary) {
*pProprietary = Binary_Input_Properties_Proprietary;
}
return;
}
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;
}
}
}
/* we simply have 0-n object instances. */
bool Binary_Input_Valid_Instance(
uint32_t object_instance)
{
if (object_instance < MAX_BINARY_INPUTS)
return true;
return false;
}
/* we simply have 0-n object instances. */
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)
{
return index;
}
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the index */
/* that correlates to the correct instance number */
unsigned Binary_Input_Instance_To_Index(
uint32_t object_instance)
{
unsigned index = MAX_BINARY_INPUTS;
if (object_instance < MAX_BINARY_INPUTS)
index = object_instance;
return index;
}
static BACNET_BINARY_PV Binary_Input_Present_Value(
uint32_t object_instance)
{
BACNET_BINARY_PV value = BINARY_INACTIVE;
unsigned index = 0;
Binary_Input_Initialize();
index = Binary_Input_Instance_To_Index(object_instance);
if (index < MAX_BINARY_INPUTS) {
value = Present_Value[index];
}
return value;
}
char *Binary_Input_Name(
uint32_t object_instance)
{
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;
return text_string;
}
return NULL;
}
/* 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,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
BACNET_POLARITY polarity = POLARITY_NORMAL;
BACNET_BINARY_PV value = BINARY_INACTIVE;
(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;
}
return apdu_len;
}
/**************************************************************************
*
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Binary Input Objects customize for your use */
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "config.h"
#define MAX_BINARY_INPUTS 8
#if (MAX_BINARY_INPUTS > 9)
#error Modify the Binary_Input_Name to handle multiple digits
#endif
static BACNET_BINARY_PV Present_Value[MAX_BINARY_INPUTS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Binary_Input_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_POLARITY,
-1
};
static const int Binary_Input_Properties_Optional[] = {
PROP_DESCRIPTION,
-1
};
static const int Binary_Input_Properties_Proprietary[] = {
-1
};
void Binary_Input_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (pRequired) {
*pRequired = Binary_Input_Properties_Required;
}
if (pOptional) {
*pOptional = Binary_Input_Properties_Optional;
}
if (pProprietary) {
*pProprietary = Binary_Input_Properties_Proprietary;
}
return;
}
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;
}
}
}
/* we simply have 0-n object instances. */
bool Binary_Input_Valid_Instance(
uint32_t object_instance)
{
if (object_instance < MAX_BINARY_INPUTS)
return true;
return false;
}
/* we simply have 0-n object instances. */
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)
{
return index;
}
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the index */
/* that correlates to the correct instance number */
unsigned Binary_Input_Instance_To_Index(
uint32_t object_instance)
{
unsigned index = MAX_BINARY_INPUTS;
if (object_instance < MAX_BINARY_INPUTS)
index = object_instance;
return index;
}
static BACNET_BINARY_PV Binary_Input_Present_Value(
uint32_t object_instance)
{
BACNET_BINARY_PV value = BINARY_INACTIVE;
unsigned index = 0;
Binary_Input_Initialize();
index = Binary_Input_Instance_To_Index(object_instance);
if (index < MAX_BINARY_INPUTS) {
value = Present_Value[index];
}
return value;
}
char *Binary_Input_Name(
uint32_t object_instance)
{
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;
return text_string;
}
return NULL;
}
/* 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,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
BACNET_POLARITY polarity = POLARITY_NORMAL;
BACNET_BINARY_PV value = BINARY_INACTIVE;
(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;
}
return apdu_len;
}
File diff suppressed because it is too large Load Diff
@@ -1,46 +1,46 @@
/* definitions generated by preprocessor, copy into defines.h */
#ifndef PPINC
#define _ATMEGA644P // device select: _ATMEGAxxxx
#define _B2048 // boot size select: _Bxxxx (words), powers of two only
#ifdef __ICCAVR__
#include "iom644.h"
#endif
#if __GNUC__
#include <avr/io.h>
#endif
/* define pin for enter-self-prog-mode */
#define PROGPORT PORTB
#define PROGPIN PINB
#define PROG_NO PB0
/* baud rate register value calculation */
#define CPU_FREQ 18430000
#define BAUD_RATE 115200
#define BRREG_VALUE 9
/* definitions for UART control */
#define BAUD_RATE_LOW_REG UBRR1
#define UART_CONTROL_REG UCSR1B
#define ENABLE_TRANSMITTER_BIT TXEN1
#define ENABLE_RECEIVER_BIT RXEN1
#define UART_STATUS_REG UCSR1A
#define TRANSMIT_COMPLETE_BIT TXC1
#define RECEIVE_COMPLETE_BIT RXC1
#define UART_DATA_REG UDR1
/* definitions for SPM control */
#define SPMCR_REG SPMCSR
#define PAGESIZE 256
#define APP_END 61440
//#define LARGE_MEMORY
/* definitions for device recognition */
#define PARTCODE 0
#define SIGNATURE_BYTE_1 0x1E
#define SIGNATURE_BYTE_2 0x96
#define SIGNATURE_BYTE_3 0x0A
/* indicate that preprocessor result is included */
#define PPINC
#endif
/* definitions generated by preprocessor, copy into defines.h */
#ifndef PPINC
#define _ATMEGA644P /* device select: _ATMEGAxxxx */
#define _B2048 /* boot size select: _Bxxxx (words), powers of two only */
#ifdef __ICCAVR__
#include "iom644.h"
#endif
#if __GNUC__
#include <avr/io.h>
#endif
/* define pin for enter-self-prog-mode */
#define PROGPORT PORTB
#define PROGPIN PINB
#define PROG_NO PB0
/* baud rate register value calculation */
#define CPU_FREQ 18430000
#define BAUD_RATE 115200
#define BRREG_VALUE 9
/* definitions for UART control */
#define BAUD_RATE_LOW_REG UBRR1
#define UART_CONTROL_REG UCSR1B
#define ENABLE_TRANSMITTER_BIT TXEN1
#define ENABLE_RECEIVER_BIT RXEN1
#define UART_STATUS_REG UCSR1A
#define TRANSMIT_COMPLETE_BIT TXC1
#define RECEIVE_COMPLETE_BIT RXC1
#define UART_DATA_REG UDR1
/* definitions for SPM control */
#define SPMCR_REG SPMCSR
#define PAGESIZE 256
#define APP_END 61440
/*#define LARGE_MEMORY */
/* definitions for device recognition */
#define PARTCODE 0
#define SIGNATURE_BYTE_1 0x1E
#define SIGNATURE_BYTE_2 0x96
#define SIGNATURE_BYTE_3 0x0A
/* indicate that preprocessor result is included */
#define PPINC
#endif
@@ -31,11 +31,11 @@
/* Uncomment the following to save code space */
//#define REMOVE_AVRPROG_SUPPORT
//#define REMOVE_FUSE_AND_LOCK_BIT_SUPPORT
//#define REMOVE_BLOCK_SUPPORT
//#define REMOVE_EEPROM_BYTE_SUPPORT
//#define REMOVE_FLASH_BYTE_SUPPORT
/*#define REMOVE_AVRPROG_SUPPORT */
/*#define REMOVE_FUSE_AND_LOCK_BIT_SUPPORT */
/*#define REMOVE_BLOCK_SUPPORT */
/*#define REMOVE_EEPROM_BYTE_SUPPORT */
/*#define REMOVE_FLASH_BYTE_SUPPORT */
/*
* GCC doesn't optimize long int arithmetics very clever. As the
@@ -47,13 +47,19 @@
*/
#ifdef LARGE_MEMORY
# define ADDR_T unsigned long
#else /* !LARGE_MEMORY */
#else /* !LARGE_MEMORY */
# define ADDR_T unsigned int
#endif /* LARGE_MEMORY */
#ifndef REMOVE_BLOCK_SUPPORT
unsigned char BlockLoad(unsigned int size, unsigned char mem, ADDR_T *address);
void BlockRead(unsigned int size, unsigned char mem, ADDR_T *address);
unsigned char BlockLoad(
unsigned int size,
unsigned char mem,
ADDR_T * address);
void BlockRead(
unsigned int size,
unsigned char mem,
ADDR_T * address);
/* BLOCKSIZE should be chosen so that the following holds: BLOCKSIZE*n = PAGESIZE, where n=1,2,3... */
#define BLOCKSIZE PAGESIZE
@@ -61,433 +67,398 @@ void BlockRead(unsigned int size, unsigned char mem, ADDR_T *address);
#endif /* REMOVE_BLOCK_SUPPORT */
#ifdef __ICCAVR__
__C_task void main(void)
__C_task void main(
void)
#else /* ! __ICCAVR__ */
int main(void)
int main(
void)
#endif /* __ICCAVR__ */
{
ADDR_T address;
unsigned int temp_int;
unsigned char val;
/* Initialization */
void (*funcptr)( void ) = 0x0000; // Set up function pointer to RESET vector.
PROGPORT |= (1<<PROG_NO); // Enable pull-up on PROG_NO line on PROGPORT.
initbootuart(); // Initialize UART.
/* Initialization */
void (
*funcptr) (
void) = 0x0000; /* Set up function pointer to RESET vector. */
PROGPORT |= (1 << PROG_NO); /* Enable pull-up on PROG_NO line on PROGPORT. */
initbootuart(); /* Initialize UART. */
/* Branch to bootloader or application code? */
if( !(PROGPIN & (1<<PROG_NO)) ) // If PROGPIN is pulled low, enter programmingmode.
{
if (!(PROGPIN & (1 << PROG_NO))) { /* If PROGPIN is pulled low, enter programmingmode. */
/* Main loop */
for(;;)
{
val=recchar(); // Wait for command character.
for (;;) {
val = recchar(); /* Wait for command character. */
// Check autoincrement status.
if(val=='a')
{
sendchar('Y'); // Yes, we do autoincrement.
/* Check autoincrement status. */
if (val == 'a') {
sendchar('Y'); /* Yes, we do autoincrement. */
}
// Set address.
else if(val=='A') // Set address...
{ // NOTE: Flash addresses are given in words, not bytes.
address=(recchar()<<8) | recchar(); // Read address high and low byte.
sendchar('\r'); // Send OK back.
/* Set address. */
else if (val == 'A') { /* Set address... *//* NOTE: Flash addresses are given in words, not bytes. */
address = (recchar() << 8) | recchar(); /* Read address high and low byte. */
sendchar('\r'); /* Send OK back. */
}
// Chip erase.
else if(val=='e')
{
for(address = 0; address < APP_END;address += PAGESIZE)
{ // NOTE: Here we use address as a byte-address, not word-address, for convenience.
_WAIT_FOR_SPM();
/* Chip erase. */
else if (val == 'e') {
for (address = 0; address < APP_END; address += PAGESIZE) { /* NOTE: Here we use address as a byte-address, not word-address, for convenience. */
_WAIT_FOR_SPM();
#ifdef __ICCAVR__
#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
#pragma diag_suppress=Pe1053 /* Suppress warning for conversion from long-type address to flash ptr. */
#endif
_PAGE_ERASE( address );
_PAGE_ERASE(address);
#ifdef __ICCAVR__
#pragma diag_default=Pe1053 // Back to default.
#pragma diag_default=Pe1053 /* Back to default. */
#endif
}
sendchar('\r'); // Send OK back.
sendchar('\r'); /* Send OK back. */
}
#ifndef REMOVE_BLOCK_SUPPORT
// Check block load support.
else if(val=='b')
{
sendchar('Y'); // Report block load supported.
sendchar((BLOCKSIZE>>8) & 0xFF); // MSB first.
sendchar(BLOCKSIZE&0xFF); // Report BLOCKSIZE (bytes).
}
/* Check block load support. */
else if (val == 'b') {
sendchar('Y'); /* Report block load supported. */
sendchar((BLOCKSIZE >> 8) & 0xFF); /* MSB first. */
sendchar(BLOCKSIZE & 0xFF); /* Report BLOCKSIZE (bytes). */
}
// Start block load.
else if(val=='B')
{
temp_int = (recchar()<<8) | recchar(); // Get block size.
val = recchar(); // Get memtype.
sendchar( BlockLoad(temp_int,val,&address) ); // Block load.
}
// Start block read.
else if(val=='g')
{
temp_int = (recchar()<<8) | recchar(); // Get block size.
val = recchar(); // Get memtype
BlockRead(temp_int,val,&address); // Block read
}
/* Start block load. */
else if (val == 'B') {
temp_int = (recchar() << 8) | recchar(); /* Get block size. */
val = recchar(); /* Get memtype. */
sendchar(BlockLoad(temp_int, val, &address)); /* Block load. */
}
/* Start block read. */
else if (val == 'g') {
temp_int = (recchar() << 8) | recchar(); /* Get block size. */
val = recchar(); /* Get memtype */
BlockRead(temp_int, val, &address); /* Block read */
}
#endif /* REMOVE_BLOCK_SUPPORT */
#ifndef REMOVE_FLASH_BYTE_SUPPORT
// Read program memory.
else if(val=='R')
{
// Send high byte, then low byte of flash word.
_WAIT_FOR_SPM();
#ifndef REMOVE_FLASH_BYTE_SUPPORT
/* Read program memory. */
else if (val == 'R') {
/* Send high byte, then low byte of flash word. */
_WAIT_FOR_SPM();
_ENABLE_RWW_SECTION();
#ifdef __ICCAVR__
#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
#pragma diag_suppress=Pe1053 /* Suppress warning for conversion from long-type address to flash ptr. */
#endif
sendchar( _LOAD_PROGRAM_MEMORY( (address << 1)+1 ) );
sendchar( _LOAD_PROGRAM_MEMORY( (address << 1)+0 ) );
sendchar(_LOAD_PROGRAM_MEMORY((address << 1) + 1));
sendchar(_LOAD_PROGRAM_MEMORY((address << 1) + 0));
#ifdef __ICCAVR__
#pragma diag_default=Pe1053 // Back to default.
#pragma diag_default=Pe1053 /* Back to default. */
#endif
address++; // Auto-advance to next Flash word.
address++; /* Auto-advance to next Flash word. */
}
// Write program memory, low byte.
else if(val=='c')
{ // NOTE: Always use this command before sending high byte.
temp_int=recchar(); // Get low byte for later _FILL_TEMP_WORD.
sendchar('\r'); // Send OK back.
/* Write program memory, low byte. */
else if (val == 'c') { /* NOTE: Always use this command before sending high byte. */
temp_int = recchar(); /* Get low byte for later _FILL_TEMP_WORD. */
sendchar('\r'); /* Send OK back. */
}
// Write program memory, high byte.
else if(val=='C')
{
temp_int |= (recchar()<<8); // Get and insert high byte.
/* Write program memory, high byte. */
else if (val == 'C') {
temp_int |= (recchar() << 8); /* Get and insert high byte. */
_WAIT_FOR_SPM();
#ifdef __ICCAVR__
#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
#pragma diag_suppress=Pe1053 /* Suppress warning for conversion from long-type address to flash ptr. */
#endif
_FILL_TEMP_WORD( (address << 1), temp_int ); // Convert word-address to byte-address and fill.
_FILL_TEMP_WORD((address << 1), temp_int); /* Convert word-address to byte-address and fill. */
#ifdef __ICCAVR__
#pragma diag_default=Pe1053 // Back to default.
#pragma diag_default=Pe1053 /* Back to default. */
#endif
address++; // Auto-advance to next Flash word.
sendchar('\r'); // Send OK back.
address++; /* Auto-advance to next Flash word. */
sendchar('\r'); /* Send OK back. */
}
// Write page.
else if(val== 'm')
{
if( address >= (APP_END>>1) ) // Protect bootloader area.
{
/* Write page. */
else if (val == 'm') {
if (address >= (APP_END >> 1)) { /* Protect bootloader area. */
sendchar('?');
} else
{
_WAIT_FOR_SPM();
} else {
_WAIT_FOR_SPM();
#ifdef __ICCAVR__
#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
#pragma diag_suppress=Pe1053 /* Suppress warning for conversion from long-type address to flash ptr. */
#endif
_PAGE_WRITE( address << 1 ); // Convert word-address to byte-address and write.
_PAGE_WRITE(address << 1); /* Convert word-address to byte-address and write. */
#ifdef __ICCAVR__
#pragma diag_default=Pe1053 // Back to default.
#pragma diag_default=Pe1053 /* Back to default. */
#endif
}
sendchar('\r'); // Send OK back.
sendchar('\r'); /* Send OK back. */
}
#endif /* REMOVE_FLASH_BYTE_SUPPORT */
#ifndef REMOVE_EEPROM_BYTE_SUPPORT
// Write EEPROM memory.
else if (val == 'D')
{
_WAIT_FOR_SPM();
EEARL = address; // Setup EEPROM address.
/* Write EEPROM memory. */
else if (val == 'D') {
_WAIT_FOR_SPM();
EEARL = address; /* Setup EEPROM address. */
EEARH = (address >> 8);
EEDR = recchar(); // Get byte.
EECR |= (1<<EEMWE); // Write byte.
EECR |= (1<<EEWE);
while (EECR & (1<<EEWE)) // Wait for write operation to finish.
EEDR = recchar(); /* Get byte. */
EECR |= (1 << EEMWE); /* Write byte. */
EECR |= (1 << EEWE);
while (EECR & (1 << EEWE)) /* Wait for write operation to finish. */
;
address++; // Auto-advance to next EEPROM byte.
sendchar('\r');// Send OK back.
address++; /* Auto-advance to next EEPROM byte. */
sendchar('\r'); /* Send OK back. */
}
// Read EEPROM memory.
else if (val == 'd')
{
EEARL = address; // Setup EEPROM address.
/* Read EEPROM memory. */
else if (val == 'd') {
EEARL = address; /* Setup EEPROM address. */
EEARH = (address >> 8);
EECR |= (1<<EERE); // Read byte...
sendchar(EEDR); // ...and send it back.
address++; // Auto-advance to next EEPROM byte.
EECR |= (1 << EERE); /* Read byte... */
sendchar(EEDR); /* ...and send it back. */
address++; /* Auto-advance to next EEPROM byte. */
}
#endif /* REMOVE_EEPROM_BYTE_SUPPORT */
#ifndef REMOVE_FUSE_AND_LOCK_BIT_SUPPORT
// Write lockbits.
else if(val=='l')
{
_WAIT_FOR_SPM();
_SET_LOCK_BITS( recchar() ); // Read and set lock bits.
sendchar('\r'); // Send OK back.
/* Write lockbits. */
else if (val == 'l') {
_WAIT_FOR_SPM();
_SET_LOCK_BITS(recchar()); /* Read and set lock bits. */
sendchar('\r'); /* Send OK back. */
}
#if defined(_GET_LOCK_BITS)
// Read lock bits.
else if(val=='r')
{
_WAIT_FOR_SPM();
sendchar( _GET_LOCK_BITS() );
/* Read lock bits. */
else if (val == 'r') {
_WAIT_FOR_SPM();
sendchar(_GET_LOCK_BITS());
}
// Read fuse bits.
else if(val=='F')
{
_WAIT_FOR_SPM();
sendchar( _GET_LOW_FUSES() );
/* Read fuse bits. */
else if (val == 'F') {
_WAIT_FOR_SPM();
sendchar(_GET_LOW_FUSES());
}
// Read high fuse bits.
else if(val=='N')
{
_WAIT_FOR_SPM();
sendchar( _GET_HIGH_FUSES() );
/* Read high fuse bits. */
else if (val == 'N') {
_WAIT_FOR_SPM();
sendchar(_GET_HIGH_FUSES());
}
// Read extended fuse bits.
else if(val=='Q')
{
_WAIT_FOR_SPM();
sendchar( _GET_EXTENDED_FUSES() );
/* Read extended fuse bits. */
else if (val == 'Q') {
_WAIT_FOR_SPM();
sendchar(_GET_EXTENDED_FUSES());
}
#endif /* defined(_GET_LOCK_BITS) */
#endif /* REMOVE_FUSE_AND_LOCK_BIT_SUPPORT */
#ifndef REMOVE_AVRPROG_SUPPORT
// Enter and leave programming mode.
else if((val=='P')||(val=='L'))
{
sendchar('\r'); // Nothing special to do, just answer OK.
}
// Exit bootloader.
else if(val=='E')
{
_WAIT_FOR_SPM();
_ENABLE_RWW_SECTION();
sendchar('\r');
funcptr(); // Jump to Reset vector 0x0000 in Application Section.
#ifndef REMOVE_AVRPROG_SUPPORT
/* Enter and leave programming mode. */
else if ((val == 'P') || (val == 'L')) {
sendchar('\r'); /* Nothing special to do, just answer OK. */
}
// Get programmer type.
else if (val=='p')
{
sendchar('S'); // Answer 'SERIAL'.
/* Exit bootloader. */
else if (val == 'E') {
_WAIT_FOR_SPM();
_ENABLE_RWW_SECTION();
sendchar('\r');
funcptr(); /* Jump to Reset vector 0x0000 in Application Section. */
}
// Return supported device codes.
else if(val=='t')
{
/* Get programmer type. */
else if (val == 'p') {
sendchar('S'); /* Answer 'SERIAL'. */
}
/* Return supported device codes. */
else if (val == 't') {
#if PARTCODE+0 > 0
sendchar( PARTCODE ); // Supports only this device, of course.
sendchar(PARTCODE); /* Supports only this device, of course. */
#endif /* PARTCODE */
sendchar( 0 ); // Send list terminator.
sendchar(0); /* Send list terminator. */
}
// Set LED, clear LED and set device type.
else if((val=='x')||(val=='y')||(val=='T'))
{
recchar(); // Ignore the command and it's parameter.
sendchar('\r'); // Send OK back.
/* Set LED, clear LED and set device type. */
else if ((val == 'x') || (val == 'y') || (val == 'T')) {
recchar(); /* Ignore the command and it's parameter. */
sendchar('\r'); /* Send OK back. */
}
#endif /* REMOVE_AVRPROG_SUPPORT */
// Return programmer identifier.
else if(val=='S')
{
sendchar('A'); // Return 'AVRBOOT'.
sendchar('V'); // Software identifier (aka programmer signature) is always 7 characters.
/* Return programmer identifier. */
else if (val == 'S') {
sendchar('A'); /* Return 'AVRBOOT'. */
sendchar('V'); /* Software identifier (aka programmer signature) is always 7 characters. */
sendchar('R');
sendchar('B');
sendchar('O');
sendchar('O');
sendchar('T');
}
// Return software version.
else if(val=='V')
{
/* Return software version. */
else if (val == 'V') {
sendchar('1');
sendchar('5');
}
}
// Return signature bytes.
else if(val=='s')
{
sendchar( SIGNATURE_BYTE_3 );
sendchar( SIGNATURE_BYTE_2 );
sendchar( SIGNATURE_BYTE_1 );
}
/* Return signature bytes. */
else if (val == 's') {
sendchar(SIGNATURE_BYTE_3);
sendchar(SIGNATURE_BYTE_2);
sendchar(SIGNATURE_BYTE_1);
}
// The last command to accept is ESC (synchronization).
else if(val!=0x1b) // If not ESC, then it is unrecognized...
{
/* The last command to accept is ESC (synchronization). */
else if (val != 0x1b) { /* If not ESC, then it is unrecognized... */
sendchar('?');
}
} // end: for(;;)
}
else
{
_WAIT_FOR_SPM();
} /* end: for(;;) */
} else {
_WAIT_FOR_SPM();
_ENABLE_RWW_SECTION();
funcptr(); // Jump to Reset vector 0x0000 in Application Section.
funcptr(); /* Jump to Reset vector 0x0000 in Application Section. */
}
} // end: main
} /* end: main */
#ifndef REMOVE_BLOCK_SUPPORT
unsigned char BlockLoad(unsigned int size, unsigned char mem, ADDR_T *address)
unsigned char BlockLoad(
unsigned int size,
unsigned char mem,
ADDR_T * address)
{
unsigned char buffer[BLOCKSIZE];
unsigned int data;
ADDR_T tempaddress;
// EEPROM memory type.
if(mem=='E')
{
/* EEPROM memory type. */
if (mem == 'E') {
/* Fill buffer first, as EEPROM is too slow to copy with UART speed */
for(tempaddress=0;tempaddress<size;tempaddress++)
for (tempaddress = 0; tempaddress < size; tempaddress++)
buffer[tempaddress] = recchar();
/* Then program the EEPROM */
_WAIT_FOR_SPM();
for( tempaddress=0; tempaddress < size; tempaddress++)
{
EEARL = *address; // Setup EEPROM address
for (tempaddress = 0; tempaddress < size; tempaddress++) {
EEARL = *address; /* Setup EEPROM address */
EEARH = ((*address) >> 8);
EEDR = buffer[tempaddress]; // Get byte.
EECR |= (1<<EEMWE); // Write byte.
EECR |= (1<<EEWE);
while (EECR & (1<<EEWE)) // Wait for write operation to finish.
EEDR = buffer[tempaddress]; /* Get byte. */
EECR |= (1 << EEMWE); /* Write byte. */
EECR |= (1 << EEWE);
while (EECR & (1 << EEWE)) /* Wait for write operation to finish. */
;
(*address)++; // Select next EEPROM byte
(*address)++; /* Select next EEPROM byte */
}
return '\r'; // Report programming OK
}
// Flash memory type.
else if(mem=='F')
{ // NOTE: For flash programming, 'address' is given in words.
(*address) <<= 1; // Convert address to bytes temporarily.
tempaddress = (*address); // Store address in page.
do
{
return '\r'; /* Report programming OK */
}
/* Flash memory type. */
else if (mem == 'F') { /* NOTE: For flash programming, 'address' is given in words. */
(*address) <<= 1; /* Convert address to bytes temporarily. */
tempaddress = (*address); /* Store address in page. */
do {
data = recchar();
data |= (recchar() << 8);
#ifdef __ICCAVR__
#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
#pragma diag_suppress=Pe1053 /* Suppress warning for conversion from long-type address to flash ptr. */
#endif
_FILL_TEMP_WORD(*address,data);
_FILL_TEMP_WORD(*address, data);
#ifdef __ICCAVR__
#pragma diag_default=Pe1053 // Back to default.
#pragma diag_default=Pe1053 /* Back to default. */
#endif
(*address)+=2; // Select next word in memory.
size -= 2; // Reduce number of bytes to write by two.
} while(size); // Loop until all bytes written.
(*address) += 2; /* Select next word in memory. */
size -= 2; /* Reduce number of bytes to write by two. */
} while (size); /* Loop until all bytes written. */
#ifdef __ICCAVR__
#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
#pragma diag_suppress=Pe1053 /* Suppress warning for conversion from long-type address to flash ptr. */
#endif
_PAGE_WRITE(tempaddress);
_PAGE_WRITE(tempaddress);
#ifdef __ICCAVR__
#pragma diag_default=Pe1053 // Back to default.
#pragma diag_default=Pe1053 /* Back to default. */
#endif
_WAIT_FOR_SPM();
_ENABLE_RWW_SECTION();
_WAIT_FOR_SPM();
_ENABLE_RWW_SECTION();
(*address) >>= 1; // Convert address back to Flash words again.
return '\r'; // Report programming OK
(*address) >>= 1; /* Convert address back to Flash words again. */
return '\r'; /* Report programming OK */
}
// Invalid memory type?
else
{
/* Invalid memory type? */
else {
return '?';
}
}
void BlockRead(unsigned int size, unsigned char mem, ADDR_T *address)
void BlockRead(
unsigned int size,
unsigned char mem,
ADDR_T * address)
{
// EEPROM memory type.
if (mem=='E') // Read EEPROM
{
do
{
EEARL = *address; // Setup EEPROM address
/* EEPROM memory type. */
if (mem == 'E') { /* Read EEPROM */
do {
EEARL = *address; /* Setup EEPROM address */
EEARH = ((*address) >> 8);
(*address)++; // Select next EEPROM byte
EECR |= (1<<EERE); // Read EEPROM
sendchar(EEDR); // Transmit EEPROM dat ato PC
(*address)++; /* Select next EEPROM byte */
EECR |= (1 << EERE); /* Read EEPROM */
sendchar(EEDR); /* Transmit EEPROM dat ato PC */
size--; // Decrease number of bytes to read
} while (size); // Repeat until all block has been read
size--; /* Decrease number of bytes to read */
} while (size); /* Repeat until all block has been read */
}
// Flash memory type.
else if(mem=='F')
{
(*address) <<= 1; // Convert address to bytes temporarily.
do
{
#ifdef __ICCAVR__
#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
#endif
sendchar( _LOAD_PROGRAM_MEMORY(*address) );
sendchar( _LOAD_PROGRAM_MEMORY((*address)+1) );
#ifdef __ICCAVR__
#pragma diag_default=Pe1053 // Back to default.
#endif
(*address) += 2; // Select next word in memory.
size -= 2; // Subtract two bytes from number of bytes to read
} while (size); // Repeat until all block has been read
(*address) >>= 1; // Convert address back to Flash words again.
/* Flash memory type. */
else if (mem == 'F') {
(*address) <<= 1; /* Convert address to bytes temporarily. */
do {
#ifdef __ICCAVR__
#pragma diag_suppress=Pe1053 /* Suppress warning for conversion from long-type address to flash ptr. */
#endif
sendchar(_LOAD_PROGRAM_MEMORY(*address));
sendchar(_LOAD_PROGRAM_MEMORY((*address) + 1));
#ifdef __ICCAVR__
#pragma diag_default=Pe1053 /* Back to default. */
#endif
(*address) += 2; /* Select next word in memory. */
size -= 2; /* Subtract two bytes from number of bytes to read */
} while (size); /* Repeat until all block has been read */
(*address) >>= 1; /* Convert address back to Flash words again. */
}
}
#endif /* REMOVE_BLOCK_SUPPORT */
@@ -19,24 +19,26 @@
#include "defines.h"
void initbootuart(void)
void initbootuart(
void)
{
BAUD_RATE_LOW_REG = BRREG_VALUE;
UART_CONTROL_REG = (1 << ENABLE_RECEIVER_BIT) |
(1 << ENABLE_TRANSMITTER_BIT); // enable receive and transmit
BAUD_RATE_LOW_REG = BRREG_VALUE;
UART_CONTROL_REG = (1 << ENABLE_RECEIVER_BIT) | (1 << ENABLE_TRANSMITTER_BIT); /* enable receive and transmit */
}
void sendchar(unsigned char c)
void sendchar(
unsigned char c)
{
UART_DATA_REG = c; // prepare transmission
while (!(UART_STATUS_REG & (1 << TRANSMIT_COMPLETE_BIT)));// wait until byte sendt
UART_STATUS_REG |= (1 << TRANSMIT_COMPLETE_BIT); // delete TXCflag
UART_DATA_REG = c; /* prepare transmission */
while (!(UART_STATUS_REG & (1 << TRANSMIT_COMPLETE_BIT))); /* wait until byte sendt */
UART_STATUS_REG |= (1 << TRANSMIT_COMPLETE_BIT); /* delete TXCflag */
}
unsigned char recchar(void)
unsigned char recchar(
void)
{
while(!(UART_STATUS_REG & (1 << RECEIVE_COMPLETE_BIT))); // wait for data
return UART_DATA_REG;
while (!(UART_STATUS_REG & (1 << RECEIVE_COMPLETE_BIT))); /* wait for data */
return UART_DATA_REG;
}
@@ -17,6 +17,9 @@
* Description : Header file for serial.c
****************************************************************************/
void initbootuart( void );
void sendchar( unsigned char );
unsigned char recchar( void );
void initbootuart(
void);
void sendchar(
unsigned char);
unsigned char recchar(
void);
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+70 -70
View File
@@ -1,70 +1,70 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "hardware.h"
#include "eeprom.h"
/* Internal EEPROM of the AVR - http://supp.iar.com/Support/?note=45745 */
#if defined(__GNUC__)
/* bug in WinAVR - not quite IAR compatible */
#define __EEPUT _EEPUT
#define __EEGET _EEGET
#endif
int eeprom_bytes_read(
uint16_t eeaddr, /* EEPROM starting memory address (offset of zero) */
uint8_t * buf, /* data to store */
int len) /* number of bytes of data to read */
{
int count = 0; /* return value */
while (len) {
__EEGET(buf[count], eeaddr);
count++;
eeaddr++;
len--;
}
return count;
}
int eeprom_bytes_write(
uint16_t eeaddr, /* EEPROM starting memory address */
uint8_t * buf, /* data to send */
int len) /* number of bytes of data */
{
int count = 0;
while (len) {
__EEPUT(eeaddr, buf[count]);
count++;
eeaddr++;
len--;
}
return count;
}
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "hardware.h"
#include "eeprom.h"
/* Internal EEPROM of the AVR - http://supp.iar.com/Support/?note=45745 */
#if defined(__GNUC__)
/* bug in WinAVR - not quite IAR compatible */
#define __EEPUT _EEPUT
#define __EEGET _EEGET
#endif
int eeprom_bytes_read(
uint16_t eeaddr, /* EEPROM starting memory address (offset of zero) */
uint8_t * buf, /* data to store */
int len)
{ /* number of bytes of data to read */
int count = 0; /* return value */
while (len) {
__EEGET(buf[count], eeaddr);
count++;
eeaddr++;
len--;
}
return count;
}
int eeprom_bytes_write(
uint16_t eeaddr, /* EEPROM starting memory address */
uint8_t * buf, /* data to send */
int len)
{ /* number of bytes of data */
int count = 0;
while (len) {
__EEPUT(eeaddr, buf[count]);
count++;
eeaddr++;
len--;
}
return count;
}
+46 -46
View File
@@ -1,46 +1,46 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#ifndef EEPROM_H
#define EEPROM_H
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
int eeprom_bytes_read(
uint16_t ee_address, /* EEPROM starting memory address */
uint8_t * buffer, /* data to store */
int nbytes); /* number of bytes of data to read */
int eeprom_bytes_write(
uint16_t ee_address, /* EEPROM starting memory address */
uint8_t * buffer, /* data to send */
int nbytes); /* number of bytes of data */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#ifndef EEPROM_H
#define EEPROM_H
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
int eeprom_bytes_read(
uint16_t ee_address, /* EEPROM starting memory address */
uint8_t * buffer, /* data to store */
int nbytes); /* number of bytes of data to read */
int eeprom_bytes_write(
uint16_t ee_address, /* EEPROM starting memory address */
uint8_t * buffer, /* data to send */
int nbytes); /* number of bytes of data */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+113 -113
View File
@@ -1,113 +1,113 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "config.h"
#include "txbuf.h"
#include "bacdef.h"
#include "bacdcode.h"
#include "bacerror.h"
#include "apdu.h"
#include "npdu.h"
#include "abort.h"
#include "reject.h"
#include "rd.h"
static char *Password = "rehmite";
static BACNET_CHARACTER_STRING My_Password;
void handler_reinitialize_device(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_REINITIALIZED_STATE state;
BACNET_CHARACTER_STRING their_password;
int len = 0;
int pdu_len = 0;
BACNET_NPDU_DATA npdu_data;
int bytes_sent = 0;
BACNET_ADDRESS my_address;
/* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address);
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
pdu_len =
npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
&npdu_data);
if (service_data->segmented_message) {
len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
goto RD_ABORT;
}
/* decode the service request only */
len =
rd_decode_service_request(service_request, service_len, &state,
&their_password);
/* 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 RD_ABORT;
}
/* check the data from the request */
if (state >= MAX_BACNET_REINITIALIZED_STATE) {
len =
reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, REJECT_REASON_UNDEFINED_ENUMERATION);
} else {
characterstring_init_ansi(&My_Password, Password);
if (characterstring_same(&their_password, &My_Password)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_REINITIALIZE_DEVICE);
/* FIXME: now you can reboot, restart, quit, or something clever */
/* Note: you can use a mix of state and password to do specific stuff */
/* Note: if you don't do something clever like actually restart,
you probably should clear any DCC status and timeouts */
/* Note: you probably need to send the reply BEFORE restarting */
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
ERROR_CLASS_SERVICES, ERROR_CODE_PASSWORD_FAILURE);
}
}
RD_ABORT:
pdu_len += len;
bytes_sent =
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
pdu_len);
return;
}
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "config.h"
#include "txbuf.h"
#include "bacdef.h"
#include "bacdcode.h"
#include "bacerror.h"
#include "apdu.h"
#include "npdu.h"
#include "abort.h"
#include "reject.h"
#include "rd.h"
static char *Password = "rehmite";
static BACNET_CHARACTER_STRING My_Password;
void handler_reinitialize_device(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_REINITIALIZED_STATE state;
BACNET_CHARACTER_STRING their_password;
int len = 0;
int pdu_len = 0;
BACNET_NPDU_DATA npdu_data;
int bytes_sent = 0;
BACNET_ADDRESS my_address;
/* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address);
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
pdu_len =
npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
&npdu_data);
if (service_data->segmented_message) {
len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
goto RD_ABORT;
}
/* decode the service request only */
len =
rd_decode_service_request(service_request, service_len, &state,
&their_password);
/* 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 RD_ABORT;
}
/* check the data from the request */
if (state >= MAX_BACNET_REINITIALIZED_STATE) {
len =
reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, REJECT_REASON_UNDEFINED_ENUMERATION);
} else {
characterstring_init_ansi(&My_Password, Password);
if (characterstring_same(&their_password, &My_Password)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_REINITIALIZE_DEVICE);
/* FIXME: now you can reboot, restart, quit, or something clever */
/* Note: you can use a mix of state and password to do specific stuff */
/* Note: if you don't do something clever like actually restart,
you probably should clear any DCC status and timeouts */
/* Note: you probably need to send the reply BEFORE restarting */
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
ERROR_CLASS_SERVICES, ERROR_CODE_PASSWORD_FAILURE);
}
}
RD_ABORT:
pdu_len += len;
bytes_sent =
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
pdu_len);
return;
}
+180 -180
View File
@@ -1,180 +1,180 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "config.h"
#include "txbuf.h"
#include "bacdef.h"
#include "bacdcode.h"
#include "bacerror.h"
#include "apdu.h"
#include "npdu.h"
#include "abort.h"
#include "rp.h"
/* demo objects */
#include "device.h"
#include "ai.h"
#include "bi.h"
#include "bo.h"
static uint8_t Temp_Buf[MAX_APDU] = { 0 };
/* Encodes the property APDU and returns the length,
or sets the error, and returns -1 */
int Encode_Property_APDU(
uint8_t * apdu,
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = -1;
/* initialize the default return values */
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
/* handle each 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);
}
break;
case OBJECT_ANALOG_INPUT:
if (Analog_Input_Valid_Instance(object_instance)) {
apdu_len =
Analog_Input_Encode_Property_APDU(&apdu[0],
object_instance, 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],
object_instance, property, array_index, error_class,
error_code);
}
break;
case OBJECT_BINARY_OUTPUT:
if (Binary_Output_Valid_Instance(object_instance)) {
apdu_len =
Binary_Output_Encode_Property_APDU(&apdu[0],
object_instance, property, array_index, error_class,
error_code);
}
break;
default:
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNSUPPORTED_OBJECT_TYPE;
break;
}
return apdu_len;
}
void handler_read_property(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_READ_PROPERTY_DATA data;
int len = 0;
int pdu_len = 0;
BACNET_NPDU_DATA npdu_data;
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_ADDRESS my_address;
/* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address);
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
pdu_len =
npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
&npdu_data);
if (service_data->segmented_message) {
/* we don't support segmentation - send an abort */
len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
goto RP_ABORT;
}
len = rp_decode_service_request(service_request, service_len, &data);
if (len < 0) {
/* bad decoding - send an abort */
len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_OTHER, true);
goto RP_ABORT;
}
/* most cases will be error */
error = true;
len =
Encode_Property_APDU(&Temp_Buf[0], data.object_type,
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;
}
if (error) {
if (len == -2) {
/* BACnet APDU too small to fit data, so proper response is Abort */
len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
goto RP_ABORT;
}
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY,
error_class, error_code);
}
RP_ABORT:
pdu_len += len;
bytes_sent =
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
pdu_len);
return;
}
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "config.h"
#include "txbuf.h"
#include "bacdef.h"
#include "bacdcode.h"
#include "bacerror.h"
#include "apdu.h"
#include "npdu.h"
#include "abort.h"
#include "rp.h"
/* demo objects */
#include "device.h"
#include "ai.h"
#include "bi.h"
#include "bo.h"
static uint8_t Temp_Buf[MAX_APDU] = { 0 };
/* Encodes the property APDU and returns the length,
or sets the error, and returns -1 */
int Encode_Property_APDU(
uint8_t * apdu,
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = -1;
/* initialize the default return values */
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
/* handle each 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);
}
break;
case OBJECT_ANALOG_INPUT:
if (Analog_Input_Valid_Instance(object_instance)) {
apdu_len =
Analog_Input_Encode_Property_APDU(&apdu[0],
object_instance, 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],
object_instance, property, array_index, error_class,
error_code);
}
break;
case OBJECT_BINARY_OUTPUT:
if (Binary_Output_Valid_Instance(object_instance)) {
apdu_len =
Binary_Output_Encode_Property_APDU(&apdu[0],
object_instance, property, array_index, error_class,
error_code);
}
break;
default:
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNSUPPORTED_OBJECT_TYPE;
break;
}
return apdu_len;
}
void handler_read_property(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_READ_PROPERTY_DATA data;
int len = 0;
int pdu_len = 0;
BACNET_NPDU_DATA npdu_data;
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_ADDRESS my_address;
/* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address);
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
pdu_len =
npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
&npdu_data);
if (service_data->segmented_message) {
/* we don't support segmentation - send an abort */
len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
goto RP_ABORT;
}
len = rp_decode_service_request(service_request, service_len, &data);
if (len < 0) {
/* bad decoding - send an abort */
len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_OTHER, true);
goto RP_ABORT;
}
/* most cases will be error */
error = true;
len =
Encode_Property_APDU(&Temp_Buf[0], data.object_type,
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;
}
if (error) {
if (len == -2) {
/* BACnet APDU too small to fit data, so proper response is Abort */
len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
goto RP_ABORT;
}
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY,
error_class, error_code);
}
RP_ABORT:
pdu_len += len;
bytes_sent =
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
pdu_len);
return;
}
+134 -134
View File
@@ -1,134 +1,134 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "config.h"
#include "txbuf.h"
#include "bacdef.h"
#include "bacdcode.h"
#include "bacerror.h"
#include "apdu.h"
#include "npdu.h"
#include "abort.h"
#include "wp.h"
/* demo objects */
#include "device.h"
#include "ai.h"
#include "bi.h"
#include "bo.h"
/* too big to reside on stack frame for PIC */
static BACNET_WRITE_PROPERTY_DATA wp_data;
void handler_write_property(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
int len = 0;
int pdu_len = 0;
BACNET_NPDU_DATA npdu_data;
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
int bytes_sent = 0;
BACNET_ADDRESS my_address;
/* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address);
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
pdu_len =
npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
&npdu_data);
if (service_data->segmented_message) {
len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
goto WP_ABORT;
}
/* decode the service request only */
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;
}
/* 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 {
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_OUTPUT:
if (Binary_Output_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;
}
WP_ABORT:
pdu_len += len;
bytes_sent =
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
pdu_len);
return;
}
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "config.h"
#include "txbuf.h"
#include "bacdef.h"
#include "bacdcode.h"
#include "bacerror.h"
#include "apdu.h"
#include "npdu.h"
#include "abort.h"
#include "wp.h"
/* demo objects */
#include "device.h"
#include "ai.h"
#include "bi.h"
#include "bo.h"
/* too big to reside on stack frame for PIC */
static BACNET_WRITE_PROPERTY_DATA wp_data;
void handler_write_property(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
int len = 0;
int pdu_len = 0;
BACNET_NPDU_DATA npdu_data;
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
int bytes_sent = 0;
BACNET_ADDRESS my_address;
/* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address);
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
pdu_len =
npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
&npdu_data);
if (service_data->segmented_message) {
len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
goto WP_ABORT;
}
/* decode the service request only */
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;
}
/* 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 {
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_OUTPUT:
if (Binary_Output_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;
}
WP_ABORT:
pdu_len += len;
bytes_sent =
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
pdu_len);
return;
}
+55 -55
View File
@@ -1,55 +1,55 @@
/**************************************************************************
*
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef HARDWARE_H
#define HARDWARE_H
#if !defined(F_CPU)
/* The processor clock frequency */
#define F_CPU 18430000UL
#endif
#if defined(__ICCAVR__)
#include <iom644p.h>
#endif
#if defined(__GNUC__)
#if !defined(__AVR_ATmega644P__)
#error Firmware is configured for ATmega644P only (-mmcu=atmega644p)
#endif
/* GCC specific configuration */
#include <avr/wdt.h>
#endif
#include "iar2gcc.h"
#include "bits.h"
/* SEEPROM is 24LC128 */
//#define SEEPROM_PAGE_SIZE 128
//#define SEEPROM_WORD_ADDRESS_16BIT 1
/* SEEPROM is 24C16 */
#define SEEPROM_PAGE_SIZE 16
#define SEEPROM_WORD_ADDRESS_16BIT 0
#endif
/**************************************************************************
*
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef HARDWARE_H
#define HARDWARE_H
#if !defined(F_CPU)
/* The processor clock frequency */
#define F_CPU 18430000UL
#endif
#if defined(__ICCAVR__)
#include <iom644p.h>
#endif
#if defined(__GNUC__)
#if !defined(__AVR_ATmega644P__)
#error Firmware is configured for ATmega644P only (-mmcu=atmega644p)
#endif
/* GCC specific configuration */
#include <avr/wdt.h>
#endif
#include "iar2gcc.h"
#include "bits.h"
/* SEEPROM is 24LC128 */
/*#define SEEPROM_PAGE_SIZE 128 */
/*#define SEEPROM_WORD_ADDRESS_16BIT 1 */
/* SEEPROM is 24C16 */
#define SEEPROM_PAGE_SIZE 16
#define SEEPROM_WORD_ADDRESS_16BIT 0
#endif
+239 -239
View File
@@ -1,239 +1,239 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2007 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 IAR2GCC_H
#define IAR2GCC_H
#if !defined(F_CPU)
#define F_CPU (7372800)
#endif
/* IAR */
#if defined(__ICCAVR__)
#include <inavr.h>
#include <stdint.h>
/* inline function */
static inline void _delay_us(
uint8_t microseconds)
{
do {
__delay_cycles(F_CPU / 1000000UL);
} while (microseconds--);
}
#endif
/* Input/Output Registers */
#if defined(__GNUC__)
#include <avr/io.h>
typedef struct {
unsigned char bit0:1;
unsigned char bit1:1;
unsigned char bit2:1;
unsigned char bit3:1;
unsigned char bit4:1;
unsigned char bit5:1;
unsigned char bit6:1;
unsigned char bit7:1;
} BitRegisterType;
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
#define GPIO_BITREG(port,bitnum) \
((volatile BitRegisterType*)_SFR_MEM_ADDR(port) \
)->bit ## bitnum
#define PINA_Bit0 GPIO_BITREG(PINA,0)
#define PINA_Bit1 GPIO_BITREG(PINA,1)
#define PINA_Bit2 GPIO_BITREG(PINA,2)
#define PINA_Bit3 GPIO_BITREG(PINA,3)
#define PINA_Bit4 GPIO_BITREG(PINA,4)
#define PINA_Bit5 GPIO_BITREG(PINA,5)
#define PINA_Bit6 GPIO_BITREG(PINA,6)
#define PINA_Bit7 GPIO_BITREG(PINA,7)
#define PORTA_Bit0 GPIO_BITREG(PORTA,0)
#define PORTA_Bit1 GPIO_BITREG(PORTA,1)
#define PORTA_Bit2 GPIO_BITREG(PORTA,2)
#define PORTA_Bit3 GPIO_BITREG(PORTA,3)
#define PORTA_Bit4 GPIO_BITREG(PORTA,4)
#define PORTA_Bit5 GPIO_BITREG(PORTA,5)
#define PORTA_Bit6 GPIO_BITREG(PORTA,6)
#define PORTA_Bit7 GPIO_BITREG(PORTA,7)
#define PINB_Bit0 GPIO_BITREG(PINB,0)
#define PINB_Bit1 GPIO_BITREG(PINB,1)
#define PINB_Bit2 GPIO_BITREG(PINB,2)
#define PINB_Bit3 GPIO_BITREG(PINB,3)
#define PINB_Bit4 GPIO_BITREG(PINB,4)
#define PINB_Bit5 GPIO_BITREG(PINB,5)
#define PINB_Bit6 GPIO_BITREG(PINB,6)
#define PINB_Bit7 GPIO_BITREG(PINB,7)
#define PORTB_Bit0 GPIO_BITREG(PORTB,0)
#define PORTB_Bit1 GPIO_BITREG(PORTB,1)
#define PORTB_Bit2 GPIO_BITREG(PORTB,2)
#define PORTB_Bit3 GPIO_BITREG(PORTB,3)
#define PORTB_Bit4 GPIO_BITREG(PORTB,4)
#define PORTB_Bit5 GPIO_BITREG(PORTB,5)
#define PORTB_Bit6 GPIO_BITREG(PORTB,6)
#define PORTB_Bit7 GPIO_BITREG(PORTB,7)
#define PINC_Bit0 GPIO_BITREG(PINC,0)
#define PINC_Bit1 GPIO_BITREG(PINC,1)
#define PINC_Bit2 GPIO_BITREG(PINC,2)
#define PINC_Bit3 GPIO_BITREG(PINC,3)
#define PINC_Bit4 GPIO_BITREG(PINC,4)
#define PINC_Bit5 GPIO_BITREG(PINC,5)
#define PINC_Bit6 GPIO_BITREG(PINC,6)
#define PINC_Bit7 GPIO_BITREG(PINC,7)
#define PORTC_Bit0 GPIO_BITREG(PORTC,0)
#define PORTC_Bit1 GPIO_BITREG(PORTC,1)
#define PORTC_Bit2 GPIO_BITREG(PORTC,2)
#define PORTC_Bit3 GPIO_BITREG(PORTC,3)
#define PORTC_Bit4 GPIO_BITREG(PORTC,4)
#define PORTC_Bit5 GPIO_BITREG(PORTC,5)
#define PORTC_Bit6 GPIO_BITREG(PORTC,6)
#define PORTC_Bit7 GPIO_BITREG(PORTC,7)
#define PIND_Bit0 GPIO_BITREG(PIND,0)
#define PIND_Bit1 GPIO_BITREG(PIND,1)
#define PIND_Bit2 GPIO_BITREG(PIND,2)
#define PIND_Bit3 GPIO_BITREG(PIND,3)
#define PIND_Bit4 GPIO_BITREG(PIND,4)
#define PIND_Bit5 GPIO_BITREG(PIND,5)
#define PIND_Bit6 GPIO_BITREG(PIND,6)
#define PIND_Bit7 GPIO_BITREG(PIND,7)
#define PORTD_Bit0 GPIO_BITREG(PORTD,0)
#define PORTD_Bit1 GPIO_BITREG(PORTD,1)
#define PORTD_Bit2 GPIO_BITREG(PORTD,2)
#define PORTD_Bit3 GPIO_BITREG(PORTD,3)
#define PORTD_Bit4 GPIO_BITREG(PORTD,4)
#define PORTD_Bit5 GPIO_BITREG(PORTD,5)
#define PORTD_Bit6 GPIO_BITREG(PORTD,6)
#define PORTD_Bit7 GPIO_BITREG(PORTD,7)
#define GPIOR0_Bit0 GPIO_BITREG(GPIOR0,0)
#define GPIOR0_Bit1 GPIO_BITREG(GPIOR0,1)
#define GPIOR0_Bit2 GPIO_BITREG(GPIOR0,2)
#define GPIOR0_Bit3 GPIO_BITREG(GPIOR0,3)
#define GPIOR0_Bit4 GPIO_BITREG(GPIOR0,4)
#define GPIOR0_Bit5 GPIO_BITREG(GPIOR0,5)
#define GPIOR0_Bit6 GPIO_BITREG(GPIOR0,6)
#define GPIOR0_Bit7 GPIO_BITREG(GPIOR0,7)
#define GPIOR1_Bit0 GPIO_BITREG(GPIOR1,0)
#define GPIOR1_Bit1 GPIO_BITREG(GPIOR1,1)
#define GPIOR1_Bit2 GPIO_BITREG(GPIOR1,2)
#define GPIOR1_Bit3 GPIO_BITREG(GPIOR1,3)
#define GPIOR1_Bit4 GPIO_BITREG(GPIOR1,4)
#define GPIOR1_Bit5 GPIO_BITREG(GPIOR1,5)
#define GPIOR1_Bit6 GPIO_BITREG(GPIOR1,6)
#define GPIOR1_Bit7 GPIO_BITREG(GPIOR1,7)
#define GPIOR2_Bit0 GPIO_BITREG(GPIOR2,0)
#define GPIOR2_Bit1 GPIO_BITREG(GPIOR2,1)
#define GPIOR2_Bit2 GPIO_BITREG(GPIOR2,2)
#define GPIOR2_Bit3 GPIO_BITREG(GPIOR2,3)
#define GPIOR2_Bit4 GPIO_BITREG(GPIOR2,4)
#define GPIOR2_Bit5 GPIO_BITREG(GPIOR2,5)
#define GPIOR2_Bit6 GPIO_BITREG(GPIOR2,6)
#define GPIOR2_Bit7 GPIO_BITREG(GPIOR2,7)
#endif
/* Global Interrupts */
#if defined(__GNUC__)
#define __enable_interrupt() sei()
#define __disable_interrupt() cli()
#endif
/* Interrupts */
#if defined(__ICCAVR__)
#define PRAGMA(x) _Pragma( #x )
#define ISR(vec) PRAGMA( vector=vec ) __interrupt void handler_##vec(void)
#endif
#if defined(__GNUC__)
#include <avr/interrupt.h>
#endif
/* Flash */
#if defined(__ICCAVR__)
#define FLASH_DECLARE(x) __flash x
#endif
#if defined(__GNUC__)
#define FLASH_DECLARE(x) x __attribute__((__progmem__))
#endif
/* EEPROM */
#if defined(__ICCAVR__)
#define EEPROM_DECLARE(x) __eeprom x
#endif
#if defined(__GNUC__)
#include <avr/eeprom.h>
#define EEPROM_DECLARE(x) x __attribute__((section (".eeprom")))
#endif
/* IAR intrinsic routines */
#if defined(__GNUC__)
/* FIXME: intrinsic routines: map to assembler for size/speed */
#define __multiply_unsigned(x,y) ((x)*(y))
/* FIXME: __root means to not optimize or strip */
#define __root
#endif
/* watchdog */
#if defined(__ICCAVR__)
#include <intrinsics.h>
#define watchdog_reset __watchdog_reset
#define WDTO_15MS 0
#define WDTO_30MS 1
#define WDTO_60MS 2
#define WDTO_120MS 3
#define WDTO_250MS 4
#define WDTO_500MS 5
#define WDTO_1S 6
#define WDTO_2S 7
#endif
#endif
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2007 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 IAR2GCC_H
#define IAR2GCC_H
#if !defined(F_CPU)
#define F_CPU (7372800)
#endif
/* IAR */
#if defined(__ICCAVR__)
#include <inavr.h>
#include <stdint.h>
/* inline function */
static inline void _delay_us(
uint8_t microseconds)
{
do {
__delay_cycles(F_CPU / 1000000UL);
} while (microseconds--);
}
#endif
/* Input/Output Registers */
#if defined(__GNUC__)
#include <avr/io.h>
typedef struct {
unsigned char bit0:1;
unsigned char bit1:1;
unsigned char bit2:1;
unsigned char bit3:1;
unsigned char bit4:1;
unsigned char bit5:1;
unsigned char bit6:1;
unsigned char bit7:1;
} BitRegisterType;
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
#define GPIO_BITREG(port,bitnum) \
((volatile BitRegisterType*)_SFR_MEM_ADDR(port) \
)->bit ## bitnum
#define PINA_Bit0 GPIO_BITREG(PINA,0)
#define PINA_Bit1 GPIO_BITREG(PINA,1)
#define PINA_Bit2 GPIO_BITREG(PINA,2)
#define PINA_Bit3 GPIO_BITREG(PINA,3)
#define PINA_Bit4 GPIO_BITREG(PINA,4)
#define PINA_Bit5 GPIO_BITREG(PINA,5)
#define PINA_Bit6 GPIO_BITREG(PINA,6)
#define PINA_Bit7 GPIO_BITREG(PINA,7)
#define PORTA_Bit0 GPIO_BITREG(PORTA,0)
#define PORTA_Bit1 GPIO_BITREG(PORTA,1)
#define PORTA_Bit2 GPIO_BITREG(PORTA,2)
#define PORTA_Bit3 GPIO_BITREG(PORTA,3)
#define PORTA_Bit4 GPIO_BITREG(PORTA,4)
#define PORTA_Bit5 GPIO_BITREG(PORTA,5)
#define PORTA_Bit6 GPIO_BITREG(PORTA,6)
#define PORTA_Bit7 GPIO_BITREG(PORTA,7)
#define PINB_Bit0 GPIO_BITREG(PINB,0)
#define PINB_Bit1 GPIO_BITREG(PINB,1)
#define PINB_Bit2 GPIO_BITREG(PINB,2)
#define PINB_Bit3 GPIO_BITREG(PINB,3)
#define PINB_Bit4 GPIO_BITREG(PINB,4)
#define PINB_Bit5 GPIO_BITREG(PINB,5)
#define PINB_Bit6 GPIO_BITREG(PINB,6)
#define PINB_Bit7 GPIO_BITREG(PINB,7)
#define PORTB_Bit0 GPIO_BITREG(PORTB,0)
#define PORTB_Bit1 GPIO_BITREG(PORTB,1)
#define PORTB_Bit2 GPIO_BITREG(PORTB,2)
#define PORTB_Bit3 GPIO_BITREG(PORTB,3)
#define PORTB_Bit4 GPIO_BITREG(PORTB,4)
#define PORTB_Bit5 GPIO_BITREG(PORTB,5)
#define PORTB_Bit6 GPIO_BITREG(PORTB,6)
#define PORTB_Bit7 GPIO_BITREG(PORTB,7)
#define PINC_Bit0 GPIO_BITREG(PINC,0)
#define PINC_Bit1 GPIO_BITREG(PINC,1)
#define PINC_Bit2 GPIO_BITREG(PINC,2)
#define PINC_Bit3 GPIO_BITREG(PINC,3)
#define PINC_Bit4 GPIO_BITREG(PINC,4)
#define PINC_Bit5 GPIO_BITREG(PINC,5)
#define PINC_Bit6 GPIO_BITREG(PINC,6)
#define PINC_Bit7 GPIO_BITREG(PINC,7)
#define PORTC_Bit0 GPIO_BITREG(PORTC,0)
#define PORTC_Bit1 GPIO_BITREG(PORTC,1)
#define PORTC_Bit2 GPIO_BITREG(PORTC,2)
#define PORTC_Bit3 GPIO_BITREG(PORTC,3)
#define PORTC_Bit4 GPIO_BITREG(PORTC,4)
#define PORTC_Bit5 GPIO_BITREG(PORTC,5)
#define PORTC_Bit6 GPIO_BITREG(PORTC,6)
#define PORTC_Bit7 GPIO_BITREG(PORTC,7)
#define PIND_Bit0 GPIO_BITREG(PIND,0)
#define PIND_Bit1 GPIO_BITREG(PIND,1)
#define PIND_Bit2 GPIO_BITREG(PIND,2)
#define PIND_Bit3 GPIO_BITREG(PIND,3)
#define PIND_Bit4 GPIO_BITREG(PIND,4)
#define PIND_Bit5 GPIO_BITREG(PIND,5)
#define PIND_Bit6 GPIO_BITREG(PIND,6)
#define PIND_Bit7 GPIO_BITREG(PIND,7)
#define PORTD_Bit0 GPIO_BITREG(PORTD,0)
#define PORTD_Bit1 GPIO_BITREG(PORTD,1)
#define PORTD_Bit2 GPIO_BITREG(PORTD,2)
#define PORTD_Bit3 GPIO_BITREG(PORTD,3)
#define PORTD_Bit4 GPIO_BITREG(PORTD,4)
#define PORTD_Bit5 GPIO_BITREG(PORTD,5)
#define PORTD_Bit6 GPIO_BITREG(PORTD,6)
#define PORTD_Bit7 GPIO_BITREG(PORTD,7)
#define GPIOR0_Bit0 GPIO_BITREG(GPIOR0,0)
#define GPIOR0_Bit1 GPIO_BITREG(GPIOR0,1)
#define GPIOR0_Bit2 GPIO_BITREG(GPIOR0,2)
#define GPIOR0_Bit3 GPIO_BITREG(GPIOR0,3)
#define GPIOR0_Bit4 GPIO_BITREG(GPIOR0,4)
#define GPIOR0_Bit5 GPIO_BITREG(GPIOR0,5)
#define GPIOR0_Bit6 GPIO_BITREG(GPIOR0,6)
#define GPIOR0_Bit7 GPIO_BITREG(GPIOR0,7)
#define GPIOR1_Bit0 GPIO_BITREG(GPIOR1,0)
#define GPIOR1_Bit1 GPIO_BITREG(GPIOR1,1)
#define GPIOR1_Bit2 GPIO_BITREG(GPIOR1,2)
#define GPIOR1_Bit3 GPIO_BITREG(GPIOR1,3)
#define GPIOR1_Bit4 GPIO_BITREG(GPIOR1,4)
#define GPIOR1_Bit5 GPIO_BITREG(GPIOR1,5)
#define GPIOR1_Bit6 GPIO_BITREG(GPIOR1,6)
#define GPIOR1_Bit7 GPIO_BITREG(GPIOR1,7)
#define GPIOR2_Bit0 GPIO_BITREG(GPIOR2,0)
#define GPIOR2_Bit1 GPIO_BITREG(GPIOR2,1)
#define GPIOR2_Bit2 GPIO_BITREG(GPIOR2,2)
#define GPIOR2_Bit3 GPIO_BITREG(GPIOR2,3)
#define GPIOR2_Bit4 GPIO_BITREG(GPIOR2,4)
#define GPIOR2_Bit5 GPIO_BITREG(GPIOR2,5)
#define GPIOR2_Bit6 GPIO_BITREG(GPIOR2,6)
#define GPIOR2_Bit7 GPIO_BITREG(GPIOR2,7)
#endif
/* Global Interrupts */
#if defined(__GNUC__)
#define __enable_interrupt() sei()
#define __disable_interrupt() cli()
#endif
/* Interrupts */
#if defined(__ICCAVR__)
#define PRAGMA(x) _Pragma( #x )
#define ISR(vec) PRAGMA( vector=vec ) __interrupt void handler_##vec(void)
#endif
#if defined(__GNUC__)
#include <avr/interrupt.h>
#endif
/* Flash */
#if defined(__ICCAVR__)
#define FLASH_DECLARE(x) __flash x
#endif
#if defined(__GNUC__)
#define FLASH_DECLARE(x) x __attribute__((__progmem__))
#endif
/* EEPROM */
#if defined(__ICCAVR__)
#define EEPROM_DECLARE(x) __eeprom x
#endif
#if defined(__GNUC__)
#include <avr/eeprom.h>
#define EEPROM_DECLARE(x) x __attribute__((section (".eeprom")))
#endif
/* IAR intrinsic routines */
#if defined(__GNUC__)
/* FIXME: intrinsic routines: map to assembler for size/speed */
#define __multiply_unsigned(x,y) ((x)*(y))
/* FIXME: __root means to not optimize or strip */
#define __root
#endif
/* watchdog */
#if defined(__ICCAVR__)
#include <intrinsics.h>
#define watchdog_reset __watchdog_reset
#define WDTO_15MS 0
#define WDTO_30MS 1
#define WDTO_60MS 2
#define WDTO_120MS 3
#define WDTO_250MS 4
#define WDTO_500MS 5
#define WDTO_1S 6
#define WDTO_2S 7
#endif
#endif
+63 -63
View File
@@ -1,63 +1,63 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include "hardware.h"
void init(
void)
{
/* Initialize the Clock Prescaler for ATmega48/88/168 */
/* The default CLKPSx bits are factory set to 0011 */
/* Enbable the Clock Prescaler */
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
*/
/* Set the CLKPS3..0 bits to Prescaler of 1 */
CLKPR = 0;
/* Initialize I/O ports */
/* For Port DDRx (Data Direction) Input=0, Output=1 */
/* For Port PORTx (Bit Value) TriState=0, High=1 */
DDRA = 0;
PORTA = 0;
DDRB = 0;
PORTB = 0;
DDRC = 0;
PORTC = 0;
DDRD = 0;
PORTD = 0;
/* Configure the watchdog timer - Disabled for testing */
BIT_CLEAR(MCUSR, WDRF);
WDTCSR = 0;
}
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include "hardware.h"
void init(
void)
{
/* Initialize the Clock Prescaler for ATmega48/88/168 */
/* The default CLKPSx bits are factory set to 0011 */
/* Enbable the Clock Prescaler */
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
*/
/* Set the CLKPS3..0 bits to Prescaler of 1 */
CLKPR = 0;
/* Initialize I/O ports */
/* For Port DDRx (Data Direction) Input=0, Output=1 */
/* For Port PORTx (Bit Value) TriState=0, High=1 */
DDRA = 0;
PORTA = 0;
DDRB = 0;
PORTB = 0;
DDRC = 0;
PORTC = 0;
DDRD = 0;
PORTD = 0;
/* Configure the watchdog timer - Disabled for testing */
BIT_CLEAR(MCUSR, WDRF);
WDTCSR = 0;
}
+39 -39
View File
@@ -1,39 +1,39 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#ifndef INIT_H
#define INIT_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void init(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#ifndef INIT_H
#define INIT_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void init(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+59 -62
View File
@@ -1,62 +1,59 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include "hardware.h"
static uint8_t Address_Switch;
void input_task(
void)
{
uint8_t value;
static uint8_t old_value = 0;
value = BITMASK_CHECK(PINA, 0x7F);
if (value != old_value) {
old_value = value;
} else {
if (old_value != Address_Switch) {
Address_Switch = old_value;
}
}
}
uint8_t input_address(void)
{
return Address_Switch;
}
void input_init(void)
{
/* configure the port pins */
BITMASK_CLEAR(DDRA,
_BV(DDA0) |
_BV(DDA1) |
_BV(DDA2) |
_BV(DDA3) |
_BV(DDA4) |
_BV(DDA5) |
_BV(DDA6)
);
}
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include "hardware.h"
static uint8_t Address_Switch;
void input_task(
void)
{
uint8_t value;
static uint8_t old_value = 0;
value = BITMASK_CHECK(PINA, 0x7F);
if (value != old_value) {
old_value = value;
} else {
if (old_value != Address_Switch) {
Address_Switch = old_value;
}
}
}
uint8_t input_address(
void)
{
return Address_Switch;
}
void input_init(
void)
{
/* configure the port pins */
BITMASK_CLEAR(DDRA,
_BV(DDA0) | _BV(DDA1) | _BV(DDA2) | _BV(DDA3) | _BV(DDA4) | _BV(DDA5) |
_BV(DDA6)
);
}
+43 -41
View File
@@ -1,41 +1,43 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#ifndef INPUT_H
#define INPUT_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void input_init(void);
void input_task(void);
uint8_t input_address(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#ifndef INPUT_H
#define INPUT_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void input_init(
void);
void input_task(
void);
uint8_t input_address(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+211 -211
View File
@@ -1,211 +1,211 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#include <stdint.h>
#include "hardware.h"
#include "timer.h"
#include "led.h"
static uint32_t Off_Delay_Milliseconds_1;
static uint32_t Off_Delay_Milliseconds_2;
static uint32_t Off_Delay_Milliseconds_3;
static uint32_t Off_Delay_Milliseconds_4;
/*************************************************************************
* Description: Turn on an LED
* Returns: none
* Notes: none
*************************************************************************/
void led_on(uint8_t index)
{
switch (index) {
case LED_1:
BIT_SET(PORTD, PD7);
break;
case LED_2:
BIT_SET(PORTD, PD6);
break;
case LED_3:
BIT_SET(PORTC, PC7);
break;
case LED_4:
BIT_SET(PORTC, PC6);
break;
default:
break;
}
}
/*************************************************************************
* Description: Turn off an LED
* Returns: none
* Notes: none
*************************************************************************/
void led_off(uint8_t index)
{
switch (index) {
case LED_1:
BIT_CLEAR(PORTD, PD7);
break;
case LED_2:
BIT_CLEAR(PORTD, PD6);
break;
case LED_3:
BIT_CLEAR(PORTC, PC7);
break;
case LED_4:
BIT_CLEAR(PORTC, PC6);
break;
default:
break;
}
}
/*************************************************************************
* Description: Get the state of the LED
* Returns: true if on, false if off.
* Notes: none
*************************************************************************/
bool led_state(uint8_t index)
{
switch (index) {
case LED_1:
return (BIT_CHECK(PIND, PD7));
break;
case LED_2:
return (BIT_CHECK(PIND, PD6));
break;
case LED_3:
return (BIT_CHECK(PINC, PC7));
break;
case LED_4:
return (BIT_CHECK(PINC, PC6));
break;
default:
break;
}
return false;
}
/*************************************************************************
* Description: Toggle the state of the setup LED
* Returns: none
* Notes: none
*************************************************************************/
void led_toggle(uint8_t index)
{
if (led_state(index)) {
led_off(index);
} else {
led_on(index);
}
}
/*************************************************************************
* Description: Delay before going off to give minimum brightness.
* Returns: none
* Notes: none
*************************************************************************/
void led_off_delay(uint8_t index, uint32_t delay_ms)
{
switch (index) {
case LED_1:
Off_Delay_Milliseconds_1 = delay_ms;
timer_reset(TIMER_LED_1);
break;
case LED_2:
Off_Delay_Milliseconds_2 = delay_ms;
timer_reset(TIMER_LED_2);
break;
case LED_3:
Off_Delay_Milliseconds_3 = delay_ms;
timer_reset(TIMER_LED_3);
break;
case LED_4:
Off_Delay_Milliseconds_4 = delay_ms;
timer_reset(TIMER_LED_4);
break;
default:
break;
}
}
/*************************************************************************
* Description: Task for blinking LED
* Returns: none
* Notes: none
*************************************************************************/
void led_task(void)
{
if (Off_Delay_Milliseconds_1) {
if (timer_elapsed_milliseconds(
TIMER_LED_1,
Off_Delay_Milliseconds_1)) {
Off_Delay_Milliseconds_1 = 0;
led_off(LED_1);
}
}
if (Off_Delay_Milliseconds_2) {
if (timer_elapsed_milliseconds(
TIMER_LED_2,
Off_Delay_Milliseconds_2)) {
Off_Delay_Milliseconds_2 = 0;
led_off(LED_2);
}
}
if (Off_Delay_Milliseconds_3) {
if (timer_elapsed_milliseconds(
TIMER_LED_3,
Off_Delay_Milliseconds_3)) {
Off_Delay_Milliseconds_3 = 0;
led_off(LED_3);
}
}
if (Off_Delay_Milliseconds_4) {
if (timer_elapsed_milliseconds(
TIMER_LED_4,
Off_Delay_Milliseconds_4)) {
Off_Delay_Milliseconds_4 = 0;
led_off(LED_4);
}
}
}
/*************************************************************************
* Description: Initialize the LED hardware
* Returns: none
* Notes: none
*************************************************************************/
void led_init(void)
{
/* configure the port pins as outputs */
BIT_SET(DDRC, DDC7);
BIT_SET(DDRC, DDC6);
BIT_SET(DDRD, DDD7);
BIT_SET(DDRD, DDD6);
led_off(LED_1);
led_off(LED_2);
led_off(LED_3);
led_off(LED_4);
}
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#include <stdint.h>
#include "hardware.h"
#include "timer.h"
#include "led.h"
static uint32_t Off_Delay_Milliseconds_1;
static uint32_t Off_Delay_Milliseconds_2;
static uint32_t Off_Delay_Milliseconds_3;
static uint32_t Off_Delay_Milliseconds_4;
/*************************************************************************
* Description: Turn on an LED
* Returns: none
* Notes: none
*************************************************************************/
void led_on(
uint8_t index)
{
switch (index) {
case LED_1:
BIT_SET(PORTD, PD7);
break;
case LED_2:
BIT_SET(PORTD, PD6);
break;
case LED_3:
BIT_SET(PORTC, PC7);
break;
case LED_4:
BIT_SET(PORTC, PC6);
break;
default:
break;
}
}
/*************************************************************************
* Description: Turn off an LED
* Returns: none
* Notes: none
*************************************************************************/
void led_off(
uint8_t index)
{
switch (index) {
case LED_1:
BIT_CLEAR(PORTD, PD7);
break;
case LED_2:
BIT_CLEAR(PORTD, PD6);
break;
case LED_3:
BIT_CLEAR(PORTC, PC7);
break;
case LED_4:
BIT_CLEAR(PORTC, PC6);
break;
default:
break;
}
}
/*************************************************************************
* Description: Get the state of the LED
* Returns: true if on, false if off.
* Notes: none
*************************************************************************/
bool led_state(
uint8_t index)
{
switch (index) {
case LED_1:
return (BIT_CHECK(PIND, PD7));
break;
case LED_2:
return (BIT_CHECK(PIND, PD6));
break;
case LED_3:
return (BIT_CHECK(PINC, PC7));
break;
case LED_4:
return (BIT_CHECK(PINC, PC6));
break;
default:
break;
}
return false;
}
/*************************************************************************
* Description: Toggle the state of the setup LED
* Returns: none
* Notes: none
*************************************************************************/
void led_toggle(
uint8_t index)
{
if (led_state(index)) {
led_off(index);
} else {
led_on(index);
}
}
/*************************************************************************
* Description: Delay before going off to give minimum brightness.
* Returns: none
* Notes: none
*************************************************************************/
void led_off_delay(
uint8_t index,
uint32_t delay_ms)
{
switch (index) {
case LED_1:
Off_Delay_Milliseconds_1 = delay_ms;
timer_reset(TIMER_LED_1);
break;
case LED_2:
Off_Delay_Milliseconds_2 = delay_ms;
timer_reset(TIMER_LED_2);
break;
case LED_3:
Off_Delay_Milliseconds_3 = delay_ms;
timer_reset(TIMER_LED_3);
break;
case LED_4:
Off_Delay_Milliseconds_4 = delay_ms;
timer_reset(TIMER_LED_4);
break;
default:
break;
}
}
/*************************************************************************
* Description: Task for blinking LED
* Returns: none
* Notes: none
*************************************************************************/
void led_task(
void)
{
if (Off_Delay_Milliseconds_1) {
if (timer_elapsed_milliseconds(TIMER_LED_1, Off_Delay_Milliseconds_1)) {
Off_Delay_Milliseconds_1 = 0;
led_off(LED_1);
}
}
if (Off_Delay_Milliseconds_2) {
if (timer_elapsed_milliseconds(TIMER_LED_2, Off_Delay_Milliseconds_2)) {
Off_Delay_Milliseconds_2 = 0;
led_off(LED_2);
}
}
if (Off_Delay_Milliseconds_3) {
if (timer_elapsed_milliseconds(TIMER_LED_3, Off_Delay_Milliseconds_3)) {
Off_Delay_Milliseconds_3 = 0;
led_off(LED_3);
}
}
if (Off_Delay_Milliseconds_4) {
if (timer_elapsed_milliseconds(TIMER_LED_4, Off_Delay_Milliseconds_4)) {
Off_Delay_Milliseconds_4 = 0;
led_off(LED_4);
}
}
}
/*************************************************************************
* Description: Initialize the LED hardware
* Returns: none
* Notes: none
*************************************************************************/
void led_init(
void)
{
/* configure the port pins as outputs */
BIT_SET(DDRC, DDC7);
BIT_SET(DDRC, DDC6);
BIT_SET(DDRD, DDD7);
BIT_SET(DDRD, DDD6);
led_off(LED_1);
led_off(LED_2);
led_off(LED_3);
led_off(LED_4);
}
+59 -52
View File
@@ -1,52 +1,59 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#ifndef LED_H
#define LED_H
#include <stdint.h>
#include <stdbool.h>
#define LED_1 0
#define LED_2 1
#define LED_3 2
#define LED_4 3
#define MAX_LEDS 4
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void led_on(uint8_t index);
void led_off(uint8_t index);
void led_off_delay(uint8_t index, uint32_t delay_ms);
void led_toggle(uint8_t index);
bool led_state(uint8_t index);
void led_task(void);
void led_init(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#ifndef LED_H
#define LED_H
#include <stdint.h>
#include <stdbool.h>
#define LED_1 0
#define LED_2 1
#define LED_3 2
#define LED_4 3
#define MAX_LEDS 4
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void led_on(
uint8_t index);
void led_off(
uint8_t index);
void led_off_delay(
uint8_t index,
uint32_t delay_ms);
void led_toggle(
uint8_t index);
bool led_state(
uint8_t index);
void led_task(
void);
void led_init(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+217 -222
View File
@@ -1,222 +1,217 @@
/************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "hardware.h"
#include "init.h"
#include "stack.h"
#include "timer.h"
#include "input.h"
#include "led.h"
#include "nvdata.h"
#include "timer.h"
#include "dcc.h"
#include "rs485.h"
#include "serial.h"
#include "datalink.h"
#include "npdu.h"
#include "handlers.h"
#include "client.h"
#include "txbuf.h"
#include "iam.h"
#include "device.h"
#include "ai.h"
#include "bi.h"
#include "bo.h"
/* local version override */
const char *BACnet_Version = "1.0";
/* MAC Address of MS/TP */
static uint8_t MSTP_MAC_Address;
/* For porting to IAR, see:
http://www.avrfreaks.net/wiki/index.php/Documentation:AVR_GCC/IarToAvrgcc*/
#if defined(__GNUC__) && (__GNUC__ > 4)
/* AVR fuse settings */
FUSES =
{
/* External Ceramic Resonator - configuration */
/* Full Swing Crystal Oscillator Clock Selection */
/* Ceramic resonator, slowly rising power 1K CK 14CK + 65 ms */
/* note: fuses are enabled by clearing the bit, so
any fuses listed below are cleared fuses. */
.low = (FUSE_CKSEL3 &
FUSE_SUT0 &
FUSE_SUT1),
/* BOOTSZ configuration:
BOOTSZ1 BOOTSZ0 Boot Size
------- ------- ---------
1 1 512
1 0 1024
0 1 2048
0 0 4096
*/
/* note: fuses are enabled by clearing the bit, so
any fuses listed below are cleared fuses. */
.high = (
FUSE_BOOTSZ1 &
FUSE_BOOTRST &
FUSE_EESAVE &
FUSE_SPIEN &
FUSE_JTAGEN),
/* Brown-out detection VCC=2.7V */
/* BODLEVEL configuration
BODLEVEL2 BODLEVEL1 BODLEVEL0 Voltage
--------- --------- --------- --------
1 1 1 disabled
1 1 0 1.8V
1 0 1 2.7V
1 0 0 4.3V
*/
/* note: fuses are enabled by clearing the bit, so
any fuses listed below are cleared fuses. */
.extended = (FUSE_BODLEVEL1 & FUSE_BODLEVEL0),
};
/* AVR lock bits - unlocked */
LOCKBITS = LOCKBITS_DEFAULT;
#endif
bool seeprom_version_test(void)
{
uint16_t version = 0;
uint16_t id = 0;
bool status = false;
seeprom_bytes_read(NV_SEEPROM_TYPE_0, (uint8_t *)&id, 2);
seeprom_bytes_read(NV_SEEPROM_VERSION_0, (uint8_t *)&version, 2);
if ((id == SEEPROM_ID) && (version == SEEPROM_VERSION)) {
status = true;
} else {
version = SEEPROM_VERSION;
id = SEEPROM_ID;
seeprom_bytes_write(NV_SEEPROM_TYPE_0, (uint8_t *)&id, 2);
seeprom_bytes_write(NV_SEEPROM_VERSION_0, (uint8_t *)&version, 2);
}
return status;
}
static void bacnet_init(
void)
{
MSTP_MAC_Address = input_address();
dlmstp_set_mac_address(MSTP_MAC_Address);
dlmstp_init(NULL);
if (!seeprom_version_test()) {
/* invalid version data */
}
/* initialize objects */
Device_Init();
Binary_Output_Init();
/* we need to handle who-is to support dynamic device binding */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* Set the handlers for any confirmed services that we support. */
/* We must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROP_MULTIPLE,
handler_read_property_multiple);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
handler_reinitialize_device);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
handler_write_property);
/* handle communication so we can shutup when asked */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
handler_device_communication_control);
Send_I_Am(&Handler_Transmit_Buffer[0]);
}
static uint8_t PDUBuffer[MAX_MPDU];
static void bacnet_task(void)
{
uint8_t mstp_mac_address = 0;
uint16_t pdu_len = 0;
BACNET_ADDRESS src; /* source address */
mstp_mac_address = input_address();
if (MSTP_MAC_Address != mstp_mac_address) {
MSTP_MAC_Address = mstp_mac_address;
dlmstp_set_mac_address(MSTP_MAC_Address);
Send_I_Am(&Handler_Transmit_Buffer[0]);
}
if (timer_elapsed_seconds(TIMER_DCC, 1)) {
dcc_timer_seconds(1);
}
pdu_len = datalink_receive(&src, &PDUBuffer[0], sizeof(PDUBuffer), 0);
if (pdu_len) {
npdu_handler(&src, &PDUBuffer[0], pdu_len);
}
}
void idle_init(void)
{
timer_reset(TIMER_LED_3);
timer_reset(TIMER_LED_4);
}
void idle_task(void)
{
#if 0
/* blink the leds */
if (timer_elapsed_seconds(TIMER_LED_3, 1)) {
timer_reset(TIMER_LED_3);
led_toggle(LED_3);
}
if (timer_elapsed_milliseconds(TIMER_LED_4, 125)) {
timer_reset(TIMER_LED_4);
led_toggle(LED_4);
}
#endif
}
int main(
void)
{
init();
led_init();
input_init();
timer_init();
seeprom_init();
rs485_init();
serial_init();
bacnet_init();
idle_init();
/* Enable global interrupts */
__enable_interrupt();
for (;;) {
input_task();
bacnet_task();
led_task();
idle_task();
}
}
/************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "hardware.h"
#include "init.h"
#include "stack.h"
#include "timer.h"
#include "input.h"
#include "led.h"
#include "nvdata.h"
#include "timer.h"
#include "dcc.h"
#include "rs485.h"
#include "serial.h"
#include "datalink.h"
#include "npdu.h"
#include "handlers.h"
#include "client.h"
#include "txbuf.h"
#include "iam.h"
#include "device.h"
#include "ai.h"
#include "bi.h"
#include "bo.h"
/* local version override */
const char *BACnet_Version = "1.0";
/* MAC Address of MS/TP */
static uint8_t MSTP_MAC_Address;
/* For porting to IAR, see:
http://www.avrfreaks.net/wiki/index.php/Documentation:AVR_GCC/IarToAvrgcc*/
#if defined(__GNUC__) && (__GNUC__ > 4)
/* AVR fuse settings */
FUSES = {
/* External Ceramic Resonator - configuration */
/* Full Swing Crystal Oscillator Clock Selection */
/* Ceramic resonator, slowly rising power 1K CK 14CK + 65 ms */
/* note: fuses are enabled by clearing the bit, so
any fuses listed below are cleared fuses. */
.low = (FUSE_CKSEL3 & FUSE_SUT0 & FUSE_SUT1),
/* BOOTSZ configuration:
BOOTSZ1 BOOTSZ0 Boot Size
------- ------- ---------
1 1 512
1 0 1024
0 1 2048
0 0 4096
*/
/* note: fuses are enabled by clearing the bit, so
any fuses listed below are cleared fuses. */
.high =
(FUSE_BOOTSZ1 & FUSE_BOOTRST & FUSE_EESAVE & FUSE_SPIEN & FUSE_JTAGEN),
/* Brown-out detection VCC=2.7V */
/* BODLEVEL configuration
BODLEVEL2 BODLEVEL1 BODLEVEL0 Voltage
--------- --------- --------- --------
1 1 1 disabled
1 1 0 1.8V
1 0 1 2.7V
1 0 0 4.3V
*/
/* note: fuses are enabled by clearing the bit, so
any fuses listed below are cleared fuses. */
.extended = (FUSE_BODLEVEL1 & FUSE_BODLEVEL0),};
/* AVR lock bits - unlocked */
LOCKBITS = LOCKBITS_DEFAULT;
#endif
bool seeprom_version_test(
void)
{
uint16_t version = 0;
uint16_t id = 0;
bool status = false;
seeprom_bytes_read(NV_SEEPROM_TYPE_0, (uint8_t *) & id, 2);
seeprom_bytes_read(NV_SEEPROM_VERSION_0, (uint8_t *) & version, 2);
if ((id == SEEPROM_ID) && (version == SEEPROM_VERSION)) {
status = true;
} else {
version = SEEPROM_VERSION;
id = SEEPROM_ID;
seeprom_bytes_write(NV_SEEPROM_TYPE_0, (uint8_t *) & id, 2);
seeprom_bytes_write(NV_SEEPROM_VERSION_0, (uint8_t *) & version, 2);
}
return status;
}
static void bacnet_init(
void)
{
MSTP_MAC_Address = input_address();
dlmstp_set_mac_address(MSTP_MAC_Address);
dlmstp_init(NULL);
if (!seeprom_version_test()) {
/* invalid version data */
}
/* initialize objects */
Device_Init();
Binary_Output_Init();
/* we need to handle who-is to support dynamic device binding */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* Set the handlers for any confirmed services that we support. */
/* We must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROP_MULTIPLE,
handler_read_property_multiple);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
handler_reinitialize_device);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
handler_write_property);
/* handle communication so we can shutup when asked */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
handler_device_communication_control);
Send_I_Am(&Handler_Transmit_Buffer[0]);
}
static uint8_t PDUBuffer[MAX_MPDU];
static void bacnet_task(
void)
{
uint8_t mstp_mac_address = 0;
uint16_t pdu_len = 0;
BACNET_ADDRESS src; /* source address */
mstp_mac_address = input_address();
if (MSTP_MAC_Address != mstp_mac_address) {
MSTP_MAC_Address = mstp_mac_address;
dlmstp_set_mac_address(MSTP_MAC_Address);
Send_I_Am(&Handler_Transmit_Buffer[0]);
}
if (timer_elapsed_seconds(TIMER_DCC, 1)) {
dcc_timer_seconds(1);
}
pdu_len = datalink_receive(&src, &PDUBuffer[0], sizeof(PDUBuffer), 0);
if (pdu_len) {
npdu_handler(&src, &PDUBuffer[0], pdu_len);
}
}
void idle_init(
void)
{
timer_reset(TIMER_LED_3);
timer_reset(TIMER_LED_4);
}
void idle_task(
void)
{
#if 0
/* blink the leds */
if (timer_elapsed_seconds(TIMER_LED_3, 1)) {
timer_reset(TIMER_LED_3);
led_toggle(LED_3);
}
if (timer_elapsed_milliseconds(TIMER_LED_4, 125)) {
timer_reset(TIMER_LED_4);
led_toggle(LED_4);
}
#endif
}
int main(
void)
{
init();
led_init();
input_init();
timer_init();
seeprom_init();
rs485_init();
serial_init();
bacnet_init();
idle_init();
/* Enable global interrupts */
__enable_interrupt();
for (;;) {
input_task();
bacnet_task();
led_task();
idle_task();
}
}
+132 -132
View File
@@ -1,132 +1,132 @@
/************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*************************************************************************/
#ifndef NVDATA_H
#define NVDATA_H
#include "seeprom.h"
#include "eeprom.h"
/* data version - use to check valid version */
#define SEEPROM_ID 0xBAC0
#define SEEPROM_VERSION 0x0001
#define SEEPROM_BYTES_MAX (2*1024)
/* list of SEEPROM addresses */
/* note to developers: define each byte,
even if they are not used explicitly */
#define NV_SEEPROM_TYPE_0 0
#define NV_SEEPROM_TYPE_1 1
#define NV_SEEPROM_VERSION_0 2
#define NV_SEEPROM_VERSION_1 3
/* --- */
/* define the MAC, BAUD, MAX Master, Device Instance internal
so that bootloader *could* use them. */
/* note: MAC could come from DIP switch, or be in non-volatile memory */
#define NV_EEPROM_MAC 0
/* 9=9.6k, 19=19.2k, 38=38.4k, 57=57.6k, 76=76.8k, 115=115.2k */
#define NV_EEPROM_BAUD_K 1
#define NV_EEPROM_MAX_MASTER 2
/* device instance is only 22 bits - easier if we use 32 bits */
#define NV_EEPROM_DEVICE_0 3
#define NV_EEPROM_DEVICE_1 4
#define NV_EEPROM_DEVICE_2 5
#define NV_EEPROM_DEVICE_3 6
/* Device Name */
#define NV_EEPROM_DEVICE_NAME_LENGTH 8
#define NV_EEPROM_DEVICE_NAME_ENCODING 9
#define NV_EEPROM_DEVICE_NAME_0 10
#define NV_EEPROM_DEVICE_NAME_1 11
#define NV_EEPROM_DEVICE_NAME_2 12
#define NV_EEPROM_DEVICE_NAME_3 13
#define NV_EEPROM_DEVICE_NAME_4 14
#define NV_EEPROM_DEVICE_NAME_5 15
#define NV_EEPROM_DEVICE_NAME_6 16
#define NV_EEPROM_DEVICE_NAME_7 17
#define NV_EEPROM_DEVICE_NAME_8 18
#define NV_EEPROM_DEVICE_NAME_9 19
#define NV_EEPROM_DEVICE_NAME_10 20
#define NV_EEPROM_DEVICE_NAME_11 21
#define NV_EEPROM_DEVICE_NAME_12 22
#define NV_EEPROM_DEVICE_NAME_13 23
#define NV_EEPROM_DEVICE_NAME_14 24
#define NV_EEPROM_DEVICE_NAME_15 25
#define NV_EEPROM_DEVICE_NAME_16 26
#define NV_EEPROM_DEVICE_NAME_17 27
#define NV_EEPROM_DEVICE_NAME_18 28
#define NV_EEPROM_DEVICE_NAME_19 29
#define NV_EEPROM_DEVICE_NAME_20 30
#define NV_EEPROM_DEVICE_NAME_21 31
#define NV_EEPROM_DEVICE_NAME_22 32
#define NV_EEPROM_DEVICE_NAME_23 33
#define NV_EEPROM_DEVICE_NAME_24 34
#define NV_EEPROM_DEVICE_NAME_25 35
#define NV_EEPROM_DEVICE_NAME_26 36
#define NV_EEPROM_DEVICE_NAME_27 37
#define NV_EEPROM_DEVICE_NAME_28 38
#define NV_EEPROM_DEVICE_NAME_29 39
#define NV_EEPROM_DEVICE_NAME_30 40
#define NV_EEPROM_DEVICE_NAME_31 41
#define NV_EEPROM_DEVICE_NAME_SIZE 32
/*=============== SEEPROM ================*/
#define NV_SEEPROM_BINARY_OUTPUT_OFFSET 32
#define NV_SEEPROM_BINARY_OUTPUT_0 10
#define NV_SEEPROM_BINARY_OUTPUT(n,p) \
(NV_SEEPROM_BINARY_OUTPUT_0 + \
(NV_SEEPROM_BINARY_OUTPUT_OFFSET * (n)) + (p))
/* BO properties */
#define NV_SEEPROM_BO_POLARITY 0
#define NV_SEEPROM_BO_OUT_OF_SERVICE 1
#define NV_SEEPROM_BO_PRIORITY_ARRAY_1 2
#define NV_SEEPROM_BO_PRIORITY_ARRAY_2 3
#define NV_SEEPROM_BO_PRIORITY_ARRAY_3 4
#define NV_SEEPROM_BO_PRIORITY_ARRAY_4 5
#define NV_SEEPROM_BO_PRIORITY_ARRAY_5 6
#define NV_SEEPROM_BO_PRIORITY_ARRAY_6 7
#define NV_SEEPROM_BO_PRIORITY_ARRAY_7 8
#define NV_SEEPROM_BO_PRIORITY_ARRAY_8 9
#define NV_SEEPROM_BO_PRIORITY_ARRAY_9 10
#define NV_SEEPROM_BO_PRIORITY_ARRAY_10 11
#define NV_SEEPROM_BO_PRIORITY_ARRAY_11 12
#define NV_SEEPROM_BO_PRIORITY_ARRAY_12 13
#define NV_SEEPROM_BO_PRIORITY_ARRAY_13 14
#define NV_SEEPROM_BO_PRIORITY_ARRAY_14 15
#define NV_SEEPROM_BO_PRIORITY_ARRAY_15 16
#define NV_SEEPROM_BO_PRIORITY_ARRAY_16 17
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*************************************************************************/
#ifndef NVDATA_H
#define NVDATA_H
#include "seeprom.h"
#include "eeprom.h"
/* data version - use to check valid version */
#define SEEPROM_ID 0xBAC0
#define SEEPROM_VERSION 0x0001
#define SEEPROM_BYTES_MAX (2*1024)
/* list of SEEPROM addresses */
/* note to developers: define each byte,
even if they are not used explicitly */
#define NV_SEEPROM_TYPE_0 0
#define NV_SEEPROM_TYPE_1 1
#define NV_SEEPROM_VERSION_0 2
#define NV_SEEPROM_VERSION_1 3
/* --- */
/* define the MAC, BAUD, MAX Master, Device Instance internal
so that bootloader *could* use them. */
/* note: MAC could come from DIP switch, or be in non-volatile memory */
#define NV_EEPROM_MAC 0
/* 9=9.6k, 19=19.2k, 38=38.4k, 57=57.6k, 76=76.8k, 115=115.2k */
#define NV_EEPROM_BAUD_K 1
#define NV_EEPROM_MAX_MASTER 2
/* device instance is only 22 bits - easier if we use 32 bits */
#define NV_EEPROM_DEVICE_0 3
#define NV_EEPROM_DEVICE_1 4
#define NV_EEPROM_DEVICE_2 5
#define NV_EEPROM_DEVICE_3 6
/* Device Name */
#define NV_EEPROM_DEVICE_NAME_LENGTH 8
#define NV_EEPROM_DEVICE_NAME_ENCODING 9
#define NV_EEPROM_DEVICE_NAME_0 10
#define NV_EEPROM_DEVICE_NAME_1 11
#define NV_EEPROM_DEVICE_NAME_2 12
#define NV_EEPROM_DEVICE_NAME_3 13
#define NV_EEPROM_DEVICE_NAME_4 14
#define NV_EEPROM_DEVICE_NAME_5 15
#define NV_EEPROM_DEVICE_NAME_6 16
#define NV_EEPROM_DEVICE_NAME_7 17
#define NV_EEPROM_DEVICE_NAME_8 18
#define NV_EEPROM_DEVICE_NAME_9 19
#define NV_EEPROM_DEVICE_NAME_10 20
#define NV_EEPROM_DEVICE_NAME_11 21
#define NV_EEPROM_DEVICE_NAME_12 22
#define NV_EEPROM_DEVICE_NAME_13 23
#define NV_EEPROM_DEVICE_NAME_14 24
#define NV_EEPROM_DEVICE_NAME_15 25
#define NV_EEPROM_DEVICE_NAME_16 26
#define NV_EEPROM_DEVICE_NAME_17 27
#define NV_EEPROM_DEVICE_NAME_18 28
#define NV_EEPROM_DEVICE_NAME_19 29
#define NV_EEPROM_DEVICE_NAME_20 30
#define NV_EEPROM_DEVICE_NAME_21 31
#define NV_EEPROM_DEVICE_NAME_22 32
#define NV_EEPROM_DEVICE_NAME_23 33
#define NV_EEPROM_DEVICE_NAME_24 34
#define NV_EEPROM_DEVICE_NAME_25 35
#define NV_EEPROM_DEVICE_NAME_26 36
#define NV_EEPROM_DEVICE_NAME_27 37
#define NV_EEPROM_DEVICE_NAME_28 38
#define NV_EEPROM_DEVICE_NAME_29 39
#define NV_EEPROM_DEVICE_NAME_30 40
#define NV_EEPROM_DEVICE_NAME_31 41
#define NV_EEPROM_DEVICE_NAME_SIZE 32
/*=============== SEEPROM ================*/
#define NV_SEEPROM_BINARY_OUTPUT_OFFSET 32
#define NV_SEEPROM_BINARY_OUTPUT_0 10
#define NV_SEEPROM_BINARY_OUTPUT(n,p) \
(NV_SEEPROM_BINARY_OUTPUT_0 + \
(NV_SEEPROM_BINARY_OUTPUT_OFFSET * (n)) + (p))
/* BO properties */
#define NV_SEEPROM_BO_POLARITY 0
#define NV_SEEPROM_BO_OUT_OF_SERVICE 1
#define NV_SEEPROM_BO_PRIORITY_ARRAY_1 2
#define NV_SEEPROM_BO_PRIORITY_ARRAY_2 3
#define NV_SEEPROM_BO_PRIORITY_ARRAY_3 4
#define NV_SEEPROM_BO_PRIORITY_ARRAY_4 5
#define NV_SEEPROM_BO_PRIORITY_ARRAY_5 6
#define NV_SEEPROM_BO_PRIORITY_ARRAY_6 7
#define NV_SEEPROM_BO_PRIORITY_ARRAY_7 8
#define NV_SEEPROM_BO_PRIORITY_ARRAY_8 9
#define NV_SEEPROM_BO_PRIORITY_ARRAY_9 10
#define NV_SEEPROM_BO_PRIORITY_ARRAY_10 11
#define NV_SEEPROM_BO_PRIORITY_ARRAY_11 12
#define NV_SEEPROM_BO_PRIORITY_ARRAY_12 13
#define NV_SEEPROM_BO_PRIORITY_ARRAY_13 14
#define NV_SEEPROM_BO_PRIORITY_ARRAY_14 15
#define NV_SEEPROM_BO_PRIORITY_ARRAY_15 16
#define NV_SEEPROM_BO_PRIORITY_ARRAY_16 17
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+257 -259
View File
@@ -1,259 +1,257 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "hardware.h"
#include "fifo.h"
#include "timer.h"
#include "led.h"
#include "nvdata.h"
/* baud rate */
static uint32_t Baud_Rate = 9600;
/* 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 (40UL)
/* turnaround_time_milliseconds = (Tturnaround*1000UL)/Baud_Rate; */
/* buffer for storing received bytes - size must be power of two */
static uint8_t Receive_Buffer_Data[128];
static FIFO_BUFFER Receive_Buffer;
static void rs485_rts_init(void)
{
/* configure the port pin as an output */
BIT_SET(DDRD, DDD4);
}
/* enable the transmit-enable line on the RS-485 transceiver */
void rs485_rts_enable(
bool enable)
{
if (enable) {
BIT_SET(PORTD, PD4);
} else {
BIT_CLEAR(PORTD, PD4);
}
}
static void rs485_receiver_enable(void)
{
UCSR0B = _BV(TXEN0) | _BV(RXEN0) | _BV(RXCIE0);
}
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) / Baud_Rate);
while (!timer_elapsed_milliseconds(TIMER_SILENCE, turnaround_time)) {
/* do nothing - wait for timer to increment */
};
}
ISR(USART0_RX_vect)
{
uint8_t data_byte;
if (BIT_CHECK(UCSR0A, RXC0)) {
/* data is available */
data_byte = UDR0;
(void)FIFO_Put(&Receive_Buffer, data_byte);
timer_reset(TIMER_SILENCE);
}
}
bool rs485_byte_available(
uint8_t * data_register)
{
bool data_available = false; /* return value */
if (!FIFO_Empty(&Receive_Buffer)) {
led_on(LED_1);
*data_register = FIFO_Get(&Receive_Buffer);
data_available = true;
led_off_delay(LED_1, 10);
}
return data_available;
}
bool rs485_receive_error(void)
{
return false;
}
void rs485_bytes_send(
uint8_t * buffer, /* data to send */
uint16_t nbytes) /* number of bytes of data */
{
led_on(LED_2);
while (!BIT_CHECK(UCSR0A, UDRE0)) {
/* do nothing - wait until Tx buffer is empty */
}
while (nbytes) {
/* Send the data byte */
UDR0 = *buffer;
while (!BIT_CHECK(UCSR0A, UDRE0)) {
/* do nothing - wait until Tx buffer is empty */
}
buffer++;
nbytes--;
}
/* was the frame sent? */
while (!BIT_CHECK(UCSR0A, TXC0)) {
/* do nothing - wait until the entire frame in the
Transmit Shift Register has been shifted out */
}
/* Clear the Transmit Complete flag by writing a one to it. */
BIT_SET(UCSR0A, TXC0);
timer_reset(TIMER_SILENCE);
led_off_delay(LED_2, 1);
return;
}
uint32_t rs485_baud_rate(
void)
{
return Baud_Rate;
}
static void rs485_baud_rate_configure(void)
{
/* 2x speed mode */
BIT_SET(UCSR0A, U2X0);
/* configure baud rate */
UBRR0 = (F_CPU / (8UL * Baud_Rate)) - 1;
}
bool rs485_baud_rate_set(
uint32_t baud)
{
bool valid = true;
uint8_t baud_k = 0;
switch (baud) {
case 9600:
case 19200:
case 38400:
case 57600:
case 76800:
case 115200:
Baud_Rate = baud;
rs485_baud_rate_configure();
/* store the baud rate */
baud_k = baud/1000;
eeprom_bytes_write(
NV_EEPROM_BAUD_K,
&baud_k,
1);
break;
default:
valid = false;
break;
}
return valid;
}
static void rs485_usart_init(void)
{
/* enable Transmit and Receive */
UCSR0B = _BV(TXEN0) | _BV(RXEN0);
/* Set USART Control and Status Register n C */
/* Asynchronous USART 8-bit data, No parity, 1 stop */
/* Set USART Mode Select: UMSELn1 UMSELn0 = 00 for Asynchronous USART */
/* Set Parity Mode: UPMn1 UPMn0 = 00 for Parity Disabled */
/* Set Stop Bit Select: USBSn = 0 for 1 stop bit */
/* Set Character Size: UCSZn2 UCSZn1 UCSZn0 = 011 for 8-bit */
/* Clock Polarity: UCPOLn = 0 when asynchronous mode is used. */
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
/* Clear Power Reduction */
BIT_CLEAR(PRR, PRUSART0);
}
static void rs485_init_nvdata(void)
{
uint8_t baud_k = 9; /* from EEPROM value */
eeprom_bytes_read(
NV_EEPROM_BAUD_K,
&baud_k,
1);
switch (baud_k) {
case 9:
Baud_Rate = 9600;
break;
case 19:
Baud_Rate = 19200;
break;
case 38:
Baud_Rate = 38400;
break;
case 57:
Baud_Rate = 57600;
break;
case 76:
Baud_Rate = 76800;
break;
case 115:
Baud_Rate = 115200;
break;
default:
/* not configured yet */
Baud_Rate = 38400;
baud_k = 38400/1000;
eeprom_bytes_write(
NV_EEPROM_BAUD_K,
&baud_k,
1);
break;
}
rs485_baud_rate_configure();
}
void rs485_init(void)
{
FIFO_Init(&Receive_Buffer, &Receive_Buffer_Data[0],
(unsigned)sizeof(Receive_Buffer_Data));
rs485_rts_init();
rs485_usart_init();
rs485_init_nvdata();
rs485_receiver_enable();
rs485_rts_enable(false);
}
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "hardware.h"
#include "fifo.h"
#include "timer.h"
#include "led.h"
#include "nvdata.h"
/* baud rate */
static uint32_t Baud_Rate = 9600;
/* 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 (40UL)
/* turnaround_time_milliseconds = (Tturnaround*1000UL)/Baud_Rate; */
/* buffer for storing received bytes - size must be power of two */
static uint8_t Receive_Buffer_Data[128];
static FIFO_BUFFER Receive_Buffer;
static void rs485_rts_init(
void)
{
/* configure the port pin as an output */
BIT_SET(DDRD, DDD4);
}
/* enable the transmit-enable line on the RS-485 transceiver */
void rs485_rts_enable(
bool enable)
{
if (enable) {
BIT_SET(PORTD, PD4);
} else {
BIT_CLEAR(PORTD, PD4);
}
}
static void rs485_receiver_enable(
void)
{
UCSR0B = _BV(TXEN0) | _BV(RXEN0) | _BV(RXCIE0);
}
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) / Baud_Rate);
while (!timer_elapsed_milliseconds(TIMER_SILENCE, turnaround_time)) {
/* do nothing - wait for timer to increment */
};
}
ISR(USART0_RX_vect)
{
uint8_t data_byte;
if (BIT_CHECK(UCSR0A, RXC0)) {
/* data is available */
data_byte = UDR0;
(void) FIFO_Put(&Receive_Buffer, data_byte);
timer_reset(TIMER_SILENCE);
}
}
bool rs485_byte_available(
uint8_t * data_register)
{
bool data_available = false; /* return value */
if (!FIFO_Empty(&Receive_Buffer)) {
led_on(LED_1);
*data_register = FIFO_Get(&Receive_Buffer);
data_available = true;
led_off_delay(LED_1, 10);
}
return data_available;
}
bool rs485_receive_error(
void)
{
return false;
}
void rs485_bytes_send(
uint8_t * buffer, /* data to send */
uint16_t nbytes)
{ /* number of bytes of data */
led_on(LED_2);
while (!BIT_CHECK(UCSR0A, UDRE0)) {
/* do nothing - wait until Tx buffer is empty */
}
while (nbytes) {
/* Send the data byte */
UDR0 = *buffer;
while (!BIT_CHECK(UCSR0A, UDRE0)) {
/* do nothing - wait until Tx buffer is empty */
}
buffer++;
nbytes--;
}
/* was the frame sent? */
while (!BIT_CHECK(UCSR0A, TXC0)) {
/* do nothing - wait until the entire frame in the
Transmit Shift Register has been shifted out */
}
/* Clear the Transmit Complete flag by writing a one to it. */
BIT_SET(UCSR0A, TXC0);
timer_reset(TIMER_SILENCE);
led_off_delay(LED_2, 1);
return;
}
uint32_t rs485_baud_rate(
void)
{
return Baud_Rate;
}
static void rs485_baud_rate_configure(
void)
{
/* 2x speed mode */
BIT_SET(UCSR0A, U2X0);
/* configure baud rate */
UBRR0 = (F_CPU / (8UL * Baud_Rate)) - 1;
}
bool rs485_baud_rate_set(
uint32_t baud)
{
bool valid = true;
uint8_t baud_k = 0;
switch (baud) {
case 9600:
case 19200:
case 38400:
case 57600:
case 76800:
case 115200:
Baud_Rate = baud;
rs485_baud_rate_configure();
/* store the baud rate */
baud_k = baud / 1000;
eeprom_bytes_write(NV_EEPROM_BAUD_K, &baud_k, 1);
break;
default:
valid = false;
break;
}
return valid;
}
static void rs485_usart_init(
void)
{
/* enable Transmit and Receive */
UCSR0B = _BV(TXEN0) | _BV(RXEN0);
/* Set USART Control and Status Register n C */
/* Asynchronous USART 8-bit data, No parity, 1 stop */
/* Set USART Mode Select: UMSELn1 UMSELn0 = 00 for Asynchronous USART */
/* Set Parity Mode: UPMn1 UPMn0 = 00 for Parity Disabled */
/* Set Stop Bit Select: USBSn = 0 for 1 stop bit */
/* Set Character Size: UCSZn2 UCSZn1 UCSZn0 = 011 for 8-bit */
/* Clock Polarity: UCPOLn = 0 when asynchronous mode is used. */
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
/* Clear Power Reduction */
BIT_CLEAR(PRR, PRUSART0);
}
static void rs485_init_nvdata(
void)
{
uint8_t baud_k = 9; /* from EEPROM value */
eeprom_bytes_read(NV_EEPROM_BAUD_K, &baud_k, 1);
switch (baud_k) {
case 9:
Baud_Rate = 9600;
break;
case 19:
Baud_Rate = 19200;
break;
case 38:
Baud_Rate = 38400;
break;
case 57:
Baud_Rate = 57600;
break;
case 76:
Baud_Rate = 76800;
break;
case 115:
Baud_Rate = 115200;
break;
default:
/* not configured yet */
Baud_Rate = 38400;
baud_k = 38400 / 1000;
eeprom_bytes_write(NV_EEPROM_BAUD_K, &baud_k, 1);
break;
}
rs485_baud_rate_configure();
}
void rs485_init(
void)
{
FIFO_Init(&Receive_Buffer, &Receive_Buffer_Data[0],
(unsigned) sizeof(Receive_Buffer_Data));
rs485_rts_init();
rs485_usart_init();
rs485_init_nvdata();
rs485_receiver_enable();
rs485_rts_enable(false);
}
+67 -64
View File
@@ -1,64 +1,67 @@
/*####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>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void rs485_init(void);
void rs485_rts_enable(
bool enable);
bool rs485_byte_available(
uint8_t * data_register);
bool rs485_receive_error(void);
void rs485_bytes_send(
uint8_t * buffer, /* data to send */
uint16_t nbytes); /* number of bytes of data */
uint32_t rs485_baud_rate(void);
bool rs485_baud_rate_set(
uint32_t baud);
void rs485_turnaround_delay(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/*####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>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void rs485_init(
void);
void rs485_rts_enable(
bool enable);
bool rs485_byte_available(
uint8_t * data_register);
bool rs485_receive_error(
void);
void rs485_bytes_send(
uint8_t * buffer, /* data to send */
uint16_t nbytes); /* number of bytes of data */
uint32_t rs485_baud_rate(
void);
bool rs485_baud_rate_set(
uint32_t baud);
void rs485_turnaround_delay(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+426 -424
View File
@@ -1,424 +1,426 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "hardware.h"
#include "seeprom.h"
/* the SEEPROM chip select bits A2, A1, and A0 are grounded */
/* control byte is 0xAx */
#ifndef SEEPROM_I2C_ADDRESS
#define SEEPROM_I2C_ADDRESS 0xA0
#endif
/* SEEPROM Clock Frequency */
#ifndef SEEPROM_I2C_CLOCK
#define SEEPROM_I2C_CLOCK 400000UL
#endif
/* max number of bytes that can be written in a single write */
#ifndef SEEPROM_PAGE_SIZE
#define SEEPROM_PAGE_SIZE 128
#endif
/* word addressing - is it 8-bit or 16-bit */
#ifndef SEEPROM_WORD_ADDRESS_16BIT
#define SEEPROM_WORD_ADDRESS_16BIT 1
#endif
/* The lower 3 bits of TWSR are reserved on the ATmega163 */
#define TW_STATUS_MASK (_BV(TWS7)|_BV(TWS6)|_BV(TWS5)|_BV(TWS4)|_BV(TWS3))
/* start condition transmitted */
#define TW_START 0x08
/* repeated start condition transmitted */
#define TW_REP_START 0x10
/* ***Master Transmitter*** */
/* SLA+W transmitted, ACK received */
#define TW_MT_SLA_ACK 0x18
/* SLA+W transmitted, NACK received */
#define TW_MT_SLA_NACK 0x20
/* data transmitted, ACK received */
#define TW_MT_DATA_ACK 0x28
/* data transmitted, NACK received */
#define TW_MT_DATA_NACK 0x30
/* arbitration lost in SLA+W or data */
#define TW_MT_ARB_LOST 0x38
/* ***Master Receiver*** */
/* arbitration lost in SLA+R or NACK */
#define TW_MR_ARB_LOST 0x38
/* SLA+R transmitted, ACK received */
#define TW_MR_SLA_ACK 0x40
/* SLA+R transmitted, NACK received */
#define TW_MR_SLA_NACK 0x48
/* data received, ACK returned */
#define TW_MR_DATA_ACK 0x50
/* data received, NACK returned */
#define TW_MR_DATA_NACK 0x58
/* SLA+R address */
#define TW_READ 1
/* SLA+W address */
#define TW_WRITE 0
/*
* Maximal number of iterations to wait for a device to respond for a
* selection. Should be large enough to allow for a pending write to
* complete, but low enough to properly abort an infinite loop in case
* a slave is broken or not present at all. With 100 kHz TWI clock,
* transfering the start condition and SLA+R/W packet takes about 10
* µs. The longest write period is supposed to not exceed ~ 10 ms.
* Thus, normal operation should not require more than 100 iterations
* to get the device to respond to a selection.
*/
#define MAX_ITER 200
/*************************************************************************
* DESCRIPTION: Return bytes from SEEPROM memory at address
* RETURN: number of bytes read, or -1 on error
* NOTES: none
**************************************************************************/
int seeprom_bytes_read(
uint16_t eeaddr, /* SEEPROM starting memory address */
uint8_t * buf, /* data to store */
int len) /* number of bytes of data to read */
{
uint8_t sla, twcr, n = 0;
int rv = 0;
uint8_t twst; /* status - only valid while TWINT is set. */
#if SEEPROM_WORD_ADDRESS_16BIT
/* 16bit address devices need only TWI Device Address */
sla = SEEPROM_I2C_ADDRESS;
#else
/* patch high bits of EEPROM address into SLA */
sla = SEEPROM_I2C_ADDRESS | (((eeaddr >> 8) & 0x07) << 1);
#endif
/* Note [8] First cycle: master transmitter mode */
restart:
if (n++ >= MAX_ITER) {
return -1;
}
begin:
/* send start condition */
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0) ;
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_REP_START:
/* OK, but should not happen */
case TW_START:
break;
case TW_MT_ARB_LOST:
/* Note [9] */
goto begin;
default:
/* error: not in start condition */
/* NB: do /not/ send stop condition */
return -1;
}
/* Note [10] */
/* send SLA+W */
TWDR = sla | TW_WRITE;
/* clear interrupt to start transmission */
TWCR = _BV(TWINT) | _BV(TWEN);
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0) ;
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_MT_SLA_ACK:
break;
case TW_MT_SLA_NACK:
/* nack during select: device busy writing */
/* Note [11] */
goto restart;
case TW_MT_ARB_LOST:
/* re-arbitrate */
goto begin;
default:
/* must send stop condition */
goto error;
}
#if SEEPROM_WORD_ADDRESS_16BIT
/* 16 bit word address device, send high 8 bits of addr */
TWDR = (eeaddr>>8);
/* clear interrupt to start transmission */
TWCR = _BV(TWINT) | _BV(TWEN);
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0) ;
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_MT_DATA_ACK:
break;
case TW_MT_DATA_NACK:
goto quit;
case TW_MT_ARB_LOST:
goto begin;
default:
/* must send stop condition */
goto error;
}
#endif
/* low 8 bits of addr */
TWDR = eeaddr;
/* clear interrupt to start transmission */
TWCR = _BV(TWINT) | _BV(TWEN);
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0) ;
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_MT_DATA_ACK:
break;
case TW_MT_DATA_NACK:
goto quit;
case TW_MT_ARB_LOST:
goto begin;
default:
/* must send stop condition */
goto error;
}
/* Note [12] Next cycle(s): master receiver mode */
/* send repeated start condition */
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0) ;
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_START:
/* OK, but should not happen */
case TW_REP_START:
break;
case TW_MT_ARB_LOST:
goto begin;
default:
goto error;
}
/* send SLA+R */
TWDR = sla | TW_READ;
/* clear interrupt to start transmission */
TWCR = _BV(TWINT) | _BV(TWEN);
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0) ;
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_MR_SLA_ACK:
break;
case TW_MR_SLA_NACK:
goto quit;
case TW_MR_ARB_LOST:
goto begin;
default:
goto error;
}
/* Note [13] */
twcr = _BV(TWINT) | _BV(TWEN) | _BV(TWEA);
for (;len > 0; len--) {
if (len == 1) {
/* send NAK this time */
twcr = _BV(TWINT) | _BV(TWEN);
}
/* clear int to start transmission */
TWCR = twcr;
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0) ;
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_MR_DATA_NACK:
/* force end of loop */
len = 0;
/* FALLTHROUGH */
case TW_MR_DATA_ACK:
*buf= TWDR;
buf++;
rv++;
break;
default:
goto error;
}
}
quit:
/* Note [14] */
/* send stop condition */
TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN);
return rv;
error:
rv = -1;
goto quit;
}
/*************************************************************************
* DESCRIPTION: Write some data and wait until it is sent
* RETURN: number of bytes written, or -1 on error
* NOTES: none
**************************************************************************/
int seeprom_bytes_write(
uint16_t eeaddr, /* SEEPROM starting memory address */
uint8_t * buf, /* data to send */
int len) /* number of bytes of data */
{
uint8_t sla, n = 0;
int rv = 0;
uint16_t endaddr;
uint8_t twst; /* status - only valid while TWINT is set. */
if ((eeaddr + len) < (eeaddr | (SEEPROM_PAGE_SIZE - 1))) {
endaddr = eeaddr + len;
} else {
endaddr = (eeaddr | (SEEPROM_PAGE_SIZE - 1)) + 1;
}
len = endaddr - eeaddr;
#if SEEPROM_WORD_ADDRESS_16BIT
/* 16bit address devices need only TWI Device Address */
sla = SEEPROM_I2C_ADDRESS;
#else
/* patch high bits of EEPROM address into SLA */
sla = SEEPROM_I2C_ADDRESS | (((eeaddr >> 8) & 0x07) << 1);
#endif
restart:
if (n++ >= MAX_ITER) {
return -1;
}
begin:
/* Note [15] */
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); /* send start condition */
while ((TWCR & _BV(TWINT)) == 0) ; /* wait for transmission */
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_REP_START:
/* OK, but should not happen */
case TW_START:
break;
case TW_MT_ARB_LOST:
goto begin;
default:
/* error: not in start condition */
/* NB: do /not/ send stop condition */
return -1;
}
/* send SLA+W */
TWDR = sla | TW_WRITE;
/* clear interrupt to start transmission */
TWCR = _BV(TWINT) | _BV(TWEN);
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0) ;
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_MT_SLA_ACK:
break;
case TW_MT_SLA_NACK:
/* nack during select: device busy writing */
goto restart;
case TW_MT_ARB_LOST:
/* re-arbitrate */
goto begin;
default:
/* must send stop condition */
goto error;
}
#if SEEPROM_WORD_ADDRESS_16BIT
/* 16 bit word address device, send high 8 bits of addr */
TWDR = (eeaddr>>8);
/* clear interrupt to start transmission */
TWCR = _BV(TWINT) | _BV(TWEN);
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0) ;
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_MT_DATA_ACK:
break;
case TW_MT_DATA_NACK:
goto quit;
case TW_MT_ARB_LOST:
goto begin;
default:
/* must send stop condition */
goto error;
}
#endif
/* low 8 bits of addr */
TWDR = eeaddr;
/* clear interrupt to start transmission */
TWCR = _BV(TWINT) | _BV(TWEN);
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0) {};
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_MT_DATA_ACK:
break;
case TW_MT_DATA_NACK:
goto quit;
case TW_MT_ARB_LOST:
goto begin;
default:
/* must send stop condition */
goto error;
}
for (; len > 0; len--) {
TWDR = *buf++;
/* start transmission */
TWCR = _BV(TWINT) | _BV(TWEN);
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0) ;
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_MT_DATA_NACK:
/* device write protected -- Note [16] */
goto error;
case TW_MT_DATA_ACK:
rv++;
break;
default:
goto error;
}
}
quit:
/* send stop condition */
TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN);
return rv;
error:
rv = -1;
goto quit;
}
/*************************************************************************
* Description: Initialize the SEEPROM TWI connection
* Returns: none
* Notes: none
**************************************************************************/
void seeprom_init(void)
{
/* bit rate prescaler */
TWSR=0;
TWCR=_BV(TWEN) | _BV(TWEA);
/* bit rate */
TWBR = (F_CPU / SEEPROM_I2C_CLOCK - 16) / 2;
/* my address */
TWAR=0;
}
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "hardware.h"
#include "seeprom.h"
/* the SEEPROM chip select bits A2, A1, and A0 are grounded */
/* control byte is 0xAx */
#ifndef SEEPROM_I2C_ADDRESS
#define SEEPROM_I2C_ADDRESS 0xA0
#endif
/* SEEPROM Clock Frequency */
#ifndef SEEPROM_I2C_CLOCK
#define SEEPROM_I2C_CLOCK 400000UL
#endif
/* max number of bytes that can be written in a single write */
#ifndef SEEPROM_PAGE_SIZE
#define SEEPROM_PAGE_SIZE 128
#endif
/* word addressing - is it 8-bit or 16-bit */
#ifndef SEEPROM_WORD_ADDRESS_16BIT
#define SEEPROM_WORD_ADDRESS_16BIT 1
#endif
/* The lower 3 bits of TWSR are reserved on the ATmega163 */
#define TW_STATUS_MASK (_BV(TWS7)|_BV(TWS6)|_BV(TWS5)|_BV(TWS4)|_BV(TWS3))
/* start condition transmitted */
#define TW_START 0x08
/* repeated start condition transmitted */
#define TW_REP_START 0x10
/* ***Master Transmitter*** */
/* SLA+W transmitted, ACK received */
#define TW_MT_SLA_ACK 0x18
/* SLA+W transmitted, NACK received */
#define TW_MT_SLA_NACK 0x20
/* data transmitted, ACK received */
#define TW_MT_DATA_ACK 0x28
/* data transmitted, NACK received */
#define TW_MT_DATA_NACK 0x30
/* arbitration lost in SLA+W or data */
#define TW_MT_ARB_LOST 0x38
/* ***Master Receiver*** */
/* arbitration lost in SLA+R or NACK */
#define TW_MR_ARB_LOST 0x38
/* SLA+R transmitted, ACK received */
#define TW_MR_SLA_ACK 0x40
/* SLA+R transmitted, NACK received */
#define TW_MR_SLA_NACK 0x48
/* data received, ACK returned */
#define TW_MR_DATA_ACK 0x50
/* data received, NACK returned */
#define TW_MR_DATA_NACK 0x58
/* SLA+R address */
#define TW_READ 1
/* SLA+W address */
#define TW_WRITE 0
/*
* Maximal number of iterations to wait for a device to respond for a
* selection. Should be large enough to allow for a pending write to
* complete, but low enough to properly abort an infinite loop in case
* a slave is broken or not present at all. With 100 kHz TWI clock,
* transfering the start condition and SLA+R/W packet takes about 10
* µs. The longest write period is supposed to not exceed ~ 10 ms.
* Thus, normal operation should not require more than 100 iterations
* to get the device to respond to a selection.
*/
#define MAX_ITER 200
/*************************************************************************
* DESCRIPTION: Return bytes from SEEPROM memory at address
* RETURN: number of bytes read, or -1 on error
* NOTES: none
**************************************************************************/
int seeprom_bytes_read(
uint16_t eeaddr, /* SEEPROM starting memory address */
uint8_t * buf, /* data to store */
int len)
{ /* number of bytes of data to read */
uint8_t sla, twcr, n = 0;
int rv = 0;
uint8_t twst; /* status - only valid while TWINT is set. */
#if SEEPROM_WORD_ADDRESS_16BIT
/* 16bit address devices need only TWI Device Address */
sla = SEEPROM_I2C_ADDRESS;
#else
/* patch high bits of EEPROM address into SLA */
sla = SEEPROM_I2C_ADDRESS | (((eeaddr >> 8) & 0x07) << 1);
#endif
/* Note [8] First cycle: master transmitter mode */
restart:
if (n++ >= MAX_ITER) {
return -1;
}
begin:
/* send start condition */
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0);
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_REP_START:
/* OK, but should not happen */
case TW_START:
break;
case TW_MT_ARB_LOST:
/* Note [9] */
goto begin;
default:
/* error: not in start condition */
/* NB: do /not/ send stop condition */
return -1;
}
/* Note [10] */
/* send SLA+W */
TWDR = sla | TW_WRITE;
/* clear interrupt to start transmission */
TWCR = _BV(TWINT) | _BV(TWEN);
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0);
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_MT_SLA_ACK:
break;
case TW_MT_SLA_NACK:
/* nack during select: device busy writing */
/* Note [11] */
goto restart;
case TW_MT_ARB_LOST:
/* re-arbitrate */
goto begin;
default:
/* must send stop condition */
goto error;
}
#if SEEPROM_WORD_ADDRESS_16BIT
/* 16 bit word address device, send high 8 bits of addr */
TWDR = (eeaddr >> 8);
/* clear interrupt to start transmission */
TWCR = _BV(TWINT) | _BV(TWEN);
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0);
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_MT_DATA_ACK:
break;
case TW_MT_DATA_NACK:
goto quit;
case TW_MT_ARB_LOST:
goto begin;
default:
/* must send stop condition */
goto error;
}
#endif
/* low 8 bits of addr */
TWDR = eeaddr;
/* clear interrupt to start transmission */
TWCR = _BV(TWINT) | _BV(TWEN);
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0);
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_MT_DATA_ACK:
break;
case TW_MT_DATA_NACK:
goto quit;
case TW_MT_ARB_LOST:
goto begin;
default:
/* must send stop condition */
goto error;
}
/* Note [12] Next cycle(s): master receiver mode */
/* send repeated start condition */
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0);
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_START:
/* OK, but should not happen */
case TW_REP_START:
break;
case TW_MT_ARB_LOST:
goto begin;
default:
goto error;
}
/* send SLA+R */
TWDR = sla | TW_READ;
/* clear interrupt to start transmission */
TWCR = _BV(TWINT) | _BV(TWEN);
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0);
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_MR_SLA_ACK:
break;
case TW_MR_SLA_NACK:
goto quit;
case TW_MR_ARB_LOST:
goto begin;
default:
goto error;
}
/* Note [13] */
twcr = _BV(TWINT) | _BV(TWEN) | _BV(TWEA);
for (; len > 0; len--) {
if (len == 1) {
/* send NAK this time */
twcr = _BV(TWINT) | _BV(TWEN);
}
/* clear int to start transmission */
TWCR = twcr;
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0);
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_MR_DATA_NACK:
/* force end of loop */
len = 0;
/* FALLTHROUGH */
case TW_MR_DATA_ACK:
*buf = TWDR;
buf++;
rv++;
break;
default:
goto error;
}
}
quit:
/* Note [14] */
/* send stop condition */
TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN);
return rv;
error:
rv = -1;
goto quit;
}
/*************************************************************************
* DESCRIPTION: Write some data and wait until it is sent
* RETURN: number of bytes written, or -1 on error
* NOTES: none
**************************************************************************/
int seeprom_bytes_write(
uint16_t eeaddr, /* SEEPROM starting memory address */
uint8_t * buf, /* data to send */
int len)
{ /* number of bytes of data */
uint8_t sla, n = 0;
int rv = 0;
uint16_t endaddr;
uint8_t twst; /* status - only valid while TWINT is set. */
if ((eeaddr + len) < (eeaddr | (SEEPROM_PAGE_SIZE - 1))) {
endaddr = eeaddr + len;
} else {
endaddr = (eeaddr | (SEEPROM_PAGE_SIZE - 1)) + 1;
}
len = endaddr - eeaddr;
#if SEEPROM_WORD_ADDRESS_16BIT
/* 16bit address devices need only TWI Device Address */
sla = SEEPROM_I2C_ADDRESS;
#else
/* patch high bits of EEPROM address into SLA */
sla = SEEPROM_I2C_ADDRESS | (((eeaddr >> 8) & 0x07) << 1);
#endif
restart:
if (n++ >= MAX_ITER) {
return -1;
}
begin:
/* Note [15] */
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); /* send start condition */
while ((TWCR & _BV(TWINT)) == 0); /* wait for transmission */
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_REP_START:
/* OK, but should not happen */
case TW_START:
break;
case TW_MT_ARB_LOST:
goto begin;
default:
/* error: not in start condition */
/* NB: do /not/ send stop condition */
return -1;
}
/* send SLA+W */
TWDR = sla | TW_WRITE;
/* clear interrupt to start transmission */
TWCR = _BV(TWINT) | _BV(TWEN);
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0);
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_MT_SLA_ACK:
break;
case TW_MT_SLA_NACK:
/* nack during select: device busy writing */
goto restart;
case TW_MT_ARB_LOST:
/* re-arbitrate */
goto begin;
default:
/* must send stop condition */
goto error;
}
#if SEEPROM_WORD_ADDRESS_16BIT
/* 16 bit word address device, send high 8 bits of addr */
TWDR = (eeaddr >> 8);
/* clear interrupt to start transmission */
TWCR = _BV(TWINT) | _BV(TWEN);
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0);
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_MT_DATA_ACK:
break;
case TW_MT_DATA_NACK:
goto quit;
case TW_MT_ARB_LOST:
goto begin;
default:
/* must send stop condition */
goto error;
}
#endif
/* low 8 bits of addr */
TWDR = eeaddr;
/* clear interrupt to start transmission */
TWCR = _BV(TWINT) | _BV(TWEN);
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0) {
};
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_MT_DATA_ACK:
break;
case TW_MT_DATA_NACK:
goto quit;
case TW_MT_ARB_LOST:
goto begin;
default:
/* must send stop condition */
goto error;
}
for (; len > 0; len--) {
TWDR = *buf++;
/* start transmission */
TWCR = _BV(TWINT) | _BV(TWEN);
/* wait for transmission */
while ((TWCR & _BV(TWINT)) == 0);
twst = TWSR & TW_STATUS_MASK;
switch (twst) {
case TW_MT_DATA_NACK:
/* device write protected -- Note [16] */
goto error;
case TW_MT_DATA_ACK:
rv++;
break;
default:
goto error;
}
}
quit:
/* send stop condition */
TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN);
return rv;
error:
rv = -1;
goto quit;
}
/*************************************************************************
* Description: Initialize the SEEPROM TWI connection
* Returns: none
* Notes: none
**************************************************************************/
void seeprom_init(
void)
{
/* bit rate prescaler */
TWSR = 0;
TWCR = _BV(TWEN) | _BV(TWEA);
/* bit rate */
TWBR = (F_CPU / SEEPROM_I2C_CLOCK - 16) / 2;
/* my address */
TWAR = 0;
}
+48 -48
View File
@@ -1,48 +1,48 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#ifndef SEEPROM_H
#define SEEPROM_H
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
int seeprom_bytes_read(
uint16_t ee_address, /* SEEPROM starting memory address */
uint8_t * buffer, /* data to store */
int nbytes); /* number of bytes of data to read */
int seeprom_bytes_write(
uint16_t ee_address, /* SEEPROM starting memory address */
uint8_t * buffer, /* data to send */
int nbytes); /* number of bytes of data */
void seeprom_init(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#ifndef SEEPROM_H
#define SEEPROM_H
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
int seeprom_bytes_read(
uint16_t ee_address, /* SEEPROM starting memory address */
uint8_t * buffer, /* data to store */
int nbytes); /* number of bytes of data to read */
int seeprom_bytes_write(
uint16_t ee_address, /* SEEPROM starting memory address */
uint8_t * buffer, /* data to send */
int nbytes); /* number of bytes of data */
void seeprom_init(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+177 -173
View File
@@ -1,173 +1,177 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "hardware.h"
#include "fifo.h"
#include "serial.h"
/* baud rate */
static uint32_t Baud_Rate = 9600;
/* buffer for storing received bytes - size must be power of two */
static uint8_t Receive_Buffer_Data[128];
static FIFO_BUFFER Receive_Buffer;
static void serial_receiver_enable(void)
{
UCSR0B = _BV(TXEN0) | _BV(RXEN0) | _BV(RXCIE0);
}
ISR(USART1_RX_vect)
{
uint8_t data_byte;
if (BIT_CHECK(UCSR1A, RXC1)) {
/* data is available */
data_byte = UDR1;
(void)FIFO_Put(&Receive_Buffer, data_byte);
}
}
bool serial_byte_get(
uint8_t * data_register)
{
bool data_available = false; /* return value */
if (!FIFO_Empty(&Receive_Buffer)) {
*data_register = FIFO_Get(&Receive_Buffer);
data_available = true;
}
return data_available;
}
bool serial_byte_peek(
uint8_t * data_register)
{
bool data_available = false; /* return value */
if (!FIFO_Empty(&Receive_Buffer)) {
*data_register = FIFO_Peek(&Receive_Buffer);
data_available = true;
}
return data_available;
}
void serial_bytes_send(
uint8_t * buffer, /* data to send */
uint16_t nbytes) /* number of bytes of data */
{
while (!BIT_CHECK(UCSR1A, UDRE1)) {
/* do nothing - wait until Tx buffer is empty */
}
while (nbytes) {
/* Send the data byte */
UDR1 = *buffer;
while (!BIT_CHECK(UCSR1A, UDRE1)) {
/* do nothing - wait until Tx buffer is empty */
}
buffer++;
nbytes--;
}
/* was the frame sent? */
while (!BIT_CHECK(UCSR1A, TXC1)) {
/* do nothing - wait until the entire frame in the
Transmit Shift Register has been shifted out */
}
/* Clear the Transmit Complete flag by writing a one to it. */
BIT_SET(UCSR1A, TXC1);
return;
}
void serial_byte_send(uint8_t ch)
{
uint8_t buffer[1];
buffer[0] = ch;
serial_bytes_send(&buffer[0], 1);
return;
}
uint32_t serial_baud_rate(
void)
{
return Baud_Rate;
}
bool serial_baud_rate_set(
uint32_t baud)
{
bool valid = true;
switch (baud) {
case 9600:
case 19200:
case 38400:
case 57600:
case 76800:
case 115200:
Baud_Rate = baud;
/* 2x speed mode */
BIT_SET(UCSR1A, U2X1);
/* configure baud rate */
UBRR1 = (F_CPU / (8UL * Baud_Rate)) - 1;
/* FIXME: store the baud rate */
break;
default:
valid = false;
break;
}
return valid;
}
static void serial_usart_init(void)
{
/* enable Transmit and Receive */
UCSR1B = _BV(TXEN1) | _BV(RXEN1);
/* Set USART Control and Status Register n C */
/* Asynchronous USART 8-bit data, No parity, 1 stop */
/* Set USART Mode Select: UMSELn1 UMSELn0 = 00 for Asynchronous USART */
/* Set Parity Mode: UPMn1 UPMn0 = 00 for Parity Disabled */
/* Set Stop Bit Select: USBSn = 0 for 1 stop bit */
/* Set Character Size: UCSZn2 UCSZn1 UCSZn0 = 011 for 8-bit */
/* Clock Polarity: UCPOLn = 0 when asynchronous mode is used. */
UCSR0C = _BV(UCSZ11) | _BV(UCSZ10);
/* Clear Power Reduction */
BIT_CLEAR(PRR, PRUSART1);
}
void serial_init(void)
{
FIFO_Init(&Receive_Buffer, &Receive_Buffer_Data[0],
(unsigned)sizeof(Receive_Buffer_Data));
serial_usart_init();
serial_baud_rate_set(Baud_Rate);
serial_receiver_enable();
}
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "hardware.h"
#include "fifo.h"
#include "serial.h"
/* baud rate */
static uint32_t Baud_Rate = 9600;
/* buffer for storing received bytes - size must be power of two */
static uint8_t Receive_Buffer_Data[128];
static FIFO_BUFFER Receive_Buffer;
static void serial_receiver_enable(
void)
{
UCSR0B = _BV(TXEN0) | _BV(RXEN0) | _BV(RXCIE0);
}
ISR(USART1_RX_vect)
{
uint8_t data_byte;
if (BIT_CHECK(UCSR1A, RXC1)) {
/* data is available */
data_byte = UDR1;
(void) FIFO_Put(&Receive_Buffer, data_byte);
}
}
bool serial_byte_get(
uint8_t * data_register)
{
bool data_available = false; /* return value */
if (!FIFO_Empty(&Receive_Buffer)) {
*data_register = FIFO_Get(&Receive_Buffer);
data_available = true;
}
return data_available;
}
bool serial_byte_peek(
uint8_t * data_register)
{
bool data_available = false; /* return value */
if (!FIFO_Empty(&Receive_Buffer)) {
*data_register = FIFO_Peek(&Receive_Buffer);
data_available = true;
}
return data_available;
}
void serial_bytes_send(
uint8_t * buffer, /* data to send */
uint16_t nbytes)
{ /* number of bytes of data */
while (!BIT_CHECK(UCSR1A, UDRE1)) {
/* do nothing - wait until Tx buffer is empty */
}
while (nbytes) {
/* Send the data byte */
UDR1 = *buffer;
while (!BIT_CHECK(UCSR1A, UDRE1)) {
/* do nothing - wait until Tx buffer is empty */
}
buffer++;
nbytes--;
}
/* was the frame sent? */
while (!BIT_CHECK(UCSR1A, TXC1)) {
/* do nothing - wait until the entire frame in the
Transmit Shift Register has been shifted out */
}
/* Clear the Transmit Complete flag by writing a one to it. */
BIT_SET(UCSR1A, TXC1);
return;
}
void serial_byte_send(
uint8_t ch)
{
uint8_t buffer[1];
buffer[0] = ch;
serial_bytes_send(&buffer[0], 1);
return;
}
uint32_t serial_baud_rate(
void)
{
return Baud_Rate;
}
bool serial_baud_rate_set(
uint32_t baud)
{
bool valid = true;
switch (baud) {
case 9600:
case 19200:
case 38400:
case 57600:
case 76800:
case 115200:
Baud_Rate = baud;
/* 2x speed mode */
BIT_SET(UCSR1A, U2X1);
/* configure baud rate */
UBRR1 = (F_CPU / (8UL * Baud_Rate)) - 1;
/* FIXME: store the baud rate */
break;
default:
valid = false;
break;
}
return valid;
}
static void serial_usart_init(
void)
{
/* enable Transmit and Receive */
UCSR1B = _BV(TXEN1) | _BV(RXEN1);
/* Set USART Control and Status Register n C */
/* Asynchronous USART 8-bit data, No parity, 1 stop */
/* Set USART Mode Select: UMSELn1 UMSELn0 = 00 for Asynchronous USART */
/* Set Parity Mode: UPMn1 UPMn0 = 00 for Parity Disabled */
/* Set Stop Bit Select: USBSn = 0 for 1 stop bit */
/* Set Character Size: UCSZn2 UCSZn1 UCSZn0 = 011 for 8-bit */
/* Clock Polarity: UCPOLn = 0 when asynchronous mode is used. */
UCSR0C = _BV(UCSZ11) | _BV(UCSZ10);
/* Clear Power Reduction */
BIT_CLEAR(PRR, PRUSART1);
}
void serial_init(
void)
{
FIFO_Init(&Receive_Buffer, &Receive_Buffer_Data[0],
(unsigned) sizeof(Receive_Buffer_Data));
serial_usart_init();
serial_baud_rate_set(Baud_Rate);
serial_receiver_enable();
}
+55 -53
View File
@@ -1,53 +1,55 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#ifndef SERIAL_H
#define SERIAL_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
bool serial_byte_get(
uint8_t * data_register);
bool serial_byte_peek(
uint8_t * data_register);
void serial_bytes_send(
uint8_t * buffer, /* data to send */
uint16_t nbytes); /* number of bytes of data */
void serial_byte_send(uint8_t ch);
uint32_t serial_baud_rate(void);
bool serial_baud_rate_set(
uint32_t baud);
void serial_init(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#ifndef SERIAL_H
#define SERIAL_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
bool serial_byte_get(
uint8_t * data_register);
bool serial_byte_peek(
uint8_t * data_register);
void serial_bytes_send(
uint8_t * buffer, /* data to send */
uint16_t nbytes); /* number of bytes of data */
void serial_byte_send(
uint8_t ch);
uint32_t serial_baud_rate(
void);
bool serial_baud_rate_set(
uint32_t baud);
void serial_init(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+80 -77
View File
@@ -1,77 +1,80 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include "hardware.h"
/* stack checking */
extern uint8_t _end;
extern uint8_t __stack;
#define STACK_CANARY (0xC5)
void stack_init(
void) __attribute__ ((naked)) __attribute__ ((section(".init1")));
void stack_init(
void)
{
#if 0
uint8_t *p = &_end;
while (p <= &__stack) {
*p = STACK_CANARY;
p++;
}
#else
__asm volatile (
" ldi r30,lo8(_end)\n" " ldi r31,hi8(_end)\n" " ldi r24,lo8(0xc5)\n" /* STACK_CANARY = 0xc5 */
" ldi r25,hi8(__stack)\n" " rjmp .cmp\n" ".loop:\n"
" st Z+,r24\n" ".cmp:\n" " cpi r30,lo8(__stack)\n"
" cpc r31,r25\n" " brlo .loop\n" " breq .loop"::);
#endif
}
unsigned stack_size(void)
{
return (&__stack) - (&_end);
}
uint8_t stack_byte(unsigned offset)
{
return *(&_end + offset);
}
unsigned stack_unused(void)
{
uint8_t *p = &_end;
unsigned count = 0;
while (p <= &__stack) {
if ((*p) != STACK_CANARY) {
count = p - (&_end);
break;
}
p++;
}
return count;
}
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include "hardware.h"
/* stack checking */
extern uint8_t _end;
extern uint8_t __stack;
#define STACK_CANARY (0xC5)
void stack_init(
void) __attribute__ ((naked)) __attribute__ ((section(".init1")));
void stack_init(
void)
{
#if 0
uint8_t *p = &_end;
while (p <= &__stack) {
*p = STACK_CANARY;
p++;
}
#else
__asm volatile (
" ldi r30,lo8(_end)\n" " ldi r31,hi8(_end)\n" " ldi r24,lo8(0xc5)\n" /* STACK_CANARY = 0xc5 */
" ldi r25,hi8(__stack)\n" " rjmp .cmp\n" ".loop:\n"
" st Z+,r24\n" ".cmp:\n" " cpi r30,lo8(__stack)\n"
" cpc r31,r25\n" " brlo .loop\n" " breq .loop"::);
#endif
}
unsigned stack_size(
void)
{
return (&__stack) - (&_end);
}
uint8_t stack_byte(
unsigned offset)
{
return *(&_end + offset);
}
unsigned stack_unused(
void)
{
uint8_t *p = &_end;
unsigned count = 0;
while (p <= &__stack) {
if ((*p) != STACK_CANARY) {
count = p - (&_end);
break;
}
p++;
}
return count;
}
+50 -48
View File
@@ -1,49 +1,51 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef STACK_H
#define STACK_H
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* C stack checking */
void stack_init(void);
unsigned stack_size(void);
uint8_t stack_byte(unsigned offset);
unsigned stack_unused(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef STACK_H
#define STACK_H
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* C stack checking */
void stack_init(
void);
unsigned stack_size(
void);
uint8_t stack_byte(
unsigned offset);
unsigned stack_unused(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+67 -67
View File
@@ -1,67 +1,67 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#ifndef TIMER_H
#define TIMER_H
#include <stdbool.h>
#include <stdint.h>
/* Timer Module */
/* reserve the millisecond timer indexes as needed for each module */
#define TIMER_SILENCE 0
#define TIMER_DEBOUNCE 1
#define TIMER_LED_1 2
#define TIMER_LED_2 3
#define TIMER_LED_3 4
#define TIMER_LED_4 5
#define TIMER_DCC 6
#define MAX_MILLISECOND_TIMERS 7
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void timer_init(
void);
unsigned long timer_milliseconds(
unsigned index);
bool timer_elapsed_milliseconds(
unsigned index,
unsigned long value);
bool timer_elapsed_seconds(
unsigned index,
unsigned long value);
bool timer_elapsed_minutes(
unsigned index,
unsigned long seconds);
unsigned long timer_milliseconds_set(
unsigned index,
unsigned long value);
unsigned long timer_reset(
unsigned index);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#ifndef TIMER_H
#define TIMER_H
#include <stdbool.h>
#include <stdint.h>
/* Timer Module */
/* reserve the millisecond timer indexes as needed for each module */
#define TIMER_SILENCE 0
#define TIMER_DEBOUNCE 1
#define TIMER_LED_1 2
#define TIMER_LED_2 3
#define TIMER_LED_3 4
#define TIMER_LED_4 5
#define TIMER_DCC 6
#define MAX_MILLISECOND_TIMERS 7
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void timer_init(
void);
unsigned long timer_milliseconds(
unsigned index);
bool timer_elapsed_milliseconds(
unsigned index,
unsigned long value);
bool timer_elapsed_seconds(
unsigned index,
unsigned long value);
bool timer_elapsed_minutes(
unsigned index,
unsigned long seconds);
unsigned long timer_milliseconds_set(
unsigned index,
unsigned long value);
unsigned long timer_reset(
unsigned index);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+223 -222
View File
@@ -1,222 +1,223 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "hardware.h"
#include "timer.h"
/* define various timers in timer.h file */
#ifndef MAX_MILLISECOND_TIMERS
#define MAX_MILLISECOND_TIMERS 2
#endif
/* Timer2 Prescaling: 1, 8, 32, 64, 128, 256, or 1024 */
#define TIMER2_PRESCALER 128
/* Count: Timer counts up to 0xFF and then signals overflow */
#define TIMER2_TICKS (F_CPU/TIMER2_PRESCALER/1000)
#if (TIMER2_TICKS > 0xFF)
#error Timer2 Prescaler value is too small
#endif
#define TIMER2_COUNT (0xFF-TIMER2_TICKS)
/* counter for the various timers */
static volatile unsigned long Millisecond_Counter[MAX_MILLISECOND_TIMERS];
/*************************************************************************
* Description: Timer Interrupt Handler
* Returns: none
* Notes: Global interupts must be enabled
*************************************************************************/
static inline void timer_interrupt_handler(void)
{
unsigned i; /* loop counter */
/* increment the tick count */
for (i = 0; i < MAX_MILLISECOND_TIMERS; i++) {
Millisecond_Counter[i]++;
}
}
/*************************************************************************
* Description: Timer Interrupt Service Routine - Timer Overflowed!
* Returns: none
* Notes: Global interupts must be enabled
*************************************************************************/
ISR(TIMER2_OVF_vect)
{
/* Set the counter for the next interrupt */
TCNT2 = TIMER2_COUNT;
timer_interrupt_handler();
}
/*************************************************************************
* Description: sets the current time count with a value
* Returns: none
* Notes: none
*************************************************************************/
unsigned long timer_milliseconds_set(
unsigned index,
unsigned long value)
{
uint8_t sreg = 0; /* holds interrupts pending */
unsigned long old_value = 0; /* return value */
if (index < MAX_MILLISECOND_TIMERS) {
sreg = SREG;
__disable_interrupt();
old_value = Millisecond_Counter[index];
Millisecond_Counter[index] = value;
SREG = sreg;
}
return old_value;
}
/*************************************************************************
* Description: returns the current millisecond count
* Returns: none
* Notes: none
*************************************************************************/
unsigned long timer_milliseconds(
unsigned index)
{
unsigned long timer_value = 0; /* return value */
uint8_t sreg = 0; /* holds interrupts pending */
if (index < MAX_MILLISECOND_TIMERS) {
sreg = SREG;
__disable_interrupt();
timer_value = Millisecond_Counter[index];
SREG = sreg;
}
return timer_value;
}
/*************************************************************************
* Description: compares the current time count with a value
* Returns: true if the time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_milliseconds(
unsigned index,
unsigned long value)
{
return (timer_milliseconds(index) >= value);
}
/*************************************************************************
* Description: compares the current time count with a value
* Returns: true if the time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_seconds(
unsigned index,
unsigned long seconds)
{
return ((timer_milliseconds(index)/1000UL) >= seconds);
}
/*************************************************************************
* Description: compares the current time count with a value
* Returns: true if the time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_minutes(
unsigned index,
unsigned long minutes)
{
return ((timer_milliseconds(index)/(1000UL*60UL)) >= minutes);
}
/*************************************************************************
* Description: Sets the timer counter to zero.
* Returns: none
* Notes: none
*************************************************************************/
unsigned long timer_reset(
unsigned index)
{
return timer_milliseconds_set(index,0);
}
/*************************************************************************
* Description: Initialization for Timer
* Returns: none
* Notes: none
*************************************************************************/
static void timer2_init(
void)
{
/* Normal Operation */
TCCR2A = 0;
/* Timer2: prescale selections:
CSn2 CSn1 CSn0 Description
---- ---- ---- -----------
0 0 0 No Clock Source
0 0 1 No prescaling
0 1 0 CLKt2s/8
0 1 1 CLKt2s/32
1 0 0 CLKt2s/64
1 0 1 CLKt2s/128
1 1 0 CLKt2s/256
1 1 1 CLKt2s/1024
*/
#if (TIMER2_PRESCALER==1)
TCCR2B = _BV(CS20);
#elif (TIMER2_PRESCALER==8)
TCCR2B = _BV(CS21);
#elif (TIMER2_PRESCALER==32)
TCCR2B = _BV(CS21) | _BV(CS20);
#elif (TIMER2_PRESCALER==64)
TCCR2B = _BV(CS22);
#elif (TIMER2_PRESCALER==128)
TCCR2B = _BV(CS22) | _BV(CS20);
#elif (TIMER2_PRESCALER==256)
TCCR2B = _BV(CS22) | _BV(CS21);
#elif (TIMER2_PRESCALER==1024)
TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);
#else
#error Timer2 Prescale: Invalid Value
#endif
/* Clear any TOV Flag set when the timer overflowed */
BIT_CLEAR(TIFR2, TOV2);
/* Initial value */
TCNT2 = TIMER2_COUNT;
/* Enable the overflow interrupt */
BIT_SET(TIMSK2, TOIE2);
/* Clear the Power Reduction Timer/Counter0 */
BIT_CLEAR(PRR, PRTIM2);
}
/*************************************************************************
* Description: Initialization for Timer
* Returns: none
* Notes: none
*************************************************************************/
void timer_init(
void)
{
timer2_init();
}
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "hardware.h"
#include "timer.h"
/* define various timers in timer.h file */
#ifndef MAX_MILLISECOND_TIMERS
#define MAX_MILLISECOND_TIMERS 2
#endif
/* Timer2 Prescaling: 1, 8, 32, 64, 128, 256, or 1024 */
#define TIMER2_PRESCALER 128
/* Count: Timer counts up to 0xFF and then signals overflow */
#define TIMER2_TICKS (F_CPU/TIMER2_PRESCALER/1000)
#if (TIMER2_TICKS > 0xFF)
#error Timer2 Prescaler value is too small
#endif
#define TIMER2_COUNT (0xFF-TIMER2_TICKS)
/* counter for the various timers */
static volatile unsigned long Millisecond_Counter[MAX_MILLISECOND_TIMERS];
/*************************************************************************
* Description: Timer Interrupt Handler
* Returns: none
* Notes: Global interupts must be enabled
*************************************************************************/
static inline void timer_interrupt_handler(
void)
{
unsigned i; /* loop counter */
/* increment the tick count */
for (i = 0; i < MAX_MILLISECOND_TIMERS; i++) {
Millisecond_Counter[i]++;
}
}
/*************************************************************************
* Description: Timer Interrupt Service Routine - Timer Overflowed!
* Returns: none
* Notes: Global interupts must be enabled
*************************************************************************/
ISR(TIMER2_OVF_vect)
{
/* Set the counter for the next interrupt */
TCNT2 = TIMER2_COUNT;
timer_interrupt_handler();
}
/*************************************************************************
* Description: sets the current time count with a value
* Returns: none
* Notes: none
*************************************************************************/
unsigned long timer_milliseconds_set(
unsigned index,
unsigned long value)
{
uint8_t sreg = 0; /* holds interrupts pending */
unsigned long old_value = 0; /* return value */
if (index < MAX_MILLISECOND_TIMERS) {
sreg = SREG;
__disable_interrupt();
old_value = Millisecond_Counter[index];
Millisecond_Counter[index] = value;
SREG = sreg;
}
return old_value;
}
/*************************************************************************
* Description: returns the current millisecond count
* Returns: none
* Notes: none
*************************************************************************/
unsigned long timer_milliseconds(
unsigned index)
{
unsigned long timer_value = 0; /* return value */
uint8_t sreg = 0; /* holds interrupts pending */
if (index < MAX_MILLISECOND_TIMERS) {
sreg = SREG;
__disable_interrupt();
timer_value = Millisecond_Counter[index];
SREG = sreg;
}
return timer_value;
}
/*************************************************************************
* Description: compares the current time count with a value
* Returns: true if the time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_milliseconds(
unsigned index,
unsigned long value)
{
return (timer_milliseconds(index) >= value);
}
/*************************************************************************
* Description: compares the current time count with a value
* Returns: true if the time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_seconds(
unsigned index,
unsigned long seconds)
{
return ((timer_milliseconds(index) / 1000UL) >= seconds);
}
/*************************************************************************
* Description: compares the current time count with a value
* Returns: true if the time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_minutes(
unsigned index,
unsigned long minutes)
{
return ((timer_milliseconds(index) / (1000UL * 60UL)) >= minutes);
}
/*************************************************************************
* Description: Sets the timer counter to zero.
* Returns: none
* Notes: none
*************************************************************************/
unsigned long timer_reset(
unsigned index)
{
return timer_milliseconds_set(index, 0);
}
/*************************************************************************
* Description: Initialization for Timer
* Returns: none
* Notes: none
*************************************************************************/
static void timer2_init(
void)
{
/* Normal Operation */
TCCR2A = 0;
/* Timer2: prescale selections:
CSn2 CSn1 CSn0 Description
---- ---- ---- -----------
0 0 0 No Clock Source
0 0 1 No prescaling
0 1 0 CLKt2s/8
0 1 1 CLKt2s/32
1 0 0 CLKt2s/64
1 0 1 CLKt2s/128
1 1 0 CLKt2s/256
1 1 1 CLKt2s/1024
*/
#if (TIMER2_PRESCALER==1)
TCCR2B = _BV(CS20);
#elif (TIMER2_PRESCALER==8)
TCCR2B = _BV(CS21);
#elif (TIMER2_PRESCALER==32)
TCCR2B = _BV(CS21) | _BV(CS20);
#elif (TIMER2_PRESCALER==64)
TCCR2B = _BV(CS22);
#elif (TIMER2_PRESCALER==128)
TCCR2B = _BV(CS22) | _BV(CS20);
#elif (TIMER2_PRESCALER==256)
TCCR2B = _BV(CS22) | _BV(CS21);
#elif (TIMER2_PRESCALER==1024)
TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);
#else
#error Timer2 Prescale: Invalid Value
#endif
/* Clear any TOV Flag set when the timer overflowed */
BIT_CLEAR(TIFR2, TOV2);
/* Initial value */
TCNT2 = TIMER2_COUNT;
/* Enable the overflow interrupt */
BIT_SET(TIMSK2, TOIE2);
/* Clear the Power Reduction Timer/Counter0 */
BIT_CLEAR(PRR, PRTIM2);
}
/*************************************************************************
* Description: Initialization for Timer
* Returns: none
* Notes: none
*************************************************************************/
void timer_init(
void)
{
timer2_init();
}
+1 -1
View File
@@ -450,7 +450,7 @@ int Device_Encode_Property_APDU(
case PROP_UTC_OFFSET:
/* Note: BACnet Time Zone is offset of local time and UTC,
rather than offset of GMT. It is expressed in minutes */
apdu_len = encode_application_signed(&apdu[0], 5*60 /* EST */ );
apdu_len = encode_application_signed(&apdu[0], 5 * 60 /* EST */ );
break;
case PROP_LOCAL_DATE:
/* FIXME: if you support date */
+5 -11
View File
@@ -98,8 +98,8 @@ void RS485_Set_Interface(
if (ifname) {
if (strncmp("COM", ifname, 3) == 0) {
if (strlen(ifname) > 3) {
sprintf(RS485_Port_Name, "\\\\.\\COM%i", atoi(ifname+3));
fprintf(stderr, "Adjusted interface name to %s\r\n",
sprintf(RS485_Port_Name, "\\\\.\\COM%i", atoi(ifname + 3));
fprintf(stderr, "Adjusted interface name to %s\r\n",
RS485_Port_Name);
}
}
@@ -119,15 +119,9 @@ static void RS485_Print_Error(
DWORD dwExtSize;
DWORD dwErr;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL );
MessageBox( NULL, lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION );
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
(LPTSTR) & lpMsgBuf, 0, NULL);
MessageBox(NULL, lpMsgBuf, "GetLastError", MB_OK | MB_ICONINFORMATION);
LocalFree(lpMsgBuf);
return;
+5 -10
View File
@@ -809,34 +809,29 @@ bool bacapp_print_value(
if (value->type.Date.day == 255) {
fprintf(stream, "(unspecified), ");
} else {
fprintf(stream, "%u, ",
(unsigned) value->type.Date.day);
fprintf(stream, "%u, ", (unsigned) value->type.Date.day);
}
if (value->type.Date.year == 255) {
fprintf(stream, "(unspecified), ");
} else {
fprintf(stream, "%u",
(unsigned) value->type.Date.year);
fprintf(stream, "%u", (unsigned) value->type.Date.year);
}
break;
case BACNET_APPLICATION_TAG_TIME:
if (value->type.Time.hour == 255) {
fprintf(stream, "**:");
} else {
fprintf(stream, "%02u:",
(unsigned) value->type.Time.hour);
fprintf(stream, "%02u:", (unsigned) value->type.Time.hour);
}
if (value->type.Time.min == 255) {
fprintf(stream, "**:");
} else {
fprintf(stream, "%02u:",
(unsigned) value->type.Time.min);
fprintf(stream, "%02u:", (unsigned) value->type.Time.min);
}
if (value->type.Time.sec == 255) {
fprintf(stream, "**.");
} else {
fprintf(stream, "%02u.",
(unsigned) value->type.Time.sec);
fprintf(stream, "%02u.", (unsigned) value->type.Time.sec);
}
if (value->type.Time.hundredths == 255) {
fprintf(stream, "**");