diff --git a/bacnet-stack/ports/atmega168/Makefile b/bacnet-stack/ports/atmega168/Makefile
new file mode 100644
index 00000000..e87f13a7
--- /dev/null
+++ b/bacnet-stack/ports/atmega168/Makefile
@@ -0,0 +1,83 @@
+###############################################################################
+# Makefile for the project bacnet
+###############################################################################
+
+## General Flags
+PROJECT = bacnet
+MCU = atmega168
+TARGET = bacnet.elf
+CC = avr-gcc.exe
+
+## Options common to compile, link and assembly rules
+COMMON = -mmcu=$(MCU)
+
+## Compile options common for all C compilation units.
+CFLAGS = $(COMMON)
+CFLAGS += -Wall -gdwarf-2 -O0
+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)
+LDFLAGS +=
+
+
+## Intel Hex file production flags
+HEX_FLASH_FLAGS = -R .eeprom
+
+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
+
+
+## Include Directories
+INCLUDES = -I"C:\code\bacnet-stack\ports\atmega168\..\.."
+
+## Objects that must be built in order to link
+OBJECTS = main.o rs485.o timer.o
+
+## Objects explicitly added by the user
+LINKONLYOBJECTS =
+
+## Build
+all: $(TARGET) bacnet.hex bacnet.eep size
+
+## Compile
+main.o: ../main.c
+ $(CC) $(INCLUDES) $(CFLAGS) -c $<
+
+rs485.o: ../rs485.c
+ $(CC) $(INCLUDES) $(CFLAGS) -c $<
+
+timer.o: ../timer.c
+ $(CC) $(INCLUDES) $(CFLAGS) -c $<
+
+##Link
+$(TARGET): $(OBJECTS)
+ $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)
+
+%.hex: $(TARGET)
+ avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@
+
+%.eep: $(TARGET)
+ -avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0
+
+%.lss: $(TARGET)
+ avr-objdump -h -S $< > $@
+
+size: ${TARGET}
+ @echo
+ @avr-size -C --mcu=${MCU} ${TARGET}
+
+## Clean target
+.PHONY: clean
+clean:
+ -rm -rf $(OBJECTS) bacnet.elf dep/* bacnet.hex bacnet.eep
+
+## Other dependencies
+-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)
+
diff --git a/bacnet-stack/ports/atmega168/avr035.h b/bacnet-stack/ports/atmega168/avr035.h
new file mode 100644
index 00000000..0dd766ab
--- /dev/null
+++ b/bacnet-stack/ports/atmega168/avr035.h
@@ -0,0 +1,18 @@
+#ifndef AVR035_H
+#define AVR035_H
+
+/* from AVR035: Efficient C Coding for AVR */
+
+/* a=register, b=bit number to act upon */
+#define BIT_SET(a,b) ((a) |= (1<<(b)))
+#define BIT_CLEAR(a,b) ((a) &= ~(1<<(b)))
+#define BIT_FLIP(a,b) ((a) ^= (1<<(b)))
+#define BIT_CHECK(a,b) ((a) & (1<<(b)))
+
+/* x=target variable, y=mask */
+#define BITMASK_SET(x,y) ((x) |= (y))
+#define BITMASK_CLEAR(x,y) ((x) &= (~(y)))
+#define BITMASK_FLIP(x,y) ((x) ^= (y))
+#define BITMASK_CHECK(x,y) ((x) & (y))
+
+#endif
diff --git a/bacnet-stack/ports/atmega168/bacnet.aps b/bacnet-stack/ports/atmega168/bacnet.aps
new file mode 100644
index 00000000..4486921e
--- /dev/null
+++ b/bacnet-stack/ports/atmega168/bacnet.aps
@@ -0,0 +1 @@
+13-Aug-2007 15:08:2714-Aug-2007 17:09:10013-Aug-2007 15:08:2744, 13, 0, 528AVR GCC241bacnet13-Aug-2007 15:11:0713-Aug-2007 15:11:07241013-Aug-2007 15:11:0744, 13, 0, 528AVR GCCdefault\bacnet.elfC:\code\bacnet-stack\ports\atmega168\falseR00R01R02R03R04R05R06R07R08R09R10R11R12R13R14R15R16R17R18R19R20R21R22R23R24R25R26R27R28R29R30R31AVR SimulatorAVR SimulatorATmega168.xmlAuto000main.crs485.ctimer.cavr035.hhardware.hrs485.hiocompat.htimer.hdefaultNOatmega16810bacnet.elfdefault\0..\..\-Wall -gdwarf-2 -DF_CPU=7372800UL -O0 -fsigned-chardefault1C:\WinAVR-20070525\bin\avr-gcc.exeC:\WinAVR-20070525\utils\bin\make.exe00000C:\WinAVR-20070525\avr\include\avr\eeprom.h100001C:\WinAVR-20070525\avr\include\avr\iomx8.h100002C:\WinAVR-20070525\examples\stdiodemo\uart.h100003C:\WinAVR-20070525\examples\stdiodemo\uart.c100004main.c100005timer.c259748 696 908 72020 45566 211 1235 650690 21428 696 588 7200 0268 696 428 7200 0444 272 1300 69850 14290 118 1092 52052 2
diff --git a/bacnet-stack/ports/atmega168/hardware.h b/bacnet-stack/ports/atmega168/hardware.h
new file mode 100644
index 00000000..c4411c57
--- /dev/null
+++ b/bacnet-stack/ports/atmega168/hardware.h
@@ -0,0 +1,40 @@
+/**************************************************************************
+*
+* Copyright (C) 2007 Steve Karg
+*
+* Permission is hereby granted, free of charge, to any person obtaining
+* a copy of this software and associated documentation files (the
+* "Software"), to deal in the Software without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to
+* permit persons to whom the Software is furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*
+*********************************************************************/
+#ifndef HARDWARE_H
+#define HARDWARE_H
+
+#include
+#include
+#include "avr035.h"
+
+#if !defined(__AVR_ATmega168__)
+#error Firmware is configured for ATmega168 only.
+#endif
+
+/* The processor clock frequency */
+#define FREQ_CPU (7372800)
+
+
+#endif
diff --git a/bacnet-stack/ports/atmega168/main.c b/bacnet-stack/ports/atmega168/main.c
new file mode 100644
index 00000000..29f8c54b
--- /dev/null
+++ b/bacnet-stack/ports/atmega168/main.c
@@ -0,0 +1,85 @@
+/**************************************************************************
+*
+* Copyright (C) 2007 Steve Karg
+*
+* Permission is hereby granted, free of charge, to any person obtaining
+* a copy of this software and associated documentation files (the
+* "Software"), to deal in the Software without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to
+* permit persons to whom the Software is furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*
+*********************************************************************/
+
+#include
+#include
+#include "hardware.h"
+#include "timer.h"
+#include "rs485.h"
+
+/* For porting to IAR, see:
+ http://www.avrfreaks.net/wiki/index.php/Documentation:AVR_GCC/IarToAvrgcc*/
+
+static uint16_t Transmit_Timer = 0;
+#define MAX_FRAME 5
+static uint8_t Transmit_Frame[MAX_FRAME] = {0xAA, 0x55, 0x01, 0x45, 0xAB };
+
+void init(void)
+{
+
+ /* Initialize I/O ports */
+ /* For Port DDRx (Data Direction) Input=1, Output=1 */
+ /* For Port PORTx (Bit Value) TriState=0, High=1 */
+
+ DDRB = 0;
+ PORTB = 0;
+ DDRC = 0;
+ PORTC = 0;
+ DDRD = 0;
+ PORTD = 0;
+
+ /* Configure the watchdog timer */
+
+ /* Configure USART */
+ RS485_Set_Baud_Rate(38400);
+ RS485_Initialize();
+
+ /* Configure Timer0 for millisecond timer */
+ timer_initialize();
+}
+
+void task_milliseconds(void)
+{
+ while (Timer_Milliseconds) {
+ Timer_Milliseconds--;
+ /* add other millisecond timer tasks here */
+ Transmit_Timer++;
+ }
+}
+
+int main(void)
+{
+ init();
+ for (;;) {
+ task_milliseconds();
+ /* other tasks */
+ if (Transmit_Timer > 1000) {
+ Transmit_Timer = 0;
+ RS485_Send_Frame(NULL,Transmit_Frame, MAX_FRAME);
+ }
+ }
+
+ return 0;
+}
diff --git a/bacnet-stack/ports/atmega168/rs485.c b/bacnet-stack/ports/atmega168/rs485.c
new file mode 100644
index 00000000..4721717b
--- /dev/null
+++ b/bacnet-stack/ports/atmega168/rs485.c
@@ -0,0 +1,160 @@
+/**************************************************************************
+*
+* Copyright (C) 2007 Steve Karg
+*
+* Permission is hereby granted, free of charge, to any person obtaining
+* a copy of this software and associated documentation files (the
+* "Software"), to deal in the Software without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to
+* permit persons to whom the Software is furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*
+*********************************************************************/
+
+/* The module handles sending data out the RS-485 port */
+/* and handles receiving data from the RS-485 port. */
+/* Customize this file for your specific hardware */
+#include
+#include
+#include
+#include
+#include
+#include "mstp.h"
+
+/* This file has been customized for use with ATMEGA168 */
+#include "hardware.h"
+
+/* baud rate */
+static uint32_t RS485_Baud = 38400;
+
+/****************************************************************************
+* DESCRIPTION: Initializes the RS485 hardware and variables, and starts in
+* receive mode.
+* RETURN: none
+* ALGORITHM: none
+* NOTES: none
+*****************************************************************************/
+void RS485_Initialize(void)
+{
+ /* enable Transmit and Receive */
+ UCSR0B = _BV(TXEN0) | _BV(RXEN0);
+
+ /* Set frame format: 8data, 2stop bit */
+ UCSR0C = _BV(USBS0) | _BV(UCSZ00);
+
+ return;
+}
+
+void RS485_Cleanup(void)
+{
+
+}
+
+/****************************************************************************
+* DESCRIPTION: Returns the baud rate that we are currently running at
+* RETURN: none
+* ALGORITHM: none
+* NOTES: none
+*****************************************************************************/
+uint32_t RS485_Get_Baud_Rate(void)
+{
+ return RS485_Baud;
+}
+
+/****************************************************************************
+* DESCRIPTION: Sets the baud rate for the chip USART
+* RETURN: none
+* ALGORITHM: none
+* NOTES: none
+*****************************************************************************/
+bool RS485_Set_Baud_Rate(uint32_t baud)
+{
+ bool valid = true;
+
+ switch (baud) {
+ case 9600:
+ case 19200:
+ case 38400:
+ case 57600:
+ case 76800:
+ case 115200:
+ RS485_Baud = baud;
+ /* 2x speed mode */
+ BIT_SET(UCSR0A,U2X0);
+ /* configure baud rate */
+ UBRR0 = (FREQ_CPU / (8UL * RS485_Baud)) - 1;
+ /* FIXME: store the baud rate */
+ break;
+ default:
+ valid = false;
+ break;
+ }
+
+ return valid;
+}
+
+/* Transmits a Frame on the wire */
+void RS485_Send_Frame(
+ volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
+ uint8_t * buffer, /* frame to send (up to 501 bytes of data) */
+ uint16_t nbytes) /* number of bytes of data (up to 501) */
+{
+ uint8_t turnaround_time;
+
+ /* delay after reception - per MS/TP spec */
+ if (mstp_port) {
+ /* wait about 40 bit times since reception */
+ turnaround_time = (40UL*1000UL)/RS485_Baud;
+ if (!turnaround_time) {
+ turnaround_time = 1;
+ }
+ while (mstp_port->SilenceTimer < turnaround_time) {
+ /* do nothing - wait for timer to increment */
+ };
+ }
+ while (nbytes) {
+ while (!BIT_CHECK(UCSR0A,UDRE0)) {
+ /* do nothing - wait until Tx buffer is empty */
+ }
+ UDR0 = *buffer;
+ buffer++;
+ nbytes--;
+ /* per MSTP spec */
+ if (mstp_port) {
+ mstp_port->SilenceTimer = 0;
+ }
+ }
+ while (!BIT_CHECK(UCSR0A,UDRE0)) {
+ /* do nothing - wait until Tx buffer is empty */
+ }
+
+ return;
+}
+
+/* called by timer, interrupt(?) or other thread */
+void RS485_Check_UART_Data(struct mstp_port_struct_t *mstp_port)
+{
+ if (mstp_port->ReceiveError == true) {
+ /* wait for state machine to clear this */
+ }
+ /* wait for state machine to read from the DataRegister */
+ else if (mstp_port->DataAvailable == false) {
+ /* check for data */
+ if (!BIT_CHECK(UCSR0A,RXC0)) {
+ mstp_port->DataRegister = UDR0;
+ mstp_port->DataAvailable = true;
+ }
+ }
+}
diff --git a/bacnet-stack/ports/atmega168/rs485.h b/bacnet-stack/ports/atmega168/rs485.h
new file mode 100644
index 00000000..acdde4a7
--- /dev/null
+++ b/bacnet-stack/ports/atmega168/rs485.h
@@ -0,0 +1,52 @@
+/**************************************************************************
+*
+* Copyright (C) 2007 Steve Karg
+*
+* Permission is hereby granted, free of charge, to any person obtaining
+* a copy of this software and associated documentation files (the
+* "Software"), to deal in the Software without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to
+* permit persons to whom the Software is furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*
+*********************************************************************/
+
+#ifndef RS485_H
+#define RS485_H
+
+#include
+#include "mstp.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ void RS485_Initialize(void);
+
+ void RS485_Send_Frame(
+ volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
+ uint8_t * buffer, /* frame to send (up to 501 bytes of data) */
+ uint16_t nbytes); /* number of bytes of data (up to 501) */
+
+ uint8_t RS485_Check_UART_Data(
+ volatile struct mstp_port_struct_t *mstp_port); /* port specific data */
+
+ uint32_t RS485_Get_Baud_Rate(void);
+ bool RS485_Set_Baud_Rate(uint32_t baud);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
diff --git a/bacnet-stack/ports/atmega168/timer.c b/bacnet-stack/ports/atmega168/timer.c
new file mode 100644
index 00000000..63469c54
--- /dev/null
+++ b/bacnet-stack/ports/atmega168/timer.c
@@ -0,0 +1,60 @@
+/**************************************************************************
+*
+* Copyright (C) 2007 Steve Karg
+*
+* Permission is hereby granted, free of charge, to any person obtaining
+* a copy of this software and associated documentation files (the
+* "Software"), to deal in the Software without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to
+* permit persons to whom the Software is furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*
+*********************************************************************/
+
+#include "hardware.h"
+
+/* Prescaling: 1, 8, 64, 256, 1024 */
+#define TIMER_1_PRESCALER 1
+/* Count: Timer counts up to 0xFFFF and then signals overflow */
+#define TIMER_1_TICKS (FREQ_CPU/TIMER_1_PRESCALER/1000)
+#define TIMER_1_COUNT (0xFFFF-TIMER_1_TICKS)
+/* Global variable millisecond timer - used by main.c for timers task */
+volatile uint8_t Timer_Milliseconds = 0;
+
+/* Configure the Timer */
+void timer_initialize(void)
+{
+ /* Normal Operation */
+ TCCR1A = 0;
+ /* CS10 = clkI/O/1 (No prescaling) */
+ TCCR1B = _BV(CS10);
+ /* Clear any TOV1 Flag set when the timer overflowed */
+ BIT_CLEAR(TIFR1,TOV1);
+ /* Initial value */
+ TCNT1 = TIMER_1_COUNT;
+ /* Enable the overflow interrupt */
+ BIT_SET(TIMSK1,TOIE1);
+}
+
+
+/* Timer Overflowed! Increment the time. */
+ISR(TIMER1_OVF_vect)
+{
+ /* Set the counter for the next interrupt */
+ TCNT1 = TIMER_1_COUNT;
+ /* Overflow Flag is automatically cleared */
+ if (Timer_Milliseconds < 0xFF)
+ Timer_Milliseconds++;
+}
diff --git a/bacnet-stack/ports/atmega168/timer.h b/bacnet-stack/ports/atmega168/timer.h
new file mode 100644
index 00000000..f49493a2
--- /dev/null
+++ b/bacnet-stack/ports/atmega168/timer.h
@@ -0,0 +1,32 @@
+/**************************************************************************
+*
+* Copyright (C) 2007 Steve Karg
+*
+* Permission is hereby granted, free of charge, to any person obtaining
+* a copy of this software and associated documentation files (the
+* "Software"), to deal in the Software without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to
+* permit persons to whom the Software is furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*
+*********************************************************************/
+#ifndef TIMER_H
+#define TIMER_H
+
+extern volatile uint8_t Timer_Milliseconds;
+
+void timer_initialize(void);
+
+#endif