summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsicarius <devnull@localhost>2007-02-11 19:32:03 +0100
committersicarius <devnull@localhost>2007-02-11 19:32:03 +0100
commit56d9bdd39ed36c36e9a61411b86c76d5228b2133 (patch)
tree0cca7a63a5609f91d1912ecbde6743938c9ae5d2
parent644121b478a57772150f460c3c8cd035aa6767a2 (diff)
downloadrc2007-soccer-56d9bdd39ed36c36e9a61411b86c76d5228b2133.tar
rc2007-soccer-56d9bdd39ed36c36e9a61411b86c76d5228b2133.zip
Added lot's of code-files used during work
-rw-r--r--source/Code/.dep/main.o.d24
-rw-r--r--source/Code/HAL/board.c9
-rw-r--r--source/Code/HAL/board.h14
-rwxr-xr-xsource/Code/genmakefile.sh11
-rw-r--r--source/Code/main.c10
-rw-r--r--source/Code/makefile438
-rw-r--r--source/ct-Bot/.cdtbuild145
-rw-r--r--source/ct-Bot/.cdtproject33
-rw-r--r--source/ct-Bot/.cvsignore2
-rw-r--r--source/ct-Bot/.project19
-rw-r--r--source/ct-Bot/.settings/org.eclipse.cdt.managedbuilder.core.prefs18
-rw-r--r--source/ct-Bot/.settings/org.eclipse.core.runtime.prefs5
-rw-r--r--source/ct-Bot/Changelog.txt447
-rw-r--r--source/ct-Bot/Documentation/TWI-Treiber.htm70
-rw-r--r--source/ct-Bot/Documentation/mmc-vm.html154
-rw-r--r--source/ct-Bot/Documentation/mmc.jpgbin0 -> 193468 bytes
-rw-r--r--source/ct-Bot/Documentation/remote-calls.html33
-rw-r--r--source/ct-Bot/Documentation/select-behaviours.txt29
-rw-r--r--source/ct-Bot/Documentation/style.css128
-rw-r--r--source/ct-Bot/GPL.txt92
-rw-r--r--source/ct-Bot/Makefile461
-rw-r--r--source/ct-Bot/TODO.txt58
-rw-r--r--source/ct-Bot/bot-logic/behaviour_avoid_border.c41
-rw-r--r--source/ct-Bot/bot-logic/behaviour_avoid_col.c142
-rw-r--r--source/ct-Bot/bot-logic/behaviour_catch_pillar.c106
-rw-r--r--source/ct-Bot/bot-logic/behaviour_drive_distance.c120
-rw-r--r--source/ct-Bot/bot-logic/behaviour_drive_square.c76
-rw-r--r--source/ct-Bot/bot-logic/behaviour_follow_line.c176
-rw-r--r--source/ct-Bot/bot-logic/behaviour_goto.c141
-rw-r--r--source/ct-Bot/bot-logic/behaviour_gotoxy.c141
-rw-r--r--source/ct-Bot/bot-logic/behaviour_olympic.c428
-rw-r--r--source/ct-Bot/bot-logic/behaviour_remotecall.c407
-rw-r--r--source/ct-Bot/bot-logic/behaviour_scan.c144
-rw-r--r--source/ct-Bot/bot-logic/behaviour_servo.c68
-rw-r--r--source/ct-Bot/bot-logic/behaviour_simple.c139
-rw-r--r--source/ct-Bot/bot-logic/behaviour_solve_maze.c660
-rw-r--r--source/ct-Bot/bot-logic/behaviour_turn.c361
-rw-r--r--source/ct-Bot/bot-logic/bot-logik.c500
-rw-r--r--source/ct-Bot/command.c469
-rw-r--r--source/ct-Bot/contrib/bot.map.zipbin0 -> 4232 bytes
-rw-r--r--source/ct-Bot/contrib/flash_n_fuse/STK200.bat39
-rw-r--r--source/ct-Bot/contrib/flash_n_fuse/STK200Fuses.bat24
-rw-r--r--source/ct-Bot/contrib/flash_n_fuse/flash.bat21
-rw-r--r--source/ct-Bot/contrib/flash_n_fuse/flash.sh55
-rw-r--r--source/ct-Bot/contrib/flash_n_fuse/fuses.txt17
-rw-r--r--source/ct-Bot/contrib/flash_n_fuse/hfuse.hex2
-rw-r--r--source/ct-Bot/contrib/flash_n_fuse/lfuse.hex2
-rw-r--r--source/ct-Bot/contrib/flash_n_fuse/loadusbtty.sh14
-rw-r--r--source/ct-Bot/contrib/flash_n_fuse/lock.hex2
-rw-r--r--source/ct-Bot/contrib/flash_n_fuse/setfuses.bat17
-rw-r--r--source/ct-Bot/contrib/flash_n_fuse/setfuses.sh11
-rw-r--r--source/ct-Bot/ct-Bot.c747
-rw-r--r--source/ct-Bot/ct-Bot.h272
-rw-r--r--source/ct-Bot/doxygen.Doxyfile1228
-rw-r--r--source/ct-Bot/gdb-run5
-rw-r--r--source/ct-Bot/include/TWI_driver.h120
-rw-r--r--source/ct-Bot/include/adc.h55
-rw-r--r--source/ct-Bot/include/bot-2-pc.h47
-rw-r--r--source/ct-Bot/include/bot-2-sim.h71
-rw-r--r--source/ct-Bot/include/bot-local.h111
-rw-r--r--source/ct-Bot/include/bot-logic/available_behaviours.h98
-rw-r--r--source/ct-Bot/include/bot-logic/behaviour_avoid_border.h39
-rw-r--r--source/ct-Bot/include/bot-logic/behaviour_avoid_col.h42
-rw-r--r--source/ct-Bot/include/bot-logic/behaviour_catch_pillar.h51
-rw-r--r--source/ct-Bot/include/bot-logic/behaviour_drive_distance.h57
-rw-r--r--source/ct-Bot/include/bot-logic/behaviour_drive_square.h50
-rw-r--r--source/ct-Bot/include/bot-logic/behaviour_follow_line.h44
-rw-r--r--source/ct-Bot/include/bot-logic/behaviour_goto.h46
-rw-r--r--source/ct-Bot/include/bot-logic/behaviour_gotoxy.h50
-rw-r--r--source/ct-Bot/include/bot-logic/behaviour_olympic.h93
-rw-r--r--source/ct-Bot/include/bot-logic/behaviour_scan.h51
-rw-r--r--source/ct-Bot/include/bot-logic/behaviour_servo.h55
-rw-r--r--source/ct-Bot/include/bot-logic/behaviour_simple.h90
-rw-r--r--source/ct-Bot/include/bot-logic/behaviour_solve_maze.h61
-rw-r--r--source/ct-Bot/include/bot-logic/behaviour_turn.h51
-rw-r--r--source/ct-Bot/include/bot-logic/bot-logik.h196
-rw-r--r--source/ct-Bot/include/bot-logic/remote_calls.h89
-rw-r--r--source/ct-Bot/include/command.h195
-rw-r--r--source/ct-Bot/include/delay.h41
-rw-r--r--source/ct-Bot/include/display.h69
-rw-r--r--source/ct-Bot/include/ena.h68
-rw-r--r--source/ct-Bot/include/global.h67
-rw-r--r--source/ct-Bot/include/ir-rc5.h51
-rw-r--r--source/ct-Bot/include/led.h86
-rw-r--r--source/ct-Bot/include/log.h172
-rw-r--r--source/ct-Bot/include/map.h149
-rw-r--r--source/ct-Bot/include/mini-fat.h63
-rw-r--r--source/ct-Bot/include/mmc-emu.h85
-rw-r--r--source/ct-Bot/include/mmc-low.h45
-rw-r--r--source/ct-Bot/include/mmc-vm.h150
-rw-r--r--source/ct-Bot/include/mmc.h104
-rw-r--r--source/ct-Bot/include/motor-low.h53
-rw-r--r--source/ct-Bot/include/motor.h98
-rw-r--r--source/ct-Bot/include/mouse.h113
-rw-r--r--source/ct-Bot/include/rc5-codes.h591
-rw-r--r--source/ct-Bot/include/rc5.h33
-rw-r--r--source/ct-Bot/include/sensor-low.h44
-rw-r--r--source/ct-Bot/include/sensor.h111
-rw-r--r--source/ct-Bot/include/sensor_correction.h39
-rw-r--r--source/ct-Bot/include/shift.h63
-rw-r--r--source/ct-Bot/include/srf10.h105
-rw-r--r--source/ct-Bot/include/tcp-server.h49
-rw-r--r--source/ct-Bot/include/tcp.h92
-rw-r--r--source/ct-Bot/include/timer.h102
-rw-r--r--source/ct-Bot/include/uart.h75
-rw-r--r--source/ct-Bot/log.c290
-rw-r--r--source/ct-Bot/map.c659
-rw-r--r--source/ct-Bot/mcu/TWI_driver.c194
-rw-r--r--source/ct-Bot/mcu/adc.c70
-rw-r--r--source/ct-Bot/mcu/bot-2-pc.c111
-rw-r--r--source/ct-Bot/mcu/delay.c69
-rw-r--r--source/ct-Bot/mcu/display.c272
-rw-r--r--source/ct-Bot/mcu/ena.c128
-rw-r--r--source/ct-Bot/mcu/ir-rc5.c163
-rw-r--r--source/ct-Bot/mcu/led.c74
-rw-r--r--source/ct-Bot/mcu/mini-fat.c93
-rw-r--r--source/ct-Bot/mcu/mmc-low.S482
-rw-r--r--source/ct-Bot/mcu/mmc.c420
-rw-r--r--source/ct-Bot/mcu/motor-low.c242
-rw-r--r--source/ct-Bot/mcu/mouse.c183
-rw-r--r--source/ct-Bot/mcu/sensor-low.c229
-rw-r--r--source/ct-Bot/mcu/shift.c93
-rw-r--r--source/ct-Bot/mcu/srf10.c171
-rw-r--r--source/ct-Bot/mcu/timer-low.c87
-rw-r--r--source/ct-Bot/mcu/uart.c206
-rw-r--r--source/ct-Bot/mmc-vm.c534
-rw-r--r--source/ct-Bot/motor.c268
-rw-r--r--source/ct-Bot/pc/bot-2-sim.c241
-rw-r--r--source/ct-Bot/pc/delay_pc.c66
-rw-r--r--source/ct-Bot/pc/display_pc.c175
-rw-r--r--source/ct-Bot/pc/ir-rc5_pc.c54
-rw-r--r--source/ct-Bot/pc/led_pc.c72
-rw-r--r--source/ct-Bot/pc/mini-fat.c65
-rw-r--r--source/ct-Bot/pc/mmc-emu_pc.c200
-rw-r--r--source/ct-Bot/pc/motor-low_pc.c81
-rw-r--r--source/ct-Bot/pc/mouse_pc.c87
-rw-r--r--source/ct-Bot/pc/sensor-low_pc.c45
-rw-r--r--source/ct-Bot/pc/tcp-server.c274
-rw-r--r--source/ct-Bot/pc/tcp.c282
-rw-r--r--source/ct-Bot/rc5.c502
-rw-r--r--source/ct-Bot/sensor.c347
-rw-r--r--source/ct-Bot/timer.c115
-rw-r--r--source/qFix/qfix.h96
-rw-r--r--source/qFix/qfixBobbyBoard.h344
-rw-r--r--source/qFix/qfixCAN128Board.h322
-rw-r--r--source/qFix/qfixI2C.h278
-rw-r--r--source/qFix/qfixI2CDefs.h21
-rw-r--r--source/qFix/qfixI2CMaster.h119
-rw-r--r--source/qFix/qfixI2CSlave.h113
-rw-r--r--source/qFix/qfixLCD.h216
-rw-r--r--source/qFix/qfixMega128Board.h323
-rw-r--r--source/qFix/qfixServoBoard4.h89
-rw-r--r--source/qFix/qfixSlaveBoard.h157
-rw-r--r--source/qFix/qfixSoccerBoard.h339
-rw-r--r--source/qFix/qfixSonar.h107
155 files changed, 23423 insertions, 0 deletions
diff --git a/source/Code/.dep/main.o.d b/source/Code/.dep/main.o.d
new file mode 100644
index 0000000..8c8d6c4
--- /dev/null
+++ b/source/Code/.dep/main.o.d
@@ -0,0 +1,24 @@
+main.o: main.c HAL/board.h \
+ /usr/lib/gcc/avr/4.1.0/../../../../avr/include/avr/io.h \
+ /usr/lib/gcc/avr/4.1.0/../../../../avr/include/avr/sfr_defs.h \
+ /usr/lib/gcc/avr/4.1.0/../../../../avr/include/inttypes.h \
+ /usr/lib/gcc/avr/4.1.0/../../../../avr/include/stdint.h \
+ /usr/lib/gcc/avr/4.1.0/../../../../avr/include/avr/iom128.h \
+ /usr/lib/gcc/avr/4.1.0/../../../../avr/include/avr/portpins.h \
+ /usr/lib/gcc/avr/4.1.0/../../../../avr/include/avr/version.h
+
+HAL/board.h:
+
+/usr/lib/gcc/avr/4.1.0/../../../../avr/include/avr/io.h:
+
+/usr/lib/gcc/avr/4.1.0/../../../../avr/include/avr/sfr_defs.h:
+
+/usr/lib/gcc/avr/4.1.0/../../../../avr/include/inttypes.h:
+
+/usr/lib/gcc/avr/4.1.0/../../../../avr/include/stdint.h:
+
+/usr/lib/gcc/avr/4.1.0/../../../../avr/include/avr/iom128.h:
+
+/usr/lib/gcc/avr/4.1.0/../../../../avr/include/avr/portpins.h:
+
+/usr/lib/gcc/avr/4.1.0/../../../../avr/include/avr/version.h:
diff --git a/source/Code/HAL/board.c b/source/Code/HAL/board.c
new file mode 100644
index 0000000..cf1bae8
--- /dev/null
+++ b/source/Code/HAL/board.c
@@ -0,0 +1,9 @@
+#include "HAL/board.h"
+
+board::board() {
+
+}
+
+board::~board() {
+
+}
diff --git a/source/Code/HAL/board.h b/source/Code/HAL/board.h
new file mode 100644
index 0000000..f0133c1
--- /dev/null
+++ b/source/Code/HAL/board.h
@@ -0,0 +1,14 @@
+#ifndef _BOARD_H
+#define _BOARD_H
+
+#include <avr/io.h>
+
+class board
+{
+private:
+public:
+ board();
+ ~board();
+};
+
+#endif
diff --git a/source/Code/genmakefile.sh b/source/Code/genmakefile.sh
new file mode 100755
index 0000000..0ea26a7
--- /dev/null
+++ b/source/Code/genmakefile.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+cat makefile | grep -v "^SRC +=" > makefile.new
+for row in $(find | grep .c$); do
+ if [ "$row" != "./main.c" ]; then
+ echo "SRC += $row" >> makefile.new
+ fi
+done
+rm makefile
+mv makefile.new makefile
+
diff --git a/source/Code/main.c b/source/Code/main.c
new file mode 100644
index 0000000..dfe265d
--- /dev/null
+++ b/source/Code/main.c
@@ -0,0 +1,10 @@
+#include "HAL/board.h"
+
+board Controllerboard;
+
+int main() {
+ Controllerboard = new board();
+
+ int i = 0;
+ return 0;
+}
diff --git a/source/Code/makefile b/source/Code/makefile
new file mode 100644
index 0000000..8c41ab9
--- /dev/null
+++ b/source/Code/makefile
@@ -0,0 +1,438 @@
+# Hey Emacs, this is a -*- makefile -*-
+#
+# WinAVR makefile written by Eric B. Weddington, Jörg Wunsch, et al.
+# Released to the Public Domain
+# Please read the make user manual!
+#
+# Additional material for this makefile was submitted by:
+# Tim Henigan
+# Peter Fleury
+# Reiner Patommel
+# Sander Pool
+# Frederik Rouleau
+# Markus Pfaff
+#
+# On command line:
+#
+# make all = Make software.
+#
+# make clean = Clean out built project files.
+#
+# make coff = Convert ELF to AVR COFF (for use with AVR Studio 3.x or VMLAB).
+#
+# make extcoff = Convert ELF to AVR Extended COFF (for use with AVR Studio
+# 4.07 or greater).
+#
+# make program = Download the hex file to the device, using avrdude. Please
+# customize the avrdude settings below first!
+#
+# make filename.s = Just compile filename.c into the assembler code only
+#
+# To rebuild project do "make clean" then "make all".
+#
+
+# mth 2004/09
+# Differences from WinAVR 20040720 sample:
+# - DEPFLAGS according to Eric Weddingtion's fix (avrfreaks/gcc-forum)
+# - F_OSC Define in CFLAGS and AFLAGS
+
+
+# MCU name
+MCU = atmega128
+
+# Main Oscillator Frequency
+# This is only used to define F_OSC in all assembler and c-sources.
+F_OSC = 16000000
+
+
+# Output format. (can be srec, ihex, binary)
+FORMAT = ihex
+
+# Target file name (without extension).
+TARGET = main
+
+
+# List C source files here. (C dependencies are automatically generated.)
+SRC = $(TARGET).c
+#SRC = $(find | grep .c$)
+
+# List Assembler source files here.
+# Make them always end in a capital .S. Files ending in a lowercase .s
+# will not be considered source files but generated files (assembler
+# output from the compiler), and will be deleted upon "make clean"!
+# Even though the DOS/Win* filesystem matches both .s and .S the same,
+# it will preserve the spelling of the filenames, and gcc itself does
+# care about how the name is spelled on its command-line.
+ASRC =
+
+
+
+# Optimization level, can be [0, 1, 2, 3, s].
+# 0 = turn off optimization. s = optimize for size.
+# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
+OPT = s
+
+# Debugging format.
+# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
+# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
+DEBUG = stabs
+#DEBUG = dwarf-2
+
+# List any extra directories to look for include files here.
+# Each directory must be seperated by a space.
+EXTRAINCDIRS =
+
+
+# Compiler flag to set the C Standard level.
+# c89 - "ANSI" C
+# gnu89 - c89 plus GCC extensions
+# c99 - ISO C99 standard (not yet fully implemented)
+# gnu99 - c99 plus GCC extensions
+CSTANDARD = -std=gnu99
+
+# Place -D or -U options here
+CDEFS =
+
+# Place -I options here
+CINCS =
+
+
+# Compiler flags.
+# -g*: generate debugging information
+# -O*: optimization level
+# -f...: tuning, see GCC manual and avr-libc documentation
+# -Wall...: warning level
+# -Wa,...: tell GCC to pass this to the assembler.
+# -adhlns...: create assembler listing
+CFLAGS = -g$(DEBUG)
+CFLAGS += $(CDEFS) $(CINCS)
+CFLAGS += -O$(OPT)
+CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
+CFLAGS += -Wall -Wstrict-prototypes
+CFLAGS += -Wa,-adhlns=$(<:.c=.lst)
+CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
+CFLAGS += $(CSTANDARD)
+CFLAGS += -DF_OSC=$(F_OSC)
+
+
+
+# Assembler flags.
+# -Wa,...: tell GCC to pass this to the assembler.
+# -ahlms: create listing
+# -gstabs: have the assembler create line number information; note that
+# for use in COFF files, additional information about filenames
+# and function names needs to be present in the assembler source
+# files -- see avr-libc docs [FIXME: not yet described there]
+ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
+ASFLAGS += -DF_OSC=$(F_OSC)
+
+
+#Additional libraries.
+
+# Minimalistic printf version
+PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
+
+# Floating point printf version (requires MATH_LIB = -lm below)
+PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
+
+PRINTF_LIB =
+
+# Minimalistic scanf version
+SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
+
+# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
+SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
+
+SCANF_LIB =
+
+MATH_LIB = -lm
+
+# External memory options
+
+# 64 KB of external RAM, starting after internal RAM (ATmega128!),
+# used for variables (.data/.bss) and heap (malloc()).
+#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
+
+# 64 KB of external RAM, starting after internal RAM (ATmega128!),
+# only used for heap (malloc()).
+#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff
+
+EXTMEMOPTS =
+
+# Linker flags.
+# -Wl,...: tell GCC to pass this to linker.
+# -Map: create map file
+# --cref: add cross reference to map file
+LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
+LDFLAGS += $(EXTMEMOPTS)
+LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
+
+
+
+
+# Programming support using avrdude. Settings and variables.
+
+# Programming hardware: alf avr910 avrisp bascom bsd
+# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
+#
+# Type: avrdude -c ?
+# to get a full listing.
+#
+AVRDUDE_PROGRAMMER = stk200
+
+# com1 = serial port. Use lpt1 to connect to parallel port.
+AVRDUDE_PORT = /dev/parport0 # programmer connected to serial device
+
+AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
+#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
+
+
+# Uncomment the following if you want avrdude's erase cycle counter.
+# Note that this counter needs to be initialized first using -Yn,
+# see avrdude manual.
+#AVRDUDE_ERASE_COUNTER = -y
+
+# Uncomment the following if you do /not/ wish a verification to be
+# performed after programming the device.
+#AVRDUDE_NO_VERIFY = -V
+
+# Increase verbosity level. Please use this when submitting bug
+# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
+# to submit bug reports.
+#AVRDUDE_VERBOSE = -v -v
+
+AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
+AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
+AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
+AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
+
+
+
+# ---------------------------------------------------------------------------
+
+# Define directories, if needed.
+DIRAVR = c:/winavr
+DIRAVRBIN = $(DIRAVR)/bin
+DIRAVRUTILS = $(DIRAVR)/utils/bin
+DIRINC = .
+DIRLIB = $(DIRAVR)/avr/lib
+
+
+# Define programs and commands.
+SHELL = sh
+CC = avr-g++
+OBJCOPY = avr-objcopy
+OBJDUMP = avr-objdump
+SIZE = avr-size
+NM = avr-nm
+AVRDUDE = avrdude
+REMOVE = rm -f
+COPY = cp
+
+
+
+
+# Define Messages
+# English
+MSG_ERRORS_NONE = Errors: none
+MSG_BEGIN = -------- begin --------
+MSG_END = -------- end --------
+MSG_SIZE_BEFORE = Size before:
+MSG_SIZE_AFTER = Size after:
+MSG_COFF = Converting to AVR COFF:
+MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
+MSG_FLASH = Creating load file for Flash:
+MSG_EEPROM = Creating load file for EEPROM:
+MSG_EXTENDED_LISTING = Creating Extended Listing:
+MSG_SYMBOL_TABLE = Creating Symbol Table:
+MSG_LINKING = Linking:
+MSG_COMPILING = Compiling:
+MSG_ASSEMBLING = Assembling:
+MSG_CLEANING = Cleaning project:
+
+
+
+
+# Define all object files.
+OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
+
+# Define all listing files.
+LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
+
+
+# Compiler flags to generate dependency files.
+### GENDEPFLAGS = -Wp,-M,-MP,-MT,$(*F).o,-MF,.dep/$(@F).d
+GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d
+
+# Combine all necessary flags and optional flags.
+# Add target processor to flags.
+ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
+ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
+
+
+
+
+
+# Default target.
+all: begin gccversion sizebefore build sizeafter finished end
+
+build: elf hex eep lss sym
+
+elf: $(TARGET).elf
+hex: $(TARGET).hex
+eep: $(TARGET).eep
+lss: $(TARGET).lss
+sym: $(TARGET).sym
+
+
+
+# Eye candy.
+# AVR Studio 3.x does not check make's exit code but relies on
+# the following magic strings to be generated by the compile job.
+begin:
+ @echo
+ @echo $(MSG_BEGIN)
+
+finished:
+ @echo $(MSG_ERRORS_NONE)
+
+end:
+ @echo $(MSG_END)
+ @echo
+
+
+# Display size of file.
+HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
+ELFSIZE = $(SIZE) -A $(TARGET).elf
+sizebefore:
+ @if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi
+
+sizeafter:
+ @if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
+
+
+
+# Display compiler version information.
+gccversion :
+ @$(CC) --version
+
+
+
+# Program the device.
+program: $(TARGET).hex $(TARGET).eep
+ $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
+
+
+
+
+# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
+COFFCONVERT=$(OBJCOPY) --debugging \
+--change-section-address .data-0x800000 \
+--change-section-address .bss-0x800000 \
+--change-section-address .noinit-0x800000 \
+--change-section-address .eeprom-0x810000
+
+
+coff: $(TARGET).elf
+ @echo
+ @echo $(MSG_COFF) $(TARGET).cof
+ $(COFFCONVERT) -O coff-avr $< $(TARGET).cof
+
+
+extcoff: $(TARGET).elf
+ @echo
+ @echo $(MSG_EXTENDED_COFF) $(TARGET).cof
+ $(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
+
+
+
+# Create final output files (.hex, .eep) from ELF output file.
+%.hex: %.elf
+ @echo
+ @echo $(MSG_FLASH) $@
+ $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
+
+%.eep: %.elf
+ @echo
+ @echo $(MSG_EEPROM) $@
+ -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
+ --change-section-lma .eeprom=0 -O $(FORMAT) $< $@
+
+# Create extended listing file from ELF output file.
+%.lss: %.elf
+ @echo
+ @echo $(MSG_EXTENDED_LISTING) $@
+ $(OBJDUMP) -h -S $< > $@
+
+# Create a symbol table from ELF output file.
+%.sym: %.elf
+ @echo
+ @echo $(MSG_SYMBOL_TABLE) $@
+ $(NM) -n $< > $@
+
+
+
+# Link: create ELF output file from object files.
+.SECONDARY : $(TARGET).elf
+.PRECIOUS : $(OBJ)
+%.elf: $(OBJ)
+ @echo
+ @echo $(MSG_LINKING) $@
+ $(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
+
+
+# Compile: create object files from C source files.
+%.o : %.c
+ @echo
+ @echo $(MSG_COMPILING) $<
+ $(CC) -c $(ALL_CFLAGS) $< -o $@
+
+
+# Compile: create assembler files from C source files.
+%.s : %.c
+ $(CC) -S $(ALL_CFLAGS) $< -o $@
+
+
+# Assemble: create object files from assembler source files.
+%.o : %.S
+ @echo
+ @echo $(MSG_ASSEMBLING) $<
+ $(CC) -c $(ALL_ASFLAGS) $< -o $@
+
+
+
+# Target: clean project.
+clean: begin clean_list finished end
+
+clean_list :
+ @echo
+ @echo $(MSG_CLEANING)
+ $(REMOVE) $(TARGET).hex
+ $(REMOVE) $(TARGET).eep
+ $(REMOVE) $(TARGET).obj
+ $(REMOVE) $(TARGET).cof
+ $(REMOVE) $(TARGET).elf
+ $(REMOVE) $(TARGET).map
+ $(REMOVE) $(TARGET).obj
+ $(REMOVE) $(TARGET).a90
+ $(REMOVE) $(TARGET).sym
+ $(REMOVE) $(TARGET).lnk
+ $(REMOVE) $(TARGET).lss
+ $(REMOVE) $(OBJ)
+ $(REMOVE) $(LST)
+ $(REMOVE) $(SRC:.c=.s)
+ $(REMOVE) $(SRC:.c=.d)
+ $(REMOVE) .dep/*
+
+
+
+# Include the dependency files.
+-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
+
+
+# Listing of phony targets.
+.PHONY : all begin finish end sizebefore sizeafter gccversion \
+build elf hex eep lss sym coff extcoff \
+clean clean_list program
+
+SRC += ./HAL/board.c
diff --git a/source/ct-Bot/.cdtbuild b/source/ct-Bot/.cdtbuild
new file mode 100644
index 0000000..850ac3f
--- /dev/null
+++ b/source/ct-Bot/.cdtbuild
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?fileVersion 3.0.0?>
+
+<ManagedProjectBuildInfo>
+<project id="ct-Bot.cdt.managedbuild.target.gnu.exe.449611534" name="Executable (Gnu)" projectType="cdt.managedbuild.target.gnu.exe">
+<configuration artifactExtension="exe" artifactName="ct-Bot" cleanCommand="rm -rf" description="Windows mit Debug-Code" errorParsers="org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GASErrorParser" id="cdt.managedbuild.config.gnu.exe.debug.1077176217" name="Debug-W32" parent="cdt.managedbuild.config.gnu.exe.debug">
+<toolChain id="cdt.managedbuild.toolchain.gnu.exe.debug.1011694867" name="GCC Tool Chain" superClass="cdt.managedbuild.toolchain.gnu.exe.debug">
+<builder command="mingw32-make" id="cdt.managedbuild.target.gnu.builder.exe.debug.1690147207" name="Gnu Make.Debug" superClass="cdt.managedbuild.target.gnu.builder.exe.debug"/>
+<tool command="gcc" id="cdt.managedbuild.tool.gnu.c.compiler.exe.debug.629250704" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.debug">
+<option id="gnu.c.compiler.option.include.paths.387475860" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
+<listOptionValue builtIn="false" value="&quot;${ProjDirPath}&quot;"/>
+<listOptionValue builtIn="false" value="&quot;${ProjDirPath}/include&quot;"/>
+<listOptionValue builtIn="false" value="&quot;C:\Programme\MinGW\include&quot;"/>
+<listOptionValue builtIn="false" value="&quot;C:\Programme\pthreads\pthreads.2&quot;"/>
+</option>
+<option id="gnu.c.compiler.option.preprocessor.def.symbols.1823712582" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
+<listOptionValue builtIn="false" value="PC"/>
+<listOptionValue builtIn="false" value="WIN32"/>
+</option>
+<option id="gnu.c.compiler.option.misc.other.1772115072" superClass="gnu.c.compiler.option.misc.other" value="-c -fmessage-length=0 -Wstrict-prototypes" valueType="string"/>
+</tool>
+<tool command="g++" id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.919152894" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug"/>
+<tool command="gcc" id="cdt.managedbuild.tool.gnu.c.linker.exe.debug.1189819022" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.debug">
+<option id="gnu.c.link.option.libs.1949526381" superClass="gnu.c.link.option.libs" valueType="libs">
+<listOptionValue builtIn="false" value="wsock32"/>
+<listOptionValue builtIn="false" value="m"/>
+<listOptionValue builtIn="false" value="pthreadGC2"/>
+</option>
+<option id="gnu.c.link.option.paths.142594843" superClass="gnu.c.link.option.paths" valueType="stringList">
+<listOptionValue builtIn="false" value="&quot;C:\Programme\pthreads\Pre-built.2\lib&quot;"/>
+<listOptionValue builtIn="false" value="&quot;C:\Programme\MinGW\lib&quot;"/>
+</option>
+<option id="gnu.c.link.option.noshared.1812776571" superClass="gnu.c.link.option.noshared" value="true" valueType="boolean"/>
+</tool>
+<tool command="g++" id="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug.1957316739" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug"/>
+<tool command="as" id="cdt.managedbuild.tool.gnu.assembler.exe.debug.149224953" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.debug"/>
+<macros/>
+</toolChain>
+</configuration>
+<configuration artifactName="ct-Bot" cleanCommand="rm -rf" description="" errorParsers="org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GASErrorParser" id="cdt.managedbuild.config.gnu.exe.release.1181183675" name="Release" parent="cdt.managedbuild.config.gnu.exe.release">
+<toolChain id="cdt.managedbuild.toolchain.gnu.exe.release.510588697" name="GCC Tool Chain" superClass="cdt.managedbuild.toolchain.gnu.exe.release">
+<tool id="cdt.managedbuild.tool.gnu.c.compiler.exe.release.1146417472" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.release"/>
+<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.75280107" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.release"/>
+<tool id="cdt.managedbuild.tool.gnu.c.linker.exe.release.1065963860" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.release"/>
+<tool id="cdt.managedbuild.tool.gnu.cpp.linker.exe.release.1913499732" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.release"/>
+<tool id="cdt.managedbuild.tool.gnu.assembler.exe.release.56645534" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.release"/>
+<macros/>
+</toolChain>
+</configuration>
+<configuration artifactExtension="elf" artifactName="ct-Bot" cleanCommand="rm -rf" description="Linux mit Debug-Code" errorParsers="org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GASErrorParser" id="cdt.managedbuild.config.gnu.exe.debug.2039935845" name="Debug-Linux" parent="cdt.managedbuild.config.gnu.exe.debug">
+<toolChain id="cdt.managedbuild.toolchain.gnu.exe.debug.699734591" name="GCC Tool Chain" superClass="cdt.managedbuild.toolchain.gnu.exe.debug">
+<builder command="make" id="cdt.managedbuild.target.gnu.builder.exe.debug.1049987635" name="Gnu Make" superClass="cdt.managedbuild.target.gnu.builder.exe.debug"/>
+<tool command="gcc" id="cdt.managedbuild.tool.gnu.c.compiler.exe.debug.1730575762" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.debug">
+<option id="gnu.c.compiler.option.include.paths.540485352" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
+<listOptionValue builtIn="false" value="${ProjDirPath}"/>
+<listOptionValue builtIn="false" value="${ProjDirPath}/include"/>
+<listOptionValue builtIn="false" value="/usr/include"/>
+</option>
+<option id="gnu.c.compiler.option.preprocessor.def.symbols.934712041" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
+<listOptionValue builtIn="false" value="PC"/>
+</option>
+<option id="gnu.c.compiler.option.misc.other.185426673" superClass="gnu.c.compiler.option.misc.other" value="-c -fmessage-length=0 -Wstrict-prototypes" valueType="string"/>
+</tool>
+<tool command="g++" id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.949610982" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug"/>
+<tool command="gcc" id="cdt.managedbuild.tool.gnu.c.linker.exe.debug.1315268416" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.debug">
+<option id="gnu.c.link.option.libs.369911061" name="Libraries (-l)" superClass="gnu.c.link.option.libs" valueType="libs">
+<listOptionValue builtIn="false" value="pthread"/>
+<listOptionValue builtIn="false" value="m"/>
+</option>
+<option id="gnu.c.link.option.paths.551816040" name="Library search path (-L)" superClass="gnu.c.link.option.paths" valueType="stringList">
+<listOptionValue builtIn="false" value="/usr/lib"/>
+</option>
+<option id="gnu.c.link.option.noshared.1657974289" name="No shared libraries (-static)" superClass="gnu.c.link.option.noshared" value="false" valueType="boolean"/>
+</tool>
+<tool command="g++" id="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug.1840155456" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug"/>
+<tool command="as" id="cdt.managedbuild.tool.gnu.assembler.exe.debug.1863865265" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.debug"/>
+<macros/>
+</toolChain>
+</configuration>
+<configuration artifactExtension="elf" artifactName="ct-Bot" cleanCommand="rm -rf" description="Mikrocontroller mit Debug-Code" errorParsers="org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GASErrorParser" id="cdt.managedbuild.config.gnu.exe.debug.1197043799" name="Debug-MCU-Linux" parent="cdt.managedbuild.config.gnu.exe.debug" postbuildStep="avr-objcopy -O ihex -R .eeprom ct-Bot.elf ct-Bot.hex; avr-objcopy -j .eeprom --set-section-flags=.eeprom=&quot;alloc,load&quot; --change-section-lma .eeprom=0 -O ihex ct-Bot.elf ct-Bot.eep">
+<toolChain id="cdt.managedbuild.toolchain.gnu.exe.debug.1344160083" name="GCC Tool Chain" superClass="cdt.managedbuild.toolchain.gnu.exe.debug">
+<builder command="make" id="cdt.managedbuild.target.gnu.builder.exe.debug.865699592" name="Gnu Make" superClass="cdt.managedbuild.target.gnu.builder.exe.debug"/>
+<tool command="avr-gcc" id="cdt.managedbuild.tool.gnu.c.compiler.exe.debug.1998007787" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.debug">
+<option id="gnu.c.compiler.option.include.paths.796809135" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
+<listOptionValue builtIn="false" value="/usr/local/avr/include"/>
+<listOptionValue builtIn="false" value="${ProjDirPath}/include"/>
+<listOptionValue builtIn="false" value="${ProjDirPath}"/>
+</option>
+<option id="gnu.c.compiler.option.preprocessor.def.symbols.258987088" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
+<listOptionValue builtIn="false" value="MCU"/>
+</option>
+<option id="gnu.c.compiler.option.misc.other.1122958060" superClass="gnu.c.compiler.option.misc.other" value="-c -fmessage-length=0 -mmcu=atmega32 -Wstrict-prototypes" valueType="string"/>
+<option id="gnu.c.compiler.option.debugging.gprof.1275190243" superClass="gnu.c.compiler.option.debugging.gprof" value="false" valueType="boolean"/>
+<option id="gnu.c.compiler.option.debugging.prof.1974870563" superClass="gnu.c.compiler.option.debugging.prof" value="false" valueType="boolean"/>
+<option id="gnu.c.compiler.option.optimization.flags.780063591" superClass="gnu.c.compiler.option.optimization.flags" value="-Os" valueType="string"/>
+</tool>
+<tool command="g++" id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.565798556" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug"/>
+<tool command="avr-gcc" id="cdt.managedbuild.tool.gnu.c.linker.exe.debug.802239009" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.debug">
+<option id="gnu.c.link.option.libs.836351171" name="Libraries (-l)" superClass="gnu.c.link.option.libs" valueType="libs">
+<listOptionValue builtIn="false" value="m"/>
+</option>
+<option id="gnu.c.link.option.paths.972012367" name="Library search path (-L)" superClass="gnu.c.link.option.paths" valueType="stringList">
+<listOptionValue builtIn="false" value="/usr/local/avr"/>
+</option>
+<option id="gnu.c.link.option.noshared.1381459017" name="No shared libraries (-static)" superClass="gnu.c.link.option.noshared" value="false" valueType="boolean"/>
+<option id="gnu.c.link.option.ldflags.174201475" superClass="gnu.c.link.option.ldflags" value="-mmcu=atmega32" valueType="string"/>
+</tool>
+<tool command="g++" id="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug.1899644885" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug"/>
+<tool command="as" id="cdt.managedbuild.tool.gnu.assembler.exe.debug.1825020912" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.debug"/>
+<macros/>
+</toolChain>
+</configuration>
+<configuration artifactExtension="elf" artifactName="ct-Bot" cleanCommand="rm -rf" description="Mikrocontroller mit Debug-Code" errorParsers="org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GASErrorParser" id="cdt.managedbuild.config.gnu.exe.debug.1150677647" name="Debug-MCU-W32" parent="cdt.managedbuild.config.gnu.exe.debug" postbuildStep="avr-objcopy -O ihex -R .eeprom ct-Bot.elf ct-Bot.hex; avr-objcopy -j .eeprom --set-section-flags=.eeprom=&quot;alloc,load&quot; --change-section-lma .eeprom=0 -O ihex ct-Bot.elf ct-Bot.eep">
+<toolChain id="cdt.managedbuild.toolchain.gnu.exe.debug.84194754" name="GCC Tool Chain" superClass="cdt.managedbuild.toolchain.gnu.exe.debug">
+<builder command="make" id="cdt.managedbuild.target.gnu.builder.exe.debug.239679071" name="Gnu Make" superClass="cdt.managedbuild.target.gnu.builder.exe.debug"/>
+<tool command="avr-gcc" id="cdt.managedbuild.tool.gnu.c.compiler.exe.debug.113274235" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.debug">
+<option id="gnu.c.compiler.option.include.paths.818995866" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
+<listOptionValue builtIn="false" value="&quot;${ProjDirPath}&quot;"/>
+<listOptionValue builtIn="false" value="&quot;${ProjDirPath}/include&quot;"/>
+</option>
+<option id="gnu.c.compiler.option.preprocessor.def.symbols.736140060" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
+<listOptionValue builtIn="false" value="MCU"/>
+</option>
+<option id="gnu.c.compiler.option.misc.other.462981231" name="Other flags" superClass="gnu.c.compiler.option.misc.other" value="-c -fmessage-length=0 -mmcu=atmega32 -Wstrict-prototypes" valueType="string"/>
+<option id="gnu.c.compiler.option.optimization.flags.1587419901" superClass="gnu.c.compiler.option.optimization.flags" value="-Os" valueType="string"/>
+</tool>
+<tool command="g++" id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.1457522364" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug"/>
+<tool command="avr-gcc" id="cdt.managedbuild.tool.gnu.c.linker.exe.debug.1422052481" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.debug">
+<option id="gnu.c.link.option.libs.1944124942" name="Libraries (-l)" superClass="gnu.c.link.option.libs" valueType="libs">
+<listOptionValue builtIn="false" value="m"/>
+</option>
+<option id="gnu.c.link.option.paths.1035619079" name="Library search path (-L)" superClass="gnu.c.link.option.paths" valueType="stringList">
+<listOptionValue builtIn="false" value="&quot;C:\Programme\WinAVR\lib&quot;"/>
+</option>
+<option id="gnu.c.link.option.noshared.456282519" name="No shared libraries (-static)" superClass="gnu.c.link.option.noshared" value="false" valueType="boolean"/>
+<option id="gnu.c.link.option.ldflags.918822459" name="Linker flags" superClass="gnu.c.link.option.ldflags" value="-mmcu=atmega32" valueType="string"/>
+</tool>
+<tool command="g++" id="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug.1073017226" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug"/>
+<tool command="as" id="cdt.managedbuild.tool.gnu.assembler.exe.debug.212943627" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.debug"/>
+<macros/>
+</toolChain>
+</configuration>
+<macros/>
+</project>
+</ManagedProjectBuildInfo>
diff --git a/source/ct-Bot/.cdtproject b/source/ct-Bot/.cdtproject
new file mode 100644
index 0000000..7c4f87f
--- /dev/null
+++ b/source/ct-Bot/.cdtproject
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse-cdt version="2.0"?>
+
+<cdtproject id="org.eclipse.cdt.managedbuilder.core.managedMake">
+<extension point="org.eclipse.cdt.core.ScannerInfoProvider" id="org.eclipse.cdt.managedbuilder.core.ManagedBuildManager"/>
+<extension point="org.eclipse.cdt.core.ScannerInfoProvider" id="org.eclipse.cdt.managedbuilder.core.ManagedBuildManager"/>
+<extension point="org.eclipse.cdt.core.BinaryParser" id="org.eclipse.cdt.core.ELF"/>
+<extension point="org.eclipse.cdt.core.BinaryParser" id="org.eclipse.cdt.core.PE"/>
+<extension point="org.eclipse.cdt.core.BinaryParser" id="org.eclipse.cdt.core.GNU_ELF">
+<attribute key="addr2line" value="addr2line"/>
+<attribute key="c++filt" value="c++filt"/>
+</extension>
+<extension point="org.eclipse.cdt.core.BinaryParser" id="org.eclipse.cdt.core.Cygwin_PE">
+<attribute key="addr2line" value="addr2line"/>
+<attribute key="cygpath" value="cygpath"/>
+<attribute key="c++filt" value="c++filt"/>
+<attribute key="nm" value="nm"/>
+</extension>
+<extension point="org.eclipse.cdt.core.CIndexer" id="org.eclipse.cdt.core.ctagsindexer">
+<attribute key="ctagslocation" value=""/>
+<attribute key="ctagfiletype" value="ctags_internal"/>
+<attribute key="ctagsindexincludes" value="true"/>
+<attribute key="ctagfilelocation" value=""/>
+<attribute key="ctagslocationtype" value="ctags_path_default"/>
+</extension>
+<data>
+<item id="org.eclipse.cdt.core.pathentry">
+<pathentry kind="src" path=""/>
+<pathentry kind="out" path=""/>
+<pathentry kind="con" path="org.eclipse.cdt.managedbuilder.MANAGED_CONTAINER"/>
+</item>
+</data>
+</cdtproject>
diff --git a/source/ct-Bot/.cvsignore b/source/ct-Bot/.cvsignore
new file mode 100644
index 0000000..46da5ed
--- /dev/null
+++ b/source/ct-Bot/.cvsignore
@@ -0,0 +1,2 @@
+.dep
+.cvsignore
diff --git a/source/ct-Bot/.project b/source/ct-Bot/.project
new file mode 100644
index 0000000..12b3846
--- /dev/null
+++ b/source/ct-Bot/.project
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>ct-Bot</name>
+ <comment></comment>
+ <projects>
+ <project>ct-Sim</project>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.cdt.core.cnature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+ </natures>
+</projectDescription>
diff --git a/source/ct-Bot/.settings/org.eclipse.cdt.managedbuilder.core.prefs b/source/ct-Bot/.settings/org.eclipse.cdt.managedbuilder.core.prefs
new file mode 100644
index 0000000..ebd7dbd
--- /dev/null
+++ b/source/ct-Bot/.settings/org.eclipse.cdt.managedbuilder.core.prefs
@@ -0,0 +1,18 @@
+#Fri Apr 28 20:32:38 CEST 2006
+eclipse.preferences.version=1
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1077176217=<?xml version\="1.0" encoding\="UTF-8"?>\n<environment>\n<variable name\="CPATH" operation\="remove"/>\n<variable name\="C_INCLUDE_PATH" operation\="remove"/>\n</environment>\n
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1150677647=<?xml version\="1.0" encoding\="UTF-8"?>\n<environment>\n<variable name\="CPATH" operation\="remove"/>\n<variable name\="C_INCLUDE_PATH" operation\="remove"/>\n</environment>\n
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1197043799=<?xml version\="1.0" encoding\="UTF-8"?>\n<environment>\n<variable name\="CPATH" operation\="remove"/>\n<variable name\="C_INCLUDE_PATH" operation\="remove"/>\n</environment>\n
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.2039935845=<?xml version\="1.0" encoding\="UTF-8"?>\n<environment>\n<variable name\="CPATH" operation\="remove"/>\n<variable name\="C_INCLUDE_PATH" operation\="remove"/>\n</environment>\n
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1181183675=<?xml version\="1.0" encoding\="UTF-8"?>\r\n<environment>\r\n<variable name\="CPATH" operation\="remove"/>\r\n<variable name\="C_INCLUDE_PATH" operation\="remove"/>\r\n</environment>\r\n
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.debug.1077176217=<?xml version\="1.0" encoding\="UTF-8"?>\n<environment>\n<variable name\="LIBRARY_PATH" operation\="remove"/>\n</environment>\n
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.debug.1150677647=<?xml version\="1.0" encoding\="UTF-8"?>\n<environment>\n<variable name\="LIBRARY_PATH" operation\="remove"/>\n</environment>\n
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.debug.1197043799=<?xml version\="1.0" encoding\="UTF-8"?>\n<environment>\n<variable name\="LIBRARY_PATH" operation\="remove"/>\n</environment>\n
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.debug.2039935845=<?xml version\="1.0" encoding\="UTF-8"?>\n<environment>\n<variable name\="LIBRARY_PATH" operation\="remove"/>\n</environment>\n
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1181183675=<?xml version\="1.0" encoding\="UTF-8"?>\r\n<environment>\r\n<variable name\="LIBRARY_PATH" operation\="remove"/>\r\n</environment>\r\n
+environment/project=<?xml version\="1.0" encoding\="UTF-8"?>\n<environment>\n<variable delimiter\="/" name\="${ProjDirPath}" operation\="replace" value\="C\:\\Dokumente und Einstellungen\\pek\\Eigene Dateien\\ctSim_2006\\workspace\\ct-Bot"/>\n</environment>\n
+environment/project/cdt.managedbuild.config.gnu.exe.debug.1077176217=<?xml version\="1.0" encoding\="UTF-8"?>\r\n<environment/>\r\n
+environment/project/cdt.managedbuild.config.gnu.exe.debug.1150677647=<?xml version\="1.0" encoding\="UTF-8"?>\r\n<environment/>\r\n
+environment/project/cdt.managedbuild.config.gnu.exe.debug.1197043799=<?xml version\="1.0" encoding\="UTF-8"?>\n<environment>\n<variable name\="PATH" operation\="append" value\="\:/usr/local/avr/bin"/>\n</environment>\n
+environment/project/cdt.managedbuild.config.gnu.exe.debug.2039935845=<?xml version\="1.0" encoding\="UTF-8"?>\n<environment/>\n
+environment/project/cdt.managedbuild.config.gnu.exe.release.1181183675=<?xml version\="1.0" encoding\="UTF-8"?>\r\n<environment/>\r\n
diff --git a/source/ct-Bot/.settings/org.eclipse.core.runtime.prefs b/source/ct-Bot/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..59ac141
--- /dev/null
+++ b/source/ct-Bot/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,5 @@
+#Mon Jan 15 12:17:03 CET 2007
+content-types/enabled=true
+content-types/org.eclipse.cdt.core.cHeader/file-extensions=h
+content-types/org.eclipse.cdt.core.cSource/file-extensions=c,S
+eclipse.preferences.version=1
diff --git a/source/ct-Bot/Changelog.txt b/source/ct-Bot/Changelog.txt
new file mode 100644
index 0000000..55b50f7
--- /dev/null
+++ b/source/ct-Bot/Changelog.txt
@@ -0,0 +1,447 @@
+CHANGELOG fuer c't-Bot
+======================
+2007-01-15 Timo Sandmann [mail@timosandmann.de]: Mini-Bugfix: In behaviour_remotecall.c war versehentlich eine Schleife verschwunden
+
+2007-01-15 Benjamin Benz [bbe@heise.de]: Code ins Public-CVS eingespielt. Das betrifft alle Log-Eintraege ab dem (2006-11-07)
+
+2007-01-15 Benjamin Benz [bbe@heise.de]: Testrukturen und Log-ausgaben entfernt
+
+2007-01-15 Timo Sandmann [mail@timosandmann.de]: Map verwendet nun entweder VM (MMC oder PC) oder MMC/MCU oder PC. 2 warnings in log.c entfernt.
+
+2007-01-15 Timo Sandmann [mail@timosandmann.de]: Init-Fehler in mmc-vm.c im Zusammenhang mit fopen() behoben. Mini-VM-Statistik fuer MCU hinzugefuegt.
+
+2007-01-14 Timo Sandmann [mail@timosandmann.de]: Noch ein paar kleinere Verbesserungen & Bugfixes bei den Remotecalls vorgenommen, kein Umordnen kritischer Codebloecke durch den Compiler mehr
+
+2007-01-14 Benjamin Benz [bbe@heise.de]: Doku fuer Remote-calls & Remote-call-Eintraege vervollstaendigt
+
+2007-01-14 Benjamin Benz [bbe@heise.de]: Remote-calls benachrichtigen jetzt den Caller wenn sie fertig sind
+
+2007-01-13 Benjamin Benz [bbe@heise.de]: Remote-calls lassen sich nun auch aus der ferne aufrufen
+
+2007-01-13 Benjamin Benz [bbe@heise.de]: Parameterlaengen in die remeote_call-Datenstruktur uebernommen und dafuer aus bot_remote_call den parameter entfernt
+
+2007-01-12 Benjamin Benz [bbe@heise.de]: Bot kann nun eine Liste der verfuegbaren Remote-Calls an den PC uebertragen
+
+2007-01-12 Timo Sandmann [mail@timosandmann.de]: Remotecalls: Kommentare ergaenzt und neuen Datentyp einfefuert, der strict-aliasing beachtet.
+
+2007-01-12 Benjamin Benz [bbe@heise.de]: Parameterreihenfolge von bot_goto angepasst
+
+2007-01-12 Timo Sandmann [mail@timosandmann.de]: Remotecalls um Parameteruebergabe erweitert
+
+2007-01-12 Benjamin Benz [bbe@heise.de]: Ueberlauf in drive_distance beseitigt
+
+2007-01-12 Timo Sandmann [mail@timosandmann.de]: FAT16-Dateien auf MMC koennen nun laengere Dateinamen haben und wir speichern ihre Groesse im ersten Sektor. Die Dateigroesse ist per mmc_get_filesize() auslesbar.
+
+2007-01-09 Benjamin Benz [bbe@heise.de]: Remotecall-Behaviours erweitert
+
+2007-01-09 Benjamin Benz [bbe@heise.de]: Bugfix in map.c
+
+2007-01-08 Benjamin Benz [bbe@heise.de]: Nach einem Vorschlag von Achiem: Die groesse der benutzten Karte ist nun fuer andere Funktionen sichtbar, sofern in map.h SHRINK_MAP_ONLINE gesetzt ist. Wenn nicht steht in den "Variablen" die maximale Kartengroesse
+
+2007-01-08 Benjamin Benz [bbe@heise.de]: Nach einem Vorschlag von Frank Menzel die Prioritaeten von Bot_turn und bot_gotoxy geaendert
+
+2007-01-07 Timo Sandmann [mail@timosandmann.de]: MMC-Doku erweitert
+
+2007-01-05 Benjamin Benz [bbe@heise.de]: Die PC-Version des Codes kann nun mit dem Schalter "-c" leere Dateien erstellen, die spaeter der mini-fat-Treiber auf dem MCU findet
+
+2007-01-02 Timo Sandmann [mail@timosandmann.de]: Funktion zum Leeren einer FAT16-Datei auf MMC hinzugefuegt
+
+2007-01-01 Timo Sandmann [mail@timosandmann.de]: VM um Statistik-Auswertung erweitert
+
+2006-12-29 Timo Sandmann [mail@timosandmann.de]: PC-Emulation einer MMC / SD-Card implementiert (pc/mmc-emu_pc.c)
+
+2006-12-26 Timo Sandmann [mail@timosandmann.de]: Compiler-Warnings beim Timer (MCU) beseitigt (Vielen Dank an Torsten Evers fuer die Hinweise zu strict-aliasing)
+
+2006-12-22 Benjamin Benz [bbe@heise.de]: auch der reale Bot kann nun das Remote-Display nutzen
+
+2006-12-21 Timo Sandmann [mail@timosandmann.de]: MMC-VM um eine Funktion zum Oeffnen von FAT16-Dateien ergaenzt (mmc_fopen())
+
+2006-12-19 Timo Sandmann [mail@timosandmann.de]: Distsensor-Update deaktiviert waehrend Servoaktivitaet fuer Transportfachklappe. Unnoetige volatile-Deklarationen entfernt. Ein paar #define-Abhaengigkeiten korrigiert
+
+2006-12-19 Timo Sandmann [mail@timosandmann.de]: MMC-Code um asynchrones Schreiben ergaenzt, aktivierbar in mmc-low.h
+
+2006-12-19 Benjamin Benz [bbe@heise.de]: Angefangen Remote-calls einzufuehren
+
+2006-12-19 Frank Menzel(menzelfr@gmx.de) Aenderungen der Verhaltensanzeige: 1.) sichtbaren Priobereich auf Defines in bot-local.h gelegt 2.) dynamische Verhaltensanzeige
+ via Define ermoeglicht Online-Sehen der Zustandsaenderungen, Selektion eines Verh. geht sofort durch
+
+2006-12-18 Timo Sandmann [mail@timosandmann.de]: Servoverhalten optimiert
+
+2006-12-16 Timo Sandmann [mail@timosandmann.de]: Kompatibilitaet mit einigen MMC / SD-Cards verbessert
+
+2006-12-10 Timo Sandmann [mail@timosandmann.de]: Robustheit beim MMC-Timing verbessert, kleine Bugfixes, VM erweitert
+
+2006-12-08 Benjamin Benz [bbe@heise.de]: ENA-Bugfixes, catch_pillar eingefuehrt
+
+2006-12-07 Timo Sandmann [mail@timosandmann.de]: Support fuer ATmega644 eingebaut
+
+2006-12-07 Timo Sandmann [mail@timosandmann.de]: Detailverbesserungen am MMC-Code und Tippfehler in bot_scan_behaviour() korrigiert
+
+2006-12-07 Benjamin Benz [bbe@heise.de]: MMC-Code von Timo und Benjamin gemerged
+
+2006-12-07 Benjamin Benz [bbe@heise.de]: Enable-System fuer Maus und MMC umgestellt
+
+2006-12-07 Benjamin Benz [bbe@heise.de]: UART auf 57600 Baud umgestellt
+
+2006-12-07 Benjamin Benz [bbe@heise.de]: Servo-Verhalten eingefuehrt
+
+2006-12-04 Timo Sandmann [mail@timosandmann.de]: Low-Level-Funktionen fuer MMC / SD-Card anders implementiert, 1. Version eines virtuellen Speicher-Managements fuer MMC / SD-Card eingefuehrt, MMC- / SD-Card-Code aufgeraeumt
+
+2006-12-03 Timo Sandmann [mail@timosandmann.de]: Die delay-Funktion arbeitet jetzt auch im (sehr) theoretischen Worstcase (Interrupt unterbricht Timer-Abfrage und gleichzeitiger Uebertrag an 8-Bit Grenze) korrekt
+
+2006-11-23 Timo Sandmann [mail@timosandmann.de]: Bugfix fuer gettimeofday-Problem unter Win und Map-Konvertierung nur, wenn MAP auch an ist
+
+2006-11-10 Benjamin Benz [bbe@heise.de]: Mini-fat eingefuehrt
+
+2006-11-09 Benjamin Benz [bbe@heise.de]: map.c fuer Flash-Karte vorbereitet, die 2.
+
+2006-11-08 Benjamin Benz [bbe@heise.de]: map.c fuer Flash-Karte vorbereitet
+
+2006-11-08 Benjamin Benz [bbe@heise.de]: Code fuer MMC-/SD-Karten funktioniert nun im Bit-Bang-Betrieb
+
+2006-11-07 Benjamin Benz [bbe@heise.de]: Code fuer MMC-/SD-Karten eingefuehrt
+
+2006-11-06 Benjamin Benz [bbe@heise.de]: Kartenkoordinaten auf uin16 umgestellt
+
+2006-11-06 Benjamin Benz [bbe@heise.de]: map.c kommentiert und etwas geschliffen
+
+2006-11-03 Timo Sandmann [mail@timosandmann.de]: Zwei warnings beseitigt und zwei unnoetige volatiles in bot-logik.c entfernt
+
+2006-11-03 Benjamin Benz [bbe@heise.de]: Verhalten aus bot-logik.c auf einzelfunktionen aufgeteilt und in available_behaviours Schalter zur Auswahl eingefuehrt
+
+2006-11-01 Timo Sandmann [mail@timosandmann.de]: Timer auf tickCounts [176 us] umgestellt (bevorzugt TIMER_GET_TICKCOUNT_16 oder 32 verwenden; MS_TO_TICKS() rechnet dazu ms in Ticks um)
+
+2006-11-01 Benjamin Benz [bbe@heise.de]: Karten funktionieren jetzt schon mal auf dem PC
+
+2006-10-31 Benjamin Benz [bbe@heise.de]: Bugfixes bei den define-Schaltern
+
+2006-10-31 Achim Pankalla [achim.pankalla@gmx.de]: Ergaenzung / Fehlerkorrektur bei DISPLAY_... defines in ct-bot.h
+
+2006-10-29 Timo Sandmann [mail@timosandmann.de]: Bug in command.c behoben (Code compilierte nicht ohne LOG_AVAILABLE)
+
+2006-10-26 Benjamin Benz (bbe@heise.de) Karten (nur PC) eingefuehrt, Kommunikation angepasst
+
+2006-09-12 Benjamin Benz [bbe@heise.de]: Timersteps auf 176 angepasst
+
+2006-09-12 Benjamin Benz [bbe@heise.de]: Nach einem Hinweis von Achim Pankalla 2 Warnings entfernt und eine Variable sauber initialisiert
+
+2006-09-10 Timo Sandmann [mail@timosandmann.de]: Fehler in bot_gotoxy_behaviour() korrigiert (Code kompilierte nicht ohne MEASURE_MOUSE_AVAILABLE)
+
+2006-09-04 Timo Sandmann [mail@timosandmann.de]: Heading-Berechnung bei Maus-Encoder-Kopplung korrigiert
+
+2006-09-01 Timo Sandmann [mail@timosandmann.de]: Mausueberlaufbehandlung nochmal praezisiert
+
+2006-09-01 Benjamin Benz [bbe@heise.de]: Datentyp von simultime angepasst
+
+2006-08-30 Achim Pankalla [achim.pankalla@gmx.de]: Korrektur behebt Compiler warning in ct-bot.c beim setzen von LOG_DISPLAY_AVAILABLE
+
+2006-08-29 Timo Sandmann [mail@timosandmann.de]: Berechnung von v_mou_left / right korrigiert
+
+2006-08-29 Benjamin Benz [bbe@heise.de]: Bugfix in mcu/delay.c
+
+2006-08-29 Benjamin Benz [bbe@heise.de]: bot_gotoxy nach einem Patch von Thomas Noll (nollsen@web.de) verbessert
+
+2006-08-29 Timo Sandmann [mail@timosandmann.de]: Maussensor-Ueberlauf korrigiert
+
+2006-08-28 Achim Pankalla [achim.pankalla@gmx.de]: Optimierung der LOG-Makros
+
+2006-08-25 Achim Pankalla [achim.pankalla@gmx.de]: Verhindert in sensor_abstand den Wert Null und eine Division durch Null.
+
+2006-08-24 Timo Sandmann [mail@timosandmann.de]: allgemeine Variablen fuer Speed und Odometrie eingefuehrt, v_mou_center und modifiedAngles-Bug korrigiert
+
+2006-08-04 Benjamin Benz [bbe@heise.de]: motor_low_pc.c Bugfix
+
+2006-08-16 Felix Beckwermert [felix@beckwermert.de]: sensor.c -- buf-fix (aus forum): Klammern bei dHead ergaenzt
+
+2006-08-04 Timo Sandmann [mail@timosandmann.de]: tcp.h um include fuer Macs ergaenzt
+
+2006-08-04 Benjamin Benz [bbe@heise.de]: Alle TCP-Daten werden nun auf einen Schlag uebertragen
+
+2006-07-26 Benjamin Benz [bbe@heise.de]: TestClient eingefuehrt
+
+2006-07-26 Benjamin Benz [bbe@heise.de]: Timing-estcode ueberarbeitet
+
+2006-07-26 Benjamin Benz [bbe@heise.de]: Debug-Output und debug-Befehle entfernt
+
+2006-07-24 Peter Koenig [pek@heise.de]: Text der GPL eingefuegt
+
+2006-07-20 Benjamin Benz [bbe@heise.de]: Default FB fuer Sim auf RC_HAVE_HQ_RC_UNIVERS29_334 gesetzt
+
+2006-07-20 Benjamin Benz [bbe@heise.de]: Thread-Modell grundlegend ueberarbeitet. Bot und sim nun synchron
+
+2006-07-11 Benjamin Benz (bbe@heise.de) Sensor-correction grob an ct-sim angepasst
+
+2006-07-11 Frank Menzel(menzelfr@gmx.de) Korrekturen bzgl. Logausgabe
+
+2006-07-11 Benjamin Benz (bbe@heise.de) Toggle-Bit nach einem Hinweis von Frank Menzel korrigiert
+
+2006-07-09 Benjamin Benz (bbe@heise.de) Mauskalibrierung an ct-Sim angepasst
+
+2006-07-09 Torsten Evers (tevers@onlinehome.de) Geschwindigkeitsberechnung in sensor.c nach Hinweis von Frank Menzel korrigiert
+
+2006-07-06 Torsten Evers (tevers@onlinehome.de) Diverse Verbesserungen an bot_maze()
+
+2006-07-06 Benjamin Benz (bbe@heise.de) Kennlinien nun fuer virtuelle und reale Bots!
+
+2006-07-04 Torsten Evers (tevers@onlinehome.de) Getrennte Stuetzwerte fuer Distanzermittlung DP2D12 und Bildung von Schnittwerten aus den letzten drei Messungen eingefuehrt
+
+2006-07-04 Benjamin Benz (bbe@heise.de) Timer_steps gerundet
+
+2006-07-03 Benjamin Benz (bbe@heise.de) Bugfix in ir_isr()
+
+2006-06-22 Peter Koenig (pek@heise.de) Nach Hinweis von Torsten Evers den Wert LINE_SENSE in bot-local.h auf 0x350 gesetzt, da Bot sonst die 0x323 vom rechten Startpad als Linie interpretiert
+
+2006-06-13 Torsten Evers (tevers@onlinehome.de) Anzeige des aktuell freien RAMs auf Screen 5 hinzugefuegt (nur MCU!)
+
+2006-06-12 Benjamin Benz (bbe@heise.de) Promo8-FB-Codes erweitert
+
+2006-06-12 Benjamin Benz (bbe@heise.de) Prioritaeten angepasst
+
+2006-06-08 Torsten Evers (tevers@onlinehome.de) Odometrie-Funktionen in sensor_update() integriert, bot_turn() fuer Verwendung von Odometriewerten angepasst und bot_gotoxy() eingefuehrt
+
+2006-05-23 Benjamin Benz (bbe@heise.de) Makefile ueberarbeitet
+
+2006-05-19 Benjamin Benz (bbe@heise.de) Deadlock aus command_read entfernt.
+
+2006-05-12 Torsten Evers (tevers@onlinehome.de) maus_get_squal() zur Ermittlung des SQUAL-Wertes des Maussensors hinzugefuegt
+
+2006-05-10 Ralf Loehmer (rl@loehmer.de) maus_sens_write(); MSB
+
+2006-05-10 Benjamin Benz (bbe@heise.de) UART-Baudrate-Formeln ueberarbeitet
+
+2006-05-07 Torsten Evers (tevers@onlinehome.de) Fernbedienung LifeTec LT 3607 hinzugefuegt
+
+2006-05-01 Torsten Evers (tevers@onlinehome.de) Linienfolger ueberarbeitet und eingepflegt
+
+2006-05-01 Benjamin Benz (bbe@heise.de) Speed_control komplett neu geschrieben
+
+2006-04-30 Benjamin Benz (bbe@heise.de) Wertebegrenzung fuer IR-Sensor eingefuehrt
+
+2006-04-29 Benjamin Benz (bbe@heise.de) Delay angepasst
+
+2006-04-29 Benjamin Benz (bbe@heise.de) Datentypen der Uebertragung der MouseDX/DY-Werte angepasst
+
+2006-04-29 Benjamin Benz (bbe@heise.de) Bot_simple_behaviour und Bot_simple2_behaviour vorbereitet und kommentiert
+
+2006-04-28 Benjamin Benz (bbe@heise.de) Loggen auf Konsole reaktiviert
+
+2006-04-28 Benjamin Benz (bbe@heise.de) Default Fernbedienung HQ RC Univers 29 (Code 334) eingefuehrt
+
+2006-04-28 Benjamin Benz (bbe@heise.de) Maussensor kommt nun auch mit Optimiertem Compilat klar (-Os)
+
+2006-04-27 Benjamin Benz (bbe@heise.de) UART-Empfangsroutinen entkaefert
+
+2006-04-26 Benjamin Benz (bbe@heise.de) Routinen zum simulieren (PC) von Maussensorbildern eingefuehrt
+
+2006-04-25 Benjamin Benz (bbe@heise.de) Routinen zum Auslesen von Maussensorbildern vorbereitet
+
+2006-04-20 Torsten Evers <tevers@onlinehome.de> Drehrichtungen fuer die Tasten 4,6 und 7,9 geaendert, so dass die Drehrichtung der Anordnung der Tasten auf der Fernbedienung entspricht
+
+2006-04-06 Frank Menzel(menzelfr@gmx.de) Not-Aus eingefuehrt nach PWR. Alle Verhalten werden deaktiviert und der vorheriger Zustand in der Verhaltens-Puffervariable gemerkt. Dann wird die Verhaltensanzeige Screen 2 aktiviert, wo nach Select die Verhalten wieder wie vorher eingeschaltet werden koennen.
+
+2006-04-19 Joerg Bullmann (jbc@mac10.de) RC5-Codes fuer Technisat CIP Fernbedienung
+
+2006-04-13 Benjamin Benz (bbe@heise.de) 2 Codes für Conrad-Fb wie ind er Mailingliste diskutiert geaendert
+
+2006-04-18 Ulrich Scheffler (ulrich.scheffler@web.de) Codes fuer die Fernbedienung VIVANCO UR89, TV Modus (Code089) eingepflegt
+
+2006-04-18 Torsten Evers (tevers@onlinehome.de) bot_solve_maze erkennt Startfelder
+
+2006-04-16 Torsten Evers (tevers@onlinehome.de) bot_solve_maze + Hilfsverhalten eingefuegt
+
+2006-04-16 Torsten Evers (tevers@onlinehome.de) bot_turn ueberarbeitet
+
+2006-04-16 Ulrich Scheffler (ulrich.scheffler@web.de) Kleine anpassungen an den rc5-codes
+
+2006-04-14 Carsten Giesen (info@cnau.de) TWI (I2C) Treiber und SRF10 Ansteuerung
+
+2006-04-13 Staudenmayer (andreas.staudenmayer@t-online.de) Batchdatei fuer Programmieradapter STK200 und viele baugleiche Programmer am Parallelport eingefuehrt
+
+2006-04-13 Benjamin Benz (bbe@heise.de) bot_avoid_col_behaviour veraendert, alle verhalten auf namenskonvention angepasst
+
+2006-04-13 Daniel Bachfeld (dab@heise.de) Bot-Geschwindigkeit in mm/s geaendert. regelung geht jetzt auch fuer Rueckwaertsfahrt
+
+2006-04-03 Benjamin Benz (bbe@heise.de) bot_behave() nimmt die Arbeit erst auf, wenn alle Sensoren initialisiert sind
+
+2006-04-04 Torsten Evers (tevers@onlinehome.de) bot_turn ueberarbeitet
+
+2006-04-04 Daniel Bachfeld (dab@heise.de) Motorregelung eingefuehrt
+
+2006-04-03 Benjamin Benz (bbe@heise.de) Für den simulierten Bot gilt immer die Standardfernbedienung
+
+2006-04-03 Benjamin Benz (bbe@heise.de) Unterverzeichnis Documentation eingefuehrt
+
+2006-04-03 Frank Menzel(menzelfr@gmx.de) & Carsten Giesen (info@cnau.de) Die folgenden beiden Aenderungen eingereicht:
+ Verhaltensanzeige im Screen 3 an Stelle des
+ Counters via Define DISPLAY_BEHAVIOUR_AVAILABLE. Durch die Mehrfachnutzung der Zahlentasten (1-6) bekommen diese im Screen 3 die Bedeutung der
+ Umschaltmoeglichkeit eines Verhaltens (aktiv <-> inaktiv), wobei 1 und 0 fr aktiv und inaktiv stehen.
+ Geblaettert werden kann mit der Taste RC5_CODE_VIEW und scharfgeschaltet wird via RC5_CODE_SELECT.
+ Fuer Eindeutigkeit sind Verhalten gleicher Prioritaet angepasst worden (bot_simple und slalom_behaviour).
+
+2006-03-27 Andreas Merkle (mail@blue-andi.de) Zeiger, welche als Funktionszeiger verwendet wurden, ersetzt.
+
+2006-03-31 Frank Menzel (Menzelfr@gmx.de) RC5-Signale werden nur noch mit geaendertem Toggle-Bit akzeptiert
+
+2006-03-28 Peter Koenig (pek@ctmagazin.de) Alle int in bot-logik.c/.h nach Absprache mit Christoph Grimmer in int16 bzw. int8 umgewandelt
+
+2006-03-24 Andreas Staudenmayer (andreas.staudenmayer@t-online.de) Fernbedienung VIVANCO UR89 eingefuegt
+
+2006-02-24 Fabian Recktenwald (fa.re.wal@gmx.de) Alle char-Datentypen in int8 oder uint8 umgewandelt
+
+2006-03-24 Benjamin Benz (bbe@heise.de) Bugfix rc5_bot_next_behaviour
+
+2006-03-23 Benjamin Benz (bbe@heise.de) Bugfix in bot_turn()
+
+2006-03-22 Andreas Merkle (mail@blue-andi.de) Die Funktionen in delay_pc.c mit Funktionalitaet hinterlegt.
+
+2006-03-23 Benjamin Benz (bbe@heise.de) Display-Delay auf optimierten Code angepasst, Verhaltensinitialisierung uebersichtlicher gestaltet
+
+2006-03-20 Carsten Giesen (info@cnau.de) Codes fuer die FB des MediaMPV von Hauappauge eingepflegt
+
+2006-03-19 Andreas Merkle (mail@blue-andi.de) Timer Variablen ueber Funktionen auf dem PC geschuetzt (Thread-Safe).
+
+2006-03-21 Benjamin Benz (bbe@heise.de) RC5-Mask-Definition in rc5-codes.h umgezogen
+
+2006-03-19 Lukas Jelonek (ljelonek@techfak.uni-bielefeld.de) Motoren verhalten sich nun links und rechts identisch
+
+2006-03-19 Benjamin Benz (bbe@heise.de) Der simulierte Bot nutzt nun auch den Maussensor
+
+2006-03-19 Benjamin Benz (bbe@heise.de) Der PC darf jetzt FB-Kommandos per UART an den realen Bot uebertragen
+
+2006-03-18  Michail Brzitwa (michail@brzitwa.de)    Definition und Selektierbarkeit verschiedener Fernbedienungen in rc5-codes.h
+
+2006-03-16 Peter Koenig (pek@heise.de) Kommentare korrigiert, bot_olympic_behaviour fuer Release aktiviert
+
+2006-03-15 Benjamin Benz (bbe@heise.de) Servos fuer PC-Bot eingefuehrt
+
+2006-03-11 Benjamin Benz (bbe@heise.de) Select-Taste fuer Verhalten eingefuehrt, bot_olympic_behaviour deaktiviert
+
+2006-03-08 Andreas Merkle (mail@blue-andi.de) Log-Funktionen eingefuehrt
+
+2006-03-05 Benjamin Benz (bbe@heise.de) Kommunikation Bot-PC ueberarbeitet, Anmeldung am c't-Sim
+
+2006-03-07 Christoph Grimmer (c.grimmer@futurio.de) bot_complex_behaviour in bot_olympic_behaviour umbenannt.
+
+2006-03-05 Christoph Grimmer (c.grimmer@futurio.de) Das complex_behaviour und alle zugehoerigen Funktionen so umgeschrieben, dass sie in das behaviour-framework passen. Zu bot_drive_distance und bot_turn wurden entsprechende Botschaftsfunktionen und globale Variablen angelegt. ACHTUNG: Es kommt sicherlich zu Problemen, wenn die Radencoder waehrend eines Laufs von bot_turn oder bot_drive_distance ueberlaufen!
+
+2006-03-04 Andreas Merkle (mail@blue-andi.de) Ausgaben auf das LCD-Display vereinfacht.
+
+2006-03-03 Benjamin Benz (bbe@heise.de) Routinen wie bot_goto() kann man nun mehrmals aufrufen
+
+2006-03-03 Benjamin Benz (bbe@heise.de) internes und externes CVS abgeglichen
+
+2006-03-03 Benjamin Benz (bbe@heise.de) Zustandsorientierte Regeln in das Framework eingefuegt
+
+2006-03-02 Benjamin Benz (bbe@heise.de) Remote-Display repariert
+
+2006-03-02 Benjamin Benz (bbe@heise.de) Display.c aufgeraeumt, Makefile angepasst
+
+2006-03-01 Benjamin Benz (bbe@heise.de) Kommunikation Bot-PC eingefuehrt
+
+2006-03-01 Benjamin Benz (bbe@heise.de) Routinen aus bot-2-sim.c verschoben in command.c
+
+2006-02-28 Benjamin Benz (bbe@heise.de) Uart-Kommunikation ueberarbeitet
+
+2006-02-28 Benjamin Benz (bbe@heise.de) Geschwindigkeitsvariabeln v_left und v_right eingefuehrt
+
+2006-02-28 Benjamin Benz (bbe@heise.de) Alle Anpassungen des Roboters an lokale Gegebenheiten in bot-local.h ausgelagert
+
+2006-02-28 Benjamin Benz (bbe@heise.de) TODO-Datei eingefuehrt
+
+2006-02-28 Benjamin Benz (bbe@heise.de) Es gibt jetzt (auf dem MCU) eine globale Zeit (siehe timer.h)
+
+2006-02-27 Benjamin Benz (bbe@heise.de) Bugfix bei der Uebergabe der Lichtwerte
+
+2006-02-27 Markus Hennecke (markus-hennecke@markus-hennecke.de) Auswertung der Kommandozeile, Zielhost kann als Argument uebergeben werden.
+
+2006-02-27 Benjamin Benz (bbe@heise.de) Wertebereiche der sensoren dokumentiert
+
+2006-02-27 Benjamin Benz (bbe@heise.de) Cleanup im goto-System
+
+2006-02-23 Torsten Evers (tevers@onlinehome.de) Flash-Skript um Pruefung der Fuses erweitert
+
+2006-02-23 Benjamin Benz (bbe@heise.de) doppelte LDR-Variablen entfernt
+
+2006-02-23 Benjamin Benz (bbe@heise.de) Direction-Variablen eingefuehrt, in denen die Drehrichtung auch noch steht, wenn die Speed wieder auf Null ist
+
+2006-02-23 Ansgar Esztermann (ansgar@thphy.uni-duesseldorf.de) Big Endian Unterstuetzung im Netzwerkcode
+
+2006-02-23 Markus Hennecke (markus-hennecke@markus-hennecke.de) Bessere Handhabung weiterer Zielplattformen
+
+2006-02-23 Benjamin Benz (bbe@heise.de) Motor-Drehrichtung angepasst, BORDER_DANGEROUS angepasst, BEHAVIOUR_AVAILABLE eingefuehrt
+
+2006-02-23 Benjamin Benz (bbe@heise.de) Neues Testprogramm, um Resets zu analysieren
+
+2006-02-21 Carsten Giesen (info@cnau.de) Die Variable Target_Speed wird limitiert
+
+2006-02-21 Carsten Giesen (info@cnau.de) Das Register MCUCSR wird auf Screen 4 angezeigt
+
+2006-02-21 Torsten Evers (tevers@onlinehome.de) Linux-Skritpe zum Flashen und Fusen mit avrdude eingefuegt
+
+2006-02-20 Benjamin Benz (bbe@heise.de) Und nochmal Bugfix in bot_logik.c
+
+2006-02-20 Carsten Giesen (info@cnau.de) Erweiterung um 3 zusaetzliche Screens fuer das Display
+
+2006-02-20 Benjamin Benz (bbe@heise.de) Bugfix in bot_logik.c nach einer Idee von (Fabian Recktenwald, fa.re.wal@gmx.de)
+
+2006-02-20 Benjamin Benz (bbe@heise.de) Bugfix in bot_behave()
+
+2006-02-18 Benjamin Benz (bbe@heise.de) Schoenheitskorrektur in den Maus-Routinen
+
+2006-02-19 Benjamin Benz (bbe@heise.de) RC5-Variable in sensor.h umgezogen
+
+2006-02-18 Benjamin Benz (bbe@heise.de) Watchdog sicherheitshalber deaktiviert
+
+2006-02-18 Andreas Staudenmayer (andreas.staudenmayer@t-online.de) Batch-Files zum Flashen/fusen unter Windows
+
+2006-02-18 Rolf Ebert (Rolf.Ebert@gmx.net) LCD-Ausgabe kann nun auch im Simulator erscheinen
+
+2006-02-18 Benjamin Benz (bbe@heise.de) Fuse-Bit-Dateien fuer avrdude eingefügt
+
+2006-02-17 Benjamin Benz (bbe@heise.de) Linearisierung der Distanzsensoren eingeführt
+
+2006-02-17 Benjamin Benz (bbe@heise.de) Stromsparen eingefuehrt
+
+2006-02-15 Andreas Merkle (mail@blue-andi.de) RC5-Fernbedienungscodes in eine Header-Datei ausgelagert. Fernbedienungsaktionen in einer Tabelle zusammengefasst. Dadurch sind Erweiterungen bzw. Aenderungen noch einfacher moeglich.
+
+2006-02-13 Benjamin Benz (bbe@heise.de) Bugfix im bot_goto_system()
+
+2006-02-10 Andreas Merkle (mail@blue-andi.de) Die Makros CLEAR und POSITION unter Windows mit Funktionalitaet hinterlegt.
+
+2006-02-03 Benjamin Benz (bbe@heise.de) Externes CVS mit internem überschrieben
+
+2006-02-02 Benjamin Benz (bbe@heise.de) Bugfix und Cleanup im goto_system
+
+2006-02-02 Benjamin Benz (bbe@heise.de) Maussensor angepasst
+
+2006-02-01 Benjamin Benz (bbe@heise.de) Verhalten bot_glance von Ralph Glass (ralph.glass@t-online.de) eingebaut
+
+2006-02-01 Benjamin Benz (bbe@heise.de) MCU-Code freigegeben
+
+2006-02-01 Benjamin Benz (bbe@heise.de) Verhaltensframework nochmals modifiziert. Additives Verhalten ist wieder raus.
+ speed_l-Variablen und Co aus den Datenstrukturen raus ==> spart RAM
+ goto-System deaktiviert sich nun selbsttaetig
+
+2006-02-01 Benjamin Benz (bbe@heise.de) Bugfix im Verhaltenscode. BOT_SPEED_IGNORE eingefuegt
+
+2006-02-01 Benjamin Benz (bbe@heise.de) Brake-Konstante angepasst
+
+2006-01-31 Benjamin Benz (bbe@heise.de) Kommentare aktualisiert, GPL-Infos eingebaut
+
+2006-01-31 Benjamin Benz (bbe@heise.de) Testprogramme erstellt und dabei kleine Fehler ausgebessert
+
+2006-01-30 Benjamin Benz (bbe@heise.de) Sensoren ueberarbeitet, Encoder reaktiviert
+
+2006-01-30 Benjamin Benz (bbe@heise.de) sensDistL und sensDistR initialisieren bun mit 1023 ==> keine Rotation zu Beginn mehr
+
+2006-01-28 Andreas Merkle (mail@blue-andi.de) Beim Ausfuehren von Verhalten werden Verhalten mit gleicher Prioritaet nun additiv behandelt und erst dann die Werte gesetzt. Im Verhalten bot_avoid_col wurde die Geschwindigkeitsaenderung nicht in die Verhaltenstruktur geschrieben. Dieses wurde korrigiert. Beim Anlegen einer Verhaltensstruktur wird nun ueberprueft, ob genuegend Heap-Speicher vorhanden ist.
+
+2006-01-27 Benjamin Benz (bbe@heise.de) Patch von Andreas Merkle (mail@blue-andi.de) eingebaut. Man kann Verhalten jetzt vereinfacht laden
+
+2006-01-26 Benjamin Benz (bbe@heise.de) Gesamtes Verhalten umgestellt. es gibt jetzt ein eigenes Verhaltens-Framework.
+
+2006-01-26 Benjamin Benz (bbe@heise.de) Kommentare geaendert
+
+2006-01-25 Benjamin Benz (bbe@heise.de) Status der LEDs wird nun an den Simulator uebertragen
+
+2006-01-24 Benjamin Benz (bbe@heise.de) Schreibweise des Changelogs nochmal veraendert \ No newline at end of file
diff --git a/source/ct-Bot/Documentation/TWI-Treiber.htm b/source/ct-Bot/Documentation/TWI-Treiber.htm
new file mode 100644
index 0000000..524774d
--- /dev/null
+++ b/source/ct-Bot/Documentation/TWI-Treiber.htm
@@ -0,0 +1,70 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML><HEAD><TITLE></TITLE>
+<META http-equiv=Content-Type content="text/html; charset=iso-8859-1">
+<META content="MSHTML 6.00.2900.2873" name=GENERATOR></HEAD>
+<BODY><!-- Converted from text/plain format --><FONT face=Arial
+size=2></FONT><FONT size=2>
+<P>Carsten Giesen (info@cnau.de)</P>
+<P>TWI-Treiber (I2C)</P>
+<P>Die gesammte Kommunikation mit der TWI Schnittstelle steckt in TWI_driver.c
+und TWI_driver.h.<BR>Angesprochen wird der Treiber �ber "Send_to_TWI(tx_frame)"
+daf�r sind aber ein paar Vorarbeiten n�tig.</P>
+<P>Zur Vereinfachung hier ein Beispiel am Beispiel vom SRF10:</P>
+<P><BR>char
+temp[2];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+//Array um Platz f�r die Befehle zu schaffen<BR>char
+state;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+//Platz f�r das Ergebniss der Aktion<BR>tx_type
+tx_frame[2];&nbsp;&nbsp;&nbsp;&nbsp; //Hier wird der Container geschaffen</P>
+<P></P>
+<P>state = SUCCESS;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+//Vorbelegen, da manche Aktionen nur Sinn machen, wenn state=SUCCESS</P>
+<P>//Jetzt gehts los:<BR>tx_frame[0].slave_adr = address+W; //Die Adresse des
+Ziel-Bausteins <BR>tx_frame[0].size = 2; //Wie viele Befehle (Daten) sollen
+�bertragen werden<BR>tx_frame[0].data_ptr = temp; //der Pointer f�r die
+Befehle<BR>tx_frame[0].data_ptr[0] = SRF10_COMMAND;&nbsp;&nbsp;&nbsp;&nbsp;
+//Der erste Befehl ist normaler Weise das
+Register,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+//welches Angesprochen werden soll<BR>tx_frame[0].data_ptr[1] =
+metric_unit;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+//Was soll gemacht werden (hier eine Messung in cm)<BR>tx_frame[1].slave_adr =
+OWN_ADR;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+//Damit wird dem Treiber klar gemachtm das er fertig ist.<BR>state =
+Send_to_TWI(tx_frame);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+//Und jetzt wird alles �bergeben<BR><BR>In State steht jetzt ob der Befehl
+erfolgreich war, oder nicht.<BR><BR>Wie man Daten empf�ngt, am Beispiel Register
+auslesen:</P>
+<P>uint8 srf10_read_register(unsigned char srf10_register)<BR>{<BR>char
+temp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+//Variable um Platz f�r die Befehle zu schaffen<BR>char
+value;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+//Variable um Platz f�r die Resultate zu schaffen<BR>char
+state;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+//Platz f�r das Ergebniss der Aktion<BR>tx_type
+tx_frame[3];&nbsp;&nbsp;&nbsp;&nbsp; //Hier wird der Container
+geschaffen<BR>state = SUCCESS;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+//Vorbelegen, da manche Aktionen nur Sinn machen, wenn state=SUCCESS<BR>value =
+0;<BR>tx_frame[0].slave_adr =
+address+W;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Die Adresse
+des Ziel-Bausteins<BR>tx_frame[0].size =
+1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+//Wie viele Befehle (Daten) sollen �bertragen werden<BR>tx_frame[0].data_ptr =
+&amp;temp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+//der Pointer f�r die Befehle<BR>tx_frame[0].data_ptr[0] =
+srf10_register;&nbsp;&nbsp;&nbsp;&nbsp; //Der erste Befehl ist normaler Weise
+das
+Register,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+//welches Angesprochen werden soll<BR>tx_frame[1].slave_adr =
+address+R;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+//Die Adresse des Ziel-Bausteins +R f�r lesen<BR>tx_frame[1].size =
+1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+//Wie viele Daten sollen gelesen werden<BR>tx_frame[1].data_ptr =
+&amp;value;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+//der Pointer f�r die Daten<BR>tx_frame[2].slave_adr =
+OWN_ADR;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Damit wird dem
+Treiber klar gemachtm das er fertig ist.<BR>state =
+Send_to_TWI(tx_frame);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+//Und jetzt wird alles �bergeben<BR>srf10_state = state;<BR>return
+value;<BR>}</P>
+<P>Man kann also gut sehen, das beide Aktionen, schreiben und lesen kombiniert
+werden k�nnen.</P></FONT></BODY></HTML>
diff --git a/source/ct-Bot/Documentation/mmc-vm.html b/source/ct-Bot/Documentation/mmc-vm.html
new file mode 100644
index 0000000..e7ccaf3
--- /dev/null
+++ b/source/ct-Bot/Documentation/mmc-vm.html
@@ -0,0 +1,154 @@
+<?xml version="1.0" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<meta name="description" content="Uebersicht der Speicherverwaltung mit MMC am c't-Bot" />
+<meta name="author" content="Timo Sandmann" />
+<meta name="keywords" content="c't-Bot,mmc,virtueller Speicher, fat" />
+<meta name="date" content="2007-01-06" />
+<title>c't-Bot - VM-Dokumentation</title>
+<link rel="stylesheet" type="text/css" href="style.css" />
+</head>
+<body>
+<h1>Dokumentation zur virtuellen Speicherverwaltung</h1>
+<br />
+
+<a class="menu" href="#uebersicht">Eine allgemeine &Uuml;bersicht</a><br />
+<a class="menu" href="#vm">Der virtuelle Speicher im Detail</a>
+<ul>
+ <li><a class="menu" href="#alloc">Die Speicherallokierung</a></li>
+ <li><a class="menu" href="#example">Ein kleines Beispiel</a></li>
+ <li><a class="menu" href="#mmc">Die Schnittstelle zur Hardware</a></li>
+ <li><a class="menu" href="#cache">Einige Erl&auml;uterungen zum Cache</a></li>
+</ul>
+<a class="menu" href="#fat">Der Zugriff auf ein FAT16-Dateisystem</a><br />
+<a class="menu" href="#stat">Etwas Statistik zur Leistungsbewertung</a><br />
+<a class="menu" href="#defines">Eine &Uuml;bersicht aller Konfigurationsparameter</a><br />
+
+<a name="uebersicht"></a><h2>Eine allgemeine &Uuml;bersicht</h2>
+<p>Das Speichersystem ist wie folgt organisiert: <br />
+Man fordert eine beliebige Menge an Speicher an und bekommt eine virtuelle Adresse in 32 Bit zur&uuml;ck.
+Diese Adresse entspricht der Adresse auf der MMC / SD-Card, was den Benutzer aber nicht weiter interessieren muss. Zum Arbeiten mit den Daten
+erh&auml;lt man eine "echte" SRAM-Adresse, die auf einen 512 Byte gro&szlig;en Speicherbereich zeigt. Dieser Cacheeintrag wird
+auf die MMC / SD-Card zur&uuml;ckgeschrieben, sobald der maximal f&uuml;r den <a href="#cache">Cache</a> zugeteilte Speicher komplett belegt ist, das
+Ein- und Auslagern der Seiten auf die MMC / SD-Card macht die Speicherverwaltung also automatisch.<br />
+Somit kann ein Verhalten beliebig viel (virtuellen) Speicher benutzen, siehe Abschnitt zum <a href="#vm">virtuellen Speicher</a>.
+Au&szlig;erdem kann derselbe Adressraum und Cache auch f&uuml;r den Zugriff auf FAT16-Dateien benutzt werden, N&auml;heres dazu gibt es <a href="#fat">hier</a>.<br />
+Die Bezeichnung "page" (oder "Seite") stellt durchg&auml;ngig etwas logisches (virtuelles) dar, mit "Block" hingegen ist ein physischer Block auf dem verwendeten
+Datentr&auml;ger gemeint.<br />
+Im Folgenden wird ausschlie&szlig;lich auf die Verwendung einer MMC / SD-Card als Speichermedium eingegangen, l&auml;uft der Code auf einem PC, so wird die
+Speicherkarte mit Hilfe einer Datei emuliert, die Verwendung ist aber &auml;quivalent (siehe auch <a href="../pc/mmc-emu_pc.c">pc/mmc-emu_pc.c</a>).
+</p>
+
+<a name="vm"></a><h2>Der virtuelle Speicher im Detail</h2>
+<a name="alloc"></a><h3>Die Speicherallokierung</h3>
+<p>Nach der Anforderung einer beliebige Menge an Speicher per<span class="function"> mmcalloc()</span>, bekommt man eine virtuelle Adresse des 32 Bit gro&szlig;en
+Adressraums zur&uuml;ck.<span class="function"> mmc_get_data(uint32 virtuelle_Adresse)</span> liefert dann eine "echte" SRAM-Adresse auf einen 512 Byte
+gro&szlig;en Puffer zur&uuml;ck, dessen Inhalt auf die MMC / SC-Card geschrieben wird, sobald er nicht mehr im SRAM gehalten werden kann.<br />
+Die Funktion<span class="function"> mmc_get_end_of_page(uint32 virtuelle_Adresse)</span> hilft herauszufinden, bis wohin man diesen Pointer verwenden darf.
+Ben&ouml;tigt man mehr Speicher, fordert man<span class="function"> mit mmc_get_data(uint32 virtuelle_Adresse)</span> einen neuen Pointer an.<br />
+Zu beachten ist, dass nur soviel virtueller Speicher zur Verf&uuml;gung steht, wie die intuitive Rechnung &quot;letzter Sektor der MMC / SD-Card&quot; minus
+&quot;<a href="#defines">Startadresse f&uuml;r den virtuellen Speicher</a>&quot; ergibt. Ansonsten liefert<span class="function"> mmcalloc()</span> null zur&uuml;ck.
+</p>
+
+<a name="example"></a><h3>Ein kleines Beispiel</h3>
+<p>Das folgende Beispiel demonstriert, wie sich der virtuelle Speicher benutzen l&auml;sst:<br />
+<ins><div class="code">
+<span class="keyword">uint32</span> v_addr = mmcalloc(2048, 1); <span class="comment">// wir wollen 2 KB Speicher</span><br />
+<span class="keyword">uint8</span>* p_addr = mmc_get_data(v_addr); <span class="comment">// Pointer auf Puffer holen</span><br />
+... <span class="comment">// irgendwas sinnvolles tun</span><br />
+<span class="keyword">if</span> (i &lt; 512) { <span class="comment">// Ziel liegt noch im gleichen Block</span><br />
+&nbsp;p_addr[i] = my_data; <span class="comment">// Daten speichern</span><br />
+&nbsp;i++;<br />
+} <span class="keyword">else</span> { <span class="comment">// Blockende erreicht => zunaechst neuen Pointer holen</span><br />
+&nbsp;v_addr += i;<br />
+&nbsp;i = 0;<br />
+&nbsp;p_addr = mmc_get_data(v_addr);<br />
+&nbsp;p_addr[i] = my_data; <span class="comment">// Daten koennen nun gespeichert werden</span><br />
+}
+</div></ins><br />
+Der zweite Parameter von<span class="function"> mmcalloc()</span> gibt an, ob man den angeforderten Speicher auf m&ouml;glichst wenige Bl&ouml;cke verteilt
+haben m&ouml;chte (also 512 Byte ausgerichtet), oder ob er einfach am n&auml;chsten freien Byte auf der Karte beginnen soll (1: aligned, 0: beliebig). Passt der
+angeforderte Speicher noch komplett in einen bereits teilweise belegten Block, so wird er immer dort untergebracht.
+</p>
+
+<a name="mmc"></a><h3>Die Schnittstelle zur Hardware</h3>
+<p>
+Das folgende Diagramm zeigt die Beziehung der Funktionen des MMC-Codes und die entsprechenden Schnittstellen:
+<br /><a href="mmc.jpg" onclick="popup=window.open('mmc.jpg','','dependent=yes,location=no,menubar=no,status=no,toolbar=no,scrollbars=yes'); popup.focus(); return false"><img src="mmc.jpg" width="200" alt="mmc-Code" /></a>
+<br />Die gr&uuml;n gekennzeichneten Funktionen sind in den jeweiligen Header-Dateien deklariert und bilden zusammen
+die Schnittstelle des MMC-Codes nach au&szlig;en. Die rot Gekennzeichneten hingegen bleiben dem eigentlichen Code f&uuml;r MMC und virtual Memory vorbehalten.<br />
+Die Abh&auml;ngigkeiten untereinander sind durch die Pfeile dargestellt (in Aufrufrichtung).<br />
+Den doppelt umrandeten Funktionen m&ouml;ge man besondere Aufmerksamkeit schenken - diese sind vorrangig in eigenen Verhalten zu verwenden. Die restlichen
+(internen) Funktionen sind eher zur Dokumentation des Speichersystems an sich aufgef&uuml;hrt, f&uuml;r die Benutzung in Bot-Verhalten sind sie nicht so sehr
+interessant.
+</p>
+
+<a name="cache"></a><h3 style="clear:both">Einige Erl&auml;uterungen zum Cache</h3>
+<p>
+Um den Zugriff auf die jeweiligen Daten m&ouml;glichst performant zu halten, cached das Speichersystem eine vorgegebene Anzahl an 512 Byte gro&szlig;en
+Bl&ouml;cken im SRAM. Der Cache ist vollassoziativ, f&uuml;r das Zur&uuml;ckschreiben kommt das LRU-Verfahren zum Einsatz. Im Speicher wird er durch ein Array
+vom Typ <i>vm_cache_t</i> (siehe auch <a href="../mmc-vm.c">mmc-vm.c</a>) repr&auml;sentiert, die maximale Gr&ouml;&szlig;e l&auml;sst sich mit einem
+<a href="#defines">Konfigurationsparameter</a> festlegen und wird bei Speichermangel automatisch reduziert. Es wird erst dann Cachespeicher belegt, wenn
+auch Daten angefordert werden.<br />
+Ein Aufruf der Funktion<span class="function"> mmc_flush_cache()</span> schreibt den kompletten Cache auf die Karte zur&uuml;ck,<span class="function">
+mmc_page_write_back(uint32 virtuelle_Adresse)</span> hingegen nur die Seite, die zu der &uuml;bergebenen Adresse geh&ouml;rt. Letztere Funktion tut dies
+unabh&auml;ngig davon, ob die Seite seit der Einlagerung ver&auml;ndert wurde oder nicht und erm&ouml;glicht so einen &quot;tieferen&quot; Eingriff in das
+sonst automatisch arbeitende System.<br />
+Ein Verhalten sollte also vor seiner Beendigung daf&uuml;r sorgen, dass der Cacheinhalt gesichert wird, wenn die gespeicherten Daten erhalten bleiben sollen!
+</p>
+
+<a name="fat"></a><h2>Der Zugriff auf ein FAT16-Dateisystems</h2>
+<p>
+Die Unterst&uuml;tzung f&uuml;r FAT16-Dateien auf einer MMC / SD-Card ist wie folgt aufgebaut:<br />
+<span class="function"> mmc_fopen(const char *filename)</span> &ouml;ffnet eine Datei im FAT16-Dateisystem der Karte und gibt die virtuelle Startadresse
+zur&uuml;ck, so dass man mit<span class="function"> mmc_get_data()</span> Zugriff auf die Daten bekommt. Der Dateiname muss dabei ganz am Anfang in der Datei
+stehen.<br />
+Achtung: &Ouml;ffnet man eine Datei, die bereits mit<span class="function"> mmc_fopen()</span> ge&ouml;ffnet wurde, ist das Verhalten bzgl. dieser Datei derzeit
+undefiniert!<br />
+<span class="function"> mmc_clear_file(uint32 file_start)</span> leert eine Datei im FAT16-Dateisystem, die zuvor mit<span class="function">
+mmc_fopen()</span> ge&ouml;ffnet wurde. Die Datei wird komplett mit Nullen &uuml;berschrieben, nur der erste Sektor mit dem &quot;Dateinamen&quot; und der
+Gr&ouml;&szlig;e bleibt erhalten.<br />
+<span class="function"> mmc_get_filesize(uint32 file_start)</span> gibt die Gr&ouml;&szlig;e einer ge&ouml;ffneten Datei in Byte zur&uuml;ck.
+</p>
+
+<a name="stat"></a><h2>Etwas Statistik zur Leistungsbewertung</h2>
+<p>
+Wenn <a href="#defines">VM_STATS_AVAILABLE</a> definiert ist, l&auml;sst sich mit der Funktion<span class="function"> mmc_get_vm_stats()</span> eine Statistik
+&uuml;ber die Leistung des Speichersystems erstellen.<span class="function"> mmc_print_statistic()</span> gibt solch eine Statistik in der Konsole aus, wenn der
+Code auf einem PC l&auml;uft:
+<ins><table class="console">
+<tr><td>*** VM-Statistik ***</td></tr>
+<tr><td>Groesse des Volumes:</td><td>32 MByte</td></tr>
+<tr><td>Groesse des VM:</td><td>16 MByte</td></tr>
+<tr><td>Belegter virt. Speicher:</td><td>0 KByte</td></tr>
+<tr><td>Groesse des Caches:</td><td>1024 Byte</td></tr>
+<tr><td>Auslastung des Caches:</td><td>100 %</td></tr>
+<tr><td>Seitenzugriffe:</td><td>1375054</td></tr>
+<tr><td>Seiteneinlagerungen:</td><td>33770</td></tr>
+<tr><td>Seitenauslagerungen:</td><td>33768</td></tr>
+<tr><td>Seitenzugriffe / s:</td><td>5288</td></tr>
+<tr><td>Seiteneinlagerungen / s:</td><td>129</td></tr>
+<tr><td>Seitenauslagerungen / s:&nbsp;&nbsp;</td><td>129</td></tr>
+<tr><td>Cache-Hit-Rate:</td><td>97.544096 %&nbsp;&nbsp;&nbsp;&nbsp;</td></tr>
+<tr><td>Messdauer:</td><td>260 s</td></tr>
+</table></ins><br />
+Die hier ersichtlichen Daten stellen die Leistung des Speichersystems dar, unmittelbar nachdem ein Bot das Standardlabyrinth im c't-Sim komplett mit dem Wandfolger-Algorithmus
+durchfahren und dabei eine Umgebungskarte erstellt hat.<br />
+F&uuml;r die MCU gibt es derzeit noch keine entsprechende Ausgabem&ouml;glichkeit.
+</p>
+
+<a name="defines"></a><h2>Eine &Uuml;bersicht aller Konfigurationsparameter</h2>
+<ul>
+ <li><span class="function"> MMC_VM_AVAILABLE</span> schaltet den Speichermanager ein oder aus.</li>
+ <li><span class="function"> VM_STATS_AVAILABLE</span> erm&ouml;glicht die Berechnung und Ausgabe einer <a href="#stat">Statistik</a> &uuml;ber das Speichersystem, wenn definiert.</li>
+ <li><span class="function"> MMC_START_ADDRESS</span> gibt die physische Adresse (in Byte) an, wo der virtuelle Speicher beginnt. Sinnvoll ist z.B. die H&auml;lfte der MMC- / SD-Card-Gr&ouml;&szlig;e, der Speicherplatz davor kann dann f&uuml;r ein Dateisystem verwendet werden.</li>
+ <li><span class="function"> MAX_SPACE_IN_SRAM</span> definiert die Anzahl der 512 Byte gro&szlig;en Bl&ouml;cke, die maximal gleichzeitig im SRAM gehalten werden.</li>
+ <li><span class="function"> VM_FILENAME_MAX</span> ist die maximale L&auml;nge eines Dateinamens in Zeichen.</li>
+</ul>
+
+<br /><br />
+<p><a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0 Transitional" height="31" width="88" /></a></p>
+</body>
+</html> \ No newline at end of file
diff --git a/source/ct-Bot/Documentation/mmc.jpg b/source/ct-Bot/Documentation/mmc.jpg
new file mode 100644
index 0000000..d73357b
--- /dev/null
+++ b/source/ct-Bot/Documentation/mmc.jpg
Binary files differ
diff --git a/source/ct-Bot/Documentation/remote-calls.html b/source/ct-Bot/Documentation/remote-calls.html
new file mode 100644
index 0000000..3691afe
--- /dev/null
+++ b/source/ct-Bot/Documentation/remote-calls.html
@@ -0,0 +1,33 @@
+<?xml version="1.0" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<meta name="description" content="Uebersicht der Remote-Calls am c't-Bot" />
+<meta name="keywords" content="c't-Bot,c't-Sim,Remote-Calls" />
+<meta name="date" content="2007-01-15" />
+<title>c't-Bot -Remote-Calls</title>
+<link rel="stylesheet" type="text/css" href="style.css" />
+</head>
+<body>
+<h1>Dokumentation zum Remote-Call-System</h1>
+<br />
+<h2>Funktionsweise der Remote-Calls f&uuml;r den c't-Bot:</h2>
+<p>Auf das Kommando<span class="function"> CMD_REMOTE_CALL:SUB_REMOTE_CALL_LIST</span> schickt der Bot
+eine Liste mit den verf&uuml;gbaren Remote-Calls an den PC.<br />
+Jeder Listeneintrag kommt als eigenes Kommando<span class="function"> (CMD_REMOTE_CALL:SUB_REMOTE_CALL_ENTRY)</span>. <br />
+In der Payload steht neben dem Namen der Funktion auch, wie sie aufzurufen
+ist und welche Parameter sie braucht. Das geschieht, indem die ganze interne
+Datenstruktur (siehe<span class="function"> call_t</span> in <a href="../include/bot-logic/remote_calls.h">remote_calls.h</a>) &uuml;bertragen wird.</p>
+<p>Der PC kann jederzeit einen Remote-Call starten. Dazu schickt es das Kommando
+<span class="function"> CMD_REMOTE_CALL:SUB_REMOTE_CALL_ORDER.</span> In der Payload steht zuerst der Name
+der Funktion (null terminierter String). Danach kommen die Parameter. Jeder
+Parameter muss dabei (unabh&auml;ngig von seiner tats&auml;chlichen L&auml;nge) 32 Bit belegen.</p>
+<p>Ist der Bot fertig, antwortet er mit<span class="function"> CMD_REMOTE_CALL:SUB_REMOTE_CALL_DONE</span>
+im DataL Feld steht eine 0, wenn das Verhalten nicht erfolgreich ausgef&uuml;hrt wurde. Steht dort eine 1, ist alles ok.</span></p>
+<p>Um eigen Verhalten remote-aufrufbar zu machen, muss man ihre Botenfunktion nur in
+die calls-Struktur in <a href="../bot-logic/behaviour_remotecall.c">behaviour_remotecall.c</a> eintragen. Wie das geht ist dort
+ausf&uuml;hrlich beschrieben. Alles andere &uuml;bernimmt das Framework.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/source/ct-Bot/Documentation/select-behaviours.txt b/source/ct-Bot/Documentation/select-behaviours.txt
new file mode 100644
index 0000000..64ef403
--- /dev/null
+++ b/source/ct-Bot/Documentation/select-behaviours.txt
@@ -0,0 +1,29 @@
+Frank Menzel(menzelfr@gmx.de) & Carsten Giesen (info@cnau.de):
+
+Auswahl von Verhalten ueber Fernbedienungstasten
+
+Anstelle des Counters koennen im Screen 3 nun alle Verhalten dargestellt werden,
+jeweils 6 Stueck (2 neben-, 3 untereinander). Erst die Prioritaet und dann die Aktivitaet,
+wobei 0 fuer ein inaktives und 1 fuer aktives Verhalten steht. Passen nicht
+alle rauf, wird weitergeblaettert zu den naechsten Verhalten. Die aktuelle Verhaltens-Seite wird
+durch die letzte Zahl in der ueberschrift dargestellt.
+Folgende Vorgehensweise:
+Mit der Screen-Toggle Taste (RC5_CODE_VIEW-bei meiner Hauppauge Fullscreen) werden die Screens
+durchgeblaettert und im Screen 3 nun die Verhalten angezeigt. Die Tasten 1-6 sind den
+Verhalten zugeordnet, wodurch diese damit getoggelt werden. Der angezeigte Aktivitaetswert
+aendert sich von 0 nach 1 und umgedreht. Man kann nun alle Verhaltensseiten weiter
+durchblaettern, beliebige ein- und ausschalten oder kombinieren und zum Schluss wird
+die Taste RC5_CODE_SELECT betaetigt (bei meiner Hauppauge ist dies die Taste Source),
+wodurch alle Verhalten entsprechend der Auswahl in ihrer Aktivitaet geaendert werden.
+
+Im Simulator gibt es leider die Tasten RC5_CODE_VIEW und RC5_CODE_SELECT (noch) nicht. Waehrend
+hier aber die gelbe Taste den Verhaltens-Screen direkt anwaehlen kann, existiert fuer die Select-Taste
+kein Aequivalent. So erhaelt die Taste 9 im Screen 3 diese Funktion.
+
+Moegliche Erweiterungen:
+-Verhalten sind bis jetzt nur vorwaerts blaetterbar, ein Rueckwaertsblaettern koennte bei Bedarf noch
+realisiert werden
+-Wenn ein Verhalten ein oder mehrere andere Verhalten in ihrer Aktivitaet beeinflusst, ist dies im Moment
+ nicht online sichtbar. Die Anzeige und Wunschaenderungen gehen immer nur auf die Puffervariable des Verhaltens
+ und ist somit statisch. Ist die dynamische Variante gewuenscht, also dass man direkt online die Aktivitaeten
+ der Verhalten verfolgen kann, so ist dies relativ leicht realisierbar.
diff --git a/source/ct-Bot/Documentation/style.css b/source/ct-Bot/Documentation/style.css
new file mode 100644
index 0000000..c6a0821
--- /dev/null
+++ b/source/ct-Bot/Documentation/style.css
@@ -0,0 +1,128 @@
+/* das grosse Ganze */
+body {
+ margin: 20px 10px;
+ padding: 5px;
+ color: #000;
+ text-align: justify;
+ font-family: Verdana, "Lucida Grande", Lucida;
+ background-color: #e4e4e4;
+}
+
+/* Seitenueberschrift */
+h1 {
+ color: #940000;
+ text-align: center;
+ text-decoration: underline;
+ font: 22pt Geneva, sans-serif, Helvetica, Arial;
+}
+
+/* Themenueberschrift */
+h2 {
+ font-size: 18pt;
+ color: #000;
+ font-variant: small-caps;
+ margin-top: 40px;
+}
+
+/* Unterueberschrift */
+h3 {
+ font-size: 16pt;
+ color: #000;
+ font-variant: small-caps;
+ margin: 0;
+ padding-top: 10px;
+}
+
+/* Text */
+p {
+ font-size: 11pt;
+}
+
+/* Quellcode hervorheben */
+.code {
+ color: #000;
+ font-family: Courier, mono;
+ background-color: #fff;
+ display: table;
+ margin-left: 10px;
+ padding: 5px;
+ margin-top: 10px;
+}
+
+.keyword {
+ color: #9f0b55;
+}
+
+.comment {
+ color: #008600;
+}
+
+/* inline-Quellcode */
+.function {
+ color: #006900;
+ font-family: "Courier New", Courier, mono;
+ font-weight: bold;
+}
+
+/* Konsolenausgaben hervorheben */
+.console {
+ color: #0f0;
+ background-color: #000;
+ display: table;
+ margin-left: 10px;
+ padding: 5px;
+ margin-top: 10px;
+ font: 10pt "Lucida Grande", Lucida, Verdana;
+}
+
+/* alle Links sind gleich */
+a:link {
+ text-decoration: none;
+ color: #110086;
+}
+
+a:visited {
+ text-decoration: none;
+ color: #110086;
+}
+
+a:active {
+ text-decoration: underline;
+ color: #110086;
+}
+
+a:hover {
+ color: #ff2021;
+ /*color: #5796ff;*/
+ text-decoration: underline;
+}
+
+/* oberes Menue */
+.menu {
+ line-height: 22px;
+}
+
+/* Liste */
+ul {
+ margin: 0;
+ list-style-type: circle;
+ padding: 0 20px;
+ list-style-position: outside;
+}
+
+/* Unterpunkte im Menue */
+ul.menu {
+ color: #110086;
+}
+
+/* Grafiken */
+img {
+ margin: 10px 20px 5px 5px;
+ float: left;
+ border: 1px solid #000;
+}
+
+/* IE-Workaround */
+ins {
+ text-decoration: none;
+} \ No newline at end of file
diff --git a/source/ct-Bot/GPL.txt b/source/ct-Bot/GPL.txt
new file mode 100644
index 0000000..c33273c
--- /dev/null
+++ b/source/ct-Bot/GPL.txt
@@ -0,0 +1,92 @@
+GNU GENERAL PUBLIC LICENSE
+
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification follow.
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
+
+3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
+
+If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS \ No newline at end of file
diff --git a/source/ct-Bot/Makefile b/source/ct-Bot/Makefile
new file mode 100644
index 0000000..ade0e2a
--- /dev/null
+++ b/source/ct-Bot/Makefile
@@ -0,0 +1,461 @@
+# Hey Emacs, this is a -*- makefile -*-
+#
+# WinAVR Sample makefile written by Eric B. Weddington, Joerg Wunsch, et al.
+# Released to the Public Domain
+# Please read the make user manual!
+#
+# Additional material for this makefile was submitted by:
+# Tim Henigan
+# Peter Fleury
+# Reiner Patommel
+# Sander Pool
+# Frederik Rouleau
+# Markus Pfaff
+#
+# On command line:
+#
+# make all = Make software.
+#
+# make clean = Clean out built project files.
+#
+# make coff = Convert ELF to AVR COFF (for use with AVR Studio 3.x or VMLAB).
+#
+# make extcoff = Convert ELF to AVR Extended COFF (for use with AVR Studio
+# 4.07 or greater).
+#
+# make program = Download the hex file to the device, using avrdude. Please
+# customize the avrdude settings below first!
+#
+# make filename.s = Just compile filename.c into the assembler code only
+#
+# To rebuild project do "make clean" then "make all".
+#
+
+
+# MCU name
+MCU = atmega32
+
+# Output format. (can be srec, ihex, binary)
+FORMAT = ihex
+
+# Target file name (without extension).
+TARGET = ct-Bot
+
+# Target Device, either pc or mcu, usually defined on commandline
+#DEVICE = MCU
+DEVICE = PC
+
+MSG_DEVICE = Target device is $(DEVICE)
+
+# List C source files here. (C dependencies are automatically generated.)
+SRCMCU = mcu/adc.c mcu/bot-2-pc.c mcu/delay.c mcu/display.c mcu/ena.c mcu/ir-rc5.c mcu/led.c mcu/motor-low.c mcu/mouse.c mcu/sensor-low.c mcu/shift.c mcu/timer-low.c mcu/uart.c mcu/mmc.c
+
+SRCPC = pc/bot-2-sim.c pc/delay_pc.c pc/display_pc.c pc/ir-rc5_pc.c pc/led_pc.c pc/motor-low_pc.c pc/sensor-low_pc.c pc/tcp.c pc/tcp-server.c pc/mouse_pc.c
+
+SRCCOM = bot-logic/bot-logik.c map.c command.c log.c motor.c rc5.c sensor.c timer.c bot-logic/behaviour_avoid_border.c bot-logic/behaviour_drive_square.c bot-logic/behaviour_gotoxy.c bot-logic/behaviour_simple.c bot-logic/behaviour_avoid_col.c bot-logic/behaviour_follow_line.c bot-logic/behaviour_olympic.c bot-logic/behaviour_solve_maze.c bot-logic/behaviour_drive_distance.c bot-logic/behaviour_goto.c bot-logic/behaviour_scan.c bot-logic/behaviour_turn.c bot-logic/behaviour_servo.c
+
+
+ifeq ($(DEVICE),MCU)
+ SRC = $(TARGET).c $(SRCCOM) $(SRCMCU)
+else
+ SRC = $(TARGET).c $(SRCCOM) $(SRCPC)
+endif
+
+
+# List Assembler source files here.
+# Make them always end in a capital .S. Files ending in a lowercase .s
+# will not be considered source files but generated files (assembler
+# output from the compiler), and will be deleted upon "make clean"!
+# Even though the DOS/Win* filesystem matches both .s and .S the same,
+# it will preserve the spelling of the filenames, and gcc itself does
+# care about how the name is spelled on its command-line.
+ASRC =
+
+MATH_LIB = -lm
+
+ifeq ($(DEVICE),MCU)
+ # List any extra directories to look for include files here.
+ # Each directory must be seperated by a space.
+ EXTRAINCDIRS = /usr/local/avr/include include
+
+
+
+
+ # Assembler flags.
+ # -Wa,...: tell GCC to pass this to the assembler.
+ # -ahlms: create listing
+ # -gstabs: have the assembler create line number information; note that
+ # for use in COFF files, additional information about filenames
+ # and function names needs to be present in the assembler source
+ # files -- see avr-libc docs [FIXME: not yet described there]
+ ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
+
+
+
+ #Additional libraries.
+
+ # Minimalistic printf version
+ PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
+
+ # Floating point printf version (requires MATH_LIB = -lm below)
+ PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
+
+ PRINTF_LIB =
+
+ # Minimalistic scanf version
+ SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
+
+ # Floating point + %[ scanf version (requires MATH_LIB = -lm below)
+ SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
+
+ SCANF_LIB =
+
+ # External memory options
+
+ # 64 KB of external RAM, starting after internal RAM (ATmega128!),
+ # used for variables (.data/.bss) and heap (malloc()).
+ #EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
+
+ # 64 KB of external RAM, starting after internal RAM (ATmega128!),
+ # only used for heap (malloc()).
+ #EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff
+
+ EXTMEMOPTS =
+
+ # Linker flags.
+ # -Wl,...: tell GCC to pass this to linker.
+ # -Map: create map file
+ # --cref: add cross reference to map file
+ LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
+ LDFLAGS += $(EXTMEMOPTS)
+ LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
+
+
+
+
+ # Programming support using avrdude. Settings and variables.
+
+ # Programming hardware: alf avr910 avrisp bascom bsd
+ # dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
+ #
+ # Type: avrdude -c ?
+ # to get a full listing.
+ #
+ AVRDUDE_PROGRAMMER = pony-stk200
+
+ # com1 = serial port. Use lpt1 to connect to parallel port.
+ AVRDUDE_PORT = lpt1
+
+ AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
+ #AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
+
+
+ # Uncomment the following if you want avrdude's erase cycle counter.
+ # Note that this counter needs to be initialized first using -Yn,
+ # see avrdude manual.
+ #AVRDUDE_ERASE_COUNTER = -y
+
+ # Uncomment the following if you do /not/ wish a verification to be
+ # performed after programming the device.
+ #AVRDUDE_NO_VERIFY = -V
+
+ # Increase verbosity level. Please use this when submitting bug
+ # reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
+ # to submit bug reports.
+ #AVRDUDE_VERBOSE = -v -v
+
+ AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
+ AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
+ AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
+ AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
+
+
+
+ # ---------------------------------------------------------------------------
+
+ # Define directories, if needed.
+ DIRAVR = /usr/local/avr
+ DIRAVRBIN = $(DIRAVR)/bin
+ DIRAVRUTILS = $(DIRAVR)/utils/bin
+ DIRINC = $(DIRAVR)/include
+ DIRLIB = $(DIRAVR)/lib/avr5
+
+ CC = avr-gcc
+ OBJCOPY = avr-objcopy
+ OBJDUMP = avr-objdump
+ SIZE = avr-size
+ NM = avr-nm
+ AVRDUDE = avrdude
+
+else
+ # List any extra directories to look for include files here.
+ # Each directory must be seperated by a space.
+ EXTRAINCDIRS = include
+
+ CC = gcc
+ PTHREAD_LIB = -lpthread
+ LDFLAGS += $(PTHREAD_LIB) $(MATH_LIB)
+ SIZE = size
+endif
+
+
+
+# Define programs and commands.
+SHELL = sh
+REMOVE = rm -f
+COPY = cp
+
+
+# Optimization level, can be [0, 1, 2, 3, s].
+# 0 = turn off optimization. s = optimize for size.
+# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
+OPT = s
+
+# Compiler flag to set the C Standard level.
+# c89 - "ANSI" C
+# gnu89 - c89 plus GCC extensions
+# c99 - ISO C99 standard (not yet fully implemented)
+# gnu99 - c99 plus GCC extensions
+CSTANDARD = -std=gnu99
+
+# Place -D or -U options here
+CDEFS =
+
+# Place -I options here
+CINCS =
+
+
+# Compiler flags.
+# -g: generate debugging information
+# -O*: optimization level
+# -f...: tuning, see GCC manual and avr-libc documentation
+# -Wall...: warning level
+# -Wa,...: tell GCC to pass this to the assembler.
+# -adhlns...: create assembler listing
+CFLAGS = -g
+CFLAGS += $(CDEFS) $(CINCS)
+CFLAGS += -O$(OPT)
+CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
+CFLAGS += -Wall -Wstrict-prototypes
+CFLAGS += -Wa,-adhlns=$(<:.c=.lst)
+CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
+CFLAGS += $(CSTANDARD)
+
+
+
+# Define Messages
+# English
+MSG_ERRORS_NONE = Errors: none
+MSG_BEGIN = -------- begin --------
+MSG_END = -------- end --------
+MSG_SIZE_BEFORE = Size before:
+MSG_SIZE_AFTER = Size after:
+MSG_COFF = Converting to AVR COFF:
+MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
+MSG_FLASH = Creating load file for Flash:
+MSG_EEPROM = Creating load file for EEPROM:
+MSG_EXTENDED_LISTING = Creating Extended Listing:
+MSG_SYMBOL_TABLE = Creating Symbol Table:
+MSG_LINKING = Linking:
+MSG_COMPILING = Compiling:
+MSG_ASSEMBLING = Assembling:
+MSG_CLEANING = Cleaning project:
+
+
+
+
+# Define all object files.
+OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
+
+# Define all listing files.
+LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
+
+
+# Compiler flags to generate dependency files.
+GENDEPFLAGS = -Wp,-M,-MP,-MT,$(*F).o,-MF,.dep/$(@F).d
+
+
+# Combine all necessary flags and optional flags.
+# Add target processor to flags.
+ifeq ($(DEVICE),MCU)
+ ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS) -D $(DEVICE)
+ ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
+else
+ ALL_CFLAGS = -I. $(CFLAGS) $(GENDEPFLAGS) -D $(DEVICE)
+endif
+
+
+
+# Default target.
+all: begin gccversion sizebefore build sizeafter finished end
+
+ifeq ($(DEVICE),MCU)
+build: elf hex eep lss sym
+else
+build: elf
+endif
+
+elf: $(TARGET).elf
+hex: $(TARGET).hex
+eep: $(TARGET).eep
+lss: $(TARGET).lss
+sym: $(TARGET).sym
+
+
+# Eye candy.
+# AVR Studio 3.x does not check make's exit code but relies on
+# the following magic strings to be generated by the compile job.
+begin:
+ @echo
+ @echo $(MSG_DEVICE)
+ @echo
+ @echo $(MSG_BEGIN)
+
+finished:
+ @echo $(MSG_ERRORS_NONE)
+
+end:
+ @echo $(MSG_END)
+ @echo
+
+
+# Display size of file.
+HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
+ELFSIZE = $(SIZE) -A $(TARGET).elf
+sizebefore:
+ @if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi
+
+sizeafter:
+ @if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
+
+
+
+# Display compiler version information.
+gccversion :
+ @$(CC) --version
+
+
+
+# Program the device.
+program: $(TARGET).hex $(TARGET).eep
+ $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
+
+
+
+
+# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
+COFFCONVERT=$(OBJCOPY) --debugging \
+--change-section-address .data-0x800000 \
+--change-section-address .bss-0x800000 \
+--change-section-address .noinit-0x800000 \
+--change-section-address .eeprom-0x810000
+
+
+coff: $(TARGET).elf
+ @echo
+ @echo $(MSG_COFF) $(TARGET).cof
+ $(COFFCONVERT) -O coff-avr $< $(TARGET).cof
+
+
+extcoff: $(TARGET).elf
+ @echo
+ @echo $(MSG_EXTENDED_COFF) $(TARGET).cof
+ $(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
+
+
+
+# Create final output files (.hex, .eep) from ELF output file.
+%.hex: %.elf
+ @echo
+ @echo $(MSG_FLASH) $@
+ $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
+
+%.eep: %.elf
+ @echo
+ @echo $(MSG_EEPROM) $@
+ -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
+ --change-section-lma .eeprom=0 -O $(FORMAT) $< $@
+
+# Create extended listing file from ELF output file.
+%.lss: %.elf
+ @echo
+ @echo $(MSG_EXTENDED_LISTING) $@
+ $(OBJDUMP) -h -S $< > $@
+
+# Create a symbol table from ELF output file.
+%.sym: %.elf
+ @echo
+ @echo $(MSG_SYMBOL_TABLE) $@
+ $(NM) -n $< > $@
+
+
+
+# Link: create ELF output file from object files.
+.SECONDARY : $(TARGET).elf
+.PRECIOUS : $(OBJ)
+%.elf: $(OBJ)
+ @echo
+ @echo $(MSG_LINKING) $@
+ $(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
+
+
+# Compile: create object files from C source files.
+%.o : %.c
+ @echo
+ @echo $(MSG_COMPILING) $<
+ $(CC) -c $(ALL_CFLAGS) $< -o $@
+
+
+# Compile: create assembler files from C source files.
+%.s : %.c
+ $(CC) -S $(ALL_CFLAGS) $< -o $@
+
+
+# Assemble: create object files from assembler source files.
+%.o : %.S
+ @echo
+ @echo $(MSG_ASSEMBLING) $<
+ $(CC) -c $(ALL_ASFLAGS) $< -o $@
+
+
+
+# Target: clean project.
+clean: begin clean_list finished end
+
+clean_list :
+ @echo
+ @echo $(MSG_CLEANING)
+ $(REMOVE) $(TARGET).hex
+ $(REMOVE) $(TARGET).eep
+ $(REMOVE) $(TARGET).obj
+ $(REMOVE) $(TARGET).cof
+ $(REMOVE) $(TARGET).elf
+ $(REMOVE) $(TARGET).map
+ $(REMOVE) $(TARGET).obj
+ $(REMOVE) $(TARGET).a90
+ $(REMOVE) $(TARGET).sym
+ $(REMOVE) $(TARGET).lnk
+ $(REMOVE) $(TARGET).lss
+ $(REMOVE) $(OBJ)
+ $(REMOVE) $(LST)
+ $(REMOVE) $(SRC:.c=.s)
+ $(REMOVE) $(SRC:.c=.d)
+ $(REMOVE) .dep/*
+
+
+
+# Include the dependency files.
+-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
+
+
+# Listing of phony targets.
+.PHONY : all begin finish end sizebefore sizeafter gccversion \
+build elf hex eep lss sym coff extcoff \
+clean clean_list program
+
+
+# you need to erase first before loading the program.
+# load (program) the software into the eeprom:
+load: avrledtest.hex
+ uisp -dlpt=/dev/parport0 --erase -dprog=dapa
+ uisp -dlpt=/dev/parport0 --upload if=$(TARGET).hex -dprog=dapa -v=3 --hash=32
diff --git a/source/ct-Bot/TODO.txt b/source/ct-Bot/TODO.txt
new file mode 100644
index 0000000..99f07da
--- /dev/null
+++ b/source/ct-Bot/TODO.txt
@@ -0,0 +1,58 @@
+Wunsch- und Aufgabenliste fuer die c't-Bot-Firmware bzw. ihr PC-Pendant:
+========================================================================
+
+Alle hier aufgefuehrten Punkte stehen noch aus. Wer moechte, ist herzlich eingeladen,
+uns Patches (siehe FAQ) zu schicken, die diese Liste sinnvoll ergaenzen. Aber auch ueber Loesungen
+fuer hier genannte Probleme freuen wir uns.
+
+Thema Datei Task
+==========================================================================
+gefahren bot-logik.c Low-Level-Verhalten müssen andere über gefahren warnen
+Anmeldung command.c Der Bot sollte auch auf Welcome-Nachrichten des Sims antworten
+Zeit Timer.c Auf dem PC existiert noch keine Routine, die die globalen Zeitvariablen aktualisiert
+Sensoren Linearisierung der Sensorwerte
+Info Readme-Datei zu Variablen und Funktionen schreiben
+delay delay.c Delay von busy-wait auf timer-basiert umstellen
+Framework bot-logik.c bot-logik-c aufspalten in mehrere Dateien
+
+
+Ideen/Ausbaustufen
+# Scanner:
+ * Abtasten der Umgebung mit den IR-Sensoren
+ * Bot langsam drehen, dabei Sensorwerte auslesen
+ * Daten per UART an den c't-Sim versenden
+ * c't-Sim für Anzeige modifizieren
+ * Daten benutzen um Karte zu zeichnen
+
+# Servosteuerung:
+ * Position anfahren
+ * Position abfragen
+ * Strom prüfen
+
+# Fehlerkontrolle
+ * Batterieschaltung testen
+
+# Positionsstack
+ * Funktion push_pos() - Sichert eine Position auf dem Stack
+ * Funktion pop_pos() - Holt eine Position vom Stack
+ * geeignete Datenstruktur konzipieren
+ * drive_stack_behaviour fährt alle Punkte auf dem Stack an. Kann man benutzen, um zum Ursprung zurückzufahren, oder einen Weg zu planen
+
+# Funk
+ * Kommunikationscode erweitern für Punkt zu Multipunkt / From-To
+ * testen
+
+# Kamera
+ * anschliessen
+ * testen
+ * Sample-Code entwickeln
+
+# CPU-Modul:
+ * EVM-Board besorgen
+ * Experimentieren mit EVM-Board
+
+# Sensorerweiterungen:
+ * experimentieren
+ * weitere Distanzsensoren
+ * Kompass
+ * Beschleunigungssensoren \ No newline at end of file
diff --git a/source/ct-Bot/bot-logic/behaviour_avoid_border.c b/source/ct-Bot/bot-logic/behaviour_avoid_border.c
new file mode 100644
index 0000000..9665b8d
--- /dev/null
+++ b/source/ct-Bot/bot-logic/behaviour_avoid_border.c
@@ -0,0 +1,41 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_avoid_border.c
+ * @brief Vermeide Abgruende
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+#include "bot-logic/bot-logik.h"
+
+#ifdef BEHAVIOUR_AVOID_BORDER_AVAILABLE
+/*!
+ * Verhindert, dass der Bot in Graeben faellt
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_avoid_border_behaviour(Behaviour_t *data){
+ if (sensBorderL > BORDER_DANGEROUS)
+ speedWishLeft=-BOT_SPEED_NORMAL;
+
+ if (sensBorderR > BORDER_DANGEROUS)
+ speedWishRight=-BOT_SPEED_NORMAL;
+}
+#endif
diff --git a/source/ct-Bot/bot-logic/behaviour_avoid_col.c b/source/ct-Bot/bot-logic/behaviour_avoid_col.c
new file mode 100644
index 0000000..a5c889a
--- /dev/null
+++ b/source/ct-Bot/bot-logic/behaviour_avoid_col.c
@@ -0,0 +1,142 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_avoid_col.c
+ * @brief Vermeide Kollisionen
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+
+#include "bot-logic/bot-logik.h"
+
+#ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
+
+#define ZONE_CLOSEST 0 /*!< Zone fuer extremen Nahbereich */
+#define ZONE_NEAR 1 /*!< Zone fuer Nahbereich */
+#define ZONE_FAR 2 /*!< Zone fuer Fernbereich */
+#define ZONE_CLEAR 3 /*!< Zone fuer Freien Bereich */
+
+#define BRAKE_CLOSEST -1.0 /*!< Bremsfaktor fuer extremen Nahbereich ( <1 ==> bremsen <0 ==> rueckwaerts) */
+#define BRAKE_NEAR 0.6 /*!< Bremsfaktor fuer Nahbereich ( <1 ==> bremsen <0 ==> rueckwaerts) */
+#define BRAKE_FAR 0.8 /*!< Bremsfaktor fuer Fernbereich ( <1 ==> bremsen <0 ==> rueckwaerts) */
+
+uint8 col_zone_l=ZONE_CLEAR; /*!< Kollisionszone, in der sich der linke Sensor befindet */
+uint8 col_zone_r=ZONE_CLEAR; /*!< Kollisionszone, in der sich der rechte Sensor befindet */
+
+
+/*!
+ * Passt auf, dass keine Kollision mit Hindernissen an der Front des Roboters
+ * geschieht.
+ * TODO: Diese Funktion ist nur ein Dummy-Beispiel, wie eine Kollisionsvermeidung aussehen
+ * koennte. Hier ist ein guter Einstiegspunkt fuer eigene Experimente und Algorithmen!
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_avoid_col_behaviour(Behaviour_t *data){
+ if (sensDistR < COL_CLOSEST) /* sehr nah */
+ col_zone_r=ZONE_CLOSEST; /* dann auf jeden Fall CLOSEST Zone */
+ else
+ /* sind wir naeher als NEAR und nicht in der inneren Zone gewesen */
+ if ((sensDistR < COL_NEAR) && (col_zone_r > ZONE_CLOSEST))
+ col_zone_r=ZONE_NEAR; /* dann auf in die NEAR-Zone */
+ else
+ /* sind wir naeher als FAR und nicht in der NEAR-Zone gewesen */
+ if ((sensDistR < COL_FAR) && (col_zone_r > ZONE_NEAR))
+ col_zone_r=ZONE_FAR; /* dann auf in die FAR-Zone */
+ else
+ /* wir waren in einer engeren Zone und verlassen sie in Richtung NEAR */
+ if (sensDistR < (COL_NEAR * 0.50))
+ col_zone_r=ZONE_NEAR; /* dann auf in die NEAR-Zone */
+ else
+ if (sensDistR < (COL_FAR * 0.50))
+ col_zone_r=ZONE_FAR; /* dann auf in die NEAR-Zone */
+ else
+ col_zone_r=ZONE_CLEAR; /* dann auf in die CLEAR-Zone */
+
+ if (sensDistL < COL_CLOSEST) /* sehr nah */
+ col_zone_l=ZONE_CLOSEST; /* dann auf jeden Fall CLOSEST-Zone */
+ else
+ /* sind wir naeher als NEAR und nicht in der inneren Zone gewesen */
+ if ((sensDistL < COL_NEAR) && (col_zone_l > ZONE_CLOSEST))
+ col_zone_l=ZONE_NEAR; /* dann auf in die NEAR-Zone */
+ else
+ /* sind wir naeher als FAR und nicht in der NEAR-Zone gewesen */
+ if ((sensDistL < COL_FAR) && (col_zone_l > ZONE_NEAR))
+ col_zone_l=ZONE_FAR; /* dann auf in die FAR-Zone */
+ else
+ /* wir waren in einer engeren Zone und verlassen sie in Richtung NEAR */
+ if (sensDistL < (COL_NEAR * 0.50))
+ col_zone_l=ZONE_NEAR; /* dann auf in die NEAR-Zone */
+ else
+ if (sensDistL < (COL_FAR * 0.50))
+ col_zone_l=ZONE_FAR; /* dann auf in die NEAR-Zone */
+ else
+ col_zone_l=ZONE_CLEAR; /* dann auf in die CLEAR-Zone */
+
+ // Nur reagieren, wenn der Bot vorwaerts faehrt
+ if ((speed_l > 0) && (speed_r >0)) {
+ // wenn auf beiden Seiten in der Kollisionszone
+ if ((col_zone_r == ZONE_CLOSEST)&&(col_zone_l == ZONE_CLOSEST)){
+ // Drehe Dich zur Seite, wo mehr Platz ist
+ if (sensDistR < sensDistL)
+ bot_turn(data,20);
+ else
+ bot_turn(data,-20);
+ return;
+ }
+
+ switch (col_zone_l){
+ case ZONE_CLOSEST:
+ faktorWishRight = BRAKE_CLOSEST;
+ break;
+ case ZONE_NEAR:
+ faktorWishRight = BRAKE_NEAR;
+ break;
+ case ZONE_FAR:
+ faktorWishRight = BRAKE_FAR;
+ break;
+ case ZONE_CLEAR:
+ faktorWishRight = 1;
+ break;
+ default:
+ col_zone_l = ZONE_CLEAR;
+ break;
+ }
+
+ switch (col_zone_r){
+ case ZONE_CLOSEST:
+ faktorWishLeft = BRAKE_CLOSEST;
+ break;
+ case ZONE_NEAR:
+ faktorWishLeft = BRAKE_NEAR;
+ break;
+ case ZONE_FAR:
+ faktorWishLeft = BRAKE_FAR;
+ break;
+ case ZONE_CLEAR:
+ faktorWishLeft = 1;
+ break;
+ default:
+ col_zone_r = ZONE_CLEAR;
+ break;
+ }
+ }
+}
+#endif
diff --git a/source/ct-Bot/bot-logic/behaviour_catch_pillar.c b/source/ct-Bot/bot-logic/behaviour_catch_pillar.c
new file mode 100644
index 0000000..efc0a4e
--- /dev/null
+++ b/source/ct-Bot/bot-logic/behaviour_catch_pillar.c
@@ -0,0 +1,106 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+
+/*! @file behaviour_catch_pillar.c
+ * @brief sucht nach einer Dose und fängt sie ein
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 08.12.06
+*/
+
+
+#include "bot-logic/bot-logik.h"
+#ifdef BEHAVIOUR_CATCH_PILLAR_AVAILABLE
+#include <math.h>
+
+#define MAX_PILLAR_DISTANCE 350
+
+#define START 0
+#define LEFT_FOUND 1
+#define TURN_MIDDLE 2
+#define GO 3
+
+static uint8 pillar_state=START;
+/*!
+ * Fange eine Dose ein
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_catch_pillar_behaviour(Behaviour_t *data){
+ static float angle;
+
+ switch (pillar_state){
+ case START:
+ if (sensDistL < MAX_PILLAR_DISTANCE){ // sieht der linke Sensor schon was?
+ angle=heading;
+ pillar_state=LEFT_FOUND;
+ } else
+ speedWishLeft=-BOT_SPEED_SLOW;
+ speedWishRight=+BOT_SPEED_SLOW;
+ //bot_turn(data,5); // Ein Stueck drehen
+ break;
+ case LEFT_FOUND:
+ if (sensDistR < MAX_PILLAR_DISTANCE){ // sieht der rechte Sensor schon was?
+ angle= heading- angle;
+ if (angle < 0)
+ angle+=360;
+ angle= heading - angle/2;
+ pillar_state=TURN_MIDDLE;
+// bot_turn(data,-angle/2);
+ }else
+ speedWishLeft=-BOT_SPEED_SLOW;
+ speedWishRight=+BOT_SPEED_SLOW;
+// bot_turn(data,5); // Eins Stueck drehen
+ break;
+ case TURN_MIDDLE:
+ if (fabs(heading - angle) > 2){
+ speedWishLeft=+BOT_SPEED_SLOW;
+ speedWishRight=-BOT_SPEED_SLOW;
+ } else {
+ bot_servo(data,SERVO1,DOOR_OPEN); // Klappe auf
+ pillar_state=GO;
+ }
+ break;
+ case GO:
+ if (sensTrans ==0){
+ speedWishLeft=+BOT_SPEED_SLOW;
+ speedWishRight=+BOT_SPEED_SLOW;
+ } else {
+ bot_servo(data,SERVO1,DOOR_CLOSE);
+ pillar_state++;
+ }
+ break;
+
+ default:
+ pillar_state=START;
+ return_from_behaviour(data);
+ break;
+ }
+}
+
+/*!
+ * Fange ein Objekt ein
+ * @param caller Der obligatorische Verhaltensdatensatz des Aufrufers
+ */
+void bot_catch_pillar(Behaviour_t * caller){
+ pillar_state=0;
+ // Zielwerte speichern
+ switch_to_behaviour(caller,bot_catch_pillar_behaviour,OVERRIDE);
+}
+#endif
diff --git a/source/ct-Bot/bot-logic/behaviour_drive_distance.c b/source/ct-Bot/bot-logic/behaviour_drive_distance.c
new file mode 100644
index 0000000..bb29e66
--- /dev/null
+++ b/source/ct-Bot/bot-logic/behaviour_drive_distance.c
@@ -0,0 +1,120 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_drive_distance.c
+ * @brief Bot faehrt ein Stueck
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+#include "bot-logic/bot-logik.h"
+#include "log.h"
+
+#ifdef BEHAVIOUR_DRIVE_DISTANCE_AVAILABLE
+
+
+/* Parameter fuer das bot_drive_distance_behaviour() */
+int16 drive_distance_target; /*!< Zu fahrende Distanz bzw. angepeilter Stand der Radencoder sensEncL bzw. sensEncR */
+int8 drive_distance_curve; /*!< Kruemmung der zu fahrenden Strecke. */
+int16 drive_distance_speed; /*!< Angepeilte Geschwindigkeit. */
+
+
+/*!
+ * laesst den Bot in eine Richtung fahren.
+ * Es handelt sich hierbei nicht im eigentlichen Sinn um ein Verhalten, sondern ist nur eine Abstraktion der Motorkontrollen.
+ * @param curve Gibt an, ob der Bot eine Kurve fahren soll. Werte von -127 (So scharf wie moeglich links) ueber 0 (gerade aus) bis 127 (so scharf wie moeglich rechts)
+ * @param speed Gibt an, wie schnell der Bot fahren soll. */
+void bot_drive(int8 curve, int16 speed){
+ // Wenn etwas ausgewichen wurde, bricht das Verhalten hier ab, sonst wuerde es evtl. die Handlungsanweisungen von bot_avoid_harm() stoeren.
+ //if(bot_avoid_harm()) return;
+ if(curve < 0) {
+ speedWishLeft = speed * (1.0 + 2.0*((float)curve/127));
+ speedWishRight = speed;
+ } else if (curve > 0) {
+ speedWishRight = speed * (1.0 - 2.0*((float)curve/127));
+ speedWishLeft = speed;
+ } else {
+ speedWishLeft = speed;
+ speedWishRight = speed;
+ }
+}
+
+/*!
+ * Das Verhalten laesst den Bot eine vorher festgelegte Strecke fahren.
+ * @param *data der Verhaltensdatensatz
+ * @see bot_drive_distance()
+ */
+void bot_drive_distance_behaviour(Behaviour_t* data){
+ int16 *encoder;
+ int16 to_drive;
+
+ if (drive_distance_curve > 0){
+ // Es handelt sich um eine Rechtskurve, daher wird mit dem linken Encoder gerechnet
+ encoder = (int16*)&sensEncL;
+ } else {
+ encoder = (int16*)&sensEncR;
+ }
+
+ to_drive = drive_distance_target - *encoder;
+ if(drive_distance_speed < 0) to_drive = -to_drive;
+
+ if(to_drive <= 0){
+ return_from_behaviour(data);
+ } else {
+ if((drive_distance_speed > BOT_SPEED_SLOW || drive_distance_speed < -BOT_SPEED_SLOW) && to_drive < (0.1 * ENCODER_MARKS)) bot_drive(drive_distance_curve, drive_distance_speed / 2);
+ else bot_drive(drive_distance_curve, drive_distance_speed);
+ }
+}
+
+
+
+/*!
+ * Das Verhalten laesst den Bot eine vorher festgelegte Strecke fahren. Dabei legt die Geschwindigkeit fest, ob der Bot vorwaerts oder rueckwaerts fahren soll.
+ * @param curve Gibt an, ob der Bot eine Kurve fahren soll. Werte von -127 (So scharf wie moeglich links) ueber 0 (gerade aus) bis 127 (so scharf wie moeglich rechts)
+ * @param speed Gibt an, wie schnell der Bot fahren soll. Negative Werte lassen den Bot rueckwaerts fahren.
+ * @param cm Gibt an, wie weit der Bot fahren soll. In cm :-) Die Strecke muss positiv sein, die Fahrtrichtung wird ueber speed geregelt.
+ */
+void bot_drive_distance(Behaviour_t* caller,int8 curve, int16 speed, int16 cm){
+// LOG_DEBUG(("curve= %d, speed= %d, cm =%d",curve, speed, cm));
+
+ int32 tmp = cm;
+ tmp*= 10 * ENCODER_MARKS;
+ tmp /= WHEEL_PERIMETER;
+ int16 marks_to_drive = (int16) tmp;
+
+ int16 *encoder;
+ drive_distance_curve = curve;
+ drive_distance_speed = speed;
+
+ if (curve > 0){
+ // Es handelt sich um eine Rechtskurve, daher wird mit dem linken Encoder gerechnet
+ encoder = (int16*)&sensEncL;
+ } else {
+ encoder = (int16*)&sensEncR;
+ }
+ if(speed < 0){
+ // Es soll rueckwaerts gefahren werden. Der Zielwert ist also kleiner als der aktuelle Encoder-Stand.
+ drive_distance_target = *encoder - marks_to_drive;
+ } else {
+ drive_distance_target = *encoder + marks_to_drive;
+ }
+ switch_to_behaviour(caller, bot_drive_distance_behaviour,NOOVERRIDE);
+}
+#endif
diff --git a/source/ct-Bot/bot-logic/behaviour_drive_square.c b/source/ct-Bot/bot-logic/behaviour_drive_square.c
new file mode 100644
index 0000000..7c2a924
--- /dev/null
+++ b/source/ct-Bot/bot-logic/behaviour_drive_square.c
@@ -0,0 +1,76 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_drive_square.c
+ * @brief Bot faehrt im Quadrat
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+
+#include "bot-logic/bot-logik.h"
+
+#ifdef BEHAVIOUR_DRIVE_SQUARE_AVAILABLE
+/*!
+ * Laesst den Roboter ein Quadrat abfahren.
+ * Einfaches Beispiel fuer ein Verhalten, das einen Zustand besitzt.
+ * Es greift auf andere Behaviours zurueck und setzt daher
+ * selbst keine speedWishes.
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_drive_square_behaviour(Behaviour_t *data){
+ #define STATE_TURN 1
+ #define STATE_FORWARD 0
+ #define STATE_INTERRUPTED 2
+
+ static uint8 state = STATE_FORWARD;
+
+ if (data->subResult == SUBFAIL) // letzter Auftrag schlug fehl?
+ state= STATE_INTERRUPTED;
+
+ switch (state) {
+ case STATE_FORWARD: // Vorwaerts
+ bot_goto(data,100,100);
+ state = STATE_TURN;
+ break;
+ case STATE_TURN: // Drehen
+ bot_goto(data,22,-22);
+ state=STATE_FORWARD;
+ break;
+ case STATE_INTERRUPTED:
+ return_from_behaviour(data); // Beleidigt sein und sich selbst deaktiviern
+ break;
+
+ default: /* Sind wir fertig, dann Kontrolle zurueck an Aufrufer */
+ return_from_behaviour(data);
+ break;
+ }
+}
+
+/*!
+ * Laesst den Roboter ein Quadrat abfahren.
+ * @param caller Der obligatorische Verhaltensdatensatz des aufrufers
+ */
+void bot_drive_square(Behaviour_t* caller){
+ switch_to_behaviour(caller, bot_drive_square_behaviour,OVERRIDE);
+}
+
+
+#endif
diff --git a/source/ct-Bot/bot-logic/behaviour_follow_line.c b/source/ct-Bot/bot-logic/behaviour_follow_line.c
new file mode 100644
index 0000000..e35b16f
--- /dev/null
+++ b/source/ct-Bot/bot-logic/behaviour_follow_line.c
@@ -0,0 +1,176 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_follow_line.c
+ * @brief Linienverfolger
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+#include "bot-logic/bot-logik.h"
+
+#ifdef BEHAVIOUR_FOLLOW_LINE_AVAILABLE
+
+/*! Folgt einer Linie, sobald beide Liniensensoren ausloesen
+ * Die Linie sollte in etwa die Breite beider CNY70 haben
+ */
+void bot_follow_line_behaviour(Behaviour_t *data) {
+ /* Konstanten fuer das Verhalten */
+ #define CORNER_LEFT 1
+ #define CORNER_RIGHT 2
+ /* Zustaende fuer das Verhalten */
+ #define CHECK_LINE 0 /* !< Feststellen ob wir ueber einer Linie sind */
+ #define FOLLOW_LINE 1 /* !< Folgen einer geraden oder leicht gekruemmten Linie */
+ #define CHECK_BORDER 2 /* !< Abgrundsensoren haben Alarm geschlagen. Feststellen ob wirklich Abgrund oder Ecke */
+ #define CORNER_TURN 3 /* !< Drehung in Richtun detektiertem Abgrund */
+ #define CORRECT_POS 4 /* !< Nach der Drehung 1cm vorfahren zum Ausgleichen */
+ #define ADVANCE_CORNER 5 /* !< Auf die Ecke zufahren, bis die Linie verschwindet */
+ #define RETREAT_AND_STOP 6 /* !< Zurueckfahren mit voller Geschwindigkeit, dann Stop und Verhalten verlassen */
+
+ /* Status- und Hilfsvariablen */
+ static int8 lineState=CHECK_LINE;
+ static int8 cornerDetected=False;
+
+ switch(lineState) {
+ case CHECK_LINE: /* sind beide Sensoren ueber einer Linie? */
+ if (sensLineL>=LINE_SENSE && sensLineR>=LINE_SENSE) {
+ /* zunaechst alle Hilfsverhalten ausschalten, die den Algorithmus stoeren */
+ /* Abgrund- und Kollisions-Verhalten ausschalten */
+ #ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
+ deactivateBehaviour(bot_avoid_col_behaviour);
+ #endif
+ #ifdef BEHAVIOUR_AVOID_BORDER_AVAILABLE
+ deactivateBehaviour(bot_avoid_border_behaviour);
+ #endif
+ /* bot_glance() stoert bot_turn() */
+ //deactivateBehaviour(bot_glance_behaviour);
+ /* losfahren und nach FOLLOW_LINE wechseln */
+ speedWishLeft=BOT_SPEED_FOLLOW;
+ speedWishRight=BOT_SPEED_FOLLOW;
+ lineState=FOLLOW_LINE;
+ }
+ break;
+
+ case FOLLOW_LINE:
+ /* Pruefen, ob die Abgrundsensoren einen Abgrund sehen */
+ if (sensBorderL>BORDER_DANGEROUS || sensBorderR>BORDER_DANGEROUS) {
+ /* Abgrund erkannt, das kann jetzt eine Linie sein oder ein richtiger Abgrund.*/
+ if (sensBorderL>BORDER_DANGEROUS && sensBorderR>BORDER_DANGEROUS) {
+ /* Wenn beidseitig erkannt, koennen wir damit nicht umgehen ->
+ * Ende des Verhaltens */
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ lineState=CHECK_LINE; /* Verhaltensstatus zuruecksetzen */
+ //LOG_INFO(("Stopp in FOLLOW_LINE"));
+ return_from_behaviour(data);
+ break;
+ }
+ /* nachsehen, ob der linke oder rechte Liniensensor ohne Kontakt zur Linie ist
+ * und ggfs. gegensteuern */
+ if (sensBorderL>BORDER_DANGEROUS) {
+ cornerDetected=CORNER_LEFT;
+ } else {
+ cornerDetected=CORNER_RIGHT;
+ }
+ /* nun zur vermuteten Ecke vorfahren */
+ lineState=CHECK_BORDER;
+ bot_drive_distance(data,0,BOT_SPEED_FOLLOW,3);
+ break;
+ }
+ if (sensLineL<LINE_SENSE && sensLineR>LINE_SENSE) {
+ /* links von der Linie abgekommen, daher nach rechts drehen */
+ //LOG_DEBUG(("Drehe rechts"));
+ speedWishLeft=BOT_SPEED_FOLLOW;
+ speedWishRight=-BOT_SPEED_FOLLOW;
+ } else if (sensLineL>LINE_SENSE && sensLineR<LINE_SENSE) {
+ /* andersrum, also links drehen */
+ //LOG_DEBUG(("Drehe links"));
+ speedWishLeft=-BOT_SPEED_FOLLOW;
+ speedWishRight=BOT_SPEED_FOLLOW;
+ } else if (sensLineL>LINE_SENSE && sensLineR>LINE_SENSE) {
+ /* noch ueber der Linie, also einfach geradeaus weiter */
+ //LOG_DEBUG(("Fahre geradeaus"));
+ speedWishLeft=BOT_SPEED_FOLLOW;
+ speedWishRight=BOT_SPEED_FOLLOW;
+ }
+ break;
+
+ case CHECK_BORDER:
+ /* wir sollten jetzt direkt an der Kante zum Abgrund stehen, wenn es
+ * denn wirklich eine ist. In dem Fall fahren wir ein Stueck zurueck.
+ * sonst gehen wir von einer Linie aus, drehen uns in die Richtung,
+ * in der wir den "Abgrund" entdeckt haben und machen dann weiter mit
+ * der Linienverfolgung */
+ if (sensBorderL>BORDER_DANGEROUS || sensBorderR>BORDER_DANGEROUS) {
+ /* scheint wirklich ein Abgrund zu sein */
+ lineState=RETREAT_AND_STOP;
+ speedWishLeft=-BOT_SPEED_MAX;
+ speedWishRight=-BOT_SPEED_MAX;
+ break;
+ }
+ /* war nur eine Ecke, noch weiter darauf zu bis kein Kontakt mehr zur Linie */
+ lineState=ADVANCE_CORNER;
+ speedWishLeft=BOT_SPEED_FOLLOW;
+ speedWishRight=BOT_SPEED_FOLLOW;
+ break;
+
+ case ADVANCE_CORNER:
+ /* auf die Ecke zufahren, bis die Linie verschwindet */
+ if (sensLineL<LINE_SENSE && sensLineR<LINE_SENSE) {
+ /* Linie weg, also Stop, kurz zurueck und drehen */
+ lineState=CORNER_TURN;
+ speedWishLeft=-BOT_SPEED_SLOW;
+ speedWishRight=-BOT_SPEED_SLOW;
+ break;
+ }
+ speedWishLeft=BOT_SPEED_FOLLOW;
+ speedWishRight=BOT_SPEED_FOLLOW;
+ break;
+
+ case CORNER_TURN:
+ /* 90� in Richtung des detektierten Abgrunds drehen */
+ lineState=CORRECT_POS;
+ bot_turn(data,(cornerDetected==CORNER_LEFT)?90:-90);
+ cornerDetected=False;
+ break;
+
+ case CORRECT_POS:
+ lineState=FOLLOW_LINE;
+ bot_drive_distance(data,0,BOT_SPEED_SLOW,2);
+ break;
+
+ case RETREAT_AND_STOP:
+ /* wir sind an einem Abgrund, Stop und Ende des Verhaltens */
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ cornerDetected=False;
+ lineState=CHECK_LINE;
+ return_from_behaviour(data);
+ break;
+ }
+}
+
+/*! Folgt einer Linie, sobald beide Liniensensoren ausloesen
+ * Die Linie sollte in etwa die Breite beider CNY70 haben
+ */
+void bot_follow_line(Behaviour_t *caller) {
+ switch_to_behaviour(caller, bot_follow_line_behaviour,NOOVERRIDE);
+}
+#endif
diff --git a/source/ct-Bot/bot-logic/behaviour_goto.c b/source/ct-Bot/bot-logic/behaviour_goto.c
new file mode 100644
index 0000000..9b655a4
--- /dev/null
+++ b/source/ct-Bot/bot-logic/behaviour_goto.c
@@ -0,0 +1,141 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_goto.c
+ * @brief Bot faehrt einen punkt an
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+
+
+#include "bot-logic/bot-logik.h"
+
+#ifdef BEHAVIOUR_GOTO_AVAILABLE
+#include <stdlib.h>
+
+
+#define MOT_GOTO_MAX 4 /*!< Richtungsaenderungen, bis goto erreicht sein muss */
+#define GOTO_REACHED 2 /*!< Wenn Encoder-Distanz <= GOTO_REACHED dann stop */
+#define GOTO_SLOW 4 /*!< Wenn Encoder-Distanz < GOTO_SLOW dann langsame Fahrt */
+#define GOTO_NORMAL 10 /*!< Wenn Encoder-Distanz < GOTO_NORMAL dann normale Fahrt */
+#define GOTO_FAST 40 /*!< Wenn Encoder-Distanz < GOTO_FAST dann schnelle Fahrt, sonst maximale Fahrt */
+
+
+int16 mot_l_goto=0; /*!< Speichert wie weit der linke Motor drehen soll */
+int16 mot_r_goto=0; /*!< Speichert wie weit der rechte Motor drehen soll */
+
+
+/*!
+ * Kuemmert sich intern um die Ausfuehrung der goto-Kommandos,
+ * @param *data der Verhaltensdatensatz
+ * @see bot_goto()
+ */
+void bot_goto_behaviour(Behaviour_t *data){
+ static int16 mot_goto_l=0; /*!< Muss der linke Motor noch drehen? */
+ static int16 mot_goto_r=0; /*!< Muss der rechte Motor noch drehen? */
+
+ int16 diff_l; /* Restdistanz links */
+ int16 diff_r; /* Restdistanz rechts */
+
+ /* Sind beide Zaehler Null und ist die Funktion active
+ * -- sonst waeren wir nicht hier --
+ * so ist dies der erste Aufruf ==> initialisieren */
+ if (( mot_goto_l ==0) && ( mot_goto_r ==0)){
+ /* Zaehler einstellen */
+ if (mot_l_goto !=0)
+ mot_goto_l= MOT_GOTO_MAX;
+ if (mot_r_goto !=0)
+ mot_goto_r=MOT_GOTO_MAX;
+
+ /* Encoder zuruecksetzen */
+ sensEncL=0;
+ sensEncR=0;
+ }
+
+ /* Motor L hat noch keine MOT_GOTO_MAX Nulldurchgaenge gehabt */
+ if (mot_goto_l >0){
+ diff_l = sensEncL - mot_l_goto; /* Restdistanz links */
+
+ if (abs(diff_l) <= GOTO_REACHED){ /* 2 Encoderstaende Genauigkeit reicht */
+ speedWishLeft = BOT_SPEED_STOP; /* Stop */
+ mot_goto_l--; /* wie Nulldurchgang behandeln */
+ }else if (abs(diff_l) < GOTO_SLOW)
+ speedWishLeft= BOT_SPEED_SLOW;
+ else if (abs(diff_l) < GOTO_NORMAL)
+ speedWishLeft= BOT_SPEED_NORMAL;
+ else if (abs(diff_l) < GOTO_FAST)
+ speedWishLeft= BOT_SPEED_FAST;
+ else speedWishLeft= BOT_SPEED_MAX;
+
+ // Richtung
+ if (diff_l>0) { // Wenn uebersteuert,
+ speedWishLeft= -speedWishLeft; //Richtung umkehren
+ }
+
+ // Wenn neue Richtung ungleich alter Richtung
+ if (((speedWishLeft<0)&& (direction.left == DIRECTION_FORWARD))|| ( (speedWishLeft>0) && (direction.left == DIRECTION_BACKWARD) ) )
+ mot_goto_l--; // Nulldurchgang merken
+ }
+
+ // Motor R hat noch keine MOT_GOTO_MAX Nulldurchgaenge gehabt
+ if (mot_goto_r >0){
+ diff_r = sensEncR - mot_r_goto; /* Restdistanz rechts */
+
+ if (abs(diff_r) <= GOTO_REACHED){ // 2 Encoderstaende Genauigkeit reicht
+ speedWishRight = BOT_SPEED_STOP; //Stop
+ mot_goto_r--; // wie Nulldurchgang behandeln
+ }else if (abs(diff_r) < GOTO_SLOW)
+ speedWishRight= BOT_SPEED_SLOW;
+ else if (abs(diff_r) < GOTO_NORMAL)
+ speedWishRight= BOT_SPEED_NORMAL;
+ else if (abs(diff_r) < GOTO_FAST)
+ speedWishRight= BOT_SPEED_FAST;
+ else speedWishRight= BOT_SPEED_MAX;
+
+ // Richtung
+ if (diff_r>0) { // Wenn uebersteurt,
+ speedWishRight= -speedWishRight; //Richtung umkehren
+ }
+
+ // Wenn neue Richtung ungleich alter Richtung
+ if (((speedWishRight<0)&& (direction.right == DIRECTION_FORWARD))|| ( (speedWishRight>0) && (direction.right == DIRECTION_BACKWARD) ) )
+ mot_goto_r--; // Nulldurchgang merken
+ }
+
+ /* Sind wir fertig, dann Regel deaktivieren */
+ if ((mot_goto_l == 0) && (mot_goto_r == 0)){
+ return_from_behaviour(data);
+ }
+}
+
+/*!
+ * Drehe die Raeder um die gegebene Zahl an Encoder-Schritten weiter
+ * @param left Schritte links
+ * @param right Schritte rechts
+ */
+void bot_goto(Behaviour_t * caller, int16 left, int16 right){
+ // Zielwerte speichern
+ mot_l_goto=left;
+ mot_r_goto=right;
+
+ switch_to_behaviour(caller,bot_goto_behaviour,OVERRIDE);
+}
+#endif
diff --git a/source/ct-Bot/bot-logic/behaviour_gotoxy.c b/source/ct-Bot/bot-logic/behaviour_gotoxy.c
new file mode 100644
index 0000000..f5190ae
--- /dev/null
+++ b/source/ct-Bot/bot-logic/behaviour_gotoxy.c
@@ -0,0 +1,141 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_gotoxy.c
+ * @brief Bot faehrt eine Position an
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+#include "bot-logic/bot-logik.h"
+
+#ifdef BEHAVIOUR_GOTOXY_AVAILABLE
+#include <math.h>
+
+
+
+
+/* Parameter fuer bot_gotoxy_behaviour-Verhalten */
+float target_x; /*!< Zielkoordinate X */
+float target_y; /*!< Zielkoordinate Y */
+float initialDiffX; /*!< Anfangsdifferenz in X-Richtung */
+float initialDiffY; /*!< Anfangsdifferenz in Y-Richtung */
+
+
+/*!
+ * Auslagerung der Berechnung der benoetigten Drehung aus dem gotoxy_behaviour
+ * @param xDiff
+ * @param yDiff
+ */
+int16 bot_gotoxy_calc_turn(float xDiff, float yDiff){
+ float newHeading;
+ if(fabs(yDiff)>0.001 && fabs(xDiff)>0.001){
+ newHeading=atan(yDiff/xDiff)*180/(M_PI);
+ if (xDiff<0)
+ newHeading+=180;
+ } else{
+ if(fabs(xDiff)<=0.001)
+ newHeading=(yDiff>0)?90:(-90);
+ else
+ newHeading=(xDiff>0)?0:(180);
+ }
+
+ int16 toTurn=(int16)newHeading-heading;
+ if (toTurn > 180) toTurn-=360;
+ if (toTurn < -180) toTurn+=360;
+
+ return toTurn;
+}
+
+/*!
+ * Das Verhalten faehrt von der aktuellen Position zur angegebenen Position (x/y)
+ * @param *data der Verhaltensdatensatz
+ * Verbessert von Thomas Noll, Jens Schoemann, Ben Horst (Philipps-Universitaet Marburg)
+ */
+void bot_gotoxy_behaviour(Behaviour_t *data){
+ #define INITIAL_TURN 0
+ #define GOTO_LOOP 1
+ #define CORRECT_HEAD 2
+ #define REACHED_POS 3
+ static int16 speedLeft=BOT_SPEED_FOLLOW;
+ static int16 speedRight=BOT_SPEED_FOLLOW;
+ static int8 gotoState=INITIAL_TURN;
+ /* aus aktueller Position und Ziel neuen Zielwinkel berechnen */
+ float xDiff=target_x-x_pos;
+ float yDiff=target_y-y_pos;
+
+ if(xDiff*initialDiffX <0 || yDiff*initialDiffY <0){ // Hier kann noch verbessert werden
+ gotoState=REACHED_POS; // z.B. Abfragen statt *-Operation
+ speedWishLeft=BOT_SPEED_STOP; // bzw. neue Drehung statt Stehenbleiben
+ speedWishRight=BOT_SPEED_STOP;
+ }
+
+
+ switch(gotoState) {
+ case INITIAL_TURN:
+ gotoState=GOTO_LOOP;
+ bot_turn(data,bot_gotoxy_calc_turn(xDiff,yDiff));
+ break;
+
+ case GOTO_LOOP:
+ /* Position erreicht? */
+ if ((xDiff)<10 || (yDiff)<10) {
+ gotoState=CORRECT_HEAD;
+ bot_turn(data,bot_gotoxy_calc_turn(xDiff,yDiff));
+ break;
+ }
+ speedWishLeft=speedLeft;
+ speedWishRight=speedRight;
+ break;
+
+ case CORRECT_HEAD:
+ /* Position erreicht? */
+ if ((xDiff)<3 && (yDiff)<3) {
+ gotoState=REACHED_POS;
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ break;
+ }
+ speedWishLeft=BOT_SPEED_SLOW;
+ speedWishRight=BOT_SPEED_SLOW;
+ break;
+
+ case REACHED_POS:
+ gotoState=INITIAL_TURN;
+ return_from_behaviour(data);
+ break;
+ }
+
+}
+
+/*!
+ * Botenfunktion: Das Verhalten faehrt von der aktuellen Position zur angegebenen Position (x/y)
+ * @param caller Aufrufendes Verhalten
+ * @param x X-Ordinate an die der Bot fahren soll
+ * @param y Y-Ordinate an die der Bot fahren soll
+ */
+void bot_gotoxy(Behaviour_t *caller, float x, float y){
+ target_x=x;
+ target_y=y;
+ initialDiffX=x-x_pos;
+ initialDiffY=y-y_pos;
+ switch_to_behaviour(caller, bot_gotoxy_behaviour, NOOVERRIDE);
+}
+#endif
diff --git a/source/ct-Bot/bot-logic/behaviour_olympic.c b/source/ct-Bot/bot-logic/behaviour_olympic.c
new file mode 100644
index 0000000..2c6e853
--- /dev/null
+++ b/source/ct-Bot/bot-logic/behaviour_olympic.c
@@ -0,0 +1,428 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_olympic.c
+ * @brief Bot sucht saeulen und faehrt dann slalom
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+#include "bot-logic/bot-logik.h"
+
+#ifdef BEHAVIOUR_OLYMPIC_AVAILABLE
+#include <stdlib.h>
+
+/* Zustaende des bot_explore-Verhaltens */
+
+#define EXPLORATION_STATE_GOTO_WALL 1 /*!< Zustand: Bot sucht eine Wand o.ae. Hinderniss */
+#define EXPLORATION_STATE_TURN_PARALLEL_LEFT 2 /*!< Zustand: Bot dreht sich nach links, bis er parallel zur Wand blickt. */
+#define EXPLORATION_STATE_TURN_PARALLEL_RIGHT 3 /*!< Zustand: Bot dreht sich nach rechts, bis er parallel zur Wand blickt. */
+#define EXPLORATION_STATE_DRIVE_PARALLEL_LEFT 4 /*!< Zustand: Bot faehrt parallel zur Wand links von sich. */
+#define EXPLORATION_STATE_DRIVE_PARALLEL_RIGHT 5 /*!< Zustand: Bot faehrt parallel zur Wand rechts von sich. */
+#define EXPLORATION_STATE_TURN_ORTHOGONAL_LEFT 6 /*!< Zustand: Bot dreht sich nach links, bis er senkrecht zur Wand steht. */
+#define EXPLORATION_STATE_TURN_ORTHOGONAL_RIGHT 7 /*!< Zustand: Bot dreht sich nach rechts, bis er senkrecht zur Wand steht. */
+#define EXPLORATION_STATE_DRIVE_ARC 8 /*!< Zustand: Bot faehrt einen Bogen. Der Winkel des Bogens sollte in einer
+ *!< weiteren static Variablen (z.B. curve) gespeichert sein. */
+
+/* Zustaende des bot_olympic_behaviour-Verhaltens */
+
+#define CB_STATE_EXPLORATION 0 /*!< Zustand: Bot erforscht die Umgebung. */
+#define CB_STATE_DOING_SLALOM 1 /*!< Zustand: Bot ist dabei Slalom zu fahren. */
+
+/* Zustaende des bot_do_slalom-Verhaltens */
+
+#define SLALOM_STATE_START 0 /*!< Zustand: Bot startet eine Slalomlauf und positioniert sich vor der Saeule. */
+#define SLALOM_STATE_TURN_1 1 /*!< Zustand: Bot dreht sich um 90�. */
+#define SLALOM_STATE_DRIVE_ARC 2 /*!< Zustand: Bot faehrt den Bogen um die Saeule. */
+#define SLALOM_STATE_TURN_2 3 /*!< Zustand: Bot dreht sich fuer den Sweep um 45�. */
+#define SLALOM_STATE_SWEEP_RUNNING 4 /*!< Zustand: Bot macht den Sweep. */
+#define SLALOM_STATE_SWEEP_DONE 5 /*!< Zustand: Bot ist fertig mit dem Sweep. */
+#define SLALOM_STATE_CHECK_PILLAR 6 /*!< Zustand: Bot ueberprueft, ob er den Slalom fortsetzen kann. */
+
+#define SLALOM_ORIENTATION_LEFT 0
+#define SLALOM_ORIENTATION_RIGHT 1
+
+/* Parameter fuer das bot_explore_behaviour() */
+int8 (*exploration_check_function)(void); /*!< Die Funktion, mit der das bot_explore_behaviour() feststellt, ob es etwas gefunden hat.
+ * Die Funktion muss True (1) zurueck geben, wenn dem so ist, sonst False (0).
+ * Beispiele fuer eine solche Funktion sind check_for_light, is_good_pillar_ahead etc.*/
+
+
+
+
+/*!
+ * Das Verhalten dreht den Bot so, dass er auf eine Lichtquelle zufaehrt. */
+void bot_goto_light(void){
+ int16 speed, curve = (sensLDRL - sensLDRR)/1.5;
+
+ if(curve < -127) curve = -127;
+ if(curve > 127) curve = 127;
+
+ if(abs(sensLDRL - sensLDRR) < 20){
+ speed = BOT_SPEED_MAX;
+ }else if(abs(sensLDRL - sensLDRR) < 150) {
+ speed = BOT_SPEED_FAST;
+ }else {
+ speed = BOT_SPEED_NORMAL;
+ }
+
+ bot_drive(curve, speed);
+}
+
+
+
+/*!
+ * Gibt aus, ob der Bot Licht sehen kann.
+ * @return True, wenn der Bot Licht sieht, sonst False. */
+int8 check_for_light(void){
+ // Im Simulator kann man den Bot gut auf den kleinsten Lichtschein
+ // reagieren lassen, in der Realitaet gibt es immer Streulicht, so dass
+ // hier ein hoeherer Schwellwert besser erscheint.
+ // Simulator:
+ if(sensLDRL >= 1023 && sensLDRR >= 1023) return False;
+ // Beim echten Bot eher:
+ // if(sensLDRL >= 100 && sensLDRR >= 100) return False;
+
+ else return True;
+}
+
+/*!
+ * Die Funktion gibt aus, ob sich innerhalb einer gewissen Entfernung ein Objekt-Hindernis befindet.
+ * @param distance Entfernung in mm, bis zu welcher ein Objekt gesichtet wird.
+ * @return Gibt False (0) zurueck, wenn kein Objekt innerhalb von distance gesichtet wird. Ansonsten die Differenz
+ * zwischen dem linken und rechten Sensor. Negative Werte besagen, dass das Objekt naeher am linken, positive, dass
+ * es naeher am rechten Sensor ist. Sollten beide Sensoren den gleichen Wert haben, gibt die Funktion 1 zurueck, um
+ * von False unterscheiden zu koennen. */
+int16 is_obstacle_ahead(int16 distance){
+ if(sensDistL > distance && sensDistR > distance) return False;
+ if(sensDistL - sensDistR == 0) return 1;
+ else return (sensDistL - sensDistR);
+}
+
+/*!
+ * Gibt aus, ob der Bot eine fuer sein Slalomverhalten geeignete Saeule vor sich hat.
+ * @return True, wenn er eine solche Saeule vor sich hat, sonst False.*/
+int8 is_good_pillar_ahead(void){
+ if(is_obstacle_ahead(COL_NEAR) != False && sensLDRL < 600 && sensLDRR < 600) return True;
+ else return False;
+}
+
+/*!
+ * Das Verhalten verhindert, dass dem Bot boese Dinge wie Kollisionen oder Abstuerze widerfahren.
+ * @return Bestand Handlungsbedarf? True, wenn das Verhalten ausweichen musste, sonst False.
+ * TODO: Parameter einfuegen, der dem Verhalten vorschlaegt, wie zu reagieren ist.
+ * */
+int8 bot_avoid_harm(void){
+ if(is_obstacle_ahead(COL_CLOSEST) != False || sensBorderL > BORDER_DANGEROUS || sensBorderR > BORDER_DANGEROUS){
+ speedWishLeft = -BOT_SPEED_NORMAL;
+ speedWishRight = -BOT_SPEED_NORMAL;
+ return True;
+ } else return False;
+}
+
+/*!
+ * Das Verhalten laesst den Roboter den Raum durchsuchen.
+ * Das Verhalten hat mehrere unterschiedlich Zustaende:
+ * 1. Zu einer Wand oder einem anderen Hindernis fahren.
+ * 2. Zu einer Seite drehen, bis der Bot parallel zur Wand ist.
+ * Es macht vielleicht Sinn, den Maussensor auszulesen, um eine Drehung um
+ * einen bestimmten Winkel zu realisieren. Allerdings muesste dafuer auch der
+ * Winkel des Bots zur Wand bekannt sein.
+ * 3. Eine feste Strecke parallel zur Wand vorwaerts fahren.
+ * Da bot_glance_behaviour abwechselnd zu beiden Seiten schaut, ist es fuer die Aufgabe,
+ * einer Wand auf einer Seite des Bots zu folgen, nur bedingt gewachsen und muss
+ * evtl. erweitert werden.
+ * 4. Senkrecht zur Wand drehen.
+ * Siehe 2.
+ * 5. Einen Bogen fahren, bis der Bot wieder auf ein Hindernis stoesst.
+ * Dann das Ganze von vorne beginnen, nur in die andere Richtung und mit einem
+ * weiteren Bogen. So erforscht der Bot einigermassen systematisch den Raum.
+ *
+ * Da das Verhalten jeweils nach 10ms neu aufgerufen wird, muss der Bot sich
+ * 'merken', in welchem Zustand er sich gerade befindet.
+ * */
+void bot_explore_behaviour(Behaviour_t *data){
+ static int8 curve = 0,state = EXPLORATION_STATE_GOTO_WALL, running_curve = False;
+
+ if((*exploration_check_function)()) return_from_behaviour(data);
+
+ switch(state){
+ // Volle Fahrt voraus, bis ein Hindernis erreicht ist.
+ case EXPLORATION_STATE_GOTO_WALL:
+ // Der Bot steht jetzt vor einem Hindernis und soll sich nach rechts drehen
+ if(bot_avoid_harm()) {
+ state = EXPLORATION_STATE_TURN_PARALLEL_RIGHT;
+ #ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
+ deactivateBehaviour(bot_avoid_col_behaviour);
+ #endif
+ }
+ // Es befindet sich kein Hindernis direkt vor dem Bot.
+ else {
+ if(sensDistL < COL_NEAR || sensDistR < COL_NEAR){
+ bot_drive(0,BOT_SPEED_FAST);
+ } else {
+ bot_drive(0,BOT_SPEED_MAX);
+ }
+ }
+ break;
+ // Nach links drehen, bis der Bot parallel zum Hindernis auf der rechten Seite steht.
+ /* TODO: Aufgabe: Entwickle ein Verhalten, dass auch bei Loechern funktioniert.
+ * Tipp dazu: Drehe den Roboter auf das Loch zu, bis beide Bodensensoren das Loch 'sehen'. Anschliessend drehe den Bot um 90 Grad.
+ * Es ist noetig, neue Zustaende zu definieren, die diese Zwischenschritte beschreiben.
+ * TODO: Drehung mit dem Maussensor ueberwachen. */
+ case EXPLORATION_STATE_TURN_PARALLEL_LEFT:
+ if(sensDistR < COL_FAR){
+ // Volle Drehung nach links mit ca. 3Grad/10ms
+ bot_drive(-127,BOT_SPEED_FAST);
+ } else {
+ // Nachdem das Hindernis nicht mehr in Sicht ist, dreht der Bot noch ca. 3 Grad weiter.
+ // Im Zweifelsfall dreht das den Bot zu weit, aber das ist besser, als ihn zu kurz zu drehen.
+ bot_drive(-127,BOT_SPEED_FAST);
+ state = EXPLORATION_STATE_DRIVE_PARALLEL_RIGHT;
+ }
+ break;
+ // Nach rechts drehen, bis der Bot parallel zum Hindernis auf der linken Seite steht.
+ /* Aufgabe: siehe EXPLORATION_STATE_TURN_PARALLEL_LEFT */
+ case EXPLORATION_STATE_TURN_PARALLEL_RIGHT:
+ if(sensDistL < COL_FAR){
+ // Volle Drehung nach rechts mit ca. 3Grad/10ms
+ bot_drive(127,BOT_SPEED_FAST);
+ } else {
+ /* Nachdem das Hindernis nicht mehr in Sicht ist, dreht der Bot noch ca. 3 Grad weiter.
+ * Im Zweifelsfall dreht das den Bot zu weit, aber das ist besser, als ihn zu kurz zu drehen. */
+ bot_drive(127,BOT_SPEED_FAST);
+ state = EXPLORATION_STATE_DRIVE_PARALLEL_LEFT;
+ }
+ break;
+ case EXPLORATION_STATE_DRIVE_PARALLEL_LEFT:
+ bot_drive_distance(data,0,BOT_SPEED_FAST,15);
+ state = EXPLORATION_STATE_TURN_ORTHOGONAL_RIGHT;
+ break;
+ case EXPLORATION_STATE_DRIVE_PARALLEL_RIGHT:
+ bot_drive_distance(data,0,BOT_SPEED_FAST,15);
+ state = EXPLORATION_STATE_TURN_ORTHOGONAL_LEFT;
+ break;
+ case EXPLORATION_STATE_TURN_ORTHOGONAL_LEFT:
+ // Drehe den Bot um 90 Grad nach links.
+ /* Da der Bot sich immer ein bisschen zu weit von der Wand weg dreht, soll er sich
+ * hier nur um 85 Grad drehen. Nicht schoen, aber klappt.*/
+ bot_turn(data,85);
+ state = EXPLORATION_STATE_DRIVE_ARC;
+ #ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
+ activateBehaviour(bot_avoid_col_behaviour);
+ #endif
+ break;
+ case EXPLORATION_STATE_TURN_ORTHOGONAL_RIGHT:
+ // Drehe den Bot um 90 Grad nach rechts.
+ /* Da der Bot sich immer ein bisschen zu weit von der Wand weg dreht, soll er sich
+ * hier nur um 85 Grad drehen. Nicht schoen, aber klappt.*/
+ bot_turn(data,-85);
+ state = EXPLORATION_STATE_DRIVE_ARC;
+ #ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
+ activateBehaviour(bot_avoid_col_behaviour);
+ #endif
+ break;
+ case EXPLORATION_STATE_DRIVE_ARC:
+ /* Fahre einen Bogen.
+ * Der Bot soll im Wechsel Links- und Rechtsboegen fahren. Daher muss das Vorzeichen von curve wechseln.
+ * Ausserdem soll der Bogen zunehmend weiter werden, so dass der absolute Wert von curve abnehmen muss.
+ * Ist der Wert 0, wird er auf den engsten Bogen initialisiert. Da der Bot am Anfang nach rechts abbiegt,
+ * muss der Wert positiv sein.
+ * Aufgabe: Manchmal kann es passieren, dass der Bot bei einer kleinen Kurve zu weit weg von der Wand
+ * startet und dann nur noch im Kreis faehrt. Unterbinde dieses Verhalten.
+ */
+ if(curve == 0){
+ curve = 25;
+ running_curve = True;
+ } else if (running_curve == False){
+ curve *= -0.9;
+ running_curve = True;
+ }
+ /* Sobald der Bot auf ein Hindernis stoesst, wird der naechste Zyklus eingeleitet.
+ * Auf einen Rechtsbogen (curve > 0) folgt eine Linksdrehung und auf einen Linksbogen eine Rechtsdrehung.
+ * Wenn der Wert von curve (durch Rundungsfehler bei int) auf 0 faellt, beginnt das Suchverhalten erneut.*/
+ if(bot_avoid_harm()) {
+ state = (curve > 0) ? EXPLORATION_STATE_TURN_PARALLEL_LEFT : EXPLORATION_STATE_TURN_PARALLEL_RIGHT;
+ running_curve = False;
+ #ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
+ deactivateBehaviour(bot_avoid_col_behaviour);
+ #endif
+ } else {
+ bot_drive(curve, BOT_SPEED_MAX);
+ }
+ break;
+ default:
+ state = EXPLORATION_STATE_GOTO_WALL;
+ curve = 0;
+ #ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
+ activateBehaviour(bot_avoid_col_behaviour);
+ #endif
+ }
+
+}
+
+/*!
+ * Aktiviert bot_explore_behaviour. */
+void bot_explore(Behaviour_t *caller, int8 (*check)(void)){
+ exploration_check_function = check;
+ switch_to_behaviour(caller,bot_explore_behaviour,NOOVERRIDE);
+}
+
+/*!
+ * Das Verhalten laesst den Bot einen Slalom fahren.
+ * @see bot_do_slalom()
+ * */
+void bot_do_slalom_behaviour(Behaviour_t *data){
+ static int8 state = SLALOM_STATE_CHECK_PILLAR;
+ static int8 orientation = SLALOM_ORIENTATION_RIGHT;
+ static int8 sweep_state;
+ static int8 sweep_steps = 0;
+ int16 turn;
+ int8 curve;
+
+ switch(state){
+ case SLALOM_STATE_CHECK_PILLAR:
+ // Der Bot sollte jetzt Licht sehen koennen...
+ if(check_for_light()){
+ // Wenn der Bot direkt vor der Saeule steht, kann der Slalom anfangen, sonst zum Licht fahren
+ if(bot_avoid_harm()){
+ state = SLALOM_STATE_START;
+ } else bot_goto_light();
+ } else {// ... sonst muss er den Slalom-Kurs neu suchen.
+ #ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
+ activateBehaviour(bot_avoid_col_behaviour);
+ #endif
+ return_from_behaviour(data);
+ }
+ break;
+ case SLALOM_STATE_START:
+ // Hier ist Platz fuer weitere Vorbereitungen, falls noetig.
+ #ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
+ deactivateBehaviour(bot_avoid_col_behaviour);
+ #endif
+ state = SLALOM_STATE_TURN_1;
+ // break;
+ case SLALOM_STATE_TURN_1:
+ turn = (orientation == SLALOM_ORIENTATION_LEFT) ? 90 : -90;
+ bot_turn(data,turn);
+ state = SLALOM_STATE_DRIVE_ARC;
+ break;
+ case SLALOM_STATE_DRIVE_ARC:
+ // Nicht wundern: Bei einem Links-Slalom faehrt der Bot eine Rechtskurve.
+ curve = (orientation == SLALOM_ORIENTATION_LEFT) ? 25 : -25;
+ bot_drive_distance(data,curve,BOT_SPEED_FAST,20);
+ state = SLALOM_STATE_TURN_2;
+ break;
+ case SLALOM_STATE_TURN_2:
+ turn = (orientation == SLALOM_ORIENTATION_LEFT) ? 45 : -45;
+ bot_turn(data,turn);
+ state = SLALOM_STATE_SWEEP_RUNNING;
+ break;
+ case SLALOM_STATE_SWEEP_RUNNING:
+ if(sweep_steps == 0){
+ sweep_state = SWEEP_STATE_CHECK;
+ }
+ // Insgesamt 6 Schritte drehen
+ if(sweep_steps < 6) {
+ if(sweep_state == SWEEP_STATE_CHECK){
+ // Phase 1: Pruefen, ob vor dem Bot eine gute Saeule ist
+ if(is_good_pillar_ahead() == True){
+ // Wenn die Saeule gut ist, drauf zu und Slalom anders rum fahren.
+ state = SLALOM_STATE_CHECK_PILLAR;
+ orientation = (orientation == SLALOM_ORIENTATION_LEFT) ? SLALOM_ORIENTATION_RIGHT : SLALOM_ORIENTATION_LEFT;
+ sweep_steps = 0;
+ } else {
+ // Sonst drehen.
+ sweep_state = SWEEP_STATE_TURN;
+ }
+ }
+ if(sweep_state == SWEEP_STATE_TURN) {
+ // Phase 2: Bot um 15 Grad drehen
+ turn = (orientation == SLALOM_ORIENTATION_LEFT) ? 15 : -15;
+ bot_turn(data,turn);
+ sweep_state = SWEEP_STATE_CHECK;
+ sweep_steps++;
+ }
+ } else {
+ turn = (orientation == SLALOM_ORIENTATION_LEFT) ? -90 : 90;
+ bot_turn(data,turn);
+ state = SLALOM_STATE_SWEEP_DONE;
+ sweep_steps = 0;
+ }
+ break;
+ case SLALOM_STATE_SWEEP_DONE:
+ turn = (orientation == SLALOM_ORIENTATION_LEFT) ? -135 : 135;
+ bot_turn(data,turn);
+ state = SLALOM_STATE_CHECK_PILLAR;
+ break;
+ default:
+ state = SLALOM_STATE_CHECK_PILLAR;
+ }
+
+}
+
+/*!
+ * Das Verhalten laesst den Bot zwischen einer Reihe beleuchteter Saeulen Slalom fahren.
+ * Das Verhalten ist wie bot_explore() in eine Anzahl von Teilschritten unterteilt.
+ * 1. Vor die aktuelle Saeule stellen, so dass sie zentral vor dem Bot und ungefaehr
+ * COL_CLOSEST (100 mm) entfernt ist.
+ * 2. 90 Grad nach rechts drehen.
+ * 3. In einem relativ engen Bogen 20 cm weit fahren.
+ * 4. Auf der rechten Seite des Bot nach einem Objekt suchen, dass
+ * a) im rechten Sektor des Bot liegt, also zwischen -45 Grad und -135 Grad zur Fahrtrichtung liegt,
+ * b) beleuchtet und
+ * c) nicht zu weit entfernt ist.
+ * Wenn es dieses Objekt gibt, wird es zur aktuellen Saeule und der Bot faehrt jetzt Slalom links.
+ * 5. Sonst zurueck drehen, 90 Grad drehen und Slalom rechts fahren.
+ * In diesem Schritt kann der Bot das Verhalten auch abbrechen, falls er gar kein Objekt mehr findet.
+ */
+void bot_do_slalom(Behaviour_t *caller){
+ switch_to_behaviour(caller, bot_do_slalom_behaviour,NOOVERRIDE);
+}
+
+/*!
+ * Das Verhalten setzt sich aus 3 Teilverhalten zusammen:
+ * Nach Licht suchen, auf das Licht zufahren, im Licht Slalom fahren. */
+void bot_olympic_behaviour(Behaviour_t *data){
+ if(check_for_light()){
+ /* Sobald der Bot auf ein Objekt-Hinderniss stoesst, versucht er, Slalom zu fahren.
+ * Aufgabe: Wenn der Bot vor einem Loch steht, hinter welchem sich die Lichtquelle
+ * befindet, wird er daran haengen bleiben. Schreibe ein Verhalten, dass das verhindert. */
+ if(bot_avoid_harm() && is_obstacle_ahead(COL_NEAR)){
+ bot_do_slalom(data);
+ } else bot_goto_light();
+ } else bot_explore(data,check_for_light);
+}
+
+/*!
+ * Initialisiert das Olympische Verhalten
+ * @param prio_main Prioritaet des Olympischen Verhalten (typ. 100)
+ * @param prio_helper Prioritaet der Hilfsfunktionen (typ. 52)
+ * @param active ACTIVE wenn es sofort starten soll, sonst INACTIVE
+ */
+void bot_olympic_init(int8 prio_main,int8 prio_helper, int8 active){
+ // unwichtigere Hilfsverhalten
+ insert_behaviour_to_list(&behaviour, new_behaviour(prio_helper--, bot_explore_behaviour,INACTIVE));
+ insert_behaviour_to_list(&behaviour, new_behaviour( prio_helper, bot_do_slalom_behaviour,INACTIVE));
+ // Demo-Verhalten fuer aufwendiges System, inaktiv
+ insert_behaviour_to_list(&behaviour, new_behaviour(prio_main, bot_olympic_behaviour, active));
+}
+
+#endif
diff --git a/source/ct-Bot/bot-logic/behaviour_remotecall.c b/source/ct-Bot/bot-logic/behaviour_remotecall.c
new file mode 100644
index 0000000..6e0125f
--- /dev/null
+++ b/source/ct-Bot/bot-logic/behaviour_remotecall.c
@@ -0,0 +1,407 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+
+/*! @file behaviour_remotecall_behaviour.c
+ * @brief ruft auf ein Kommando hin andere Verhalten auf und bestaetigt dann ihre Ausfuehrung
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 07.12.06
+*/
+
+#include "bot-logic/bot-logik.h"
+#ifdef BEHAVIOUR_REMOTECALL_AVAILABLE
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "log.h"
+#include "command.h"
+
+#include "bot-logic/remote_calls.h"
+
+#define REMOTE_CALL_IDLE 0
+#define REMOTE_CALL_SCHEDULED 1
+#define REMOTE_CALL_RUNNING 2
+
+/*! Uebergabevariable fuer Remotecall-Verhalten */
+static uint8 running_behaviour =REMOTE_CALL_IDLE;
+
+static uint8 function_id = 255;
+static uint8 parameter_count = 0; /*!< Anzahl der Paramter (ohne Zeiger auf Aufrufer) */
+static uint8 parameter_data[8] = {0}; /*!< Hier liegen die eigentlichen Parameter, derzeit brauchen wir maximal 8 Byte (2 floats, 4 (u)int16 oder 4 (u)int8 */
+#ifdef MCU
+ static uint8 parameter_length[REMOTE_CALL_MAX_PARAM] = {0}; /*!< Hier speichern wir die Laenge der jeweiligen Parameter */
+#else
+ static uint8* parameter_length = NULL; /*!< Hier speichern wir die Laenge der jeweiligen Parameter */
+#endif
+
+#ifdef MCU
+ #include <avr/pgmspace.h>
+#else
+ #define PROGMEM // Alibideklaration hat keine Funktion, verhindert aber eine Warning
+ #define strcmp_P strcmp // Auf dem PC gibt es keinen Flash, also auch kein eigenes Compare
+#endif
+
+/*!
+ * Hier muessen alle Boten-Funktionen rein, die Remote aufgerufen werden sollen
+ * Diese stoßen dann das zugehoerige Verhalten an
+ * Ein Eintrag erfolgt so:
+ * PREPARE_REMOTE_CALL(BOTENFUNKTION,NUMBER_OF_PARAMS, STRING DER DIE PARAMETER BESCHREIBT,laenge der jeweiligen Parameter in Byte)
+ *
+ * Alle Botenfunktionen muessen folgendem Schema entsprechen
+ * void bot_xxx(Behaviour_t * caller, ...);
+ *
+ * Erklaerung am Bsp:
+ * PREPARE_REMOTE_CALL(bot_gotoxy, 2, "float x, float y", 4, 4),
+ * Name der Botenfunktion --^ ^ ^ ^ ^
+ * Anzahl der Parameter --------- | | |
+ * Beschreibung der Parameter -------- | |
+ * Anzahl der Bytes Parameter 1 ------------------------ |
+ * Anzahl der Bytes Parameter 2 ---------------------------
+ *
+ * Zur Info:
+ * 1 Byte brauchen: uint8, int8,char
+ * 2 Byte brauchen: uint16, int16
+ * 4 Byte brauchen: uint32, int32, float
+ */
+const call_t calls[] PROGMEM = {
+ #ifdef BEHAVIOUR_DRIVE_DISTANCE_AVAILABLE
+ PREPARE_REMOTE_CALL(bot_drive_distance,3, "int8 curve, int16 speed, int16 cm", 1,2,2),
+ #endif
+ #ifdef BEHAVIOUR_GOTOXY_AVAILABLE
+ PREPARE_REMOTE_CALL(bot_gotoxy, 2, "float x, float y", 4, 4),
+ #endif
+ #ifdef BEHAVIOUR_SOLVE_MAZE_AVAILABLE
+ PREPARE_REMOTE_CALL(bot_solve_maze,0,""),
+ #endif
+ #ifdef BEHAVIOUR_CATCH_PILLAR_AVAILABLE
+ PREPARE_REMOTE_CALL(bot_catch_pillar,0,""),
+ #endif
+ #ifdef BEHAVIOUR_DRIVE_SQUARE_AVAILABLE
+ PREPARE_REMOTE_CALL(bot_drive_square,0,""),
+ #endif
+ #ifdef BEHAVIOUR_FOLLOW_LINE_AVAILABLE
+ PREPARE_REMOTE_CALL(bot_follow_line,0,""),
+ #endif
+ #ifdef BEHAVIOUR_GOTO_AVAILABLE
+ PREPARE_REMOTE_CALL(bot_goto,2," int16 left, int16 right",2,2),
+ #endif
+ #ifdef BEHAVIOUR_OLYMPIC_AVAILABLE
+ PREPARE_REMOTE_CALL(bot_do_slalom,0,""),
+ #endif
+ #ifdef BEHAVIOUR_SCAN_AVAILABLE
+ PREPARE_REMOTE_CALL(bot_scan,0,""),
+ #endif
+ #ifdef BEHAVIOUR_SERVO_AVAILABLE
+ PREPARE_REMOTE_CALL(bot_servo,2,"uint8 servo, uint8 pos",1,1),
+ #endif
+ #ifdef BEHAVIOUR_SIMPLE_AVAILABLE
+ PREPARE_REMOTE_CALL(bot_simple,0,""),
+ PREPARE_REMOTE_CALL(bot_simple2,1,"int16 light",2),
+ #endif
+ #ifdef BEHAVIOUR_TURN_AVAILABLE
+ PREPARE_REMOTE_CALL(bot_turn,1,"int16 degrees",2)
+ #endif
+};
+
+#define STORED_CALLS (sizeof(calls)/sizeof(call_t)) /*!< Anzahl der Remote calls im Array */
+
+/*!
+ * Sucht den Index des Remote-Calls heraus
+ * @param call String mit dem namen der gesuchten fkt
+ * @return Index in das calls-Array. Wenn nicht gefunden, dann 255
+ */
+uint8 getRemoteCall(char * call){
+// LOG_DEBUG(("Suche nach Funktion: %s",call));
+
+ uint8 i;
+ for (i=0; i< (STORED_CALLS); i++){
+ if (!strcmp_P (call, calls[i].name)){
+ LOG_DEBUG(("calls[%d].name=%s passt",i,call));
+ return i;
+ }
+ }
+ return 255;
+}
+
+#ifdef MCU
+ /*!
+ * Hilfsfunktion fuer bot_remotecall()
+ * Baut einen AVR-kompatiblen Parameterstream aus einem uint32-Parameterarray und einem Infoarray ueber die Parameter
+ * @param dest Zeiger auf das Ausgabearray (len[0]*2 Byte gross!)
+ * @param count Anzahl der Parameter
+ * @param len Zeiger auf ein Array, das die Anzahl der Bytes fuer die jeweiligen Parameter enthaelt
+ * @param data Zeiger auf die Daten (32 Bit, Laenge 8)
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 12.01.2007
+ */
+ void remotecall_convert_params(uint8* dest, uint8 count, uint8* len, uint8* data){
+ uint8 i;
+ /* jeden Parameter behandeln */
+ for (i=0; i<count; i++){
+ int8 j;
+ if (len[i] == 1) *dest++ = 0; // auch (u)int8 beginnen immer in geraden Registern
+ /* pro Parameter LSB zuerst nach dest kopieren */
+ for (j=len[i]-1; j>=0; j--)
+ *dest++ = data[j];
+ data += 4; // data-Array ist immer in 32 Bit
+ }
+ }
+#endif // MCU
+
+/*!
+ * Dieses Verhalten kuemmert sich darum die Verhalten, die von aussen angefragt wurden zu starten und liefert ein feedback zurueck, wenn sie beendet sind.
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_remotecall_behaviour(Behaviour_t *data){
+ uint8 call_id =255;
+
+// LOG_DEBUG(("Enter bot_remotecall_behaviour"));
+ void (* func) (struct _Behaviour_t *data);
+
+ switch (running_behaviour) {
+ case REMOTE_CALL_SCHEDULED: // Es laueft kein Auftrag, aber es steht ein neuer an
+// LOG_DEBUG(("REMOTE_CALL_SCHEDULED"));
+
+ call_id=function_id;
+ if (call_id >= STORED_CALLS){
+// LOG_DEBUG(("keine Funktion gefunden. Exit"));
+ running_behaviour=REMOTE_CALL_IDLE;
+ return;
+ }
+
+ #ifdef PC
+ // Auf dem PC liegt die calls-Struktur im RAM
+ func = (void*) calls[call_id].func;
+ #else
+ // Auf dem MCU liegt die calls-Struktur im Flash und muss erst geholt werden
+ func = (void*) pgm_read_word (& calls[call_id].func);
+ #endif
+
+ if (parameter_count ==0 ){ // Kommen wir ohne Parameter aus?
+// LOG_DEBUG(("call_id=%u",call_id));
+ func(data); // Die aufgerufene Botenfunktion starten
+ running_behaviour=REMOTE_CALL_RUNNING;
+ } else if (parameter_count <= REMOTE_CALL_MAX_PARAM){ // Es gibt gueltige Parameter
+ // TODO: Ja hier wird es spannend, denn jetzt muessen die Parameter auf den Stack
+ LOG_DEBUG(("call_id=%u",call_id));
+ LOG_DEBUG(("parameter_count=%u", parameter_count));
+ // asm-hacks here ;)
+ #ifdef PC
+ /* Prinzip auf dem PC: Wir legen alle Parameter einzeln auf den Stack, springen in die Botenfunktion und raeumen anschliessend den Stack wieder auf */
+ uint32 tmp;
+ uint8 i;
+ volatile uint8 td=1; // verwenden wir nur, damit der Compiler unsere inline-asm-Bloecke nicht umordnet
+ for (i=0; i<parameter_count*4 && td>0; i+=4,td++){ // Debug-Info ausgeben
+// LOG_DEBUG(("parameter_data[%u-%u] = %lu",i, i+3, *(uint32*)(parameter_data+i)));
+ }
+ /* Erster Wert in parameter_length ist die Anzahl der Parameter (ohne Zeiger des Aufrufers) */
+ for (i=0; i<parameter_count && td>1; i++,td++){ // Check von td eigentlich sinnlos, aber wir brauchen eine echte Datenabhaengigkeit auf dieses Codestueck
+ /* cdecl-Aufrufkonvention => Parameter von rechts nach links auf den Stack */
+ tmp = *(uint32*)(parameter_data+(parameter_count-i-1)*4);
+ /* Parameter 2 bis n pushen */
+ asm volatile( // IA32-Support only
+ "pushl %0 # parameter i auf stack "
+ :: "g" (tmp)
+ : "memory"
+ );
+ }
+ /* Parameter 1 (data) und Funktionsaufruf */
+ asm volatile(
+ "pushl %0 # push data \n\t"
+ "movl %1, %%eax # adresse laden \n\t"
+ "call *%%eax # jump to callee \n\t"
+ :: "m" (data), "m" (func)
+ : "eax", "memory"
+ );
+ /* caller rauemt den Stack wieder auf */
+ for (i=0; i<=parameter_count && td>2; i++){ // Check von td erzwingt, dass das Aufraeumen erst jetzt passiert
+ asm volatile(
+ "pop %%eax # stack aufraeumen "
+ ::: "eax", "memory"
+ );
+ }
+ #else
+ /* Prinzip auf der MCU: Keine komplizierten Rechnungen, sondern einfach alle Register ueberschreiben.
+ * Achtung: Derzeit braucht kein Verhalten mehr als 8 Register (2*float oder 4*int16 oder 4*int8), aendert sich das,
+ * muss man den Code hier erweitern!
+ * Die AVR-Konvention beim Funktionsaufruf:
+ * Die Groesse in Byte wird zur naechsten geraden Zahl aufgerundet, falls sie ungerade ist.
+ * Der Registerort faengt mit 26 an.
+ * Vom Registerort wird die berechete Groesse abgezogen und das Argument in diesen Registern uebergeben (LSB first).
+ * In r24/r25 legt der Compiler spaeter den Zeiger des Aufrufers, koennen wir hier also weglassen. */
+// LOG_DEBUG(("r22:r23 = %u:%u", parameter_data[1], parameter_data[0]));
+// LOG_DEBUG(("r21:r20 = %u:%u", parameter_data[3], parameter_data[2]));
+// LOG_DEBUG(("r18:r19 = %u:%u", parameter_data[5], parameter_data[4]));
+// LOG_DEBUG(("r16:r17 = %u:%u", parameter_data[7], parameter_data[6]));
+ asm volatile( // remotecall_convert_params() hat den Speicher bereits richtig sortiert, nur noch Werte laden
+ "ld r23, Z+ \n\t"
+ "ld r22, Z+ \n\t"
+ "ld r21, Z+ \n\t"
+ "ld r20, Z+ \n\t"
+ "ld r19, Z+ \n\t"
+ "ld r18, Z+ \n\t"
+ "ld r17, Z+ \n\t"
+ "ld r16, Z "
+ :: "z" (parameter_data)
+ : "r23", "r22", "r21", "r20", "r19", "r18", "r17", "r16"
+ );
+ func(data); // Die aufgerufene Botenfunktion starten
+ #endif
+
+ running_behaviour=REMOTE_CALL_RUNNING;
+ return;
+ } else {
+// LOG_DEBUG(("Parameteranzahl unzulaessig!"));
+ }
+ break;
+
+ case REMOTE_CALL_RUNNING: // Es lief ein Verhalten und ist nun zuende (sonst waeren wir nicht hier)
+ {
+ // Antwort schicken
+
+ char * function_name;
+
+ #ifdef PC
+ function_name=(char*) &calls[function_id].name;
+ #else
+ // Auf dem MCU muessen wir die Daten erstmal aus dem Flash holen
+
+ char tmp[REMOTE_CALL_FUNCTION_NAME_LEN+1];
+ function_name=(char*)&tmp;
+
+ uint8* from= (uint8*)& calls[function_id].name;
+
+ uint8 i;
+ for (i=0; i<REMOTE_CALL_FUNCTION_NAME_LEN+1; i++)
+ *function_name++ = (uint8) pgm_read_byte ( from++ );
+ function_name=(char*)&tmp;
+ #endif
+
+ #ifdef COMMAND_AVAILABLE
+ int16 result = data->subResult;
+ command_write_data(CMD_REMOTE_CALL,SUB_REMOTE_CALL_DONE,&result,&result,function_name);
+ #endif
+
+// LOG_DEBUG(("Remote-call %s beendet",function_name));
+
+ // Aufrauemen
+ function_id=255;
+ //parameter_length=NULL;
+ //parameter_data=NULL;
+ running_behaviour=REMOTE_CALL_IDLE;
+
+ return_from_behaviour(data); // und Verhalten auch aus
+ break;
+ }
+ default:
+ return_from_behaviour(data); // und Verhalten auch aus
+ break;
+
+ }
+}
+
+/*!
+ * Fuehre einen remote_call aus. Es gibt KEIN aufrufendes Verhalten!!
+ * @param func Zeiger auf den Namen der Fkt
+ * @param data Zeiger auf die Daten
+ */
+void bot_remotecall(char* func, remote_call_data_t* data){
+
+ function_id= getRemoteCall(func);
+ if (function_id >= STORED_CALLS){
+// LOG_DEBUG(("Funktion %s nicht gefunden. Exit!",func));
+ return;
+ }
+
+ // parameter_length: Zeiger auf ein Array, das zuerst die Anzahl der Parameter und danach die Anzahl der Bytes fuer die jeweiligen Parameter enthaelt
+ #ifdef PC
+ parameter_count = calls[function_id].param_count;
+ parameter_length = (uint8*)calls[function_id].param_len;
+ #else
+ // Auf dem MCU muessen wir die Daten erstmal aus dem Flash holen
+ uint8* from= (uint8*)& calls[function_id].param_len;
+ uint8 i;
+ parameter_count = pgm_read_byte(&calls[function_id].param_count);
+ for (i=0; i<REMOTE_CALL_MAX_PARAM; i++)
+ parameter_length[i] = (uint8) pgm_read_byte ( from++ );
+ #endif
+// LOG_DEBUG(("func=%s param_count=%d Len= %u %u %u %u",func,parameter_count,parameter_length[0],parameter_length[1],parameter_length[2]));
+// if (data != NULL){
+// LOG_DEBUG(("data= %u %u %u %u",data[0],data[1],data[2],data[3]));
+// }
+
+ #ifdef MCU // Die MCU legt die Parameter nach einem anderen Verfahren ab, diese Funktion konvertiert sie deshalb
+ remotecall_convert_params(parameter_data, parameter_count, parameter_length, (uint8*)data);
+ #else // Auf dem PC kopieren wir die Daten einfach
+ memcpy(parameter_data, data, parameter_count*4);
+ #endif
+
+ running_behaviour=REMOTE_CALL_SCHEDULED;
+ activateBehaviour(bot_remotecall_behaviour);
+}
+
+/*!
+ * Fuehre einen remote_call aus. Es gibt KEIN aufrufendes Verhalten!!
+ * @param data Zeiger die Payload eines Kommandos. Dort muss zuerst ein String mit dem Fkt-Namen stehen. ihm folgen die Nutzdaten
+ */
+void bot_remotecall_from_command(uint8 * data){
+ char * function_name = (char*)data;
+ remote_call_data_t * params = (remote_call_data_t *)(data+ strlen(function_name)+1);
+ bot_remotecall(function_name,params);
+}
+
+
+/*!
+ * Listet alle verfuegbaren Remote-Calls auf und verschickt sie als einzelne Kommanods
+ */
+void remote_call_list(void){
+ #ifdef MCU
+ call_t call_storage;
+ uint8* to;
+ uint8* from;
+ #endif
+ call_t* call;
+
+ int16 i;
+ for (i=0; i< (STORED_CALLS); i++){
+ #ifdef MCU
+ // Auf dem MCU muessen die Daten erstmal aus dem Flash ins RAM
+ from= (uint8*)&calls[i];
+ to= (uint8*)&call_storage;
+ uint8 j;
+ for (j=0; j< sizeof(call_t); j++){
+ *to = (uint8) pgm_read_byte ( from++ );
+ to++;
+ }
+ call = &call_storage;
+ #else
+ call = (call_t*)&calls[i];
+ #endif
+
+ #ifdef COMMAND_AVAILABLE
+ // und uebertragen
+ command_write_rawdata(CMD_REMOTE_CALL,SUB_REMOTE_CALL_ENTRY,&i,&i, sizeof(call_t),(uint8*)call);
+ #endif
+
+// LOG_DEBUG(("%s(%s)",call->name,call->param_info));
+ }
+}
+
+#endif
diff --git a/source/ct-Bot/bot-logic/behaviour_scan.c b/source/ct-Bot/bot-logic/behaviour_scan.c
new file mode 100644
index 0000000..6f6869c
--- /dev/null
+++ b/source/ct-Bot/bot-logic/behaviour_scan.c
@@ -0,0 +1,144 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_scan.c
+ * @brief Scannt die Umgebung und traegt sie in die Karte ein
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+#include "bot-logic/bot-logik.h"
+#include "map.h"
+#include <math.h>
+
+#ifdef BEHAVIOUR_SCAN_AVAILABLE
+/*!
+ * Der Roboter faehrt einen Vollkreis und scannt dabei die Umgebung
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_scan_onthefly_behaviour(Behaviour_t *data){
+ #define ONTHEFLY_DIST_RESOLUTION 0.02 /*!< Alle wieviel gefahrene Strecke [m] soll die Karte aktualisiert werden. Achtung er prueft x und y getrennt, daher ist die tatsaechlich zurueckgelegte Strecke im worst case sqrt(2)*ONTHEFLY_DIST_RESOLUTION */
+ #define ONTHEFLY_ANGLE_RESOLUTION 10 /*!< Alle wieviel Gerad Drehung [m] soll die Karte aktualisiert werden */
+
+
+
+ #ifdef MAP_AVAILABLE
+ static float last_x, last_y, last_head;
+
+ float diff_x = fabs(x_pos-last_x);
+ float diff_y = fabs(y_pos-last_y);
+
+ // Wenn der Bot faehrt, aktualisieren wir alles
+ if ((diff_x > ONTHEFLY_DIST_RESOLUTION) ||( diff_y > ONTHEFLY_DIST_RESOLUTION)){
+ update_map_location(x_pos,y_pos);
+ update_map(x_pos,y_pos,heading,sensDistL,sensDistR);
+
+ last_x=x_pos;
+ last_y=y_pos;
+ last_head=heading;
+ return;
+ }
+
+ float diff_head = fabs(last_head-heading);
+ // Wenn der bot nur dreht, aktualisieren wir nur die Blickstrahlen
+ if ( diff_head > ONTHEFLY_ANGLE_RESOLUTION ){
+ update_map(x_pos,y_pos,heading,sensDistL,sensDistR);
+ last_head=heading;
+ }
+ /* if ((diff_x*diff_x + diff_y*diff_y > ONTHEFLY_DIST_RESOLUTION)||fabs(last_head-heading) > ONTHEFLY_ANGLE_RESOLUTION ){
+ last_x=x_pos;
+ last_y=y_pos;
+ last_head=heading;
+ print_map();
+ }
+ */
+ #endif
+}
+
+
+#define BOT_SCAN_STATE_START 0
+uint8 bot_scan_state = BOT_SCAN_STATE_START; /*!< Zustandsvariable fuer bot_scan_behaviour */
+
+/*!
+ * Der Roboter faehrt einen Vollkreis und scannt dabei die Umgebung
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_scan_behaviour(Behaviour_t *data){
+ #define BOT_SCAN_STATE_SCAN 1
+
+ #define ANGLE_RESOLUTION 5 /*!< Aufloesung fuer den Scan in Grad */
+
+// static uint16 bot_scan_start_angle; /*!< Winkel, bei dem mit dem Scan begonnen wurde */
+ static float turned; /*!< Winkel um den bereits gedreht wurde */
+
+ static float last_scan_angle; /*!< Winkel bei dem zuletzt gescannt wurde */
+
+ float diff;
+
+ switch (bot_scan_state){
+ case BOT_SCAN_STATE_START:
+
+ turned=0;
+ last_scan_angle=heading-ANGLE_RESOLUTION;
+ bot_scan_state=BOT_SCAN_STATE_SCAN;
+ break;
+ case BOT_SCAN_STATE_SCAN:
+ diff = heading - last_scan_angle;
+ if (diff < -180)
+ diff+=360;
+ if (diff*1.15 >= ANGLE_RESOLUTION){
+ turned+= diff;
+ last_scan_angle=heading;
+
+ #ifdef MAP_AVAILABLE
+ // Eigentlicher Scan hier
+ update_map(x_pos,y_pos,heading,sensDistL,sensDistR);
+ ////////////
+ #endif
+
+ }
+
+ if (turned >= 360-ANGLE_RESOLUTION) // Ende erreicht
+ bot_scan_state++;
+ break;
+ default:
+ bot_scan_state = BOT_SCAN_STATE_START;
+ #ifdef MAP_AVAILABLE
+ print_map();
+ #endif
+ return_from_behaviour(data);
+ break;
+ }
+}
+
+/*!
+ * Der Roboter faehrt einen Vollkreis und scannt dabei die Umgebung
+ * @param Der aufrufer
+ */
+void bot_scan(Behaviour_t* caller){
+
+ bot_scan_state = BOT_SCAN_STATE_START;
+ bot_turn(caller,360);
+ switch_to_behaviour(0, bot_scan_behaviour,OVERRIDE);
+
+// update_map(x_pos,y_pos,heading,sensDistL,sensDistR);
+// print_map();
+}
+#endif
diff --git a/source/ct-Bot/bot-logic/behaviour_servo.c b/source/ct-Bot/bot-logic/behaviour_servo.c
new file mode 100644
index 0000000..77583cc
--- /dev/null
+++ b/source/ct-Bot/bot-logic/behaviour_servo.c
@@ -0,0 +1,68 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+
+/*! @file behaviour_servo.c
+ * @brief kontrolliert die Servos
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 07.12.06
+*/
+
+
+#include "bot-logic/bot-logik.h"
+#ifdef BEHAVIOUR_SERVO_AVAILABLE
+
+#include "motor.h"
+#include "timer.h"
+/*! Uebergabevariable fuer Servo-Verhalten */
+static uint16 servo_time;
+static uint8 servo_nr;
+static uint8 servo_pos;
+uint8 servo_active = 0; /*!< 0, wenn kein Servo aktiv, sonst Bit der gerade aktiven Servos gesetzt */
+
+/*!
+ * Dieses Verhalten fuehrt ein Servo-Kommando aus und schaltet danach den Servo wieder ab
+ *
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_servo_behaviour(Behaviour_t *data){
+ /* Servo ausschalten, falls Klappe zu oder Countdown abgelaufen */
+ if ( (servo_pos == DOOR_CLOSE && sensDoor == 0) || (TIMER_GET_TICKCOUNT_16 - servo_time > MS_TO_TICKS(1000L)) ){
+ servo_set(servo_nr, SERVO_OFF); // Servo aus
+ servo_active &= ~servo_nr;
+ return_from_behaviour(data); // und Verhalten auch aus
+ }
+}
+
+/*!
+ * Fahre den Servo an eine Position
+ * @param servo Nummer des Servos
+ * @param pos Zielposition des Servos
+ */
+void bot_servo(Behaviour_t * caller, uint8 servo, uint8 pos){
+ servo_active |= servo;
+ servo_set(servo, pos); // Servo-PWM einstellen
+ servo_pos = pos; // Zielposition merken
+ servo_nr = servo; // Servo-Nr speichern
+ servo_time = TIMER_GET_TICKCOUNT_16; // Der Count down verschafft dem Servo etwas Zeit
+
+ switch_to_behaviour(caller,bot_servo_behaviour,OVERRIDE); // Warte-Verahlten an
+}
+#endif
diff --git a/source/ct-Bot/bot-logic/behaviour_simple.c b/source/ct-Bot/bot-logic/behaviour_simple.c
new file mode 100644
index 0000000..5c897e9
--- /dev/null
+++ b/source/ct-Bot/bot-logic/behaviour_simple.c
@@ -0,0 +1,139 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+
+/*! @file behaviour_simple.c
+ * @brief ganz einfache Beispielverhalten
+ * Diese Datei sollte der Einstiegspunkt fuer eigene Experimente sein,
+ * den Roboter zu steuern.
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+
+#include "bot-logic/bot-logik.h"
+#ifdef BEHAVIOUR_SIMPLE_AVAILABLE
+
+
+/*!
+ * Ein ganz einfaches Verhalten, es hat maximale Prioritaet
+ * Hier kann man auf ganz einfache Weise die ersten Schritte wagen.
+ * Wer die Moeglichkeiten des ganzen Verhaltensframeworks ausschoepfen will, kann diese Funktion getrost auskommentieren
+ * und findet dann in bot_behave_init() und bot_behave() weitere Hinweise fuer elegante Bot-Programmierung....
+ *
+ * Das Verhalten ist per default abgeschaltet. Daher muss man es erst in bot_behave_init() aktivieren.
+ * Dort steht aber bereits eine auskommentierte Zeile dazu, von der man nur die zwei Kommentarzeichen wegnehmen muss.
+ * Achtung, da bot_simple_behaviour() maximale Prioritaet hat, kommt es vor den anderen Regeln, wie dem Schutz vor Abgruenden, etc. zum Zuge
+ * Das sollte am Anfang nicht stoeren, spaeter sollte man jedoch die Prioritaet herabsetzen.
+ *
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_simple_behaviour(Behaviour_t *data){
+ static uint8 state=0;
+
+ switch (state){
+ case 0:
+ bot_drive_distance(data ,0 , BOT_SPEED_MAX, 14);
+ state++;
+ break;
+ case 1:
+ bot_turn(data , 90);
+ state=0;
+ break;
+ default:
+ state=0;
+ return_from_behaviour(data);
+ break;
+ }
+}
+
+
+/*!
+ * Rufe das Simple-Verhalten auf
+ * @param caller Der obligatorische Verhaltensdatensatz des Aufrufers
+ */
+void bot_simple(Behaviour_t * caller, int16 light){
+ switch_to_behaviour(caller,bot_simple_behaviour,OVERRIDE);
+}
+
+
+/*! Uebergabevariable fuer SIMPLE2 */
+static int16 simple2_light=0;
+
+/*!
+ * Ein ganz einfaches Beispiel fuer ein Hilfsverhalten,
+ * das selbst SpeedWishes aussert und
+ * nach getaner Arbeit die aufrufende Funktion wieder aktiviert
+ * Zudem prueft es, ob eine Uebergabebedingung erfuellt ist.
+ *
+ * Zu diesem Verhalten gehoert die Botenfunktion bot_simple2()
+ *
+ * Hier kann man auf ganz einfache Weise die ersten Schritte wagen.
+ * Wer die Moeglichkeiten des ganzen Verhaltensframeworks ausschoepfen will, kann diese Funktion getrost auskommentieren
+ * und findet dann in bot_behave_init() und bot_behave() weitere Hinweise fuer elegante Bot-Programmierung....
+ *
+ * Das Verhalten ist per default abgeschaltet. Daher muss man es erst in bot_behave_init() aktivieren.
+ * Dort steht aber bereits eine auskommentierte Zeile dazu, von der man nur die zwei Kommentarzeichen wegnehmen muss.
+ * Achtung, da bot_simple2_behaviour() maximale Prioritaet hat, kommt es vor den anderen Regeln, wie dem Schutz vor Abgruenden, etc. zum Zuge
+ * Das sollte am Anfang nicht stoeren, spaeter sollte man jedoch die Prioritaet herabsetzen.
+ *
+ * bot_simple2_behaviour faehrt den Bot solange geradeaus, bis es dunkler als im Uebergabeparameter spezifiziert ist wird
+ *
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_simple2_behaviour(Behaviour_t *data){
+ #define STATE_SIMPLE2_INIT 0
+ #define STATE_SIMPLE2_WORK 1
+ #define STATE_SIMPLE2_DONE 2
+ static uint8 state = 0;
+
+ switch (state) {
+ case STATE_SIMPLE2_INIT:
+ // Nichts zu tun
+ state=STATE_SIMPLE2_WORK;
+ break;
+ case STATE_SIMPLE2_WORK:
+ // Fahre ganz schnell
+ speedWishLeft = BOT_SPEED_FAST;
+ speedWishRight = BOT_SPEED_FAST;
+ if (sensLDRL< simple2_light) // Beispielbedingung
+ // Wenn es dunkler als angegeben wird, dann haben wir unserd Ziel erreicht
+ state=STATE_SIMPLE2_DONE;
+ break;
+
+ case STATE_SIMPLE2_DONE: /* Sind wir fertig, dann Kontrolle zurueck an Aufrufer */
+ state=STATE_SIMPLE2_INIT;
+ return_from_behaviour(data);
+ break;
+ }
+}
+
+/*!
+ * Rufe das Simple2-Verhalten auf und uebergebe light
+ * @param caller Der obligatorische Verhaltensdatensatz des Aufrufers
+ * @param light Uebergabeparameter
+ */
+void bot_simple2(Behaviour_t * caller, int16 light){
+ simple2_light=light;
+
+ // Zielwerte speichern
+ switch_to_behaviour(caller,bot_simple2_behaviour,OVERRIDE);
+}
+#endif
diff --git a/source/ct-Bot/bot-logic/behaviour_solve_maze.c b/source/ct-Bot/bot-logic/behaviour_solve_maze.c
new file mode 100644
index 0000000..5eb2fc4
--- /dev/null
+++ b/source/ct-Bot/bot-logic/behaviour_solve_maze.c
@@ -0,0 +1,660 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_solve_maze.c
+ * @brief Wandfolger durchs Labyrinth
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+#include "bot-logic/bot-logik.h"
+#include <math.h>
+#include <stdlib.h>
+#include "log.h"
+
+#ifdef BEHAVIOUR_SOLVE_MAZE_AVAILABLE
+
+/* Parameter fuer das check_wall_behaviour() */
+int8 wall_detected; /*!< enthaelt True oder False, je nach Ergebnis des Verhaltens */
+int8 check_direction; /*!< enthaelt CHECK_WALL_LEFT oder CHECK_WALL_RIGHT */
+int16 wall_distance; /*!< enthaelt gemessene Entfernung */
+
+/* Konstanten fuer check_wall_behaviour-Verhalten */
+#define CHECK_WALL_RIGHT 0
+#define CHECK_WALL_LEFT 1
+
+/* Parameter fuer das measure_angle_behaviour() */
+int8 measure_direction; /*!< enthaelt MEASURE_RIGHT oder MEASURE_LEFT */
+int16 measure_distance; /*!< enthaelt maximale Messentfernung, enthaelt nach der Messung die Entfernung */
+int16 measured_angle; /*!< enthaelt gedrehten Winkel oder 0, falls nichts entdeckt */
+#ifdef MEASURE_MOUSE_AVAILABLE
+ int16 start_heading; /*!< Blickwinkel des Bots zu Beginn der Messung */
+#else
+ int16 startEncL; /*!< enthaelt Encoderstand zu Beginn der Messung */
+ int16 startEncR; /*!< enthaelt Encoderstand zu Beginn der Messung */
+#endif
+/* Konstanten fuer measure_angle_behaviour-Verhalten */
+#define MEASURE_LEFT 1
+#define MEASURE_RIGHT -1
+
+
+/*!
+ * Das Verhalten dreht sich um 45 Grad in die angegebene Richtung (0=rechts, 1=links)
+ * und prueft, ob auf dem Sensor auf der Seite der angegebenen Richtung eine Wand
+ * im Abstand von 12cm zu sehen ist. Wenn dem so ist, wird die Variable wall_present
+ * auf True gesetzt, sonst False */
+void bot_check_wall_behaviour(Behaviour_t *data) {
+ /* Konstantenfuer check_wall_behaviour-Verhalten */
+ #define CORRECT_NEAR 0
+ #define CORRECT_NONE 1
+ #define CORRECT_FAR 2
+ /* Zustaende fuer check_wall_behaviour-Verhalten */
+ #define CHECK_WALL_TURN 0
+ #define CHECK_WALL_SENS 1
+ #define CHECK_WALL_TURN_BACK 2
+ #define CHECK_WALL_FINISHED 3
+ #define CHECK_WALL_CORRECT 4
+
+ static int8 checkState=CHECK_WALL_TURN;
+ /* wenn die Wand noch da ist aber aus dem Blickfeld rueckt, Entfernung und Winkel korrigieren */
+ static int8 correctDistance=CORRECT_NONE;
+ /* letzte, gueltige Distanz fuer Abweichungsberechnung */
+ static int16 lastDistance=0;
+ /* enthaelt anzahl der +/-5 identischen Messungen */
+ static int8 measureCount=0;
+ /* letzter Messwert */
+ static int16 lastSensor=0;
+
+ int16 sensor; /* fuer temporaer benutzte Senorwerte */
+
+ switch(checkState) {
+ case CHECK_WALL_TURN:
+ /* haben wir links oder rechts eine Wand? */
+ if (check_direction==CHECK_WALL_LEFT) {
+ checkState=CHECK_WALL_SENS;
+ bot_turn(data,45);
+ break;
+ } else {
+ checkState=CHECK_WALL_SENS;
+ bot_turn(data,-45);
+ break;
+ }
+
+ case CHECK_WALL_SENS:
+ if (check_direction==CHECK_WALL_LEFT) {
+ sensor=sensDistL;
+ } else {
+ sensor=sensDistR;
+ }
+ /* dafuer sorgen, dass wir nur verlaessliche Werte haben
+ * dazu muss der wert dreimal nacheinander max. um +/- 5
+ * unterschiedlich sein */
+ if (measureCount==0) {
+ lastSensor=sensor;
+ measureCount++;
+ break;
+ }
+ if (sensor>=lastSensor-5 && sensor<=lastSensor+5 && measureCount<4) {
+ /* Messwert ist ok */
+ measureCount++;
+ break;
+ } else if (measureCount<4) {
+ /* Messwert weicht zu doll ab -> von Neuem messen */
+ measureCount=0;
+ break;
+ }
+ /* ok, wir hatten drei Messungen mit nahezu identischen Werten */
+
+ /* keine wand in eingestellter Maximalentfernung? */
+ if (sensor>IGNORE_DISTANCE) {
+ correctDistance=CORRECT_NONE; /* dann auch keine Korrektur */
+ lastDistance=0; /* auch kein Vergleichswert */
+ wall_detected=False; /* keine Wand da */
+ } else if (sensor<OPTIMAL_DISTANCE-ADJUST_DISTANCE) {
+ /* bot hat den falschen Abstand zur Wand, zu nah dran */
+ wall_detected=True;
+ correctDistance=CORRECT_NEAR;
+ } else if (sensor>OPTIMAL_DISTANCE+ADJUST_DISTANCE) {
+ /* bot hat den falschen Abstand zur Wand, zu weit weg */
+ wall_detected=True;
+ correctDistance=CORRECT_FAR;
+ } else {
+ /* perfekter Abstand */
+ correctDistance=CORRECT_NONE;
+ wall_detected=True;
+ }
+ wall_distance=sensor;
+ /* Wenn Korrektur noetig, dann durchfuehren, sonst gleich zurueckdrehen */
+ if (correctDistance==CORRECT_NONE) checkState=CHECK_WALL_TURN_BACK;
+ else checkState=CHECK_WALL_CORRECT;
+ break;
+
+
+ case CHECK_WALL_TURN_BACK:
+ checkState=CHECK_WALL_FINISHED;
+ int16 turnAngle=45;
+
+ /* welcher Sensorwert wird gebraucht? */
+ if (check_direction==CHECK_WALL_LEFT) {
+ sensor=sensDistL;
+ } else {
+ sensor=sensDistR;
+ }
+ /* wenn vorhanden, aus letztem Abstand und aktuellem Abstand
+ * Korrekturwinkel berechnen, falls vorheriger Abstand da.
+ * wird durch Abstand>IGNORE_DISTANCE zurueckgesetzt */
+ if (lastDistance!=0) {
+ turnAngle=turnAngle+(lastDistance-wall_distance)/10;
+ }
+ if (sensor<IGNORE_DISTANCE) lastDistance=sensor;
+ if (check_direction==CHECK_WALL_LEFT) {
+ bot_turn(data,-turnAngle);
+ } else {
+ bot_turn(data,turnAngle);
+ }
+ break;
+
+ case CHECK_WALL_FINISHED:
+ /* ok, check beendet -> Verhalten verlassen */
+ checkState=CHECK_WALL_TURN;
+ return_from_behaviour(data);
+ break;
+
+ case CHECK_WALL_CORRECT:
+ /* Abhaengig von der Seite, auf der die Wand ist, Entfernung korrigieren */
+ if (check_direction==CHECK_WALL_LEFT) {
+ sensor=sensDistL;
+ } else {
+ sensor=sensDistR;
+ }
+ if (sensor-OPTIMAL_DISTANCE<0) {
+ speedWishLeft=-BOT_SPEED_SLOW;
+ speedWishRight=-BOT_SPEED_SLOW;
+ } else if (sensor-OPTIMAL_DISTANCE>0) {
+ speedWishLeft=BOT_SPEED_SLOW;
+ speedWishRight=BOT_SPEED_SLOW;
+ }
+ else {
+ checkState=CHECK_WALL_TURN_BACK;
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ }
+ break;
+
+
+ default:
+ checkState=CHECK_WALL_TURN;
+ return_from_behaviour(data);
+ break;
+ }
+}
+
+
+/*!
+ * Das Verhalten dreht sich um 45 Grad in die angegebene Richtung (0=rechts, 1=links)
+ * und prueft, ob auf dem Sensor auf der Seite der angegebenen Richtung eine Wand
+ * im Abstand von 12-22cm zu sehen ist. Wenn dem so ist, wird die Variable wall_present
+ * auf True gesetzt, sonst False */
+void bot_check_wall(Behaviour_t *caller,int8 direction) {
+ check_direction=direction;
+ wall_detected=False;
+ switch_to_behaviour(caller, bot_check_wall_behaviour,NOOVERRIDE);
+}
+
+#ifdef MEASURE_MOUSE_AVAILABLE
+ /*!
+ * Das Verhalten dreht den Bot in die angegebene Richtung bis ein Hindernis
+ * im Sichtbereich erscheint, das eine Entfernung bis max. zur angegebenen
+ * Distanz zum Bot hat.
+ */
+
+ void bot_measure_angle_behaviour(Behaviour_t *caller) {
+ /* Zustaende measure_angle_behaviour-Verhalten */
+ #define MEASURE_TURN 0
+ #define FOUND_OBSTACLE 1
+ #define MEASUREMENT_DONE 2
+
+ static int8 measureState=MEASURE_TURN;
+
+ /* enthaelt anzahl der +/-5 identischen Messungen */
+ static int8 measureCount=0;
+ /* letzter Messwert */
+ static int16 lastSensor=0;
+
+ /* bereits gedrehten Winkel */
+ int16 turned_angle=0;
+ if (measure_direction>0) {
+ if ((int16)heading_mou<start_heading) {
+ /* war ein ueberlauf */
+ turned_angle=360-start_heading+(int16)heading_mou;
+ } else {
+ /* sonst normale differenz berechnen */
+ turned_angle=(int16)heading_mou-start_heading;
+ }
+ } else {
+ if ((int16)heading_mou>start_heading) {
+ /* war ein ueberlauf */
+ turned_angle=360-(int16)heading_mou+start_heading;
+ } else {
+ turned_angle=start_heading-(int16)heading_mou;
+ }
+
+ }
+
+ /* sensorwert abhaengig von der Drehrichtung abnehmen */
+ int16 sensor=(measure_direction==MEASURE_LEFT)?sensDistL:sensDistR;
+ /* solange drehen, bis Hindernis innerhalb Messstrecke oder 360 Grad komplett */
+ switch(measureState){
+ case MEASURE_TURN:
+ /* nicht mehr als eine komplette Drehung machen! */
+ if (turned_angle>=360) {
+ measure_direction=-measure_direction;
+ measureState=MEASUREMENT_DONE;
+ bot_turn(caller,measure_direction*turned_angle);
+ measured_angle=0; /* kein Hindernis gefunden */
+ break;
+ }
+ /* Ist ein Objekt in Reichweite? */
+ if (sensor<=measure_distance) {
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ measureState=FOUND_OBSTACLE;
+ break;
+ }
+ /* Beginnen, zurueckzudrehen */
+ speedWishLeft = (measure_direction > 0) ? -BOT_SPEED_FOLLOW : BOT_SPEED_FOLLOW;
+ speedWishRight = (measure_direction > 0) ? BOT_SPEED_FOLLOW : -BOT_SPEED_FOLLOW;
+ break;
+
+ case FOUND_OBSTACLE:
+ /* dafuer sorgen, dass wir nur verlaessliche Werte haben
+ * dazu muss der wert dreimal nacheinander max. um +/- 5
+ * unterschiedlich sein */
+ if (measureCount==0) {
+ lastSensor=sensor;
+ measureCount++;
+ break;
+ }
+ if (sensor>=lastSensor-5 && sensor<=lastSensor+5 && measureCount<4) {
+ /* Messwert ist ok */
+ measureCount++;
+ break;
+ } else if (measureCount<4) {
+ /* Messwert weicht zu doll ab -> von Neuem messen */
+ measureCount=0;
+ break;
+ }
+ /* ok, wir hatten drei Messungen mit nahezu identischen Werten */
+ measure_distance=sensor;
+ /* Hindernis gefunden, nun Bot wieder in Ausgangsstellung drehen */
+ measure_direction=-measure_direction;
+ measured_angle=turned_angle;
+ measureState=MEASUREMENT_DONE;
+ bot_turn(caller,measure_direction*turned_angle);
+ break;
+
+ case MEASUREMENT_DONE:
+ measureState=MEASURE_TURN;
+ measureCount=0;
+ return_from_behaviour(caller);
+ break;
+ }
+ }
+
+ /*!
+ * Das Verhalten dreht den Bot in die angegebene Richtung bis ein Hindernis
+ * im Sichtbereich erscheint, das eine Entfernung bis max. zur angegebenen
+ * Distanz zum Bot hat.
+ */
+
+ void bot_measure_angle(Behaviour_t *caller, int8 direction, int16 distance) {
+ /* maximale Messentfernung und Richtung setzen */
+ measure_direction=direction;
+ measure_distance=distance;
+ /* Heading zu Anfang des Verhaltens merken */
+ start_heading=(int16)heading_mou;
+ switch_to_behaviour(caller, bot_measure_angle_behaviour,NOOVERRIDE);
+ }
+#else
+/*!
+ * Das Verhalten dreht den Bot in die angegebene Richtung bis ein Hindernis
+ * im Sichtbereich erscheint, das eine Entfernung bis max. zur angegebenen
+ * Distanz zum Bot hat.
+ */
+
+void bot_measure_angle_behaviour(Behaviour_t *caller) {
+ /* Zustaende measure_angle_behaviour-Verhalten */
+ #define MEASURE_TURN 0
+ #define FOUND_OBSTACLE 1
+ #define TURN_COMPLETED 2
+ #define TURN_BACK 3
+ #define CORRECT_ANGLE 4
+ #define MEASUREMENT_DONE 5
+
+ static int8 measureState=MEASURE_TURN;
+
+ /* bereits gedrehte Strecke errechnen */
+ int16 turnedLeft=(measure_direction>0)?-(sensEncL-startEncL):(sensEncL-startEncL);
+ int16 turnedRight=(measure_direction>0)?(sensEncR-startEncR):-(sensEncR-startEncR);
+ int16 turnedSteps=(abs(turnedLeft)+abs(turnedRight))/2;
+
+ /* sensorwert abhaengig von der Drehrichtung abnehmen */
+ int16 sensor=(measure_direction==MEASURE_LEFT)?sensDistL:sensDistR;
+ /* solange drehen, bis Hindernis innerhalb Messstrecke oder 360� komplett */
+ switch(measureState){
+ case MEASURE_TURN:
+ /* nicht mehr als eine komplette Drehung machen! */
+ if (turnedSteps>=ANGLE_CONSTANT) {
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ measureState=TURN_COMPLETED;
+ measured_angle=0; /* kein Hindernis gefunden */
+ break;
+ }
+ /* Ist ein Objekt in Reichweite? */
+ if (sensor<=measure_distance) {
+ measure_distance=sensor;
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ measureState=FOUND_OBSTACLE;
+ break;
+ }
+ /* Beginnen, zurueckzudrehen */
+ speedWishLeft = (measure_direction > 0) ? -BOT_SPEED_SLOW : BOT_SPEED_SLOW;
+ speedWishRight = (measure_direction > 0) ? BOT_SPEED_SLOW : -BOT_SPEED_SLOW;
+ break;
+
+ case FOUND_OBSTACLE:
+ /* Hindernis gefunden, nun Bot wieder in Ausgangsstellung drehen */
+ measure_direction=-measure_direction;
+ measured_angle=(int16)((long)(turnedSteps*360)/ANGLE_CONSTANT);
+ measureState=TURN_BACK;
+ speedWishLeft = (measure_direction > 0) ? -BOT_SPEED_SLOW : BOT_SPEED_SLOW;
+ speedWishRight = (measure_direction > 0) ? BOT_SPEED_SLOW : -BOT_SPEED_SLOW;
+ break;
+
+ case TURN_COMPLETED:
+ /* bot steht wieder in Ausgangsrichtung, Verhalten beenden */
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ measureState=CORRECT_ANGLE;
+ break;
+
+ case TURN_BACK:
+ /* Bot in Ausgangsposition drehen */
+ if ((turnedLeft+turnedRight)/2>=0) {
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ measureState=TURN_COMPLETED;
+ break;
+ }
+ speedWishLeft = (measure_direction > 0) ? -BOT_SPEED_SLOW : BOT_SPEED_SLOW;
+ speedWishRight = (measure_direction > 0) ? BOT_SPEED_SLOW : -BOT_SPEED_SLOW;
+ break;
+
+ case CORRECT_ANGLE:
+ /* Evtl. etwas zuruecksetzen, falls wir zu weit gefahren sind */
+ if (turnedRight>0) {
+ /* rechts zu weit gefahren..langsam zurueck */
+ speedWishRight = (measure_direction > 0) ? -BOT_SPEED_SLOW : BOT_SPEED_SLOW;
+ } else if (turnedRight<0) {
+ /* rechts noch nicht weit genug...langsam vor */
+ speedWishRight = (measure_direction > 0) ? BOT_SPEED_SLOW : -BOT_SPEED_SLOW;
+ } else {
+ /* Endposition erreicht, rechtes Rad anhalten */
+ speedWishRight = BOT_SPEED_STOP;
+ }
+ if (turnedLeft<0) {
+ /* links zu weit gefahren..langsam zurueck */
+ speedWishLeft = (measure_direction > 0) ? -BOT_SPEED_SLOW : BOT_SPEED_SLOW;
+ } else if (turnedLeft>0) {
+ /* links noch nicht weit genug...langsam vor */
+ speedWishLeft = (measure_direction > 0) ? BOT_SPEED_SLOW : -BOT_SPEED_SLOW;
+ } else {
+ /* Endposition erreicht, linkes Rad anhalten */
+ speedWishLeft = BOT_SPEED_STOP;
+ }
+ if (speedWishLeft == BOT_SPEED_STOP && speedWishRight == BOT_SPEED_STOP) {
+ /* beide Raeder haben nun wirklich die Endposition erreicht, daher anhalten */
+ measureState=MEASUREMENT_DONE;
+ }
+ break;
+
+ case MEASUREMENT_DONE:
+ measureState=MEASURE_TURN;
+ return_from_behaviour(caller);
+ break;
+ }
+}
+
+/*!
+ * Das Verhalten dreht den Bot in die angegebene Richtung bis ein Hindernis
+ * im Sichtbereich erscheint, das eine Entfernung bis max. zur angegebenen
+ * Distanz zum Bot hat.
+ */
+
+void bot_measure_angle(Behaviour_t *caller, int8 direction, int16 distance) {
+ /* maximale Messentfernung und Richtung setzen */
+ measure_direction=direction;
+ measure_distance=distance;
+ /* Encoderwerte zu Anfang des Verhaltens merken */
+ startEncL=sensEncL;
+ startEncR=sensEncR;
+ switch_to_behaviour(caller, bot_measure_angle_behaviour,NOOVERRIDE);
+}
+#endif
+/*!
+ * Das Verhalten findet seinen Weg durch ein Labyrinth, das nach gewissen Grundregeln gebaut ist
+ * in nicht immer optimaler Weise aber in jedem Fall. Es arbeitet nach dem Hoehlenforscher-Algorithmus.
+ * Einschraenkung: Objekte im Labyrinth, die Endlossschleifen verursachen koennen, z.b. ein einzeln
+ * stehender Pfeiler im Labyrinth um den der Bot dann immer wieder herum fahren wuerde.
+ */
+void bot_solve_maze_behaviour(Behaviour_t *data){
+ /* Zustaende fuer das bot_solve_maze_behaviour-Verhalten */
+ #define CHECK_FOR_STARTPAD 0
+ #define CHECK_FOR_WALL_RIGHT 1
+ #define CHECK_FOR_WALL_LEFT 2
+ #define CHECK_WALL_PRESENT 3
+ #define SOLVE_MAZE_LOOP 4
+ #define SOLVE_TURN_WALL 5
+ #define CHECK_CONDITION 6
+ #define TURN_TO_BRANCH 7
+ #define DETECTED_CROSS_BRANCH 8
+ #define APPROACH_CORNER 9
+ #define AVOID_ABYSS 10
+ #define REACHED_GOAL 11
+ static int8 mazeState=CHECK_FOR_STARTPAD;
+ static int8 followWall=-1;
+ static int8 checkedWalls=0;
+
+ int16 distance;
+ double x;
+ switch(mazeState) {
+ case CHECK_FOR_STARTPAD:
+ /* Wo beginnen wir, nach einer Wand zu suchen?
+ * Abgrund- und Kollisions-Verhalten ausschalten */
+ #ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
+ deactivateBehaviour(bot_avoid_col_behaviour);
+ #endif
+ #ifdef BEHAVIOUR_AVOID_BORDER_AVAILABLE
+ deactivateBehaviour(bot_avoid_border_behaviour);
+ #endif
+ /* sieht nach, ob der Bot auf einem definierten Startpad steht und
+ * beginnt dann mit der Suche gleich an der richtigen Wand */
+ /* Zuserst bei nach Startpad1 gucken */
+ checkedWalls=0;
+ if ((sensLineL>=STARTPAD1-10 && sensLineL<=STARTPAD1+10) ||
+ (sensLineR>=STARTPAD1-10 && sensLineR<=STARTPAD1+10)) {
+ mazeState=CHECK_FOR_WALL_LEFT;
+ break;
+ }
+ mazeState=CHECK_FOR_WALL_RIGHT;
+ break;
+
+ case CHECK_FOR_WALL_RIGHT:
+
+ mazeState=CHECK_WALL_PRESENT;
+ followWall=CHECK_WALL_RIGHT;
+ bot_check_wall(data,followWall);
+ break;
+
+ case CHECK_FOR_WALL_LEFT:
+
+ followWall=CHECK_WALL_LEFT;
+ bot_check_wall(data,followWall);
+ mazeState=CHECK_WALL_PRESENT;
+ break;
+
+
+ case CHECK_WALL_PRESENT:
+ /* wenn keine Wand gefunden aber links noch nicht nachgesehen, andere
+ * Richtung checken, sonst vorfahren */
+ checkedWalls++;
+ if (wall_detected==False){
+ /* Wand noch nicht entdeckt...haben wir schon beide gecheckt? */
+ if (checkedWalls<2) {
+ if (followWall==CHECK_WALL_RIGHT) {
+ mazeState=CHECK_FOR_WALL_LEFT;
+ break;
+ } else {
+ mazeState=CHECK_FOR_WALL_RIGHT;
+ break;
+ }
+ } else {
+ /* keine wand? dann vorfahren und selbes prozedere nochmal */
+ bot_drive_distance(data,0,BOT_SPEED_NORMAL,BOT_DIAMETER);
+ mazeState=CHECK_FOR_WALL_RIGHT;
+ checkedWalls=0;
+ break;
+ }
+ }
+ /* ok, wir haben unsere richtung im labyrinth gefunden jetzt dieser
+ * nur noch folgen bis Ziel, Abzweig oder Abgrund */
+ mazeState=SOLVE_MAZE_LOOP;
+ break;
+
+ case SOLVE_MAZE_LOOP:
+ /* Einen Schritt (=halbe BOT-Groesse) vorwaerts */
+ mazeState=SOLVE_TURN_WALL;
+ bot_drive_distance(data,0,BOT_SPEED_NORMAL,BOT_DIAMETER);
+ break;
+
+ case SOLVE_TURN_WALL:
+ /* Ziel erreicht? */
+ if ((sensLineL>GROUND_GOAL-20 && sensLineL<GROUND_GOAL+20) ||
+ (sensLineR>GROUND_GOAL-20 && sensLineR<GROUND_GOAL+20)) {
+ /* Bot hat Ziel erreicht...aus Freude einmal um die Achse drehen */
+ bot_turn(data,360);
+ mazeState=REACHED_GOAL;
+ break;
+ }
+ /* checken, ob wand vor uns (Abstand 2.5*Bot-Durchmesser in mm) */
+ distance=(sensDistL+sensDistR)/2;
+ if (distance<=25*BOT_DIAMETER) { // umrechnen 10*BOT_DIAMETER, da letzteres in cm angegeben wird
+ /* berechnete Entfernung zur Wand abzueglich optimale Distanz fahren */
+ mazeState=DETECTED_CROSS_BRANCH;
+ bot_drive_distance(data,0,BOT_SPEED_NORMAL,(distance-OPTIMAL_DISTANCE)/10);
+ break;
+ }
+ /* Zur Wand drehen....ist die Wand noch da? */
+ mazeState=CHECK_CONDITION;
+ bot_check_wall(data,followWall);
+ break;
+
+ case CHECK_CONDITION:
+ /* Solange weiter, wie die Wand zu sehen ist */
+ if (wall_detected==True) {
+ mazeState=SOLVE_MAZE_LOOP;
+ break;
+ }
+ /* messen, wo genau die Ecke ist */
+ mazeState=APPROACH_CORNER;
+ if (followWall==CHECK_WALL_LEFT){
+ bot_measure_angle(data,MEASURE_LEFT,300);
+ } else {
+ bot_measure_angle(data,MEASURE_RIGHT,300);
+ }
+ break;
+
+ case TURN_TO_BRANCH:
+ /* nun in Richtung Abzweig drehen , dann mit Hauptschleife weiter*/
+ mazeState=SOLVE_MAZE_LOOP;
+ if (followWall==CHECK_WALL_RIGHT) {
+ bot_turn(data,-90);
+ } else {
+ bot_turn(data,90);
+ }
+ break;
+
+ case DETECTED_CROSS_BRANCH:
+ /* Bot faehrt auf eine Ecke zu, in Richtung Gang drehen */
+ if (followWall==CHECK_WALL_LEFT) {
+ mazeState=SOLVE_MAZE_LOOP;
+ bot_turn(data,-90);
+ } else {
+ mazeState=SOLVE_MAZE_LOOP;
+ bot_turn(data,90);
+ }
+ break;
+
+ case APPROACH_CORNER:
+ /* ok, nun strecke bis zur Kante berechnen */
+ x=measure_distance*cos(measured_angle*M_PI/180)/10+BOT_DIAMETER*1.5;
+ mazeState=TURN_TO_BRANCH;
+ bot_drive_distance(data,0,BOT_SPEED_NORMAL,(int16)x);
+ break;
+
+ case REACHED_GOAL:
+ mazeState=CHECK_WALL_RIGHT;
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ return_from_behaviour(data);
+ break;
+ }
+}
+
+
+/*!
+ * Das Verhalten findet seinen Weg durch ein Labyrinth, das nach gewissen Grundregeln gebaut ist
+ * in nicht immer optimaler Weise aber in jedem Fall. Es arbeitet nach dem Hoehlenforscher-Algorithmus.
+ * Einschraenkung: Objekte im Labyrinth, die Endlossschleifen verursachen koennen, z.b. ein einzeln
+ * stehender Pfeiler im Labyrinth um den der Bot dann immer wieder herum fahren wuerde.
+ */
+
+void bot_solve_maze(Behaviour_t *caller){
+ LOG_DEBUG(("bot_solve_maze()"));
+ switch_to_behaviour(caller, bot_solve_maze_behaviour,NOOVERRIDE);
+}
+
+/*!
+ * Initialisiert den Hoelenforscher
+ * @param prio_main Prioritaet des Hoehlenforschers (typ. 100)
+ * @param prio_helper Prioritaet der Hilfsfunktionen (typ. 42)
+ * @param active ACTIVE wenn der hoehlenforcher sofort starten soll, sonst INACTIVE
+ */
+void bot_solve_maze_init(int8 prio_main,int8 prio_helper, int8 active){
+ // Verhalten, um ein Labyrinth nach der Hoehlenforscher-Methode loesen
+ insert_behaviour_to_list(&behaviour, new_behaviour(prio_main, bot_solve_maze_behaviour,active));
+
+ insert_behaviour_to_list(&behaviour, new_behaviour(prio_helper--, bot_measure_angle_behaviour,INACTIVE));
+ insert_behaviour_to_list(&behaviour, new_behaviour(prio_helper, bot_check_wall_behaviour,INACTIVE));
+
+}
+#endif
diff --git a/source/ct-Bot/bot-logic/behaviour_turn.c b/source/ct-Bot/bot-logic/behaviour_turn.c
new file mode 100644
index 0000000..5b53c89
--- /dev/null
+++ b/source/ct-Bot/bot-logic/behaviour_turn.c
@@ -0,0 +1,361 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_turn.c
+ * @brief Drehe den Bot
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+
+#include "bot-logic/bot-logik.h"
+
+#ifdef BEHAVIOUR_TURN_AVAILABLE
+#ifdef MCU
+ #include <avr/eeprom.h>
+#endif
+#include <stdlib.h>
+#include <math.h>
+
+/* Parameter fuer das bot_turn_behaviour() */
+#ifndef MEASURE_MOUSE_AVAILABLE
+int16 turn_targetR; /*!< Zu drehender Winkel bzw. angepeilter Stand des Radencoders sensEncR */
+int16 turn_targetL; /*!< Zu drehender Winkel bzw. angepeilter Stand des Radencoders sensEncL */
+#else
+int8 angle_correct=0; /*!< Drehabschnitt 0=0-15Grad, 1=16-45 Grad, 2= >45 Grad */
+int16 to_turn; /*!< Wieviel Grad sind noch zu drehen? */
+ #ifdef MCU
+ uint8 __attribute__ ((section (".eeprom"))) err15=1; /*!< Fehler bei Drehungen unter 15 Grad */
+ uint8 __attribute__ ((section (".eeprom"))) err45=2; /*!< Fehler bei Drehungen zwischen 15 und 45 Grad */
+ uint8 __attribute__ ((section (".eeprom"))) err_big=4; /*!< Fehler bei groesseren Drehungen */
+ #else
+ uint8 err15=0;
+ uint8 err45=0;
+ uint8 err_big=0;
+ #endif
+#endif
+int8 turn_direction; /*!< Richtung der Drehung */
+
+
+/* Hilfsfunktion zur Berechnung einer Winkeldifferenz */
+inline int16 calc_turned_angle(int8 direction, int16 angle1, int16 angle2) {
+ int16 diff_angle=0;
+
+ if (direction>0){
+ // Drehung in mathematisch positivem Sinn
+ if (angle1>angle2) {
+ // Es gab einen Ueberlauf
+ diff_angle=360-angle1+angle2;
+ } else {
+ diff_angle=angle2-angle1;
+ }
+ } else {
+ // Drehung in mathematisch negativem Sinn
+ if (angle1<angle2) {
+ // Es gab einen Ueberlauf
+ diff_angle=angle1+360-angle2;
+ } else {
+ diff_angle=angle1-angle2;
+ }
+ }
+ return diff_angle;
+}
+
+#ifdef MEASURE_MOUSE_AVAILABLE
+ /*!
+ * Das Verhalten laesst den Bot eine Punktdrehung durchfuehren.
++ * Drehen findet in drei Schritten statt. Die Drehung wird dabei
++ * bei Winkeln > 15 Grad zunaechst mit hoeherer Geschwindigkeit ausgefuehrt. Bei kleineren
++ * Winkeln oder wenn nur noch 15 Grad zu drehen sind, nur noch mit geringer Geschwindigkeit
+ * @param *data der Verhaltensdatensatz
+ * @see bot_turn()
+ */
+void bot_turn_behaviour(Behaviour_t *data){
+ // Zustaende fuer das bot_turn_behaviour-Verhalten
+ #define NORMAL_TURN 0
+ #define STOP_TURN 1
+ #define FULL_STOP 2
+ static int8 turnState=NORMAL_TURN;
+ static int16 old_heading=-1;
+ static int16 head_count=0;
+ uint8 e15;
+ uint8 e45;
+ uint8 ebig;
+
+ // seit dem letzten mal gedrehte Grad
+ int16 turned=0;
+ // aktueller Winkel als int16
+ int16 akt_heading=(int16)heading_mou;
+
+ // erster Aufruf? -> alter Winkel==neuer Winkel
+ if (old_heading==-1) old_heading=akt_heading;
+
+ // berechnen, wieviel Grad seit dem letzten Aufruf gedreht wurden
+ turned=calc_turned_angle(turn_direction,old_heading,akt_heading);
+ if (turned > 300) turned -= 360; // hier ging etwas schief
+
+ // aktueller Winkel wird alter Winkel
+ old_heading=akt_heading;
+ // aktuelle Drehung von zu drehendem Winkel abziehen
+ to_turn-=turned;
+
+ switch(turnState) {
+ case NORMAL_TURN:
+ // Solange drehen, bis Drehwinkel erreicht ist
+ // oder gar zu weit gedreht wurde
+ if (to_turn<1) {
+ /* Nachlauf abwarten */
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ turnState=STOP_TURN;
+ break;
+ }
+ speedWishLeft = (turn_direction > 0) ? -BOT_SPEED_NORMAL : BOT_SPEED_NORMAL; speedWishLeft = (turn_direction > 0) ? -BOT_SPEED_SLOW : BOT_SPEED_SLOW;
+ speedWishRight = (turn_direction > 0) ? BOT_SPEED_NORMAL : -BOT_SPEED_NORMAL; speedWishRight = (turn_direction > 0) ? BOT_SPEED_SLOW : -BOT_SPEED_SLOW;
+ break;
+
+ case STOP_TURN:
+ // Abwarten, bis Nachlauf beendet
+ if (akt_heading!=old_heading){
+ head_count=0;
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ break;
+ }
+ if (head_count<10) {
+ head_count++;
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ break;
+ }
+ #ifdef MCU
+ e15=eeprom_read_byte(&err15);
+ e45=eeprom_read_byte(&err45);
+ ebig=eeprom_read_byte(&err_big);
+ #else
+ e15=err15;
+ e45=err45;
+ ebig=err_big;
+ #endif
+
+ // Neue Abweichung mit alter vergleichen und ggfs neu bestimmen
+
+ switch(angle_correct) {
+ case 0:
+ if (abs(to_turn)-e15>1) {
+ e15=(int8)(abs(to_turn)+e15)/2;
+ #ifdef MCU
+ eeprom_write_byte(&err15,e15);
+ #else
+ err15=e15;
+ #endif
+ }
+ break;
+
+ case 1:
+ if (abs(to_turn)-e45>1) {
+ e45=(int8)(abs(to_turn)+e45)/2;
+ #ifdef MCU
+ eeprom_write_byte(&err45,e45);
+ #else
+ err45=e45;
+ #endif
+ }
+ break;
+
+ case 2:
+ if (abs(to_turn)-ebig>1) {
+ ebig=(int8)(abs(to_turn)+ebig)/2;
+ #ifdef MCU
+ eeprom_write_byte(&err_big,ebig);
+ #else
+ err_big=ebig;
+ #endif
+ }
+ break;
+ }
+ // ok, verhalten beenden
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ turnState=NORMAL_TURN;
+ old_heading=-1;
+ return_from_behaviour(data);
+ break;
+ }
+}
+
+void bot_turn(Behaviour_t *caller, int16 degrees)
+{
+ // Richtungsgerechte Umrechnung in den Zielwinkel
+ if(degrees < 0) turn_direction = -1;
+ else turn_direction = 1;
+ to_turn=abs(degrees);
+ #ifdef MCU
+ if (eeprom_read_byte(&err15)==255 && eeprom_read_byte(&err45)==255 && eeprom_read_byte(&err_big)==255) {
+ eeprom_write_byte(&err15,1);
+ eeprom_write_byte(&err45,2);
+ eeprom_write_byte(&err_big,4);
+ }
+ if (to_turn>45) {
+ to_turn-=eeprom_read_byte(&err_big);
+ angle_correct=2;
+ } else if (to_turn<=45 && to_turn>15) {
+ to_turn-=eeprom_read_byte(&err45);
+ angle_correct=1;
+ } else {
+ to_turn-=eeprom_read_byte(&err15);
+ angle_correct=0;
+ }
+ #else
+ if (to_turn>45) {
+ to_turn-=err_big;
+ angle_correct=2;
+ } else if (to_turn<=45 && to_turn>15) {
+ to_turn-=err45;
+ angle_correct=1;
+ } else {
+ to_turn-=err15;
+ angle_correct=0;
+ }
+ #endif
+ switch_to_behaviour(caller, bot_turn_behaviour,NOOVERRIDE);
+ }
+#else
+/*!
+ * Das Verhalten laesst den Bot eine Punktdrehung durchfuehren.
+ * @see bot_turn()
+ * */
+void bot_turn_behaviour(Behaviour_t* data){
+ /* Drehen findet in vier Schritten statt. Die Drehung wird dabei
+ * bei Winkeln > 90 Grad zunaechst mit maximaler Geschwindigkeit ausgefuehrt. Bei kleineren
+ * Winkeln oder wenn nur noch 90 Grad zu drehen sind, nur noch mit normaler Geschwindigkeit
+ */
+ /* Zustaende fuer das bot_turn_behaviour-Verhalten */
+ #define NORMAL_TURN 0
+ #define SHORT_REVERSE 1
+ #define CORRECT_POSITION 2
+ #define FULL_STOP 3
+ static int8 turnState=NORMAL_TURN;
+ /* zu drehende Schritte in die korrekte Drehrichtung korrigieren */
+ int16 to_turnR = turn_direction*(turn_targetR - sensEncR);
+ int16 to_turnL = -turn_direction*(turn_targetL - sensEncL);
+
+ switch(turnState) {
+ case NORMAL_TURN:
+ /* Solange drehen, bis beide Encoder nur noch zwei oder weniger Schritte zu fahren haben */
+
+ if (to_turnL <= 2 && to_turnR<=2){
+ /* nur noch 2 Schritte oder weniger, abbremsen einleiten */
+ turnState=SHORT_REVERSE;
+ break;
+ }
+
+ /* Bis 90 Grad kann mit maximaler Geschwindigkeit gefahren werden, danach auf Normal reduzieren */
+ /* Geschwindigkeit fuer beide Raeder getrennt ermitteln */
+ if(abs(to_turnL) < ANGLE_CONSTANT*0.25) {
+ speedWishLeft = (turn_direction > 0) ? -BOT_SPEED_MEDIUM : BOT_SPEED_MEDIUM;
+ } else {
+ speedWishLeft = (turn_direction > 0) ? -BOT_SPEED_NORMAL : BOT_SPEED_NORMAL;
+ }
+
+ if(abs(to_turnR) < ANGLE_CONSTANT*0.25) {
+ speedWishRight = (turn_direction > 0) ? BOT_SPEED_MEDIUM : -BOT_SPEED_MEDIUM;
+ } else {
+ speedWishRight = (turn_direction > 0) ? BOT_SPEED_NORMAL : -BOT_SPEED_NORMAL;
+ }
+
+ break;
+
+ case SHORT_REVERSE:
+ /* Ganz kurz durch umpolen anbremsen */
+ speedWishLeft = (turn_direction > 0) ? BOT_SPEED_SLOW : -BOT_SPEED_SLOW;
+ speedWishRight = (turn_direction > 0) ? -BOT_SPEED_SLOW : BOT_SPEED_SLOW;
+ turnState=CORRECT_POSITION;
+ break;
+
+ case CORRECT_POSITION:
+ /* Evtl. etwas zuruecksetzen, falls wir zu weit gefahren sind */
+ if (to_turnR<0) {
+ /* rechts zu weit gefahren..langsam zurueck */
+ speedWishRight = (turn_direction > 0) ? -BOT_SPEED_SLOW : BOT_SPEED_SLOW;
+ } else if (to_turnR>0) {
+ /* rechts noch nicht weit genug...langsam vor */
+ speedWishRight = (turn_direction > 0) ? BOT_SPEED_SLOW : -BOT_SPEED_SLOW;
+ } else {
+ /* Endposition erreicht, rechtes Rad anhalten */
+ speedWishRight = BOT_SPEED_STOP;
+ }
+
+ if (to_turnL<0) {
+ /* links zu weit gefahren..langsam zurueck */
+ speedWishLeft = (turn_direction > 0) ? BOT_SPEED_SLOW : -BOT_SPEED_SLOW;
+ } else if (to_turnL>0) {
+ /* links noch nicht weit genug...langsam vor */
+ speedWishLeft = (turn_direction > 0) ? -BOT_SPEED_SLOW : BOT_SPEED_SLOW;
+ } else {
+ /* Endposition erreicht, linkes Rad anhalten */
+ speedWishLeft = BOT_SPEED_STOP;
+ }
+
+ if (speedWishLeft == BOT_SPEED_STOP && speedWishRight == BOT_SPEED_STOP) {
+ /* beide Raeder haben nun wirklich die Endposition erreicht, daher anhalten */
+ turnState=FULL_STOP;
+ }
+ break;
+
+
+ default:
+ /* ist gleichzeitig FULL_STOP, da gleiche Aktion
+ * Stoppen, State zuruecksetzen und Verhalten beenden */
+ speedWishLeft = BOT_SPEED_STOP;
+ speedWishRight = BOT_SPEED_STOP;
+ turnState=NORMAL_TURN;
+ return_from_behaviour(data);
+ break;
+ }
+}
+
+/*!
+ * Dreht den Bot im mathematisch positiven Sinn.
+ * @param degrees Grad, um die der Bot gedreht wird. Negative Zahlen drehen im (mathematisch negativen) Uhrzeigersinn.
+ * Die Aufloesung betraegt rund 3 Grad
+ */
+void bot_turn(Behaviour_t* caller,int16 degrees){
+ /* Umrechnung von Grad in Encoder-Markierungen.
+ * Hinweis: Eigentlich muessten der Umfang von Bot und Rad verwendet werden. Die Rechnung wird
+ * allerdings viel einfacher, wenn man Pi auskuerzt.
+ * Ist degrees negativ, ist die Drehung negativ und der rechte Encoder muss kleiner werden.
+ */
+
+ if(degrees < 0) turn_direction = -1;
+ else turn_direction = 1;
+ /* Anzahl zu fahrender Encoderschritte berechnen */
+ turn_targetR=(degrees*ANGLE_CONSTANT)/360;
+ /* linkes Rad dreht entgegengesetzt, daher negativer Wert */
+ turn_targetL=-turn_targetR;
+
+ /* aktuellen Sensorwert zu zu drehenden Encoderschritten addieren */
+ turn_targetR+=sensEncR;
+ turn_targetL+=sensEncL;
+ switch_to_behaviour(caller, bot_turn_behaviour,OVERRIDE);
+}
+#endif
+#endif
+
diff --git a/source/ct-Bot/bot-logic/bot-logik.c b/source/ct-Bot/bot-logic/bot-logik.c
new file mode 100644
index 0000000..3274375
--- /dev/null
+++ b/source/ct-Bot/bot-logic/bot-logik.c
@@ -0,0 +1,500 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file bot-logik.c
+ * @brief High-Level Routinen fuer die Steuerung des c't-Bots.
+ * Diese Datei sollte der Einstiegspunkt fuer eigene Experimente sein,
+ * den Roboter zu steuern.
+ *
+ * bot_behave() arbeitet eine Liste von Verhalten ab.
+ * Jedes Verhalten kann entweder absolute Werte setzen, dann kommen niedrigerpriorisierte nicht mehr dran.
+ * Alternativ dazu kann es Modifikatoren aufstellen, die bei niedriger priorisierten angewendet werden.
+ * bot_behave_init() baut diese Liste auf.
+ * Jede Verhaltensfunktion bekommt einen Verhaltensdatensatz uebergeben, in den Sie ihre Daten eintraegt
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @author Christoph Grimmer (c.grimmer@futurio.de)
+ * @date 01.12.05
+*/
+
+
+#include "bot-logic/bot-logik.h"
+
+#ifdef BEHAVIOUR_AVAILABLE
+
+#include "display.h"
+#include "rc5.h"
+
+
+
+#include <stdlib.h>
+
+int16 speedWishLeft; /*!< Puffervariablen fuer die Verhaltensfunktionen absolut Geschwindigkeit links*/
+int16 speedWishRight; /*!< Puffervariablen fuer die Verhaltensfunktionen absolut Geschwindigkeit rechts*/
+
+float faktorWishLeft; /*!< Puffervariablen fuer die Verhaltensfunktionen Modifikationsfaktor links*/
+float faktorWishRight; /*!< Puffervariablen fuer die Verhaltensfunktionen Modifikationsfaktor rechts */
+
+int16 target_speed_l=BOT_SPEED_STOP; /*!< Sollgeschwindigkeit linker Motor - darum kuemmert sich bot_base()*/
+int16 target_speed_r=BOT_SPEED_STOP; /*!< Sollgeschwindigkeit rechter Motor - darum kuemmert sich bot_base() */
+
+
+/*! Liste mit allen Verhalten */
+Behaviour_t *behaviour = NULL;
+
+/*!
+ * Das einfachste Grundverhalten
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_base_behaviour(Behaviour_t *data){
+ speedWishLeft=target_speed_l;
+ speedWishRight=target_speed_r;
+}
+
+/*!
+ * Initialisert das ganze Verhalten
+ */
+void bot_behave_init(void){
+ #ifdef BEHAVIOUR_REMOTECALL_AVAILABLE
+ // Dieses Verhalten kann andere Starten
+ insert_behaviour_to_list(&behaviour, new_behaviour(254, bot_remotecall_behaviour,INACTIVE));
+ #endif
+
+ #ifdef BEHAVIOUR_SERVO_AVAILABLE
+ insert_behaviour_to_list(&behaviour, new_behaviour(253, bot_servo_behaviour,INACTIVE));
+ #endif
+
+ // Demo-Verhalten, ganz einfach, inaktiv
+ // Achtung, im Moment hat es eine hoehere Prioritaet als die Gefahrenerkenner!!!
+ #ifdef BEHAVIOUR_SIMPLE_AVAILABLE
+ insert_behaviour_to_list(&behaviour, new_behaviour(252, bot_simple_behaviour,INACTIVE));
+ insert_behaviour_to_list(&behaviour, new_behaviour(251, bot_simple2_behaviour,INACTIVE));
+ #endif
+
+
+ // Hoechste Prioritate haben die Notfall Verhalten
+
+ // Verhalten zum Schutz des Bots, hohe Prioritaet, Aktiv
+ #ifdef BEHAVIOUR_AVOID_BORDER_AVAILABLE
+ insert_behaviour_to_list(&behaviour, new_behaviour(250, bot_avoid_border_behaviour,ACTIVE));
+ #endif
+ #ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
+ insert_behaviour_to_list(&behaviour, new_behaviour(249, bot_avoid_col_behaviour,ACTIVE));
+ #endif
+
+ #ifdef BEHAVIOUR_SCAN_AVAILABLE
+ // Verhalten, das die Umgebung des Bots on-the fly beim fahren scannt
+ insert_behaviour_to_list(&behaviour, new_behaviour(155, bot_scan_onthefly_behaviour,ACTIVE));
+
+ // Verhalten, das einmal die Umgebung des Bots scannt
+ insert_behaviour_to_list(&behaviour, new_behaviour(152, bot_scan_behaviour,INACTIVE));
+ #endif
+
+ // Alle Hilfsroutinen sind relativ wichtig, da sie auch von den Notverhalten her genutzt werden
+ // Hilfsverhalten, die Befehle von Boten-Funktionen ausfuehren, erst inaktiv, werden von Boten aktiviert
+ #ifdef BEHAVIOUR_TURN_AVAILABLE
+ insert_behaviour_to_list(&behaviour, new_behaviour(150, bot_turn_behaviour,INACTIVE));
+ #endif
+ #ifdef BEHAVIOUR_DRIVE_DISTANCE_AVAILABLE
+ insert_behaviour_to_list(&behaviour, new_behaviour(149, bot_drive_distance_behaviour,INACTIVE));
+ #endif
+ #ifdef BEHAVIOUR_GOTO_AVAILABLE
+ insert_behaviour_to_list(&behaviour, new_behaviour(148, bot_goto_behaviour,INACTIVE));
+ #endif
+
+ // Hilfsverhalten zum Anfahren von Positionen
+ #ifdef BEHAVIOUR_GOTOXY_AVAILABLE
+ insert_behaviour_to_list(&behaviour, new_behaviour(147, bot_gotoxy_behaviour,INACTIVE));
+ #endif
+
+
+ #ifdef BEHAVIOUR_CATCH_PILLAR_AVAILABLE
+ insert_behaviour_to_list(&behaviour, new_behaviour(44, bot_catch_pillar_behaviour,INACTIVE));
+ #endif
+
+
+ #ifdef BEHAVIOUR_OLYMPIC_AVAILABLE
+ bot_olympic_init(52,100,INACTIVE);
+ #endif
+
+ #ifdef BEHAVIOUR_FOLLOW_LINE_AVAILABLE
+ // Verhalten um einer Linie zu folgen
+ insert_behaviour_to_list(&behaviour, new_behaviour(70, bot_follow_line_behaviour, ACTIVE));
+ #endif
+
+ #ifdef BEHAVIOUR_SOLVE_MAZE_AVAILABLE
+ bot_solve_maze_init(100,43,INACTIVE);
+ #endif
+
+ #ifdef BEHAVIOUR_DRIVE_SQUARE_AVAILABLE
+ // Demo-Verhalten, etwas komplexer, inaktiv
+ insert_behaviour_to_list(&behaviour, new_behaviour(51, bot_drive_square_behaviour,INACTIVE));
+ #endif
+
+
+
+ // Grundverhalten, setzt aeltere FB-Befehle um, aktiv
+ insert_behaviour_to_list(&behaviour, new_behaviour(2, bot_base_behaviour, ACTIVE));
+
+ // Um das Simple-Behaviour zu nutzen, die Kommentarzeichen vor der folgenden Zeile entfernen!!!
+ // activateBehaviour(bot_simple_behaviour);
+ // activateBehaviour(bot_simple2_behaviour);
+
+ #ifdef PC
+ #ifdef DISPLAY_AVAILABLE
+ /* Anzeigen der geladenen Verhalten */
+ Behaviour_t *ptr = behaviour;
+
+ display_cursor(5,1);
+ display_printf("Verhaltensstack:\n");
+ while(ptr != NULL) {
+ display_printf("Prioritaet: %d.\n", ptr->priority);
+ ptr = ptr->next;
+ }
+ #endif
+ #endif
+}
+
+
+/*!
+ * Aktiviert eine Regel mit gegebener Funktion
+ * @param function Die Funktion, die das Verhalten realisiert.
+ */
+void activateBehaviour(BehaviourFunc function){
+ Behaviour_t *job; // Zeiger auf ein Verhalten
+
+ // Einmal durch die Liste gehen, bis wir den gewuenschten Eintrag haben
+ for (job = behaviour; job; job = job->next) {
+ if (job->work == function) {
+ job->active = ACTIVE;
+ break;
+ }
+ }
+}
+
+
+/*!
+ * Deaktiviert eine Regel mit gegebener Funktion
+ * @param function Die Funktion, die das Verhalten realisiert.
+ */
+void deactivateBehaviour(BehaviourFunc function){
+ Behaviour_t *job; // Zeiger auf ein Verhalten
+
+ // Einmal durch die Liste gehen, bis wir den gewuenschten Eintrag haben
+ for (job = behaviour; job; job = job->next) {
+ if (job->work == function) {
+ job->active = INACTIVE;
+ break;
+ }
+ }
+}
+
+/*!
+ * Ruft ein anderes Verhalten auf und merkt sich den Ruecksprung
+ * return_from_behaviour() kehrt dann spaeter wieder zum aufrufenden Verhalten zurueck
+ * @param from aufrufendes Verhalten
+ * @param to aufgerufenes Verhalten
+ * @param override Hier sind zwei Werte Moeglich:
+ * 1. OVERRIDE : Das Zielverhalten to wird aktiviert, auch wenn es noch aktiv ist.
+ * Das Verhalten, das es zuletzt aufgerufen hat wird dadurch automatisch
+ * wieder aktiv und muss selbst sein eigenes Feld subResult auswerten, um zu pruefen, ob das
+ * gewuenschte Ziel erreicht wurde, oder vorher ein Abbruch stattgefunden hat.
+ * 2. NOOVERRIDE : Das Zielverhalten wird nur aktiviert, wenn es gerade nichts zu tun hat.
+ * In diesem Fall kann der Aufrufer aus seinem eigenen subResult auslesen,
+ * ob seibem Wunsch Folge geleistet wurde.
+ */
+void switch_to_behaviour(Behaviour_t * from, void *to, uint8 override ){
+ Behaviour_t *job; // Zeiger auf ein Verhalten
+
+ // Einmal durch die Liste gehen, bis wir den gewuenschten Eintrag haben
+ for (job = behaviour; job; job = job->next) {
+ if (job->work == to) {
+ break; // Abbruch der Schleife, job zeigt nun auf die Datenstruktur des Zielverhaltens
+ }
+ }
+
+ if (job->caller){ // Ist das auzurufende Verhalten noch beschaeftigt?
+ if (override==NOOVERRIDE){ // nicht ueberschreiben, sofortige Rueckkehr
+ if (from)
+ from->subResult=SUBFAIL;
+ return;
+ }
+ // Wir wollen also ueberschreiben, aber nett zum alten Aufrufer sein und ihn darueber benachrichtigen
+ job->caller->active=ACTIVE; // alten Aufrufer reaktivieren
+ job->caller->subResult=SUBFAIL; // er bekam aber nicht das gewuenschte Resultat
+ }
+
+ if (from) {
+ // laufendes Verhalten abschalten
+ from->active=INACTIVE;
+ from->subResult=SUBRUNNING;
+ }
+
+ // neues Verhalten aktivieren
+ job->active=ACTIVE;
+ // Aufrufer sichern
+ job->caller = from;
+}
+
+/*!
+ * Kehrt zum aufrufenden Verhalten zurueck
+ * @param running laufendes Verhalten
+ */
+void return_from_behaviour(Behaviour_t * data){
+ data->active=INACTIVE; // Unterverhalten deaktivieren
+ if (data->caller){
+ data->caller->active=ACTIVE; // aufrufendes Verhalten aktivieren
+ data->caller->subResult=SUBSUCCESS; // Unterverhalten war erfolgreich
+ }
+ data->caller=NULL; // Job erledigt, Verweis loeschen
+}
+
+/*!
+ * Deaktiviert alle Verhalten bis auf Grundverhalten. Bei Verhaltensauswahl werden die Aktivitaeten vorher
+ * in die Verhaltens-Auswahlvariable gesichert.
+ */
+void deactivateAllBehaviours(void){
+ Behaviour_t *job; // Zeiger auf ein Verhalten
+
+ #ifdef DISPLAY_BEHAVIOUR_AVAILABLE
+ // bei Verhaltensanzeige in Aktivitaets-Auswahl-Variable sichern
+ #ifndef DISPLAY_DYNAMIC_BEHAVIOUR_AVAILABLE
+ // bei Verhaltensanzeige in Aktivitaets-Auswahl-Variable sichern
+ // nicht bei dynamischer Anzeige und Selektion
+ set_behaviours_equal();
+ #endif
+ #endif
+
+ // Einmal durch die Liste gehen und (fast) alle deaktivieren, Grundverhalten nicht
+ for (job = behaviour; job; job = job->next) {
+ if ((job->priority >= PRIO_VISIBLE_MIN) &&(job->priority <= PRIO_VISIBLE_MAX)) {
+ // Verhalten deaktivieren
+ job->active = INACTIVE;
+ }
+ }
+}
+
+/*!
+ * Zentrale Verhaltens-Routine, wird regelmaessig aufgerufen.
+ * Dies ist der richtige Platz fuer eigene Routinen, um den Bot zu steuern.
+ */
+void bot_behave(void){
+ Behaviour_t *job; // Zeiger auf ein Verhalten
+
+ float faktorLeft = 1.0; // Puffer fuer Modifkatoren
+ float faktorRight = 1.0; // Puffer fuer Modifkatoren
+
+ #ifdef RC5_AVAILABLE
+ rc5_control(); // Abfrage der IR-Fernbedienung
+ #endif
+
+ /* Solange noch Verhalten in der Liste sind...
+ (Achtung: Wir werten die Jobs sortiert nach Prioritaet aus. Wichtige zuerst einsortieren!!!) */
+ for (job = behaviour; job; job = job->next) {
+ if (job->active) {
+ /* WunschVariablen initialisieren */
+ speedWishLeft = BOT_SPEED_IGNORE;
+ speedWishRight = BOT_SPEED_IGNORE;
+
+ faktorWishLeft = 1.0;
+ faktorWishRight = 1.0;
+
+ job->work(job); /* Verhalten ausfuehren */
+ /* Modifikatoren sammeln */
+ faktorLeft *= faktorWishLeft;
+ faktorRight *= faktorWishRight;
+ /* Geschwindigkeit aendern? */
+ if ((speedWishLeft != BOT_SPEED_IGNORE) || (speedWishRight != BOT_SPEED_IGNORE)){
+ if (speedWishLeft != BOT_SPEED_IGNORE)
+ speedWishLeft *= faktorLeft;
+ if (speedWishRight != BOT_SPEED_IGNORE)
+ speedWishRight *= faktorRight;
+
+ motor_set(speedWishLeft, speedWishRight);
+ break; /* Wenn ein Verhalten Werte direkt setzen will, nicht weitermachen */
+ }
+
+ }
+ /* Dieser Punkt wird nur erreicht, wenn keine Regel im System die Motoren beeinflusen will */
+ if (job->next == NULL) {
+ motor_set(BOT_SPEED_IGNORE, BOT_SPEED_IGNORE);
+ }
+ }
+}
+
+/*!
+ * Erzeugt ein neues Verhalten
+ * @param priority Die Prioritaet
+ * @param *work Den Namen der Funktion, die sich drum kuemmert
+ */
+Behaviour_t *new_behaviour(uint8 priority, void (*work) (struct _Behaviour_t *data), int8 active){
+ Behaviour_t *newbehaviour = (Behaviour_t *) malloc(sizeof(Behaviour_t));
+
+ if (newbehaviour == NULL)
+ return NULL;
+
+ newbehaviour->priority = priority;
+ newbehaviour->active=active;
+ newbehaviour->next= NULL;
+ newbehaviour->work=work;
+ newbehaviour->caller=NULL;
+ newbehaviour->subResult=SUBSUCCESS;
+ return newbehaviour;
+}
+
+/*!
+ * Fuegt ein Verhalten der Verhaltenliste anhand der Prioritaet ein.
+ * @param list Die Speicherstelle an der die globale Verhaltensliste anfaengt
+ * @param behave Einzufuegendes Verhalten
+ */
+void insert_behaviour_to_list(Behaviour_t **list, Behaviour_t *behave){
+ Behaviour_t *ptr = *list;
+ Behaviour_t *temp = NULL;
+
+ /* Kein Eintrag dabei? */
+ if (behave == NULL)
+ return;
+
+ /* Erster Eintrag in der Liste? */
+ if (ptr == NULL){
+ ptr = behave;
+ *list = ptr;
+ } else {
+ /* Gleich mit erstem Eintrag tauschen? */
+ if (ptr->priority < behave->priority) {
+ behave->next = ptr;
+ ptr = behave;
+ *list = ptr;
+ } else {
+ /* Mit dem naechsten Eintrag vergleichen */
+ while(NULL != ptr->next) {
+ if (ptr->next->priority < behave->priority)
+ break;
+
+ /* Naechster Eintrag */
+ ptr = ptr->next;
+ }
+
+ temp = ptr->next;
+ ptr->next = behave;
+ behave->next = temp;
+ }
+ }
+}
+
+
+
+#ifdef DISPLAY_BEHAVIOUR_AVAILABLE
+
+/*!
+ * ermittelt ob noch eine weitere Verhaltensseite existiert
+ */
+ int8 another_behaviour_page(void) {
+ int16 max_behaviours ;
+ Behaviour_t *ptr ;
+
+ /* dazu muss ich auch gueltige Screenseite sein */
+ #ifdef DISPLAY_SCREENS_AVAILABLE
+ if (display_screen != 2)
+ return 0;
+ #endif
+
+ ptr = behaviour;
+ max_behaviours = 0;
+
+// zuerst alle Verhalten ermitteln ausser Grundverhalten
+ while(ptr != NULL) {
+ if ((ptr->priority >= PRIO_VISIBLE_MIN) &&(ptr->priority <= PRIO_VISIBLE_MAX))
+ max_behaviours++;
+
+ ptr = ptr->next;
+ }
+
+ return (behaviour_page * 6) < max_behaviours;
+}
+
+
+/*!
+ * toggled ein Verhalten der Verhaltensliste an Position pos,
+ * die Aenderung erfolgt nur auf die Puffervariable
+ * @param pos Listenposition, entspricht der Taste 1-6 der gewaehlten Verhaltensseite
+ */
+void toggleNewBehaviourPos(int8 pos){
+ Behaviour_t *job; // Zeiger auf ein Verhalten
+ int8 i;
+
+ // nur aendern, wenn ich richtige Screenseite bin
+ if (display_screen != 2)
+ return ;
+
+ // richtigen Index je nach Seite ermitteln
+ pos = (behaviour_page - 1) * 6 + pos;
+ i = 0;
+
+ // durch die Liste gehen, bis wir den gewuenschten Index erreicht haben
+ for (job = behaviour; job; job = job->next) {
+ if ((job->priority >= PRIO_VISIBLE_MIN) &&(job->priority <= PRIO_VISIBLE_MAX)) {
+ i++;
+ if (i == pos) {
+ // bei dynamischer Wahl wird direkt die Zustandsvariable geaendert
+ #ifdef DISPLAY_DYNAMIC_BEHAVIOUR_AVAILABLE
+ job->active = !job->active;
+ #else
+ job->active_new = !job->active_new;
+ #endif
+
+ break;
+ }
+ }
+ }
+}
+
+#ifndef DISPLAY_DYNAMIC_BEHAVIOUR_AVAILABLE
+/*!
+ * Startschuss, die gewaehlten neuen Verhaltensaktivitaeten werden in die
+ * Verhaltensliste geschrieben und die Verhalten damit scharf geschaltet
+ */
+void set_behaviours_active_to_new(void) {
+
+ Behaviour_t *job;
+ for (job = behaviour; job; job = job->next) {
+
+ if ((job->priority >= PRIO_VISIBLE_MIN) &&(job->priority <= PRIO_VISIBLE_MAX))
+ job->active = job->active_new;
+
+ }
+
+}
+
+/*!
+ * Die Aktivitaeten der Verhalten werden in die Puffervariable geschrieben,
+ * welche zur Anzeige und Auswahl verwendet wird
+ */
+void set_behaviours_equal(void) {
+ Behaviour_t *job;
+ for (job = behaviour; job; job = job->next) {
+
+ if ((job->priority >= PRIO_VISIBLE_MIN) &&(job->priority <= PRIO_VISIBLE_MAX))
+ job->active_new = job->active;
+
+ }
+}
+#endif
+#endif
+#endif
diff --git a/source/ct-Bot/command.c b/source/ct-Bot/command.c
new file mode 100644
index 0000000..a1993dd
--- /dev/null
+++ b/source/ct-Bot/command.c
@@ -0,0 +1,469 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file command.c
+ * @brief Kommando-Management
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 20.12.05
+*/
+
+#include "ct-Bot.h"
+
+#include "led.h"
+#include "log.h"
+
+#include "uart.h"
+#include "adc.h"
+#include "timer.h"
+#include "mouse.h"
+
+#include "command.h"
+#include "display.h"
+
+#include "sensor.h"
+#include "motor.h"
+#include "rc5.h"
+#include "ir-rc5.h"
+#include "bot-logic/bot-logik.h"
+#include "bot-2-pc.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef PC
+ #include "tcp.h"
+ #include <pthread.h>
+#endif
+
+#define COMMAND_TIMEOUT 10 /*!< Anzahl an ms, die maximal auf fehlende Daten gewartet wird */
+
+#ifdef COMMAND_AVAILABLE
+
+#define RCVBUFSIZE (sizeof(command_t)*2) /*!< Groesse des Empfangspuffers */
+
+command_t received_command; /*!< Puffer fuer Kommandos */
+
+#ifdef PC
+ // Auf dword alignment bestehen, wird fuer MacOS X benoetigt
+ pthread_mutex_t command_mutex __attribute__ ((aligned (4)))
+ = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+/*!
+ * Liest ein Kommando ein, ist blockierend!
+ * Greift auf low_read() zurueck
+ * Achtung, die Payload wird nicht mitgelesen!!!
+ * @see low_read()
+ */
+int8 command_read(void){
+ int bytesRcvd;
+ int start=0; // start des Kommandos
+ int i;
+ command_t * command; // Pointer zum Casten der empfangegen Daten
+ char * ptr; // Nur zu Hilfszwecken
+ char buffer[RCVBUFSIZE]; // Buffer
+ #if BYTE_ORDER == BIG_ENDIAN
+ uint16 store; //Puffer für die Endian-Konvertierung
+ #endif
+
+ uint16 old_ticks; // alte Systemzeit
+
+ buffer[0]=0; // Sicherheitshalber mit sauberem Puffer anfangen
+
+ // Daten holen, maximal soviele, wie ein Kommando lang ist
+ bytesRcvd=low_read(buffer,sizeof(command_t));
+
+ // LOG_DEBUG(("%d/%d read/av",bytesRcvd,tmp));
+ // LOG_DEBUG(("%x %x %x",buffer[0],buffer[1],buffer[2]));
+
+ // Suche nach dem Beginn des Frames
+ while ((start<bytesRcvd)&&(buffer[start] != CMD_STARTCODE)) {
+// printf("\nStartzeichen nicht am Anfang des Puffers! (%d)\n",start);
+// printf(".");
+ start++;
+ }
+
+ // Wenn keine STARTCODE gefunden ==> Daten verwerfen
+ if (buffer[start] != CMD_STARTCODE){
+ // LOG_DEBUG(("start not found"));
+ return -1;
+ }
+
+ // LOG_DEBUG(("Start @%d",start));
+
+ // haben wir noch genug Platz im Puffer, um das Packet ferig zu lesen?
+ if ((RCVBUFSIZE-start) < sizeof(command_t)){
+ // LOG_DEBUG(("not enough space"));
+// printf("not enough space");
+ return -1; // nein? ==> verwerfen
+ }
+
+ i=sizeof(command_t) - (bytesRcvd-start)-1;
+
+
+ if (i> 0) { // Fehlen noch Daten ?
+ LOG_DEBUG(("command.c: Start @ %d es fehlen %d bytes ",start,i));
+ // Systemzeit erfassen
+ old_ticks = TIMER_GET_TICKCOUNT_16;
+
+ // So lange Daten lesen, bis das Packet vollstaendig ist, oder der Timeout zuschlaegt
+ while (i > 0){
+ // Wenn der Timeout ueberschritten ist
+ if (TIMER_GET_TICKCOUNT_16-old_ticks > MS_TO_TICKS(COMMAND_TIMEOUT))
+ return -1; // ==> Abbruch
+ // LOG_DEBUG(("%d bytes missing",i));
+ i= low_read(buffer+bytesRcvd,i);
+ // LOG_DEBUG(("%d read",i));
+ bytesRcvd+=i;
+ i=sizeof(command_t) - (bytesRcvd-start);
+ }
+ }
+
+ // LOG_DEBUG(("%d/%d read/start",bytesRcvd,start));
+ // LOG_DEBUG(("%x %x %x",buffer[start],buffer[start+1],buffer[start+2]));
+
+ // Cast in command_t
+ command= (command_t *) ( buffer +start);
+
+ // LOG_DEBUG(("start: %x ",command->startCode));
+ // command_display(command);
+
+ // validate (startcode ist bereits ok, sonst waeren wir nicht hier )
+ if (command->CRC==CMD_STOPCODE){
+ // LOG_DEBUG(("Command is valid"));
+ // Transfer
+ #ifdef PC
+ command_lock(); // on PC make storage threadsafe
+ #endif
+ ptr = (char *) &received_command;
+ for (i=0; i<sizeof(command_t);i++){
+ *ptr=buffer[i+start];
+ ptr++;
+ }
+ #if BYTE_ORDER == BIG_ENDIAN
+ /* Umwandeln der 16 bit Werte in Big Endian */
+ store = received_command.data_l;
+ received_command.data_l = store << 8;
+ received_command.data_l |= (store >> 8) & 0xff;
+
+ store = received_command.data_r;
+ received_command.data_r = store << 8;
+ received_command.data_r |= (store >> 8) & 0xff;
+
+ store = received_command.seq;
+ received_command.seq = store << 8;
+ received_command.seq |= (store >> 8) & 0xff;
+
+ /* "Umdrehen" des Bitfields */
+ store = received_command.request.subcommand;
+ received_command.request.subcommand = store << 1;
+ received_command.request.direction = store >> 7;
+ #endif
+ #ifdef PC
+ command_unlock(); // on PC make storage threadsafe
+ #endif
+
+ return 0;
+ } else { // Command not valid
+ // LOG_DEBUG(("Invalid Command:"));
+ // LOG_DEBUG(("%x %x %x",command->startCode,command->request.command,command->CRC));
+ return -1;
+ }
+}
+
+static uint16 count=1; /*!< Zaehler fuer Paket-Sequenznummer*/
+
+/*!
+ * Uebertraegt ein Kommando und wartet nicht auf eine Antwort
+ * @param command Kennung zum Command
+ * @param subcommand Kennung des Subcommand
+ * @param data_l Daten fuer den linken Kanal
+ * @param data_r Daten fuer den rechten Kanal
+ * @param payload Anzahl der Bytes, die diesem Kommando als Payload folgen
+ */
+void command_write(uint8 command, uint8 subcommand, int16* data_l,int16* data_r,uint8 payload){
+ command_t cmd;
+
+
+ cmd.startCode=CMD_STARTCODE;
+ cmd.request.direction=DIR_REQUEST; // Anfrage
+ cmd.request.command= command;
+ cmd.request.subcommand= subcommand;
+
+ cmd.payload=payload;
+ if (data_l != NULL)
+ cmd.data_l = *data_l;
+ else
+ cmd.data_l = 0;
+
+ if (data_r != NULL)
+ cmd.data_r = *data_r;
+ else
+ cmd.data_r = 0;
+
+ cmd.seq=count++;
+ cmd.CRC=CMD_STOPCODE;
+
+ low_write(&cmd);
+}
+
+
+/*!
+ * Uebertraegt ein Kommando und wartet nicht auf eine Antwort
+ * @param command Kennung zum Command
+ * @param subcommand Kennung des Subcommand
+ * @param data_l Daten fuer den linken Kanal
+ * @param data_r Daten fuer den rechten Kanal
+ */
+//void command_write(uint8 command, uint8 subcommand, int16* data_l,int16* data_r){
+//}
+
+/*!
+ * Gibt dem Simulator Daten mit Anhang und wartet nicht auf Antwort
+ * @param command Kennung zum Command
+ * @param subcommand Kennung des Subcommand
+ * @param data_l Daten fuer den linken Kanal
+ * @param data_r Daten fuer den rechten Kanal
+ * @param payload Anzahl der Bytes im Anhang
+ * @param data Datenanhang an das eigentliche Command
+ */
+void command_write_rawdata(uint8 command, uint8 subcommand, int16* data_l, int16* data_r, uint8 payload, uint8* data){
+ command_write(command, subcommand, data_l, data_r,payload);
+ low_write_data(data, payload);
+}
+
+
+/*!
+ * Gibt dem Simulator Daten mit String-Anhang und wartet nicht auf Antwort
+ * @param command Kennung zum Command
+ * @param subcommand Kennung des Subcommand
+ * @param data_l Daten fuer den linken Kanal
+ * @param data_r Daten fuer den rechten Kanal
+ * @param data Datenanhang an das eigentliche Command
+ */
+void command_write_data(uint8 command, uint8 subcommand, int16* data_l, int16* data_r, const char* data){
+ size_t len;
+ uint8 payload;
+
+ if (data != NULL) {
+ len = strlen(data);
+ if (len > MAX_PAYLOAD) {
+ payload = MAX_PAYLOAD;
+ } else {
+ payload = len;
+ }
+ } else {
+ payload = 0;
+ }
+
+ command_write(command, subcommand, data_l, data_r,payload);
+ low_write_data((uint8 *)data, payload);
+}
+
+#ifdef MAUS_AVAILABLE
+ /*!
+ * Uebertraegt ein Bild vom Maussensor an den PC
+ */
+ void transmit_mouse_picture(void){
+ int16 dummy,i;
+
+ int16 pixel;
+ uint8 data;
+ maus_image_prepare();
+
+ for (i=0; i<6; i++) {
+ dummy= i*54 +1;
+ command_write(CMD_SENS_MOUSE_PICTURE, SUB_CMD_NORM, &dummy , &dummy,54);
+ for (pixel=0; pixel <54; pixel++){
+ data= maus_image_read();
+ low_write_data((uint8 *)&data,1);
+ }
+ }
+
+ }
+#endif
+
+
+/*!
+ * Wertet das Kommando im Puffer aus
+ * return 1, wenn Kommando schon bearbeitet wurde, 0 sonst
+ */
+int command_evaluate(void){
+ uint8 analyzed = 1;
+
+ #ifdef LOG_AVAILABLE
+ // command_display(&received_command);
+ #endif // LOG_AVAILABLE
+
+ switch (received_command.request.command) {
+ #ifdef IR_AVAILABLE
+ case CMD_SENS_RC5:
+ ir_data=received_command.data_l;
+ break;
+ #endif
+ case CMD_AKT_LED: // LED-Steuerung
+ LED_set(received_command.data_l & 255);
+ break;
+
+ // Einige Kommandos ergeben nur fuer reale Bots Sinn
+ case CMD_WELCOME:
+ #ifdef MCU
+ command_write(CMD_WELCOME, SUB_WELCOME_REAL,0,0,0);
+ #else
+ command_write(CMD_WELCOME, SUB_WELCOME_SIM,0,0,0);
+ #endif
+ break;
+
+
+ #ifdef MAUS_AVAILABLE
+ case CMD_SENS_MOUSE_PICTURE: // PC fragt nach dem Bild
+ transmit_mouse_picture();
+ break;
+ #endif
+
+ #ifdef BEHAVIOUR_REMOTECALL_AVAILABLE
+ case CMD_REMOTE_CALL:
+ switch (received_command.request.subcommand) {
+ case SUB_REMOTE_CALL_LIST:
+ remote_call_list();
+ break;
+ case SUB_REMOTE_CALL_ORDER:
+ {
+ uint8 buffer[REMOTE_CALL_BUFFER_SIZE];
+ low_read(buffer,received_command.payload);
+ bot_remotecall_from_command((uint8 *)&buffer);
+
+ break;
+ }
+ default:
+ LOG_DEBUG(("unbekanntes Subkommando: %c",received_command.request.subcommand));
+ break;
+ }
+ break;
+ #endif
+
+
+ // Einige Kommandos ergeben nur fuer simulierte Bots Sinn
+ #ifdef PC
+ case CMD_SENS_IR:
+ sensor_abstand(received_command.data_l,received_command.data_r);
+ break;
+ case CMD_SENS_ENC:
+ sensEncL+=received_command.data_l;
+ sensEncR+=received_command.data_r;
+ break;
+ case CMD_SENS_BORDER:
+ sensBorderL=received_command.data_l;
+ sensBorderR=received_command.data_r;
+ break;
+ case CMD_SENS_LINE:
+ sensLineL=received_command.data_l;
+ sensLineR=received_command.data_r;
+ break;
+ case CMD_SENS_LDR:
+ sensLDRL=received_command.data_l;
+ sensLDRR=received_command.data_r;
+ break;
+ case CMD_SENS_TRANS:
+ sensTrans=(char)received_command.data_l;
+ break;
+ #ifdef MAUS_AVAILABLE
+ case CMD_SENS_MOUSE:
+ sensMouseDX=received_command.data_l;
+ sensMouseDY=received_command.data_r;
+ break;
+ #endif
+ case CMD_SENS_ERROR:
+ sensError=(char)received_command.data_l;
+ sensor_update(); /* Error ist der letzte uebertragene Sensorwert, danach koennen wir uns um allgemeine updates kümmern*/
+ break;
+ case CMD_DONE:
+ simultime=received_command.data_l;
+ system_time_isr(); /* Einmal pro Update-Zyklus aktualisieren wir die Systemzeit */
+ // printf("X-Frame for Simultime = %d received ",simultime);
+ break;
+ #endif
+ default:
+ analyzed=0; // Command was not analysed yet
+ break;
+ }
+ return analyzed;
+}
+
+
+
+#ifdef LOG_AVAILABLE
+/*!
+ * Gibt ein Kommando auf dem Bildschirm aus
+ */
+ void command_display(command_t * command){
+ #ifdef PC
+/* printf("START= %d\nDIR= %d CMD= %d SUBCMD= %d\nPayload= %d\nDATA = %d %d\nSeq= %d\nCRC= %d",
+ (*command).startCode,
+ (*command).request.direction,
+ (*command).request.command,
+ (*command).request.subcommand,
+ (*command).payload,
+ (*command).data_l,
+ (*command).data_r,
+ (*command).seq,
+ (*command).CRC);
+*/
+ LOG_DEBUG(("CMD: %c\tData L: %d\tSeq: %d\n",
+ (*command).request.command,
+ (*command).data_l,
+ (*command).seq));
+ #else
+ LOG_DEBUG(("%x %x %x",
+ (*command).request.command,
+ (*command).data_l,
+ (*command).seq));
+
+/* char* raw= (char*)command;
+ unsigned char i=0;
+ char hex[6];
+
+ display_cursor(4,1);
+ display_string("0x");
+ to_hex(*raw,hex);
+ display_string(hex);
+ display_string(" ");
+ raw++;
+
+ for (i=1; i<sizeof(command_t)-1; i++){
+ to_hex(*raw++,hex);
+ display_string(hex);
+ }
+
+ display_string(" ");
+ to_hex(*raw,hex);
+ display_string(hex);
+
+ sprintf(hex,"%5d",(*command).seq);
+ display_string(" ");
+ display_string(hex);
+*/
+ #ifdef WIN32
+ printf("\n");
+ #endif
+
+ #endif
+ }
+#endif
+#endif
diff --git a/source/ct-Bot/contrib/bot.map.zip b/source/ct-Bot/contrib/bot.map.zip
new file mode 100644
index 0000000..68d740f
--- /dev/null
+++ b/source/ct-Bot/contrib/bot.map.zip
Binary files differ
diff --git a/source/ct-Bot/contrib/flash_n_fuse/STK200.bat b/source/ct-Bot/contrib/flash_n_fuse/STK200.bat
new file mode 100644
index 0000000..156e122
--- /dev/null
+++ b/source/ct-Bot/contrib/flash_n_fuse/STK200.bat
@@ -0,0 +1,39 @@
+rem Aufruf von Avrdude zur Programmierung c't-Bot
+
+rem (Unten sollte zunaechst der Pfad angepasst werden)
+
+rem Batchdatei fuer Programmieradapter STK200 und viele baugleiche Programmer am Parallelport
+rem
+rem von andreas Staudenmayer (andreas.staudenmayer@t-online.de)
+rem angepasst fuer STK200 (rl@loehmer.de)
+rem Parameter
+rem
+rem -p m32 fuer ATMega32
+rem -c stk200 Adapter kompatibel zu stk200
+rem -P lpt1 Adapter installiert auf lpt1
+rem -u disable safemode, um fusebits setzen zu koennen
+rem -U flash:w:<Datei>:i Programmdatei, die geschrieben werden soll, wird als erster Batch Parameter uebergeben
+rem
+rem -U lfuse:w:lfuse.hex:i lowfusebits setzen, Inhalt Bin-Datei lfuse.hex: FF
+rem -U hfuse:w:hfuse.hex:i highfusebits setzen, Inhalt Bin-Datei hfuse.hex: D9
+rem -U lock:w:lock.hex:i lockbits setzen, Inhalt Bin-Datei lock.hex: 3F
+rem -F Signatur des Chips lesen
+rem -v geschwaetzige Ausgabe
+rem -E reset Reset wenn fertig
+rem -e Chip loeschen
+
+rem Moeglichkeit 1:
+rem Verknuepfung auf avrdude-Batchdatei auf dem Desktop ablegen,
+rem "Fallenlassen" einer Hex-Datei auf diese Verknuepfung startet
+rem den Programmierprozess
+
+rem Moeglichkeit 2:
+rem Nutzung von ECLIPSE 'External Tools'
+rem kurze Anleitung :
+rem http://www.ctbot.de/forum/fuse-bits-t108-15.html#2372
+
+
+rem !!!Anfuehrungsstriche sind wichtig bei Pfaden mit Leerstellen!!!
+rem Die naechste Zeile ist schon alles! Pfad fuer AVRDUDE anpassen!
+
+"D:\Programme\WinAVR\bin\avrdude" -p m32 -c stk200 -P lpt1 -U flash:w:%1:i -e -F -v -E reset \ No newline at end of file
diff --git a/source/ct-Bot/contrib/flash_n_fuse/STK200Fuses.bat b/source/ct-Bot/contrib/flash_n_fuse/STK200Fuses.bat
new file mode 100644
index 0000000..c153560
--- /dev/null
+++ b/source/ct-Bot/contrib/flash_n_fuse/STK200Fuses.bat
@@ -0,0 +1,24 @@
+rem Aufruf von Avrdude zur Programmierung c't-Bot
+rem Setzen der Fuses/Locks ist EINMALIG vor der ersten Programmierung NOTWENDIG
+rem weiteres hier: http://www.heise.de/ct/ftp/projekte/ct-bot/faq/f.shtml
+
+rem (Unten sollte zunaechst der Pfad angepasst werden)
+
+rem Batchdatei fuer Programmieradapter STK200 und viele baugleiche Programmer am Parallelport
+rem
+rem von andreas Staudenmayer (andreas.staudenmayer@t-online.de)
+rem angepasst fuer STK200 (rl@loehmer.de)
+rem Parameter
+rem
+rem -p m32 fuer ATMega32
+rem -c stk200 Adapter kompatibel zu stk200
+rem -P lpt1 Adapter installiert auf lpt1
+rem -u disable safemode, um fusebits setzen zu koennen
+rem -U flash:w:<Datei>:i Programmdatei, die geschrieben werden soll, wird als erster Batch Parameter übergeben
+rem
+rem -U lfuse:w:lfuse.hex:i lowfusebits setzen, Inhalt Bin-Datei lfuse.hex: FF
+rem -U hfuse:w:hfuse.hex:i highfusebits setzen, Inhalt Bin-Datei hfuse.hex: D9
+rem -U lock:w:lock.hex:i lockbits setzen, Inhalt Bin-Datei lock.hex: 3F
+
+rem auch hier den Pfad setzen
+"D:\Programme\WinAVR\bin\avrdude" -p m32 -c stk200 -P lpt1 -u -U lfuse:w:lfuse.hex:i -U hfuse:w:hfuse.hex:i -U lock:w:lock.hex:i \ No newline at end of file
diff --git a/source/ct-Bot/contrib/flash_n_fuse/flash.bat b/source/ct-Bot/contrib/flash_n_fuse/flash.bat
new file mode 100644
index 0000000..3993431
--- /dev/null
+++ b/source/ct-Bot/contrib/flash_n_fuse/flash.bat
@@ -0,0 +1,21 @@
+rem Aufruf von Avrdude zur Programmierung c't-Bot
+rem Batchdatei für Programmieradapter mysmartUSB
+rem
+rem von andreas Staudenmayer (andreas.staudenmayer@t-online.de)
+rem Parameter
+rem
+rem -p m32 für ATMega32
+rem -c avr910 Adapter kompatibel zu avr910
+rem -P com5 Adapter installiert auf com5
+rem -u disable safemode, um fusebits setzen zu können
+rem -U flash:w:<Datei>:i Programmdatei, die geschrieben werden soll, wird als erster Batch Parameter übergeben
+rem
+rem -U lfuse:w:lfuse.hex:i lowfusebits setzen, Inhalt Bin-Datei lfuse.hex: FF
+rem -U hfuse:w:hfuse.hex:i highfusebits setzen, Inhalt Bin-Datei hfuse.hex: D9
+rem -U lock:w:lock.hex:i lockbits setzen, Inhalt Bin-Datei lock.hex: 3F
+
+rem Verknüpfung auf avrdud-Batchdatei auf dem Desktop ablegen,
+rem "Fallenlassen" einer Hex-Datei auf diese Verknüfpung startet
+rem den Programmierprozess
+
+avrdude -p m32 -c avr910 -P com5 -U flash:w:%1:i \ No newline at end of file
diff --git a/source/ct-Bot/contrib/flash_n_fuse/flash.sh b/source/ct-Bot/contrib/flash_n_fuse/flash.sh
new file mode 100644
index 0000000..3a386e3
--- /dev/null
+++ b/source/ct-Bot/contrib/flash_n_fuse/flash.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+# echo program C't-Bot with avrdude and mySmartUSB
+#
+# echo Usage: flash.sh <filename>
+#
+if [ $# != 1 ]; then
+ echo "Usage: flash.sh <filename>"
+ exit 1;
+fi
+# now check if the fuses are set correctly
+# use temporary file names in /tmp for it
+lowtemp="$(mktemp /tmp/lfuse.XXXXX)"
+hightemp="$(mktemp /tmp/hfuse.XXXXX)"
+locktemp="$(mktemp /tmp/lock.XXXXX)"
+
+# read fuses
+avrdude -p m32 -c avr910 -P /dev/ttyUSB0 -U lfuse:r:$lowtemp:i \
+ -U hfuse:r:$hightemp:i -U lock:r:$locktemp:i >/dev/null 2>&1
+if [ $? != "0" ]; then
+ echo "Error while reading fuses!"
+ exit 1
+fi
+
+fuses_ok=1
+# now compare the values with the correspondent .hex file
+cmp -n 13 lfuse.hex $lowtemp >/dev/null 2>&1
+if [ $? != "0" ]; then
+ echo "low fuse doesn't fit!"
+ fuses_ok=0;
+fi
+cmp -n 13 hfuse.hex $hightemp >/dev/null 2>&1
+if [ $? != "0" ]; then
+ echo "high fuse doesn't fit!"
+ fuses_ok=0;
+fi
+cmp -n 13 lock.hex $locktemp >/dev/null 2>&1
+if [ $? != "0" ]; then
+ echo "lock byte doesn't fit!"
+ fuses_ok=0;
+fi
+
+
+# clean up temp files
+rm $lowtemp
+rm $hightemp
+rm $locktemp
+
+# if some or all fuses were wrong, give hint and bail out
+if [ $fuses_ok != "1" ]; then
+ echo "Please correct your fuses with setfuses.sh, else you'll probably get locked out from your MCU!"
+ exit 2;
+fi
+
+# all fuses ok, now program flash
+avrdude -p m32 -c avr910 -P /dev/ttyUSB0 -e -U flash:w:$1:i
diff --git a/source/ct-Bot/contrib/flash_n_fuse/fuses.txt b/source/ct-Bot/contrib/flash_n_fuse/fuses.txt
new file mode 100644
index 0000000..368a043
--- /dev/null
+++ b/source/ct-Bot/contrib/flash_n_fuse/fuses.txt
@@ -0,0 +1,17 @@
+Die drei Hex-Dateien hfuse.hex, lfuse.hex und lock.hex
+sind nur für ATmega32-Prozessoren geeignet.
+Die Dateien sind im Intel-Hex-Format.
+
+
+Mit der Programmiersoftware avrdude, die zum Beispiel bei WINAVR dabei ist kann man:
+
+1. Seine eigenen Fuses wie folgt auslesen:
+avrdude -p m32 -c stk200 -P lpt1 -U lfuse:r:lfuse.hex:i -U hfuse:r:hfuse.hex:i -U lock:r:lock.hex:i
+
+2. Die hier stehenden Dateien schreiben:
+avrdude -p m32 -c stk200 -P lpt1 -u -U lfuse:w:lfuse.hex:i -U hfuse:w:hfuse.hex:i -U lock:w:lock.hex:i
+
+Dabei muss man die -c und -P Paramter an den jeweiligen Programmieradpter anpassen.
+
+Für den ISP-Adapter aus dem BlueMP3-Projekt gilt, sofern er an der ersten Druckerschnittstelle (LPT1 hängt:
+-c stk200 -P lpt1
diff --git a/source/ct-Bot/contrib/flash_n_fuse/hfuse.hex b/source/ct-Bot/contrib/flash_n_fuse/hfuse.hex
new file mode 100644
index 0000000..794961a
--- /dev/null
+++ b/source/ct-Bot/contrib/flash_n_fuse/hfuse.hex
@@ -0,0 +1,2 @@
+:01000000D926
+:00000001FF
diff --git a/source/ct-Bot/contrib/flash_n_fuse/lfuse.hex b/source/ct-Bot/contrib/flash_n_fuse/lfuse.hex
new file mode 100644
index 0000000..05b6588
--- /dev/null
+++ b/source/ct-Bot/contrib/flash_n_fuse/lfuse.hex
@@ -0,0 +1,2 @@
+:01000000FF00
+:00000001FF
diff --git a/source/ct-Bot/contrib/flash_n_fuse/loadusbtty.sh b/source/ct-Bot/contrib/flash_n_fuse/loadusbtty.sh
new file mode 100644
index 0000000..930ac87
--- /dev/null
+++ b/source/ct-Bot/contrib/flash_n_fuse/loadusbtty.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+# create ttyUSB0 device and load module for cp2101
+
+if [ ! -c /dev/ttyUSB0 ]; then
+ mknod -m 666 /dev/ttyUSB0 c 188 0
+fi
+
+if [ -z $(lsmod |cut -d" " -f1 |grep "cp2101") ]; then
+ modprobe cp2101 >/dev/null 2>&1
+ if [ $? != "0" ]; then
+ exit 1;
+ fi
+fi
+
diff --git a/source/ct-Bot/contrib/flash_n_fuse/lock.hex b/source/ct-Bot/contrib/flash_n_fuse/lock.hex
new file mode 100644
index 0000000..9223968
--- /dev/null
+++ b/source/ct-Bot/contrib/flash_n_fuse/lock.hex
@@ -0,0 +1,2 @@
+:010000003FC0
+:00000001FF
diff --git a/source/ct-Bot/contrib/flash_n_fuse/setfuses.bat b/source/ct-Bot/contrib/flash_n_fuse/setfuses.bat
new file mode 100644
index 0000000..39bf741
--- /dev/null
+++ b/source/ct-Bot/contrib/flash_n_fuse/setfuses.bat
@@ -0,0 +1,17 @@
+rem Aufruf von Avrdude zur Programmierung c't-Bot
+rem Batchdatei für Programmieradapter mysmartUSB
+rem
+rem von andreas Staudenmayer (andreas.staudenmayer@t-online.de)
+rem Parameter
+rem
+rem -p m32 für ATMega32
+rem -c avr910 Adapter kompatibel zu avr910
+rem -P com5 Adapter installiert auf com5
+rem -u disable safemode, um fusebits setzen zu können
+rem -U flash:w:<Datei>:i Programmdatei, die geschrieben werden soll, wird als erster Batch Parameter übergeben
+rem
+rem -U lfuse:w:lfuse.hex:i lowfusebits setzen, Inhalt Bin-Datei lfuse.hex: FF
+rem -U hfuse:w:hfuse.hex:i highfusebits setzen, Inhalt Bin-Datei hfuse.hex: D9
+rem -U lock:w:lock.hex:i lockbits setzen, Inhalt Bin-Datei lock.hex: 3F
+
+avrdude -p m32 -c avr910 -P com5 -u -U lfuse:w:lfuse.hex:i -U hfuse:w:hfuse.hex:i -U lock:w:lock.hex:i \ No newline at end of file
diff --git a/source/ct-Bot/contrib/flash_n_fuse/setfuses.sh b/source/ct-Bot/contrib/flash_n_fuse/setfuses.sh
new file mode 100644
index 0000000..0c02970
--- /dev/null
+++ b/source/ct-Bot/contrib/flash_n_fuse/setfuses.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+# echo program C't-Bot with avrdude and mySmartUSB
+#
+# echo Usage: setfuses.sh <filename>
+#
+if [ $# != 1 ]; then
+ echo "Usage: setfuses.sh <filename>"
+ exit 1;
+fi
+
+avrdude -p m32 -c avr910 -P /dev/ttyUSB0 -e -u -U lfuse:w:lfuse.hex:i -U hfuse:w:hfuse.hex:i -U lock:w:lock.hex:i \ No newline at end of file
diff --git a/source/ct-Bot/ct-Bot.c b/source/ct-Bot/ct-Bot.c
new file mode 100644
index 0000000..0cc077c
--- /dev/null
+++ b/source/ct-Bot/ct-Bot.c
@@ -0,0 +1,747 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file ct-Bot.c
+ * @brief Demo-Hauptprogramm
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+
+#include "ct-Bot.h"
+
+#ifdef MCU
+ #include <avr/io.h>
+ #include <avr/interrupt.h>
+// #include <avr/signal.h>
+ #include <avr/wdt.h>
+ #include "bot-2-pc.h"
+#endif
+
+#ifdef PC
+ #include "bot-2-sim.h"
+ #include "tcp.h"
+ #include "tcp-server.h"
+ #include <pthread.h>
+ #include <unistd.h>
+ #include <stdlib.h>
+ #include <time.h>
+ #include <sys/time.h>
+#endif
+
+#ifdef TWI_AVAILABLE
+ #include "TWI_driver.h"
+#endif
+
+#include <string.h>
+#include <stdio.h>
+
+#include "global.h"
+#include "display.h"
+#include "led.h"
+#include "ena.h"
+#include "shift.h"
+#include "delay.h"
+#include "uart.h"
+#include "adc.h"
+#include "timer.h"
+#include "sensor.h"
+#include "log.h"
+
+
+#include "motor.h"
+#include "sensor-low.h"
+#include "bot-logic/bot-logik.h"
+#include "mouse.h"
+
+#include "command.h"
+#include "ir-rc5.h"
+#include "rc5.h"
+#include "timer.h"
+#include "mmc.h"
+#include "map.h"
+#include "mmc-emu.h"
+#include "mini-fat.h"
+
+/* Nimmt den Status von MCU(C)SR bevor dieses Register auf 0x00 gesetzt wird */
+#ifdef DISPLAY_SCREEN_RESETINFO
+ uint8 reset_flag;
+#endif
+
+/* Enthaelt den Start des Heaps und ermoeglicht z.B. die Berechnung des verwendeten RAMs */
+#ifdef MCU
+ extern unsigned char __heap_start;
+#endif
+
+#ifdef TEST_AVAILABLE_COUNTER
+ #include <avr/eeprom.h>
+ uint8 resetsEEPROM __attribute__ ((section (".eeprom")))=0;
+ uint8 resetInfoEEPROM __attribute__ ((section (".eeprom")));
+ uint8 resets;
+#endif
+/*!
+ * Der Mikrocontroller und der PC-Simulator brauchen ein paar Einstellungen,
+ * bevor wir loslegen koennen.
+ */
+void init(void){
+
+ #ifdef MCU
+ PORTA=0; DDRA=0; //Alles Eingang alles Null
+ PORTB=0; DDRB=0;
+ PORTC=0; DDRC=0;
+ PORTD=0; DDRD=0;
+
+ // Watchdog aus!
+ wdt_disable();
+ timer_2_init();
+
+ // Ist das ein Power on Reset ?
+ #ifdef __AVR_ATmega644__
+ if ((MCUSR & 1) ==1 ) {
+ MCUSR &= ~1; // Bit loeschen
+ #else
+ if ((MCUCSR & 1) ==1 ) {
+ MCUCSR &= ~1; // Bit loeschen
+ #endif
+ delay(100);
+ asm volatile("jmp 0");
+ }
+
+ delay(100);
+ #ifdef DISPLAY_SCREEN_RESETINFO
+ #ifdef __AVR_ATmega644__
+ reset_flag = MCUSR & 0x1F; //Lese Grund fuer Reset und sichere Wert
+ MCUSR = 0; //setze Register auf 0x00 (loeschen)
+ #else
+ reset_flag = MCUCSR & 0x1F; //Lese Grund fuer Reset und sichere Wert
+ MCUCSR = 0; //setze Register auf 0x00 (loeschen)
+ #endif
+ #endif
+ #endif
+
+ #ifdef UART_AVAILABLE
+ uart_init();
+ #endif
+
+ #ifdef BOT_2_PC_AVAILABLE
+ bot_2_pc_init();
+ #endif
+
+
+ #ifdef PC
+ bot_2_sim_init();
+ #endif
+
+ #ifdef DISPLAY_AVAILABLE
+ display_init();
+ display_update=1;
+ #endif
+
+ #ifdef LED_AVAILABLE
+ LED_init();
+ #endif
+
+ motor_init();
+ bot_sens_init();
+ #ifdef BEHAVIOUR_AVAILABLE
+ bot_behave_init();
+ #endif
+
+ #ifdef MCU
+ #ifdef RC5_AVAILABLE
+ ir_init();
+ #endif
+ #endif
+
+ #ifdef MMC_AVAILABLE
+ mmc_init();
+ #endif
+
+ #ifdef MAUS_AVAILABLE
+ maus_sens_init();
+ #endif
+
+ #ifdef MAP_AVAILABLE
+ map_init();
+ #endif
+
+
+ #ifdef DISPLAY_BEHAVIOUR_AVAILABLE
+ behaviour_page = 1;
+ #endif
+
+ #ifdef TWI_AVAILABLE
+ Init_TWI();
+ Close_TWI();
+ #endif
+}
+
+#ifdef DISPLAY_AVAILABLE
+
+/*!
+ * Zeigt ein paar Informationen an
+ */
+ void display(void){
+
+ #ifdef DISPLAY_BEHAVIOUR_AVAILABLE
+ /*!
+ * Definitionen fuer die Verhaltensanzeige
+ */
+ #undef TEST_AVAILABLE_COUNTER
+ Behaviour_t *ptr = behaviour;
+ int8 colcounter = 0;
+ int8 linecounter = 0;
+ int8 firstcol = 0;
+ #endif
+ #ifdef MCU
+ #ifndef LOG_DISPLAY_AVAILABLE
+ #ifdef DISPLAY_SCREENS_AVAILABLE
+ uint16 frei; // enthaelt im Screen 5 den freien RAM-Speicher
+ #endif // DISPLAY_SCREENS_AVAILABLE
+ #endif
+ #endif
+ #ifdef TEST_AVAILABLE_COUNTER
+ static int counter=0;
+ #endif
+ if (display_update >0)
+ #ifdef DISPLAY_SCREENS_AVAILABLE
+ switch (display_screen) {
+ case 0:
+ #endif
+ display_cursor(1,1);
+ display_printf("P=%03X %03X D=%03d %03d ",sensLDRL,sensLDRR,sensDistL,sensDistR);
+
+ display_cursor(2,1);
+ display_printf("B=%03X %03X L=%03X %03X ",sensBorderL,sensBorderR,sensLineL,sensLineR);
+
+ display_cursor(3,1);
+ display_printf("R=%2d %2d F=%d K=%d T=%d ",sensEncL % 10,sensEncR %10,sensError,sensDoor,sensTrans);
+
+ display_cursor(4,1);
+ #ifdef RC5_AVAILABLE
+ #ifdef MAUS_AVAILABLE
+ display_printf("I=%04X M=%05d %05d",RC5_Code,sensMouseX,sensMouseY);
+ #else
+ display_printf("I=%04X",RC5_Code);
+ #endif
+ #else
+ #ifdef MAUS_AVAILABLE
+ display_printf("M=%05d %05d",sensMouseX,sensMouseY);
+ #endif
+ #endif
+ #ifdef DISPLAY_SCREENS_AVAILABLE
+ break;
+ case 1:
+ #ifdef TIME_AVAILABLE
+ display_cursor(1,1);
+ display_printf("Zeit: %04d:%03d", timer_get_s(), timer_get_ms());
+ #endif
+
+ #ifdef BEHAVIOUR_AVAILABLE
+ display_cursor(2,1);
+ display_printf("TS=%+4d %+4d",target_speed_l,target_speed_r);
+ #endif
+ #ifdef SRF10_AVAILABLE
+ display_cursor(2,15);
+ display_printf("US%+4d",sensSRF10);
+ #endif
+
+ display_cursor(3,1);
+ display_printf("RC=%+4d %+4d",sensEncL,sensEncR);
+
+ display_cursor(4,1);
+ display_printf("Speed= %04d",(int16)v_center);
+ break;
+
+ case 2:
+ display_cursor(1,1);
+
+ #ifdef DISPLAY_BEHAVIOUR_AVAILABLE
+ /*!
+ * zeilenweise Anzeige der Verhalten
+ */
+ display_printf("Verhalten (Pri/Akt)%d",behaviour_page);
+
+ colcounter = 0; linecounter = 2;
+ /* je nach Seitenwahl die ersten Saetze ueberlesen bis richtige Seite */
+ firstcol = (behaviour_page -1)*6;
+
+ /*!
+ * max. 3 Zeilen mit 6 Verhalten anzeigbar wegen Ueberschrift
+ * Seitensteuerung bei mehr Verhalten
+ */
+ while((ptr != NULL)&& (linecounter<5)) {
+
+ if ((ptr->priority >= PRIO_VISIBLE_MIN) &&(ptr->priority <= PRIO_VISIBLE_MAX)) {
+ if (colcounter >= firstcol) {
+ display_cursor(linecounter,((colcounter % 2)* 12)+1);
+ #ifdef DISPLAY_DYNAMIC_BEHAVIOUR_AVAILABLE
+ display_printf(" %3d,%2d",ptr->priority,ptr->active);
+ #else
+ display_printf(" %3d,%2d",ptr->priority,ptr->active_new);
+ #endif
+ colcounter++;
+
+ /* bei colcounter 0 neue Zeile */
+ if (colcounter % 2 == 0)
+ linecounter++;
+
+ }
+ else
+ colcounter ++;
+ }
+ ptr = ptr->next;
+ }
+
+ #endif
+ #ifdef DISPLAY_ODOMETRIC_INFO
+ /* Zeige Positions- und Geschwindigkeitsdaten */
+ display_cursor(1,1);
+ display_printf("heading: %3d ",(int16)heading);
+ display_cursor(2,1);
+ display_printf("x: %3d y: %3d ",(int16)x_pos,(int16)y_pos);
+ display_cursor(3,1);
+ display_printf("v_l: %3d v_r: %3d ",(int16)v_left,(int16)v_right);
+ #ifdef MEASURE_MOUSE_AVAILABLE
+ display_cursor(4,1);
+ display_printf("squal: %3d v_c: %3d",maus_get_squal(),(int16)v_mou_center);
+ #endif
+ #endif
+
+
+ #ifdef TEST_AVAILABLE_COUNTER
+ display_printf("Screen 3");
+ display_cursor(2,1);
+ display_printf("count %d",counter++);
+
+ display_cursor(3,1);
+ display_printf("Reset-Counter %d",resets);
+ #endif
+ break;
+
+ case 3:
+ #ifdef DISPLAY_SCREEN_RESETINFO
+ display_cursor(1,1);
+ /* Zeige den Grund fuer Resets an */
+ display_printf("MCU(C)SR - Register");
+
+ display_cursor(2,1);
+ display_printf("PORF :%d WDRF :%d",binary(reset_flag,0),binary(reset_flag,3));
+
+ display_cursor(3,1);
+ display_printf("EXTRF:%d JTRF :%d",binary(reset_flag,1),binary(reset_flag,4));
+
+ display_cursor(4,1);
+ display_printf("BORF :%d",binary(reset_flag,2));
+ #endif
+ #ifdef DISPLAY_MMC_INFO
+ #ifdef MMC_INFO_AVAILABLE
+ {
+ uint32 size = 0;
+ uint8 csd[16];
+ static uint8 mmc_state= 0xFF;
+
+
+ uint8 dummy= mmc_init();
+ // hat sich was geaendert?
+ if (dummy!=mmc_state) {
+ mmc_state=dummy;
+
+ uint8 i;
+ for (i=0;i<16;i++)
+ csd[i]=0;
+
+ display_cursor(1,1);
+ if (mmc_state !=0){
+ display_printf("MMC not init (%d) ",mmc_state);
+ }else {
+ size=mmc_get_size();
+ mmc_read_csd(csd);
+ display_printf("MMC= %4d MByte ",size >> 20);
+ }
+ #ifndef MMC_WRITE_TEST_AVAILABLE
+ display_cursor(3,1);
+ for (i=0;i<16;i++){
+ if (i == 8) display_cursor(4,1);
+ if (i%2 == 0) display_printf(" ");
+ display_printf("%02x",csd[i]);
+ }
+ #endif // MMC_WRITE_TEST_AVAILABLE
+ }
+ #ifdef MMC_WRITE_TEST_AVAILABLE
+ if (mmc_state == 0){
+ static uint16 time = 0;
+ if (TIMER_GET_TICKCOUNT_16-time > MS_TO_TICKS(200)){
+ time = TIMER_GET_TICKCOUNT_16;
+ uint8 result = mmc_test();
+ if (result != 0){
+ display_cursor(3,1);
+ display_printf("mmc_test()=%u :( ", result);
+ }
+ }
+ }
+ #endif // MMC_WRITE_TEST_AVAILABLE
+ }
+ #else
+ #ifdef MMC_VM_AVAILABLE
+ #ifdef PC
+ display_cursor(3,1);
+ display_printf("mmc_emu_test() = %u ", mmc_emu_test());
+ #endif // PC
+ #endif // MMC_VM_AVAILABLE
+ #endif // MMC_INFO_AVAILABLE
+ #endif
+
+ break;
+
+ case 4:
+ /* Ausgabe des freien RAMs */
+ #ifdef MCU
+ #ifndef LOG_DISPLAY_AVAILABLE
+ frei = SP - (uint16) &__heap_start;
+ display_cursor(1,1);
+ display_printf("free RAM: %4d ",frei);
+ #endif
+ #endif
+
+ break;
+
+ }
+ #endif
+ }
+#endif
+
+#ifdef TEST_AVAILABLE
+ /*! Zeigt den internen Status der Sensoren mit den LEDs an */
+ void show_sensors(void){
+ uint8 led=0x00;
+ led_t * status = (led_t *)&led;
+ #ifdef TEST_AVAILABLE_ANALOG
+ (*status).rechts = (sensDistR >> 9) & 0x01;
+ (*status).links = (sensDistL >> 9) & 0x01;
+ (*status).rot = (sensLineL >> 9) & 0x01;
+ (*status).orange = (sensLineR >> 9) & 0x01;
+ (*status).gelb = (sensLDRL >> 9) & 0x01;
+ (*status).gruen = (sensLDRR >> 9) & 0x01;
+ (*status).tuerkis = (sensBorderL >> 9) & 0x01;
+ (*status).weiss = (sensBorderR >> 9) & 0x01;
+ #endif
+ #ifdef TEST_AVAILABLE_DIGITAL
+ (*status).rechts = sensEncR & 0x01;
+ (*status).links = sensEncL & 0x01;
+ (*status).rot = sensTrans & 0x01;
+ (*status).orange = sensError & 0x01;
+ (*status).gelb = sensDoor & 0x01;
+ #ifdef MAUS_AVAILABLE
+ (*status).gruen = (sensMouseDX >>1) & 0x01;
+ (*status).tuerkis = (sensMouseDY >>1) & 0x01;
+ #endif
+ #ifdef RC5_AVAILABLE
+ (*status).weiss = RC5_Code & 0x01;
+ #endif
+ #endif
+
+ LED_set(led);
+ }
+#endif
+
+#ifdef PC
+ /*!
+ * Zeigt Informationen zu den moeglichen Kommandozeilenargumenten an.
+ * Das Programm wird nach Anzeige des Hilfetextes per exit() beendet.
+ */
+ void usage(void){
+ puts("USAGE: ct-Bot [-t host] [-T] [-h] [-s] [-M from] [-c FILE ID SIZE]");
+ puts("\t-t\tHostname oder IP Adresse zu der Verbunden werden soll");
+ puts("\t-T\tTestClient");
+ puts("\t-s\tServermodus");
+ puts("\t-M from\tKonvertiert eine Bot-map in eine PGM-Datei");
+ puts("\t-c \tErzeugt eine Mini-Fat-Datei fuer den Bot.");
+ puts("\t FILE\tDateiname");
+ puts("\t ID \tDie ID aus ASCII-Zeichen");
+ puts("\t SIZE\tDie Nutzgroesse der Datei in KByte");
+ puts("\t-h\tZeigt diese Hilfe an");
+ exit(1);
+ }
+
+#endif
+
+#ifdef MCU
+/*!
+ * Hauptprogramm des Bots. Diese Schleife kuemmert sich um seine Steuerung.
+ */
+ int main (void){
+
+#endif
+
+#ifdef PC
+
+/*!
+ * Hauptprogramm des Bots. Diese Schleife kuemmert sich um seine Steuerung.
+ */
+ int main (int argc, char *argv[]){
+ //Zum debuggen der Zeiten:
+ #ifdef DEBUG_TIMES
+ struct timeval start, stop;
+ #endif
+
+
+ int ch;
+ int start_server = 0; /*!< Wird auf 1 gesetzt, falls -s angegeben wurde */
+ int start_test_client =0; /*!< Wird auf 1 gesetzt, falls -T angegeben wurde */
+ char *hostname = NULL; /*!< Speichert den per -t uebergebenen Hostnamen zwischen */
+
+ int convert =0; /*!< Wird auf 1 gesetzt, wenn die Karte konvertiert werden soll */
+ int create =0; /*!< Wird auf 1 gesetzt, wenn eine neue Datei fuer Bot-mini-fat erzeugt werden soll */
+ char *from = NULL; /*!< Speichert den per -M uebergebenen Quellnamen zwischen */
+
+
+ // Die Kommandozeilenargumente komplett verarbeiten
+ while ((ch = getopt(argc, argv, "hsTt:M:c:")) != -1) {
+ switch (ch) {
+ case 's':
+ // Servermodus [-s] wird verlangt
+ start_server = 1;
+ break;
+ case 'T':
+ start_test_client=1;
+ break;
+ case 't':
+ // Hostname, auf dem ct-Sim laeuft wurde
+ // uebergeben. Der String wird in hostname
+ // gesichert.
+ {
+ const int len = strlen(optarg);
+ hostname = malloc(len + 1);
+ if (NULL == hostname)
+ exit(1);
+ strcpy(hostname, optarg);
+ }
+ break;
+ case 'M':
+ // Dateiname, fuer die Map wurde
+ // uebergeben. Der String wird in from
+ // gesichert.
+ {
+ int len = strlen(optarg);
+ from = malloc(len + 1);
+ if (NULL == from)
+ exit(1);
+ strcpy(from, optarg);
+
+ convert=1;
+ }
+ break;
+ case 'c':
+ // Datei fuer den Bot (mini-fat soll erzeugt werden
+ // Der Name wird in hostname gesichert.
+ {
+ int len = strlen(optarg);
+ from = malloc(len + 1);
+ if (NULL == from)
+ exit(1);
+ strcpy(from, optarg);
+
+ create=1;
+ }
+ break;
+ case 'h':
+ default:
+ // -h oder falscher Parameter, Usage anzeigen
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (start_server != 0) { // Soll der TCP-Server gestartet werden?
+ printf("ARGV[0]= %s\n",argv[0]);
+ tcp_server_init();
+ tcp_server_run(100);
+ } else {
+ #ifdef MAP_AVAILABLE
+ /* Karte in pgm konvertieren */
+ if (convert !=0) {
+
+
+ printf("Konvertiere Karte %s in PGM %s\n",from,"map.pgm");
+ read_map(from);
+ map_to_pgm("map.pgm");
+ exit(0);
+ }
+
+ #endif // MAP_AVAILABLE
+
+ if (create !=0) {
+ printf("optind= %d argc=%d\n",optind, argc);
+
+ if (argc != 2){
+ usage();
+ exit(1);
+ }
+
+ char * id;
+ id = malloc(strlen(argv[0]));
+ strcpy(id,argv[0]);
+
+ char * s;
+ s = malloc(strlen(argv[1]));
+ strcpy(s,argv[1]);
+
+ int size = atoi(s);
+
+ create_mini_fat_file(from,id,size);
+
+ printf("Erstelle eine Mini-Fat-Datei (%s) mit %d kByte fuer den Bot. ID=%s \n",from,size,id);
+// read_map(from);
+// map_to_pgm("map.pgm");
+ exit(0);
+ }
+
+
+ printf("c't-Bot\n");
+ if (hostname)
+ // Hostname wurde per Kommandozeile uebergeben
+ tcp_hostname = hostname;
+ else {
+ // Der Zielhost wird per default durch das Macro IP definiert und
+ // tcp_hostname mit einer Kopie des Strings initialisiert.
+ tcp_hostname = malloc(strlen(IP) + 1);
+ if (NULL == tcp_hostname)
+ exit(1);
+ strcpy(tcp_hostname, IP);
+ }
+
+ if (start_test_client !=0) {
+ tcp_test_client_init();
+ tcp_test_client_run(100);
+ }
+
+ }
+
+
+#endif
+ #ifdef TEST_AVAILABLE_MOTOR
+ uint16 calls=0; /*!< Im Testfall zaehle die Durchlaeufe */
+ #endif
+
+ init();
+
+
+ #ifdef WELCOME_AVAILABLE
+ display_cursor(1,1);
+ display_printf("c't-Roboter");
+ LED_set(0x00);
+ #ifdef LOG_AVAILABLE
+ LOG_DEBUG(("Hallo Welt!"));
+ #endif
+ #endif
+
+ #ifdef TEST_AVAILABLE_COUNTER
+ display_screen=2;
+
+ resets=eeprom_read_byte(&resetsEEPROM)+1;
+ eeprom_write_byte(&resetsEEPROM,resets);
+ /* Lege den Grund für jeden Reset im EEPROM ab */
+ eeprom_write_byte(&resetInfoEEPROM+resets,reset_flag);
+ #endif
+ /*! Hauptschleife des Bot */
+
+ for(;;){
+ #ifdef PC
+ receive_until_Frame(CMD_DONE);
+ #ifdef DEBUG_TIMES
+ //Zum debuggen der Zeiten:
+ GETTIMEOFDAY(&start, NULL);
+ int t1=(start.tv_sec - stop.tv_sec)*1000000 + start.tv_usec - stop.tv_usec;
+ printf("Done-Token (%d) in nach %d usec ",received_command.data_l,t1);
+ #endif
+ #endif
+
+
+ #ifdef MCU
+ bot_sens_isr();
+ #endif
+ #ifdef TEST_AVAILABLE
+ show_sensors();
+ #endif
+
+ // Testprogramm, dass den Bot erst links, dann rechtsrum dreht
+ #ifdef TEST_AVAILABLE_MOTOR
+ calls++;
+ if (calls == 1)
+ motor_set(BOT_SPEED_SLOW,-BOT_SPEED_SLOW);
+ else if (calls == 501)
+ motor_set(-BOT_SPEED_SLOW,BOT_SPEED_SLOW);
+ else if (calls== 1001)
+ motor_set(BOT_SPEED_STOP,BOT_SPEED_STOP);
+ else
+ #endif
+ // hier drin steckt der Verhaltenscode
+ #ifdef BEHAVIOUR_AVAILABLE
+ if (sensors_initialized ==1 )
+ bot_behave();
+ #ifdef LOG_AVAILABLE
+ //else
+ //LOG_DEBUG(("sens not init"));
+ #endif
+ #endif
+
+ #ifdef MCU
+ #ifdef BOT_2_PC_AVAILABLE
+// static int16 lastTimeCom =0;
+
+ bot_2_pc_inform(); // Den PC ueber Sensorern und aktuatoren informieren
+ bot_2_pc_listen(); // Kommandos vom PC empfangen
+
+// if (timer_get_s() != lastTimeCom) { // sollte genau 1x pro Sekunde zutreffen
+// lastTimeCom = timer_get_s();
+
+// }
+ #endif
+ #endif
+
+ #ifdef LOG_AVAILABLE
+ //LOG_DEBUG(("BOT TIME %d s", timer_get_s()));
+ #endif
+
+ // Alles Anzeigen
+ #ifdef DISPLAY_AVAILABLE
+ display();
+ #endif
+ #ifdef MCU
+// delay(10);
+ #endif
+
+ #ifdef PC
+ command_write(CMD_DONE, SUB_CMD_NORM ,(int16*)&simultime,0,0);
+
+ flushSendBuffer();
+ //Zum debuggen der Zeiten:
+ #ifdef DEBUG_TIMES
+ GETTIMEOFDAY(&stop, NULL);
+ int t2=(stop.tv_sec - start.tv_sec)*1000000 +stop.tv_usec - start.tv_usec;
+ printf("Done-Token (%d) out after %d usec\n",simultime,t2);
+ #endif
+ #endif
+
+ }
+
+ /*! Falls wir das je erreichen sollten ;-) */
+ return 1;
+}
diff --git a/source/ct-Bot/ct-Bot.h b/source/ct-Bot/ct-Bot.h
new file mode 100644
index 0000000..29b7010
--- /dev/null
+++ b/source/ct-Bot/ct-Bot.h
@@ -0,0 +1,272 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file ct-Bot.h
+ * @brief Demo-Hauptprogramm
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+#ifndef CT_BOT_H_DEF
+#define CT_BOT_H_DEF
+
+#ifndef MMC_LOW_H_
+ #include "global.h" // denn in mmc-low.S sind typedefs unerwuenscht
+#endif
+
+/************************************************************
+* Module switches, to make code smaller if features are not needed
+************************************************************/
+//#define LOG_CTSIM_AVAILABLE /*!< Logging ueber das ct-Sim (PC und MCU) */
+//#define LOG_DISPLAY_AVAILABLE /*!< Logging ueber das LCD-Display (PC und MCU) */
+//#define LOG_UART_AVAILABLE /*!< Logging ueber UART (NUR für MCU) */
+#define LOG_STDOUT_AVAILABLE /*!< Logging auf die Konsole (NUR für PC) */
+
+
+#define LED_AVAILABLE /*!< LEDs for local control */
+
+#define IR_AVAILABLE /*!< Infrared Remote Control */
+#define RC5_AVAILABLE /*!< Key-Mapping for IR-RC */
+
+#define BOT_2_PC_AVAILABLE /*!< Soll der Bot mit dem PC kommunmizieren? */
+
+//#define TIME_AVAILABLE /*!< Gibt es eine Systemzeit im s und ms? */
+
+#define DISPLAY_AVAILABLE /*!< Display for local control */
+#define DISPLAY_REMOTE_AVAILABLE /*!< Sende LCD Anzeigedaten an den Simulator */
+#define DISPLAY_SCREENS_AVAILABLE /*!< Ermoeglicht vier verschiedene Screen */
+//#define DISPLAY_SCREEN_RESETINFO /*!< Zeigt auf Screen 4 Informationen ueber Resets an */
+//#define DISPLAY_ODOMETRIC_INFO /*!< Zeigt auf Screen 4 Positions- und Geschwindigkeitsdaten */
+//#define DISPLAY_REGELUNG_AVAILABLE 3 /*!< Zeigt Reglerdaten auf Screen 4, wenn SPEED_CONTROL_AVAILABLE gesetzt ist*/
+#define DISPLAY_MMC_INFO /*!< Zeigt auf Screen 4 die Daten der MMC-Karte an */
+//#define DISPLAY_BEHAVIOUR_AVAILABLE /*!< Anzeige der Verhalten im Display Screen 3, ersetzt Counteranzeige */
+#define DISPLAY_DYNAMIC_BEHAVIOUR_AVAILABLE /*!< Zustandsaenderungen der Verhalten sind direkt unter Umgehung der Puffervar sichtbar */
+#define MEASURE_MOUSE_AVAILABLE /*!< Geschwindigkeiten werden aus den Maussensordaten berechnet */
+//#define MEASURE_COUPLED_AVAILABLE /*!< Geschwindigkeiten werden aus Maus- und Encoderwerten ermittelt und gekoppelt */
+
+
+//#define WELCOME_AVAILABLE /*!< kleiner Willkommensgruss */
+
+#define ADC_AVAILABLE /*!< A/D-Converter */
+
+#define MAUS_AVAILABLE /*!< Maus Sensor */
+
+#define ENA_AVAILABLE /*!< Enable-Leitungen */
+#define SHIFT_AVAILABLE /*!< Shift Register */
+
+//#define TEST_AVAILABLE_ANALOG /*!< Sollen die LEDs die analoge Sensorwerte anzeigen */
+#define TEST_AVAILABLE_DIGITAL /*!< Sollen die LEDs die digitale Sensorwerte anzeigen */
+//#define TEST_AVAILABLE_MOTOR /*!< Sollen die Motoren ein wenig drehen */
+//#define TEST_AVAILABLE_COUNTER /*!< Gibt einen Endlos-Counter auf Screen 3 aus und aktiviert Screen 3 */
+//#define DOXYGEN /*!< Nur zum Erzeugen der Doku, wenn dieser schalter an ist, jammert der gcc!!! */
+
+#define BEHAVIOUR_AVAILABLE /*!< Nur wenn dieser Parameter gesetzt ist, exisitiert das Verhaltenssystem */
+
+#define MAP_AVAILABLE /*!< Aktiviere die Kartographie */
+
+//#define SPEED_CONTROL_AVAILABLE /*!< Aktiviert die Motorregelung */
+
+//#define SRF10_AVAILABLE /*!< Ultraschallsensor SRF10 vorhanden */
+
+#define MMC_AVAILABLE /*!< haben wir eine MMC/SD-Karte zur Verfuegung */
+#define MINI_FAT_AVAILABLE /*!< koennen wir sektoren in FAT-systemen finden */
+//#define MMC_VM_AVAILABLE /*!< Virtual Memory Management mit MMC / SD-Card oder PC-Emulation */
+/************************************************************
+* Some Dependencies!!!
+************************************************************/
+
+#ifdef DOXYGEN
+ #define PC /*!< Beim generieren der Doku alles anschalten */
+ #define MCU /*!< Beim generieren der Doku alles anschalten */
+ #define TEST_AVAILABLE_MOTOR /*!< Beim generieren der Doku alles anschalten */
+#endif
+
+
+#ifndef DISPLAY_AVAILABLE
+ #undef WELCOME_AVAILABLE
+ #undef DISPLAY_REMOTE_AVAILABLE
+ #undef DISPLAY_SCREENS_AVAILABLE
+ #undef DISPLAY_SCREEN_RESETINFO
+#endif
+
+#ifndef IR_AVAILABLE
+ #undef RC5_AVAILABLE
+#endif
+
+#ifndef MAUS_AVAILABLE
+ #undef MEASURE_MOUSE_AVAILABLE
+ #undef MEASURE_COUPLED_AVAILABLE
+#endif
+
+#ifdef PC
+ #ifndef DOXYGEN
+ #undef UART_AVAILABLE
+ #undef BOT_2_PC_AVAILABLE
+ #undef SRF10_AVAILABLE
+ #undef TWI_AVAILABLE
+ #undef SPEED_CONTROL_AVAILABLE // Deaktiviere die Motorregelung
+ #undef MMC_AVAILABLE
+ #endif
+
+ #define COMMAND_AVAILABLE /*!< High-Level Communication */
+ #undef DISPLAY_SCREEN_RESETINFO
+ #undef TEST_AVAILABLE_COUNTER
+#endif
+
+#ifdef MCU
+ #ifdef LOG_CTSIM_AVAILABLE
+ #define BOT_2_PC_AVAILABLE
+ #endif
+ #ifdef BOT_2_PC_AVAILABLE
+ #define UART_AVAILABLE /*!< Serial Communication */
+ #define COMMAND_AVAILABLE /*!< High-Level Communication */
+ #endif
+// #undef MAP_AVAILABLE
+#endif
+
+
+#ifdef TEST_AVAILABLE_MOTOR
+ #define TEST_AVAILABLE /*!< brauchen wir den Testkrams */
+ #define TEST_AVAILABLE_DIGITAL /*!< Sollen die LEDs die digitale Sensorwerte anzeigen */
+#endif
+
+#ifdef TEST_AVAILABLE_DIGITAL
+ #define TEST_AVAILABLE /*!< brauchen wir den Testkrams */
+ #undef TEST_AVAILABLE_ANALOG
+#endif
+
+#ifdef TEST_AVAILABLE_ANALOG
+ #define TEST_AVAILABLE /*!< brauchen wir den Testkrams */
+#endif
+
+#ifdef TEST_AVAILABLE_COUNTER
+ #define TEST_AVAILABLE /*!< brauchen wir den Testkrams */
+ #define DISPLAY_SCREENS_AVAILABLE
+ #define DISPLAY_SCREEN_RESETINFO
+#endif
+
+#ifdef DISPLAY_ODOMETRIC_INFO
+ #undef DISPLAY_SCREEN_RESETINFO /*!< Wenn Odometrieinfos, dann keine Resetinfos */
+#endif
+
+#ifndef SPEED_CONTROL_AVAILABLE
+ #undef DISPLAY_REGELUNG_AVAILABLE
+#endif
+
+#ifdef LOG_UART_AVAILABLE
+ #define LOG_AVAILABLE
+#endif
+#ifdef LOG_CTSIM_AVAILABLE
+ #define LOG_AVAILABLE
+#endif
+#ifdef LOG_DISPLAY_AVAILABLE
+ #define LOG_AVAILABLE
+#endif
+#ifdef LOG_STDOUT_AVAILABLE
+ #define LOG_AVAILABLE
+#endif
+
+#ifndef MMC_AVAILABLE
+ #undef MINI_FAT_AVAILABLE
+ #ifdef MCU
+ #undef MMC_VM_AVAILABLE
+ #endif
+#endif
+
+#ifdef LOG_AVAILABLE
+ #ifdef PC
+ /* Auf dem PC gibts kein Logging ueber UART. */
+ #undef LOG_UART_AVAILABLE
+ #endif
+
+ #ifdef MCU
+ /* Mit Bot zu PC Kommunikation auf dem MCU gibts kein Logging ueber UART.
+ * Ohne gibts keine Kommunikation ueber ct-Sim.
+ */
+ #undef LOG_STDOUT_AVAILABLE /*!< MCU hat kein STDOUT */
+ #ifdef BOT_2_PC_AVAILABLE
+ #undef LOG_UART_AVAILABLE
+ #else
+ #undef LOG_CTSIM_AVAILABLE
+ #endif
+ #endif
+
+ /* Ohne Display gibts auch keine Ausgaben auf diesem. */
+ #ifndef DISPLAY_AVAILABLE
+ #undef LOG_DISPLAY_AVAILABLE
+ #endif
+
+ /* Logging aufs Display ist nur moeglich, wenn mehrere Screens
+ * unterstuetzt werden.
+ */
+ #ifndef DISPLAY_SCREENS_AVAILABLE
+ #undef LOG_DISPLAY_AVAILABLE
+ #endif
+
+ /* Es kann immer nur ueber eine Schnittstelle geloggt werden. */
+
+ #ifdef LOG_UART_AVAILABLE
+ #define UART_AVAILABLE
+ #undef LOG_CTSIM_AVAILABLE
+ #undef LOG_DISPLAY_AVAILABLE
+ #undef LOG_STDOUT_AVAILABLE
+ #endif
+
+ #ifdef LOG_CTSIM_AVAILABLE
+ #undef LOG_DISPLAY_AVAILABLE
+ #undef LOG_STDOUT_AVAILABLE
+ #endif
+
+ #ifdef LOG_DISPLAY_AVAILABLE
+ #undef LOG_STDOUT_AVAILABLE
+ #endif
+
+ // Wenn keine sinnvolle Log-Option mehr uebrig, loggen wir auch nicht
+ #ifndef LOG_CTSIM_AVAILABLE
+ #ifndef LOG_DISPLAY_AVAILABLE
+ #ifndef LOG_UART_AVAILABLE
+ #ifndef LOG_STDOUT_AVAILABLE
+ #undef LOG_AVAILABLE
+ #endif
+ #endif
+ #endif
+ #endif
+
+#endif
+
+
+#ifdef SRF10_AVAILABLE
+ #define TWI_AVAILABLE /*!< TWI-Schnittstelle (I2C) nutzen */
+#endif
+
+
+#define F_CPU 16000000L /*!< Crystal frequency in Hz */
+#define XTAL F_CPU /*!< Crystal frequency in Hz */
+
+#define LINE_FEED "\n\r" /*!< Windows und Linux unterscheiden beim Linefeed. Windows erwarten \n\r, Linux nur \n */
+
+#ifdef MCU
+ #ifndef MMC_LOW_H_
+ #include <avr/interrupt.h>
+ #endif
+ #ifdef SIGNAL
+ #define NEW_AVR_LIB
+ #endif
+#endif
+
+#endif
diff --git a/source/ct-Bot/doxygen.Doxyfile b/source/ct-Bot/doxygen.Doxyfile
new file mode 100644
index 0000000..183841b
--- /dev/null
+++ b/source/ct-Bot/doxygen.Doxyfile
@@ -0,0 +1,1228 @@
+# Doxyfile 1.4.4
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = c't-Bot
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = German
+
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST = YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is YES.
+
+SHOW_DIRECTORIES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the progam writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT =
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE = .dep Debug-Linux Debug-MCU-Linux Debug-W32 Debug-MCU-W32
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that a graph may be further truncated if the graph's
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
+# the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/source/ct-Bot/gdb-run b/source/ct-Bot/gdb-run
new file mode 100644
index 0000000..202d458
--- /dev/null
+++ b/source/ct-Bot/gdb-run
@@ -0,0 +1,5 @@
+file /home/cttest/.eclipse/ct-Bot/Debug-MCU-Linux/ct-Bot.elf
+target remote localhost:1212
+load
+break main
+continue
diff --git a/source/ct-Bot/include/TWI_driver.h b/source/ct-Bot/include/TWI_driver.h
new file mode 100644
index 0000000..2442b62
--- /dev/null
+++ b/source/ct-Bot/include/TWI_driver.h
@@ -0,0 +1,120 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file TWI_driver.h
+ * @brief TWI Treiber
+ * @author Chris efstathiou hendrix@otenet.gr & Carsten Giesen (info@cnau.de)
+ * @date 11.04.2006
+*/
+
+#include <avr/io.h>
+#include "global.h"
+
+#ifndef TWI_driver_H
+ #define TWI_driver_H 1
+
+ /*!
+ Struktur Definition
+ tx_type ist eine Datenstruktur um den TWI Treiber anzusprechen
+ und behinhaltet folgende Informationen:
+ Slave Adresse + Datenrichtung
+ Anzahl der zu uebertragendenden Bytes (Senden oder Empfangen)
+ Pointer auf den Sende- oder Empfangspuffer
+ */
+ typedef struct
+ {
+ uint8 slave_adr; /*!< Slave Adresse and W/R byte */
+ uint8 size; /*!< Anzahl der Bytes, die gesendet oder empfagen werden sollen */
+ uint8 *data_ptr; /*!< Pointer zum Sende und Empfangs Puffer */
+ }tx_type;
+
+/*!
+ * Hier wird der eigentliche TWI-Treiber angesprochen
+ * @param *data_pack Container mit den Daten fuer den Treiber
+ * @return Resultat der Aktion
+ */
+ extern uint8 Send_to_TWI(tx_type *data_pack);
+/*!
+ * Sende ein Byte
+ * @param data das zu uebertragende Byte
+ */
+ extern uint8 Send_byte(uint8 data);
+/*!
+ * Empfange ein Byte
+ * @param *rx_ptr Container f�r die Daten
+ * @param last_byte Flag ob noch Daten erwartet werden
+ * @return Resultat der Aktion
+ */
+ extern uint8 Get_byte(uint8 *rx_ptr, uint8 last_byte);
+/*!
+ * Sende Start Sequence
+ * @return Resultat der Aktion
+ */
+ extern uint8 Send_start(void);
+/*!
+ * Sende Slave Adresse
+ * @param adr die gewuenschte Adresse
+ * @return Resultat der Aktion
+ */
+ extern uint8 Send_adr(uint8 adr);
+/*!
+ * Sende Stop Sequence
+ */
+ extern void Send_stop(void);
+/*!
+ * Warte auf TWI interrupt
+ */
+ extern void Wait_TWI_int(void);
+
+/*!
+ * TWI Bus initialsieren
+ * @return Resultat der Aktion
+ */
+ extern int8 Init_TWI(void);
+/*!
+ * TWI Bus schliesen
+ * @return Resultat der Aktion
+ */
+ extern int8 Close_TWI(void);
+
+ #define W 0 /*!< Daten Transfer Richtung Schreiben */
+ #define R 1 /*!< Daten Transfer Richtung Lesen */
+ #define OWN_ADR 60 /*!< Die eigene Slave Adresse */
+ #define SUCCESS 0xFF /*!< Status Code alles OK */
+
+ /*!
+ TWI Stautus Register Definitionen
+ */
+
+ /*!< Genereller Master Statuscode */
+ #define START 0x08 /*!< START wurde uebertragen */
+ #define REP_START 0x10 /*!< Wiederholter START wurde uebertragen */
+ /*!< Master Sender Statuscode */
+ #define MTX_ADR_ACK 0x18 /*!< SLA+W wurde uebertragen und ACK empfangen */
+ #define MTX_ADR_NACK 0x20 /*!< SLA+W wurde uebertragen und NACK empfangen */
+ #define MTX_DATA_ACK 0x28 /*!< Datenbyte wurde uebertragen und ACK empfangen */
+ #define MTX_DATA_NACK 0x30 /*!< Datenbyte wurde uebertragen und NACK empfangen */
+ #define MTX_ARB_LOST 0x38 /*!< Schlichtung verloren in SLA+W oder Datenbytes */
+ /*!< Master Empfaenger Statuscode */
+ #define MRX_ARB_LOST 0x38 /*!< Schlichtung verloren in SLA+R oder NACK bit */
+ #define MRX_ADR_ACK 0x40 /*!< SLA+R wurde uebertragen und ACK empfangen */
+ #define MRX_ADR_NACK 0x48 /*!< SLA+R wurde uebertragen und NACK empfangen */
+ #define MRX_DATA_ACK 0x50 /*!< Datenbyte wurde empfangen und ACK gesendet */
+ #define MRX_DATA_NACK 0x58 /*!< Datenbyte wurde empfangen und NACK gesendet */
+#endif
diff --git a/source/ct-Bot/include/adc.h b/source/ct-Bot/include/adc.h
new file mode 100644
index 0000000..120a19e
--- /dev/null
+++ b/source/ct-Bot/include/adc.h
@@ -0,0 +1,55 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file adc.h
+ * @brief Routinen zum Einlesen der Analogeingaenge
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+#ifndef ADC_H_
+#define ADC_H_
+
+#include "global.h"
+
+/*!
+ * Liest einen analogen Kanal aus
+ * @param channel Kanal - hex-Wertigkeit des Pins (0x01 fuer PA0; 0x02 fuer PA1, ..)
+ */
+uint16 adc_read(uint8 channel);
+
+/*!
+ * Wechselt einen ADU-kanal. Dafuer muessen auch die Puffer zurueckgesetzt werden
+ * @param channel Kanal - hex-Wertigkeit des Pins (0x01 fuer PA0; 0x02 fuer PA1, ..)
+ */
+void adc_select_channel(uint8 channel);
+
+/*!
+ * Diese Routine wird vom Timer-Interrupt aufgerufen und speichert einen
+ * Messwert (vorher wendet sie evtl. noch eine Filterfunktion an).
+ */
+void adc_isr(void);
+
+/*!
+ * Initialisert den AD-Umsetzer.
+ * @param channel fuer jeden Kanal, den man nutzen moechte,
+ * muss das entsprechende Bit in channel gesetzt sein.
+ * Bit0 = Kanal 0 usw.
+ */
+void adc_init(uint8 channel);
+#endif
diff --git a/source/ct-Bot/include/bot-2-pc.h b/source/ct-Bot/include/bot-2-pc.h
new file mode 100644
index 0000000..4f53136
--- /dev/null
+++ b/source/ct-Bot/include/bot-2-pc.h
@@ -0,0 +1,47 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file bot-2-pc.h
+ * @brief Verbindung c't-Bot zum PC
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 01.03.06
+*/
+#ifndef __bot_2_pc
+#define __bot_2_pc
+
+#include "global.h"
+
+/*!
+ * Diese Funktion nimmt die Daten vom PC entgegen
+ * und wertet sie aus. dazu nutzt er die Funktion command_evaluate()
+ */
+void bot_2_pc_listen(void);
+
+/*!
+ * Diese Funktion informiert den PC ueber alle Sensor und Aktuator-Werte
+ */
+void bot_2_pc_inform(void);
+
+
+
+/*!
+ * Meldet den Bot am c't-Sim an
+ */
+void bot_2_pc_init(void);
+#endif
diff --git a/source/ct-Bot/include/bot-2-sim.h b/source/ct-Bot/include/bot-2-sim.h
new file mode 100644
index 0000000..2a3fe46
--- /dev/null
+++ b/source/ct-Bot/include/bot-2-sim.h
@@ -0,0 +1,71 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file bot-2-sim.h
+ * @brief Verbindung c't-Bot zu c't-Sim
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+#ifndef __bot_2_sim
+#define __bot_2_sim
+
+#include "ct-Bot.h"
+#include "global.h"
+
+/*!
+ * Ein wenig Initilisierung kann nicht schaden
+ */
+void bot_2_sim_init(void);
+
+/*!
+ * Frage Simulator nach Daten
+ */
+int bot_2_sim_ask(uint8 command, uint8 subcommand,int16* data_l,int16* data_r);
+
+/*!
+ * Schickt einen Thread in die Warteposition
+ * @param timeout_us Wartezeit in Mikrosekunden
+ */
+void wait_for_time(long timeout_us);
+/*!
+ * Wartet auf die Antwort des PC
+ * Achtung blockierend ohne Timeout
+ * @param command Das kommando auf das gewartet wird.
+ * @return 0, wenn Ok
+ */
+int wait_for_special_command(uint8 command);
+
+/*!
+ * Schleife, die Kommandis empfaengt und bearbeitet, bis ein Kommando vom Typ Frame kommt
+ * @param frame Kommando zum abbruch
+ */
+int8 receive_until_Frame(int8 frame);
+
+#ifdef WIN32
+ #include <sys/time.h>
+ /*!
+ * Hilfsfunktion, die es nur auf dem PC gibt
+ */
+ void gettimeofday_win(struct timeval* p, void* tz /* IGNORED */);
+ #define GETTIMEOFDAY gettimeofday_win
+#else
+ #define GETTIMEOFDAY gettimeofday
+#endif // WIN32
+
+#endif
diff --git a/source/ct-Bot/include/bot-local.h b/source/ct-Bot/include/bot-local.h
new file mode 100644
index 0000000..3a80e53
--- /dev/null
+++ b/source/ct-Bot/include/bot-local.h
@@ -0,0 +1,111 @@
+ /*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file bot-local.h
+ * @brief Konstanten, die den Bot an reale Umgebungen anpassen
+ * @author Benjamin Benz (bbe@heise.de)
+ * @author Christoph Grimmer (c.grimmer@futurio.de)
+ * @date 28.02.06
+*/
+
+#ifndef BOTLOCAL_H_
+#define BOTLOCAL_H_
+
+#include "ct-Bot.h"
+
+#define ENCODER_MARKS 60 /*!< Anzahl der Flanken, die ein Encoder bei einer Radumdrehung liefert, also Anzahl der weissen + Anzahl der schwarzen Felder */
+#define WHEEL_DIAMETER 57 /*!< Durchmesser eines Rades in mm */
+#define WHEEL_PERIMETER 179 /*!< Umfang eines Rades in mm */
+#define WHEEL_TO_WHEEL_DIAMETER 97 /*!< Abstand der beiden Raeder in mm */
+
+#define DISTSENSOR_POS_FW 35 /*!< Abstand der Distanzsensoren von der Radachse (in fahrtrichtung)*/
+#define DISTSENSOR_POS_SW 32 /*!< Abstand der Distanzsensoren von der Mittelachse (in querrichtung)*/
+
+#define SPEED_CONTROL_INTERVAL 333 /*!> Intervall fuer die Motorregelung [ms]*/
+
+//#define SPEED_TO_ENCODER_RATE (WHEEL_PERIMETER /ENCODER_MARKS*(1000/SPEED_CONTROL_INTERVAL)) /*!< Faktor durch den man eine Speed [mm/s] teilt um Ticks/intervall zu erhalten */
+#define SPEED_TO_ENCODER_RATE 9 /*!< Faktor durch den man eine Speed [mm/s] teilt um Ticks/intervall zu erhalten */
+
+/* Odometrie-Konstanten */
+//#define MOUSE_CPI 401 /*!< CPI-Wert aus Kalibrierung */
+//#define MOUSE_FULL_TURN 1430 /*!< Mausaenderung in X-Richtung fuer einen vollen Kreis */
+#define MOUSE_CPI 400 /*!< CPI-Wert aus Kalibrierung (Wert fuer den Sim) */
+#define MOUSE_FULL_TURN 1484 /*!< Mausaenderung in X-Richtung fuer einen vollen Kreis (Wert fuer den Sim) */
+
+#define WHEEL_DISTANCE 49 /*!< Abstand eines Rades zur Mitte des Bots */
+#define STUCK_DIFF 100 /*!< ab welcher Differenz haben wir durchdrehende Raeder? */
+#define G_SPEED 0.5 /*!< Kopplung Encoder- und Maussensor fuer Geschwindigkeiten (0.0=nur Radencoder, 1.0=nur Maussensor) */
+#define G_POS 0.5 /*!< Kopplung Encoder- und Maussensor fuer Positionen und Winkel (0.0=nur Radencoder, 1.0=nur Maussensor) */
+
+/*! Hilfskonstante */
+#define ANGLE_CONSTANT (WHEEL_TO_WHEEL_DIAMETER * ENCODER_MARKS / WHEEL_DIAMETER)
+
+/* Motorregelung */
+#define PID_LOW_RATE (BOT_SPEED_MEDIUM / SPEED_TO_ENCODER_RATE) /*!< Encoder-rate/aufruf, fuer den dieser PID-Satz gilt */
+#define PID_LOW_Kp 8 /*!< Regelung PID-Parameter [Zehntel Schritte] */
+#define PID_LOW_Ki 6 /*!< Regelung PID-Parameter [Zehntel Schritte] */
+#define PID_LOW_Kd 0 /*!< Regelung PID-Parameter */
+
+#define PID_HIGH_RATE (BOT_SPEED_NORMAL / SPEED_TO_ENCODER_RATE) /*!< Encoder-rate/aufruf, fuer den dieser PID-Satz gilt */
+#define PID_HIGH_Kp 70 /*!< Regelung PID-Parameter [Zehntel Schritte] */
+#define PID_HIGH_Ki 40 /*!< Regelung PID-Parameter [Zehntel Schritte] */
+#define PID_HIGH_Kd 0 /*!< Regelung PID-Parameter */
+
+/* Einstellunge fuer die Verhaltensregeln */
+#define BORDER_DANGEROUS 0x3A0 /*!< Wert, ab dem wir sicher sind, dass es eine Kante ist */
+
+
+#define GLANCE_FACTOR 0.9 /*!< Schlangenlinienfaktor zur Erweiterung des Sensorfeldes */
+#define GLANCE_STRAIGHT 20 /*!< Anzahl der Zyklen, die nicht geschielt wird Gesamtzahl der Zyklen ist GLANCE_STRAIGHT + GLANCE_SIDE*4 */
+#define GLANCE_SIDE 5 /*!< Anzahl der Zyklen, die geschielt wird (jeweils pro Seite) Gesamtzahl der Zyklen ist GLANCE_STRAIGHT + GLANCE_SIDE*4 */
+
+
+
+#define COL_CLOSEST 200 /*!< Abstand in mm, den wir als zu nah betrachten -- je nach echtem Sensor ist das schon zu nah! */
+#define COL_NEAR 300 /*!< Nahbereich */
+#define COL_FAR 400 /*!< Fernbereich */
+
+
+
+#define SWEEP_STATE_TURN 0 /*!< Zustand: Drehung im Sweep. */
+#define SWEEP_STATE_CHECK 1 /*!< Zustamd: Ueberpruefe Objekt vor dem Bot. */
+
+/* Zustaende und Konstanten fuer das bot_solve_maze_behaviour-Verhalten */
+#define BOT_DIAMETER 12
+#define OPTIMAL_DISTANCE BOT_DIAMETER*12 /* etwas mehr als Bot-Durchmesser ist ideal (vergroessert aufgrund der kennlinien der sharps) */
+#define ADJUST_DISTANCE 10
+#define IGNORE_DISTANCE 240
+#define GROUND_GOAL 0x221
+#define STARTPAD1 0x2B2
+#define STARTPAD2 0x332
+
+
+/* Konstanten fuer das bot_follow_line_behaviour-Verhalten */
+#define LINE_SENSE 0x350 // Ab wann ist es Linie? (Fuer den Sim auf 350 setzen, helle Tischflaeche 50)
+
+
+/* Konstanten fuer Verhaltensanzeige, Verhalten mit prio von bis sichtbar */
+#define PRIO_VISIBLE_MIN 3
+#define PRIO_VISIBLE_MAX 200
+
+
+
+
+
+#endif /*BOTLOCAL_H_*/
diff --git a/source/ct-Bot/include/bot-logic/available_behaviours.h b/source/ct-Bot/include/bot-logic/available_behaviours.h
new file mode 100644
index 0000000..f1524cb
--- /dev/null
+++ b/source/ct-Bot/include/bot-logic/available_behaviours.h
@@ -0,0 +1,98 @@
+#ifndef AVAILABLE_BEHAVIOURS_H_
+#define AVAILABLE_BEHAVIOURS_H_
+
+#ifdef BEHAVIOUR_AVAILABLE
+
+//#define BEHAVIOUR_SIMPLE_AVAILABLE /*!< sind die Beispielverhalten vorhanden ?*/
+//#define BEHAVIOUR_DRIVE_SQUARE_AVAILABLE /*!< Demoverhalten im quadrat fahren vorhanden ?*/
+
+#define BEHAVIOUR_AVOID_BORDER_AVAILABLE /*!< Abgruenden ausweichen vorhanden ?*/
+#define BEHAVIOUR_AVOID_COL_AVAILABLE /*!< Hindernis ausweichen vorhanden ?*/
+//#define BEHAVIOUR_GOTO_AVAILABLE /*!< goto vorhanden ?*/
+#define BEHAVIOUR_GOTOXY_AVAILABLE /*!< gotoxy vorhanden ?*/
+#define BEHAVIOUR_TURN_AVAILABLE /*!< turn vorhanden ?*/
+
+#define BEHAVIOUR_DRIVE_DISTANCE_AVAILABLE /*!< strecke fahren vorhanden ?*/
+
+#define BEHAVIOUR_SCAN_AVAILABLE /*!< gegend scannen vorhanden ?*/
+#define BEHAVIOUR_SOLVE_MAZE_AVAILABLE /*!< Wandfolger vorhanden ?*/
+#define BEHAVIOUR_FOLLOW_LINE_AVAILABLE /*!< Linienfolger vorhanden ?*/
+
+#define BEHAVIOUR_SERVO_AVAILABLE /*!< Kontrollverhalten fuer die Servos */
+
+//#define BEHAVIOUR_OLYMPIC_AVAILABLE /*!< Olympiadenverhalten vorhanden ?*/
+
+#define BEHAVIOUR_CATCH_PILLAR_AVAILABLE /*!< Suche eine Dose und fange sie ein */
+
+#define BEHAVIOUR_REMOTECALL_AVAILABLE /*!< Nehmen wir Remote-kommandos entgegen?*/
+
+/* Aufgrund einer ganzen reihe von Abhaengigkeiten sollte man beim Versuch Speicher
+ * zu sparen, zuerst mal bei den Hauptverhalten ausmisten, sonst kommen die
+ * Unterverhalten durch die Hintertuer wieder rein
+ */
+#ifndef MAP_AVAILABLE
+ #undef BEHAVIOUR_SCAN_AVAILABLE
+#endif
+
+#ifdef BEHAVIOUR_GOTOXY_AVAILABLE
+ #define BEHAVIOUR_TURN_AVAILABLE
+#endif
+
+#ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
+ #define BEHAVIOUR_TURN_AVAILABLE
+#endif
+
+#ifdef BEHAVIOUR_FOLLOW_LINE_AVAILABLE
+ #define BEHAVIOUR_DRIVE_DISTANCE_AVAILABLE
+ #define BEHAVIOUR_TURN_AVAILABLE
+#endif
+
+#ifdef BEHAVIOUR_OLYMPIC_AVAILABLE
+ #define BEHAVIOUR_DRIVE_DISTANCE_AVAILABLE
+ #define BEHAVIOUR_TURN_AVAILABLE
+#endif
+
+#ifdef BEHAVIOUR_SIMPLE_AVAILABLE
+ #define BEHAVIOUR_DRIVE_DISTANCE_AVAILABLE
+#endif
+
+#ifdef BEHAVIOUR_SOLVE_MAZE_AVAILABLE
+ #define BEHAVIOUR_DRIVE_DISTANCE_AVAILABLE
+#endif
+
+#ifdef BEHAVIOUR_DRIVE_SQUARE_AVAILABLE
+ #define BEHAVIOUR_GOTO_AVAILABLE
+#endif
+
+#ifdef BEHAVIOUR_CATCH_PILLAR_AVAILABLE
+ #define BEHAVIOUR_SERVO_AVAILABLE
+#endif
+
+
+#include "bot-logic/behaviour_simple.h"
+#include "bot-logic/behaviour_drive_square.h"
+
+#include "bot-logic/behaviour_avoid_border.h"
+#include "bot-logic/behaviour_avoid_col.h"
+
+#include "bot-logic/behaviour_goto.h"
+#include "bot-logic/behaviour_gotoxy.h"
+
+#include "bot-logic/behaviour_turn.h"
+#include "bot-logic/behaviour_drive_distance.h"
+
+#include "bot-logic/behaviour_scan.h"
+
+
+#include "bot-logic/behaviour_solve_maze.h"
+#include "bot-logic/behaviour_follow_line.h"
+
+#include "bot-logic/behaviour_olympic.h"
+
+#include "bot-logic/behaviour_servo.h"
+#include "bot-logic/behaviour_catch_pillar.h"
+
+#include "bot-logic/remote_calls.h"
+
+#endif
+#endif /*AVAILABLE_BEHAVIOURS_H_*/
diff --git a/source/ct-Bot/include/bot-logic/behaviour_avoid_border.h b/source/ct-Bot/include/bot-logic/behaviour_avoid_border.h
new file mode 100644
index 0000000..e12301c
--- /dev/null
+++ b/source/ct-Bot/include/bot-logic/behaviour_avoid_border.h
@@ -0,0 +1,39 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_avoid_border.c
+ * @brief Vermeide Abgruende
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+#ifndef BEHAVIOUR_AVOID_BORDER_H_
+#define BEHAVIOUR_AVOID_BORDER_H_
+
+#include "bot-logic/bot-logik.h"
+#ifdef BEHAVIOUR_AVOID_BORDER_AVAILABLE
+/*!
+ * Verhindert, dass der Bot in Graeben faellt
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_avoid_border_behaviour(Behaviour_t *data);
+#endif
+
+#endif /*BEHAVIOUR_AVOID_BORDER_H_*/
diff --git a/source/ct-Bot/include/bot-logic/behaviour_avoid_col.h b/source/ct-Bot/include/bot-logic/behaviour_avoid_col.h
new file mode 100644
index 0000000..7a7acfb
--- /dev/null
+++ b/source/ct-Bot/include/bot-logic/behaviour_avoid_col.h
@@ -0,0 +1,42 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_avoid_col.h
+ * @brief Vermeide Kollisionen
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+#ifndef BEHAVIOUR_AVOID_COL_H_
+#define BEHAVIOUR_AVOID_COL_H_
+
+#include "bot-logic/bot-logik.h"
+
+#ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
+/*!
+ * Passt auf, dass keine Kollision mit Hindernissen an der Front des Roboters
+ * geschieht.
+ * TODO: Diese Funktion ist nur ein Dummy-Beispiel, wie eine Kollisionsvermeidung aussehen
+ * koennte. Hier ist ein guter Einstiegspunkt fuer eigene Experimente und Algorithmen!
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_avoid_col_behaviour(Behaviour_t *data);
+#endif
+#endif /*BEHAVIOUR_AVOID_COL_H_*/
diff --git a/source/ct-Bot/include/bot-logic/behaviour_catch_pillar.h b/source/ct-Bot/include/bot-logic/behaviour_catch_pillar.h
new file mode 100644
index 0000000..a1156b4
--- /dev/null
+++ b/source/ct-Bot/include/bot-logic/behaviour_catch_pillar.h
@@ -0,0 +1,51 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+
+
+/*! @file behaviour_catch_pillar.c
+ * @brief sucht nach einer Dose und fängt sie ein
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 08.12.06
+*/
+
+#ifndef BEHAVIOUR_CATCH_PILLAR_H_
+#define BEHAVIOUR_CATCH_PILLAR_H_
+
+#include "ct-Bot.h"
+#include "bot-logic/bot-logik.h"
+
+#ifdef BEHAVIOUR_CATCH_PILLAR_AVAILABLE
+/*!
+ * Fange eine Dose ein
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_catch_pillar_behaviour(Behaviour_t *data);
+
+/*!
+ * Botenfkt
+ * Fange eine Dose ein
+ * @param caller Der obligatorische Verhaltensdatensatz des Aufrufers
+ */
+void bot_catch_pillar(Behaviour_t * caller);
+
+#endif
+
+#endif /*BEHAVIOUR_CATCH_PILLAR_H_*/
diff --git a/source/ct-Bot/include/bot-logic/behaviour_drive_distance.h b/source/ct-Bot/include/bot-logic/behaviour_drive_distance.h
new file mode 100644
index 0000000..9d49ed9
--- /dev/null
+++ b/source/ct-Bot/include/bot-logic/behaviour_drive_distance.h
@@ -0,0 +1,57 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_drive_distance.c
+ * @brief Bot faehrt ein Stueck
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+#ifndef BEHAVIOUR_DRIVE_DISTANCE_H_
+#define BEHAVIOUR_DRIVE_DISTANCE_H_
+
+#include "bot-logic/bot-logik.h"
+
+#ifdef BEHAVIOUR_DRIVE_DISTANCE_AVAILABLE
+/*!
+ * Das Verhalten laesst den Bot eine vorher festgelegte Strecke fahren.
+ * @param *data der Verhaltensdatensatz
+ * @see bot_drive_distance()
+ */
+void bot_drive_distance_behaviour(Behaviour_t* data);
+
+/*!
+ * Das Verhalten laesst den Bot eine vorher festgelegte Strecke fahren. Dabei legt die Geschwindigkeit fest, ob der Bot vorwaerts oder rueckwaerts fahren soll.
+ * @param curve Gibt an, ob der Bot eine Kurve fahren soll. Werte von -127 (So scharf wie moeglich links) ueber 0 (gerade aus) bis 127 (so scharf wie moeglich rechts)
+ * @param speed Gibt an, wie schnell der Bot fahren soll. Negative Werte lassen den Bot rueckwaerts fahren.
+ * @param cm Gibt an, wie weit der Bot fahren soll. In cm :-) Die Strecke muss positiv sein, die Fahrtrichtung wird ueber speed geregelt.
+ */
+void bot_drive_distance(Behaviour_t* caller,int8 curve, int16 speed, int16 cm);
+
+/*!
+ * laesst den Bot in eine Richtung fahren.
+ * Es handelt sich hierbei nicht im eigentlichen Sinn um ein Verhalten, sondern ist nur eine Abstraktion der Motorkontrollen.
+ * @param curve Gibt an, ob der Bot eine Kurve fahren soll. Werte von -127 (So scharf wie moeglich links) ueber 0 (gerade aus) bis 127 (so scharf wie moeglich rechts)
+ * @param speed Gibt an, wie schnell der Bot fahren soll. */
+void bot_drive(int8 curve, int16 speed);
+
+#endif
+#endif /*BEHAVIOUR_DRIVE_DISTANCE_H_*/
+
diff --git a/source/ct-Bot/include/bot-logic/behaviour_drive_square.h b/source/ct-Bot/include/bot-logic/behaviour_drive_square.h
new file mode 100644
index 0000000..934a4e4
--- /dev/null
+++ b/source/ct-Bot/include/bot-logic/behaviour_drive_square.h
@@ -0,0 +1,50 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_drive_square.h
+ * @brief Bot faehrt im Quadrat
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+
+#ifndef BEHAVIOUR_DRIVE_SQUARE_H_
+#define BEHAVIOUR_DRIVE_SQUARE_H_
+
+#include "bot-logic/bot-logik.h"
+#ifdef BEHAVIOUR_DRIVE_SQUARE_AVAILABLE
+/*!
+ * Laesst den Roboter ein Quadrat abfahren.
+ * Einfaches Beispiel fuer ein Verhalten, das einen Zustand besitzt.
+ * Es greift auf andere Behaviours zurueck und setzt daher
+ * selbst keine speedWishes.
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_drive_square_behaviour(Behaviour_t *data);
+
+/*!
+ * Laesst den Roboter ein Quadrat abfahren.
+ * @param caller Der obligatorische Verhaltensdatensatz des aufrufers
+ */
+void bot_drive_square(Behaviour_t* caller);
+
+#endif
+
+#endif /*BEHAVIOUR_DRIVE_SQUARE_H_*/
diff --git a/source/ct-Bot/include/bot-logic/behaviour_follow_line.h b/source/ct-Bot/include/bot-logic/behaviour_follow_line.h
new file mode 100644
index 0000000..dcfaba0
--- /dev/null
+++ b/source/ct-Bot/include/bot-logic/behaviour_follow_line.h
@@ -0,0 +1,44 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_follow_line.h
+ * @brief Linienverfolger
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+#include "bot-logic/bot-logik.h"
+
+#ifndef BEHAVIOUR_FOLLOW_LINE_H_
+#define BEHAVIOUR_FOLLOW_LINE_H_
+
+#ifdef BEHAVIOUR_FOLLOW_LINE_AVAILABLE
+
+/*! Folgt einer Linie, sobald beide Liniensensoren ausloesen
+ * Die Linie sollte in etwa die Breite beider CNY70 haben
+ */
+void bot_follow_line_behaviour(Behaviour_t *data);
+
+/*! Folgt einer Linie, sobald beide Liniensensoren ausloesen
+ * Die Linie sollte in etwa die Breite beider CNY70 haben
+ */
+void bot_follow_line(Behaviour_t *caller);
+#endif
+#endif /*BEHAVIOUR_FOLLOW_LINE_H_*/
diff --git a/source/ct-Bot/include/bot-logic/behaviour_goto.h b/source/ct-Bot/include/bot-logic/behaviour_goto.h
new file mode 100644
index 0000000..9d34886
--- /dev/null
+++ b/source/ct-Bot/include/bot-logic/behaviour_goto.h
@@ -0,0 +1,46 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_goto.h
+ * @brief Fahre ein stueck
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+#ifndef BEHAVIOUR_GOTO_H_
+#define BEHAVIOUR_GOTO_H_
+
+#include "bot-logic/bot-logik.h"
+#ifdef BEHAVIOUR_GOTO_AVAILABLE
+/*!
+ * Kuemmert sich intern um die Ausfuehrung der goto-Kommandos,
+ * @param *data der Verhaltensdatensatz
+ * @see bot_goto()
+ */
+void bot_goto_behaviour(Behaviour_t *data);
+
+/*!
+ * Drehe die Raeder um die gegebene Zahl an Encoder-Schritten weiter
+ * @param left Schritte links
+ * @param right Schritte rechts
+ */
+void bot_goto(Behaviour_t * caller, int16 left, int16 right);
+#endif
+#endif /*BEHAVIOUR_GOTO_H_*/
diff --git a/source/ct-Bot/include/bot-logic/behaviour_gotoxy.h b/source/ct-Bot/include/bot-logic/behaviour_gotoxy.h
new file mode 100644
index 0000000..fedfb44
--- /dev/null
+++ b/source/ct-Bot/include/bot-logic/behaviour_gotoxy.h
@@ -0,0 +1,50 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_gotoxy.c
+ * @brief Bot faehrt eine Position an
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+
+#ifndef BEHAVIOUR_GOTOXY_H_
+#define BEHAVIOUR_GOTOXY_H_
+
+#include "bot-logic/bot-logik.h"
+
+#ifdef BEHAVIOUR_GOTOXY_AVAILABLE
+/*!
+ * Das Verhalten faehrt von der aktuellen Position zur angegebenen Position (x/y)
+ * @param *data der Verhaltensdatensatz
+ * Verbessert von Thomas Noll, Jens Schoemann, Ben Horst (Philipps-Universitaet Marburg)
+ */
+void bot_gotoxy_behaviour(Behaviour_t *data);
+
+/*!
+ * Botenfunktion: Das Verhalten faehrt von der aktuellen Position zur angegebenen Position (x/y)
+ * @param caller Aufrufendes Verhalten
+ * @param x X-Ordinate an die der Bot fahren soll
+ * @param y Y-Ordinate an die der Bot fahren soll
+ */
+void bot_gotoxy(Behaviour_t *caller, float x, float y);
+#endif
+
+#endif /*BEHAVIOUR_GOTOXY_H_*/
diff --git a/source/ct-Bot/include/bot-logic/behaviour_olympic.h b/source/ct-Bot/include/bot-logic/behaviour_olympic.h
new file mode 100644
index 0000000..84059e5
--- /dev/null
+++ b/source/ct-Bot/include/bot-logic/behaviour_olympic.h
@@ -0,0 +1,93 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_olympic.h
+ * @brief Bot sucht saeulen und faehrt dann slalom
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+#ifndef BEHAVIOUR_OLYMPIC_H_
+#define BEHAVIOUR_OLYMPIC_H_
+
+#include "bot-logic/bot-logik.h"
+#ifdef BEHAVIOUR_OLYMPIC_AVAILABLE
+
+/*!
+ * Das Verhalten setzt sich aus 3 Teilverhalten zusammen:
+ * Nach Licht suchen, auf das Licht zufahren, im Licht Slalom fahren. */
+void bot_olympic_behaviour(Behaviour_t *data);
+
+/*!
+ * Das Verhalten laesst den Roboter den Raum durchsuchen.
+ * Das Verhalten hat mehrere unterschiedlich Zustaende:
+ * 1. Zu einer Wand oder einem anderen Hindernis fahren.
+ * 2. Zu einer Seite drehen, bis der Bot parallel zur Wand ist.
+ * Es macht vielleicht Sinn, den Maussensor auszulesen, um eine Drehung um
+ * einen bestimmten Winkel zu realisieren. Allerdings muesste dafuer auch der
+ * Winkel des Bots zur Wand bekannt sein.
+ * 3. Eine feste Strecke parallel zur Wand vorwaerts fahren.
+ * Da bot_glance_behaviour abwechselnd zu beiden Seiten schaut, ist es fuer die Aufgabe,
+ * einer Wand auf einer Seite des Bots zu folgen, nur bedingt gewachsen und muss
+ * evtl. erweitert werden.
+ * 4. Senkrecht zur Wand drehen.
+ * Siehe 2.
+ * 5. Einen Bogen fahren, bis der Bot wieder auf ein Hindernis stoesst.
+ * Dann das Ganze von vorne beginnen, nur in die andere Richtung und mit einem
+ * weiteren Bogen. So erforscht der Bot einigermassen systematisch den Raum.
+ *
+ * Da das Verhalten jeweils nach 10ms neu aufgerufen wird, muss der Bot sich
+ * 'merken', in welchem Zustand er sich gerade befindet.
+ * */
+void bot_explore_behaviour(Behaviour_t *data);
+
+/*!
+ * Das Verhalten laesst den Bot einen Slalom fahren.
+ * @see bot_do_slalom()
+ * */
+void bot_do_slalom_behaviour(Behaviour_t *data);
+
+
+/*!
+ * Das Verhalten laesst den Bot zwischen einer Reihe beleuchteter Saeulen Slalom fahren.
+ * Das Verhalten ist wie bot_explore() in eine Anzahl von Teilschritten unterteilt.
+ * 1. Vor die aktuelle Saeule stellen, so dass sie zentral vor dem Bot und ungefaehr
+ * COL_CLOSEST (100 mm) entfernt ist.
+ * 2. 90 Grad nach rechts drehen.
+ * 3. In einem relativ engen Bogen 20 cm weit fahren.
+ * 4. Auf der rechten Seite des Bot nach einem Objekt suchen, dass
+ * a) im rechten Sektor des Bot liegt, also zwischen -45 Grad und -135 Grad zur Fahrtrichtung liegt,
+ * b) beleuchtet und
+ * c) nicht zu weit entfernt ist.
+ * Wenn es dieses Objekt gibt, wird es zur aktuellen Saeule und der Bot faehrt jetzt Slalom links.
+ * 5. Sonst zurueck drehen, 90 Grad drehen und Slalom rechts fahren.
+ * In diesem Schritt kann der Bot das Verhalten auch abbrechen, falls er gar kein Objekt mehr findet.
+ */
+void bot_do_slalom(Behaviour_t *caller);
+
+/*!
+ * Initialisiert das Olympische Verhalten
+ * @param prio_main Prioritaet des Olympischen Verhalten (typ. 100)
+ * @param prio_helper Prioritaet der Hilfsfunktionen (typ. 52)
+ * @param active ACTIVE wenn es sofort starten soll, sonst INACTIVE
+ */
+void bot_olympic_init(int8 prio_main,int8 prio_helper, int8 active);
+#endif
+#endif /*BEHAVIOUR_OLYMPIC_H_*/
diff --git a/source/ct-Bot/include/bot-logic/behaviour_scan.h b/source/ct-Bot/include/bot-logic/behaviour_scan.h
new file mode 100644
index 0000000..f194bf1
--- /dev/null
+++ b/source/ct-Bot/include/bot-logic/behaviour_scan.h
@@ -0,0 +1,51 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_scan.h
+ * @brief Scannt die Umgebung und traegt sie in die Karte ein
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+#ifndef BEHAVIOUR_SCAN_H_
+#define BEHAVIOUR_SCAN_H_
+
+#include "bot-logic/bot-logik.h"
+
+#ifdef BEHAVIOUR_SCAN_AVAILABLE
+/*!
+ * Der Roboter faehrt einen Vollkreis und scannt dabei die Umgebung
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_scan_onthefly_behaviour(Behaviour_t *data);
+
+/*!
+ * Der Roboter faehrt einen Vollkreis und scannt dabei die Umgebung
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_scan_behaviour(Behaviour_t *data);
+
+/*!
+ * Der Roboter faehrt einen Vollkreis und scannt dabei die Umgebung
+ * @param Der aufrufer
+ */
+void bot_scan(Behaviour_t* caller);
+#endif
+#endif /*BEHAVIOUR_SCAN_H_*/
diff --git a/source/ct-Bot/include/bot-logic/behaviour_servo.h b/source/ct-Bot/include/bot-logic/behaviour_servo.h
new file mode 100644
index 0000000..db8d59c
--- /dev/null
+++ b/source/ct-Bot/include/bot-logic/behaviour_servo.h
@@ -0,0 +1,55 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+
+
+/*! @file behaviour_servo.h
+ * @brief kontrolliert die Servos
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 07.12.06
+*/
+
+#ifndef BEHAVIOUR_SERVO_H_
+#define BEHAVIOUR_SERVO_H_
+
+#include "ct-Bot.h"
+#include "bot-logic/bot-logik.h"
+
+#ifdef BEHAVIOUR_SERVO_AVAILABLE
+
+uint8 servo_active; /*!< 0, wenn kein Servo aktiv, sonst Bit der gerade aktiven Servos gesetzt */
+
+/*!
+ * Dieses Verhalten fuehrt ein Servo-Kommando aus und schaltet danach den Servo wieder ab
+ *
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_servo_behaviour(Behaviour_t *data);
+
+/*!
+ * Fahre den Servo an eine Position
+ * @param servo Nummer des Servos
+ * @param pos Zielposition des Servos
+ */
+void bot_servo(Behaviour_t * caller, uint8 servo, uint8 pos);
+
+#endif
+
+#endif /*BEHAVIOUR_SIMPLE_H_*/
diff --git a/source/ct-Bot/include/bot-logic/behaviour_simple.h b/source/ct-Bot/include/bot-logic/behaviour_simple.h
new file mode 100644
index 0000000..c563ba1
--- /dev/null
+++ b/source/ct-Bot/include/bot-logic/behaviour_simple.h
@@ -0,0 +1,90 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+
+/*! @file behaviour_simple.h
+ * @brief ganz einfache Beispielverhalten
+ * Diese Datei sollte der Einstiegspunkt fuer eigene Experimente sein,
+ * den Roboter zu steuern.
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+#ifndef BEHAVIOUR_SIMPLE_H_
+#define BEHAVIOUR_SIMPLE_H_
+
+#include "ct-Bot.h"
+#include "bot-logic/bot-logik.h"
+
+#ifdef BEHAVIOUR_SIMPLE_AVAILABLE
+/*!
+ * Ein ganz einfaches Beispiel fuer ein Hilfsverhalten,
+ * das selbst SpeedWishes aussert und
+ * nach getaner Arbeit die aufrufende Funktion wieder aktiviert
+ * Zudem prueft es, ob eine Uebergabebedingung erfuellt ist.
+ *
+ * Zu diesem Verhalten gehoert die Botenfunktion bot_simple2()
+ *
+ * Hier kann man auf ganz einfache Weise die ersten Schritte wagen.
+ * Wer die Moeglichkeiten des ganzen Verhaltensframeworks ausschoepfen will, kann diese Funktion getrost auskommentieren
+ * und findet dann in bot_behave_init() und bot_behave() weitere Hinweise fuer elegante Bot-Programmierung....
+ *
+ * Das Verhalten ist per default abgeschaltet. Daher muss man es erst in bot_behave_init() aktivieren.
+ * Dort steht aber bereits eine auskommentierte Zeile dazu, von der man nur die zwei Kommentarzeichen wegnehmen muss.
+ * Achtung, da bot_simple2_behaviour() maximale Prioritaet hat, kommt es vor den anderen Regeln, wie dem Schutz vor Abgruenden, etc. zum Zuge
+ * Das sollte am Anfang nicht stoeren, spaeter sollte man jedoch die Prioritaet herabsetzen.
+ *
+ * bot_simple2_behaviour faehrt den Bot solange geradeaus, bis es dunkler als im Uebergabeparameter spezifiziert ist wird
+ *
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_simple2_behaviour(Behaviour_t *data);
+
+/*!
+ * Rufe das Simple2-Verhalten auf und uebergebe light
+ * @param caller Der obligatorische Verhaltensdatensatz des Aufrufers
+ * @param light Uebergabeparameter
+ */
+void bot_simple2(Behaviour_t * caller, int16 light);
+
+/*!
+ * Ein ganz einfaches Verhalten, es hat maximale Prioritaet
+ * Hier kann man auf ganz einfache Weise die ersten Schritte wagen.
+ * Wer die Moeglichkeiten des ganzen Verhaltensframeworks ausschoepfen will, kann diese Funktion getrost auskommentieren
+ * und findet dann in bot_behave_init() und bot_behave() weitere Hinweise fuer elegante Bot-Programmierung....
+ *
+ * Das Verhalten ist per default abgeschaltet. Daher muss man es erst in bot_behave_init() aktivieren.
+ * Dort steht aber bereits eine auskommentierte Zeile dazu, von der man nur die zwei Kommentarzeichen wegnehmen muss.
+ * Achtung, da bot_simple_behaviour() maximale Prioritaet hat, kommt es vor den anderen Regeln, wie dem Schutz vor Abgruenden, etc. zum Zuge
+ * Das sollte am Anfang nicht stoeren, spaeter sollte man jedoch die Prioritaet herabsetzen.
+ *
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_simple_behaviour(Behaviour_t *data);
+
+/*!
+ * Rufe das Simple-Verhalten auf
+ * @param caller Der obligatorische Verhaltensdatensatz des Aufrufers
+ */
+void bot_simple(Behaviour_t * caller, int16 light);
+
+#endif
+
+#endif /*BEHAVIOUR_SIMPLE_H_*/
diff --git a/source/ct-Bot/include/bot-logic/behaviour_solve_maze.h b/source/ct-Bot/include/bot-logic/behaviour_solve_maze.h
new file mode 100644
index 0000000..3450c32
--- /dev/null
+++ b/source/ct-Bot/include/bot-logic/behaviour_solve_maze.h
@@ -0,0 +1,61 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_solve_maze.h
+ * @brief Wandfolger durchs Labyrinth
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+
+
+#ifndef BEHAVIOUR_SOLVE_MAZE_H_
+#define BEHAVIOUR_SOLVE_MAZE_H_
+
+#include "bot-logic/bot-logik.h"
+
+#ifdef BEHAVIOUR_SOLVE_MAZE_AVAILABLE
+
+/*!
+ * Das Verhalten findet seinen Weg durch ein Labyrinth, das nach gewissen Grundregeln gebaut ist
+ * in nicht immer optimaler Weise aber in jedem Fall. Es arbeitet nach dem Hoehlenforscher-Algorithmus.
+ * Einschraenkung: Objekte im Labyrinth, die Endlossschleifen verursachen koennen, z.b. ein einzeln
+ * stehender Pfeiler im Labyrinth um den der Bot dann immer wieder herum fahren wuerde.
+ */
+
+void bot_solve_maze(Behaviour_t *caller);
+
+/*!
+ * Das Verhalten findet seinen Weg durch ein Labyrinth, das nach gewissen Grundregeln gebaut ist
+ * in nicht immer optimaler Weise aber in jedem Fall. Es arbeitet nach dem Hoehlenforscher-Algorithmus.
+ * Einschraenkung: Objekte im Labyrinth, die Endlossschleifen verursachen koennen, z.b. ein einzeln
+ * stehender Pfeiler im Labyrinth um den der Bot dann immer wieder herum fahren wuerde.
+ */
+void bot_solve_maze_behaviour(Behaviour_t *data);
+
+/*!
+ * Initialisiert den Hoelenforscher
+ * @param prio_main Prioritaet des Hoehlenforschers (typ. 100)
+ * @param prio_helper Prioritaet der Hilfsfunktionen (typ. 42)
+ * @param active ACTIVE wenn der hoehlenforcher sofort starten soll, sonst INACTIVE
+ */
+void bot_solve_maze_init(int8 prio_main,int8 prio_helper, int8 active);
+#endif
+#endif /*BEHAVIOUR_SOLVE_MAZE_H_*/
diff --git a/source/ct-Bot/include/bot-logic/behaviour_turn.h b/source/ct-Bot/include/bot-logic/behaviour_turn.h
new file mode 100644
index 0000000..872cdee
--- /dev/null
+++ b/source/ct-Bot/include/bot-logic/behaviour_turn.h
@@ -0,0 +1,51 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file behaviour_turn.h
+ * @brief Drehe den Bot
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+#ifndef BEHAVIOUR_TURN_H_
+#define BEHAVIOUR_TURN_H_
+
+#ifdef BEHAVIOUR_TURN_AVAILABLE
+#include "bot-logic/bot-logik.h"
+
+ /*!
+ * Das Verhalten laesst den Bot eine Punktdrehung durchfuehren.
++ * Drehen findet in drei Schritten statt. Die Drehung wird dabei
++ * bei Winkeln > 15 Grad zunaechst mit hoeherer Geschwindigkeit ausgefuehrt. Bei kleineren
++ * Winkeln oder wenn nur noch 15 Grad zu drehen sind, nur noch mit geringer Geschwindigkeit
+ * @param *data der Verhaltensdatensatz
+ * @see bot_turn()
+ */
+void bot_turn_behaviour(Behaviour_t *data);
+
+/*!
+ * Dreht den Bot im mathematisch positiven Sinn.
+ * @param degrees Grad, um die der Bot gedreht wird. Negative Zahlen drehen im (mathematisch negativen) Uhrzeigersinn.
+ * Die Aufloesung betraegt rund 3 Grad
+ */
+void bot_turn(Behaviour_t* caller,int16 degrees);
+
+#endif
+#endif
diff --git a/source/ct-Bot/include/bot-logic/bot-logik.h b/source/ct-Bot/include/bot-logic/bot-logik.h
new file mode 100644
index 0000000..7455c21
--- /dev/null
+++ b/source/ct-Bot/include/bot-logic/bot-logik.h
@@ -0,0 +1,196 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file bot-logik.h
+ * @brief High-Level-Routinen fuer die Steuerung des c't-Bots
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 01.12.05
+*/
+
+#ifndef bot_logik_H_
+#define bot_logik_H_
+
+#include "global.h"
+#include "ct-Bot.h"
+#include "motor.h"
+#include "sensor.h"
+#include "bot-local.h"
+
+
+#define BEHAVIOUR_DRIVE_AVAILABLE
+
+
+
+// Includes aller verfuegbaren Verhalten
+
+
+#define INACTIVE 0 /*!< Verhalten ist aus */
+#define ACTIVE 1 /*!< Verhalten ist an */
+
+#define OVERRIDE 1 /*!< Konstante, wenn Verhalten beim Aufruf alte Wuensche ueberschreiben sollen */
+#define NOOVERRIDE 0 /*!< Konstanten, wenn Verhalten beim Aufruf alte Wuensche nicht ueberschreiben sollen */
+
+#define SUBSUCCESS 1 /*!< Konstante fuer Behaviour_t->subResult: Aufgabe erfolgreich abgeschlossen */
+#define SUBFAIL 0 /*!< Konstante fuer Behaviour_t->subResult: Aufgabe nicht abgeschlossen */
+#define SUBRUNNING 2 /*!< Konstante fuer Behaviour_t->subResult: Aufgabe wird noch beabeitet */
+
+#define BOT_BEHAVIOUR_RUNNING 1 /*!< Rueckgabewert eines Verhaltens, das noch weiter laufen moechte. */
+#define BOT_BEHAVIOUR_DONE 0 /*!< Rueckgabewert eines Verhaltens, das fertig ist. */
+
+
+/*! Verwaltungsstruktur fuer die Verhaltensroutinen */
+typedef struct _Behaviour_t {
+ void (*work) (struct _Behaviour_t *data); /*!< Zeiger auf die Funktion, die das Verhalten bearbeitet */
+
+ uint8 priority; /*!< Prioritaet */
+ struct _Behaviour_t *caller ; /* aufrufendes verhalten */
+
+ uint8 active:1; /*!< Ist das Verhalten aktiv */
+ #ifdef DISPLAY_BEHAVIOUR_AVAILABLE
+ #ifndef DISPLAY_DYNAMIC_BEHAVIOUR_AVAILABLE /*!< bei dynamischer Anzeige und Wahl keine Puffervar notwendig */
+ uint8 active_new:1; /*!< Ist das via Display gewaehlte neue Sollverhalten */
+ #endif
+ #endif
+ uint8 subResult:2; /*!< War das aufgerufene unterverhalten erfolgreich (==1)?*/
+ struct _Behaviour_t *next; /*!< Naechster Eintrag in der Liste */
+#ifndef DOXYGEN
+ }__attribute__ ((packed)) Behaviour_t;
+#else
+ } Behaviour_t;
+#endif
+
+/*! Dieser Typ definiert eine Funktion die das eigentliche Verhalten ausfuehrt. */
+typedef void (*BehaviourFunc)(Behaviour_t *data);
+
+/*! Liste mit allen Verhalten */
+extern Behaviour_t *behaviour;
+
+extern int16 speedWishLeft; /*!< Puffervariablen fuer die Verhaltensfunktionen absolut Geschwindigkeit links*/
+extern int16 speedWishRight; /*!< Puffervariablen fuer die Verhaltensfunktionen absolut Geschwindigkeit rechts*/
+
+extern float faktorWishLeft; /*!< Puffervariablen fuer die Verhaltensfunktionen Modifikationsfaktor links*/
+extern float faktorWishRight; /*!< Puffervariablen fuer die Verhaltensfunktionen Modifikationsfaktor rechts */
+
+
+
+extern int16 target_speed_l; /*!< Sollgeschwindigkeit linker Motor */
+extern int16 target_speed_r; /*!< Sollgeschwindigkeit rechter Motor */
+
+/*!
+ * Kuemmert sich intern um die Ausfuehrung der goto-Kommandos
+ * @see bot_goto()
+ */
+extern void bot_behave(void);
+
+/*!
+ * Initilaisert das ganze Verhalten
+ */
+extern void bot_behave_init(void);
+
+/*!
+ * Aktiviert eine Regel mit gegebener Funktion
+ * @param function Die Funktion, die das Verhalten realisiert.
+ */
+void activateBehaviour(BehaviourFunc function);
+
+/*!
+ * Aktiviert eine Regel mit gegebener Funktion
+ * @param function Die Funktion, die das Verhalten realisiert.
+ */
+void deactivateBehaviour(BehaviourFunc function);
+
+/*!
+ * Deaktiviert alle Verhalten bis auf Grundverhalten. Bei Verhaltensauswahl werden die Aktivitaeten vorher
+ * in die Verhaltens-Auswahlvariable gesichert.
+ */
+void deactivateAllBehaviours(void);
+
+/*!
+ * Ruft ein anderes Verhalten auf und merkt sich den Ruecksprung
+ * return_from_behaviour() kehrt dann spaeter wieder zum aufrufenden Verhalten zurueck
+ * @param from aufrufendes Verhalten
+ * @param to aufgerufenes Verhalten
+ * @param override Hier sind zwei Werte Moeglich:
+ * 1. OVERRIDE : Das Zielverhalten to wird aktiviert, auch wenn es noch aktiv ist.
+ * Das Verhalten, das es zuletzt aufgerufen hat wird dadurch automatisch
+ * wieder aktiv und muss selbst sein eigenes Feld subResult auswerten, um zu pruefen, ob das
+ * gewuenschte Ziel erreicht wurde, oder vorher ein Abbruch stattgefunden hat.
+ * 2. NOOVERRIDE : Das Zielverhalten wird nur aktiviert, wenn es gerade nichts zu tun hat.
+ * In diesem Fall kann der Aufrufer aus seinem eigenen subResult auslesen,
+ * ob seibem Wunsch Folge geleistet wurde.
+ */
+void switch_to_behaviour(Behaviour_t * from, void *to, uint8 override );
+
+/*!
+ * Kehrt zum aufrufenden Verhalten zurueck
+ * @param running laufendes Verhalten
+ */
+void return_from_behaviour(Behaviour_t * data);
+
+
+/*!
+ * Fuegt ein Verhalten der Verhaltenliste anhand der Prioritaet ein.
+ * @param list Die Speicherstelle an der die globale Verhaltensliste anfaengt
+ * @param behave Einzufuegendes Verhalten
+ */
+void insert_behaviour_to_list(Behaviour_t **list, Behaviour_t *behave);
+
+/*!
+ * Erzeugt ein neues Verhalten
+ * @param priority Die Prioritaet
+ * @param *work Den Namen der Funktion, die sich drum kuemmert
+ */
+Behaviour_t *new_behaviour(uint8 priority, void (*work) (struct _Behaviour_t *data), int8 active);
+
+
+#include "bot-logic/available_behaviours.h"
+
+
+
+
+#ifdef DISPLAY_BEHAVIOUR_AVAILABLE
+
+ /*!
+ * ermittelt ob noch eine weitere Verhaltensseite existiert
+ */
+ extern int8 another_behaviour_page(void) ;
+
+/*!
+ * toggled ein Verhalten der Verhaltensliste an Position pos
+ * @param pos Listenposition, entspricht der Taste 1-6 der gewaehlten Verhaltensseite
+ */
+ void toggleNewBehaviourPos(int8 pos);
+
+/*!
+ * Startschuss, die gewaehlten neuen Verhaltensaktivitaeten werden in die
+ * Verhaltensliste geschrieben und die Verhalten damit scharf geschaltet
+ */
+ void set_behaviours_active_to_new(void);
+
+/*!
+ * Die Aktivitaeten der Verhalten werden in die Puffervariable geschrieben,
+ * welche zur Anzeige und Auswahl verwendet wird
+ */
+ void set_behaviours_equal(void);
+
+ int8 behaviour_page ; /*!< angezeigte Verhaltensseite */
+
+#endif
+
+#endif
diff --git a/source/ct-Bot/include/bot-logic/remote_calls.h b/source/ct-Bot/include/bot-logic/remote_calls.h
new file mode 100644
index 0000000..0771faa
--- /dev/null
+++ b/source/ct-Bot/include/bot-logic/remote_calls.h
@@ -0,0 +1,89 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file remote_calls.h
+ * @brief Liste mit Botenfkts, die man aus der Ferne aufrufen kann
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 19.12.06
+*/
+
+#ifndef REMOTE_CALLS_H_
+#define REMOTE_CALLS_H_
+
+#include "bot-logik.h"
+
+
+
+
+#define REMOTE_CALL_FUNCTION_NAME_LEN 20
+#define PARAM_TEXT_LEN 40
+#define REMOTE_CALL_MAX_PARAM 3
+
+#define REMOTE_CALL_BUFFER_SIZE (REMOTE_CALL_FUNCTION_NAME_LEN+1+REMOTE_CALL_MAX_PARAM*4)
+
+// Die Kommandostruktur
+typedef struct {
+ void* (*func)(void *); /*!< Zeiger auf die auszufuehrende Funktion*/
+ uint8 param_count; /*!< Anzahl der Parameter kommen Und zwar ohne den obligatorischen caller-parameter*/
+ uint8 param_len[REMOTE_CALL_MAX_PARAM]; /*!< Angaben ueber die Anzahl an Bytes, die jeder einzelne Parameter belegt */
+ char name[REMOTE_CALL_FUNCTION_NAME_LEN+1]; /*!< Text, maximal TEXT_LEN Zeichen lang + 1 Zeichen terminierung*/
+ char param_info[PARAM_TEXT_LEN+1]; /*!< String, der Angibt, welche und was fuer Parameter die Fkt erwartet */
+
+} call_t;
+
+typedef union{
+ uint32 u32;
+ float fl32;
+} remote_call_data_t; /*!< uint32 und float werden beide gleich ausgelesen, daher stecken wir sie in einen Speicherbereich */
+
+/*! Dieses Makro bereitet eine Botenfunktion als Remote-Call-Funktion vor.
+ * Der erste parameter ist der Funktionsname selbst
+ * Der zweite Parameter ist die Anzahl an Bytes, die die Fkt erwartet.
+ * Und zwar unabhaengig vom Datentyp. will man also einen uin16 uebergeben steht da 2
+ * Will man einen Float uebergeben eine 4. Fuer zwei Floats eine 8, usw.
+ */
+#define PREPARE_REMOTE_CALL(func,count,param,param_len...) {(void*)func, count, {param_len}, #func,param }
+
+
+/*!
+ * Dieses Verhalten kuemmert sich darum die Verhalten, die von außen angefragt wurden zu starten und liefert ein feedback zurueck, wenn sie beendet sind.
+ * @param *data der Verhaltensdatensatz
+ */
+void bot_remotecall_behaviour(Behaviour_t *data);
+
+/*!
+ * Fuehre einen remote_call aus. Es gibt KEIN aufrufendes Verhalten!!
+ * @param func Zeiger auf den Namen der Fkt
+ * @param data Zeiger auf die Daten
+ */
+void bot_remotecall(char* func, remote_call_data_t* data);
+
+/*!
+ * Fuehre einen remote_call aus. Es gibt KEIN aufrufendes Verhalten!!
+ * @param data Zeiger die Payload eines Kommandos. Dort muss zuerst ein String mit dem Fkt-Namen stehen. ihm folgen die Nutzdaten
+ */
+void bot_remotecall_from_command(uint8 * data);
+
+/*! Listet alle verfuegbaren Remote-Calls auf und verschickt sie als einzelne Kommanods
+ */
+void remote_call_list(void);
+
+
+#endif /*REMOTE_CALLS_H_*/
diff --git a/source/ct-Bot/include/command.h b/source/ct-Bot/include/command.h
new file mode 100644
index 0000000..7696635
--- /dev/null
+++ b/source/ct-Bot/include/command.h
@@ -0,0 +1,195 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file command.h
+ * @brief Kommando-Management
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 20.12.05
+*/
+
+#ifndef __command_h_
+#define __command_h_
+
+#include "global.h"
+#include "ct-Bot.h"
+
+#define MAX_PAYLOAD 255 /*!< Max. Anzahl Bytes, die an ein Command angehaengt werden */
+
+#ifdef PC
+ #define low_read tcp_read /*!< Which function to use to read data */
+ #define low_write tcp_send_cmd /*!< Which function to use to write data */
+ #define low_write_data tcp_write /*!< Which function to use to write data */
+#endif
+
+#ifdef MCU
+ #define low_read uart_read /*!< Which function to use to read data */
+ #define low_write uart_send_cmd /*!< Which function to use to write data */
+// #define low_write uart_send_cmd /*!< Which function to use to write data */
+ #define low_write_data uart_write /*!< Which function to use to write data */
+#endif
+
+
+/*!
+ * Request Teil eines Kommandos
+ */
+typedef struct {
+ uint8 command:8; /*!< command */
+ uint8 subcommand:7; /*!< subcommand */
+ uint8 direction:1; /*!< 0 ist Anfrage, 1 ist Antwort */
+#ifndef DOXYGEN
+ } __attribute__ ((packed)) request_t; // Keine Luecken in der Struktur lassen
+#else
+ } request_t; // Keine Luecken in der Struktur lassen
+#endif
+
+/*!
+ * Kommando
+ */
+typedef struct {
+ uint8 startCode; /*!< Markiert den Beginn eines Commands */
+ request_t request; /*!< Command-ID */
+ uint8 payload; /*!< Bytes, die dem Kommando noch folgen*/
+ int16 data_l; /*!< Daten zum Kommando links*/
+ int16 data_r; /*!< Daten zum Kommando rechts*/
+ int16 seq; /*!< Paket-Sequenznummer*/
+ uint8 CRC; /*!< Markiert das Ende des Commands*/
+#ifndef DOXYGEN
+ } __attribute__ ((packed)) command_t;// Keine Luecken in der Struktur lassen
+#else
+ } command_t;
+#endif
+
+#define CMD_STARTCODE '>' /*!< Anfang eines Kommandos*/
+#define CMD_STOPCODE '<' /*!< Ende eines Kommandos*/
+
+//Sensoren
+#define CMD_SENS_IR 'I' /*!< Abstandssensoren*/
+#define CMD_SENS_ENC 'E' /*!< Radencoder*/
+#define CMD_SENS_BORDER 'B' /*!< Abgrundsensoren*/
+#define CMD_SENS_LINE 'L' /*!< Liniensensoren*/
+#define CMD_SENS_LDR 'H' /*!< Helligkeitssensoren */
+#define CMD_SENS_TRANS 'T' /*!< Ueberwachung Transportfach */
+#define CMD_SENS_DOOR 'D' /*!< Ueberwachung Klappe */
+#define CMD_SENS_MOUSE 'm' /*!< Maussensor */
+#define CMD_SENS_ERROR 'e' /*!< Motor- oder Batteriefehler */
+#define CMD_SENS_RC5 'R' /*!< IR-Fernbedienung */
+
+#define CMD_SENS_MOUSE_PICTURE 'P' /*!< Bild vom Maussensor in data_l steht, welche Nummer da 1. Pixel hat*/
+
+
+// Aktuatoren
+#define CMD_AKT_MOT 'M' /*!< Motorgeschwindigkeit */
+#define CMD_AKT_DOOR 'd' /*!< Steuerung Klappe */
+#define CMD_AKT_SERVO 'S' /*!< Steuerung Servo */
+#define CMD_AKT_LED 'l' /*!< LEDs steuern */
+#define CMD_AKT_LCD 'c' /*!< LCD Anzeige */
+
+#define CMD_DONE 'X' /*!< Markiert das Ende einer Uebertragung */
+
+
+#define SUB_CMD_NORM 'N' /*!< Standard-Kommando */
+#define SUB_CMD_LEFT 'L' /*!< Kommmando fuer links */
+#define SUB_CMD_RIGHT 'R' /*!< Kommando fuer rechts */
+
+
+// Subcommandos fuer LCD
+#define SUB_LCD_CLEAR 'c' /*!< Subkommando Clear Screen */
+#define SUB_LCD_DATA 'D' /*!< Subkommando Text ohne Cursor */
+#define SUB_LCD_CURSOR 'C' /*!< Subkommando Cursorkoordinaten */
+
+// Log-Ausgaben
+#define CMD_LOG 'O' /*!< Logausgaben */
+
+//Kommandos fuer die Verbindung zum c't-Sim
+#define CMD_WELCOME 'W' /*!< Kommado zum anmelden an c't-Sim */
+#define SUB_WELCOME_REAL 'R' /*!< Subkommado zum anmelden eine realen Bots an c't-Sim */
+#define SUB_WELCOME_SIM 'S' /*!< Subkommado zum anmelden eines simulierten Bots an c't-Sim */
+
+//Kommandos fuer die Remote-Calls
+#define CMD_REMOTE_CALL 'r' /*!< Kommado fuer Remote-Calls */
+#define SUB_REMOTE_CALL_LIST 'L' /*!< Anforderung an den Bot alle verfuegbaren Kommandos zu listen */
+#define SUB_REMOTE_CALL_ENTRY 'E' /*!< Hiermit leifert der Bot ein erfuegbares Kommandos an den PC */
+#define SUB_REMOTE_CALL_ORDER 'O' /*!< Hiermit gibt der PC einen Remote-call in Auftrag */
+#define SUB_REMOTE_CALL_DONE 'D' /*!< Hiermit signalisiert der MCU dem PC die beendigung des Auftrags. Ergebins steht in DataL 0=FAIL 1=SUCCESS */
+
+
+
+#define DIR_REQUEST 0 /*!< Richtung fuer Anfragen */
+#define DIR_ANSWER 1 /*!< Richtung fuer Antworten */
+
+#ifdef PC // Auf dem PC muss der Zugriff auf received_command Thread-sicher sein
+ #include <pthread.h>
+ extern pthread_mutex_t command_mutex; /*!< Zugriff auf das Kommando */
+ #define command_lock() pthread_mutex_lock(&command_mutex) /*!< Zugriff auf das Kommando */
+ #define command_unlock() pthread_mutex_unlock(&command_mutex) /*!< Zugriff auf das Kommando */
+#endif
+
+
+extern command_t received_command; /*!< Puffer fuer Kommandos */
+
+/*!
+ * Liest ein Kommando ein, ist blockierend!
+ * greift auf low_read() zurueck
+ * @see low_read()
+ */
+int8 command_read(void);
+
+/*!
+ * Uebertraegt ein Kommando und wartet nicht auf eine Antwort
+ * @param command Kennung zum Command
+ * @param subcommand Kennung des Subcommand
+ * @param data_l Daten fuer den linken Kanal
+ * @param data_r Daten fuer den rechten Kanal
+ * @param payload Anzahl der Bytes, die diesem Kommando als Payload folgen
+ */
+void command_write(uint8 command, uint8 subcommand, int16* data_l,int16* data_r,uint8 payload);
+
+/*!
+ * Gibt dem Simulator Daten mit Anhang und wartet nicht auf Antwort
+ * @param command Kennung zum Command
+ * @param subcommand Kennung des Subcommand
+ * @param data_l Daten fuer den linken Kanal
+ * @param data_r Daten fuer den rechten Kanal
+ * @param data Datenanhang an das eigentliche Command
+ */
+void command_write_data(uint8 command, uint8 subcommand, int16* data_l, int16* data_r, const char* data);
+
+/*!
+ * Gibt dem Simulator Daten mit Anhang und wartet nicht auf Antwort
+ * @param command Kennung zum Command
+ * @param subcommand Kennung des Subcommand
+ * @param data_l Daten fuer den linken Kanal
+ * @param data_r Daten fuer den rechten Kanal
+ * @param payload Anzahl der Bytes im Anhang
+ * @param data Datenanhang an das eigentliche Command
+ */
+void command_write_rawdata(uint8 command, uint8 subcommand, int16* data_l, int16* data_r, uint8 payload, uint8* data);
+
+/*!
+ * Wertet das Kommando im Puffer aus
+ * return 1, wenn Kommando schon bearbeitet wurde, 0 sonst
+ */
+int command_evaluate(void);
+
+/*!
+ * Gibt ein Kommando auf dem Bildschirm aus
+ */
+void command_display(command_t * command);
+
+#endif
diff --git a/source/ct-Bot/include/delay.h b/source/ct-Bot/include/delay.h
new file mode 100644
index 0000000..cbf4a3a
--- /dev/null
+++ b/source/ct-Bot/include/delay.h
@@ -0,0 +1,41 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file delay.h
+ * @brief Hilfsroutinen
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 20.12.05
+*/
+#ifndef delay_H_
+#define delay_H_
+
+
+/*!
+ * Warte 100 ms
+ */
+void delay_100ms(void);
+
+/*!
+ * Verzoegert um ms Millisekunden
+ * Wenn RTC_AVAILABLE, dann ueber rtc, sonst ueber delay_100ms
+ * ==> Aufloesung ohne rtc: 100-ms-schritte; mit rtc: 5-ms-Schritte
+ * @param ms Anzahl der Millisekunden
+ */
+void delay(int ms);
+#endif
diff --git a/source/ct-Bot/include/display.h b/source/ct-Bot/include/display.h
new file mode 100644
index 0000000..db07a2b
--- /dev/null
+++ b/source/ct-Bot/include/display.h
@@ -0,0 +1,69 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file display.h
+ * @brief Routinen zur Displaysteuerung
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 20.12.05
+*/
+
+#ifndef display_H_
+#define display_H_
+
+#define DISPLAY_LENGTH 20 /*!< Wieviele Zeichen passen in eine Zeile */
+
+extern uint8 display_update; /*!< Muss das Display aktualisiert werden? */
+#ifdef DISPLAY_SCREENS_AVAILABLE
+ #define DISPLAY_SCREENS 5 /*!< Anzahl der Screens */
+ #define DISPLAY_SCREEN_TOGGLE 42 /*!< Screen-Nummer, die zum wechseln verwendet wird */
+ extern uint8 display_screen; /*!< Welcher Screen soll gezeigt werden? */
+#endif
+
+/*!
+ * Init Display
+ */
+void display_init(void);
+
+/*!
+ * Zeigt einen String an
+ * @return -1 falls String zu Ende, 0 falls Zeile (20 zeichen) zu Ende
+ */
+//int display_string(char data[20]);
+
+/*!
+ * Loescht das ganze Display
+ */
+void display_clear(void);
+
+/*!
+ * Positioniert den Cursor
+ * @param row Zeile
+ * @param column Spalte
+ */
+void display_cursor (uint8 row, uint8 column) ;
+
+/*!
+ * Schreibt einen String auf das Display.
+ * @param format Format, wie beim printf
+ * @param ... Variable Argumentenliste, wie beim printf
+ */
+void display_printf(char *format, ...);
+
+//void display_test();
+#endif
diff --git a/source/ct-Bot/include/ena.h b/source/ct-Bot/include/ena.h
new file mode 100644
index 0000000..09692cc
--- /dev/null
+++ b/source/ct-Bot/include/ena.h
@@ -0,0 +1,68 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file ena.h
+ * @brief Routinen zur Steuerung der Enable-Leitungen
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+
+#ifndef ENA_H_
+#define ENA_H_
+
+#ifndef MMC_LOW_H_
+ #include "global.h"
+#endif
+
+#define ENA_ABSTAND (1<<0) /*!< Enable-Leitung Abstandssensoren */
+#define ENA_RADLED (1<<1) /*!< Enable-Leitung Radencoder */
+#define ENA_SCHRANKE (1<<2) /*!< Enable-Leitung Fachueberwachung */
+#define ENA_KANTLED (1<<3) /*!< Enable-Leitung Angrundsensor */
+#define ENA_KLAPPLED (1<<4) /*!< Enable-Leitung Schieberueberwachung */
+#define ENA_MAUS (1<<5) /*!< Enable-Leitung Liniensensor auf Mausplatine */
+#define ENA_MMC (1<<6) /*!< Enable-Leitung Reserve 1 */
+#define ENA_MOUSE_SENSOR (1<<7) /*!< Enable-Leitung Reserve 2 */
+
+#ifndef MMC_LOW_H_
+/*!
+ * Initialisiert die Enable-Leitungen
+ */
+void ENA_init(void);
+
+/*!
+ * Schaltet einzelne Enable-Leitungen an,
+ * andere werden nicht beeinflusst
+ * @param enable Bitmaske der anzuschaltenden LEDs
+ */
+void ENA_on(uint8 enable);
+
+/*!
+ * Schaltet einzelne Enable-Leitungen aus,
+ * andere werden nicht beeinflusst
+ * @param enable Bitmaske der anzuschaltenden LEDs
+ */
+void ENA_off(uint8 enable);
+
+/*!
+ * Schaltet die Enable-Leitungen
+ * @param enable Wert der eingestellt werden soll
+ */
+void ENA_set(uint8 enable);
+#endif
+#endif
diff --git a/source/ct-Bot/include/global.h b/source/ct-Bot/include/global.h
new file mode 100644
index 0000000..93edce6
--- /dev/null
+++ b/source/ct-Bot/include/global.h
@@ -0,0 +1,67 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file global.h
+ * @brief Allgemeine Definitionen
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 20.12.05
+*/
+
+#ifndef global_H
+ #define global_H /*!< Bereits definiert */
+
+ #ifndef MCU
+ #ifndef PC
+ #define PC /*!< Zielplattform PC */
+ #endif
+ #endif
+
+ #ifndef WIN32
+ typedef unsigned char byte; /*!< vorzeichenlose 8-Bit-Zahl */
+ typedef byte bool; /*!< True/False-Aussage */
+ #endif
+
+ //#define DOXYGEN /*!< Nur zum Generieren von Doku!!!! */
+ #ifdef DOXYGEN /*!< Nur zum Generieren von Doku!!!! */
+ #define PC /*!< Zielplattform PC */
+ #define MCU /*!< Zielplattform MCU */
+ #define WIN32 /*!< System Windows */
+ #define __linux__ /*!< System Linux */
+ #endif
+
+ typedef unsigned char uint8; /*!< vorzeichenlose 8-Bit-Zahl */
+ typedef unsigned int word; /*!< vorzeichenlose 16-Bit-Zahl */
+ typedef signed char int8; /*!< vorzeichenbehaftete 8-Bit-Zahl */
+ typedef short int int16; /*!< vorzeichenbehaftete 16-Bit-Zahl */
+
+ typedef unsigned long uint32; /*!< vorzeichenlose 32-Bit-Zahl */
+ typedef signed long int32; /*!< vorzeichenbehaftete 32-Bit-Zahl */
+
+ #define uint16 word /*!< Int mit 16 Bit */
+
+ #define True 1 /*!< Wahr */
+ #define False 0 /*!< Falsch */
+
+ #define On 1 /*!< An */
+ #define Off 0 /*!< Aus */
+
+// #define PI 3.14159 /*!< Kreiszahl Pi fuer trigonometrische Berechnungen */
+ #define binary(var,bit) ((var >> bit)&1)
+ //#define NULL 0
+#endif
diff --git a/source/ct-Bot/include/ir-rc5.h b/source/ct-Bot/include/ir-rc5.h
new file mode 100644
index 0000000..fa770ae
--- /dev/null
+++ b/source/ct-Bot/include/ir-rc5.h
@@ -0,0 +1,51 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file ir-rc5.h
+ * @brief Routinen fuer die Dekodierung von RC5-Fernbedienungs-Codes
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 20.12.05
+*/
+#ifndef ir_rc5_H_
+#define ir_rc5_H_
+
+
+#include "ct-Bot.h"
+#include "global.h"
+
+
+extern volatile uint16 ir_data; /*!< letztes komplett gelesenes RC5-Paket */
+
+/*!
+ * Init IR-System
+ */
+void ir_init (void);
+
+/*!
+ * IR-Daten lesen
+ * @return Wert von ir_data, loescht anschliessend ir_data
+ */
+uint16 ir_read (void);
+
+/*!
+ * Interrupt Serviceroutine,
+ * wird ca. alle 177.8 �s aufgerufen
+ */
+void ir_isr (void);
+#endif
diff --git a/source/ct-Bot/include/led.h b/source/ct-Bot/include/led.h
new file mode 100644
index 0000000..8e65b8b
--- /dev/null
+++ b/source/ct-Bot/include/led.h
@@ -0,0 +1,86 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file led.h
+ * @brief Routinen zur LED-Steuerung
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+
+#ifndef led_H_
+#define led_H_
+
+#include "ct-Bot.h"
+
+#define LED_RECHTS (1<<0) /*!< LED in Fahrichtung rechts*/
+#define LED_LINKS (1<<1) /*!< LED in Fahrichtung links*/
+#define LED_ROT (1<<2) /*!< LED Rot */
+#define LED_ORANGE (1<<3) /*!< LED Orange */
+#define LED_GELB (1<<4) /*!< LED Gelb */
+#define LED_GRUEN (1<<5) /*!< LED Gruen */
+#define LED_TUERKIS (1<<6) /*!< LED Tuerkis */
+#define LED_WEISS (1<<7) /*!< LED Weiss */
+
+#define LED_ALL 0xFF /*!< LED Alle */
+
+/*! Datenfeld fuer den Zugriff auf die LEDs */
+typedef struct {
+ uint8 rechts:1; /*!< LED in Fahrichtung rechts*/
+ uint8 links:1; /*!< LED in Fahrichtung links*/
+
+ uint8 rot:1; /*!< LED Rot */
+ uint8 orange:1; /*!< LED Orange */
+
+ uint8 gelb:1; /*!< LED Gelb */
+ uint8 gruen:1; /*!< LED Gruen */
+
+ uint8 tuerkis:1; /*!< LED Tuerkis */
+ uint8 weiss:1; /*!< LED Weiss */
+#ifndef DOXYGEN
+ } __attribute__ ((packed)) led_t;
+#else
+ } led_t;
+#endif
+
+extern uint8 led;
+
+/*!
+ * Initialisiert die LEDs
+ */
+void LED_init(void);
+
+/*!
+ * Zeigt eine 8-Bit Variable mit den LEDs an
+ * @param LED Wert der gezeigt werden soll
+ */
+void LED_set(uint8 LED);
+
+/*! Schaltet eine LED aus
+ *
+ * @param LED HEX-Code der LED
+ */
+void LED_off(uint8 LED);
+
+/*! Schaltet eine LED an
+ *
+ * @param LED HEX-Code der LED
+ */
+void LED_on(uint8 LED);
+
+#endif
diff --git a/source/ct-Bot/include/log.h b/source/ct-Bot/include/log.h
new file mode 100644
index 0000000..eb6a35f
--- /dev/null
+++ b/source/ct-Bot/include/log.h
@@ -0,0 +1,172 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file log.c
+ * @brief Routinen zum Loggen von Informationen. Es sollten ausschliesslich nur
+ * die Log-Makros: LOG_DEBUG(), LOG_INFO(), LOG_WARN(), LOG_ERROR() und LOG_FATAL()
+ * verwendet werden.
+ * Eine Ausgabe kann wie folgt erzeugt werden:
+ * LOG_DEBUG(("Hallo Welt!"));
+ * LOG_INFO(("Wert x=%d", x));
+ * Wichtig ist die doppelte Klammerung. Bei den Ausgaben kann auf ein Line Feed
+ * '\n' am Ende des Strings verzichtet werden, da dies automatisch angeh�ngt
+ * hinzugefuegt wird.
+ *
+ * <pre>
+ * Die Logausgaben werden generell mit der Definition von LOG_AVAILABLE eingeschaltet
+ * und sind ansonsten nicht aktiv.
+ *
+ * Loggings auf dem PC:
+ * --------------------
+ * Hier stehen drei Arten der Ausgabeschnittstellen zur Verfuegung.
+ * 1. Logging ueber ct-Sim: LOG_CTSIM_AVAILABLE muss definiert sein.
+ * 2. Logging ueber Display: LOG_DISPLAY_AVAILABLE muss definiert sein, sowie
+ * DISPLAY_AVAILABLE und DISPLAY_SCREENS_AVAILABLE.
+ * Logging erfolgt auf Screen 5.
+ * 3. Logging ueber Konsole: Es muss LOG_STDOUT_AVAILABLE definiert sein.
+ *
+ * LOG_UART_AVAILABLE steht auf dem PC nicht zur Verfuegung.
+ *
+ * Loggings auf dem MCU:
+ * ---------------------
+ * Hier stehen drei Arten der Ausgabeschnittstellen zur Verfuegung.
+ * 1. Logging ueber UART: LOG_UART_AVAILABLE muss definiert sein.
+ * Es darf BOT_2_PC_AVAILABLE nicht definiert sein, da ansonsten
+ * diese Kommunikation ueber den UART laeuft.
+ * 2. Logging ueber ct-Sim: LOG_CTSIM_AVAILABLE muss definiert sein.
+ * BOT_2_PC_AVAILABLE muss zusaetzlich definiert sein.
+ * 3. Logging ueber Display: LOG_DISPLAY_AVAILABLE muss definiert sein, sowie
+ * DISPLAY_AVAILABLE und DISPLAY_SCREENS_AVAILABLE.
+ * Logging erfolgt auf Screen 5.
+ * </pre>
+ *
+ * @author Andreas Merkle (mail@blue-andi.de)
+ * @date 27.02.06
+*/
+
+#ifndef LOG_H_
+#define LOG_H_
+
+#include "ct-Bot.h"
+
+#ifdef LOG_AVAILABLE
+
+/*!
+ * Allgemeines Debugging (Methode DiesUndDas wurde mit Parameter SoUndSo
+ * aufgerufen ...)
+ */
+#define LOG_DEBUG(__dbg) log_begin(__FILE__, __LINE__, LOG_TYPE_DEBUG), \
+ log_printf __dbg, \
+ log_end()
+
+/*!
+ * Allgemeine Informationen (Programm gestartet, Programm beendet, Verbindung
+ * zu Host Foo aufgebaut, Verarbeitung dauerte SoUndSoviel Sekunden ...)
+ */
+#define LOG_INFO(__dbg) log_begin(__FILE__, __LINE__, LOG_TYPE_INFO), \
+ log_printf __dbg, \
+ log_end()
+
+/*!
+ * Auftreten einer unerwarteten Situation.
+ */
+#define LOG_WARN(__dbg) log_begin(__FILE__, __LINE__, LOG_TYPE_WARN), \
+ log_printf __dbg, \
+ log_end()
+
+/*!
+ * Fehler aufgetreten, Bearbeitung wurde alternativ fortgesetzt.
+ */
+#define LOG_ERROR(__dbg) log_begin(__FILE__, __LINE__, LOG_TYPE_ERROR), \
+ log_printf __dbg, \
+ log_end()
+
+/*!
+ * Kritischer Fehler, Programmabbruch.
+ */
+#define LOG_FATAL(__dbg) log_begin(__FILE__, __LINE__, LOG_TYPE_FATAL), \
+ log_printf __dbg, \
+ log_end()
+
+#else
+
+/*!
+ * Allgemeines Debugging (Methode DiesUndDas wurde mit Parameter SoUndSo
+ * aufgerufen ...)
+ */
+#define LOG_DEBUG(__dbg)
+
+/*!
+ * Allgemeine Informationen (Programm gestartet, Programm beendet, Verbindung
+ * zu Host Foo aufgebaut, Verarbeitung dauerte SoUndSoviel Sekunden ...)
+ */
+#define LOG_INFO(__dbg)
+
+/*!
+ * Auftreten einer unerwarteten Situation.
+ */
+#define LOG_WARN(__dbg)
+
+/*!
+ * Fehler aufgetreten, Bearbeitung wurde alternativ fortgesetzt.
+ */
+#define LOG_ERROR(__dbg)
+
+/*!
+ * Kritischer Fehler, Programmabbruch.
+ */
+#define LOG_FATAL(__dbg)
+
+#endif /* LOG_AVAILABLE */
+
+/*! Dieser Typ definiert die Typen der Log-Ausgaben. */
+typedef enum {
+ LOG_TYPE_DEBUG = 0, /*!< Allgemeines Debugging */
+ LOG_TYPE_INFO, /*!< Allgemeine Informationen */
+ LOG_TYPE_WARN, /*!< Auftreten einer unerwarteten Situation */
+ LOG_TYPE_ERROR, /*!< Fehler aufgetreten */
+ LOG_TYPE_FATAL /*!< Kritischer Fehler */
+} LOG_TYPE;
+
+#ifdef LOG_AVAILABLE
+
+/*!
+ * Schreibt Angaben ueber Datei, Zeilennummer und den Log-Typ in den Puffer.
+ * Achtung, Mutex wird gelockt und muss explizit durch log_end() wieder
+ * freigegeben werden!
+ * @param filename Dateiname
+ * @param line Zeilennummer
+ * @param log_type Log-Typ
+ */
+extern void log_begin(char *filename, unsigned int line, LOG_TYPE log_type);
+
+/*!
+ * Schreibt die eigentliche Ausgabeinformation in den Puffer.
+ * @param format Format
+ */
+extern void log_printf(char *format, ...);
+
+/*!
+ * Gibt den Puffer entsprechend aus.
+ */
+extern void log_end(void);
+
+#endif /* LOG_AVAILABLE */
+
+#endif /*LOG_H_*/
diff --git a/source/ct-Bot/include/map.h b/source/ct-Bot/include/map.h
new file mode 100644
index 0000000..0c72375
--- /dev/null
+++ b/source/ct-Bot/include/map.h
@@ -0,0 +1,149 @@
+#ifndef MAP_H_
+#define MAP_H_
+
+
+/*
+ * c't-Bot - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file map.h
+ * @brief Karte
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 19.09.06
+*/
+#include <stdio.h>
+#include "ct-Bot.h"
+
+#ifdef MAP_AVAILABLE
+
+/* Es lohnt nicht gigantische Karten auszugeben, wenn sie nichts enthalten, daher hier zwei Varianten, um die Karte auf die realen groesse zu reduzieren */
+#define SHRINK_MAP_ONLINE /*!< Wenn gesetzt, wird bei jedem update der belegte Bereich der Karte protokolliert. Pro: schnelle ausgabe Contra permanenter aufwand */
+//#define SHRINK_MAP_OFFLINE /*!< Wenn gesetzt, wird erst beid er Ausgabe der belegte Bereich der Karte berechnet. Pro: kein permanenter aufwand Contra: ausgabe dauert lange */
+
+#ifdef MCU
+ #ifdef MMC_AVAILABLE
+ #define MAP_SIZE 4 /*! Kantenlaenge der Karte in Metern. Ursprung ist der Startplatz des Bots */
+ #define MAP_RESOLUTION 128 /*!< Aufloesung der Karte in Punkte pro Meter */
+ #define MAP_SECTION_POINTS 16 /*!< Kantenlaenge einer Section in Punkten ==> eine Section braucht MAP_SECTION_POINTS*MAP_SECTION_POINTS Bytes */
+ #else
+ #define MAP_SIZE 4 /*! Kantenlaenge der Karte in Metern. Ursprung ist der Startplatz des Bots */
+ #define MAP_SECTION_POINTS 32 /*!< Kantenlaenge einer Section in Punkten ==> eine Section braucht MAP_SECTION_POINTS*MAP_SECTION_POINTS Bytes */
+ #define MAP_RESOLUTION (MAP_SECTION_POINTS/MAP_SIZE) /*!< Aufloesung der Karte in Punkte pro Meter */
+ #endif
+#else
+ #define MAP_SIZE 4 /*! Kantenlaenge der Karte in Metern. Ursprung ist der Startplatz des Bots */
+ #define MAP_RESOLUTION 128 /*!< Aufloesung der Karte in Punkte pro Meter */
+ #define MAP_SECTION_POINTS 16 /*!< Kantenlaenge einer Section in Punkten ==> eine Section braucht MAP_SECTION_POINTS*MAP_SECTION_POINTS Bytes */
+#endif
+
+// Die folgenden Variablen/konstanten NICHT direkt benutzen, sondern die zugehoerigen Makros: get_map_min_x() und Co!
+// Denn sonst erhaelt man Karten und nicht Weltkoordinaten!
+#ifdef SHRINK_MAP_ONLINE
+ extern uint16 map_min_x; /*!< belegter Bereich der Karte [Kartenindex]: kleinste X-Koordinate */
+ extern uint16 map_max_x; /*!< belegter Bereich der Karte [Kartenindex]: groesste X-Koordinate */
+ extern uint16 map_min_y; /*!< belegter Bereich der Karte [Kartenindex]: kleinste Y-Koordinate */
+ extern uint16 map_max_y; /*!< belegter Bereich der Karte [Kartenindex]: groesste Y-Koordinate */
+#else
+ #define map_min_x 0
+ #define map_min_y 0
+ #define map_max_x (MAP_SIZE*MAP_RESOLUTION)
+ #define map_max_y (MAP_SIZE*MAP_RESOLUTION)
+#endif
+
+
+
+/*!
+ * Aktualisiert die interne Karte
+ * @param x X-Achse der Position
+ * @param y Y-Achse der Position
+ * @param head Blickrichtung in Grad
+ * @param distL Sensorwert links
+ * @param distR Sensorwert rechts
+ */
+void update_map(float x, float y, float head, int16 distL, int16 distR);
+
+/*!
+ * Aktualisiert den Standkreis der internen Karte
+ * @param x X-Achse der Position
+ * @param y Y-Achse der Position
+ */
+void update_map_location(float x, float y);
+
+/*!
+ * liefert den Wert eines Feldes
+ * @param x x-Ordinate der Karte (nicht der Welt!!!)
+ * @param y y-Ordinate der Karte (nicht der Welt!!!)
+ * @return Wert des Feldes (>0 heisst frei, <0 heisst belegt
+ */
+int8 map_get_field (uint16 x, uint16 y);
+
+/*!
+ * liefert den Wert eines Feldes
+ * @param x x-Ordinate der Welt
+ * @param y y-Ordinate der Welt
+ * @return Wert des Feldes (>0 heisst frei, <0 heisst belegt
+ */
+int8 map_get_point (float x, float y);
+
+/*!
+ * Konvertiert eine Weltkoordinate in eine Kartenkoordinate
+ * @param koord Weltkordiante
+ * @return kartenkoordinate
+ */
+uint16 world_to_map(float koord);
+
+/*!
+ * Konvertiert eine Kartenkoordinate in eine Weltkoordinate
+ * @param map_koord kartenkoordinate
+ * @return Weltkordiante
+ */
+float map_to_world(uint16 map_koord);
+
+/*!
+ * Zeigt die Karte an
+ */
+void print_map(void);
+
+/*!
+ * initialisiere die Karte
+ * @return 0 wenn alles ok ist
+ */
+int8 map_init(void);
+
+/*! Liest eine Map wieder ein
+ * @param filename Quelldatei
+ */
+void read_map(char * filename);
+
+/*!
+ * Schreibt einbe Karte in eine PGM-Datei
+ * @param filename Zieldatei
+ */
+void map_to_pgm(char * filename);
+
+// Makros, um die belegte kartenbereiche (in weltkoordinaten) zu ermitteln
+#define map_get_min_x() map_to_world(map_min_x)
+#define map_get_min_y() map_to_world(map_min_y)
+#define map_get_max_x() map_to_world(map_max_x)
+#define map_get_max_y() map_to_world(map_max_y)
+
+
+#endif
+
+
+#endif /*MAP_H_*/
diff --git a/source/ct-Bot/include/mini-fat.h b/source/ct-Bot/include/mini-fat.h
new file mode 100644
index 0000000..7a936b8
--- /dev/null
+++ b/source/ct-Bot/include/mini-fat.h
@@ -0,0 +1,63 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file mini-fat.h
+ * @brief Routinen zum Auffinden von markierten Files auf einer MMC-Karte.
+ * Dies ist keine vollstaendige FAT-Unterstuetzung, sondern sucht nur eien Datei, die mit einer 3-Zeichen Sequenz beginnt.
+ * @author Benjamin Benz (bbe@heise.de)
+ * @author Ulrich Radig (mail@ulrichradig.de) www.ulrichradig.de
+ * @date 07.11.06
+*/
+
+#ifndef MINIFAT_H_
+#define MINIFAT_H_
+
+#include "ct-Bot.h"
+
+#define MMC_FILENAME_MAX 255 /*!< Maximale Dateienamenlaenge in Zeichen [1;255] */
+
+typedef union{
+ uint32 u32; // Laenge in 32 Bit
+ uint8 u8[4]; // laenge in 4 "einzelnen" Bytes
+} file_len_t;
+
+#ifdef MINI_FAT_AVAILABLE
+
+/*!
+ * Sucht einen Block auf der MMC-Karte, dessen erste drei Bytes dem key entsprechen
+ * liefert dann den folgenden Block zurueck.
+ * Achtung das prinzip geht nur, wenn die Dateien nicht fragmentiert sind
+ * @param key 3 Byte zur Identifikation
+ * @param buffer Zeiger auf 512 Byte Puffer im SRAM
+ */
+uint32 mini_fat_find_block(const char key[3], uint8* buffer);
+
+#endif
+
+#ifdef PC
+/*! Erzeugt eine Datei, die an den ersten 3 Byte die ID- enthaelt. dann folgen 512 - sizeof(id) nullen
+ * Danach kommen so viele size kByte Nullen
+ * @param filename Der Dateiname der zu erzeugenden Datei
+ * @param id_string Die ID des Files, wie sie zu beginn steht
+ * @param size kByte Nutzdaten, die der MCU spaeter beschreiben darf
+ */
+void create_mini_fat_file(const char* filename, const char* id_string, uint32 size);
+#endif
+
+#endif /*MINIFAT_H_*/
diff --git a/source/ct-Bot/include/mmc-emu.h b/source/ct-Bot/include/mmc-emu.h
new file mode 100644
index 0000000..2940942
--- /dev/null
+++ b/source/ct-Bot/include/mmc-emu.h
@@ -0,0 +1,85 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*!
+ * @file mmc-emu.h
+ * @brief MMC / SD-Card Emulation fuer PC
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 10.12.2006
+ */
+
+#ifndef MMC_EMU_H_
+#define MMC_EMU_H_
+
+#include "ct-Bot.h"
+
+#ifdef PC
+
+/*!
+ * Checkt Initialisierung der emulierten Karte
+ * @return 0, wenn initialisiert
+ * @see mcu/mmc.c
+ * @date 29.12.2006
+ */
+inline uint8 mmc_emu_get_init_state(void);
+
+/*!
+ * Initialisiere die emulierte SD/MMC-Karte
+ * @return 0 wenn allles ok, sonst 1
+ * @see mcu/mmc.c
+ * @date 29.12.2006
+ */
+uint8 mmc_emu_init (void);
+
+/*!
+ * Liest einen Block von der emulierten Karte
+ * @param addr Nummer des 512-Byte Blocks
+ * @param buffer Puffer von mindestens 512 Byte
+ * @return 0 wenn alles ok ist
+ * @see mcu/mmc.c
+ * @date 10.12.2006
+ */
+uint8 mmc_emu_read_sector(uint32 addr, uint8* buffer);
+
+/*!
+ * Schreibt einen 512-Byte Sektor auf die emulierte Karte
+ * @param addr Nummer des 512-Byte Blocks
+ * @param buffer Zeiger auf den Puffer
+ * @param async Wird bei der PC-Version nicht ausgewertet
+ * @return 0 wenn alles ok ist
+ * @date 10.12.2006
+ * @see mcu/mmc.c
+ */
+uint8 mmc_emu_write_sector(uint32 addr, uint8* buffer, uint8 async);
+
+/*!
+ * Liefert die Groesse der emulierten Karte zurueck
+ * @return Groesse der emulierten Karte in Byte.
+ * @date 29.12.2006
+ */
+uint32 mmc_emu_get_size(void);
+
+/*!
+ * Testet VM und MMC / SD-Card Emulation am PC
+ * @date 30.12.2006
+ */
+uint8 mmc_emu_test(void);
+
+#endif // PC
+#endif /*MMC_H_*/
diff --git a/source/ct-Bot/include/mmc-low.h b/source/ct-Bot/include/mmc-low.h
new file mode 100644
index 0000000..49f8105
--- /dev/null
+++ b/source/ct-Bot/include/mmc-low.h
@@ -0,0 +1,45 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*!
+ * @file mmc-low.h
+ * @brief Low-Level-Routinen zum Lesen/Schreiben einer MMC / SD-Card
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 14.11.06
+ */
+
+#ifndef MMC_LOW_H_
+#define MMC_LOW_H_
+
+/* Portkonfiguration */
+#define MMC_PORT_OUT PORTB // Port an der die MMC/SD-Karte angeschlossen ist also des SPI
+#define MMC_PORT_IN PINB
+#define MMC_DDR DDRB
+#define SPI_DI 6 // Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
+#define SPI_DO 5 // Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
+
+#define MMC_CLK_DDR DDRB
+#define MMC_CLK_PORT PORTB
+#define SPI_CLK 7 // Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
+
+#define MMC_TIMEOUT 500 // Wartezyklen auf Cardresponse
+#define MMC_ASYNC_WRITE 0 // 1 Aktiviert asynchrones Schreiben auf die Karte, wo es sinnvoll ist, 0 schaltet es aus. Funktioniert allerdings nicht mit allen Karten */
+
+
+#endif // MMC_LOW_H
diff --git a/source/ct-Bot/include/mmc-vm.h b/source/ct-Bot/include/mmc-vm.h
new file mode 100644
index 0000000..350d2ce
--- /dev/null
+++ b/source/ct-Bot/include/mmc-vm.h
@@ -0,0 +1,150 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*!
+ * @file mmc_vm.h
+ * @brief Virtual Memory Management mit MMC / SD-Card
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 30.11.2006
+ * @see Documentation/mmc-vm.html
+ */
+
+#ifndef MMC_VM_H_
+#define MMC_VM_H_
+
+#include "ct-Bot.h"
+
+#ifdef MMC_VM_AVAILABLE
+
+//#define VM_STATS_AVAILABLE /*!< Schaltet die Leistungsdatensammlung ein und ermoeglicht die Ausgabe einer Statistik */
+
+#ifdef VM_STATS_AVAILABLE
+ typedef struct{
+ uint32 page_access; /*!< Anzahl der Seitenzugriffe seit Systemstart */
+ uint32 swap_ins; /*!< Anzahl der Seiteneinlagerungen seit Systemstart */
+ uint32 swap_outs; /*!< Anzahl der Seitenauslagerungen seit Systemstart */
+ uint32 vm_used_bytes; /*!< Anzahl der vom VM belegten Bytes auf der MMC / SD-Card */
+ uint32 device_size; /*!< Groesse des Speichervolumes */
+ uint32 vm_size; /*!< Groesse des Virtuellen Speichers */
+ uint8 cache_size; /*!< Groesse des Caches */
+ int8 cache_load; /*!< Belegter Speicher des Caches */
+ uint16 page_access_s; /*!< Seitenzugriffe pro Sekunde */
+ uint16 swap_ins_s; /*!< Pagefaults pro Sekunde */
+ uint16 swap_outs_s; /*!< Seitenauslagerungen pro Sekunde */
+ uint16 delta_t; /*!< Sekunden seit Beginn der Messung */
+ } vm_extern_stats_t;
+
+ /*!
+ * Gibt die Anzahl der Pagefaults seit Systemstart bzw. Ueberlauf zurueck
+ * @return #Pagefaults
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 30.11.2006
+ */
+ uint32 mmc_get_pagefaults(void);
+
+ /*!
+ * Erstellt eine kleine Statistik ueber den VM
+ * @return Zeiger auf Statistikdaten
+ * @date 01.01.2007
+ */
+ vm_extern_stats_t* mmc_get_vm_stats(void);
+
+ /*!
+ * Gibt eine kleine Statistik ueber den VM aus (derzeit nur am PC)
+ * @date 01.01.2007
+ */
+ void mmc_print_statistic(void);
+#endif
+
+/*!
+ * Fordert virtuellen Speicher an
+ * @param size Groesse des gewuenschten Speicherblocks
+ * @param aligned 0: egal, 1: 512 Byte ausgerichtet
+ * @return Virtuelle Anfangsadresse des angeforderten Speicherblocks, 0 falls Fehler
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 30.11.2006
+ */
+uint32 mmcalloc(uint32 size, uint8 aligned);
+
+/*!
+ * Gibt einen Zeiger auf einen Speicherblock im RAM zurueck
+ * @param addr Eine virtuelle Adresse
+ * @return Zeiger auf uint8, NULL falls Fehler
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 30.11.2006
+ */
+uint8* mmc_get_data(uint32 addr);
+
+/*!
+ * Gibt die letzte Adresse einer Seite zurueck
+ * @param addr Eine virtuelle Adresse
+ * @return Adresse
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 30.11.2006
+ */
+inline uint32 mmc_get_end_of_page(uint32 addr);
+
+/*!
+ * Erzwingt das Zurueckschreiben einer eingelagerten Seite auf die MMC / SD-Card
+ * @param addr Eine virtuelle Adresse
+ * @return 0: ok, 1: Seite zurzeit nicht eingelagert, 2: Fehler beim Zurueckschreiben
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 15.12.2006
+ */
+uint8 mmc_page_write_back(uint32 addr);
+
+/*!
+ * Schreibt alle eingelagerten Seiten auf die MMC / SD-Card zurueck
+ * @return 0: alles ok, sonst: Fehler beim Zurueckschreiben
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 21.12.2006
+ */
+uint8 mmc_flush_cache(void);
+
+/*!
+ * Oeffnet eine Datei im FAT16-Dateisystem auf der MMC / SD-Card und gibt eine virtuelle Adresse zurueck,
+ * mit der man per mmc_get_data() einen Pointer auf die gewuenschten Daten bekommt. Das Ein- / Auslagern
+ * macht das VM-System automatisch. Der Dateiname muss derzeit am Amfang in der Datei stehen.
+ * Achtung: Irgendwann muss man die Daten per mmc_flush_cache() oder mmc_page_write_back() zurueckschreiben!
+ * @param filename Dateiname als 0-terminierter String
+ * @return Virtuelle Anfangsadresse der angeforderten Datei, 0 falls Fehler
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 21.12.2006
+ */
+uint32 mmc_fopen(const char *filename);
+
+/*!
+ * Leert eine Datei im FAT16-Dateisystem auf der MMC / SD-Card, die zuvor mit mmc_fopen() geoeffnet wurde.
+ * @param file_start (virtuelle) Anfangsadresse der Datei
+ * @return 0: ok, 1: ungueltige Datei oder Laenge, 2: Fehler beim Schreiben
+ * @date 02.01.2007
+ */
+uint8 mmc_clear_file(uint32 file_start);
+
+/*!
+ * Liest die Groesse einer Datei im FAT16-Dateisystem auf der MMC / SD-Card aus, die zu zuvor mit
+ * mmc_fopen() geoeffnet wurde.
+ * @param file_start (virtuelle Anfangsadresse der Datei)
+ * @return Groesse der Datei in Byte
+ * @date 12.01.2007
+ */
+uint32 mmc_get_filesize(uint32 file_start);
+
+#endif // MMC_VM_AVAILABLE
+#endif // MMC_VM_H_
diff --git a/source/ct-Bot/include/mmc.h b/source/ct-Bot/include/mmc.h
new file mode 100644
index 0000000..c652f3a
--- /dev/null
+++ b/source/ct-Bot/include/mmc.h
@@ -0,0 +1,104 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file mmc.h
+ * @brief Routinen zum Auslesen/Schreiben einer MMC-Karte
+ * @author Benjamin Benz (bbe@heise.de)
+ * @author Ulrich Radig (mail@ulrichradig.de) www.ulrichradig.de
+ * @date 07.11.06
+*/
+
+#ifndef MMC_H_
+#define MMC_H_
+
+#include "ct-Bot.h"
+
+#ifdef MMC_AVAILABLE
+
+#define MMC_INFO_AVAILABLE /*!< Die Karte kann uns einiges ueber sich verrraten, wenn wir sie danach fragen. Aber es kostet halt Platz im Flash */
+//#define MMC_WRITE_TEST_AVAILABLE /*!< Achtung dieser Test zerstoert die Daten auf der Karte!!! */
+
+/*!
+ * Checkt Initialisierung der Karte
+ * @return 0, wenn initialisiert
+ */
+inline uint8 mmc_get_init_state(void);
+
+uint8 mmc_enable(void);
+
+/*!
+ * Liest einen Block von der Karte
+ * @param addr Nummer des 512-Byte Blocks
+ * @param Buffer Puffer von mindestens 512 Byte
+ * @return 0 wenn alles ok ist, 1 wenn Init nicht moeglich oder Timeout vor / nach Kommando 17
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 17.11.2006
+ * @see mmc-low.s
+ */
+uint8 mmc_read_sector(uint32 addr, uint8 *buffer);
+
+/*!
+ * Schreibt einen 512-Byte Sektor auf die Karte
+ * @param addr Nummer des 512-Byte Blocks
+ * @param Buffer Zeiger auf den Puffer
+ * @param async 0: synchroner, 1: asynchroner Aufruf, siehe MMC_ASYNC_WRITE in mmc-low.h
+ * @return 0 wenn alles ok ist, 1 wenn Init nicht moeglich oder Timeout vor / nach Kommando 24, 2 wenn Timeout bei busy
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 16.11.2006
+ * @see mmc-low.s
+ */
+uint8 mmc_write_sector(uint32 addr, uint8 *buffer, uint8 async);
+
+/*!
+ * Initialisiere die SD/MMC-Karte
+ * @return 0 wenn allles ok, sonst Nummer des Kommandos bei dem abgebrochen wurde
+ */
+uint8 mmc_init (void);
+
+#ifdef MMC_INFO_AVAILABLE
+ /*!
+ * Liest das CSD-Register (16 Byte) von der Karte
+ * @param Buffer Puffer von mindestens 16 Byte
+ */
+ void mmc_read_csd (uint8 *buffer);
+
+ /*!
+ * Liest das CID-Register (16 Byte) von der Karte
+ * @param Buffer Puffer von mindestens 16 Byte
+ */
+ void mmc_read_cid (uint8 *buffer);
+
+ /*!
+ * Liefert die Groesse der Karte zurueck
+ * @return Groesse der Karte in Byte. Bei einer 4 GByte-Karte kommt 0xFFFFFFFF zurueck
+ */
+ uint32 mmc_get_size(void);
+#endif
+
+#ifdef MMC_WRITE_TEST_AVAILABLE
+ /*! Testet die MMC-Karte. Schreibt nacheinander 2 Sektoren a 512 Byte mit testdaten voll und liest sie wieder aus
+ * !!! Achtung loescht die Karte
+ * @return 0, wenn alles ok
+ */
+ uint8 mmc_test(void);
+#endif
+
+#endif
+
+#endif /*MMC_H_*/
diff --git a/source/ct-Bot/include/motor-low.h b/source/ct-Bot/include/motor-low.h
new file mode 100644
index 0000000..bdb6759
--- /dev/null
+++ b/source/ct-Bot/include/motor-low.h
@@ -0,0 +1,53 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file motor-low.h
+ * @brief Low-Level Routinen fuer die Motorsteuerung des c't-Bots
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 01.12.05
+*/
+
+#ifndef motor_low_H_
+#define motor_low_H_
+
+#include "global.h"
+
+
+
+
+/*!
+ * Initialisiert alles fuer die Motosteuerung
+ */
+void motor_low_init(void);
+
+/*!
+ * Unmittelbarer Zugriff auf die beiden Motoren
+ * normalerweise NICHT verwenden!!!!!
+ * @param left speed links
+ * @param right speed rechts
+*/
+void bot_motor(int16 left, int16 right);
+
+/*!
+ * Stellt die Servos
+ * Sinnvolle Werte liegen zwischen 8 und 16
+ */
+void servo_low(uint8 servo, uint8 pos);
+
+#endif
diff --git a/source/ct-Bot/include/motor.h b/source/ct-Bot/include/motor.h
new file mode 100644
index 0000000..3851497
--- /dev/null
+++ b/source/ct-Bot/include/motor.h
@@ -0,0 +1,98 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file motor.h
+ * @brief High-Level Routinen fuer die Motorsteuerung des c't-Bots
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 15.01.05
+*/
+#ifndef motor_H_
+#define motor_H_
+
+
+#include "global.h"
+#include "ct-Bot.h"
+
+#define BOT_SPEED_IGNORE 1000 /*!< Wert ausserhalb von -BOT_SPEED_MAX und BOT_SPEED_MAX wird verwendet um einen Eintrag zu ignorieren */
+#define BOT_SPEED_STOP 0 /*!< Motor aus */
+
+#define BOT_SPEED_SLOW 49 /*!< langsame Fahrt in mm/s */
+#define BOT_SPEED_FOLLOW 72 /*!< vorsichtige Fahrt, fuer Folgeverhalten in mm/s */
+#define BOT_SPEED_MEDIUM 99 /*!< mittlere Fahrt in mm/s */
+#define BOT_SPEED_NORMAL 144 /*!< normale Fahrt in mm/s */
+#define BOT_SPEED_FAST 297 /*!< schnelle Fahrt in mm/s */
+#define BOT_SPEED_MAX 450 /*!< maximale Fahrt in mm/s */
+
+
+#define DIRECTION_FORWARD 0 /*!< Drehrichtung vorwaerts */
+#define DIRECTION_BACKWARD 1 /*!< Drehrichtung rueckwaerts */
+
+
+#define DOOR_CLOSE 7 /*!< Rechter Anschlag des Servos */
+#define DOOR_OPEN 14 /*!< Linker Anschlag des Servos */
+#define SERVO_OFF 0 /*!< Servo wird zum stromsparen deaktiviert */
+
+#define SERVO1 1 /*!< Servo1 */
+#define SERVO2 2 /*!< Servo1 */
+
+extern int16 speed_l; /*!< Geschwindigkeit des linken Motors */
+extern int16 speed_r; /*!< Geschwindigkeit des rechten Motors */
+
+extern int16 motor_left; /*!< zuletzt gestellter Wert linker Motor */
+extern int16 motor_right; /*!< zuletzt gestellter Wert rechter Motor */
+
+
+/*! In diesem Typ steht die Drehrichtung, auch wenn die Speed-Variablen bereits wieder auf Null sind */
+typedef struct {
+ uint8 left:1;
+ uint8 right:1;
+#ifndef DOXYGEN
+ } __attribute__ ((packed)) direction_t;
+#else
+ } direction_t;
+#endif
+
+extern direction_t direction; /*!< Drehrichtung der Motoren, auch wenn die Speed-Variablen bereits wieder auf Null sind */
+
+/*!
+ * Initialisiere den Motorkrams
+ */
+void motor_init(void);
+
+/*!
+ * Direkter Zugriff auf den Motor
+ * @param left Geschwindigkeit fuer den linken Motor
+ * @param right Geschwindigkeit fuer den linken Motor
+ * zwischen -255 und +255;
+ * 0 bedeutet Stillstand, 255 volle Kraft voraus, -255 volle Kraft zurueck
+ * Sinnvoll ist die Verwendung der Konstanten: BOT_SPEED_XXX,
+ * also z.B. motor_set(BOT_SPEED_LOW,-BOT_SPEED_LOW);
+ * fuer eine langsame Drehung
+*/
+void motor_set(int16 left, int16 right);
+
+/*!
+ * Stellt die Servos
+ * Sinnvolle Werte liegen zwischen 8 und 16
+ * @param servo Nummer des Servos
+ * @param servo Zielwert
+ */
+void servo_set(uint8 servo, uint8 pos);
+
+#endif
diff --git a/source/ct-Bot/include/mouse.h b/source/ct-Bot/include/mouse.h
new file mode 100644
index 0000000..aa2b913
--- /dev/null
+++ b/source/ct-Bot/include/mouse.h
@@ -0,0 +1,113 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file mouse.h
+ * @brief Routinen fuer die Ansteuerung eines optischen Maussensors
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+
+#ifndef mouse_H_
+#define mouse_H_
+
+#define ADNS2610 /*!< Welcher Sensortyp? ADNS2610 oder 2620 */
+#ifdef ADNS2610
+ /* ADNS2610 */
+ #define MOUSE_CONFIG_REG 0x00 /*!< Reset, Power Down, Forced Awake, etc */
+ #define MOUSE_STATUS_REG 0x01 /*!< Product ID, Mouse state of Asleep or Awake */
+ #define MOUSE_DELTA_Y_REG 0x02 /*!< Y Movement */
+ #define MOUSE_DELTA_X_REG 0x03 /*!< X Movement */
+ #define MOUSE_SQUAL_REG 0x04 /*!< Measure of the number of features visible by the sensor */
+ #define MOUSE_MAX_PIXEL_REG 0x05 /*!< Maximum Pixel value in current frame.*/
+ #define MOUSE_MIN_PIXEL_REG 0x06 /*!< Minimum Pixel value in current frame.*/
+ #define MOUSE_PIXEL_SUM_REG 0x07 /*!< This register is used to find the average pixel value.*/
+ #define MOUSE_PIXEL_DATA_REG 0x08 /*!< Actual picture of surface */
+ #define MOUSE_SHUTTER_UPPER_REG 0x09 /*!< The sensor adjusts the shutter to keep the average and maximum pixel values within normal operating ranges.*/
+ #define MOUSE_SHUTTER_LOWER_REG 0x0A /*!< The sensor adjusts the shutter to keep the average and maximum pixel values within normal operating ranges.*/
+ #define MOUSE_INVERSE_PRODUCT_ID_REG 0x11 /*!< Inverse Product ID */
+
+ #define MOUSE_CFG_RESET 0x80 /*!< Reset Circuit */
+ #define MOUSE_CFG_POWERDOWN 0x40 /*!< Power Down analog Circuit */
+ #define MOUSE_CFG_FORCEAWAKE 0x01 /*!< Keep Sensor awake */
+
+#else
+ /* ADNS2620 */
+ #define MOUSE_CONFIG_REG 0x40 /*!< Reset, Power Down, Forced Awake, etc */
+ #define MOUSE_STATUS_REG 0x41 /*!< Product ID, Mouse state of Asleep or Awake */
+ #define MOUSE_DELTA_Y_REG 0x42 /*!< Y Movement */
+ #define MOUSE_DELTA_X_REG 0x43 /*!< X Movement */
+ #define MOUSE_SQUAL_REG 0x44 /*!< Measure of the number of features visible by the sensor */
+ #define MOUSE_MAX_PIXEL_REG 0x45 /*!< Maximum Pixel value in current frame.*/
+ #define MOUSE_MIN_PIXEL_REG 0x46 /*!< Minimum Pixel value in current frame.*/
+ #define MOUSE_PIXEL_SUM_REG 0x47 /*!< This register is used to find the average pixel value.*/
+ #define MOUSE_PIXEL_DATA_REG 0x48 /*!< Actual picture of surface */
+ #define MOUSE_SHUTTER_UPPER_REG 0x49 /*!< The sensor adjusts the shutter to keep the average and maximum pixel values within normal operating ranges.*/
+ #define MOUSE_SHUTTER_LOWER_REG 0x4A /*!< The sensor adjusts the shutter to keep the average and maximum pixel values within normal operating ranges.*/
+ #define MOUSE_FRAME_PERIOD_REG 0x4B /*!< The frame period counter counts up until it overflows. */
+#endif
+
+/*!
+ * Initialisiere Maussensor
+ */
+void maus_sens_init(void);
+
+/*!
+ * Schickt ein Lesekommando an den Sensor
+ * und liest ein Byte zurueck
+ * @param adr die Adresse
+ * @return das Datum
+ */
+uint8 maus_sens_read(uint8 adr);
+
+/*! Stellt sicher, dass der Maussensor nicht mehr die serielle Datenleitung treibt */
+#define maus_sens_highZ() maus_sens_write(0x77,0x00)
+
+/*!
+ * Uebertraegt ein write-Kommando an den Sensor
+ * @param adr Adresse
+ * @param data Datum
+ */
+void maus_sens_write(int8 adr, uint8 data);
+
+/*!
+ * Liefert bei jedem Aufruf das naechste Pixel des Bildes
+ * Insgesamt gibt es 324 Pixel
+ * <pre>
+ * 18 36 ... 324
+ * .. .. ... ..
+ * 2 20 ... ..
+ * 1 19 ... 307
+ * </pre>
+ * Bevor diese Funktion aufgerufen wird, muss maus_image_prepare() aufgerufen werden!
+ * @return Die Pixeldaten (Bit 0 bis Bit5), Pruefbit, ob Daten gueltig (Bit6), Markierung fuer den Anfang eines Frames (Bit7)
+ */
+int8 maus_image_read(void);
+
+/*!
+ * Bereitet das auslesen eines ganzen Bildes vor
+ */
+void maus_image_prepare(void);
+
+/*!
+ * Gibt den SQUAL-Wert zurueck. Dieser gibt an, wieviele Merkmale der Sensor
+ * im aktuell aufgenommenen Bild des Untergrunds wahrnimmt
+ */
+uint8 maus_get_squal(void);
+
+#endif
diff --git a/source/ct-Bot/include/rc5-codes.h b/source/ct-Bot/include/rc5-codes.h
new file mode 100644
index 0000000..9bf3b41
--- /dev/null
+++ b/source/ct-Bot/include/rc5-codes.h
@@ -0,0 +1,591 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file rc5-codes.h
+ * @brief RC5-Fernbedienungscodes
+ * @author Andreas Merkle (mail@blue-andi.de)
+ * @date 15.02.06
+ * Wer diese Datei angepasst hat, kann Sie durch einen .cvsignore Eintrag schützen.
+ * Dann Ueberschreibt Eclipse Sie nicht mehr automatisch
+*/
+
+#ifndef RC5CODE_H_
+#define RC5CODE_H_
+
+#define RC5_TOGGLE 0x0800 /*!< Das RC5-Toggle-Bit */
+#define RC5_ADDRESS 0x07C0 /*!< Der Adressbereich */
+#define RC5_COMMAND 0x103F /*!< Der Kommandobereich */
+
+/* Im Normalbetrieb hilft die Beschränkung der RC5_MASK auf RC5_COMMAND dem Bot,
+ * moeglichst viele FBs zu erkennen.
+ * Zum erfassen neuer Codes sollte man unbedingt RC5_MASK auf (RC5_COMMAND|RC5_ADDRESS) setzen */
+
+// Normalbetrieb
+#define RC5_MASK (RC5_COMMAND) /*!< Welcher Teil des Kommandos wird ausgewertet? */
+// Erfassen neuer FB-Codes
+//#define RC5_MASK (RC5_COMMAND|RC5_ADDRESS) /*!< Welcher Teil des Kommandos wird ausgewertet? */
+
+
+
+/*!
+ * Definition RC5-Codes verschiedener Fernbedienungen. Wer eine neue FB
+ * einfuegen will, sollte
+ *
+ * - eine Definition per cut&paste duplizieren,
+ * - eine geeignete Konstante RC_HAVE_{Herstellername}_{Fernbedienungsname}
+ * waehlen,
+ * - diese Konstante in die obere Liste der FB-Selektion eintragen,
+ * - die alte FB-Konstante im kopierten Bereich ersetzen,
+ * - festlegen, ob die FB ein Jog-Dial hat, ob der RC5_NOT_AVAIL-Code
+ * wirklich nie von der FB generiert werden kann (0xFFFF ist meisst ok)
+ * - die eigentlichen, herausgefunden Codes eintragen.
+ *
+ * Ist das erledigt, und funktioniert die neue FB-Definition, kann diese
+ * in der c't-bot-Entwicklerliste vorgestellt werden. (mb/18.03.2006)
+ */
+
+/* Nur auf dem realen Bot gibt es verschiedene FBs */
+#ifdef MCU
+
+ // Dies ist die Standard-Fernbedienung unter anderem fuer den Sim
+ #define RC_HAVE_HQ_RC_UNIVERS29_334
+
+ //#define RC_HAVE_HAUPPAUGE_WINTV
+ //#define RC_HAVE_HAUPPAUGE_MediaMPV
+ //#define RC_HAVE_CONRAD_PROMO8
+ //#define RC_HAVE_VIVANCO_UR89
+ //#define RC_HAVE_VIVANCO_UR89_TV_CODE_089
+ //#define RC_HAVE_Technisat_TTS35AI
+ //#define RC_HAVE_LIFETEC_LT3607
+ #else
+ // Dies ist die Standard-Fernbedienung unter anderem fuer den Sim
+ #define RC_HAVE_HQ_RC_UNIVERS29_334
+ //#define RC_HAVE_DEFAULT
+
+#endif
+
+
+
+// Code um zu kennzeichnen, dass eine Taste nicht vorhanden ist
+#define RC5_NOT_AVAIL (0xFFFF) /*!< Code fuer Taste nicht vorhanden */
+
+
+
+/*!
+ * Default-Fernbedienung
+ * HQ RC Univers 29, Geraetecode 334
+ */
+
+#ifdef RC_HAVE_HQ_RC_UNIVERS29_334
+ #define RC5_CODE_PWR (0x118C & RC5_MASK) /*!< Taste An/Aus */
+
+ #define RC5_CODE_0 (0x1180 & RC5_MASK) /*!< Taste 0 /10*/
+ #define RC5_CODE_1 (0x1181 & RC5_MASK) /*!< Taste 1 */
+ #define RC5_CODE_2 (0x1182 & RC5_MASK) /*!< Taste 2 */
+ #define RC5_CODE_3 (0x1183 & RC5_MASK) /*!< Taste 3 */
+ #define RC5_CODE_4 (0x1184 & RC5_MASK) /*!< Taste 4 */
+ #define RC5_CODE_5 (0x1185 & RC5_MASK) /*!< Taste 5 */
+ #define RC5_CODE_6 (0x1186 & RC5_MASK) /*!< Taste 6 */
+ #define RC5_CODE_7 (0x1187 & RC5_MASK) /*!< Taste 7 */
+ #define RC5_CODE_8 (0x1188 & RC5_MASK) /*!< Taste 8 */
+ #define RC5_CODE_9 (0x1189 & RC5_MASK) /*!< Taste 9 */
+ #define RC5_CODE_11 (0x118A & RC5_MASK) /*!< Taste 11 /1-*/
+ #define RC5_CODE_12 (0x11A3 & RC5_MASK) /*!< Taste 12 /2-*/
+
+ #define RC5_CODE_GREEN (0x01BA & RC5_MASK) /*!< Gruene Taste */
+ #define RC5_CODE_RED (0x01BD & RC5_MASK) /*!< Rote Taste */
+ #define RC5_CODE_YELLOW (0x01B1 & RC5_MASK) /*!< Gelbe Taste */
+ #define RC5_CODE_BLUE (0x01B0 & RC5_MASK) /*!< Blaue Taste */
+
+ #define RC5_CODE_I_II (0x11AB & RC5_MASK) /*!< I/II-Taste */
+ #define RC5_CODE_TV_VCR (0x11B8 & RC5_MASK) /*!< TV/VCR-Taste */
+
+ #define RC5_CODE_DOT (0x11AB & RC5_MASK) /*!< Taste mit rundem Punkt */
+
+ #define RC5_CODE_PLAY (0x11B5 & RC5_MASK) /*!< PLAY-Taste */
+ #define RC5_CODE_STILL (0x11A9 & RC5_MASK) /*!< Pause Taste */
+ #define RC5_CODE_STOP (0x11B6 & RC5_MASK) /*!< Pause Taste */
+ #define RC5_CODE_BWD (0x11B2 & RC5_MASK) /*!< Backward Taste */
+ #define RC5_CODE_FWD (0x11B4 & RC5_MASK) /*!< Forward Taste */
+
+ #define RC5_CODE_CH_PC (0x11BF & RC5_MASK) /*!< CH*P/C Taste */
+ #define RC5_CODE_MUTE (0x01BF & RC5_MASK) /*!< Mute-Taste */
+
+ #define RC5_VOL_PLUS (0x1190 & RC5_MASK) /*!< Vol + Taste */
+ #define RC5_VOL_MINUS (0x1191 & RC5_MASK) /*!< Vol - Taste */
+
+ #define RC5_CH_PLUS (0x11A0 & RC5_MASK) /*!< Ch + Taste */
+ #define RC5_CH_MINUS (0x11A1 & RC5_MASK) /*!< Ch - Taste */
+
+
+ #define RC5_CODE_UP RC5_CODE_STILL /*!< Taste Hoch */
+ #define RC5_CODE_DOWN RC5_CODE_STOP /*!< Taste Runter */
+ #define RC5_CODE_LEFT RC5_CODE_BWD /*!< Taste Links */
+ #define RC5_CODE_RIGHT RC5_CODE_FWD /*!< Taste Rechts */
+#endif
+
+/*!
+ * Default-Fernbedienung
+ * HQ RC Univers 29, Geraetecode 335
+ */
+
+#ifdef RC_HAVE_HQ_RC_UNIVERS29_335
+ #define RC5_CODE_PWR (0x100C & RC5_MASK) /*!< Taste An/Aus */
+
+ #define RC5_CODE_0 (0x1000 & RC5_MASK) /*!< Taste 0 /10*/
+ #define RC5_CODE_1 (0x1001 & RC5_MASK) /*!< Taste 1 */
+ #define RC5_CODE_2 (0x1002 & RC5_MASK) /*!< Taste 2 */
+ #define RC5_CODE_3 (0x1003 & RC5_MASK) /*!< Taste 3 */
+ #define RC5_CODE_4 (0x1004 & RC5_MASK) /*!< Taste 4 */
+ #define RC5_CODE_5 (0x1005 & RC5_MASK) /*!< Taste 5 */
+ #define RC5_CODE_6 (0x1006 & RC5_MASK) /*!< Taste 6 */
+ #define RC5_CODE_7 (0x1007 & RC5_MASK) /*!< Taste 7 */
+ #define RC5_CODE_8 (0x1008 & RC5_MASK) /*!< Taste 8 */
+ #define RC5_CODE_9 (0x1009 & RC5_MASK) /*!< Taste 9 */
+ #define RC5_CODE_11 (0x100A & RC5_MASK) /*!< Taste 11 /1-*/
+ #define RC5_CODE_12 (0x1003 & RC5_MASK) /*!< Taste 12 /2-*/
+
+ #define RC5_CODE_GREEN (0x101E & RC5_MASK) /*!< Gruene Taste */
+ #define RC5_CODE_RED (0x101D & RC5_MASK) /*!< Rote Taste */
+ #define RC5_CODE_YELLOW (0x1027 & RC5_MASK) /*!< Gelbe Taste */
+ #define RC5_CODE_BLUE (0x101C & RC5_MASK) /*!< Blaue Taste */
+
+ #define RC5_CODE_I_II (0x1023 & RC5_MASK) /*!< I/II-Taste */
+ #define RC5_CODE_TV_VCR (0x1038 & RC5_MASK) /*!< TV/VCR-Taste */
+
+ #define RC5_CODE_DOT (0x1037 & RC5_MASK) /*!< Taste mit rundem Punkt */
+
+ #define RC5_CODE_PLAY (0x11B5 & RC5_MASK) /*!< PLAY-Taste */
+ #define RC5_CODE_STILL (0x1029 & RC5_MASK) /*!< Pause Taste */
+ #define RC5_CODE_STOP (0x1036 & RC5_MASK) /*!< Pause Taste */
+ #define RC5_CODE_BWD (0x1032 & RC5_MASK) /*!< Backward Taste */
+ #define RC5_CODE_FWD (0x1034 & RC5_MASK) /*!< Forward Taste */
+
+ #define RC5_CODE_CH_PC (0x100B & RC5_MASK) /*!< CH*P/C Taste */
+ #define RC5_CODE_MUTE (0x003F & RC5_MASK) /*!< Mute-Taste */
+
+ #define RC5_VOL_PLUS (0x1010 & RC5_MASK) /*!< Vol + Taste */
+ #define RC5_VOL_MINUS (0x1011 & RC5_MASK) /*!< Vol - Taste */
+
+ #define RC5_CH_PLUS (0x1020 & RC5_MASK) /*!< Ch + Taste */
+ #define RC5_CH_MINUS (0x1021 & RC5_MASK) /*!< Ch - Taste */
+
+
+ #define RC5_CODE_UP RC5_CODE_STILL /*!< Taste Hoch */
+ #define RC5_CODE_DOWN RC5_CODE_STOP /*!< Taste Runter */
+ #define RC5_CODE_LEFT RC5_CODE_BWD /*!< Taste Links */
+ #define RC5_CODE_RIGHT RC5_CODE_FWD /*!< Taste Rechts */
+#endif
+
+/*!
+ * Fernbedienung Hauppauge (simple WinTV-Karten Fernbedienung)
+ */
+
+#ifdef RC_HAVE_HAUPPAUGE_WINTV
+ #define RC_HAVE_CODES /*!< Definiert Codes */
+ #undef JOG_DIAL /*!< Hat keinen Jog Dial */
+
+ #define RC5_CODE_0 (0x1000 & RC5_MASK) /*!< Taste 0 */
+ #define RC5_CODE_1 (0x1001 & RC5_MASK) /*!< Taste 1 */
+ #define RC5_CODE_2 (0x1002 & RC5_MASK) /*!< Taste 2 */
+ #define RC5_CODE_3 (0x1003 & RC5_MASK) /*!< Taste 3 */
+ #define RC5_CODE_4 (0x1004 & RC5_MASK) /*!< Taste 4 */
+ #define RC5_CODE_5 (0x1005 & RC5_MASK) /*!< Taste 5 */
+ #define RC5_CODE_6 (0x1006 & RC5_MASK) /*!< Taste 6 */
+ #define RC5_CODE_7 (0x1007 & RC5_MASK) /*!< Taste 7 */
+ #define RC5_CODE_8 (0x1008 & RC5_MASK) /*!< Taste 8 */
+ #define RC5_CODE_9 (0x1009 & RC5_MASK) /*!< Taste 9 */
+
+ #define RC5_CODE_PWR (0x1026 & RC5_MASK) /*!< Taste Minimize */
+ #define RC5_CODE_FULL (0x102E & RC5_MASK) /*!< Taste Full Screen */
+ #define RC5_CODE_SOURCE (0x1022 & RC5_MASK) /*!< Taste Source */
+
+ #define RC5_CODE_UP (0x1020 & RC5_MASK) /*!< Taste CH + */
+ #define RC5_CODE_DOWN (0x1021 & RC5_MASK) /*!< Taste CH - */
+ #define RC5_CODE_LEFT (0x1011 & RC5_MASK) /*!< Taste VOL- */
+ #define RC5_CODE_RIGHT (0x1010 & RC5_MASK) /*!< Taste VOL+ */
+
+ #define RC5_CODE_FWD RC5_NOT_AVAIL /*!< Taste nicht vorhanden */
+ #define RC5_CODE_BWD RC5_NOT_AVAIL /*!< Taste nicht vorhanden */
+ #define RC5_CODE_RED RC5_NOT_AVAIL /*!< Taste nicht vorhanden */
+ #define RC5_CODE_GREEN RC5_NOT_AVAIL /*!< Taste nicht vorhanden */
+ #define RC5_CODE_YELLOW RC5_NOT_AVAIL /*!< Taste nicht vorhanden */
+ #define RC5_CODE_BLUE RC5_NOT_AVAIL /*!< Taste nicht vorhanden */
+
+ #define RC5_CODE_I_II RC5_CODE_SOURCE
+ #define RC5_CODE_TV_VCR RC5_CODE_FULL
+#endif /* RC_HAVE_HAUPPAUGE_WINTV */
+
+#ifdef RC_HAVE_HAUPPAUGE_MediaMPV
+ #define RC_HAVE_CODES /*!< Definiert Codes */
+ #undef JOG_DIAL /*!< Hat keinen Jog Dial */
+
+ #define RC5_CODE_0 (0x17C0 & RC5_MASK) /*!< Taste 0 */
+ #define RC5_CODE_1 (0x17C1 & RC5_MASK) /*!< Taste 1 */
+ #define RC5_CODE_2 (0x17C2 & RC5_MASK) /*!< Taste 2 */
+ #define RC5_CODE_3 (0x17C3 & RC5_MASK) /*!< Taste 3 */
+ #define RC5_CODE_4 (0x17C4 & RC5_MASK) /*!< Taste 4 */
+ #define RC5_CODE_5 (0x17C5 & RC5_MASK) /*!< Taste 5 */
+ #define RC5_CODE_6 (0x17C6 & RC5_MASK) /*!< Taste 6 */
+ #define RC5_CODE_7 (0x17C7 & RC5_MASK) /*!< Taste 7 */
+ #define RC5_CODE_8 (0x17C8 & RC5_MASK) /*!< Taste 8 */
+ #define RC5_CODE_9 (0x17C9 & RC5_MASK) /*!< Taste 9 */
+
+ #define RC5_CODE_SELECT RC5_NOT_AVAIL /*!< Taste Source */
+
+ #define RC5_CODE_UP (0x17E0 & RC5_MASK) /*!< Taste CH + */
+ #define RC5_CODE_DOWN (0x17E1 & RC5_MASK) /*!< Taste CH - */
+ #define RC5_CODE_LEFT (0x17D1 & RC5_MASK) /*!< Taste VOL- */
+ #define RC5_CODE_RIGHT (0x17D0 & RC5_MASK) /*!< Taste VOL+ */
+
+ #define RC5_CODE_OK (0x17E5 & RC5_MASK) /*!< Taste OK */
+
+ #define RC5_CODE_PWR (0x17FD & RC5_MASK) /*!< Taste An/Aus */
+
+ #define RC5_CODE_RED (0x17CB & RC5_MASK) /*!< Taste Rot */
+ #define RC5_CODE_GREEN (0x17EE & RC5_MASK) /*!< Taste Gruen */
+ #define RC5_CODE_YELLOW (0x17F8 & RC5_MASK) /*!< Taste Gelb */
+ #define RC5_CODE_BLUE (0x17E9 & RC5_MASK) /*!< Taste Blau */
+
+ #define RC5_CODE_FWD (0x17F4 & RC5_MASK) /*!< Taste >> */
+ #define RC5_CODE_BWD (0x17F2 & RC5_MASK) /*!< Taste << */
+ #define RC5_CODE_PLAY (0x17F5 & RC5_MASK) /*!< Taste > */
+ #define RC5_CODE_RECORD (0x17F7 & RC5_MASK) /*!< Taste Aufnahme */
+ #define RC5_CODE_STOP (0x17F6 & RC5_MASK) /*!< Taste Stop */
+ #define RC5_CODE_WAIT (0x17F0 & RC5_MASK) /*!< Taste Pause */
+ #define RC5_CODE_REPLAY (0x17E4 & RC5_MASK) /*!< Taste Anfang |< */
+ #define RC5_CODE_SKIP (0x17DE & RC5_MASK) /*!< Taste Ende >| */
+
+ #define RC5_CODE_MUTE (0x17CF & RC5_MASK) /*!< Taste Mute */
+ #define RC5_CODE_VIEW (0x17CC & RC5_MASK) /*!< Taste View zwischen Mute und Full */
+ #define RC5_CODE_FULL (0x17FC & RC5_MASK) /*!< Taste Full */
+
+ #define RC5_CODE_BACK (0x17DF & RC5_MASK) /*!< Taste Back/Exit */
+ #define RC5_CODE_MENU (0x17CD & RC5_MASK) /*!< Taste Menue */
+ #define RC5_CODE_GO (0x17FB & RC5_MASK) /*!< Taste GO */
+
+ #define RC5_CODE_I_II RC5_CODE_SELECT
+ #define RC5_CODE_TV_VCR RC5_CODE_VIEW
+ #define RC5_CH_PLUS RC5_CODE_BWD /*!< Taste fuer Transprtfach schliessen */
+ #define RC5_CH_MINUS RC5_CODE_FWD /*!< Taste fuer Transportfach oeffnen */
+
+#endif /* RC_HAVE_HAUPPAUGE_MediaMPV */
+
+/*!
+ * Fernbedienung Conrad Promo 8
+ */
+
+#ifdef RC_HAVE_CONRAD_PROMO8
+ #define RC_HAVE_CODES /*!< Definiert Codes */
+ #undef JOG_DIAL /*!< Hat keinen Jog Dial */
+
+ #define RC5_CODE_0 (0x3000 & RC5_MASK) /*!< Taste 0 */
+ #define RC5_CODE_1 (0x3001 & RC5_MASK) /*!< Taste 1 */
+ #define RC5_CODE_2 (0x3002 & RC5_MASK) /*!< Taste 2 */
+ #define RC5_CODE_3 (0x3003 & RC5_MASK) /*!< Taste 3 */
+ #define RC5_CODE_4 (0x3004 & RC5_MASK) /*!< Taste 4 */
+ #define RC5_CODE_5 (0x3005 & RC5_MASK) /*!< Taste 5 */
+ #define RC5_CODE_6 (0x3006 & RC5_MASK) /*!< Taste 6 */
+ #define RC5_CODE_7 (0x3007 & RC5_MASK) /*!< Taste 7 */
+ #define RC5_CODE_8 (0x3008 & RC5_MASK) /*!< Taste 8 */
+ #define RC5_CODE_9 (0x3009 & RC5_MASK) /*!< Taste 9 */
+
+ #define RC5_CODE_UP (0x2010 & RC5_MASK) /*!< Taste Hoch */
+ #define RC5_CODE_DOWN (0x2011 & RC5_MASK) /*!< Taste Runter */
+ #define RC5_CODE_LEFT (0x2015 & RC5_MASK) /*!< Taste Links */
+ #define RC5_CODE_RIGHT (0x2016 & RC5_MASK) /*!< Taste Rechts */
+
+ #define RC5_CODE_ENTER (0x2017 & RC5_MASK) /*!< Enter-Taste*/
+ #define RC5_CODE_PWR (0x100C & RC5_MASK) /*!< Enter Taste als Ersatz fuer Taste An/Aus */
+
+ #define RC5_CODE_RED (0x202B & RC5_MASK) /*!< Rote Taste */
+ #define RC5_CODE_GREEN (0x202C & RC5_MASK) /*!< Gruene Taste */
+ #define RC5_CODE_YELLOW (0x202D & RC5_MASK) /*!< Gelbe Taste */
+ #define RC5_CODE_BLUE (0x202E & RC5_MASK) /*!< Blaue Taste */
+ #define RC5_CODE_VIEW (0x2012 & RC5_MASK) /*!< Instant View Taste */
+
+
+ #define RC5_CODE_SELECT (0x300D & RC5_MASK) /*!< Select Taste */
+ #define RC5_CODE_BWD (0x3011 & RC5_MASK) /*!< Backward Taste */
+ #define RC5_CODE_FWD (0x3010 & RC5_MASK) /*!< Forward Taste */
+
+ #define RC5_CH_PLUS (0x1020 & RC5_MASK) /*!< Ch + Taste */
+ #define RC5_CH_MINUS (0x1021 & RC5_MASK) /*!< Ch - Taste */
+
+ #define RC5_CODE_I_II RC5_CODE_SELECT
+ #define RC5_CODE_TV_VCR RC5_CODE_VIEW
+#endif
+
+/*!
+ * Fernbedienung VIVANCO UR89, vor Verwendung auf VCR druecken
+ * @author Andreas Staudenmayer
+ */
+#ifdef RC_HAVE_VIVANCO_UR89
+ #define RC_HAVE_CODES /*!< Definiert Codes */
+ #undef JOG_DIAL /*!< Hat keinen Jog Dial */
+
+ #define RC5_CODE_0 (0x1140 & RC5_MASK) /*!< Taste 0 */
+ #define RC5_CODE_1 (0x1141 & RC5_MASK) /*!< Taste 1 */
+ #define RC5_CODE_2 (0x1142 & RC5_MASK) /*!< Taste 2 */
+ #define RC5_CODE_3 (0x1143 & RC5_MASK) /*!< Taste 3 */
+ #define RC5_CODE_4 (0x1144 & RC5_MASK) /*!< Taste 4 */
+ #define RC5_CODE_5 (0x1145 & RC5_MASK) /*!< Taste 5 */
+ #define RC5_CODE_6 (0x1146 & RC5_MASK) /*!< Taste 6 */
+ #define RC5_CODE_7 (0x1147 & RC5_MASK) /*!< Taste 7 */
+ #define RC5_CODE_8 (0x1148 & RC5_MASK) /*!< Taste 8 */
+ #define RC5_CODE_9 (0x1149 & RC5_MASK) /*!< Taste 9 */
+
+ #define RC5_CODE_PWR (0x114C & RC5_MASK) /*!< Taste An, Aus */
+ #define RC5_CODE_VIEW RC5_NOT_AVAIL /*!< Taste nicht vorhanden */
+ #define RC5_CODE_SELECT RC5_NOT_AVAIL /*!< Taste nicht vorhanden */
+
+ #define RC5_CODE_UP (0x1160 & RC5_MASK) /*!< Taste Hoch */
+ #define RC5_CODE_DOWN (0x1161 & RC5_MASK) /*!< Taste Runter */
+ #define RC5_CODE_LEFT (0x0171 & RC5_MASK) /*!< Taste Links */
+ #define RC5_CODE_RIGHT (0x0170 & RC5_MASK) /*!< Taste Rechts */
+
+ #define RC5_CODE_FWD RC5_NOT_AVAIL /*!< Taste nicht vorhanden */
+ #define RC5_CODE_BWD RC5_NOT_AVAIL /*!< Taste nicht vorhanden */
+ #define RC5_CODE_RED (0x1172 & RC5_MASK) /*!< rote Taste */
+ #define RC5_CODE_GREEN (0x1176 & RC5_MASK) /*!< gruene Taste */
+ #define RC5_CODE_YELLOW (0x1175 & RC5_MASK) /*!< gelbe Taste */
+ #define RC5_CODE_BLUE (0x1174 & RC5_MASK) /*!< blaue Taste */
+
+ #define RC5_CODE_I_II RC5_CODE_SELECT
+ #define RC5_CODE_TV_VCR RC5_CODE_VIEW
+#endif /* RC_HAVE_VIVANCO_UR89 */
+
+
+/*!
+ * Fernbedienung VIVANCO UR89, TV Modus (Alle Tasten funktionieren)
+ * vor Verwendung fuer TV den Code 089 auf der Fernbedienung programmieren
+ * @author Ulrich Scheffler
+ */
+#ifdef RC_HAVE_VIVANCO_UR89_TV_CODE_089
+ #define RC_HAVE_CODES /*!< Definiert Codes */
+ #undef JOG_DIAL /*!< Hat keinen Jog Dial */
+
+ #define RC5_NOT_AVAIL (0xFFFF) /*!< Code fuer Taste nicht vorhanden */
+ /* Jede Taste bekommt erstmal die Bezeichnung, die aufgedruckt ist */
+ #define RC5_CODE_PWR (0x100C & RC5_MASK) /*!< Taste An/Aus-Symbol (rot)*/
+ #define RC5_CODE_MUTE (0x100D & RC5_MASK) /*!< Taste Mute-Symbol (gruen) */
+ #define RC5_CODE_CH_PLUS (0x1020 & RC5_MASK) /*!< Taste CH + (blau) */
+ #define RC5_CODE_CH_MINUS (0x1021 & RC5_MASK) /*!< Taste CH - (blau) */
+ #define RC5_CODE_VOL_MINUS (0x1011 & RC5_MASK) /*!< Taste VOL - (blau) */
+ #define RC5_CODE_VOL_PLUS (0x1010 & RC5_MASK) /*!< Taste VOL + (blau) */
+ #define RC5_CODE_BOX_WITH_DOT (0x0017 & RC5_MASK) /*!< Taste Quadrat mit Punkt */
+ #define RC5_CODE_TV_VCR (0x1038 & RC5_MASK) /*!< Taste TV/VCR (gleicher Code wie Taste A.B) */
+ #define RC5_CODE_0 (0x1000 & RC5_MASK) /*!< Taste 0 */
+ #define RC5_CODE_1 (0x1001 & RC5_MASK) /*!< Taste 1 */
+ #define RC5_CODE_2 (0x1002 & RC5_MASK) /*!< Taste 2 */
+ #define RC5_CODE_3 (0x1003 & RC5_MASK) /*!< Taste 3 */
+ #define RC5_CODE_4 (0x1004 & RC5_MASK) /*!< Taste 4 */
+ #define RC5_CODE_5 (0x1005 & RC5_MASK) /*!< Taste 5 */
+ #define RC5_CODE_6 (0x1006 & RC5_MASK) /*!< Taste 6 */
+ #define RC5_CODE_7 (0x1007 & RC5_MASK) /*!< Taste 7 */
+ #define RC5_CODE_8 (0x1008 & RC5_MASK) /*!< Taste 8 */
+ #define RC5_CODE_9 (0x1009 & RC5_MASK) /*!< Taste 9 */
+ #define RC5_CODE_RETURN (0x1022 & RC5_MASK) /*!< Taste Return-Symbol (gleicher Code wie Taste EXIT) */
+ #define RC5_CODE_A_DOT_B (0x1038 & RC5_MASK) /*!< Taste A.B (gleicher Code wie Taste TV/VCR) */
+ #define RC5_CODE_WAIT (0x002F & RC5_MASK) /*!< Taste Pause-Symbol */
+ #define RC5_CODE_GREEN (0x002C & RC5_MASK) /*!< Taste Gruen & Stop-Symbol */
+ #define RC5_CODE_RECORD (0x102E & RC5_MASK) /*!< Taste Aufnahme-Symbol */
+ #define RC5_CODE_BOX (0x103F & RC5_MASK) /*!< Taste Quadrat */
+ #define RC5_CODE_RED (0x002B & RC5_MASK) /*!< Taste Rot & << */
+ #define RC5_CODE_YELLOW (0x002D & RC5_MASK) /*!< Taste Gelb & > */
+ #define RC5_CODE_BLUE (0x002E & RC5_MASK) /*!< Taste Blau & >> */
+ #define RC5_CODE_BOX_WITH_3_EQUAL_LINES (0x103C & RC5_MASK) /*!< Taste Quadrat mit 3 gleichlangen Linien */
+ #define RC5_CODE_GREEN_UP (0x0010 & RC5_MASK) /*!< Taste hoch (gruen) */
+ #define RC5_CODE_GREEN_LEFT (0x0015 & RC5_MASK) /*!< Taste links (gruen) */
+ #define RC5_CODE_GREEN_RIGHT (0x0016 & RC5_MASK) /*!< Taste rechts (gruen) */
+ #define RC5_CODE_GREEN_DOWN (0x0011 & RC5_MASK) /*!< Taste runter (gruen) */
+ #define RC5_CODE_BOX_WITH_BOX (0x1029 & RC5_MASK) /*!< Taste Quadrat mit innerem Rechteck und Pfeilen */
+ #define RC5_CODE_BOX_WITH_3_UNEQUAL_LINES (0x102E & RC5_MASK) /*!< Taste Quadrat mit 3 ungleichlangen Linien */
+ #define RC5_CODE_OK (0x1023 & RC5_MASK) /*!< Taste OK (gruen) */
+ #define RC5_CODE_MENU (0x0012 & RC5_MASK) /*!< Taste MENU */
+ #define RC5_CODE_EXIT (0x1022 & RC5_MASK) /*!< Taste EXIT (gleicher Code wie Taste Return) */
+
+ /* Vorhandene Tasten werden hier mit der Wunsch-Funktion belegt (Umwidmung)*/
+ #define RC5_CODE_UP RC5_CODE_CH_PLUS /*!< Taste CH + wird genutzt fuer UP-Funktion */
+ #define RC5_CODE_DOWN RC5_CODE_CH_MINUS /*!< Taste CH - wird genutzt fuer DOWN-Funktion */
+ #define RC5_CODE_LEFT RC5_CODE_VOL_MINUS /*!< Taste VOL - wird genutzt fuer LEFT-Funktion */
+ #define RC5_CODE_RIGHT RC5_CODE_VOL_PLUS /*!< Taste VOL + wird genutzt fuer RIGHT-Funktion */
+ #define RC5_CODE_VIEW RC5_CODE_TV_VCR /*!< Taste TV/VCR & A.B werden genutzt fuer VIEW-Funktion*/
+ #define RC5_CODE_SELECT RC5_CODE_RETURN /*!< Taste Return & Exit werden genutzt fuer SELECT-Funktion */
+ #define RC5_CODE_BWD RC5_CODE_GREEN_LEFT /*!< Taste links (gruen) wird genutzt fuer BWD-Funktion (backward)*/
+ #define RC5_CODE_FWD RC5_CODE_GREEN_RIGHT /*!< Taste rechts (gruen) wird genutzt fuer FWD-Funktion (forward)*/
+
+ #define RC5_CODE_I_II RC5_CODE_SELECT
+ #define RC5_CODE_TV_VCR RC5_CODE_VIEW
+#endif /* RC_HAVE_VIVANCO_UR89_TV_CODE_089 */
+
+/*!
+ * Fernbedienung Technisat_TTS35AI (Receiver Digit CIP)
+ * @author Joerg Bullmann
+ */
+#ifdef RC_HAVE_Technisat_TTS35AI
+ #define RC_HAVE_CODES /*!< Definiert Codes */
+ #undef JOG_DIAL /*!< Hat keinen Jog Dial */
+
+ #define RC5_NOT_AVAIL (0xFFFF) /*!< Code fuer Taste nicht vorhanden */
+
+ #define RC5_CODE_0 (0x1289 & RC5_MASK) /*!< Taste 0 */
+ #define RC5_CODE_1 (0x1281 & RC5_MASK) /*!< Taste 1 */
+ #define RC5_CODE_2 (0x1282 & RC5_MASK) /*!< Taste 2 */
+ #define RC5_CODE_3 (0x1283 & RC5_MASK) /*!< Taste 3 */
+ #define RC5_CODE_4 (0x1284 & RC5_MASK) /*!< Taste 4 */
+ #define RC5_CODE_5 (0x1285 & RC5_MASK) /*!< Taste 5 */
+ #define RC5_CODE_6 (0x1286 & RC5_MASK) /*!< Taste 6 */
+ #define RC5_CODE_7 (0x1287 & RC5_MASK) /*!< Taste 7 */
+ #define RC5_CODE_8 (0x1288 & RC5_MASK) /*!< Taste 8 */
+ #define RC5_CODE_9 (0x1289 & RC5_MASK) /*!< Taste 9 */
+
+ #define RC5_CODE_PWR (0x128C & RC5_MASK) /*!< Taste An, Aus */
+ #define RC5_CODE_INFO (0x028F & RC5_MASK) /*!< Taste i */
+ #define RC5_CODE_OK (0x0297 & RC5_MASK) /*!< Taste ok */
+
+ #define RC5_CODE_UP (0x12A0 & RC5_MASK) /*!< Taste Hoch */
+ #define RC5_CODE_DOWN (0x12A1 & RC5_MASK) /*!< Taste Runter */
+ #define RC5_CODE_LEFT (0x1291 & RC5_MASK) /*!< Taste Links */
+ #define RC5_CODE_RIGHT (0x1290 & RC5_MASK) /*!< Taste Rechts */
+
+ #define RC5_CODE_TV (0x0293 & RC5_MASK) /*!< Taste TV */
+ #define RC5_CODE_MENU (0x0292 & RC5_MASK) /*!< Taste Menu */
+ #define RC5_CODE_RED (0x02AB & RC5_MASK) /*!< rote Taste */
+ #define RC5_CODE_GREEN (0x02AC & RC5_MASK) /*!< gruene Taste */
+ #define RC5_CODE_YELLOW (0x02AD & RC5_MASK) /*!< gelbe Taste */
+ #define RC5_CODE_BLUE (0x02AE & RC5_MASK) /*!< blaue Taste */
+
+ #define RC5_CODE_FWD RC5_CODE_TV /*!< Taste TV - umgewidmet als FWD-Taste */
+ #define RC5_CODE_BWD RC5_CODE_MENU /*!< Taste Menu - umgewidmet als BWD-Taste */
+ #define RC5_CODE_TV_VCR RC5_CODE_INFO /*!< Taste INFO - umgewidmet als View-Taste */
+ #define RC5_CODE_I_II RC5_CODE_OK /*!< Taste OK - umgewidmet als Select-Taste */
+
+#endif /* RC_HAVE_Technisat_TTS35AI */
+
+/*!
+ * Fernbedienung Lifetec LT3607 (aeltere, lernfaehige Medion-Fernbedienung)
+ */
+#ifdef RC_HAVE_LIFETEC_LT3607
+ #define RC_HAVE_CODES /*!< Definiert Codes */
+ #undef JOG_DIAL /*!< Hat keinen Jog Dial */
+
+ #define RC5_MASK (RC5_COMMAND)
+ #define RC5_NOT_AVAIL (0xFFFF) /*!< Code fuer Taste nicht vorhanden */
+
+ #define RC5_CODE_0 (0x3000 & RC5_MASK) /*!< Taste 0 */
+ #define RC5_CODE_1 (0x3001 & RC5_MASK) /*!< Taste 1 */
+ #define RC5_CODE_2 (0x3002 & RC5_MASK) /*!< Taste 2 */
+ #define RC5_CODE_3 (0x3003 & RC5_MASK) /*!< Taste 3 */
+ #define RC5_CODE_4 (0x3004 & RC5_MASK) /*!< Taste 4 */
+ #define RC5_CODE_5 (0x3005 & RC5_MASK) /*!< Taste 5 */
+ #define RC5_CODE_6 (0x3006 & RC5_MASK) /*!< Taste 6 */
+ #define RC5_CODE_7 (0x3007 & RC5_MASK) /*!< Taste 7 */
+ #define RC5_CODE_8 (0x3008 & RC5_MASK) /*!< Taste 8 */
+ #define RC5_CODE_9 (0x3009 & RC5_MASK) /*!< Taste 9 */
+
+ #define RC5_CODE_PWR (0x300C & RC5_MASK) /*!< Taste Power */
+ #define RC5_CODE_VIEW (0x303F & RC5_MASK) /*!< Taste OSD */
+ #define RC5_CODE_SELECT (0x303C & RC5_MASK) /*!< Taste Videotext */
+ #define RC5_CH_PLUS (0x3020 & RC5_MASK) /*!< Ch + Taste */
+ #define RC5_CH_MINUS (0x3021 & RC5_MASK) /*!< Ch - Taste */
+
+ #define RC5_CODE_UP (0x3020 & RC5_MASK) /*!< Taste CH + */
+ #define RC5_CODE_DOWN (0x3021 & RC5_MASK) /*!< Taste CH - */
+ #define RC5_CODE_LEFT (0x3011 & RC5_MASK) /*!< Taste VOL- */
+ #define RC5_CODE_RIGHT (0x3010 & RC5_MASK) /*!< Taste VOL+ */
+ #define RC5_CODE_I_II (0x3038 & RC5_MASK) /*!< A/B-Taste */
+ #define RC5_CODE_FWD (0x302B & RC5_MASK) /*!< Taste Mischbild */
+ #define RC5_CODE_BWD (0x302E & RC5_MASK) /*!< Taste Ueberblenden */
+ #define RC5_CODE_RED (0x3037 & RC5_MASK) /*!< Taste FRWD / Rot */
+ #define RC5_CODE_GREEN (0x3036 & RC5_MASK) /*!< Taste STOP / Gruen */
+ #define RC5_CODE_YELLOW (0x3032 & RC5_MASK) /*!< Taste PLAY / Gelb */
+ #define RC5_CODE_BLUE (0x3034 & RC5_MASK) /*!< Taste FFWD / Blau */
+ #define RC5_CODE_TV_VCR RC5_NOT_AVAIL
+#endif /* RC_HAVE_LIFETEC_LT3607 */
+
+/*!
+ * Default-Philips-Fernbedienung mit Jog-Dial-Rad
+ */
+
+#ifdef RC_HAVE_DEFAULT /*!< Default RC5-Codes falls keine FB definiert wurde */
+
+ #undef JOG_DIAL
+
+ #define RC5_CODE_0 (0x3940 & RC5_MASK) /*!< Taste 0 */
+ #define RC5_CODE_1 (0x3941 & RC5_MASK) /*!< Taste 1 */
+ #define RC5_CODE_2 (0x3942 & RC5_MASK) /*!< Taste 2 */
+ #define RC5_CODE_3 (0x3943 & RC5_MASK) /*!< Taste 3 */
+ #define RC5_CODE_4 (0x3944 & RC5_MASK) /*!< Taste 4 */
+ #define RC5_CODE_5 (0x3945 & RC5_MASK) /*!< Taste 5 */
+ #define RC5_CODE_6 (0x3946 & RC5_MASK) /*!< Taste 6 */
+ #define RC5_CODE_7 (0x3947 & RC5_MASK) /*!< Taste 7 */
+ #define RC5_CODE_8 (0x3948 & RC5_MASK) /*!< Taste 8 */
+ #define RC5_CODE_9 (0x3949 & RC5_MASK) /*!< Taste 9 */
+
+ #define RC5_CODE_UP (0x2950 & RC5_MASK) /*!< Taste Hoch */
+ #define RC5_CODE_DOWN (0x2951 & RC5_MASK) /*!< Taste Runter */
+ #define RC5_CODE_LEFT (0x2955 & RC5_MASK) /*!< Taste Links */
+ #define RC5_CODE_RIGHT (0x2956 & RC5_MASK) /*!< Taste Rechts */
+
+ #define RC5_CODE_PWR (0x394C & RC5_MASK) /*!< Taste An/Aus */
+
+ #define RC5_CODE_RED (0x100B & RC5_MASK) /*!< Rote Taste */
+ #define RC5_CODE_GREEN (0x102E & RC5_MASK) /*!< Gruene Taste */
+ #define RC5_CODE_YELLOW (0x1038 & RC5_MASK) /*!< Gelbe Taste */
+ #define RC5_CODE_BLUE (0x1029 & RC5_MASK) /*!< Blaue Taste */
+ #define RC5_CODE_VIEW (0x000F & RC5_MASK) /*!< Instant View Taste */
+
+ #define RC5_CODE_SELECT (0x100B & RC5_MASK) /*!< Select Taste */
+
+ #define RC5_CODE_BWD (0x1025 & RC5_MASK) /*!< Backward Taste */
+ #define RC5_CODE_FWD (0x1026 & RC5_MASK) /*!< Forward Taste */
+
+ #define RC5_CODE_I_II RC5_CODE_SELECT
+ #define RC5_CODE_TV_VCR RC5_CODE_VIEW
+
+ #define RC5_CH_PLUS RC5_NOT_AVAIL /*!< Ch + Taste */
+ #define RC5_CH_MINUS RC5_NOT_AVAIL /*!< Ch - Taste */
+
+ #ifdef JOG_DIAL
+ /* Jogdial geht nur inkl. Adresscode */
+ #undef RC5_MASK
+ #define RC5_MASK (RC5_COMMAND | RC5_ADDRESS)
+
+ #define RC5_CODE_JOG_MID (0x3969 & RC5_MASK) /*!< Taste Jog-Dial Mitte */
+ #define RC5_CODE_JOG_L1 (0x3962 & RC5_MASK) /*!< Taste Jog-Dial Links 1 */
+ #define RC5_CODE_JOG_L2 (0x396F & RC5_MASK) /*!< Taste Jog-Dial Links 2 */
+ #define RC5_CODE_JOG_L3 (0x395F & RC5_MASK) /*!< Taste Jog-Dial Links 3 */
+ #define RC5_CODE_JOG_L4 (0x3A6C & RC5_MASK) /*!< Taste Jog-Dial Links 4 */
+ #define RC5_CODE_JOG_L5 (0x3A6B & RC5_MASK) /*!< Taste Jog-Dial Links 5 */
+ #define RC5_CODE_JOG_L6 (0x396C & RC5_MASK) /*!< Taste Jog-Dial Links 6 */
+ #define RC5_CODE_JOG_L7 (0x3A6A & RC5_MASK) /*!< Taste Jog-Dial Links 7 */
+
+ #define RC5_CODE_JOG_R1 (0x3968 & RC5_MASK) /*!< Taste Jog-Dial Rechts 1 */
+ #define RC5_CODE_JOG_R2 (0x3975 & RC5_MASK) /*!< Taste Jog-Dial Rechts 2 */
+ #define RC5_CODE_JOG_R3 (0x396A & RC5_MASK) /*!< Taste Jog-Dial Rechts 3 */
+ #define RC5_CODE_JOG_R4 (0x3A6D & RC5_MASK) /*!< Taste Jog-Dial Rechts 4 */
+ #define RC5_CODE_JOG_R5 (0x3A6E & RC5_MASK) /*!< Taste Jog-Dial Rechts 5 */
+ #define RC5_CODE_JOG_R6 (0x396E & RC5_MASK) /*!< Taste Jog-Dial Rechts 6 */
+ #define RC5_CODE_JOG_R7 (0x3A6F & RC5_MASK) /*!< Taste Jog-Dial Rechts 7 */
+ #endif /* JOG_DIAL */
+
+#endif /* !RC_HAVE_CODES */
+
+#endif /* RC5CODE_H_ */
diff --git a/source/ct-Bot/include/rc5.h b/source/ct-Bot/include/rc5.h
new file mode 100644
index 0000000..398f599
--- /dev/null
+++ b/source/ct-Bot/include/rc5.h
@@ -0,0 +1,33 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file rc5.h
+ * @brief RC5-Fernbedienung
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+
+#ifndef rc5_H_
+#define rc5_H_
+
+/*!
+ * Liest ein RC5-Codeword und wertet es aus
+ */
+void rc5_control(void);
+#endif
diff --git a/source/ct-Bot/include/sensor-low.h b/source/ct-Bot/include/sensor-low.h
new file mode 100644
index 0000000..cfe1e02
--- /dev/null
+++ b/source/ct-Bot/include/sensor-low.h
@@ -0,0 +1,44 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file sensor-low.h
+ * @brief Low-Level Routinen fuer die Sensor-Steuerung des c't-Bots
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 01.12.05
+*/
+#ifndef sens_low_H_
+#define sens_low_H_
+
+/*!
+ * Initialisiere alle Sensoren
+ */
+extern void bot_sens_init(void);
+
+/*!
+ * Alle Sensoren aktualisieren
+ */
+extern void bot_sens_isr(void);
+
+/*!
+ * Kuemmert sich um die Radencoder
+ * Das muss schneller gehen als die anderen Sensoren,
+ * daher Update per ISR
+ */
+extern void bot_encoder_isr(void);
+#endif
diff --git a/source/ct-Bot/include/sensor.h b/source/ct-Bot/include/sensor.h
new file mode 100644
index 0000000..80e65a2
--- /dev/null
+++ b/source/ct-Bot/include/sensor.h
@@ -0,0 +1,111 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file sensor.h
+ * @brief Architekturunabhaengiger Teil der Sensorsteuerung
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 15.01.05
+*/
+
+#ifndef SENSOR_H_
+#define SENSOR_H_
+
+#include "global.h"
+#include "ct-Bot.h"
+
+/* Analoge Sensoren: Der Wertebereich aller analogen Sensoren umfasst 10 Bit. Also 0 bis 1023 */
+
+extern int16 sensDistL; /*!< Distanz linker IR-Sensor [mm] ca. 100 bis 800 */
+extern int16 sensDistR; /*!< Distanz rechter IR-Sensor [mm] ca. 100 bis 800 */
+
+extern int16 sensLDRL; /*!< Lichtsensor links [0-1023]; 1023 = dunkel*/
+extern int16 sensLDRR; /*!< Lichtsensor rechts [0-1023]; 1023 = dunkel*/
+
+extern int16 sensBorderL; /*!< Abgrundsensor links [0-1023]; 1023 = dunkel*/
+extern int16 sensBorderR; /*!< Abgrundsensor rechts [0-1023]; 1023 = dunkel*/
+
+extern int16 sensLineL; /*!< Lininensensor links [0-1023]; 1023 = dunkel*/
+extern int16 sensLineR; /*!< Lininensensor rechts [0-1023]; 1023 = dunkel*/
+
+/* digitale Sensoren */
+extern volatile int16 sensEncL; /*!< Encoder linker Motor [-32768 bis 32767] */
+extern volatile int16 sensEncR; /*!< Encoder rechter Motor [-32768 bis 32767] */
+
+extern uint8 sensTrans; /*!< Sensor Ueberwachung Transportfach [0/1]*/
+
+extern uint8 sensDoor; /*!< Sensor Ueberwachung Klappe [0/1] */
+
+extern uint8 sensError; /*!< Ueberwachung Motor oder Batteriefehler [0/1] 1= alles ok */
+
+extern uint16 RC5_Code; /*!< Letzter empfangener RC5-Code */
+
+#ifdef MAUS_AVAILABLE
+ extern int8 sensMouseDX; /*!< Maussensor Delta X, positive Werte zeigen querab der Fahrtrichtung nach rechts */
+ extern int8 sensMouseDY; /*!< Maussensor Delta Y, positive Werte zeigen in Fahrtrichtung */
+
+ extern int16 sensMouseX; /*!< Mausposition X, positive Werte zeigen querab der Fahrtrichtung nach rechts */
+ extern int16 sensMouseY; /*!< Mausposition Y, positive Werte zeigen in Fahrtrichtung */
+#endif
+
+extern float heading_enc; /*!< Blickrichtung aus Encodern */
+extern float x_enc; /*!< X-Koordinate aus Encodern [mm] */
+extern float y_enc; /*!< Y-Koordinate aus Encodern [mm] */
+extern float v_enc_left; /*!< Abrollgeschwindigkeit des linken Rades in [mm/s] [-128 bis 127] relaisitisch [-50 bis 50] */
+extern float v_enc_right; /*!< Abrollgeschwindigkeit des linken Rades in [mm/s] [-128 bis 127] relaisitisch [-50 bis 50] */
+extern float v_enc_center; /*!< Schnittgeschwindigkeit ueber beide Raeder */
+
+#ifdef PC
+ extern uint16 simultime; /*! Simulierte Zeit */
+#endif
+
+#ifdef MEASURE_MOUSE_AVAILABLE
+ extern float heading_mou; /*!< Aktuelle Blickrichtung relativ zur Startposition aus Mausmessungen */
+ extern float x_mou; /*!< Aktuelle X-Koordinate in mm relativ zur Startposition aus Mausmessungen */
+ extern float y_mou; /*!< Aktuelle Y-Koordinate in mm relativ zur Startposition aus Mausmessungen */
+ extern float v_mou_center; /*!< Geschwindigkeit in mm/s ausschliesslich aus den Maussensorwerten berechnet */
+ extern float v_mou_left; /*!< ...aufgeteilt auf linkes Rad */
+ extern float v_mou_right; /*!< ...aufgeteilt auf rechtes Rad */
+#endif
+
+extern float heading; /*!< Aktuelle Blickrichtung aus Encoder-, Maus- oder gekoppelten Werten */
+extern float x_pos; /*!< Aktuelle X-Position aus Encoder-, Maus- oder gekoppelten Werten */
+extern float y_pos; /*!< Aktuelle Y-Position aus Encoder-, Maus- oder gekoppelten Werten */
+extern float v_left; /*!< Geschwindigkeit linkes Rad aus Encoder-, Maus- oder gekoppelten Werten */
+extern float v_right; /*!< Geschwindigkeit rechtes Rad aus Encoder-, Maus- oder gekoppelten Werten */
+extern float v_center; /*!< Geschwindigkeit im Zentrum des Bots aus Encoder-, Maus- oder gekoppelten Werten */
+
+
+extern int8 sensors_initialized; /*!< Wird 1 sobald die Sensorwerte zur Verfügung stehen */
+
+#ifdef SRF10_AVAILABLE
+ extern uint16 sensSRF10; /*!< Messergebniss Ultraschallsensor */
+#endif
+
+/*! Sensor_update
+* Kümmert sich um die Weiterverarbeitung der rohen Sensordaten
+*/
+void sensor_update(void);
+
+/*! Linearisiert die Sensorwerte
+ * @param left Linker Rohwert [0-1023]
+ * @param right Rechter Rohwert [0-1023]
+ */
+void sensor_abstand(uint16 left, uint16 right);
+
+#endif /*SENSOR_H_*/
diff --git a/source/ct-Bot/include/sensor_correction.h b/source/ct-Bot/include/sensor_correction.h
new file mode 100644
index 0000000..bfc0411
--- /dev/null
+++ b/source/ct-Bot/include/sensor_correction.h
@@ -0,0 +1,39 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file sensor_correction.h
+ * @brief Konstanten, um die Sensoren zu linearisieren
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 17.02.06
+*/
+#ifndef SENSOR_CORRECTION_H_
+#define SENSOR_CORRECTION_H_
+
+#define SENSDISTSLOPELEFT 47478 /*!< Stuetzwert a fuer Linearisierung des linken Distanzsensors */
+#define SENSDISTOFFSETLEFT 50 /*!< Stuetzwert b fuer Linearisierung des linken Distanzsensors */
+#define SENSDISTSLOPERIGHT 54333 /*!< Stuetzwert a fuer Linearisierung des rechten Distanzsensors */
+#define SENSDISTOFFSETRIGHT 9 /*!< Stuetzwert b fuer Linearisierung des rechten Distanzsensors */
+
+
+/* Parameter fuer die IR-Sensoren*/
+#define SENS_IR_MAX_DIST 750 /*!< Obergrenze des Erfassungsbereichs */
+#define SENS_IR_INFINITE 999 /*!< Kennzeichnung fuer "kein Objekt im Erfassungsbereich" */
+
+
+#endif /*SENSOR_CORRECTION_H_*/
diff --git a/source/ct-Bot/include/shift.h b/source/ct-Bot/include/shift.h
new file mode 100644
index 0000000..d4a4c24
--- /dev/null
+++ b/source/ct-Bot/include/shift.h
@@ -0,0 +1,63 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file shift.h
+ * @brief Routinen zur Ansteuerung der Shift-Register
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 20.12.05
+*/
+
+#ifndef SHIFT_H_
+#define SHIFT_H_
+
+
+#define SHIFT_LATCH (1<<1) /*!< Clock to store Data into shiftregister */
+
+#define SHIFT_REGISTER_DISPLAY 0x04 /*!< Port-Pin for shiftregister latch (display) */
+#define SHIFT_REGISTER_LED 0x10 /*!< Port-Pin for shiftregister latch (leds) */
+#define SHIFT_REGISTER_ENA 0x08 /*!< Port-Pin for shiftregister latch (enable) */
+
+/*!
+ * Initialisert die Shift-Register
+ */
+void shift_init(void);
+
+/*!
+ * Schiebt Daten durch eines der drei 74HC595-Schieberegister
+ * Achtung: den Port sollte man danach noch per shift_clear() zuruecksetzen!
+ * @param data Das Datenbyte
+ * @param latch_data der Pin, an dem der Daten-latch-Pin des Registers (PIN 11) haengt
+ * @param latch_store der Pin, an dem der latch-Pin zum Transfer des Registers (PIN 12) haengt
+ */
+void shift_data_out(uint8 data, uint8 latch_data, uint8 latch_store);
+
+/*!
+ * Schiebt Daten durch eines der drei 74HC595-Schieberegister,
+ * vereinfachte Version, braucht kein shift_clear().
+ * Funktioniert NICHT fuer das Shift-Register, an dem das Display haengt!!!
+ * @param data Das Datenbyte
+ * @param latch_data der Pin, an dem der Daten-latch-Pin des Registers (PIN 11) haengt
+ */
+void shift_data(uint8 data, uint8 latch_data);
+
+/*!
+ * Setzt die Shift-Register wieder zurueck
+ */
+void shift_clear(void);
+#endif
diff --git a/source/ct-Bot/include/srf10.h b/source/ct-Bot/include/srf10.h
new file mode 100644
index 0000000..e18f5ec
--- /dev/null
+++ b/source/ct-Bot/include/srf10.h
@@ -0,0 +1,105 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file srf10.h
+ * @brief Ansteuerung des Ultraschall Entfernungssensors SRF10
+ * @author Chris efstathiou (hendrix@otenet.gr) & Carsten Giesen (info@cnau.de)
+ * @date 08.04.06
+*/
+
+
+#include "global.h"
+
+#ifndef srf10_H
+#define srf10_H 1
+
+/*!
+ * Es sind alle moeglichen Adressen eingetragen. In de Regel reicht aber die erste
+ * Der Code geht nur von SRF10_UNIT_0 aus, daher sind die anderen auskommentiert
+*/
+
+#define SRF10_UNIT_0 0xE0 /* the SRF10 MODULE I2C address */
+//#define SRF10_UNIT_1 0xE2 /* the SRF10 MODULE I2C address */
+//#define SRF10_UNIT_2 0xE4 /* the SRF10 MODULE I2C address */
+//#define SRF10_UNIT_3 0xE6 /* the SRF10 MODULE I2C address */
+//#define SRF10_UNIT_4 0xE8 /* the SRF10 MODULE I2C address */
+//#define SRF10_UNIT_5 0xEA /* the SRF10 MODULE I2C address */
+//#define SRF10_UNIT_6 0xEC /* the SRF10 MODULE I2C address */
+//#define SRF10_UNIT_7 0xEE /* the SRF10 MODULE I2C address */
+//#define SRF10_UNIT_8 0xF0 /* the SRF10 MODULE I2C address */
+//#define SRF10_UNIT_9 0xF2 /* the SRF10 MODULE I2C address */
+//#define SRF10_UNIT_10 0xF4 /* the SRF10 MODULE I2C address */
+//#define SRF10_UNIT_11 0xF6 /* the SRF10 MODULE I2C address */
+//#define SRF10_UNIT_12 0xF8 /* the SRF10 MODULE I2C address */
+//#define SRF10_UNIT_13 0xFA /* the SRF10 MODULE I2C address */
+//#define SRF10_UNIT_14 0xFC /* the SRF10 MODULE I2C address */
+//#define SRF10_UNIT_15 0xFE /* the SRF10 MODULE I2C address */
+
+#define SRF10_MIN_GAIN 0 /*!< setze Verstaerung auf 40 */
+#define SRF10_MAX_GAIN 16 /*!< setze Verstaerung auf 700 */
+#define SRF10_MIN_RANGE 0 /*!< Minimale Reichweite 43mm */
+#define SRF10_MAX_RANGE 5977 /*!< Maximale Reichweite 5977mm */
+
+#define SRF10_INCHES 0X50 /*!< Messung in INCHES */
+#define SRF10_CENTIMETERS 0X51 /*!< Messung in CM */
+#define SRF10_MICROSECONDS 0X52 /*!< Messung in Millisekunden */
+
+#define SRF10_COMMAND 0 /*!< W=Befehls-Register R=Firmware*/
+#define SRF10_LIGHT 1 /*!< W=Verstaerkungsfaktor R=Nicht benutzt */
+#define SRF10_HIB 2 /*!< W=Reichweite R=Messung High-Byte */
+#define SRF10_LOB 3 /*!< W=Nicht benutzt R=Messung Low-Byte */
+
+/*!
+ * SRF10 initialsieren
+ */
+extern void srf10_init(void);
+
+/*!
+ * Verstaerkungsfaktor setzen
+ * @param gain Verstaerkungsfaktor
+ */
+extern void srf10_set_gain(uint8 gain);
+
+/*!
+ * Reichweite setzen, hat auch Einfluss auf die Messdauer
+ * @param millimeters Reichweite in mm
+ */
+extern void srf10_set_range(uint16 millimeters);
+
+/*!
+ * Messung ausloesen
+ * @param metric_unit 0x50 in Zoll, 0x51 in cm, 0x52 ms
+ * @return Resultat der Aktion
+ */
+extern uint8 srf10_ping(uint8 metric_unit);
+
+/*!
+ * Register auslesen
+ * @param srf10_register welches Register soll ausgelsen werden
+ * @return Inhalt des Registers
+ */
+extern uint8 srf10_read_register(uint8 SRF10_register);
+
+/*!
+ * Messung starten Ergebniss aufbereiten und zurueckgeben
+ * @return Messergebniss
+ */
+extern uint16 srf10_get_measure(void);
+
+#endif /* #ifndef SRF10_H */
diff --git a/source/ct-Bot/include/tcp-server.h b/source/ct-Bot/include/tcp-server.h
new file mode 100644
index 0000000..daae5d5
--- /dev/null
+++ b/source/ct-Bot/include/tcp-server.h
@@ -0,0 +1,49 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file tcp-server.h
+ * @brief Demo-TCP-Server
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+
+#ifndef TCP_SERVER_H_
+#define TCP_SERVER_H_
+
+
+/*!
+ * Init TCP-Server
+ */
+void tcp_server_init(void);
+
+/*!
+ * Hauptschleife des TCP-Servers
+ */
+int tcp_server_run (int runs);
+
+/*!
+ * Init TCP-test-Client
+ */
+void tcp_test_client_init(void);
+
+/*!
+ * Hauptschleife des TCP-Test-Clienzs
+ */
+int tcp_test_client_run (int runs);
+#endif
diff --git a/source/ct-Bot/include/tcp.h b/source/ct-Bot/include/tcp.h
new file mode 100644
index 0000000..c232e26
--- /dev/null
+++ b/source/ct-Bot/include/tcp.h
@@ -0,0 +1,92 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file tcp.h
+ * @brief TCP/IP-Kommunikation
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+
+#ifndef TCP_H_
+#define TCP_H_
+
+#if defined WIN32
+ #define LITTLE_ENDIAN 1234
+ #define BIG_ENDIAN 4321
+ #define BYTE_ORDER LITTLE_ENDIAN
+#elif defined __linux__
+ #include <endian.h>
+#else
+ #include <machine/endian.h>
+ #endif
+
+#include "bot-2-sim.h"
+#include "command.h"
+
+
+#define IP "localhost" /*!< IP, mit der verbunden werden soll (normalerweise localhost) */
+//#define IP "10.10.22.242"
+#define PORT 10001 /*!< Port, mit dem verbunden werden soll */
+
+extern int tcp_sock; /*!< Unser TCP-Socket */
+extern char *tcp_hostname; /*!< Hostname, auf dem ct-Sim laeuft */
+
+/*!
+ * Sende Kommando per TCP/IP im Little Endian
+ * @param cmd Zeiger auf das Kommando
+ * @return Anzahl der gesendete Bytes
+ */
+int tcp_send_cmd(command_t *cmd);
+
+
+/*!
+ * Uebertrage Daten per TCP/IP
+ * @param data Zeiger auf die Daten
+ * @param length Anzahl der Bytes
+ * @return Anzahl der uebertragenen Bytes
+*/
+int tcp_write(void* data, int length);
+
+/*!
+ * Lese Daten von TCP/IP-Verbindung.
+ * Achtung: blockierend!
+ * @param data Zeiger auf die Daten
+ * @param length Anzahl der gewuenschten Bytes
+ * @return Anzahl der uebertragenen Bytes
+*/
+int tcp_read(void* data, int length);
+
+/*!
+ * Oeffnet eine TCP-Verbindung zum Server
+ * @param hostname Symbolischer Name des Host, auf dem ct-Sim laeuft
+ * @return Der Socket
+*/
+int tcp_openConnection(const char *hostname);
+
+/*!
+ * Initialisiere TCP/IP Verbindung
+ */
+void tcp_init(void);
+
+/*!
+ * Schreibt den Sendepuffer auf einen Schlag raus
+ * @return -1 bei Fehlern, sonst zahl der uebertragenen Bytes
+ */
+int flushSendBuffer(void);
+#endif
diff --git a/source/ct-Bot/include/timer.h b/source/ct-Bot/include/timer.h
new file mode 100644
index 0000000..446f51e
--- /dev/null
+++ b/source/ct-Bot/include/timer.h
@@ -0,0 +1,102 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file timer.h
+ * @brief Timer und Zaehler
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+
+#ifndef TIMER_H_
+#define TIMER_H_
+
+#include "ct-Bot.h"
+
+/*!
+ * Makros zur Umrechnung von Ticks in ms und zurueck
+ * (ms / ticks evtl. nach uint32 casten, fuer grosse Werte)
+ */
+#define TICKS_TO_MS(ticks) ((ticks)*(TIMER_STEPS/8)/(1000/8))
+#define MS_TO_TICKS(ms) ((ms)*(1000/8)/(TIMER_STEPS/8))
+
+#ifdef TIME_AVAILABLE
+ /*!
+ * Diese Funktion liefert den Millisekundenanteil der Systemzeit zurueck.
+ * @return uint16
+ */
+ uint16 timer_get_ms(void);
+
+ /*!
+ * Diese Funktion liefert den Sekundenanteil der Systemzeit zurueck.
+ * @return uint16
+ */
+ uint16 timer_get_s(void);
+
+ /*!
+ * Liefert die Millisekunden zurueck, die seit old_s, old_ms verstrichen sind
+ * @param old_s alter Sekundenstand
+ * @param old_ms alter Millisekundenstand
+ */
+ uint16 timer_get_ms_since(uint16 old_s, uint16 old_ms);
+#endif // TIME_AVAILABLE
+
+#ifdef PC
+ /*!
+ * Funktion, die die TickCounts um die vergangene Simulzeit erhoeht
+ */
+ void system_time_isr(void);
+
+ /*!< liefert Ticks seit Systemstart [176 us] */
+ inline uint16 timer_get_tickCount16(void);
+ inline uint32 timer_get_tickCount32(void);
+
+ #define TIMER_GET_TICKCOUNT_8 (uint8)timer_get_tickCount16()
+ #define TIMER_GET_TICKCOUNT_16 timer_get_tickCount16()
+ #define TIMER_GET_TICKCOUNT_32 timer_get_tickCount32()
+#else
+ typedef union{
+ uint32 u32;
+ uint16 u16;
+ uint8 u8;
+ } tickCount_t;
+ extern volatile tickCount_t tickCount;
+
+ #define TIMER_GET_TICKCOUNT_8 tickCount.u8
+ #define TIMER_GET_TICKCOUNT_16 tickCount.u16
+ #define TIMER_GET_TICKCOUNT_32 tickCount.u32
+#endif
+
+// Die Werte fuer TIMER_X_CLOCK sind Angaben in Hz
+
+/*!
+ * Frequenz von Timer 2 in Hz
+ */
+#define TIMER_2_CLOCK 5619 // Derzeit genutzt fuer RC5-Dekodierung
+
+/*!
+ * Mikrosekunden, die zwischen zwei Timer-Aufrufen liegen
+ */
+// #define TIMER_STEPS (1 000 000/TIMER_2_CLOCK)
+ #define TIMER_STEPS 176
+
+/*!
+ * Initialisiert Timer 2 und startet ihn
+ */
+void timer_2_init(void);
+#endif
diff --git a/source/ct-Bot/include/uart.h b/source/ct-Bot/include/uart.h
new file mode 100644
index 0000000..6b91a37
--- /dev/null
+++ b/source/ct-Bot/include/uart.h
@@ -0,0 +1,75 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file uart.h
+ * @brief Routinen zur seriellen Kommunikation
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+
+#ifndef UART_H_
+#define UART_H_
+
+#include "command.h"
+
+//extern char uart_timeout; /*!< 0, wenn uart_read/uart_send erfolgreich; 1, wenn timeout erreicht */
+
+/*!
+ * Initialisiere UART
+ */
+void uart_init(void);
+
+/*!
+ * Prüft, ob daten verfügbar
+ * @return Anzahl der verfuegbaren Bytes
+ */
+uint8 uart_data_available(void);
+
+
+/*!
+ * Überträgt ein Zeichen per UART
+ * Achtung ist noch blockierend!!!!
+ * TODO: umstellen auf nicht blockierend und mehr als ein Zeichen
+ * @param data Das Zeichen
+ */
+void uart_send_byte(uint8 data);
+
+/*!
+ * Sende Kommando per UART im Little Endian
+ * @param cmd Zeiger auf das Kommando
+ * @return Anzahl der gesendete Bytes
+ */
+//int uart_send_cmd(command_t *cmd);
+#define uart_send_cmd(cmd) uart_write((uint8*)cmd,sizeof(command_t));
+
+/*!
+ * Sende Daten per UART im Little Endian
+ * @param data Datenpuffer
+ * @param length Groesse des Datenpuffers in bytes
+ * @return Anzahl der gesendete Bytes
+ */
+int uart_write(uint8 * data, int length);
+
+/* Liest Zeichen von der UART
+ * @param data Der Zeiger an die die gelesenen Zeichen kommen
+ * @param length Anzahl der zu lesenden Bytes
+ * @return Anzahl der tatsaechlich gelesenen Zeichen
+ */
+int uart_read(void* data, int length);
+#endif
diff --git a/source/ct-Bot/log.c b/source/ct-Bot/log.c
new file mode 100644
index 0000000..202a7d2
--- /dev/null
+++ b/source/ct-Bot/log.c
@@ -0,0 +1,290 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file log.c
+ * @brief Routinen zum Loggen von Informationen. Es sollten ausschliesslich nur
+ * die Log-Makros: LOG_DEBUG(), LOG_INFO(), LOG_WARN(), LOG_ERROR() und LOG_FATAL()
+ * verwendet werden.
+ * Eine Ausgabe kann wie folgt erzeugt werden:
+ * LOG_DEBUG(("Hallo Welt!"));
+ * LOG_INFO(("Wert x=%d", x));
+ * Wichtig ist die doppelte Klammerung. Bei den Ausgaben kann auf ein Line Feed
+ * '\n' am Ende des Strings verzichtet werden, da dies automatisch angeh�ngt
+ * hinzugefuegt wird.
+ *
+ * @author Andreas Merkle (mail@blue-andi.de)
+ * @date 27.02.06
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "log.h"
+#include "display.h"
+#include "command.h"
+#include "uart.h"
+
+#ifdef LOG_AVAILABLE
+
+#ifdef PC
+#include <pthread.h>
+#endif /* PC */
+
+#ifdef LOG_DISPLAY_AVAILABLE
+ /*! Nummer des Screens auf den Loggings ausgegeben werden sollen. */
+ #define LOG_TO_SCREEN 4
+
+ /*! Groesse des Puffers fuer die Logausgaben bei Verwendung des LCD-Displays. */
+ #define LOG_BUFFER_SIZE (DISPLAY_LENGTH + 1)
+#else
+ /*! Groesse des Puffers fuer die Logausgaben ueber UART und ueber TCP/IP. */
+ #define LOG_BUFFER_SIZE 200
+#endif /* LOG_DISPLAY_AVAILABLE */
+
+
+#ifdef PC
+ /*! Schuetzt den Ausgabepuffer */
+ #define LOCK() pthread_mutex_lock(&log_buffer_mutex);
+ /*! Hebt den Schutz fuer den Ausgabepuffer wieder auf */
+ #define UNLOCK() pthread_mutex_unlock(&log_buffer_mutex);
+#else
+ /*! Schuetzt den Ausgabepuffer */
+ #define LOCK() /* TODO */
+ /*! Hebt den Schutz fuer den Ausgabepuffer wieder auf */
+ #define UNLOCK() /* TODO */
+#endif /* PC */
+
+/*!
+ * Liefert den Log-Typ als String.
+ * @param log_type Log-Typ
+ * @return char*
+ */
+static char* log_get_type_str(LOG_TYPE log_type);
+
+/*! Puffer fuer das Zusammenstellen einer Logausgabe */
+static char log_buffer[LOG_BUFFER_SIZE];
+
+#ifdef PC
+ /*! Schuetzt den Ausgabepuffer */
+ static pthread_mutex_t log_buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif /* PC */
+
+#ifdef LOG_DISPLAY_AVAILABLE
+ /*! Zeile in der die naechste Logausgabe erfolgt. */
+ static uint16 log_line = 0;
+#endif /* LOG_DISPLAY_AVAILABLE */
+
+/*!
+ * Schreibt Angaben ueber Datei, Zeilennummer und den Log-Typ in den Puffer.
+ * Achtung, Mutex wird gelockt und muss explizit durch log_end() wieder
+ * freigegeben werden!
+ * @param filename Dateiname
+ * @param line Zeilennummer
+ * @param log_type Log-Typ
+ */
+extern void log_begin(char *filename, unsigned int line, LOG_TYPE log_type) {
+
+/* Ausgaben ueber das LCD-Display werden ohne Dateiname und Zeilennumer
+ * gemacht. Der Log-Typ versteckt sich im ersten Buchstaben. Durch eine
+ * die Markierung mit '>' erkennt man das letzte Logging.
+ * Nur bei Ausgaben ueber UART und an ct-Sim werden Dateiname, Zeilennummer
+ * und der Log-Typ vollstaendig ausgegeben.
+ */
+ #ifdef LOG_DISPLAY_AVAILABLE
+
+ LOCK();
+
+ /* Nur auf einem bestimmten Screen werden Loggings ausgegeben. */
+ if (display_screen != LOG_TO_SCREEN) {
+ log_buffer[0] = '\0';
+ return;
+ }
+
+ /* Zum ersten Mal aufgerufen? */
+ if (log_line == 0) {
+ log_line++;
+ } else {
+ /* Alte Markierung loeschen */
+ if (log_line - 1 == 0) {
+ display_cursor(4, 1);
+ }
+ else {
+ display_cursor(log_line - 1, 1);
+ }
+ display_printf(" ");
+ }
+ display_cursor(log_line, 1);
+ log_line++;
+ if (log_line >= DISPLAY_SCREENS) {
+ log_line = 1;
+ }
+
+ snprintf(log_buffer, LOG_BUFFER_SIZE, ">%s:", log_get_type_str(log_type));
+
+ #else
+
+ char *ptr = NULL;
+
+ /* Nur den Dateinamen loggen, ohne Verzeichnisangabe */
+ ptr = strrchr(filename, '/');
+
+ if (ptr == NULL)
+ ptr = filename;
+ else
+ ptr++;
+
+ LOCK();
+
+ snprintf(log_buffer, LOG_BUFFER_SIZE, "%s(%d)\t%s\t",
+ ptr, line, log_get_type_str(log_type));
+
+ #endif
+
+ return;
+}
+
+/*!
+ * Schreibt die eigentliche Ausgabeinformation in den Puffer.
+ * @param format Format
+ */
+extern void log_printf(char *format, ...) {
+
+ va_list args;
+ unsigned int len = strlen(log_buffer);
+
+ #ifdef LOG_DISPLAY_AVAILABLE
+ /* Nur auf einem bestimmten Screen werden Loggings ausgegeben. */
+ if (display_screen != LOG_TO_SCREEN)
+ return;
+ #endif
+
+ va_start(args, format);
+ vsnprintf(&log_buffer[len], LOG_BUFFER_SIZE - len, format, args);
+ va_end(args);
+
+ return;
+}
+
+/*!
+ * Gibt den Puffer entsprechend aus.
+ */
+extern void log_end(void) {
+
+ #ifdef LOG_UART_AVAILABLE
+ /* String ueber UART senden, ohne '\0'-Terminierung */
+ uart_write((uint8*)log_buffer, strlen(log_buffer));
+ /* Line feed senden */
+ uart_write((uint8*)LINE_FEED,strlen(LINE_FEED));
+ #endif /* LOG_UART_AVAILABLE */
+
+ #ifdef LOG_CTSIM_AVAILABLE
+ /* Kommando an ct-Sim senden, ohne Line feed am Ende. */
+ command_write_data(CMD_LOG, SUB_CMD_NORM, NULL, NULL, log_buffer);
+ #endif /* LOG_CTSIM_AVAILABLE */
+
+ #ifdef LOG_DISPLAY_AVAILABLE
+ /* Nur auf einem bestimmten Screen werden Loggings ausgegeben. */
+ if (display_screen == LOG_TO_SCREEN) {
+ /* String aufs LCD-Display schreiben */
+ display_printf("%s", log_buffer);
+ }
+ #endif /* LOG_DISPLAY_AVAILABLE */
+
+ /* Wenn das Logging aktiviert und keine Ausgabeschnittstelle
+ * definiert ist, dann wird auf dem PC auf die Konsole geschrieben.
+ */
+
+ #ifdef LOG_STDOUT_AVAILABLE
+ printf("%s\n", log_buffer);
+ #endif /* LOG_STDOUT_AVAILABLE */
+
+ UNLOCK();
+
+ return;
+}
+
+#ifdef LOG_DISPLAY_AVAILABLE
+
+/*!
+ * Liefert den Log-Typ als String.
+ * @param log_type Log-Typ
+ * @return char*
+ */
+static char* log_get_type_str(LOG_TYPE log_type) {
+
+ switch(log_type) {
+ case LOG_TYPE_DEBUG:
+ return "D";
+
+ case LOG_TYPE_INFO:
+ return "I";
+
+ case LOG_TYPE_WARN:
+ return "W";
+
+ case LOG_TYPE_ERROR:
+ return "E";
+
+ case LOG_TYPE_FATAL:
+ return "F";
+
+ default:
+ break;
+ }
+
+ return "";
+}
+
+#else
+
+/*!
+ * Liefert den Log-Typ als String.
+ * @param log_type Log-Typ
+ * @return char*
+ */
+static char* log_get_type_str(LOG_TYPE log_type) {
+
+ switch(log_type) {
+ case LOG_TYPE_DEBUG:
+ return "- DEBUG -";
+
+ case LOG_TYPE_INFO:
+ return "- INFO -";
+
+ case LOG_TYPE_WARN:
+ return "- WARNING -";
+
+ case LOG_TYPE_ERROR:
+ return "- ERROR -";
+
+ case LOG_TYPE_FATAL:
+ return "- FATAL -";
+
+ default:
+ break;
+ }
+
+ return "";
+}
+
+#endif /* LOG_DISPLAY_AVAILABLE */
+
+#endif /* LOG_AVAILABLE */
diff --git a/source/ct-Bot/map.c b/source/ct-Bot/map.c
new file mode 100644
index 0000000..753941d
--- /dev/null
+++ b/source/ct-Bot/map.c
@@ -0,0 +1,659 @@
+/*
+ * c't-Bot - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file map.c
+ * @brief Karte
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 19.09.06
+*/
+#include <stdio.h>
+#include "ct-Bot.h"
+#include "bot-local.h"
+#include "sensor_correction.h"
+#include "map.h"
+#include "mmc.h"
+#include "mini-fat.h"
+#include "mmc-vm.h"
+
+#ifdef MAP_AVAILABLE
+#include <math.h>
+#include <stdlib.h>
+
+/*
+ * Eine Karte ist wie folgt organisiert:
+ * Es gibt Sektionen zu je MAP_SECTION_POINTS * MAP_SECTION_POINTS.
+ * Diese Sektionen enthalten direkt die Pixel-Daten
+ * Auf dem PC haelt (noch) ein uebergeordnetes Array haelt die einzelnen Sections
+ * So laesst sich leicht eine Karte aufbauen,
+ * ohne dass viel Platz fuer unbenutzte Felder draufgeht
+ *
+ * Auf dem MCU passt eine Sektion in einen Flashblock, bzw immer 2 Sektionen in einen Block
+ * Es stehen immer 2 Sections also 1 Flash-Block im SRAM und werden bei Bedarf gewechselt
+ *
+ * Felder sind vom Typ int8 und haben einen Wertebereich von -128 bis 127
+ * 0 bedeutet: wir wissen nichts über das Feld
+ * negative Werte bedeuten: Hinderniss
+ * postivie Werte bedeuten: freier Weg
+ * je größer der Betrag ist, desto sicherer die Aussage über das Feld
+ * Der Wert -128 ist Löchern vorbehalten und wird dann auch nicht durch die Abstandssensoren verändert
+ * (Achtung, die Locherkennung ist derzeit noch nicht fertig impelementiert)
+ *
+ * Felder werden wie folgt aktualisiert:
+ * Wird ein Punkt als frei betrachtet, erhoehen wir den Wert des Feldes um MAP_STEP_FREE
+ * Wird ein Punkt als belegt erkannt, ziehen wir um ihn einen Streukreis mit dem Radius MAP_RADIUS.
+ * Das Zentrum des Kreises wird um MAP_STEP_OCCUPIED dekrementiert, nach aussen hin immer weniger
+ * Wird ein Feld als Loch erkannt, setzen wir den Wert fest auf -128 (Achtung, derzeit noch nicht fertig impelementiert)
+ */
+
+#define MAP_SECTIONS ((( MAP_SIZE*MAP_RESOLUTION)/MAP_SECTION_POINTS))
+
+#define MAP_STEP_FREE 2 /*!< Um diesen Wert wird ein Feld inkrementiert, wenn es als frei erkannt wird */
+#define MAP_STEP_OCCUPIED 10 /*!< Um diesen Wert wird ein Feld dekrementiert, wenn es als belegt erkannt wird */
+
+#define MAP_RADIUS 10 /*!< Umkreis einen Messpunkt, der als Besetzt aktualisiert wird (Streukreis) [mm]*/
+#define MAP_RADIUS_FIELDS (MAP_RESOLUTION*MAP_RADIUS/1000) /*!< Umkreis einen Messpunkt, der als Besetzt aktualisiert wird (Streukreis) [Felder]*/
+
+#define MAP_PRINT_SCALE /*!< Soll das PGM eine Skala erhalten */
+#define MAP_SCALE (MAP_RESOLUTION/2) /*!< Alle wieviel Punkte kommt wein Skalen-Strich */
+
+#ifdef SHRINK_MAP_ONLINE
+ uint16 map_min_x=MAP_SIZE*MAP_RESOLUTION/2; /*!< belegter Bereich der Karte [Kartenindex]: kleinste X-Koordinate */
+ uint16 map_max_x=MAP_SIZE*MAP_RESOLUTION/2; /*!< belegter Bereich der Karte [Kartenindex]: groesste X-Koordinate */
+ uint16 map_min_y=MAP_SIZE*MAP_RESOLUTION/2; /*!< belegter Bereich der Karte [Kartenindex]: kleinste Y-Koordinate */
+ uint16 map_max_y=MAP_SIZE*MAP_RESOLUTION/2; /*!< belegter Bereich der Karte [Kartenindex]: groesste Y-Koordinate */
+#endif
+
+typedef struct {
+ int8 section[MAP_SECTION_POINTS][MAP_SECTION_POINTS]; /*!< Einzelne Punkte */
+} map_section_t; /*!< Datentyp fuer die elementarfelder einer Gruppe */
+
+
+#ifdef MMC_VM_AVAILABLE
+ map_section_t * map[2][1]; /*! Array mit den Zeigern auf die Elemente */
+ uint32 map_start_block; /*! Block, bei dem die Karte auf der MMC-Karte beginnt. Derzeit nur bis 32MByte adressierbar*/
+ uint32 map_current_block; /*! Block, der aktuell im Puffer steht. Derzeit nur bis 32MByte adressierbar*/
+ uint8* map_buffer; /*! dynamischer Puffer */
+#else
+ #ifdef MCU
+ #ifdef MMC_AVAILABLE
+ // Wenn wir die MMC-Karte haben, passen immer 2 Sektionen in den SRAM
+ map_section_t * map[2][1]; /*! Array mit den Zeigern auf die Elemente */
+ uint32 map_start_block; /*! Block, bei dem die Karte auf der MMC-Karte beginnt. Derzeit nur bis 32MByte adressierbar*/
+ uint32 map_current_block; /*! Block, der aktuell im Puffer steht. Derzeit nur bis 32MByte adressierbar*/
+ uint8 map_buffer[sizeof(map_section_t)*2]; /*! statischer Puffer */
+ uint8 map_current_block_updated; /*! markiert, ob der aktuelle Block gegenueber der MMC-Karte veraendert wurde */
+ #else
+ // Ohne MMC-Karte nehmen wir nur 1 Sektionen in den SRAM und das wars dann
+ map_section_t * map[1][1]; /*! Array mit den Zeigern auf die Elemente */
+ #endif
+ #else
+ map_section_t * map[MAP_SECTIONS][MAP_SECTIONS]; /*! Array mit den Zeigern auf die Elemente */
+ #endif
+#endif // MMC_VM_AVAILABLE
+
+/*!
+ * initialisiere die Karte
+ * @return 0 wenn alles ok ist
+ */
+int8 map_init(void){
+ #ifndef MMC_VM_AVAILABLE
+ #ifdef MMC_AVAILABLE
+ map_start_block=0xFFFFFFFF;
+ map_current_block_updated = 0xFF; // Die MMC-Karte ist erstmal nicht verfuegbar
+
+ if (mmc_get_init_state() != 0) return 1;
+ map_start_block= mini_fat_find_block("MAP",map_buffer);
+
+ // Die Karte auf den Puffer biegen
+ map[0][0]=(map_section_t*)map_buffer;
+ map[1][0]=(map_section_t*)(map_buffer+sizeof(map_section_t));
+
+ if (map_start_block != 0xFFFFFFFF){
+ map_current_block_updated = False; // kein Block geladen und daher auch nicht veraendert
+ return 1;
+ }
+ #endif
+ #else
+ map_start_block = mmc_fopen("MAP")>>9; // TODO: Mit Bytes arbeiten und Shiften sparen
+ printf("Startaddress of map: 0x%lx \n\r", map_start_block<<9);
+ if (map_start_block == 0) return 1;
+ map_buffer = mmc_get_data(map_start_block<<9);
+ if (map_buffer == NULL) return 1;
+
+ // Die Karte auf den Puffer biegen
+ map[0][0]=(map_section_t*)map_buffer;
+ map[1][0]=(map_section_t*)(map_buffer+sizeof(map_section_t));
+ #endif // MMC_VM_AVAILABLE
+
+ return 0;
+}
+
+/*!
+ * liefert einen Zeiger auf die Section zurueck, in der der Punkt liegt.
+ * Auf dem MCU kuemmert sie sich darum, die entsprechende Karte aus der MMC-Karte zu laden
+ * @param x x-Ordinate der Karte (nicht der Welt!!!)
+ * @param y y-Ordinate der Karte (nicht der Welt!!!)
+ * @param create Soll das Segment erzeugt werden, falls es noch nicht existiert?
+ * @return einen zeiger auf die Karte
+ */
+map_section_t * map_get_section(uint16 x, uint16 y, uint8 create){
+ uint16 section_x, section_y;
+
+ // Berechne in welcher Sektion sich der Punkt befindet
+ section_x=x/ MAP_SECTION_POINTS;
+ section_y=y/ MAP_SECTION_POINTS;
+
+ if ((section_x>= MAP_SECTIONS) || (section_y >= MAP_SECTIONS) ||
+ (section_x < 0) || (section_y <0)){
+ #ifdef PC
+ printf("Versuch auf in Feld ausserhalb der Karte zu zugreifen!! x=%d y=%d\n",x,y);
+ #endif
+ return NULL;
+ }
+
+// cut
+
+ #ifndef MMC_VM_AVAILABLE
+ #ifdef MMC_AVAILABLE // Mit MMC-Karte geht hier einiges anders
+ // wenn die Karte nicht sauber initialisiert ist, mache nix!
+ if (map_current_block_updated == 0xFF)
+ return map[0][0];
+
+ // Berechne den gesuchten Block
+ uint32 block = section_x + section_y*MAP_SECTIONS;
+ block = block >>1; // es passen immer 2 Sections in einen Block
+ block += map_start_block; // Offset drauf
+
+ // Ist der Block noch nicht geladen
+ if (map_current_block != block){
+ // Wurde der Block im RAM veraendert?
+ if (map_current_block_updated == True)
+ mmc_write_sector(map_current_block,map_buffer,0);
+
+ //Lade den neuen Block
+ mmc_read_sector(block,map_buffer);
+ map_current_block=block;
+ map_current_block_updated = False;
+ }
+
+ // richtige der beiden sections raussuchen
+ uint8 index= section_x & 0x01;
+ return map[index][0];
+ #else // ohne MMC-Karte einfach direkt mit dem SRAM arbeiten
+ if ((map[section_x][section_y] == NULL) && (create==True)){
+ uint16 index_x, index_y;
+ map[section_x][section_y]= malloc(sizeof(map_section_t));
+ for (index_x=0; index_x<MAP_SECTION_POINTS; index_x++)
+ for (index_y=0; index_y<MAP_SECTION_POINTS; index_y++)
+ map[section_x][section_y]->section[index_x][index_y]=0;
+
+ }
+ return map[section_x][section_y];
+ #endif // MMC_AVAILABLE
+ #else
+ // Berechne den gesuchten Block
+ uint32 block = section_x + section_y*MAP_SECTIONS;
+ block = block >>1; // es passen immer 2 Sections in einen Block
+ block += map_start_block; // Offset drauf
+ map_buffer = mmc_get_data(block<<9);
+ if (map_buffer != NULL){
+ map[0][0]=(map_section_t*)map_buffer;
+ map[1][0]=(map_section_t*)(map_buffer+sizeof(map_section_t));
+ // richtige der beiden sections raussuchen
+ uint8 index= section_x & 0x01;
+ return map[index][0];
+ } else return map[0][0];
+ #endif // MMC_VM_AVAILABLE
+}
+
+/*!
+ * liefert den Wert eines Feldes
+ * @param x x-Ordinate der Karte (nicht der Welt!!!)
+ * @param y y-Ordinate der Karte (nicht der Welt!!!)
+ * @return Wert des Feldes (>0 heisst frei, <0 heisst belegt
+ */
+int8 map_get_field (uint16 x, uint16 y) {
+ uint16 index_x, index_y;
+
+ // Suche die Section heraus
+ map_section_t * section = map_get_section(x,y,False);
+
+ // Eventuell existiert die Section noch nicht
+ if (section == NULL)
+ return 0;
+
+ // Berechne den Index innerhalb der Section
+ index_x = x % MAP_SECTION_POINTS;
+ index_y = y % MAP_SECTION_POINTS;
+
+ return section->section[index_x][index_y];
+}
+
+/*!
+ * Setzt den Wert eines Feldes auf den angegebenen Wert
+ * @param x x-Ordinate der Karte (nicht der Welt!!!)
+ * @param y y-Ordinate der Karte (nicht der Welt!!!)
+ * @param value neuer wert des Feldes (> 0 heisst frei, <0 heisst belegt
+ */
+void map_set_field(uint16 x, uint16 y, int8 value) {
+ uint16 index_x, index_y;
+
+ // Suche die Section heraus
+ map_section_t * section = map_get_section(x,y,True);
+
+ // Wenn wir keine section zurueck kriegen, stimmt was nicht
+ if (section == NULL)
+ return;
+
+ // Berechne den Index innerhalb der Section
+ index_x = x % MAP_SECTION_POINTS;
+ index_y = y % MAP_SECTION_POINTS;
+
+ section->section[index_x][index_y]=value;
+
+ #ifdef SHRINK_MAP_ONLINE
+ // Belegte Kartengroesse anpassen
+ if (x < map_min_x)
+ map_min_x=x;
+ if (x > map_max_x)
+ map_max_x= x;
+ if (y < map_min_y)
+ map_min_y=y;
+ if (y > map_max_y)
+ map_max_y= y;
+ #endif
+
+ #ifdef MMC_AVAILABLE
+ #ifndef MMC_VM_AVAILABLE
+ if (map_current_block_updated != 0xFF)
+ map_current_block_updated = True;
+ #endif
+ #endif
+
+}
+
+/*!
+ * liefert den Wert eines Feldes
+ * @param x x-Ordinate der Welt
+ * @param y y-Ordinate der Welt
+ * @return Wert des Feldes (>0 heisst frei, <0 heisst belegt
+ */
+int8 map_get_point (float x, float y){
+ //Ort in Kartenkoordinaten
+ uint16 X = world_to_map(x);
+ uint16 Y = world_to_map(y);
+
+ return map_get_field(X,Y);
+}
+
+/*!
+ * aendert den Wert eines Feldes um den angegebenen Betrag
+ * @param x x-Ordinate der Karte (nicht der Welt!!!)
+ * @param y y-Ordinate der Karte (nicht der Welt!!!)
+ * @param value Betrag um den das Feld veraendert wird (>= heisst freier, <0 heisst belegter
+ */
+void map_update_field (uint16 x, uint16 y, int8 value) {
+
+ int16 tmp= map_get_field(x,y);
+ if (tmp == -128) // Nicht aktualiseren, wenn es sich um ein Loch handelt
+ return;
+
+ tmp+=value;
+
+ // pruefen, ob kein ueberlauf stattgefunden hat und das Feld nicht schon als Loch (-128) markiert ist
+ if ((tmp < 128) && (tmp > -128))
+ map_set_field(x,y,(int8)tmp);
+}
+
+/*!
+ * markiert ein Feld als frei -- drueckt den Feldwert etwas mehr in Richtung "frei"
+ * @param x x-Ordinate der Karte (nicht der Welt!!!)
+ * @param y y-Ordinate der Karte (nicht der Welt!!!)
+ */
+void map_update_free (uint16 x, uint16 y) {
+ map_update_field(x,y,MAP_STEP_FREE);
+}
+
+/*!
+ * aendert den Wert eines Feldes um den angegebenen Betrag
+ * @param x x-Ordinate der Karte (nicht der Welt!!!)
+ * @param y y-Ordinate der Karte (nicht der Welt!!!)
+ * @param value Betrag um den das Feld veraendert wird (>= heisst freier, <0 heisst belegter
+ */
+#if MAP_RADIUS_FIELDS > 0
+ void map_update_field_circle(uint16 x, uint16 y, int8 radius, int8 value) {
+ int16 dX,dY;
+ uint16 h=radius*radius;
+ for(dX = -radius; dX <= radius; dX++){
+ for(dY = -radius; dY <= radius; dY++) {
+ if(dX*dX + dY*dY <= h)
+ map_update_field (x + dX, y + dY,value);
+ }
+ }
+ }
+#endif
+
+/*!
+ * markiert ein Feld als belegt -- drueckt den Feldwert etwas mehr in Richtung "belegt"
+ * @param x x-Ordinate der Karte (nicht der Welt!!!)
+ * @param y y-Ordinate der Karte (nicht der Welt!!!)
+ */
+void map_update_occupied (uint16 x, uint16 y) {
+ // Nur wenn ein Umkreis gewuenscht ist, auch einen malen
+ #if MAP_RADIUS_FIELDS > 0
+ uint8 r;
+ for (r=1; r<=MAP_RADIUS_FIELDS; r++){
+ map_update_field_circle(x,y,r,-MAP_STEP_OCCUPIED/MAP_RADIUS_FIELDS);
+ }
+ #else
+ map_update_field(x,y,-MAP_STEP_OCCUPIED);
+ #endif
+}
+
+/*!
+ * Konvertiert eine Weltkoordinate in eine Kartenkoordinate
+ * @param koord Weltkordiante
+ * @return kartenkoordinate
+ */
+uint16 world_to_map(float koord){
+ uint16 tmp = koord * MAP_RESOLUTION / 1000 + (MAP_SIZE*MAP_RESOLUTION/2);
+
+ return tmp;
+}
+
+/*!
+ * Konvertiert eine Kartenkoordinate in eine Weltkoordinate
+ * @param map_koord kartenkoordinate
+ * @return Weltkordiante
+ */
+float map_to_world(uint16 map_koord){
+ float tmp = (map_koord - (MAP_SIZE*MAP_RESOLUTION/2)) / MAP_RESOLUTION * 1000;
+
+ return tmp;
+}
+
+/*!
+ * Aktualisiert die Karte mit den Daten eines Sensors
+ * @param x X-Achse der Position des Sensors
+ * @param y Y-Achse der Position des Sensors
+ * @param head Blickrichtung im Bogenmaß
+ * @param dist Sensorwert
+ */
+void update_map_sensor(float x, float y, float h, int16 dist){
+ //Ort des Sensors in Kartenkoordinaten
+ uint16 X = world_to_map(x);
+ uint16 Y = world_to_map(y);
+
+ uint16 d;
+ if (dist==SENS_IR_INFINITE)
+ d=SENS_IR_MAX_DIST;
+ else
+ d=dist;
+
+
+
+ // Hinderniss, dass der Sensor sieht in Weltkoordinaten
+ float PH_x = x + (DISTSENSOR_POS_FW + d) * cos(h);
+ float PH_y = y + (DISTSENSOR_POS_FW + d) * sin(h);
+ // Hinderniss, dass der linke Sensor sieht in Kartenkoordinaten
+ uint16 PH_X = world_to_map(PH_x);
+ uint16 PH_Y = world_to_map(PH_y);
+
+ if ((dist > 80 ) && (dist <SENS_IR_INFINITE))
+ map_update_occupied(PH_X,PH_Y);
+
+
+
+ // Nun markiere alle Felder vor dem Hinderniss als frei
+ uint16 i;
+
+ uint16 lX = X; // Beginne mit dem Feld, in dem der Sensor steht
+ uint16 lY = Y;
+
+ int8 sX = (PH_X < X ? -1 : 1);
+ uint16 dX=abs(PH_X - X); // Laenge der Linie in X-Richtung
+
+ int8 sY = (PH_Y < Y ? -1 : 1);
+ uint16 dY =abs(PH_Y - Y); // Laenge der Linie in Y-Richtung
+
+ if (dX >= dY) { // Hangle Dich an der laengeren Achse entlang
+ dY--; // stoppe ein Feld vor dem Hinderniss
+ uint16 lh = dX / 2;
+ for (i=0; i<dX; ++i) {
+ map_update_free (lX+i*sX, lY);
+ lh += dY;
+ if (lh >= dX) {
+ lh -= dX;
+ lY += sY;
+ }
+ }
+ } else {
+ dX--; // stoppe ein Feld vor dem Hinderniss
+ uint16 lh = dY / 2;
+ for (i=0; i<dY; ++i) {
+ map_update_free (lX, lY+i*sY);
+ lh += dX;
+ if (lh >= dY) {
+ lh -= dY;
+ lX += sX;
+ }
+ }
+ }
+}
+
+/*!
+ * Aktualisiert den Standkreis der internen Karte
+ * @param x X-Achse der Position
+ * @param y Y-Achse der Position
+ */
+void update_map_location(float x, float y){
+ int16 x_map = world_to_map(x);
+ int16 y_map = world_to_map(y);
+
+ // Aktualisiere zuerst die vom Bot selbst belegte Flaeche
+ #define dim BOT_DIAMETER/2*MAP_RESOLUTION/100
+ int16 dX,dY;
+ for(dX = -dim; dX <= dim; dX++)
+ for(dY = -dim; dY <= dim; dY++) {
+ if(dX*dX + dY*dY <= dim*dim)
+ map_update_free (x_map + dX, y_map + dY);
+ }
+}
+
+/*!
+ * Aktualisiert die interne Karte anhand der Sensordaten
+ * @param x X-Achse der Position
+ * @param y Y-Achse der Position
+ * @param head Blickrichtung in Grad
+ * @param distL Sensorwert links
+ * @param distR Sensorwert rechts
+ */
+void update_map(float x, float y, float head, int16 distL, int16 distR){
+// printf("update_map: x=%f, y=%f, head=%f, distL=%d, distR=%d\n",x,y,head,distL,distR);
+
+ float h= head * M_PI /180;
+
+ //Ort des rechten Sensors in Weltkoordinaten
+ float Pr_x = x + (DISTSENSOR_POS_SW * sin(h));
+ float Pr_y = y - (DISTSENSOR_POS_SW * cos(h));
+
+ //Ort des linken Sensors in Weltkoordinaten
+ float Pl_x = x - (DISTSENSOR_POS_SW * sin(h));
+ float Pl_y = y + (DISTSENSOR_POS_SW * cos(h));
+
+ update_map_sensor(Pl_x,Pl_y,h,distL);
+ update_map_sensor(Pr_x,Pr_y,h,distR);
+}
+
+
+
+#ifdef PC
+ /*!
+ * Schreibt einbe Karte in eine PGM-Datei
+ * @param filename Zieldatei
+ */
+ void map_to_pgm(char * filename){
+ printf("Speichere Karte nach %s\n",filename);
+ FILE *fp = fopen(filename, "w");
+
+ uint16 x,y;
+
+ // lokale Variablen mit den defaults befuellen
+ uint16 min_x=map_min_x;
+ uint16 max_x=map_max_x;
+ uint16 min_y=map_min_y;
+ uint16 max_y=map_max_y;
+
+ #ifdef SHRINK_MAP_OFFLINE // nun muessen wir die Grenezn ermitteln
+ // Kartengroesse reduzieren
+ int8 free=1;
+ while ((min_y < max_y) && (free ==1)){
+ for (x=min_x; x<max_x; x++){
+ if (map_get_field(x,min_y) != 0){
+ free=0;
+ break;
+ }
+ }
+ min_y++;
+ }
+ free=1;
+ while ((min_y < max_y) && (free ==1)){
+ for (x=min_x; x<max_x; x++){
+ if (map_get_field(x,max_y-1) != 0){
+ free=0;
+ break;
+ }
+ }
+ max_y--;
+ }
+
+ free=1;
+ while ((min_x < max_x) && (free ==1)){
+ for (y=min_y; y<max_y; y++){
+ if (map_get_field(min_x,y) != 0){
+ free=0;
+ break;
+ }
+ }
+ min_x++;
+ }
+ free=1;
+ while ((min_x < max_x) && (free ==1)){
+ for (y=min_y; y<max_y; y++){
+ if (map_get_field(max_x-1,y) != 0){
+ free=0;
+ break;
+ }
+ }
+ max_x--;
+ }
+
+ #endif
+
+ uint16 map_size_x=max_x-min_x;
+ uint16 map_size_y=max_y-min_y;
+ #ifdef MAP_PRINT_SCALE
+ fprintf(fp,"P5\n%d %d\n255\n",map_size_x+10,map_size_y+10);
+ #else
+ fprintf(fp,"P5\n%d %d\n255\n",map_size_x,map_size_y);
+ #endif
+ printf("Karte beginnt bei X=%d,Y=%d und geht bis X=%d,Y=%d (%d * %d Punkte)\n",min_x,min_y,max_x,max_y,map_size_x,map_size_y);
+
+ uint8 tmp;
+ for (y=max_y; y> min_y; y--){
+ for (x=min_x; x<max_x; x++){
+
+ tmp=map_get_field(x,y-1)+128;
+ fwrite(&tmp,1,1,fp);
+ }
+
+ #ifdef MAP_PRINT_SCALE
+ // und noch schnell ne Skala basteln
+ for (x=0; x<10; x++){
+ if (y % MAP_SCALE == 0)
+ tmp=0;
+ else tmp=255;
+
+ fwrite(&tmp,1,1,fp);
+ }
+ #endif
+
+ }
+
+ #ifdef MAP_PRINT_SCALE
+ for (y=0; y< 10; y++){
+ for (x=min_x; x<max_x+10; x++){
+ if (x % MAP_SCALE == 0)
+ tmp=0;
+ else tmp=255;
+
+ fwrite(&tmp,1,1,fp);
+ }
+ }
+ #endif
+ fclose(fp);
+
+ }
+
+
+ /*! Liest eine Map wieder ein
+ * @param filename Quelldatei
+ */
+ void read_map(char * filename){
+ printf("Lese Karte (%s) von MMC/SD (Bot-Format)\n",filename);
+ FILE *fp = fopen(filename, "r");
+
+ uint8 buffer[512];
+ fread(buffer,512,1,fp);
+
+ if (buffer[0] != 'M' || buffer[1] != 'A' || buffer[2] != 'P'){
+ printf("Datei %s enthaelt keine Karte\n",filename);
+ return;
+ }
+
+ uint16 x,y;
+ uint8 * ptr;
+
+ for (y=0; y< MAP_SECTIONS; y++)
+ for (x=0; x< MAP_SECTIONS; x++){
+ ptr= (uint8*)map_get_section(x*MAP_SECTION_POINTS, y*MAP_SECTION_POINTS, True);
+ fread(ptr,MAP_SECTION_POINTS*MAP_SECTION_POINTS,1,fp);
+ }
+
+ fclose(fp);
+
+ }
+#endif
+
+
+
+/*!
+ * Zeigt die Karte an
+ */
+void print_map(void){
+ #ifdef PC
+ map_to_pgm("map.pgm");
+ #else
+ // Todo: Wie soll der Bot eine Karte ausgeben ....
+ #endif
+}
+
+
+
+#endif
diff --git a/source/ct-Bot/mcu/TWI_driver.c b/source/ct-Bot/mcu/TWI_driver.c
new file mode 100644
index 0000000..db4c0fb
--- /dev/null
+++ b/source/ct-Bot/mcu/TWI_driver.c
@@ -0,0 +1,194 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file TWI_driver.c
+ * @brief TWI-Treiber (I2C)
+ * @author Chris efstathiou hendrix@otenet.gr & Carsten Giesen (info@cnau.de)
+ * @date 08.04.06
+*/
+
+#ifdef MCU
+#include <avr/io.h>
+#include "TWI_driver.h"
+#include "global.h"
+
+
+/*!
+ * TWI Bus initialsieren
+ * @return Resultat der Aktion
+ */
+
+int8 Init_TWI(void){
+ TWAR = OWN_ADR; /*!< Eigenen Slave Adresse setzen */
+ TWBR = 12; /*!< Setze Baudrate auf 100 KHz */
+ /*!< 4 MHz xtal */
+ TWCR = (1<<TWEN); /*!< TWI-Interface einschalten */
+
+ return 1;
+}
+
+/*!
+ * TWI Buss schliesen
+ * @return Resultat der Aktion
+ */
+
+int8 Close_TWI(void){
+ TWCR = (0<<TWEN); /*!< TWI-Interface ausschalten */
+
+ return 0;
+}
+
+/*!
+ * Warte auf TWI interrupt
+ */
+
+void Wait_TWI_int(void){
+ while (!(TWCR & (1<<TWINT)))
+ ;
+}
+
+/*!
+ * Sende Start Sequence
+ * @return Resultat der Aktion
+ */
+
+uint8 Send_start(void){
+ TWCR = ((1<<TWINT)+(1<<TWSTA)+(1<<TWEN)); /*!< Sende START */
+
+ Wait_TWI_int(); /*!< Warte auf TWI interrupt */
+
+ if((TWSR != START)&&(TWSR != REP_START)) /*!< Ist der Status ein Anderer als Start (0x08) oder wiederholter Start (0x10) */
+ return TWSR; /*!< -> error und Rueckgabe TWSR. */
+ return SUCCESS; /*!< wenn OK Rueckgabe SUCCESS */
+}
+
+/*!
+ * Sende Stop Sequence
+ */
+
+void Send_stop(void){
+ TWCR = ((1<<TWEN)+(1<<TWINT)+(1<<TWSTO));
+}
+
+/*!
+ * Hier wird der eigentliche TWI-Treiber angesprochen
+ * @param *data_pack Container mit den Daten fuer den Treiber
+ * @return Resultat der Aktion
+ */
+uint8 Send_to_TWI(tx_type *data_pack){
+ uint8 state,i,j;
+
+ state = SUCCESS;
+
+ for(i=0;(data_pack[i].slave_adr != OWN_ADR)&&(state == SUCCESS);i++) {
+ state = Send_start();
+ if (state == SUCCESS)
+ state = Send_adr(data_pack[i].slave_adr);
+
+ /*!
+ * Abhaengig von W/R senden oder empfangen
+ */
+ if(!(data_pack[i].slave_adr & R)) {
+ if (state == SUCCESS){
+ /*!
+ * Wenn W bis alle Daten gesendet sind
+ */
+ for(j=0;((j<data_pack[i].size)&&(state == SUCCESS));j++)
+ state = Send_byte(data_pack[i].data_ptr[j]);
+ }
+ }
+ else{
+ if (state == MRX_ADR_NACK) {
+ state = Send_start();
+ }
+
+ if (state == SUCCESS){
+ /*!
+ * Wenn R bis alle Daten empfangen sind
+ */
+ for(j=0;((j<data_pack[i].size)&&(state == SUCCESS));j++){
+ /*!
+ * Wenn wir keine Daten mehr erwarten NACK senden
+ */
+ if(j == data_pack[i].size-1)
+ state = Get_byte(data_pack[i].data_ptr++,0);
+ else
+ state = Get_byte(data_pack[i].data_ptr++,1);
+ }
+ }
+ }
+ Send_stop();
+ }
+ Close_TWI();
+
+ return state;
+}
+
+/*!
+ * Sende ein Byte
+ * @param data das zu uebertragende Byte
+ */
+
+uint8 Send_byte(uint8 data){
+ Wait_TWI_int();
+ TWDR = data;
+ TWCR = ((1<<TWINT)+(1<<TWEN));
+ Wait_TWI_int();
+ if(TWSR != MTX_DATA_ACK)
+ return TWSR;
+ return SUCCESS;
+}
+
+/*!
+ * Sende Slave Adresse
+ * @param adr die gewuenschte Adresse
+ * @return Resultat der Aktion
+ */
+
+uint8 Send_adr(uint8 adr){
+ Wait_TWI_int();
+ TWDR = adr;
+ TWCR = ((1<<TWINT)+(1<<TWEN));
+ Wait_TWI_int();
+ if((TWSR != MTX_ADR_ACK)&&(TWSR != MRX_ADR_ACK))
+ return TWSR;
+ return SUCCESS;
+}
+
+/*!
+ * Empfange ein Byte
+ * @param *rx_ptr Container fuer die Daten
+ * @param last_byte Flag ob noch Daten erwartet werden
+ * @return Resultat der Aktion
+ */
+
+uint8 Get_byte(uint8 *rx_ptr,uint8 last_byte){
+ Wait_TWI_int();
+ if(last_byte)
+ TWCR = ((1<<TWINT)+(1<<TWEA)+(1<<TWEN));
+ else
+ TWCR = ((1<<TWINT)+(1<<TWEN));
+ Wait_TWI_int();
+ *rx_ptr = TWDR;
+ if(((TWSR == MRX_DATA_NACK)&&(last_byte == 0))||(TWSR == MRX_DATA_ACK))
+ return SUCCESS;
+ return TWSR;
+}
+
+#endif
diff --git a/source/ct-Bot/mcu/adc.c b/source/ct-Bot/mcu/adc.c
new file mode 100644
index 0000000..1fb63d1
--- /dev/null
+++ b/source/ct-Bot/mcu/adc.c
@@ -0,0 +1,70 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file adc.c
+ * @brief Routinen zum Einlesen der AnalogeingÄnge
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+
+#ifdef MCU
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+//#include <avr/signal.h>
+
+#include "adc.h"
+
+/*!
+ * Initialisert den AD-Umsetzer.
+ * @param channel Für jeden Kanal, den man nutzen möchte,
+ * muss das entsprechende Bit in channel gesetzt sein
+ * Bit0 = Kanal 0 usw.
+ */
+void adc_init(uint8 channel){
+ DDRA &= ~ channel; // Pin als input
+ PORTA &= ~ channel; // Alle Pullups aus.
+}
+
+/*!
+ * Liest einen analogen Kanal aus
+ * @param channel Kanal - hex-Wertigkeit des Pins (0x01 fuer PA0; 0x02 fuer PA1, ..)
+ */
+uint16 adc_read(uint8 channel){
+ uint16 result = 0x00;
+
+ // interne Refernzspannung AVCC, rechts Ausrichtung
+ ADMUX= _BV(REFS0) ;//| _BV(REFS1); //|(0<<ADLAR);
+
+ ADMUX |= (channel & 0x07); // Und jetzt Kanal waehlen, nur single ended
+
+ ADCSRA= (1<<ADPS2) | (1<<ADPS1)| // prescale faktor= 128 ADC laeuft
+ (1 <<ADPS0) | // mit 14,7456MHz/ 128 = 115,2kHz
+ (1 << ADEN)| // ADC an
+ (1 << ADSC); // Beginne mit der Konvertierung
+
+ while ( (ADCSRA & (1<<ADSC)) != 0){asm volatile("nop");} //Warten bis konvertierung beendet
+ // Das sollte 25 ADC-Zyklen dauern!
+ // also 1/4608 s
+ result= ADCL;
+ result+=(ADCH <<8); // Ergebnis zusammenbauen
+
+ return result;
+}
+#endif
diff --git a/source/ct-Bot/mcu/bot-2-pc.c b/source/ct-Bot/mcu/bot-2-pc.c
new file mode 100644
index 0000000..377f117
--- /dev/null
+++ b/source/ct-Bot/mcu/bot-2-pc.c
@@ -0,0 +1,111 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file bot-2-pc.c
+ * @brief Verbindung zwischen c't-Bot und PC
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 28.2.06
+*/
+
+#include "ct-Bot.h"
+#include "command.h"
+#include "uart.h"
+#include "bot-2-pc.h"
+#include "sensor.h"
+#include "motor.h"
+#include "led.h"
+#include "mouse.h"
+#include "log.h"
+#include <stdlib.h>
+
+#ifdef MCU
+#ifdef BOT_2_PC_AVAILABLE
+
+/*!
+ * Diese Funktion nimmt die Daten vom PC entgegen
+ * und wertet sie aus. dazu nutzt er die Funktion command_evaluate()
+ */
+void bot_2_pc_listen(void){
+// LOG_DEBUG(("%d bytes recvd",uart_data_available()));
+ if (uart_data_available() >= sizeof(command_t)){
+// LOG_DEBUG(("%d bytes recvd",uart_data_available()));
+ if (command_read() ==0){
+ LOG_DEBUG(("command received"));
+ command_evaluate();
+ }else {
+ // TODO Fehlerbehandlung
+ }
+ }
+}
+
+/*!
+ * Diese Funktion informiert den PC ueber alle Sensor und Aktuator-Werte
+ */
+void bot_2_pc_inform(void){
+ int16 value1, value2;
+
+ command_write(CMD_AKT_MOT, SUB_CMD_NORM ,(int16*)&speed_l,(int16*)&speed_r,0);
+ value1=(int16)led;
+ command_write(CMD_AKT_LED, SUB_CMD_NORM ,&value1,&value1,0);
+
+ command_write(CMD_SENS_IR, SUB_CMD_NORM ,(int16*)&sensDistL,(int16*)&sensDistR,0);
+ command_write(CMD_SENS_ENC, SUB_CMD_NORM ,(int16*)&sensEncL,(int16*)&sensEncR,0);
+ command_write(CMD_SENS_BORDER, SUB_CMD_NORM ,(int16*)&sensBorderL,(int16*)&sensBorderR,0);
+ command_write(CMD_SENS_LINE, SUB_CMD_NORM ,(int16*)&sensLineL,(int16*)&sensLineR,0);
+
+ command_write(CMD_SENS_LDR, SUB_CMD_NORM ,(int16*)&sensLDRL,(int16*)&sensLDRR,0);
+
+ value1= (int16) sensTrans; value2=0;
+ command_write(CMD_SENS_TRANS, SUB_CMD_NORM ,&value1,&value2,0);
+
+ value1= (int16) sensDoor;
+ command_write(CMD_SENS_DOOR, SUB_CMD_NORM ,&value1,&value2,0);
+
+ #ifdef MAUS_AVAILABLE
+ value1=(int16)sensMouseDX;
+ value2=(int16)sensMouseDY;
+ command_write(CMD_SENS_MOUSE, SUB_CMD_NORM ,&value1,&value2,0);
+ #endif
+
+ value1=(int16)sensError; value2=0;
+ command_write(CMD_SENS_ERROR, SUB_CMD_NORM ,&value1,&value2,0);
+// command_write(CMD_SENS_RC5, SUB_CMD_NORM ,(int16*)&RC5_Code,&value2,0);
+}
+
+
+
+#include <stdio.h>
+#include <string.h>
+
+/*!
+ * Meldet den Bot am c't-Sim an
+ */
+void bot_2_pc_init(void){
+ int16 null =0;
+ uint8 j;
+
+ uart_init();
+
+ for(j=0;j<5;j++)
+ command_write(CMD_WELCOME, SUB_WELCOME_REAL ,&null,&null,0);
+}
+
+#endif
+#endif
+
diff --git a/source/ct-Bot/mcu/delay.c b/source/ct-Bot/mcu/delay.c
new file mode 100644
index 0000000..4d7ade3
--- /dev/null
+++ b/source/ct-Bot/mcu/delay.c
@@ -0,0 +1,69 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file delay.c
+ * @brief Hilfsroutinen
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 20.12.05
+*/
+
+#ifdef MCU
+
+#include "ct-Bot.h"
+
+#ifdef NEW_AVR_LIB
+ #include <util/delay.h>
+#else
+ #include <avr/delay.h>
+#endif
+
+#include "timer.h"
+
+/*!
+ * Warte 100 ms
+ */
+void delay_100ms(void){
+ char counter;
+ //wait (10 * 120000) cycles = wait 1200000 cycles
+ counter = 0;
+ while (counter != 5)
+ {
+ //wait (30000 x 4) cycles = wait 120000 cycles
+ _delay_loop_2(30000);
+ counter++;
+ }
+}
+
+
+/*!
+ * Delays for ms milliseconds
+ * @param ms Anzahl der Millisekunden
+ */
+void delay(uint16 ms){
+ uint32 start = TIMER_GET_TICKCOUNT_32;
+ if ((uint8)start != TIMER_GET_TICKCOUNT_8) start = TIMER_GET_TICKCOUNT_32;
+ uint32 ticksToWait = MS_TO_TICKS((uint32)ms);
+ uint32 now;
+ do {
+ now = TIMER_GET_TICKCOUNT_32;
+ if ((uint8)now != TIMER_GET_TICKCOUNT_8) now = TIMER_GET_TICKCOUNT_32;
+ } while (now-start < ticksToWait);
+
+}
+#endif
diff --git a/source/ct-Bot/mcu/display.c b/source/ct-Bot/mcu/display.c
new file mode 100644
index 0000000..f94ce16
--- /dev/null
+++ b/source/ct-Bot/mcu/display.c
@@ -0,0 +1,272 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file display.c
+ * @brief Routinen zur Displaysteuerung
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 20.12.05
+*/
+#include "global.h"
+#include "ct-Bot.h"
+
+#ifdef MCU
+#ifdef DISPLAY_AVAILABLE
+
+#include <avr/io.h>
+#ifdef NEW_AVR_LIB
+ #include <util/delay.h>
+#else
+ #include <avr/delay.h>
+#endif
+#include <stdarg.h>
+#include <stdio.h>
+#include "command.h"
+
+#include "display.h"
+#include "led.h"
+#include "delay.h"
+#include "shift.h"
+#include "display.h"
+
+/*! Puffergroesse fuer eine Zeile in bytes */
+#define DISPLAY_BUFFER_SIZE (DISPLAY_LENGTH + 1)
+
+uint8 display_update=0; /*!< Muss das Display aktualisiert werden? */
+#ifdef DISPLAY_SCREENS_AVAILABLE
+ #ifdef LOG_DISPLAY_AVAILABLE
+ uint8 display_screen=4; /*!< Muss das Display aktualisiert werden? */
+ #else
+ uint8 display_screen=0; /*!< Muss das Display aktualisiert werden? */
+ #endif
+#endif
+static char display_buf[DISPLAY_BUFFER_SIZE]; /*!< Pufferstring fuer Displayausgaben */
+
+#define DISPLAY_CLEAR 0x01 /*!< Kommando zum Löschen */
+#define DISPLAY_CURSORHOME 0x02 /*!< Kommando für den Cursor */
+
+#define DISPLAY_OUT 0x07 /*!< Output-Pins Display */
+#define DISPLAY_IN (1<<5) /*!< Input-Pins Display */
+
+#define DISPLAY_PORT PORTC /*!< Port an dem das Display hängt */
+#define DISPLAY_DDR DDRC /*!< Port an dem das Display hängt */
+#define DPC (DISPLAY_PORT & ~DISPLAY_OUT) /*!< Port des Displays */
+//#define DRC (DDRC & ~DISPLAY_PINS)
+
+//#define DISPLAY_READY_PINR PINC /*!< Port an dem das Ready-Flag des Display hängt */
+#define DISPLAY_READY_DDR DDRC /*!< Port an dem das Ready-Flag des Display hängt */
+#define DISPLAY_READY_PIN (1<<5) /*!< Pin an dem das Ready-Flag des Display hängt */
+
+/*! RS-Leitung
+ * legt fest, ob die Daten an das Display in den Textpuffer (RS=1) kommen
+ * oder als Steuercode interpretiert werden (RS=0)
+ */
+#define DISPLAY_RS (1<<0) /*!< Pin an dem die RS-Leitung des Displays hängt */
+
+/*! RW-Leitung
+ * legt fest, ob zum Display geschrieben wird (RW=0)
+ * oder davon gelesen wird (RW=1)
+ */
+#define DISPLAY_RW (1<<1) /*!< Pin an dem die RW-Leitung des Displays hängt */
+
+/*! Enable Leitung
+ * schaltet das Interface ein (E=1).
+ * Nur wenn Enable auf High-Pegel liegt, läßt sich das Display ansprechen
+ */
+#define DISPLAY_EN (1<<2) /*!< Pin an dem die EN-Leitung des Displays hängt */
+
+/*
+ * Im Moment der Low-High-Flanke von ENABLE liest das Dislplay
+ * die Werte von RS und R/W ein. Ist zu diesem Zeitpunkt R/W=0,
+ * dann liest das Display mit der folgenden High-Low-Flanke von ENABLE
+ * den Datenbus ein (Schreibzyklus).
+ * War aber R/W=1, dann legt das Display ein Datenword auf den
+ * Datenbus (Lese-Zyklus), solange bis die High-Low-Flanke von ENABLE
+ * das Interface wieder deaktiviert.
+ */
+
+/*!
+ * Ãœbertrage Kommando an das Display
+ * @param cmd Kommando
+ */
+void display_cmd(uint8 cmd){ //ein Kommando cmd an das Display senden
+ uint8 i;
+ shift_data_out(cmd,SHIFT_LATCH,SHIFT_REGISTER_DISPLAY);
+ // Enable muss für mind. 450 ns High bleiben, bevor es fallen darf!
+ // ==> Also mind. 8 Zyklen warten
+ for (i=0; i<150; i++){
+ asm volatile("nop");
+ }
+ DISPLAY_PORT=DPC; // Alles zurück setzen ==> Fallende Flanke von Enable
+}
+
+
+/*!
+ * Ein Zeichen auf das Display schreiben
+ * @param data Das Zeichen
+ */
+void display_data(char data){ //ein Zeichen aus data in den Displayspeicher schreiben
+ uint8 i;
+ shift_data_out(data,SHIFT_LATCH,SHIFT_REGISTER_DISPLAY|DISPLAY_RS);
+
+ // Enable muss für mind. 450 ns High bleiben, bevor es fallen darf!
+ // ==> Also mind. 8 Zyklen warten
+ for (i=0; i<150; i++){
+ asm volatile("nop");
+ }
+ DISPLAY_PORT=DPC; // Alles zurück setzen ==> Fallende Flanke von Enable
+}
+
+/*!
+ * Löscht das ganze Display
+ */
+void display_clear(void){
+ display_cmd(DISPLAY_CLEAR); // Display loeschen, Cursor Home
+ #ifdef DISPLAY_REMOTE_AVAILABLE
+ command_write(CMD_AKT_LCD, SUB_LCD_CLEAR, NULL, NULL,0);
+ #endif
+}
+
+/*!
+ * Positioniert den Cursor
+ * @param row Zeile
+ * @param column Spalte
+ */
+void display_cursor (uint8 row, uint8 column) {
+ switch (row) {
+ case 1:
+ display_cmd (0x80 + column - 1);
+ break;
+ case 2:
+ display_cmd (0xc0 + column - 1);
+ break;
+ case 3:
+ display_cmd (0x94 + column - 1);
+ break;
+ case 4:
+ display_cmd (0xd4 + column - 1);
+ break;
+ default: break;
+ }
+
+ #ifdef DISPLAY_REMOTE_AVAILABLE
+ int16 r=row-1;
+ int16 c=column-1;
+ command_write(CMD_AKT_LCD, SUB_LCD_CURSOR, &c,&r,0);
+ #endif
+
+}
+
+/*!
+ * Init Display
+ */
+void display_init(void){
+ shift_init();
+
+ DISPLAY_DDR |= DISPLAY_OUT; // Ausgänge
+ DISPLAY_DDR &= ~DISPLAY_IN; // Eingänge
+
+ delay(12); // Display steht erst 10ms nach dem Booten bereit
+
+ // Register in 8-Bit-Modus 3x Ãœbertragen, dazwischen warten
+ shift_data_out(0x38,SHIFT_LATCH,SHIFT_REGISTER_DISPLAY);
+ DISPLAY_PORT= DPC;
+ delay(5);
+ shift_data_out(0x38,SHIFT_LATCH,SHIFT_REGISTER_DISPLAY);
+ DISPLAY_PORT= DPC;
+ delay(5);
+ shift_data_out(0x38,SHIFT_LATCH,SHIFT_REGISTER_DISPLAY);
+ DISPLAY_PORT= DPC;
+ delay(5);
+
+ display_cmd(0x0f); //Display On, Cursor On, Cursor Blink
+
+ display_cmd(DISPLAY_CLEAR); // Display loeschen, Cursor Home
+
+ display_data('i');
+}
+
+/*!
+ * Zeigt einen String an
+ * @return -1 falls string zuende 0 falls Zeile (20 zeichen) zuende
+ */
+/*int display_string(char data[20]){
+ int i=0;
+
+ while ((i<20) && (data[i] != 0x00)){ // Abbruch, sobald ein Nullstring erreicht wird
+ // oder 20 Zeichen gesendet sind
+ display_data(data[i++]); // einzelnes Zeichen schicken
+ }
+
+ // return -1 falls string zuende, 0 falls zeile (20 zeichen) zuende
+ if (data[i]==0x00) return -1; else return 0;
+}
+*/
+
+/*!
+ * Schreibt einen String auf das Display.
+ * @param format Format, wie beim printf
+ * @param ... Variable Argumentenliste, wie beim printf
+ */
+void display_printf(char *format, ...) {
+
+ unsigned int run = 0;
+ va_list args;
+
+ /* Sicher gehen, das der zur Verfuegung stehende Puffer nicht
+ * ueberschrieben wird.
+ */
+ va_start(args, format);
+ vsnprintf(display_buf, DISPLAY_BUFFER_SIZE, format, args);
+ va_end(args);
+
+ /* Ausgeben bis Puffer leer ist */
+ while(display_buf[run] != '\0') {
+ display_data(display_buf[run]);
+ run++;
+ }
+
+ #ifdef DISPLAY_REMOTE_AVAILABLE
+ command_write_data(CMD_AKT_LCD, SUB_LCD_DATA, NULL, NULL, display_buf);
+ #endif
+
+ return;
+}
+
+/*
+void display_test(){
+ shift_init();
+
+// shift_data_out(0xAA,SHIFT_LATCH,SHIFT_REGISTER_DISPLAY);
+
+ display_cmd(0x38); //Display auf 8 Bit Betrieb
+ for(;;){}
+ display_cmd(0x0f); //Display On, Cursor On, Cursor Blink
+
+ display_cmd(DISPLAY_CLEAR); // Display l�schen, Cursor Home
+ display_cursor(2,2);
+
+ display_string("Hallo");
+ for(;;){
+ }
+}
+*/
+
+#endif
+
+#endif
diff --git a/source/ct-Bot/mcu/ena.c b/source/ct-Bot/mcu/ena.c
new file mode 100644
index 0000000..17ee859
--- /dev/null
+++ b/source/ct-Bot/mcu/ena.c
@@ -0,0 +1,128 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file ena.c
+ * @brief Routinen zur Steuerung der Enable-Leitungen
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+
+#ifdef MCU
+
+#include <avr/io.h>
+#include "ena.h"
+#include "ct-Bot.h"
+#include "shift.h"
+#include "mouse.h"
+
+#ifdef ENA_AVAILABLE
+
+
+uint8 ena =0; /*!< Sichert den Zustand der Enable-Leitungen */
+
+/*!
+ * Initialisiert die Enable-Leitungen
+ */
+void ENA_init(){
+ DDRD |= 4;
+ shift_init();
+ ENA_set(0x00);
+}
+
+
+//void maus_sens_write(int8 adr, uint8 data);
+/*!
+ * Schaltet einzelne Enable-Transistoren an
+ * andere werden nicht beeinflusst
+ * Achtung, die Treiber-Transistoren sind Low-Aktiv!!!
+ * ENA_on schaltet einen Transistor durch
+ * Daher zieht es die entsprechende ENA_XXX-Leitung (mit Transistor) auf Low und NICHT auf High
+ * @param enable Bitmaske der anzuschaltenden LEDs
+ */
+void ENA_on(uint8 enable){
+// uint8 i;
+ // Maussensor und MMC-Karte haengen zusammen
+ if (enable == ENA_MOUSE_SENSOR){ // Maus sensor an, MMC aus
+
+// if ((ena & ENA_MMC) ==0){ // War die MMC-Karte an?
+ ena |= ENA_MMC; // MMC aus
+
+// PORTD |= 4; // Fliplops takten
+// PORTD &= ~4;
+//
+// for (i=0; i<200; i++){ // Ein paar flanken schocken, damit auch sicher danach ruhe ist
+// PORTB &= ~(1<<7);
+// PORTB |= (1<<7);
+// }
+// }
+
+ // Und dann den Maussensor an
+ ena &= ~ENA_MOUSE_SENSOR;
+ } else if (enable == ENA_MMC) { // Maus sensor aus, MMC aan
+ #ifdef MAUS_AVAILABLE
+ if ((ena & ENA_MOUSE_SENSOR) ==0){ // War der Maussensor an?
+ maus_sens_highZ(); // Der Maussensor muss die Datenleitung freigeben
+ ena |= ENA_MOUSE_SENSOR; // Maus aus
+ }
+ #endif
+ ena &= ~enable;
+ } else {
+ ena |= enable;
+ }
+
+ ENA_set(ena);
+
+ if ( (enable & (ENA_MOUSE_SENSOR | ENA_MMC)) != 0 ){
+ PORTD |= 4; // Fliplops takten
+ PORTD &= ~4;
+ }
+}
+
+/*!
+ * Schaltet einzelne Enable-Transistoren aus
+ * andere werden nicht beeinflusst
+ * Achtung, die Treiber-Transistoren sind Low-Aktiv!!!
+ * ENA_off schaltet einen Transistor ab
+ * Daher zieht es die entsprechende ENA_XXX-Leitung (mit Transistor) auf High und NICHT auf Low
+ * @param enable Bitmaske der anzuschaltenden LEDs
+ */
+void ENA_off(uint8 enable){
+ ena &= ~enable;
+ ENA_set(ena);
+
+ if ( (enable & (ENA_MOUSE_SENSOR | ENA_MMC)) != 0 ){
+ PORTD |= 4; // Fliplops takten
+ PORTD &= ~4;
+ }
+}
+
+/*!
+ * Schaltet die Enable-Transistoren
+ * Achtung, die Treiber-Transistoren sind Low-Aktiv!!!
+ * ENA_set bezieht sich auf die Transistor
+ * Daher zieht es die entsprechende ENA_XXX-Leitung auf ~enable
+ * @param LED Wert der gezeigt werden soll
+ */
+void ENA_set(uint8 enable){
+ ena=enable;
+ shift_data(~enable,SHIFT_REGISTER_ENA);
+}
+
+#endif
+#endif
diff --git a/source/ct-Bot/mcu/ir-rc5.c b/source/ct-Bot/mcu/ir-rc5.c
new file mode 100644
index 0000000..8bb17b0
--- /dev/null
+++ b/source/ct-Bot/mcu/ir-rc5.c
@@ -0,0 +1,163 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file ir-rc5.c
+ * @brief Routinen für die Dekodierung von RC5-Fernbedienungs-Codes
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 20.12.05
+*/
+
+// Infos ueber RC6: http://www.xs4all.nl/~sbp/knowledge/ir/rc6.htm
+// http://www.xs4all.nl/~sbp/knowledge/ir/ir.htm
+
+// ========================================================================
+// RC5 Infrarot-Empf�nger
+// ========================================================================
+#include "ct-Bot.h"
+#ifdef MCU
+#ifdef IR_AVAILABLE
+
+#include <avr/io.h>
+#include "ir-rc5.h"
+#include "timer.h"
+
+
+// -----------------------------------------------------------------------------
+// Timing
+// -----------------------------------------------------------------------------
+#define IR_SAMPLES_PER_BIT 10 /*!< 10 Samples per Bit */
+#define IR_SAMPLES_PER_BIT_EARLY 8 /*!< Flanke fr�hestens nach 8 Samples */
+#define IR_SAMPLES_PER_BIT_LATE 12 /*!< Flanke sp�testens nach 12 Samples */
+#define IR_SAMPLES_PER_BIT_MIN 3 /*!< Flanke vor 3 Samples -> paket verwerfen */
+#define IR_PAUSE_SAMPLES 250 /*!< Startbit ist erst nach 250 Samples ohne */
+ // Pegel�nderung g�ltig -- eigentlich m�sste
+ // man rund 500 Samples abwarten (50 x
+ // Bitzeit), doch weil der Samplez�hler ein
+ // Byte ist, beschr�nken wir uns hier auf ein
+ // Minimum von 250 Samples
+
+#define IR_PORT PORTB /*!< Port B */
+#define IR_DDR DDRB /*!< DDR of Port B */
+#define IR_PINR PINB /*!< Port B input */
+#define IR_PIN 1 /*!< Pin 1 */
+
+
+
+static byte ir_lastsample = 0; /*!< zuletzt gelesenes Sample */
+static byte ir_bittimer = 0; /*!< zählt die Aufrufe von ir_isr() */
+
+static uint16 ir_data_tmp = 0; /*!< RC5-Bitstream */
+static byte ir_bitcount = 0; /*!< anzahl gelesener bits */
+
+volatile uint16 ir_data = 0; /*!< letztes komplett gelesenes RC5-paket */
+
+/*!
+ * Interrupt Serviceroutine
+ * wird ca alle 177.8us aufgerufen
+ */
+void ir_isr(void) {
+ // sample lesen
+ byte sample = 1;
+
+ if ((IR_PINR & (1<<IR_PIN)) != 0) {
+ sample = 0;
+ }
+
+ // bittimer erhoehen (bleibt bei 255 stehen)
+ if (ir_bittimer<255) {
+ ir_bittimer++;
+ }
+
+ // flankenerkennung
+ if ( ir_lastsample != sample) {
+ if (ir_bittimer<=IR_SAMPLES_PER_BIT_MIN) {
+ // flanke kommt zu frueh: paket verwerfen
+ ir_bitcount=0;
+ } else {
+ // Startbit
+ if (ir_bitcount==0) {
+ if ( (sample==1) && (ir_bittimer>IR_PAUSE_SAMPLES) ) {
+ // Startbit speichern
+ ir_data_tmp = 1;
+ ir_bitcount++;
+ } else {
+ // error
+ ir_data_tmp = 0;
+ }
+
+ // bittimer-reset
+ ir_bittimer = 0;
+
+ // Bits 2..14: nur Flanken innerhalb des Bits beruecksichtigen
+ } else {
+ if (ir_bittimer >= IR_SAMPLES_PER_BIT_EARLY) {
+ if(ir_bittimer<=IR_SAMPLES_PER_BIT_LATE){
+ // Bit speichern
+ ir_data_tmp = (ir_data_tmp<<1) | sample;
+ ir_bitcount++;
+ } else {
+ // zu sp�t: paket verwerfen
+ ir_bitcount = 0;
+ }
+
+ // bittimer-reset
+ ir_bittimer = 0;
+ }
+ }
+ }
+
+ } else {
+ // keine flanke innerhalb bitzeit?
+ if (ir_bittimer > IR_SAMPLES_PER_BIT_LATE) {
+ // 14 bits gelesen?
+ if (ir_bitcount==14) {
+ ir_data = ir_data_tmp;
+ }
+ // paket verwerfen
+ ir_bitcount = 0;
+ }
+ }
+
+ // sample im samplepuffer ablegen
+ ir_lastsample = sample;
+
+
+}
+
+
+/*!
+ * IR-Daten lesen
+ * @return wert von ir_data, löscht anschliessend ir_data
+ */
+uint16 ir_read(void) {
+ uint16 retvalue = ir_data;
+ ir_data = 0;
+ return retvalue;
+}
+
+/*!
+ * Init IR-System
+ */
+void ir_init(void) {
+ IR_DDR &= ~IR_PIN; // Pin auf Input
+ IR_PORT |= IR_PIN; // Pullup an
+ timer_2_init(); // Für IR-Krams
+}
+#endif
+#endif
diff --git a/source/ct-Bot/mcu/led.c b/source/ct-Bot/mcu/led.c
new file mode 100644
index 0000000..8668106
--- /dev/null
+++ b/source/ct-Bot/mcu/led.c
@@ -0,0 +1,74 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file led.c
+ * @brief Routinen zur LED-Steuerung
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+
+#ifdef MCU
+
+#include <avr/io.h>
+#include "led.h"
+#include "ct-Bot.h"
+#include "shift.h"
+
+#ifdef LED_AVAILABLE
+
+uint8 led=0;
+/*!
+ * Initialisiert die LEDs
+ */
+void LED_init(){
+ shift_init();
+ LED_off(LED_ALL);
+}
+
+/*!
+ * Schaltet einzelne LEDs an
+ * andere werden nicht beeinflusst
+ * @param LED Bitmaske der anzuschaltenden LEDs
+ */
+void LED_on(uint8 LED){
+ led |= LED;
+ LED_set(led);
+}
+
+/*!
+ * Schaltet einzelne LEDs aus
+ * andere werden nicht beeinflusst
+ * @param LED Bitmaske der anzuschaltenden LEDs
+ */
+void LED_off(uint8 LED){
+ led &= ~LED;
+ LED_set(led);
+}
+
+/*!
+ * Zeigt eine 8-Bit Variable mit den LEDs an
+ * @param LED Wert der gezeigt werden soll
+ */
+void LED_set(uint8 LED){
+ led=LED;
+ shift_data(led,SHIFT_REGISTER_LED);
+}
+
+#endif
+#endif
diff --git a/source/ct-Bot/mcu/mini-fat.c b/source/ct-Bot/mcu/mini-fat.c
new file mode 100644
index 0000000..9fa96ee
--- /dev/null
+++ b/source/ct-Bot/mcu/mini-fat.c
@@ -0,0 +1,93 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file mini-fat.c
+ * @brief Routinen zum Auffinden von markierten Files auf einer MMC-Karte.
+ * Dies ist keine vollstaendige FAT-Unterstuetzung, sondern sucht nur eien Datei, die mit einer 3-Zeichen Sequenz beginnt.
+ * @author Benjamin Benz (bbe@heise.de)
+ * @author Ulrich Radig (mail@ulrichradig.de) www.ulrichradig.de
+ * @date 07.11.06
+*/
+
+#include "ct-Bot.h"
+
+#ifdef MCU
+#ifdef MINI_FAT_AVAILABLE
+
+#include "mmc.h"
+#include "display.h"
+#include "mini-fat.h"
+
+/*!
+ * Sucht einen Block auf der MMC-Karte, dessen erste drei Bytes dem key entsprechen
+ * liefert dann den folgenden Block zurueck.
+ * Achtung das prinzip geht nur, wenn die Dateien nicht fragmentiert sind
+ * @param key 3 Byte zur Identifikation
+ * @param buffer Zeiger auf 512 Byte Puffer im SRAM
+ */
+uint32 mini_fat_find_block(const char* filename, uint8* buffer){
+
+ // Suche nach der Datei fuer die Katrte
+ int8 found = False;
+
+ uint32 card_size= mmc_get_size() >> 9; // groesse der Karte in Bloecken
+
+ #ifdef DISPLAY_AVAILABLE
+ display_cursor(2,1);
+ display_printf("Find %s: 0x",filename);
+ uint16 i=0, j=0;
+ #endif
+
+ uint32 block=0;
+ while(found == False && block < card_size){
+ #ifdef DISPLAY_AVAILABLE
+ display_cursor(2,13);
+ display_printf("%02x%04x",j,i );
+ if (i==65535)
+ j++;
+ i++;
+ #endif
+ mmc_read_sector(block++,buffer);
+ uint8 i;
+ for (i=0; i<MMC_FILENAME_MAX; i++)
+ if (filename[i] == '\0'){
+ found = True;
+ break;
+ } else if (filename[i] != buffer[i]) break;
+ }
+
+ if (found == False)
+ return 0xFFFFFFFF;
+
+ #ifdef DISPLAY_AVAILABLE
+ i= block & 0xFFFF;
+ j= (block >> 16) & 0xFFFF;
+ display_cursor(2,1);
+ display_printf("Found %s: 0x%02x%04x",filename,j,i);
+ #endif
+
+ // auf der Karte markieren, dass wir sie in der Hand hatten
+// buffer[3]++;
+// mmc_write_sector(block-1,buffer,0);
+
+ return block;
+}
+
+#endif
+#endif
diff --git a/source/ct-Bot/mcu/mmc-low.S b/source/ct-Bot/mcu/mmc-low.S
new file mode 100644
index 0000000..b4ef6f5
--- /dev/null
+++ b/source/ct-Bot/mcu/mmc-low.S
@@ -0,0 +1,482 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+#ifdef MCU
+; Hinweis:
+; Sollte der Build-Prozess an dieser Datei scheitern, bitte auch die
+; Datei ".settings/org.eclipse.core.runtime.prefs" aus dem CVS laden, oder
+; selbst veranlassen, dass .S-Dateien ebenfalls vom gcc verarbeitet werden
+; (und nicht direkt vom Assembler).
+
+/*!
+ * @file mmc-low.s
+ * @brief Low-Level-Routinen zum Lesen/Schreiben einer MMC / SD-Card
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 14.11.2006
+ */
+
+#include "mmc-low.h"
+#include "ct-Bot.h"
+#include "ena.h"
+#ifdef MMC_AVAILABLE
+#include <avr/io.h>
+
+; Portkonfiguration umrechnen
+.equ PORT_OUT, _SFR_IO_ADDR(MMC_PORT_OUT)
+.equ PORT_IN, _SFR_IO_ADDR(MMC_PORT_IN)
+.equ DDR, _SFR_IO_ADDR(MMC_DDR)
+.equ SPI_CLK_MASK, _BV(SPI_CLK) ; 1<<SPI_CLK
+
+/*!
+ * Schreibt ein Byte an die Karte
+ * @param data Das zu sendende Byte
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 14.11.2006
+ */
+.global mmc_write_byte
+ .type mmc_write_byte, @function
+mmc_write_byte:
+ in r25, PORT_OUT ; MMC_PORT_OUT einlesen
+ cbr r25, SPI_CLK_MASK ; CLK auf low
+ bst r24, 7 ; Bit 7 der Daten
+ bld r25, SPI_DO ; Daten nach DO
+ out PORT_OUT, r25 ; Daten senden
+ sbi PORT_OUT, SPI_CLK ; CLK auf high
+ bst r24, 6 ; Bit 6 der Daten
+ bld r25, SPI_DO
+ out PORT_OUT, r25
+ sbi PORT_OUT, SPI_CLK
+ bst r24, 5 ; Bit 5 der Daten
+ bld r25, SPI_DO
+ out PORT_OUT, r25
+ sbi PORT_OUT, SPI_CLK
+ bst r24, 4 ; Bit 4 der Daten
+ bld r25, SPI_DO
+ out PORT_OUT, r25
+ sbi PORT_OUT, SPI_CLK
+ bst r24, 3 ; Bit 3 der Daten
+ bld r25, SPI_DO
+ out PORT_OUT, r25
+ sbi PORT_OUT, SPI_CLK
+ bst r24, 2 ; Bit 2 der Daten
+ bld r25, SPI_DO
+ out PORT_OUT, r25
+ sbi PORT_OUT, SPI_CLK
+ bst r24, 1 ; Bit 1 der Daten
+ bld r25, SPI_DO
+ out PORT_OUT, r25
+ sbi PORT_OUT, SPI_CLK
+ bst r24, 0 ; Bit 0 der Daten
+ bld r25, SPI_DO
+ out PORT_OUT, r25
+ sbi PORT_OUT, SPI_CLK
+ sbi PORT_OUT, SPI_DO ; DO auf high
+ ret
+
+/*!
+ * Liest ein Byte von der Karte
+ * @return Das gelesene Byte
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 14.11.2006
+ */
+.global mmc_read_byte
+ .type mmc_read_byte, @function
+mmc_read_byte:
+ in r19, PORT_OUT ; MMC_PORT_OUT einlesen
+ cbr r19, SPI_CLK_MASK ; CLK low
+ out PORT_OUT, r19 ; CLK auf low
+ mov r18, r19 ; CLK high
+ sbr r18, SPI_CLK_MASK
+ in r25, PORT_IN ; Bit 7 lesen
+ out PORT_OUT, r18 ; CLK Flanke
+ out PORT_OUT, r19
+ bst r25, SPI_DI ; Bit 7 speichern
+ bld r24, 7
+ in r25, PORT_IN ; Bit 6
+ out PORT_OUT, r18
+ out PORT_OUT, r19
+ bst r25, SPI_DI
+ bld r24, 6
+ in r25, PORT_IN ; Bit 5
+ out PORT_OUT, r18
+ out PORT_OUT, r19
+ bst r25, SPI_DI
+ bld r24, 5
+ in r25, PORT_IN ; Bit 4
+ out PORT_OUT, r18
+ out PORT_OUT, r19
+ bst r25, SPI_DI
+ bld r24, 4
+ in r25, PORT_IN ; Bit 3
+ out PORT_OUT, r18
+ out PORT_OUT, r19
+ bst r25, SPI_DI
+ bld r24, 3
+ in r25, PORT_IN ; Bit 2
+ out PORT_OUT, r18
+ out PORT_OUT, r19
+ bst r25, SPI_DI
+ bld r24, 2
+ in r25, PORT_IN ; Bit 1
+ out PORT_OUT, r18
+ out PORT_OUT, r19
+ bst r25, SPI_DI
+ bld r24, 1
+ in r25, PORT_IN ; Bit 0
+ out PORT_OUT, r18
+ bst r25, SPI_DI
+ bld r24, 0
+ clr r25 ; return ist in 8 Bit und wir sind ordentlich ;)
+ ret
+
+/*!
+ * Schaltet die Karte aktiv und checkt dabei die Initialisierung
+ * @return 0 wenn alles ok ist, 1 wenn Init nicht moeglich
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 09.12.2006
+ */
+.global mmc_enable
+ .type mmc_enable, @function
+mmc_enable:
+ lds r24, mmc_init_state ; Initialisierung der Karte checken
+ tst r24
+ breq 1f
+ call mmc_init ; neu initialisieren
+ tst r24
+ breq 1f
+ ret ; kein Init moeglich => Fehler
+ 1:
+ ldi r24, lo8(ENA_MMC) ; Karte aktiv schalten
+ call ENA_on
+ ldi r24, lo8(ENA_MMC) ; Karte inaktiv schalten
+ call ENA_off
+ cbi DDR, SPI_DI ; DI auf input
+ sbi DDR, SPI_DO ; DO auf output
+ ldi r24, lo8(-1)
+ call mmc_write_byte ; sendet 8 CLK-Flanken
+ ldi r24, lo8(ENA_MMC) ; Karte aktiv schalten
+ call ENA_on
+ ldi r24, 0
+ ret ; alles ok
+
+/*!
+ * Schreibt einen 512-Byte Sektor auf die Karte
+ * @param addr Nummer des 512-Byte Blocks
+ * @param Buffer Zeiger auf den Puffer
+ * @param async 0: synchroner, 1: asynchroner Aufruf, siehe MMC_ASYNC_WRITE in mmc-low.h
+ * @return 0 wenn alles ok ist, 1 wenn Init nicht moeglich oder Timeout vor / nach Kommando 24, 2 wenn Timeout bei busy
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 16.11.2006
+ */
+.global mmc_write_sector
+ .type mmc_write_sector, @function
+mmc_write_sector:
+ push r13 ; allgemeine Register retten
+ push r14
+ push r15
+ push r16
+ push r28
+ push r29
+ movw r14, r22 ; Byte 1 und 2 von Parameter addr sichern
+ mov r16, r24 ; Byte 3 von Parameter addr sichern
+ movw r28, r20 ; Parameter Buffer sichern
+ mov r13, r18 ; Parameter async sichern
+ call mmc_enable ; Karte aktiv schalten
+ tst r24
+ breq 1f
+ rjmp 4f ; Karte kann nicht initialisiert werden => Fehler
+ 1:
+ lsl r14 ; Block in Bytes umrechnen
+ rol r15
+ rol r16
+#if MMC_ASYNC_WRITE == 1
+ clr r27 ; r27 = 0
+ 1:
+ clr r26 ; r26 = 0
+ 2:
+ call mmc_read_byte ; warten, ob Karte noch busy
+ cpi r24, lo8(-1)
+ breq 3f ; == 0xff?
+ dec r26 ; r26--
+ brne 2b ; r26 == 0?
+ dec r27 ; r27--
+ brne 1b ; r27 == 0?
+ rjmp 4f ; Timeout :(
+ 3:
+#endif
+ ldi r24, 88 ; Kommando 24 zum Schreiben eines Blocks senden, Byte 0
+ call mmc_write_byte
+ mov r24, r16 ; Byte 1
+ call mmc_write_byte
+ mov r24, r15 ; Byte 2
+ call mmc_write_byte
+ mov r24, r14 ; Byte 3
+ call mmc_write_byte
+ ldi r24, 0 ; Byte 4
+ call mmc_write_byte
+ ldi r24, lo8(-1) ; Byte 5 (CRC)
+ call mmc_write_byte
+ ldi r26, lo8(-1) ; Timeout nach 256 Versuchen
+ 1:
+ call mmc_read_byte
+ cpi r24, lo8(-1) ; !0xff = Antwort
+ brne 3f
+ dec r26 ; r26--
+ brne 1b
+ 3:
+ tst r24 ; Fehler oder Abbruch durch Timeout?
+ breq 1f
+ rjmp 4f ; Return-Code 1
+ 1:
+ ldi r24, lo8(-2) ; Start-Byte an Karte senden
+ call mmc_write_byte
+ in r26, PORT_OUT ; MMC_PORT_OUT einlesen
+ cbr r26, SPI_CLK_MASK ; CLK auf low
+ ldi r18, 2 ; r18 = 2
+ clr r27 ; r27 = 0
+ 1:
+ ld r25, Y+ ; Byte aus SRAM lesen
+ bst r25, 7 ; Bit 7
+ bld r26, SPI_DO
+ out PORT_OUT, r26 ; Daten senden
+ sbi PORT_OUT, SPI_CLK ; CLK auf high
+ bst r25, 6 ; Bit 6
+ bld r26, SPI_DO
+ out PORT_OUT, r26
+ sbi PORT_OUT, SPI_CLK
+ bst r25, 5 ; Bit 5
+ bld r26, SPI_DO
+ out PORT_OUT, r26
+ sbi PORT_OUT, SPI_CLK
+ bst r25, 4 ; Bit 4
+ bld r26, SPI_DO
+ out PORT_OUT, r26
+ sbi PORT_OUT, SPI_CLK
+ bst r25, 3 ; Bit 3
+ bld r26, SPI_DO
+ out PORT_OUT, r26
+ sbi PORT_OUT, SPI_CLK
+ bst r25, 2 ; Bit 2
+ bld r26, SPI_DO
+ out PORT_OUT, r26
+ sbi PORT_OUT, SPI_CLK
+ bst r25, 1 ; Bit 1
+ bld r26, SPI_DO
+ out PORT_OUT, r26
+ sbi PORT_OUT, SPI_CLK
+ bst r25, 0 ; Bit 0
+ bld r26, SPI_DO
+ out PORT_OUT, r26
+ sbi PORT_OUT, SPI_CLK
+ inc r27 ; r27++
+ breq 2f ; r27 == 0?
+ rjmp 1b
+ 2:
+ dec r18 ; r18--
+ breq 3f ; r18 == 0?
+ rjmp 1b
+ 3:
+ sbi PORT_OUT, SPI_DO ; DO auf high
+ call mmc_write_byte ; crc-Dummy schreiben
+ call mmc_write_byte
+#if MMC_ASYNC_WRITE == 1
+ tst r13 ; wollten wir asynchron schreiben?
+ brne 3f ; wenn ja, nicht auf busy warten
+#endif
+ 1:
+ clr r28 ; r28 = 0
+ 2:
+ call mmc_read_byte ; warten, ob Karte noch busy
+ cpi r24, lo8(-1)
+ breq 3f ; == 0xff?
+ dec r28 ; r28--
+ brne 2b ; r28 == 0?
+ dec r27 ; r27--
+ brne 1b ; r27 == 0?
+ rjmp 5f ; Timeout :(
+ 3:
+ ldi r16, 0 ; Alles ok, also Return-Code 0 laden :)
+ rjmp 6f
+ 4:
+ ldi r16, 1 ; Fehler, Return-Code 1 laden
+ sts mmc_init_state, r16 ; Initstatus auf Fehler setzen
+ rjmp 6f
+ 5:
+ ldi r16, 2 ; Fehler, Return-Code 2 laden
+ sts mmc_init_state, r16 ; Initstatus auf Fehler setzen
+ 6:
+ ldi r24, lo8(ENA_MMC) ; Karte inaktiv schalten
+ call ENA_off
+ mov r24, r16 ; Return-Code laden
+ ldi r25, 0
+ pop r29 ; allgemeine Register wiederherstellen
+ pop r28
+ pop r16
+ pop r15
+ pop r14
+ pop r13
+ ret
+
+/*!
+ * Liest einen Block von der Karte
+ * @param addr Nummer des 512-Byte Blocks
+ * @param Buffer Puffer von mindestens 512 Byte
+ * @return 0 wenn alles ok ist, 1 wenn Init nicht moeglich oder Timeout vor / nach Kommando 17
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 17.11.2006
+ */
+.global mmc_read_sector
+ .type mmc_read_sector, @function
+mmc_read_sector:
+ push r14 ; allgemeine Register retten
+ push r15
+ push r16
+ push r28
+ push r29
+ movw r14, r22 ; Byte 1 und 2 von Parameter addr sichern
+ mov r16, r24 ; Byte 3 von Parameter addr sichern
+ movw r28, r20 ; Parameter Buffer sichern
+ call mmc_enable ; Karte aktiv schalten
+ tst r24
+ breq 1f
+ rjmp 5f ; Karte kann nicht initialisiert werden => Fehler
+ 1:
+ lsl r14 ; Block in Bytes umrechnen
+ rol r15
+ rol r16
+#if MMC_ASYNC_WRITE == 1
+ clr r27 ; r27 = 0
+ 1:
+ clr r26 ; r26 = 0
+ 2:
+ call mmc_read_byte ; warten, ob Karte noch busy
+ cpi r24, lo8(-1)
+ breq 3f ; == 0xff?
+ dec r26 ; r26--
+ brne 2b ; r26 == 0?
+ dec r27 ; r27--
+ brne 1b ; r27 == 0?
+ rjmp 5f ; Timeout :(
+ 3:
+#endif
+ ldi r24, 81 ; Kommando 17 zum Lesen eines Blocks senden, Byte 0
+ call mmc_write_byte
+ mov r24, r16 ; Byte 1
+ call mmc_write_byte
+ mov r24, r15 ; Byte 2
+ call mmc_write_byte
+ mov r24, r14 ; Byte 3
+ call mmc_write_byte
+ ldi r24, 0 ; Byte 4
+ call mmc_write_byte
+ ldi r24,lo8(-1) ; Byte 5 (CRC)
+ call mmc_write_byte
+ ldi r16, lo8(-1) ; Timeout bei 256
+ 1:
+ call mmc_read_byte
+ cpi r24, lo8(-2) ; 0xfe = Startbyte
+ breq 2f
+ call mmc_read_byte ; Noch ein Versuch
+ cpi r24, lo8(-2)
+ breq 2f
+ dec r16
+ brne 1b
+ rjmp 4f ; Timeout, also abbrechen :(
+ 2:
+ in r20, PORT_OUT ; MMC_PORT_OUT einlesen
+ cbr r20, SPI_CLK_MASK ; CLK low
+ out PORT_OUT, r20 ; CLK auf low
+ mov r19, r20 ; CLK high
+ sbr r19, SPI_CLK_MASK
+ ldi r18, 2 ; Schleifenzaehler laden
+ clr r24
+ 1:
+ in r26, PORT_IN ; Bit 7 lesen
+ out PORT_OUT, r19 ; CLK Flanke
+ out PORT_OUT, r20
+ bst r26, SPI_DI ; Bit 7 speichern
+ bld r25, 7
+ in r26, PORT_IN ; Bit 6
+ out PORT_OUT, r19
+ out PORT_OUT, r20
+ bst r26, SPI_DI
+ bld r25, 6
+ in r26, PORT_IN ; Bit 5
+ out PORT_OUT, r19
+ out PORT_OUT ,r20
+ bst r26, SPI_DI
+ bld r25, 5
+ in r26, PORT_IN ; Bit 4
+ out PORT_OUT, r19
+ out PORT_OUT, r20
+ bst r26, SPI_DI
+ bld r25, 4
+ in r26, PORT_IN ; Bit 3
+ out PORT_OUT, r19
+ out PORT_OUT, r20
+ bst r26, SPI_DI
+ bld r25, 3
+ in r26, PORT_IN ; Bit 2
+ out PORT_OUT, r19
+ out PORT_OUT, r20
+ bst r26, SPI_DI
+ bld r25, 2
+ in r26, PORT_IN ; Bit 1
+ out PORT_OUT, r19
+ out PORT_OUT, r20
+ bst r26, SPI_DI
+ bld r25, 1
+ in r26, PORT_IN ; Bit 0
+ out PORT_OUT, r19
+ out PORT_OUT, r20
+ bst r26, SPI_DI
+ bld r25, 0
+ st Y+, r25 ; Byte ins SRAM kopieren
+ inc r24 ; r24++
+ breq 2f ; r24 == 0?
+ rjmp 1b
+ 2:
+ dec r18 ; r18--
+ breq 3f ; r18 == 0?
+ rjmp 1b
+ 3:
+ out PORT_OUT, r19 ; CLK auf high
+ call mmc_read_byte ; crc-Dummy lesen
+ call mmc_read_byte
+ 4:
+ tst r16 ; Abbruch durch Timeout?
+ breq 5f ; r27 == 0?
+ ldi r16, 0 ; Alles ok, also Return-Code 0 laden :)
+ rjmp 6f
+ 5:
+ ldi r16, 1 ; Fehler, also Return-Code 1 laden
+ sts mmc_init_state, r16 ; Initstatus auf Fehler setzen
+ 6:
+ ldi r24, lo8(ENA_MMC) ; Karte inaktiv schalten
+ call ENA_off
+ mov r24, r16 ; Return-Code laden
+ ldi r25, 0
+ pop r29 ; allgemeine Register wiederherstellen
+ pop r28
+ pop r16
+ pop r15
+ pop r14
+ ret
+#endif // MMC_AVAILABLE
+#endif // MCU
diff --git a/source/ct-Bot/mcu/mmc.c b/source/ct-Bot/mcu/mmc.c
new file mode 100644
index 0000000..3dbf183
--- /dev/null
+++ b/source/ct-Bot/mcu/mmc.c
@@ -0,0 +1,420 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file mmc.c
+ * @brief Routinen zum Auslesen/Schreiben einer MMC-Karte
+ * @author Benjamin Benz (bbe@heise.de)
+ * @author Ulrich Radig (mail@ulrichradig.de) www.ulrichradig.de
+ * @date 07.11.06
+ */
+
+
+/* Die (zeitkritischen) Low-Level-Funktionen read_ und write_byte bzw. _sector liegen jetzt
+ * in mmc-low.S. Der Assembler-Code ist a) wesentlich schneller und macht b) das Timing
+ * unabhaengig vom verwendeten Compiler.
+ * Die Portkonfiguration findet sich in mmc-low.h.
+ */
+
+//TODO: * kleine Doku machen
+
+#include "ct-Bot.h"
+
+#ifdef MCU
+#ifdef MMC_AVAILABLE
+
+#include "mmc.h"
+#include <avr/io.h>
+#include "ena.h"
+#include "timer.h"
+#include "display.h"
+
+#include <avr/interrupt.h>
+#ifndef NEW_AVR_LIB
+ #include <avr/signal.h>
+#endif
+
+#include "mmc-low.h"
+#include "mmc-vm.h"
+#include <stdlib.h>
+
+#define MMC_Disable() ENA_off(ENA_MMC);
+#define MMC_Enable() ENA_on(ENA_MMC);
+
+#define MMC_prepare() { MMC_DDR &=~(1<<SPI_DI); MMC_DDR |= (1<<SPI_DO); }
+
+volatile uint8 mmc_init_state=1; /*!< Initialierungsstatus der Karte, 0: ok, 1: Fehler */
+
+/*!
+ * Checkt die Initialisierung der Karte
+ * @return 0, wenn initialisiert
+ */
+inline uint8 mmc_get_init_state(void){
+ return mmc_init_state;
+}
+
+/*!
+ * Schreibt ein Byte an die Karte
+ * @param data Das zu sendende Byte
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 14.11.2006
+ * @see mmc-low.s
+ */
+void mmc_write_byte(uint8 data);
+
+
+/*!
+ * Liest ein Byte von der Karte
+ * @return Das gelesene Byte
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 14.11.2006
+ * @see mmc-low.s
+ */
+ uint8 mmc_read_byte(void);
+
+
+/*!
+ * Schickt ein Kommando an die Karte
+ * @param cmd Ein Zeiger auf das Kommando
+ * @return Die Antwort der Karte oder 0xFF im Fehlerfall
+ */
+uint8 mmc_write_command(uint8 *cmd){
+ uint8 result = 0xff;
+ uint16 timeout = 0;
+
+ mmc_enable(); // MMC / SD-Card aktiv schalten
+
+ // sendet 6 Byte Kommando
+ uint8 i;
+ for (i=0; i<6; i++) // sendet 6 Byte Kommando zur MMC/SD-Karte
+ mmc_write_byte(*cmd++);
+
+ // Wartet auf eine gueltige Antwort von der MMC/SD-Karte
+ while (result == 0xff){
+ result = mmc_read_byte();
+ if (timeout++ > MMC_TIMEOUT)
+ break; // Abbruch da die MMC/SD-Karte nicht antwortet
+ }
+
+ return result;
+}
+
+
+/*!
+ * Initialisiere die SD/MMC-Karte
+ * @return 0 wenn allles ok, sonst Nummer des Kommandos bei dem abgebrochen wurde
+ */
+uint8 mmc_init(void){
+ uint16 timeout = 0;
+ uint8 i;
+ mmc_init_state = 0;
+
+ // Konfiguration des Ports an der die MMC/SD-Karte angeschlossen wurde
+ MMC_CLK_DDR |= _BV(SPI_CLK); // Setzen von Pin MMC_Clock auf Output
+
+ MMC_prepare();
+
+ MMC_Enable();
+ MMC_Disable();
+
+ // Initialisiere MMC/SD-Karte in den SPI-Mode
+ for (i=0; i<0x0f; i++) // Sendet min 74+ Clocks an die MMC/SD-Karte
+ mmc_write_byte(0xff);
+
+ // Sendet Kommando CMD0 an MMC/SD-Karte
+ uint8 cmd[] = {0x40,0x00,0x00,0x00,0x00,0x95};
+ while (mmc_write_command(cmd) != 1){
+ if (timeout++ > MMC_TIMEOUT){
+ MMC_Disable();
+ mmc_init_state = 1;
+ return 1; // Abbruch bei Kommando 1 (Return Code 1)
+ }
+ }
+
+ // Sendet Kommando CMD1 an MMC/SD-Karte
+ timeout = 0;
+ cmd[0] = 0x41; // Kommando 1
+ cmd[5] = 0xFF;
+ while (mmc_write_command (cmd) !=0){
+ if (timeout++ > 3*MMC_TIMEOUT){
+ MMC_Disable();
+ mmc_init_state = 1;
+ return 2; // Abbruch bei Kommando 2 (Return Code 2)
+ }
+ }
+
+ // set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
+ MMC_Disable();
+ return 0;
+}
+
+
+/*!
+ * Liest einen Block von der Karte
+ * @param cmd Zeiger auf das Kommando, das erstmal an die Karte geht
+ * @param Buffer Ein Puffer mit mindestens count Bytes
+ * @param count Anzahl der zu lesenden Bytes
+ */
+uint8 mmc_read_block(uint8 *cmd, uint8 *buffer, uint16 count){
+ /* Initialisierung checken */
+ if (mmc_init_state != 0)
+ if (mmc_init() != 0) return 1;
+
+ // Sendet Kommando cmd an MMC/SD-Karte
+ if (mmc_write_command(cmd) != 0) {
+ mmc_init_state = 1;
+ return 1;
+ }
+
+ // Wartet auf Start Byte von der MMC/SD-Karte (FEh/Start Byte)
+ uint8 timeout=1;
+ while (mmc_read_byte() != 0xfe){
+ if (timeout++ == 0) break;
+ };
+
+ uint16 i;
+ // Lesen des Blocks (max 512 Bytes) von MMC/SD-Karte
+ for (i=0; i<count; i++)
+ *buffer++ = mmc_read_byte();
+
+ // CRC-Byte auslesen
+ mmc_read_byte(); //CRC - Byte wird nicht ausgewertet
+ mmc_read_byte(); //CRC - Byte wird nicht ausgewertet
+
+ // set MMC_Chip_Select to high (MMC/SD-Karte inaktiv)
+ MMC_Disable();
+ if (timeout == 0) {
+ mmc_init_state = 1;
+ return 1; // Abbruch durch Timeout
+ }
+ return 0; // alles ok
+}
+
+#ifdef MMC_INFO_AVAILABLE
+/*!
+ * Liest das CID-Register (16 Byte) von der Karte
+ * @param Buffer Puffer von mindestens 16 Byte
+ */
+void mmc_read_cid (uint8 *buffer){
+ // Kommando zum Lesen des CID Registers
+ uint8 cmd[] = {0x4A,0x00,0x00,0x00,0x00,0xFF};
+ mmc_read_block(cmd, buffer, 16);
+}
+
+/*!
+ * Liest das CSD-Register (16 Byte) von der Karte
+ * @param Buffer Puffer von mindestens 16 Byte
+ */
+void mmc_read_csd (uint8 *buffer){
+ // Kommando zum lesen des CSD Registers
+ uint8 cmd[] = {0x49,0x00,0x00,0x00,0x00,0xFF};
+ mmc_read_block(cmd, buffer, 16);
+}
+
+/*!
+ * Liefert die Groesse der Karte zurueck
+ * @return Groesse der Karte in Byte. Bei einer 4 GByte-Karte kommt 0xFFFFFFFF zurueck
+ */
+uint32 mmc_get_size(void){
+ uint8 csd[16];
+
+ mmc_read_csd(csd);
+
+ uint32 size = (csd[8]>>6) + (csd[7] << 2) + ((csd[6] & 0x03) << 10); // c_size
+ size +=1; // Fest in der Formel drin
+
+ uint8 shift = 2; // eine 2 ist fest in der Formel drin
+ shift += (csd[10]>>7) + ((csd[9] & 0x03) <<1); // c_size_mult beruecksichtigen
+ shift += csd[5] & 0x0f; // Blockgroesse beruecksichtigen
+
+ size = size << shift;
+
+ return size;
+}
+
+
+#endif //MMC_INFO_AVAILABLE
+
+#ifdef MMC_WRITE_TEST_AVAILABLE
+ /*! Testet die MMC-Karte. Schreibt nacheinander 2 Sektoren a 512 Byte mit Testdaten voll und liest sie wieder aus
+ * !!! Achtung loescht die Karte
+ * @return 0, wenn alles ok
+ */
+ uint8 mmc_test(void){
+ static uint32 sector = 0xf000;
+ /* Initialisierung checken */
+ if (mmc_init_state != 0)
+ if (mmc_init() != 0){
+ sector = 0;
+ return 1;
+ }
+ #ifdef MMC_VM_AVAILABLE // Version mit virtuellen Aressen
+ uint16 i;
+ static uint16 pagefaults = 0;
+ static uint16 old_pf;
+ /* virtuelle Adressen holen */
+ static uint32 v_addr1 = 0;
+ static uint32 v_addr2 = 0;
+ static uint32 v_addr3 = 0;
+ static uint32 v_addr4 = 0;
+ if (v_addr1 == 0) v_addr1 = mmcalloc(512, 1); // Testdaten 1
+ if (v_addr2 == 0) v_addr2 = mmcalloc(512, 1); // Testdaten 2
+ if (v_addr3 == 0) v_addr3 = mmcalloc(512, 1); // Dummy 1
+ if (v_addr4 == 0) v_addr4 = mmcalloc(512, 1); // Dummy 2
+ /* Zeitmessung starten */
+ uint16 start_ticks=TIMER_GET_TICKCOUNT_16;
+ uint8 start_reg=TCNT2;
+ /* Pointer auf Puffer holen */
+ uint8* p_addr = mmc_get_data(v_addr1); // Cache-Hit, CB 0
+ if (p_addr == NULL) return 2;
+ /* Testdaten schreiben */
+ for (i=0; i<512; i++)
+ p_addr[i] = (i & 0xff);
+ /* Pointer auf zweiten Speicherbereich holen */
+ p_addr = mmc_get_data(v_addr2); // Cache-Hit, CB 1
+ if (p_addr == NULL) return 3;
+ /* Testdaten Teil 2 schreiben */
+ for (i=0; i<512; i++)
+ p_addr[i] = 255 - (i & 0xff);
+ /* kleiner LRU-Test */
+// p_addr = mmc_get_data(v_addr1); // Cache-Hit, CB 0
+// p_addr = mmc_get_data(v_addr4); // Cache-Miss, => CB 1
+// p_addr = mmc_get_data(v_addr1); // Cache-Hit, CB 0
+// p_addr = mmc_get_data(v_addr3); // Cache-Miss, => CB 1
+// p_addr = mmc_get_data(v_addr1); // Cache-Hit, CB 0
+// p_addr = mmc_get_data(v_addr4); // Cache-Miss, => CB 1
+ /* Pointer auf Testdaten Teil 1 holen */
+ p_addr = mmc_get_data(v_addr1); // Cache-Hit, CB 0
+ if (p_addr == NULL) return 4;
+ /* Testdaten 1 vergleichen */
+ for (i=0; i<512; i++)
+ if (p_addr[i] != (i & 0xff)) return 5;
+ /* Pointer auf Testdaten Teil 2 holen */
+ p_addr = mmc_get_data(v_addr2); // Cache-Miss, => CB 1
+ if (p_addr == NULL) return 6;
+ /* Testdaten 2 vergleichen */
+ for (i=0; i<512; i++)
+ if (p_addr[i] != (255 - (i & 0xff))) return 7;
+
+ p_addr = mmc_get_data(v_addr4);
+ /* Zeitmessung beenden */
+ int8 timer_reg=TCNT2;
+ uint16 end_ticks=TIMER_GET_TICKCOUNT_16;
+ timer_reg -= start_reg;
+ #ifdef VM_STATS_AVAILABLE
+ /* Pagefaults merken */
+ old_pf = pagefaults;
+ pagefaults = mmc_get_pagefaults();
+ #endif
+ /* kleine Statistik ausgeben */
+ display_cursor(3,1);
+ display_printf("Pagefaults: %5u ", pagefaults);
+ display_cursor(4,1);
+ display_printf("Bei %3u PF: %5u us", pagefaults - old_pf, (end_ticks-start_ticks)*176 + timer_reg*4);
+ #else // alte Version
+ uint8 buffer[512];
+ uint16 i;
+ uint8 result=0;
+
+ /* Zeitmessung starten */
+ uint16 start_ticks=TIMER_GET_TICKCOUNT_16;
+ uint8 start_reg=TCNT2;
+
+ #if MMC_ASYNC_WRITE == 1
+ /* async-Test (wurde im letzten Durchlauf korrekt geschrieben?) */
+ if (sector > 0xf){
+ result= mmc_read_sector(sector-1, buffer);
+ if (result != 0){
+ return result*10 + 9;
+ }
+ for (i=0; i<512; i++)
+ if (buffer[i] != (i & 0xFF)){
+ return 10;
+ }
+ }
+ #endif // MMC_ASYNC_WRITE
+
+ // Puffer vorbereiten
+ for (i=0; i< 512; i++) buffer[i]= (i & 0xFF);
+ // und schreiben
+ result= mmc_write_sector(sector, buffer, 0);
+ if (result != 0){
+ return result*10 + 2;
+ }
+
+ // Puffer vorbereiten
+ for (i=0; i< 512; i++) buffer[i]= 255 - (i & 0xFF);
+ // und schreiben
+ result= mmc_write_sector(sector+1, buffer, 0);
+ if (result != 0){
+ return result*10 + 3;
+ }
+
+ // Puffer lesen
+ result= mmc_read_sector(sector++, buffer);
+ if (result != 0){
+ sector--;
+ return result*10 + 4;
+ }
+
+ // und vergleichen
+ for (i=0; i<512; i++)
+ if (buffer[i] != (i & 0xFF)){
+ return 5;
+ }
+
+// sector++;
+ // Puffer lesen
+ result= mmc_read_sector(sector++, buffer);
+ if (result != 0){
+ sector--;
+ return result*10 + 6;
+ }
+ // und vergleichen
+ for (i=0; i<512; i++)
+ if (buffer[i] != (255- (i & 0xFF))){
+ return 7;
+ }
+
+ #if MMC_ASYNC_WRITE == 1
+ for (i=0; i< 512; i++)
+ buffer[i]= (i & 0xFF);
+ result= mmc_write_sector(sector-1, buffer, MMC_ASYNC_WRITE);
+ if (result != 0){
+ return result*10 + 8;
+ }
+ #endif // MMC_ASYNC_WRITE
+
+ /* Zeitmessung beenden */
+ int8 timer_reg=TCNT2;
+ uint16 end_ticks=TIMER_GET_TICKCOUNT_16;
+ timer_reg -= start_reg;
+ /* kleine Statistik ausgeben */
+ display_cursor(3,1);
+ display_printf("Dauer: %5u us ", (end_ticks-start_ticks)*176 + timer_reg*4);
+ display_cursor(4,1);
+ display_printf("Sektor:%6u/", sector-2);
+ display_printf("%6u", sector-1);
+ #endif // MMC_VM_AVAILABLE
+ // hierher kommen wir nur, wenn alles ok ist
+ return 0;
+ }
+#endif //MMC_WRITE_TEST_AVAILABLE
+
+#endif
+#endif
diff --git a/source/ct-Bot/mcu/motor-low.c b/source/ct-Bot/mcu/motor-low.c
new file mode 100644
index 0000000..98e5f9f
--- /dev/null
+++ b/source/ct-Bot/mcu/motor-low.c
@@ -0,0 +1,242 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file motor-low.c
+ * @brief Low-Level Routinen fuer die Motorsteuerung des c't-Bots
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 01.12.05
+*/
+#ifdef MCU
+
+#include "ct-Bot.h"
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#ifndef NEW_AVR_LIB
+ #include <avr/signal.h>
+#endif
+#include <stdlib.h>
+
+#include "global.h"
+#include "motor.h"
+#include "timer.h"
+#include "sensor.h"
+#include "display.h"
+#include "motor-low.h"
+
+//Drehrichtung der Motoren
+#define BOT_DIR_L_PIN (1<<6) // PC7
+#define BOT_DIR_L_PORT PORTC
+#define BOT_DIR_L_DDR DDRC
+
+#define BOT_DIR_R_PIN (1<<7) // PC6
+#define BOT_DIR_R_PORT PORTC
+#define BOT_DIR_R_DDR DDRC
+
+#define PWM_L OCR1A
+#define PWM_R OCR1B
+
+#define PWM_CLK_0 (_BV(CS02) | _BV(CS00)) /*!< Prescaler fuer PWM 0 = 1024*/
+//#define PWM_CLK_2 (_BV(CS22) | _BV(CS21) |_BV(CS20)) /*!< Prescaler fuer PWM 2 =1024 */
+
+int16 motor_left; /*!< zuletzt gestellter Wert linker Motor */
+int16 motor_right; /*!< zuletzt gestellter Wert rechter Motor */
+
+
+void pwm_0_init(void);
+void pwm_1_init(void);
+// void pwm_2_init(void); // Kollidiert mit Timer2 fuer IR-Fernbedienung
+
+/*!
+ * Initialisiert alles fuer die Motosteuerung
+ */
+void motor_low_init(){
+ BOT_DIR_L_DDR|=BOT_DIR_L_PIN;
+ BOT_DIR_R_DDR|=BOT_DIR_R_PIN;
+
+ pwm_0_init();
+ pwm_1_init();
+// pwm_2_init(); // Kollidiert mit Timer2 fuer IR-Fernbedienung
+ bot_motor(0,0);
+}
+
+/*!
+ * unmittelbarere Zugriff auf die beiden Motoren
+ * normalerweise NICHT verwenden!!!!!
+ * @param left Speed links
+ * @param right Speed rechts
+*/
+void bot_motor(int16 left, int16 right){
+ // Vorzeichenbehaftete PWM-Werte sichern
+ motor_left=left;
+ motor_right=right;
+
+ PWM_L = 255-abs(left);
+ PWM_R = 255-abs(right);
+
+ if (left > 0 ){
+ BOT_DIR_L_PORT |= BOT_DIR_L_PIN;
+ direction.left= DIRECTION_FORWARD;
+ } else
+ BOT_DIR_L_PORT &= ~BOT_DIR_L_PIN;
+
+ if (left < 0 )
+ direction.left= DIRECTION_BACKWARD;
+
+
+ if (right <= 0 ) // Einer der Motoren ist invertiert, da er ja in die andere Richtung schaut
+ BOT_DIR_R_PORT |= BOT_DIR_R_PIN;
+ else {
+ BOT_DIR_R_PORT &= ~BOT_DIR_R_PIN;
+ direction.right= DIRECTION_FORWARD;
+ }
+ if (right < 0 )
+ direction.right= DIRECTION_BACKWARD;
+}
+
+/*!
+ * Stellt die Servos
+ * Sinnvolle Werte liegen zwischen 8 und 16
+ */
+void servo_low(uint8 servo, uint8 pos){
+ if (servo== SERVO1) {
+ if (pos == SERVO_OFF) {
+ #ifdef __AVR_ATmega644__
+ TCCR0B &= ~PWM_CLK_0 ; // PWM aus
+ #else
+ TCCR0 &= ~PWM_CLK_0 ; // PWM aus
+ #endif
+ } else {
+ #ifdef __AVR_ATmega644__
+ TCCR0B |= PWM_CLK_0; // PWM an
+ OCR0A=pos;
+ #else
+ TCCR0 |= PWM_CLK_0; // PWM an
+ OCR0=pos;
+ #endif
+ }
+
+ }
+
+// if (servo== SERVO2) {
+// if (pos == 0) {
+// TCCR2 &= ~ (_BV(CS22) | _BV(CS21) | _BV(CS20)); // PWM an
+// } else {
+// TCCR2 |= PWM_CLK_2; // PWM an
+// OCR2=pos;
+// }
+// }
+
+}
+
+/*!
+ * Interrupt Handler for Timer/Counter 0
+ */
+#ifdef __AVR_ATmega644__
+ SIGNAL (TIMER0_COMPA_vect){
+#else
+ SIGNAL (SIG_OUTPUT_COMPARE0){
+#endif
+}
+
+/*!
+ * Timer 0: Kontrolliert den Servo per PWM
+ * PWM loescht bei erreichen. daher steht in OCR0 255-Speed!!!
+ * initilaisiert Timer 0 und startet ihn
+ */
+void pwm_0_init(void){
+
+ DDRB |= (1<<3); // PWM-Pin als Output
+ TCNT0 = 0x00; // TIMER0 vorladen
+
+ #ifdef __AVR_ATmega644__
+ TCCR0A = _BV(WGM00) | // Normal PWM
+ _BV(COM0A1); // Clear on Compare , Set on Top
+ //PWM_CLK_0;
+
+ OCR0A = 8;
+ #else
+ TCCR0 = _BV(WGM00) | // Normal PWM
+ _BV(COM01) ; // Clear on Compare , Set on Top
+
+ OCR0 = 8; // PWM loescht bei erreichen. daher steht in OCR0 255-Speed!!!
+ #endif
+ // TIMSK |= _BV(OCIE0); // enable Output Compare 0 overflow interrupt
+ //sei(); // enable interrupts
+}
+
+// ---- Timer 1 ------
+
+/*!
+ * Interrupt Handler for Timer/Counter 1A
+ */
+SIGNAL (SIG_OUTPUT_COMPARE1A){
+}
+
+/*!
+ * Interrupt Handler for Timer/Counter 1B
+ */
+SIGNAL (SIG_OUTPUT_COMPARE1B){
+}
+
+/*!
+ * Timer 1: Kontrolliert die Motoren per PWM
+ * PWM loescht bei erreichen. daher steht in OCR1A/OCR1B 255-Speed!!!
+ * initilaisiert Timer 0 und startet ihn
+ */
+void pwm_1_init(void){
+ DDRD |= 0x30 ; // PWM-Pins als Output
+ TCNT1 = 0x0000; // TIMER1 vorladen
+
+ TCCR1A = _BV(WGM10) | // Fast PWM 8 Bit
+ _BV(COM1A1) |_BV(COM1A0) | // Clear on Top, Set on Compare
+ _BV(COM1B1) |_BV(COM1B0); // Clear on Top, Set on Compare
+
+ TCCR1B = _BV(WGM12) |
+ _BV(CS12) | _BV(CS10); // Prescaler = 1024
+// _BV(CS10); // Prescaler = 1
+
+ OCR1A = 255; // PWM loescht bei erreichen. daher steht in OCR1A 255-Speed!!!
+ OCR1B = 255; // PWM loescht bei erreichen. daher steht in OCR1B 255-Speed!!!
+
+ // TIMSK|= _BV(OCIE1A) | _BV(OCIE1B); // enable Output Compare 1 overflow interrupt
+ // sei(); // enable interrupts
+}
+
+/*!
+ * Timer 0: Kontrolliert den Servo per PWM
+ * PWM loescht bei erreichen. daher steht in OCR0 255-Speed!!!
+ * initilaisiert Timer 0 und startet ihn
+ */
+/* Kollidiert derzeit mit Timer2 fuer IR
+void pwm_2_init(void){
+ DDRD |= 0x80; // PWM-Pin als Output
+ TCNT2 = 0x00; // TIMER0 vorladen
+
+ TCCR2 = _BV(WGM20) | // Normal PWM
+ _BV(COM21); // Clear on Top, Set on Compare
+// _BV(CS22) | _BV(CS21) |_BV(CS20); // Prescaler = 1024
+
+ OCR2 = 8; // PWM löscht bei erreichen. daher steht in OCR0 255-Speed!!!
+ // TIMSK |= _BV(OCIE0); // enable Output Compare 0 overflow interrupt
+ //sei(); // enable interrupts
+}
+*/
+
+#endif
diff --git a/source/ct-Bot/mcu/mouse.c b/source/ct-Bot/mcu/mouse.c
new file mode 100644
index 0000000..f04ec13
--- /dev/null
+++ b/source/ct-Bot/mcu/mouse.c
@@ -0,0 +1,183 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file mouse.c
+ * @brief Routinen fuer die Ansteuerung eines opt. Maussensors
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+#include "global.h"
+
+
+#ifdef MCU
+
+#include <avr/io.h>
+#include "ct-Bot.h"
+#include "mouse.h"
+#include "delay.h"
+#include "ena.h"
+
+#ifdef MAUS_AVAILABLE
+
+#define MAUS_DDR DDRB /*!< DDR fuer Maus-SCLK */
+#define MAUS_PORT PORTB /*!< PORT fuer Maus-SCLK */
+#define MAUS_SCK_PIN (1<<7) /*!< PIN fuer Maus-SCLK */
+
+#define MAUS_SDA_NR 6 /*!< Pin an dem die SDA-Leitung haengt */
+#define MAUS_SDA_PINR PINB /*!< Leseregister */
+#define MAUS_SDA_PIN (1<<MAUS_SDA_NR) /*!< Bit-Wert der SDA-Leitung */
+
+#define MOUSE_Enable() ENA_on(ENA_MOUSE_SENSOR)
+
+/*!
+ * Uebertraegt ein Byte an den Sensor
+ * @param data das Byte
+ */
+void maus_sens_writeByte(uint8 data){
+ int8 i;
+ MAUS_DDR |= MAUS_SDA_PIN; // SDA auf Output
+
+ for (i=7; i>=0; i--){
+ MAUS_PORT &= ~MAUS_SCK_PIN; // SCK auf Low, vorbereiten
+
+ //Daten rausschreiben
+ MAUS_PORT = (MAUS_PORT & (~MAUS_SDA_PINR)) | ((data >> (7 - MAUS_SDA_NR)) & MAUS_SDA_PIN);
+ data = data <<1; // naechstes Bit vorbereiten
+ asm volatile("nop"); // Etwas warten
+
+ MAUS_PORT |= MAUS_SCK_PIN; // SCK =1 Sensor uebernimmt auf steigender Flanke
+ }
+}
+
+/*!
+ * Liest ein Byte vom Sensor
+ * @return das Byte
+ */
+uint8 maus_sens_readByte(void){
+ int i;
+ char data=0;
+
+ MAUS_DDR &= ~MAUS_SDA_PIN; // SDA auf Input
+
+ for (i=7; i>-1; i--){
+ MAUS_PORT &= ~MAUS_SCK_PIN; // SCK =0 Sensor bereitet Daten auf fallender Flanke vor !
+ data=data<<1; // Platz schaffen
+
+ asm volatile("nop"); // Etwas warten
+ MAUS_PORT |= MAUS_SCK_PIN; // SCK =1 Daten lesen auf steigender Flanke
+
+ data |= (MAUS_SDA_PINR >> MAUS_SDA_NR) & 0x01; //Daten lesen
+ }
+
+ return data;
+}
+
+/*!
+ * Uebertraegt ein write-Kommando an den Sensor
+ * @param adr Adresse
+ * @param data Datum
+ */
+void maus_sens_write(int8 adr, uint8 data){
+ int16 i;
+
+ MOUSE_Enable();
+
+ maus_sens_writeByte(adr|=0x80); //rl MSB muss 1 sein Datenblatt S.12 Write Operation
+ maus_sens_writeByte(data);
+ for (i=0; i<300; i++){ asm volatile("nop"); } // mindestens 100 Mikrosekunden Pause!!!
+}
+
+/*!
+ * Schickt ein Lesekommando an den Sensor
+ * und liest ein Byte zurueck
+ * @param adr die Adresse
+ * @return das Datum
+ */
+uint8 maus_sens_read(uint8 adr){
+ MOUSE_Enable();
+ int16 i;
+ maus_sens_writeByte(adr);
+ for (i=0; i<300; i++){asm volatile("nop");} // mindestens 100 Mikrosekunden Pause!!!
+
+ return maus_sens_readByte();
+}
+
+/*!
+ * Initialisiere Maussensor
+ */
+void maus_sens_init(void){
+ delay(100);
+
+ MAUS_DDR |= MAUS_SCK_PIN; // SCK auf Output
+ MAUS_PORT &= ~MAUS_SCK_PIN; // SCK auf 0
+
+ delay(10);
+
+ maus_sens_write(MOUSE_CONFIG_REG,MOUSE_CFG_RESET); //Reset sensor
+ maus_sens_write(MOUSE_CONFIG_REG,MOUSE_CFG_FORCEAWAKE); //Always on
+}
+
+/*! muessen wir nach dem ersten Pixel suchen?*/
+static uint8 firstRead;
+/*!
+ * Bereitet das auslesen eines ganzen Bildes vor
+ */
+void maus_image_prepare(void){
+ maus_sens_write(MOUSE_CONFIG_REG,MOUSE_CFG_FORCEAWAKE); //Always on
+
+ maus_sens_write(MOUSE_PIXEL_DATA_REG,0x00); // Frame grabben anstossen
+ firstRead=1; //suche erstes Pixel
+}
+
+/*!
+ * Liefert bei jedem Aufruf das naechste Pixel des Bildes
+ * Insgesamt gibt es 324 Pixel
+ * <pre>
+ * 18 36 ... 324
+ * .. .. ... ..
+ * 2 20 ... ..
+ * 1 19 ... 307
+ * </pre>
+ * Bevor diese Funktion aufgerufen wird, muss maus_image_prepare() aufgerufen werden!
+ * @return Die Pixeldaten (Bit 0 bis Bit5), Pruefbit, ob Daten gueltig (Bit6), Markierung fuer den Anfang eines Frames (Bit7)
+ */
+int8 maus_image_read(void){
+ int8 pixel=maus_sens_read(MOUSE_PIXEL_DATA_REG);
+ if ( firstRead ==1){
+ while ( (pixel & 0x80) != 0x80){
+ pixel=maus_sens_read(MOUSE_PIXEL_DATA_REG);
+// if ((pixel & 0x70) != 0x70)
+// return 0;
+ }
+ firstRead=0;
+ }
+
+ return pixel;
+}
+
+/*!
+ * Gibt den SQUAL-Wert zurueck. Dieser gibt an, wieviele Merkmale der Sensor
+ * im aktuell aufgenommenen Bild des Untergrunds wahrnimmt
+ */
+uint8 maus_get_squal(void) {
+ return maus_sens_read(MOUSE_SQUAL_REG);
+}
+
+#endif
+#endif
diff --git a/source/ct-Bot/mcu/sensor-low.c b/source/ct-Bot/mcu/sensor-low.c
new file mode 100644
index 0000000..3e7d3a7
--- /dev/null
+++ b/source/ct-Bot/mcu/sensor-low.c
@@ -0,0 +1,229 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file sensor-low.c
+ * @brief Low-Level Routinen für die Sensor Steuerung des c't-Bots
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 01.12.05
+*/
+
+#ifdef MCU
+
+#include <avr/io.h>
+#include "adc.h"
+#include "global.h"
+
+#include "ena.h"
+#include "sensor.h"
+#include "mouse.h"
+#include "motor.h"
+#include "timer.h"
+#include "sensor_correction.h"
+#include "bot-logic/available_behaviours.h"
+#ifdef BEHAVIOUR_SERVO_AVAILABLE
+ #include "bot-logic/behaviour_servo.h"
+#endif
+
+// ADC-PINS
+#define SENS_ABST_L 0 /*!< ADC-PIN Abstandssensor Links */
+#define SENS_ABST_R 1 /*!< ADC-PIN Abstandssensor Rechts */
+#define SENS_M_L 2 /*!< ADC-PIN Liniensensor Links */
+#define SENS_M_R 3 /*!< ADC-PIN Liniensensor Rechts */
+#define SENS_LDR_L 4 /*!< ADC-PIN Lichtsensor Links */
+#define SENS_LDR_R 5 /*!< ADC-PIN Lichtsensor Rechts */
+#define SENS_KANTE_L 6 /*!< ADC-PIN Kantensensor Links */
+#define SENS_KANTE_R 7 /*!< ADC-PIN Kantensensor Rechts */
+
+// Sonstige Sensoren
+#define SENS_DOOR_PINR PIND /*!< Port an dem der Klappensensor hängt */
+#define SENS_DOOR_DDR DDRD /*!< DDR für den Klappensensor */
+#define SENS_DOOR 6 /*!< Pin an dem der Klappensensor hängt */
+
+#define SENS_ENCL_PINR PINB /*!< Port an dem der linke Encoder hängt */
+#define SENS_ENCL_DDR DDRB /*!< DDR für den linken Encoder */
+#define SENS_ENCL 4 /*!< Pin an dem der linke Encoder hängt */
+
+#define SENS_ENCR_PINR PIND /*!< Port an dem der rechte Encoder hängt */
+#define SENS_ENCR_DDR DDRD /*!< DDR für den rechten Encoder */
+#define SENS_ENCR 3 /*!< Pin an dem der rechte Encoder hängt */
+
+#define SENS_ERROR_PINR PINB /*!< Port an dem die Fehlerüberwachung hängt */
+#define SENS_ERROR_DDR DDRB /*!< DDR für die Fehlerüberwachung */
+#define SENS_ERROR 2 /*!< Pin an dem die Fehlerüberwachung hängt */
+
+#define SENS_TRANS_PINR PINB /*!< Port an dem die Transportfachueberwachung haengt */
+#define SENS_TRANS_PORT PORTB /*!< Port an dem die Transportfachueberwachung haengt */
+#define SENS_TRANS_DDR DDRB /*!< DDR für die Transportfachueberwachung */
+#define SENS_TRANS 0 /*!< Pin an dem die Transportfachueberwachung haengt */
+
+#define ENC_L ((SENS_ENCL_PINR >> SENS_ENCL) & 0x01) /*!< Abkuerzung zum Zugriff auf Encoder */
+#define ENC_R ((SENS_ENCR_PINR >> SENS_ENCR) & 0x01) /*!< Abkuerzung zum Zugriff auf Encoder */
+
+#define ENC_ENTPRELL 12 /*!< Nur wenn der Encoder ein paar mal den gleichen wert gibt uebernehmen */
+
+
+/*!
+ * Initialisiere alle Sensoren
+ */
+void bot_sens_init(void){
+ ENA_init();
+ adc_init(0xFF); // Alle ADC-Ports aktivieren
+
+ ENA_set(ENA_RADLED); // Alle Sensoren bis auf die Radencoder deaktivieren
+ ENA_on(ENA_ABSTAND); // Die Abstandssensoren ebenfalls dauerhaft an, da sie fast 50 ms zum booten brauchen
+
+ SENS_DOOR_DDR &= ~ (1<<SENS_DOOR); // Input
+
+ SENS_ENCL_DDR &= ~ (1<<SENS_ENCL); // Input
+ SENS_ENCR_DDR &= ~(1<<SENS_ENCR); // Input
+
+ SENS_ERROR_DDR &= ~(1<<SENS_ERROR); // Input
+
+ SENS_TRANS_DDR &= ~(1<<SENS_TRANS); // Input
+ SENS_TRANS_PORT |= (1<<SENS_TRANS); // Pullup an
+
+ SENS_ENCL_DDR &= ~(1<<SENS_ENCL); // Input
+ SENS_ENCR_DDR &= ~(1<<SENS_ENCR); // Input
+
+ timer_2_init();
+}
+
+
+/*!
+ * Alle Sensoren aktualisieren
+ * Derzeit pollt diese Routine alle Sensoren. Insbesondere bei den
+ * analogen dauert das eine Weile. Daher kann man hier einiges
+ * an Performance gewinnen, wenn man die Routine aufspaltet und
+ * zumindest die analogen Sensoren per Interrupt bearbeitet,
+ * denn im Moment blockiert adc_read so lange, bis ein Sensorwert ausgelesen ist.
+ * Die digitalen Sensoren liefern ihre Werte dagegen unmittelbar
+ * Aber Achtung es lohnt auch nicht, immer alles so schnell als moeglich
+ * zu aktualiseren, der Bot braucht auch Zeit zum nachdenken ueber Verhalten
+ */
+void bot_sens_isr(void){
+
+ ENA_on(ENA_KANTLED|ENA_MAUS|ENA_SCHRANKE|ENA_KLAPPLED);
+
+ #ifdef MAUS_AVAILABLE
+ // Aktualisiere die Position des Maussensors
+ sensMouseDX = maus_sens_read(MOUSE_DELTA_X_REG);
+ sensMouseDY = maus_sens_read(MOUSE_DELTA_Y_REG);
+
+ #endif
+
+ // ---------- analoge Sensoren -------------------
+ sensLDRL = adc_read(SENS_LDR_L);
+ sensLDRR = adc_read(SENS_LDR_R);
+
+ sensBorderL = adc_read(SENS_KANTE_L);
+ sensBorderR = adc_read(SENS_KANTE_R);
+ ENA_off(ENA_KANTLED);
+
+ sensLineL = adc_read(SENS_M_L);
+ sensLineR = adc_read(SENS_M_R);
+ ENA_off(ENA_MAUS);
+
+ // Aktualisiere Distanz-Sensoren
+ // Die Distanzsensoren sind im Normalfall an, da sie 50 ms zum booten brauchen
+ // Abfrage nur alle 100ms
+ static uint16 old_dist; // Zeit der letzten Messung der Distanzsensoren
+ static uint8 measure_count;
+ static int16 distLeft[3];
+ static int16 distRight[3];
+
+ register uint16 dist_ticks = TIMER_GET_TICKCOUNT_16;
+ if (dist_ticks-old_dist > MS_TO_TICKS(100)){
+ // Zeit fuer naechste Messung merken
+ old_dist=dist_ticks;
+
+ // wenn Kalibrierung gewuenscht, den Part Messen und Korrigieren kommentieren
+ // und Kalibrieren auskommentieren
+ // Kalibirieren
+ //distL=adc_read(SENS_ABST_L);
+ //distR=adc_read(SENS_ABST_R);
+
+ // Messwert merken
+ distLeft[measure_count]=adc_read(SENS_ABST_L);
+ #ifdef BEHAVIOUR_SERVO_AVAILABLE
+ if ((servo_active & SERVO1) == 0) // Wenn die Transportfachklappe bewegt wird, stimmt der Messwert des rechten Sensor nicht
+ #endif
+ distRight[measure_count]=adc_read(SENS_ABST_R);
+
+ measure_count++;
+ if (measure_count==3) measure_count=0;
+
+ // Schnittwert bilden
+ sensor_abstand((distLeft[0]+distLeft[1]+distLeft[2])/3,(distRight[0]+distRight[1]+distRight[2])/3);
+ }
+
+
+ // ------- digitale Sensoren ------------------
+ sensDoor = (SENS_DOOR_PINR >> SENS_DOOR) & 0x01;
+ sensTrans = (SENS_TRANS_PINR >> SENS_TRANS) & 0x01;
+ ENA_off(ENA_SCHRANKE|ENA_KLAPPLED);
+
+ sensError = (SENS_ERROR_PINR >> SENS_ERROR) & 0x01;
+
+ sensor_update(); // Weiterverarbeitung der rohen Sensordaten
+}
+
+/*!
+ * Kuemmert sich um die Radencoder
+ * Das muss schneller gehen als die anderen Sensoren,
+ * daher Update per Timer-Interrupt und nicht per Polling
+ */
+void bot_encoder_isr(void){
+ static uint8 enc_l=0; /*!< Puffer fuer die letzten Encoder-Staende */
+ static uint8 enc_r=0; /*!< Puffer fuer die letzten Encoder-Staende */
+ static uint8 enc_l_cnt=0; /*!< Entprell-Counter fuer L-Encoder */
+ static uint8 enc_r_cnt=0; /*!< Entprell-Counter fuer R-Encoder */
+ // --------------------- links ----------------------------
+ //Rad-Encoder auswerten
+ if ( ENC_L != enc_l){ // uns interesieren nur Veraenderungen
+ enc_l=ENC_L; // neuen wert sichern
+ enc_l_cnt=0; // Counter zuruecksetzen
+ } else { // Zaehlen, wie lange Pegel bleibt
+ if (enc_l_cnt <= ENC_ENTPRELL) // Nur bis zur Entprell-Marke
+ enc_l_cnt++;
+ }
+
+ if (enc_l_cnt == ENC_ENTPRELL){// wenn lange genug konst
+ if (direction.left == DIRECTION_FORWARD) // Drehrichtung beachten
+ sensEncL++; //vorwaerts
+ else
+ sensEncL--; //rueckwaerts
+ }
+
+ // --------------------- rechts ----------------------------
+ if (ENC_R != enc_r){ // uns interesieren nur Veraenderungen
+ enc_r=ENC_R; // neuen wert sichern
+ enc_r_cnt=0;
+ } else{ // Zaehlen, wie lange Pegel bleibt
+ if (enc_r_cnt <= ENC_ENTPRELL) // Nur bis zur Entprell-Marke
+ enc_r_cnt++;
+ }
+
+ if (enc_r_cnt == ENC_ENTPRELL){// wenn lange genug konst
+ if (direction.right == DIRECTION_FORWARD) // Drehrichtung beachten
+ sensEncR++; //vorwaerts
+ else
+ sensEncR--; //rueckwaerts
+ }
+}
+#endif
diff --git a/source/ct-Bot/mcu/shift.c b/source/ct-Bot/mcu/shift.c
new file mode 100644
index 0000000..735f3ac
--- /dev/null
+++ b/source/ct-Bot/mcu/shift.c
@@ -0,0 +1,93 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file shift.c
+ * @brief Routinen zur Ansteuerung der Shift-Register
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 20.12.05
+*/
+#include "global.h"
+#include "ct-Bot.h"
+
+#include "shift.h"
+
+#ifdef MCU
+#ifdef SHIFT_AVAILABLE
+
+#include <avr/io.h>
+#ifdef NEW_AVR_LIB
+ #include <util/delay.h>
+#else
+ #include <avr/delay.h>
+#endif
+
+
+#define SHIFT_OUT 0x1F /*!< Alle Pins die Ausgänge sind */
+#define SHIFT_PORT PORTC /*!< Port an dem die Register haengen */
+#define SHIFT_DDR DDRC /*!< DDR des Ports an dem die Register haengen */
+
+/*!
+ * Initialisert die Shift-Register
+ */
+void shift_init(){
+ SHIFT_DDR |= SHIFT_OUT; // Ausgänge Schalten
+ SHIFT_PORT &= ~SHIFT_OUT; // Und auf Null
+}
+
+/*!
+ * Schiebt Daten durch eines der drei 74HC595 Schieberegister
+ * Achtung den Port sollte man danach noch per shift_clear() zurücksetzen
+ * @param data Das Datenbyte
+ * @param latch_data der Pin an dem der Daten-latch-Pin des Registers (PIN 11) hängt
+ * @param latch_store der Pin an dem der latch-Pin zum transfer des Registers (PIN 12) hängt
+ */
+void shift_data_out(uint8 data, uint8 latch_data, uint8 latch_store){
+ int8 i;
+
+ SHIFT_PORT &= ~SHIFT_OUT; // und wieder clear
+ for (i=8; i>0; i--){
+ SHIFT_PORT |= ((data >> 7)& 0x01); // Das oberste Bit von data auf PC0.0 (Datenleitung Schieberegister)
+ SHIFT_PORT |= latch_data ; // und ins jeweilige Storageregister latchen
+ data= data << 1; // data links schieben
+ SHIFT_PORT &= ~SHIFT_OUT; // und wieder clear
+ }
+
+ SHIFT_PORT |= latch_store; // alles vom Storage ins Output register latchen
+}
+
+/*!
+ * Schiebt Daten durch eines der drei 74HC595 Schieberegister
+ * vereinfachte Version, braucht kein shift_clear()
+ * geht NICHT für das Shift-register, an dem das Display-hängt!!!
+ * @param data Das Datenbyte
+ * @param latch_data der Pin an dem der Daten-latch-Pin des Registers (PIN 11) hängt
+ */
+void shift_data(uint8 data, uint8 latch_data){
+ shift_data_out(data, latch_data, SHIFT_LATCH);
+ shift_clear();
+}
+
+/*!
+ * Setzt die Shift-Register wieder zurück
+ */
+void shift_clear(){
+ SHIFT_PORT &= ~SHIFT_OUT; // und wieder clear
+}
+#endif
+#endif
diff --git a/source/ct-Bot/mcu/srf10.c b/source/ct-Bot/mcu/srf10.c
new file mode 100644
index 0000000..ca5a4bb
--- /dev/null
+++ b/source/ct-Bot/mcu/srf10.c
@@ -0,0 +1,171 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file srf10.c
+ * @brief Ansteuerung des Ultraschall Entfernungssensors SRF10
+ * @author Carsten Giesen (info@cnau.de)
+ * @date 08.04.06
+*/
+#ifdef MCU
+#include <avr/io.h>
+#include "TWI_driver.h"
+#include "srf10.h"
+#include "delay.h"
+
+static uint8 address=SRF10_UNIT_0;
+
+/*!
+ * SRF10 initialsieren
+ */
+
+void srf10_init(void){
+ srf10_set_range(SRF10_MAX_RANGE);
+ //srf10_set_range(6); //Mit diesem Wert muss man spielen um das Optimum zu ermitteln
+return;
+}
+
+/*!
+ * Verstaerkungsfaktor setzen
+ * @param gain Verstaerkungsfaktor
+ */
+
+void srf10_set_gain(unsigned char gain){
+ if(gain>16) { gain=16; }
+
+ uint8 temp[2];
+ uint8 state;
+ tx_type tx_frame[2];
+
+ state = SUCCESS;
+
+ tx_frame[0].slave_adr = address+W;
+ tx_frame[0].size = 2;
+ tx_frame[0].data_ptr = temp;
+ tx_frame[0].data_ptr[0] = 1;
+ tx_frame[0].data_ptr[1] = gain;
+
+ tx_frame[1].slave_adr = OWN_ADR;
+
+ state = Send_to_TWI(tx_frame);
+}
+
+/*!
+ * Reichweite setzen, hat auch Einfluss auf die Messdauer
+ * @param millimeters Reichweite in mm
+ */
+
+void srf10_set_range(unsigned int millimeters){
+ uint8 temp[2];
+ uint8 state;
+ tx_type tx_frame[2];
+
+ state = SUCCESS;
+
+ millimeters= (millimeters/43);
+
+ tx_frame[0].slave_adr = address+W;
+ tx_frame[0].size = 2;
+ tx_frame[0].data_ptr = temp;
+ tx_frame[0].data_ptr[0] = 2;
+ tx_frame[0].data_ptr[1] = millimeters;
+
+ tx_frame[1].slave_adr = OWN_ADR;
+
+ state = Send_to_TWI(tx_frame);
+}
+
+/*!
+ * Messung ausloesen
+ * @param metric_unit 0x50 in Zoll, 0x51 in cm, 0x52 ms
+ * @return Resultat der Aktion
+ */
+
+uint8 srf10_ping(uint8 metric_unit){
+ uint8 temp[2];
+ uint8 state;
+ tx_type tx_frame[2];
+
+ state = SUCCESS;
+
+ tx_frame[0].slave_adr = address+W;
+ tx_frame[0].size = 2;
+ tx_frame[0].data_ptr = temp;
+ tx_frame[0].data_ptr[0] = SRF10_COMMAND;
+ tx_frame[0].data_ptr[1] = metric_unit;
+
+ tx_frame[1].slave_adr = OWN_ADR;
+
+ state = Send_to_TWI(tx_frame);
+
+ return state;
+}
+
+/*!
+ * Register auslesen
+ * @param srf10_register welches Register soll ausgelsen werden
+ * @return Inhalt des Registers
+ */
+
+uint8 srf10_read_register(uint8 srf10_register){
+ uint8 temp;
+ uint8 value;
+ uint8 state;
+ tx_type tx_frame[3];
+
+ state = SUCCESS;
+ value = 0;
+
+ tx_frame[0].slave_adr = address+W;
+ tx_frame[0].size = 1;
+ tx_frame[0].data_ptr = &temp;
+ tx_frame[0].data_ptr[0] = srf10_register;
+
+ tx_frame[1].slave_adr = address+R;
+ tx_frame[1].size = 1;
+ tx_frame[1].data_ptr = &value;
+
+ tx_frame[2].slave_adr = OWN_ADR;
+
+ state = Send_to_TWI(tx_frame);
+
+ return value;
+}
+
+/*!
+ * Messung starten Ergebniss aufbereiten und zurueckgeben
+ * @return Messergebniss
+ */
+
+uint16 srf10_get_measure(){
+ char hib;
+ char lob;
+ char state;
+
+ state = SUCCESS;
+
+ state = srf10_ping(SRF10_CENTIMETERS);
+ delay(10); //Optimierungs Potential
+ lob=srf10_read_register(SRF10_LOB);
+ delay(10); //Optimierungs Potential
+ hib=srf10_read_register(SRF10_HIB);
+
+ return (hib*256)+lob;
+}
+
+#endif
diff --git a/source/ct-Bot/mcu/timer-low.c b/source/ct-Bot/mcu/timer-low.c
new file mode 100644
index 0000000..f83bd1b
--- /dev/null
+++ b/source/ct-Bot/mcu/timer-low.c
@@ -0,0 +1,87 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file timer-low.c
+ * @brief Timer und counter für den Mikrocontroller
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+
+#ifdef MCU
+
+#include "ct-Bot.h"
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#ifndef NEW_AVR_LIB
+ #include <avr/signal.h>
+#endif
+
+
+#include "ct-Bot.h"
+
+#include "timer.h"
+#include "ir-rc5.h"
+#include "sensor-low.h"
+#include "bot-local.h"
+
+// ---- Timer 2 ------
+
+/*!
+ Interrupt Handler fuer Timer/Counter 2(A)
+ */
+#ifdef __AVR_ATmega644__
+ SIGNAL (TIMER2_COMPA_vect){
+#else
+ SIGNAL (SIG_OUTPUT_COMPARE2){
+#endif
+
+ /* - FERNBEDIENUNG - */
+ #ifdef IR_AVAILABLE
+ ir_isr();
+ #endif
+ /* ----- TIMER ----- */
+ tickCount.u32++; // TickCounter [176 us] erhoehen
+ /* --- RADENCODER --- */
+ bot_encoder_isr();
+}
+
+/*!
+ * initilaisiert Timer 0 und startet ihn
+ */
+void timer_2_init(void){
+ TCNT2 = 0x00; // TIMER vorladen
+
+ // aendert man den Prescaler muss man die Formel fuer OCR2 anpassen !!!
+ // Compare Register nur 8-Bit breit --> evtl. teiler anpassen
+ #ifdef __AVR_ATmega644__
+ TCCR2A = _BV(WGM21); // CTC Mode
+ TCCR2B = _BV(CS22); // Prescaler = CLK/64
+ OCR2A = ((XTAL/64/TIMER_2_CLOCK) - 1); // Timer2A
+ TIMSK2 |= _BV(OCIE2A); // TIMER2 Output Compare Match A Interrupt an
+ #else
+ // use CLK/64 prescale value, clear timer/counter on compare match
+ TCCR2 = _BV(WGM21) | _BV(CS22);
+ OCR2 = ((XTAL/64/TIMER_2_CLOCK) - 1);
+ TIMSK |= _BV(OCIE2); // enable Output Compare 0 overflow interrupt
+ #endif
+
+ sei(); // enable interrupts
+}
+#endif
diff --git a/source/ct-Bot/mcu/uart.c b/source/ct-Bot/mcu/uart.c
new file mode 100644
index 0000000..c9c36c6
--- /dev/null
+++ b/source/ct-Bot/mcu/uart.c
@@ -0,0 +1,206 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file uart.c
+ * @brief Routinen zur seriellen Kommunikation
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+
+#ifdef MCU
+
+#include "ct-Bot.h"
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#ifndef NEW_AVR_LIB
+ #include <avr/signal.h>
+#endif
+#include "ct-Bot.h"
+#include "uart.h"
+#include "command.h"
+#include "log.h"
+
+#ifdef UART_AVAILABLE
+
+#define BAUDRATE 57600
+
+#define UART_RX_BUFFER_SIZE 16 /*!< Größe des UART-Puffers */
+
+#define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1 )
+#if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
+ #error RX buffer size is not a power of 2
+#endif
+
+//#define UART_TIMEOUT 20000 /*!< Timeout. Wartet UART_TIMEOUT CPU-Takte */
+
+static uint8 UART_RxBuf[UART_RX_BUFFER_SIZE]; /*!< UART-Puffer */
+static volatile uint8 UART_RxHead; /*!< Zeiger für UART-Puffer */
+static volatile uint8 UART_RxTail; /*!< Zeiger für UART-Puffer */
+
+//char uart_timeout; /*!< 0, wenn uart_read/uart_send erfolgreich 1, wenn timeout erreicht */
+
+/*!
+ * Initialisiere UART
+ */
+void uart_init(void){
+ #ifdef __AVR_ATmega644__
+ /* Senden und Empfangen ermöglichen + RX Interrupt an */
+ UCSR0B= (1<<RXEN0) | (1<<TXEN0)|(1<<RXCIE0);
+ /* 8 Bit, 1 Stop, Keine Parity */
+ UCSR0C=0x86;
+ #else
+ /* Senden und Empfangen ermöglichen + RX Interrupt an */
+ UCSRB= (1<<RXEN) | (1<<TXEN)|(1<<RXCIE);
+ /* 8 Bit, 1 Stop, Keine Parity */
+ UCSRC=0x86;
+ #endif
+
+ /* UART auf 9600 baud */
+// UBRRH=0;
+// UBRRL= 103; /* Werte stehen im Datenblatt tabelarisch */
+ #ifdef __AVR_ATmega644__
+ UBRR0L = (uint8) (( ((uint32)F_CPU) / 16 / ((uint32)BAUDRATE) - 1) & 0xFF);
+ UBRR0H = (uint8) (( ((uint32)F_CPU) / 16 / ((uint32)BAUDRATE) - 1) >> 8);
+ #else
+ UBRRL = (uint8) (( ((uint32)F_CPU) / 16 / ((uint32)BAUDRATE) - 1) & 0xFF);
+ UBRRH = (uint8) (( ((uint32)F_CPU) / 16 / ((uint32)BAUDRATE) - 1) >> 8);
+ #endif
+
+ /* Puffer leeren */
+ UART_RxTail = 0;
+ UART_RxHead = 0;
+}
+
+/*!
+ * Interrupt Handler fuer den Datenempfang per UART
+ */
+#ifdef __AVR_ATmega644__
+ SIGNAL (USART0_RX_vect){
+#else
+ SIGNAL (SIG_UART_RECV){
+#endif
+
+ /* Pufferindex berechnen */
+ UART_RxHead++; /* erhoehen */
+ UART_RxHead %= UART_RX_BUFFER_MASK; /* Und bei Bedarf umklappen, da Ringpuffer */
+
+ if (UART_RxHead == UART_RxTail){
+ /* TODO Fehler behandeln !!
+ * ERROR! Receive buffer overflow */
+ }
+ #ifdef __AVR_ATmega644__
+ UART_RxBuf[UART_RxHead] = UDR0; /* Daten lesen und sichern*/
+ #else
+ UART_RxBuf[UART_RxHead] = UDR; /* Daten lesen und sichern*/
+ #endif
+}
+
+/*!
+ * Prüft, ob daten verfügbar
+ * @return Anzahl der verfuegbaren Bytes
+ */
+uint8 uart_data_available(void){
+ if (UART_RxHead == UART_RxTail) /* Puffer leer */
+ return 0;
+ else if (UART_RxHead > UART_RxTail) /* Schreibzeiger vor Lesezeiger */
+ return UART_RxHead - UART_RxTail;
+ else /* Schreibzeiger ist schon umgelaufen */
+ return UART_RxHead - UART_RxTail + UART_RX_BUFFER_SIZE;
+}
+
+
+/*!
+ * Überträgt ein Zeichen per UART
+ * Achtung ist noch blockierend!!!!
+ * TODO: umstellen auf nicht blockierend und mehr als ein Zeichen
+ * @param data Das Zeichen
+ */
+void uart_send_byte(uint8 data){ // Achtung ist noch blockierend!!!!
+ #ifdef __AVR_ATmega644__
+ while ((UCSR0A & _BV(UDRE0)) ==0){asm volatile("nop"); } // warten bis UART sendebereit
+ UDR0= data;
+ #else
+ while ((UCSRA & _BV(UDRE)) ==0){asm volatile("nop"); } // warten bis UART sendebereit
+ UDR= data;
+ #endif
+}
+
+/*!
+ * Sende Kommando per UART im Little Endian
+ * @param cmd Zeiger auf das Kommando
+ * @return Anzahl der gesendete Bytes
+ */
+//#define uart_send_cmd(cmd) uart_write(cmd,sizeof(command_t));
+
+/*
+int uart_send_cmd(command_t *cmd){
+ int i;
+ char * ptr = (char*) cmd;
+ for (i=0; i<sizeof(command_t); i++)
+ uart_send_byte(*ptr++);
+
+ return sizeof(command_t);
+}
+*/
+
+/*!
+ * Sende Daten per UART im Little Endian
+ * @param data Datenpuffer
+ * @param length Groesse des Datenpuffers in bytes
+ * @return Anzahl der gesendete Bytes
+ */
+int uart_write(uint8 * data, int length){
+ int i;
+ char * ptr = (char*) data;
+ for (i=0; i<length; i++)
+ uart_send_byte(*ptr++);
+
+ return length;
+}
+
+/*!
+ * Liest Zeichen von der UART
+ * @param data Der Zeiger an die die gelesenen Zeichen kommen
+ * @param length Anzahl der zu lesenden Bytes
+ * @return Anzahl der tatsaechlich gelesenen Zeichen
+ */
+int uart_read(void* data, int length){
+ uint8 i;
+ char* ptr = data;
+
+ uint8 count= uart_data_available();
+
+// LOG_DEBUG(("%d/%d av/sel",count,length));
+
+ if (count > length)
+ count=length;
+
+ for (i=0; i<count; i++){
+ UART_RxTail++;
+ UART_RxTail %= UART_RX_BUFFER_MASK;
+ *ptr++ = UART_RxBuf[UART_RxTail];
+
+ }
+
+ return count;
+}
+
+#endif
+#endif
diff --git a/source/ct-Bot/mmc-vm.c b/source/ct-Bot/mmc-vm.c
new file mode 100644
index 0000000..c8782c8
--- /dev/null
+++ b/source/ct-Bot/mmc-vm.c
@@ -0,0 +1,534 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*!
+ * @file mmc-vm.c
+ * @brief Virtual Memory Management mit MMC / SD-Card
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 30.11.2006
+ * @see Documentation/mmc-vm.html
+ */
+
+
+//TODO: * Statistikausgabe fuer MCU ergaenzen
+// * Code optimieren, Groesse und Speed
+
+#include "ct-Bot.h"
+
+#ifdef MMC_VM_AVAILABLE
+
+#include "mmc-vm.h"
+#include "mmc.h"
+#include "mmc-low.h"
+#include "mmc-emu.h"
+#include "display.h"
+#include "timer.h"
+#include "mini-fat.h"
+#include "log.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef MCU
+ #define MMC_START_ADDRESS 0x2000000 // [512;2^32-1] in Byte - Sinnvoll ist z.B. Haelfte der MMC / SD-Card Groesse, der Speicherplatz davor kann dann fuer ein Dateisystem verwendet werden
+ #define MAX_SPACE_IN_SRAM 6 // [1;127] - Pro Page werden 512 Byte im SRAM belegt, sobald diese verwendet wird
+ #define swap_out mmc_write_sector
+ #define swap_in mmc_read_sector
+ #define swap_space mmc_get_size()
+#else
+ #define MMC_START_ADDRESS 0x1000000 // [512;2^32-1]
+ #define MAX_SPACE_IN_SRAM 2 // [1;127] - Pro Page werden 512 Byte im RAM belegt, sobald diese verwendet wird
+ #define swap_out mmc_emu_write_sector
+ #define swap_in mmc_emu_read_sector
+ #define swap_space mmc_emu_get_size()
+#endif
+
+#if MMC_ASYNC_WRITE == 1
+ #define MAX_PAGES_IN_SRAM MAX_SPACE_IN_SRAM-1
+ static uint8* swap_buffer; /*!< Puffer fuer asynchrones write-back */
+#else
+ #define MAX_PAGES_IN_SRAM MAX_SPACE_IN_SRAM
+#endif
+
+typedef struct{ /*!< Struktur eines Cacheeintrags */
+ uint32 addr; /*!< Tag = MMC-Blockadresse der ins RAM geladenen Seite */
+ uint8* p_data; /*!< Daten = Zeiger auf 512 Byte grosse Seite im RAM */
+ #if MAX_PAGES_IN_SRAM > 2
+ uint8 succ; /*!< Zeiger auf Nachfolger (LRU) */
+ uint8 prec; /*!< Zeiger auf Vorgaenger (LRU) */
+ #endif
+ uint8 dirty; /*!< Dirty-Bit (0: Daten wurden bereits auf die MMC / SD-Card zurueckgeschrieben) */
+} vm_cache_t;
+
+#ifdef VM_STATS_AVAILABLE
+ typedef struct{
+ uint32 page_access; /*!< Anzahl der Seitenzugriffe seit Systemstart */
+ uint32 swap_ins; /*!< Anzahl der Seiteneinlagerungen seit Systemstart */
+ uint32 swap_outs; /*!< Anzahl der Seitenauslagerungen seit Systemstart */
+ uint32 vm_used_bytes; /*!< Anzahl der vom VM belegten Bytes auf der MMC / SD-Card */
+ uint32 time; /*!< Timestamp bei erster Speicheranforderung */
+ } vm_stats_t;
+
+ vm_stats_t stats_data = {0};
+#endif
+
+static uint32 mmc_start_address = MMC_START_ADDRESS; /*!< physische Adresse der MMC / SD-Card, wo unser VM beginnt */
+static uint32 next_mmc_address = MMC_START_ADDRESS; /*!< naechste freie virtuelle Adresse */
+static uint8 pages_in_sram = MAX_PAGES_IN_SRAM; /*!< Groesse des Caches im RAM */
+static int8 allocated_pages = 0; /*!< Anzahl bereits belegter Cachebloecke */
+static uint8 oldest_cacheblock = 0; /*!< Zeiger auf den am laengsten nicht genutzten Eintrag (LRU) */
+static uint8 recent_cacheblock = 0; /*!< Zeiger auf den letzten genutzten Eintrag (LRU) */
+
+vm_cache_t page_cache[MAX_PAGES_IN_SRAM]; /*!< der eigentliche Cache, vollassoziativ, LRU-Policy */
+
+/*!
+ * Gibt die Blockadresse einer Seite zurueck
+ * @param addr Eine virtuelle Adresse
+ * @return Adresse
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 30.11.2006
+ */
+inline uint32 mmc_get_mmcblock_of_page(uint32 addr){
+ #ifdef MCU
+ /* Eine effizientere Variante von addr >> 9 */
+ asm volatile(
+ "mov %A0, %B0 \n\t"
+ "mov %B0, %C0 \n\t"
+ "mov %C0, %D0 \n\t"
+ "lsr %C0 \n\t"
+ "ror %B0 \n\t"
+ "ror %A0 \n\t"
+ "clr %D0 "
+ : "=r" (addr)
+ : "0" (addr)
+ );
+ return addr;
+ #else
+ return addr >> 9;
+ #endif // MCU
+}
+
+#ifdef VM_STATS_AVAILABLE
+ /*!
+ * Gibt die Anzahl der Pagefaults seit Systemstart bzw. Ueberlauf zurueck
+ * @return #Pagefaults
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 30.11.2006
+ */
+ inline uint32 mmc_get_pagefaults(void){
+ return stats_data.swap_ins;
+ }
+
+ /*!
+ * Erstellt eine kleine Statistik ueber den VM
+ * @return Zeiger auf Statistikdaten
+ * @date 01.01.2007
+ */
+ vm_extern_stats_t* mmc_get_vm_stats(void){
+ static vm_extern_stats_t extern_stats = {0};
+ memcpy(&extern_stats, &stats_data, sizeof(vm_stats_t)); // .time wird spaeter ueberschrieben
+ uint16 delta_t = TICKS_TO_MS(TIMER_GET_TICKCOUNT_32 - stats_data.time)/1000;
+ if (delta_t == 0) delta_t = 1;
+ extern_stats.page_access_s = extern_stats.page_access / delta_t;
+ extern_stats.swap_ins_s = extern_stats.swap_ins / delta_t;
+ extern_stats.swap_outs_s = extern_stats.swap_outs / delta_t;
+ extern_stats.device_size = swap_space;
+ extern_stats.vm_size = swap_space - mmc_start_address;
+ extern_stats.cache_size = pages_in_sram;
+ extern_stats.cache_load = allocated_pages;
+ extern_stats.delta_t = delta_t;
+ return &extern_stats;
+ }
+
+ /*!
+ * Gibt eine kleine Statistik ueber den VM aus (derzeit nur am PC)
+ * @date 01.01.2007
+ */
+ void mmc_print_statistic(void){
+ #ifdef PC
+ vm_extern_stats_t* vm_stats = mmc_get_vm_stats();
+ printf("\n\r*** VM-Statistik *** \n\r");
+ printf("Groesse des Volumes: \t\t%lu MByte \n\r", vm_stats->device_size>>20);
+ printf("Groesse des VM: \t\t%lu MByte \n\r", vm_stats->vm_size>>20);
+ printf("Belegter virt. Speicher: \t%lu KByte \n\r", vm_stats->vm_used_bytes>>10);
+ printf("Groesse des Caches: \t\t%u Byte \n\r", (uint16)vm_stats->cache_size<<9);
+ printf("Auslastung des Caches: \t\t%u %% \n\r", ((uint16)vm_stats->cache_load<<9)/((uint16)vm_stats->cache_size<<9)*100);
+ printf("Seitenzugriffe: \t\t%lu \n\r", vm_stats->page_access);
+ printf("Seiteneinlagerungen: \t\t%lu \n\r", vm_stats->swap_ins);
+ printf("Seitenauslagerungen: \t\t%lu \n\r", vm_stats->swap_outs);
+ printf("Seitenzugriffe / s: \t\t%u \n\r", vm_stats->page_access_s);
+ printf("Seiteneinlagerungen / s: \t%u \n\r", vm_stats->swap_ins_s);
+ printf("Seitenauslagerungen / s: \t%u \n\r", vm_stats->swap_outs_s);
+ printf("Cache-Hit-Rate: \t\t%f %% \n\r", (100.0-((float)vm_stats->swap_ins/(float)vm_stats->page_access)*100.0));
+ printf("Messdauer: \t\t\t%u s \n\r", vm_stats->delta_t);
+ #else
+ /* Ausgabe fuer MCU derzeit nur ueber Logging */
+ #ifdef LOG_AVAILABLE
+ vm_extern_stats_t* vm_stats = mmc_get_vm_stats();
+ /* Texte wie oben */
+ LOG_INFO(("%lu", vm_stats->device_size>>20));
+ LOG_INFO(("%lu", vm_stats->vm_size>>20));
+ LOG_INFO(("%lu", vm_stats->vm_used_bytes>>10));
+ LOG_INFO(("%u", (uint16)vm_stats->cache_size<<9));
+ LOG_INFO(("%u", ((uint16)vm_stats->cache_load<<9)/((uint16)vm_stats->cache_size<<9)*100));
+ LOG_INFO(("%lu", vm_stats->page_access));
+ LOG_INFO(("%lu", vm_stats->swap_ins));
+ LOG_INFO(("%lu", vm_stats->swap_outs));
+ LOG_INFO(("%u", vm_stats->page_access_s));
+ LOG_INFO(("%u", vm_stats->swap_ins_s));
+ LOG_INFO(("%u", vm_stats->swap_outs_s));
+ LOG_INFO(("%u", (uint8)(100.0-((float)vm_stats->swap_ins/(float)vm_stats->page_access)*100.0)));
+ LOG_INFO(("%u", vm_stats->delta_t));
+ #endif
+ // TODO: Display-Ausgabe?
+ #endif
+ }
+#endif
+
+/*!
+ * Gibt die letzte Adresse einer Seite zurueck
+ * @param addr Eine virtuelle Adresse
+ * @return Adresse
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 30.11.2006
+ */
+inline uint32 mmc_get_end_of_page(uint32 addr){
+ return addr | 0x1ff; // die unteren 9 Bit sind gesetzt, da Blockgroesse = 512 Byte
+}
+
+/*!
+ * Gibt den Index einer Seite im Cache zurueck
+ * @param addr Eine virtuelle Adresse
+ * @return Index des Cacheblocks, -1 falls Cache-Miss
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 30.11.2006
+ */
+int8 mmc_get_cacheblock_of_page(uint32 addr){
+ uint32 page_addr = mmc_get_mmcblock_of_page(addr);
+ int8 i;
+ for (i=0; i<allocated_pages; i++){ // O(n)
+ if (page_cache[i].addr == page_addr) return i; // Seite gefunden :)
+ }
+ return -1; // Seite nicht im Cache
+}
+
+/*!
+ * Laedt eine Seite in den Cache, falls sie noch nicht geladen ist
+ * @param addr Eine virtuelle Adresse
+ * @return 0: ok, 1: ungueltige Adresse, 2: Fehler bei swap_out, 3: Fehler bei swap_in
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 30.11.2006
+ */
+uint8 mmc_load_page(uint32 addr){
+ if (addr >= next_mmc_address) return 1; // ungueltige virtuelle Adresse :(
+ #ifdef VM_STATS_AVAILABLE
+ stats_data.page_access++;
+ #endif
+ int8 cacheblock = mmc_get_cacheblock_of_page(addr);
+ if (cacheblock >= 0){ // Cache-Hit, Seite ist bereits geladen :)
+ /* LRU */
+ #if MAX_PAGES_IN_SRAM > 2
+ if (recent_cacheblock == cacheblock) page_cache[cacheblock].succ = cacheblock; // Nachfolger des neuesten Eintrags ist die Identitaet
+ if (oldest_cacheblock == cacheblock){
+ oldest_cacheblock = page_cache[cacheblock].succ; // Nachfolger ist neuer aeltester Eintrag
+ page_cache[page_cache[cacheblock].succ].prec = oldest_cacheblock; // Vorgaenger der Nachfolgers ist seine Identitaet
+ }
+ else{
+ page_cache[page_cache[cacheblock].prec].succ = page_cache[cacheblock].succ; // Nachfolger des Vorgaengers ist eigener Nachfolger
+ page_cache[page_cache[cacheblock].succ].prec = page_cache[cacheblock].prec; // Vorganeger des Nachfolgers ist eigener Vorgaenger
+ }
+ page_cache[cacheblock].prec = recent_cacheblock; // alter neuester Eintrag ist neuer Vorgaenger
+ #else
+ oldest_cacheblock = (pages_in_sram - 1) - cacheblock; // aeltester Eintrag ist nun der andere Cacheblock (wenn verfuegbar)
+ #endif
+ recent_cacheblock = cacheblock; // neuester Eintrag ist nun die Identitaet
+ return 0;
+ }
+ /* Cache-Miss => neue Seite einlagern, LRU Policy */
+ int8 next_cacheblock = oldest_cacheblock;
+ if (allocated_pages < pages_in_sram){
+ /* Es ist noch Platz im Cache */
+ next_cacheblock = allocated_pages;
+ page_cache[next_cacheblock].p_data = malloc(512); // Speicher anfordern
+ if (page_cache[next_cacheblock].p_data == NULL){ // Da will uns jemand keinen Speicher mehr geben :(
+ if (pages_in_sram == 1) return 1; // Hier ging was schief, das wir so nicht loesen koennen
+ /* Nicht mehr genug Speicher im RAM frei => neuer Versuch mit verkleinertem Cache */
+ pages_in_sram--;
+ return mmc_load_page(addr);
+ }
+ allocated_pages++; // Cache-Fuellstand aktualisieren
+ }
+ /* Pager muss nun aktiv werden */
+ #ifdef VM_STATS_AVAILABLE
+ stats_data.swap_ins++;
+ #endif
+ #if MMC_ASYNC_WRITE == 1 // im asnychronen Fall holen wir erst die neue Seite, dann kann sich das Zurueckschreiben ruhig Zeit lassen
+ uint8* p_tmp = page_cache[next_cacheblock].p_data;
+ if (swap_in(mmc_get_mmcblock_of_page(addr), swap_buffer) != 0) return 3;
+ #endif
+ if (page_cache[next_cacheblock].dirty == 1){ // Seite zurueckschreiben, falls Daten veraendert wurden
+ #ifdef VM_STATS_AVAILABLE
+ stats_data.swap_outs++;
+ #endif
+ if (swap_out(page_cache[next_cacheblock].addr, page_cache[next_cacheblock].p_data, MMC_ASYNC_WRITE) != 0) return 2;
+ }
+ #if MMC_ASYNC_WRITE == 1
+ page_cache[next_cacheblock].p_data = swap_buffer;
+ swap_buffer = p_tmp;
+ #else
+ if (swap_in(mmc_get_mmcblock_of_page(addr), page_cache[next_cacheblock].p_data) != 0) return 3;
+ #endif
+ #if MAX_PAGES_IN_SRAM > 2
+ oldest_cacheblock = page_cache[oldest_cacheblock].succ; // Nachfolger des aeltesten Eintrags ist neuer aeltester Eintrag
+ #else
+ oldest_cacheblock = (pages_in_sram - 1) - next_cacheblock; // neuer aeltester Eintrag ist nun der andere Cacheblock (wenn verfuegbar)
+ #endif
+ page_cache[next_cacheblock].addr = mmc_get_mmcblock_of_page(addr); // Cache-Tag aktualisieren
+ /* LRU */
+ #if MAX_PAGES_IN_SRAM > 2
+ page_cache[next_cacheblock].prec = recent_cacheblock; // Vorgaenger dieses Cacheblocks ist der bisher neueste Eintrag
+ page_cache[recent_cacheblock].succ = next_cacheblock; // Nachfolger des bisher neuesten Eintrags ist dieser Cacheblock
+ #endif
+ recent_cacheblock = next_cacheblock; // Dieser Cacheblock ist der neueste Eintrag
+ return 0;
+}
+
+/*!
+ * Fordert virtuellen Speicher an
+ * @param size Groesse des gewuenschten Speicherblocks
+ * @param aligned 0: egal, 1: 512 Byte ausgerichtet
+ * @return Virtuelle Anfangsadresse des angeforderten Speicherblocks, 0 falls Fehler
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 30.11.2006
+ */
+uint32 mmcalloc(uint32 size, uint8 aligned){
+ if (next_mmc_address == mmc_start_address){
+ // TODO: Init-stuff here (z.B. FAT einlesen)
+ /* Inits */
+ if (mmc_start_address > swap_space){
+ mmc_start_address = swap_space-512;
+ next_mmc_address = mmc_start_address;
+ }
+ #if MMC_ASYNC_WRITE == 1
+ swap_buffer = malloc(512);
+ #endif
+ #ifdef VM_STATS_AVAILABLE
+ stats_data.time = TIMER_GET_TICKCOUNT_32;
+ #endif
+ }
+ uint32 start_addr;
+ if (aligned == 0 || mmc_get_end_of_page(next_mmc_address) == mmc_get_end_of_page(next_mmc_address+size-1)){
+ /* Daten einfach an der naechsten freien virtuellen Adresse speichern */
+ start_addr = next_mmc_address;
+ } else {
+ /* Rest der letzten Seite ueberspringen und Daten in neuem Block speichern */
+ start_addr = mmc_get_end_of_page(next_mmc_address) + 1;
+ }
+ if (start_addr+size > swap_space) return 0; // wir haben nicht mehr virtuellen Speicher als Platz auf dem Swap-Device
+ /* interne Daten aktualisieren */
+ next_mmc_address = start_addr + size;
+ #ifdef VM_STATS_AVAILABLE
+ stats_data.vm_used_bytes = next_mmc_address-mmc_start_address;
+ #endif
+ return start_addr;
+}
+
+/*!
+ * Gibt einen Zeiger auf einen Speicherblock im RAM zurueck
+ * @param addr Eine virtuelle Adresse
+ * @return Zeiger auf uint8, NULL falls Fehler
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 30.11.2006
+ */
+uint8* mmc_get_data(uint32 addr){
+ /* Seite der gewuenschten Adresse laden */
+ if (mmc_load_page(addr) != 0) return NULL;
+ int8 cacheblock = mmc_get_cacheblock_of_page(addr);
+ page_cache[cacheblock].dirty = 1; // Daten sind veraendert
+ /* Zeiger auf Adresse in gecacheter Seite laden / berechnen und zurueckgeben */
+ return page_cache[cacheblock].p_data + (addr - (mmc_get_mmcblock_of_page(addr)<<9)); // TODO: 2. Summanden schlauer berechnen
+}
+
+/*!
+ * Erzwingt das Zurueckschreiben einer eingelagerten Seite auf die MMC / SD-Card
+ * @param addr Eine virtuelle Adresse
+ * @return 0: ok, 1: Seite zurzeit nicht eingelagert, 2: Fehler beim Zurueckschreiben
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 15.12.2006
+ */
+uint8 mmc_page_write_back(uint32 addr){
+ int8 cacheblock = mmc_get_cacheblock_of_page(addr);
+ if (cacheblock < 0) return 1; // Seite nicht eingelagert
+ if (swap_out(page_cache[cacheblock].addr, page_cache[cacheblock].p_data, MMC_ASYNC_WRITE) != 0) return 2; // Seite (evtl. asynchron) zurueckschreiben
+ page_cache[cacheblock].dirty = 0; // Dirty-Bit zuruecksetzen
+ return 0;
+}
+
+/*!
+ * Schreibt alle eingelagerten Seiten auf die MMC / SD-Card zurueck
+ * @return 0: alles ok, sonst: Summe der Fehler beim Zurueckschreiben
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 21.12.2006
+ */
+uint8 mmc_flush_cache(void){
+ uint8 i;
+ uint8 result=0;
+ for (i=0; i<allocated_pages; i++){
+ if (page_cache[i].dirty == 1){
+ if (page_cache[i].addr < mmc_get_mmcblock_of_page(swap_space))
+ result += swap_out(page_cache[i].addr, page_cache[i].p_data, 0); // synchrones Zurueckschreiben
+ page_cache[i].dirty = 0;
+ }
+ }
+ return result;
+}
+
+/*!
+ * Oeffnet eine Datei im FAT16-Dateisystem auf der MMC / SD-Card und gibt eine virtuelle Adresse zurueck,
+ * mit der man per mmc_get_data() einen Pointer auf die gewuenschten Daten bekommt. Das Ein- / Auslagern
+ * macht das VM-System automatisch. Der Dateiname muss derzeit am Amfang in der Datei stehen.
+ * Achtung: Irgendwann muss man die Daten per mmc_flush_cache() oder mmc_page_write_back() zurueckschreiben!
+ * @param filename Dateiname als 0-terminierter String
+ * @return Virtuelle Anfangsadresse der angeforderten Datei, 0 falls Fehler
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 21.12.2006
+ */
+uint32 mmc_fopen(const char *filename){
+ uint32 block;
+ /* Pufferspeicher organisieren */
+ uint32 v_addr = mmcalloc(512, 0);
+ uint8* p_data = mmc_get_data(v_addr); // hier speichern wir im Folgenden den ersten Block der gesuchten Datei, der ist dann gleich im Cache ;)
+ /* Die Dateiadressen liegen ausserhalb des Bereichs fuer den VM, also interne Datenanpassungen hier rueckgaengig machen */
+ next_mmc_address -= 512;
+ #ifdef VM_STATS_AVAILABLE
+ stats_data.vm_used_bytes -= 512;
+ #endif
+ uint8 i;
+ #ifdef MCU // Debug-Info ausgeben
+ #ifdef DISPLAY_AVAILABLE
+ display_cursor(2,1);
+ display_printf("Find %s: 0x",filename);
+ uint16 k=0, j=0;
+ #endif
+ #else
+ printf("Find %s...",filename);
+ uint16 k=0, j=0;
+ #endif
+ /* MMC-Block suchen zwischen Kartenanfang und VM-Startadresse (<= Kartengroesse) */
+ for (block=0; block<mmc_get_mmcblock_of_page(mmc_start_address); block++){
+ #ifdef MCU // Debug-Info ausgeben
+ #ifdef DISPLAY_AVAILABLE
+ display_cursor(2,13);
+ display_printf("%02x%04x", j, k);
+ if (k==65535) j++;
+ k++;
+ #endif
+ #else
+// printf(".");
+// fflush(stdout);
+ #endif
+ if (swap_in(block, p_data) != 0) break; // Abbrechen, falls Fehler
+ /* Blockanfang mit Dateinamen vergleichen */
+ for (i=0; i<MMC_FILENAME_MAX; i++){
+ if (filename[i] == '\0'){
+ if (swap_in(++block, p_data) != 0) break; // Ersten Sektor der Datei ueberspringen, dort stehen interne Daten
+ page_cache[mmc_get_cacheblock_of_page(v_addr)].addr = block; // Cache-Tag auf gefundene Datei umbiegen
+ #ifdef MCU
+ #ifdef DISPLAY_AVAILABLE
+ k = block & 0xFFFF;
+ j = (block >> 16) & 0xFFFF;
+ display_cursor(2,1);
+ display_printf("Found %s: 0x%02x%04x",filename,j,k);
+ #endif
+ #else
+ k = block & 0xFFFF;
+ j = (block >> 16) & 0xFFFF;
+ printf("\n\rFound %s: 0x%02x%04x \n\r",filename,j,k);
+ #endif
+ return block<<9; // gesuchte Datei beginnt hier :)
+ }
+ if (filename[i] != p_data[i]) break; // gesuchte Datei beginnt nicht in diesem Block
+ }
+ }
+ /* Suche erfolglos, aber der Cache soll konsistent bleiben */
+ // TODO: ordentlich aufraeumen im Fehlerfall!
+ page_cache[mmc_get_cacheblock_of_page(v_addr)].addr = 0x800000; // Diesen Sektor gibt es auf keiner Karte <= 4 GB
+ page_cache[mmc_get_cacheblock_of_page(v_addr)].dirty = 0; // HackHack, aber so wird der ungueltige Inhalt beim Pagefault niemals versucht auf die Karte zu schreiben
+ #ifdef MCU
+ #ifdef DISPLAY_AVAILABLE
+ display_cursor(2,1);
+ display_printf("%s not found ",filename);
+ #endif
+ #else
+ printf("\n\r%s not found \n\r",filename);
+ #endif
+ return 0; // Datei nicht gefunden :(
+}
+
+/*!
+ * Liest die Groesse einer Datei im FAT16-Dateisystem auf der MMC / SD-Card aus, die zu zuvor mit
+ * mmc_fopen() geoeffnet wurde.
+ * @param file_start (virtuelle Anfangsadresse der Datei)
+ * @return Groesse der Datei in Byte
+ * @date 12.01.2007
+ */
+uint32 mmc_get_filesize(uint32 file_start){
+ file_len_t length;
+ uint8* p_addr = mmc_get_data(file_start-512);
+ /* Dateilaenge aus Block 0, Byte 256 bis 259 der Datei lesen */
+ uint8 i;
+ for (i=0; i<4; i++)
+ length.u8[i] = p_addr[259-i];
+ return length.u32;
+}
+
+/*!
+ * Leert eine Datei im FAT16-Dateisystem auf der MMC / SD-Card, die zuvor mit mmc_fopen() geoeffnet wurde.
+ * @param file_start (virtuelle) Anfangsadresse der Datei
+ * @return 0: ok, 1: ungueltige Datei oder Laenge, 2: Fehler beim Schreiben
+ * @date 02.01.2007
+ */
+uint8 mmc_clear_file(uint32 file_start){
+ #ifdef PC
+ printf("Start of file: %lu \n\r", file_start);
+ #endif
+ uint32 length = mmc_get_filesize(file_start);
+ if (file_start == 0 || file_start + length >= mmc_start_address) return 1; // Datei existiert nicht oder Laenge ist ungueltig
+ /* Ersten Block der Datei laden (dessen Speicherbereich benutzen wir einfach als 0-Puffer) */
+ uint8* p_addr = mmc_get_data(file_start);
+ memset(p_addr, 0, 512); // leeren Puffer erzeugen
+ /* Alle Bloecke der Datei mit dem 0-Puffer ueberschreiben */
+ int8 cache_block;
+ uint32 addr;
+ for (addr=file_start; addr<file_start+length; addr+=512){
+ if (swap_out(mmc_get_mmcblock_of_page(addr), p_addr, 0) != 0) return 2;
+ /* Falls ein Block der Datei im Cache ist, auch diesen leeren */
+ cache_block = mmc_get_cacheblock_of_page(addr);
+ if (cache_block >= 0){
+ memset(page_cache[cache_block].p_data, 0, 512);
+ page_cache[cache_block].dirty = 0;
+ }
+ }
+ #ifdef PC
+ printf("End of file: %lu \n\r", addr);
+ #endif
+ return 0;
+}
+
+#endif // MMC_VM_AVAILABLE
diff --git a/source/ct-Bot/motor.c b/source/ct-Bot/motor.c
new file mode 100644
index 0000000..ce62d97
--- /dev/null
+++ b/source/ct-Bot/motor.c
@@ -0,0 +1,268 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file motor.c
+ * @brief High-Level-Routinen fuer die Motorsteuerung des c't-Bot
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 15.01.05
+*/
+
+#include <stdlib.h>
+#include "global.h"
+#include "ct-Bot.h"
+#include "motor.h"
+#include "bot-local.h"
+#include "motor-low.h"
+#include "timer.h"
+#include "sensor.h"
+#include "display.h"
+
+int16 speed_l=0; /*!< Geschwindigkeit linker Motor */
+int16 speed_r=0; /*!< Geschwindigkeit rechter Motor */
+
+direction_t direction; /*!< Drehrichtung der Motoren */
+
+#define PWMMAX 255 /*!< Maximaler PWM-Wert */
+#define PWMMIN 0 /*!< Minimaler PWM-Wert */
+
+#ifdef SPEED_CONTROL_AVAILABLE
+ int8 encoderTargetRateL=0;
+ int8 encoderTargetRateR=0;
+
+ /*!
+ * @brief Drehzahlregelung fuer die Motoren des c't-Bots
+ * @author Benjamin Benz (bbe@heise.de
+ * @date 01.05.06
+ * Getrennte Drehzahlregelung fuer linken und rechten Motor sorgt fuer konstante Drehzahl und somit annaehernd
+ * fuer Geradeauslauf
+ * Feintuning von Kp, Ki, Kd verbessert die Genauigkeit und Schnelligkeit der Regelung
+ * Querkopplung der Motoren verbessert Gleichlauf, beispielsweise x*(sensEncL - sensEncR)
+ * in jeden Regler einbauen
+ */
+ void speed_control(void){
+ int8 Kp=0;
+ int8 Ki=0;
+
+ int16 StellwertL=motor_left; /*!< Stellwert links*/
+ int16 StellwertR=motor_right; /*!< Stellwert rechts*/
+
+ static int16 lastEncoderL=0; /*!< vorhergehender Wert von sensEncL */
+ static int8 lastErrL=0; /*!< letzter Drehzahlfehler links */
+ static int8 last2ErrL=0; /*!< vorletzter Drehzahlfehler links */
+
+ static int16 lastEncoderR=0; /*!< vorhergehender Wert von sensEncR */
+ static int8 lastErrR=0; /*!< letzter Drehzahlfehler rechts */
+ static int8 last2ErrR=0; /*!< vorletzter Drehzahlfehler rechts */
+
+ int16 err=0; // aktuelle Abweichung vom Soll-Wert
+ int16 encoderRate=0; // IST-Wert [Encoder-ticks/Aufruf]
+
+
+ // Wir arbeiten mit verschiedenen PID-Parametern fuer verschiedene Geschwindigkeitsabschnitte
+ if (encoderTargetRateL <= PID_LOW_RATE){
+ Kp=PID_LOW_Kp;
+ Ki=PID_LOW_Ki;
+ } else {
+ if (encoderTargetRateL >= PID_HIGH_RATE) {
+ Kp=PID_HIGH_Kp;
+ Ki=PID_HIGH_Ki;
+ } else {
+ Kp=(PID_HIGH_Kp+PID_LOW_Kp)/2;
+ Ki=(PID_HIGH_Ki+PID_LOW_Ki)/2;
+ }
+ }
+
+
+
+ //Regler links
+ if (encoderTargetRateL == 0){
+ StellwertL=0;
+ err=0; lastErrL = 0;
+ } else {
+ encoderRate = sensEncL-lastEncoderL; // aktuelle Ist-Wert berechnen [Encoder-ticks/aufruf]
+ lastEncoderL = sensEncL; // Anzahl der Encoderpulse merken fuer naechsten Aufruf merken
+ err = encoderTargetRateL - encoderRate; // Regelabweichung links
+
+ // Stellwert Berechnen
+ StellwertL += (Kp * (err - lastErrL)) / 10; // P-Beitrag
+ StellwertL += (Ki * (err + lastErrL)/2 ) /10; // I-Beitrag
+ // StellwertL += Kd * (errL - 2 * lastErrL + last2ErrL); // D-Beitrag
+
+ //berechneten Stellwert auf zulaessige Groesse begrenzen
+ if (StellwertL > PWMMAX) StellwertL = PWMMAX;
+ if (StellwertL < -PWMMAX) StellwertL = -PWMMAX;
+
+ #ifdef DISPLAY_REGELUNG_AVAILABLE
+ if (display_screen==DISPLAY_REGELUNG_AVAILABLE){
+ display_cursor(1,1);
+ display_printf("%03d/%03d ",encoderRate,encoderTargetRateL);
+ display_cursor(2,1);
+ display_printf("e =%03d ",err);
+ display_cursor(3,1);
+ display_printf("L =%04d ", StellwertL);
+ }
+ #endif
+ }
+
+ last2ErrL = lastErrL; // alten N-2 Fehler merken
+ lastErrL = err; // alten N-1 Fehler merken
+
+
+ //Regler rechts
+ if (encoderTargetRateR == 0){
+ StellwertR=0;
+ err=0; lastErrR=0;
+ } else {
+ encoderRate = sensEncR-lastEncoderR; // aktuelle Ist-Wert berechnen [Encoder-ticks/aufruf]
+ lastEncoderR = sensEncR; // Anzahl der Encoderpulse merken fuer naechsten Aufruf merken
+ err = encoderTargetRateR - encoderRate; // Regelabweichung links
+
+ // Stellwert Berechnen
+ StellwertR += (Kp * (err - lastErrR))/10; // P-Beitrag
+ StellwertR += (Ki * (err + lastErrR)/2)/10; // I-Beitrag
+ // StellwertR += Kd * (err - 2 * lastErrR + last2ErrR); // D-Beitrag
+
+ //berechneten Stellwert auf zulaessige Groesse begrenzen
+ if (StellwertR > PWMMAX) StellwertR = PWMMAX;
+ if (StellwertR < -PWMMAX) StellwertR = -PWMMAX;
+
+ #ifdef DISPLAY_REGELUNG_AVAILABLE
+ if (display_screen==DISPLAY_REGELUNG_AVAILABLE){
+ display_cursor(1,10);
+ display_printf("%03d/%03d ",encoderRate,encoderTargetRateR);
+ display_cursor(2,10);
+ display_printf("e =%03d ",err);
+ display_cursor(3,10);
+ display_printf("R =%04d ", StellwertR);
+ }
+ #endif
+ }
+
+ last2ErrR = lastErrR; // alten N-2 Fehler merken
+ lastErrR = err; // alten N-1 Fehler merken
+
+ #ifdef DISPLAY_REGELUNG_AVAILABLE
+ if (display_screen==DISPLAY_REGELUNG_AVAILABLE){
+ display_cursor(4,1);
+ display_printf("Kp=%03d Ki=%03d", Kp, Ki);
+ }
+ #endif
+
+ // Und nun den Wert setzen
+ bot_motor(StellwertL,StellwertR);
+ }
+#endif
+
+/*!
+ * Direkter Zugriff auf den Motor
+ * @param left Geschwindigkeit fuer den linken Motor
+ * @param right Geschwindigkeit fuer den linken Motor
+ * Geschwindigkeit liegt zwischen -255 und +255.
+ * 0 bedeutet Stillstand, 255 volle Kraft voraus, -255 volle Kraft zurueck.
+ * Sinnvoll ist die Verwendung der Konstanten: BOT_SPEED_XXX,
+ * also z.B. motor_set(BOT_SPEED_LOW,-BOT_SPEED_LOW);
+ * fuer eine langsame Drehung
+*/
+void motor_set(int16 left, int16 right){
+ #ifdef SPEED_CONTROL_AVAILABLE
+ static int16 old_mot_ticks=0;
+ #endif
+
+ if (left == BOT_SPEED_IGNORE)
+ left=BOT_SPEED_STOP;
+
+ if (right == BOT_SPEED_IGNORE)
+ right=BOT_SPEED_STOP;
+
+
+ // Haben wir ueberhaupt etwas zu tun?
+ if ((speed_l == left) && (speed_r == right)){
+ // Hier sitzt die eigentliche Regelung
+ #ifdef SPEED_CONTROL_AVAILABLE
+ register uint16 ticks = TIMER_GET_TICKCOUNT_16;
+ if (ticks-old_mot_ticks > MS_TO_TICKS((uint16)SPEED_CONTROL_INTERVAL)) {
+ speed_control();
+ old_mot_ticks = TIMER_GET_TICKCOUNT_16;
+ }
+ #endif
+ return; // Keine Aenderung? Dann zuerueck
+ }
+
+ if (abs(left) > BOT_SPEED_MAX) // Nicht schneller fahren als moeglich
+ speed_l = BOT_SPEED_MAX;
+ else if (left == 0) // Stop wird nicht veraendert
+ speed_l = BOT_SPEED_STOP;
+ else if (abs(left) < BOT_SPEED_SLOW) // Nicht langsamer als die
+ speed_l = BOT_SPEED_SLOW; // Motoren koennen
+ else // Sonst den Wunsch uebernehmen
+ speed_l = abs(left);
+
+ if (abs(right) > BOT_SPEED_MAX)// Nicht schneller fahren als moeglich
+ speed_r = BOT_SPEED_MAX;
+ else if (abs(right) == 0) // Stop wird nicht veraendert
+ speed_r = BOT_SPEED_STOP;
+ else if (abs(right) < BOT_SPEED_SLOW) // Nicht langsamer als die
+ speed_r = BOT_SPEED_SLOW; // Motoren koennen
+ else // Sonst den Wunsch uebernehmen
+ speed_r = abs(right);
+
+ if (left < 0 )
+ speed_l=-speed_l;
+
+ if (right < 0 )
+ speed_r=-speed_r;
+
+ #ifdef SPEED_CONTROL_AVAILABLE
+ // TODO Hier koennten wir die Motorkennlinie heranziehen um gute Einstiegswerte fuer die Regelung zu haben
+ // Evtl. sogar eine im EEPROM kalibrierbare Tabelle??
+ encoderTargetRateL = left / SPEED_TO_ENCODER_RATE; // Geschwindigkeit [mm/s] umrechnen in [EncoderTicks/Aufruf]
+ encoderTargetRateR = right / SPEED_TO_ENCODER_RATE; // Geschwindigkeit [mm/s] umrechnen in [EncoderTicks/Aufruf]
+ #endif
+
+ // Zuerst einmal eine lineare Kennlinie annehmen
+ bot_motor(speed_l/2,speed_r/2);
+
+}
+
+/*!
+ * Stellt die Servos
+ * Sinnvolle Werte liegen zwischen 8 und 16
+ * @param servo Nummer des Servos
+ * @param servo Zielwert
+ */
+void servo_set(uint8 servo, uint8 pos){
+ if ((servo== SERVO1) && (pos != SERVO_OFF)) {
+ if (pos< DOOR_CLOSE)
+ pos=DOOR_CLOSE;
+ if (pos> DOOR_OPEN)
+ pos=DOOR_OPEN;
+ }
+ servo_low(servo,pos);
+}
+
+/*!
+ * Initialisiere den Motorkrams
+ */
+void motor_init(void){
+ speed_l=0;
+ speed_r=0;
+ motor_low_init();
+}
+
+
diff --git a/source/ct-Bot/pc/bot-2-sim.c b/source/ct-Bot/pc/bot-2-sim.c
new file mode 100644
index 0000000..f76b326
--- /dev/null
+++ b/source/ct-Bot/pc/bot-2-sim.c
@@ -0,0 +1,241 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file bot-2-sim.c
+ * @brief Verbindung c't-Bot zu c't-Sim
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+
+#include "ct-Bot.h"
+
+#ifdef PC
+
+#include <stdio.h> // for printf() and fprintf()
+#include <stdlib.h> // for atoi() and exit()
+#include <string.h> // for strlen()
+#include <sys/time.h>
+#include <pthread.h>
+#include <time.h>
+
+#include "bot-2-sim.h"
+#include "tcp.h"
+#include "command.h"
+#include "display.h"
+#include "sensor.h"
+#include "bot-logic/bot-logik.h"
+#include "motor.h"
+#include "command.h"
+
+
+
+/* Linux with glibc:
+ * _REENTRANT to grab thread-safe libraries
+ * _POSIX_SOURCE to get POSIX semantics
+ */
+#ifdef __linux__
+# define _REENTRANT
+//# define _POSIX_SOURCE
+#endif
+
+/* Hack for LinuxThreads */
+#ifdef __linux__
+# define _P __P
+#endif
+
+#define low_init tcp_init /*!< Low-Funktion zum Initialisieren*/
+
+pthread_t simThread; /*!< Simuliert den Bot */
+pthread_t bot_2_sim_Thread; /*!< Thread sammelt Sensordaten, uebertraegt Motor-Daten */
+
+pthread_cond_t command_cond = PTHREAD_COND_INITIALIZER; /*!< Schuetzt das Kommando */
+pthread_mutex_t command_cond_mutex = PTHREAD_MUTEX_INITIALIZER; /*!< Schuetzt das Kommando */
+
+void signal_command_available(void);
+int wait_for_command(int timeout_s);
+
+#ifdef WIN32
+ /* These are winbase.h definitions, but to avoid including
+ tons of Windows related stuff, it is reprinted here */
+
+ typedef struct _FILETIME {
+ unsigned long dwLowDateTime;
+ unsigned long dwHighDateTime;
+ } FILETIME;
+
+ void __stdcall GetSystemTimeAsFileTime(FILETIME*);
+
+ void gettimeofday_win(struct timeval* p, void* tz /* IGNORED */){
+ union {
+ long long ns100; // time since 1 Jan 1601 in 100ns units
+ FILETIME ft;
+ } _now;
+
+ GetSystemTimeAsFileTime( &(_now.ft) );
+ p->tv_usec=(long)((_now.ns100 / 10LL) % 1000000LL );
+ p->tv_sec= (long)((_now.ns100-(116444736000000000LL))/10000000LL);
+ return;
+ }
+#endif
+
+/*!
+ * Dieser Thread nimmt die Daten vom PC entgegen
+ */
+void *bot_2_sim_rcv_isr(void * arg){
+ #ifdef DISPLAY_AVAILABLE
+ display_cursor(11,1);
+ #endif
+ printf("bot_2_sim_rcv_isr() comming up\n");
+ for (;;){
+ // only write if noone reads command
+ if (command_read()!=0)
+ printf("Error reading command\n"); // read a command
+ else {
+// command_display(&received_command); // show it
+ if (command_evaluate() ==0) // use data transfered
+ signal_command_available(); // tell anyone waiting
+ }
+ }
+ return 0;
+}
+
+/*!
+ * Schleife, die Kommandis empfaengt und bearbeitet, bis ein Kommando vom Typ Frame kommt
+ * @param frame Kommando zum abbruch
+ */
+int8 receive_until_Frame(int8 frame){
+ int8 result=0;
+ for(;;){
+ result=command_read();
+ if (result!=0){
+ printf("Error reading command\n"); // read a command
+ return result;
+ } else {
+ command_evaluate();
+ }
+
+ if (received_command.request.command == frame)
+ return 0;
+ }
+}
+
+
+/*!
+ * Ein wenig Initialisierung kann nicht schaden
+ */
+void bot_2_sim_init(void){
+ low_init();
+
+// if (pthread_create(&bot_2_sim_Thread, // thread struct
+// NULL, // default thread attributes
+// bot_2_sim_rcv_isr, // start routine
+// NULL)) { // arg to routine
+// printf("Thread Creation failed");
+// exit(1);
+// }
+
+ int j;
+ int16 null=0;
+ for(j=0;j<5;j++)
+ command_write(CMD_WELCOME, SUB_WELCOME_SIM ,&null,&null,0);
+
+ flushSendBuffer();
+}
+
+
+int not_answered_error=1; /*!< Wurde ein Packet beantwortet */
+
+
+
+
+/*!
+ * Wartet auf die Antwort des PC
+ * @param timeout_s Wartezeit in Sekunden
+ * @return 0, wenn Ok
+ */
+int wait_for_command(int timeout_s){
+ struct timespec ts;
+ struct timeval tp;
+ int result=0;
+
+ pthread_mutex_lock(&command_cond_mutex);
+
+ GETTIMEOFDAY(&tp, NULL);
+ // Convert from timeval to timespec
+ ts.tv_sec = tp.tv_sec;
+ ts.tv_nsec = tp.tv_usec * 1000;
+ ts.tv_sec += timeout_s;
+
+ result= pthread_cond_timedwait(&command_cond, &command_cond_mutex, &ts);
+
+ pthread_mutex_unlock(&command_cond_mutex);
+
+ return result;
+}
+
+/*!
+ * Wartet auf die Antwort des PC
+ * Achtung blockierend ohne Timeout
+ * @param command Das kommando auf das gewartet wird.
+ * @return 0, wenn Ok
+ */
+int wait_for_special_command(uint8 command){
+ int result=0;
+ while (1){
+ result= wait_for_command(1000);
+
+ if ((result==0) && (received_command.request.command == command))
+ return result;
+ }
+
+}
+
+/*!
+ * Benachrichtigt wartende Threads ueber eingetroffene Kommandos
+ */
+void signal_command_available(void){
+ pthread_mutex_lock(&command_cond_mutex);
+ pthread_cond_signal(&command_cond);
+ pthread_mutex_unlock(&command_cond_mutex);
+}
+
+/*!
+ * Schickt einen Thread in die Warteposition
+ * @param timeout_us Wartezeit in Mikrosekunden
+ */
+void wait_for_time(long timeout_us){
+ pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+ struct timespec ts;
+ struct timeval tp;
+
+ pthread_mutex_lock(&mutex);
+ GETTIMEOFDAY(&tp, NULL);
+ // Convert from timeval to timespec
+
+ tp.tv_usec += (timeout_us % 1000000);
+ tp.tv_sec += (timeout_us / 1000000);
+
+ ts.tv_sec = tp.tv_sec+ (tp.tv_usec/1000000);
+ ts.tv_nsec = (tp.tv_usec % 1000000)* 1000;
+
+ pthread_cond_timedwait(&cond, &mutex, &ts);
+ pthread_mutex_unlock(&mutex);
+}
+#endif
diff --git a/source/ct-Bot/pc/delay_pc.c b/source/ct-Bot/pc/delay_pc.c
new file mode 100644
index 0000000..71dff08
--- /dev/null
+++ b/source/ct-Bot/pc/delay_pc.c
@@ -0,0 +1,66 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file delay_pc.c
+ * @brief Hilfsroutinen
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 20.12.05
+*/
+#include "ct-Bot.h"
+
+#ifdef PC
+
+#ifdef WIN32
+
+ /* Windows */
+ #include <windows.h>
+
+ /*! Sleep Funktion */
+ #define SLEEP(__value) Sleep(__value)
+
+#else
+
+ /* Linux */
+ #include <unistd.h>
+
+ /*! Sleep Funktion */
+ #define SLEEP(__value) usleep(__value)
+
+#endif
+
+/*!
+ * Warte 100 ms
+ */
+void delay_100ms(void){
+
+ SLEEP(100);
+}
+
+
+/*!
+ * Verzoegert um ms Millisekunden
+ * Wenn RTC_AVAILABLE, dann ueber rtc, sonst ueber delay_100ms.
+ * ==> Aufloesung ohne rtc: 100-ms-Schritte, mit rtc: 5-ms-Schritte
+ * @param ms Anzahl der Millisekunden
+ */
+void delay(int ms){
+
+ SLEEP(ms);
+}
+#endif
diff --git a/source/ct-Bot/pc/display_pc.c b/source/ct-Bot/pc/display_pc.c
new file mode 100644
index 0000000..60a7dab
--- /dev/null
+++ b/source/ct-Bot/pc/display_pc.c
@@ -0,0 +1,175 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file display_pc.c
+ * @brief Routinen zur Displaysteuerung
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 20.12.05
+*/
+
+#include "ct-Bot.h"
+
+#ifdef PC
+
+#include "display.h"
+#include <stdarg.h>
+#include <stdio.h>
+
+/* definiere DISPLAY_REMOTE_AVAILABLE, wenn die Display-Daten per TCP an das
+ * Simulationsprogramm gesendet werden sollen. Wenn es nicht gesetzt ist,
+ * dann erscheint die LCD Ausgabe auf der Startkonsole */
+
+
+#ifdef DISPLAY_REMOTE_AVAILABLE
+ #include "command.h"
+ #include "bot-2-sim.h"
+#else
+ #ifdef WIN32
+ #include <windows.h>
+ #endif /* WIN32 */
+#endif
+
+#ifdef DISPLAY_AVAILABLE
+
+/*! Puffergroesse fuer eine Zeile in bytes */
+#define DISPLAY_BUFFER_SIZE (DISPLAY_LENGTH + 1)
+
+uint8 display_update=0; /*!< Muss das Display aktualisiert werden? */
+#ifdef DISPLAY_SCREENS_AVAILABLE
+ uint8 display_screen=0; /*!< Muss das Display aktualisiert werden? */
+#endif
+
+char display_buf[DISPLAY_BUFFER_SIZE]; /*!< Pufferstring fuer Displayausgaben */
+
+#ifdef DISPLAY_REMOTE_AVAILABLE
+ #define CLEAR command_write(CMD_AKT_LCD, SUB_LCD_CLEAR, NULL, NULL,0)
+ #define POSITION(Ze, Sp) {Ze--; Sp--; command_write(CMD_AKT_LCD, SUB_LCD_CURSOR, (int16*)&(Sp),(int16*) &(Ze),0);}
+ #define printf(data) {command_write_data(CMD_AKT_LCD, SUB_LCD_DATA, NULL, NULL, (data));}
+#else
+ #ifdef WIN32
+ static void clrscr(void);
+ static void gotoxy(int x, int y);
+ #define POSITION(Ze, Sp) gotoxy(Sp, Ze)
+ #define CLEAR clrscr()
+ #else
+ #define POSITION(Ze, Sp) printf("\033[%d;%dH",Ze,Sp) /*!< Befehl um eine Posion anzuspringen */
+ #define CLEAR printf("\033[2J") /*!< Befehl um das display zu loeschen */
+ #endif
+#endif
+
+
+/*!
+ * Loescht das ganze Display
+ */
+void display_clear(void){
+ CLEAR;
+}
+
+/*!
+** LCD_Cursor: Positioniert den LCD-Cursor bei "row", "column".
+*/
+void display_cursor (uint8 row, uint8 column) {
+ int16 r=row, c=column; // Cast auf int16
+ POSITION(r, c);
+}
+
+/*!
+ * Init Display
+ */
+void display_init(void){
+ CLEAR;
+}
+
+/*!
+ * Zeigt einen String an
+ * @return -1, falls String zu Ende; 0, falls Zeile (20 Zeichen) zu Ende
+ */
+int display_string(char data[DISPLAY_LENGTH]){
+ printf(data);
+ return -1;
+}
+
+/*!
+ * Schreibt einen String auf das Display.
+ * @param format Format, wie beim printf
+ * @param ... Variable Argumentenliste, wie beim printf
+ */
+void display_printf(char *format, ...) {
+
+ va_list args;
+
+ /* Sicher gehen, das der zur Verfuegung stehende Puffer nicht
+ * ueberschrieben wird.
+ */
+ va_start(args, format);
+ vsnprintf(display_buf, DISPLAY_BUFFER_SIZE, format, args);
+ va_end(args);
+
+ printf(display_buf);
+
+ return;
+}
+
+#ifndef DISPLAY_REMOTE_AVAILABLE
+#ifdef WIN32
+
+/*!
+ * Loescht die Konsole.
+ */
+static void clrscr(void) {
+ COORD coordScreen = { 0, 0 };
+ DWORD cCharsWritten;
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ DWORD dwConSize;
+ HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+
+ GetConsoleScreenBufferInfo(hConsole, &csbi);
+ dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
+ FillConsoleOutputCharacter( hConsole,
+ TEXT(' '),
+ dwConSize,
+ coordScreen,
+ &cCharsWritten);
+ GetConsoleScreenBufferInfo(hConsole, &csbi);
+ FillConsoleOutputAttribute( hConsole,
+ csbi.wAttributes,
+ dwConSize,
+ coordScreen,
+ &cCharsWritten);
+ SetConsoleCursorPosition(hConsole, coordScreen);
+ return;
+}
+
+/*!
+ * Springt an die angegebenen Koordinaten in der Konsole.
+ * @param x Spalte
+ * @param y Zeile
+ */
+static void gotoxy(int x, int y) {
+ COORD point;
+ point.X = x-1; point.Y = y-1;
+ SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), point);
+ return;
+}
+
+#endif /* WIN32 */
+#endif /* !DISPLAY_REMOTE_AVAILABLE */
+
+#endif
+#endif
diff --git a/source/ct-Bot/pc/ir-rc5_pc.c b/source/ct-Bot/pc/ir-rc5_pc.c
new file mode 100644
index 0000000..4072f1a
--- /dev/null
+++ b/source/ct-Bot/pc/ir-rc5_pc.c
@@ -0,0 +1,54 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file ir-rc5_pc.c
+ * @brief Routinen fuer die Dekodierung von RC5-Fernbedienungs-Codes
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 20.12.05
+*/
+
+#include "ct-Bot.h"
+
+#ifdef PC
+
+#include "ir-rc5.h"
+#include "command.h"
+#include "bot-2-sim.h"
+
+#ifdef IR_AVAILABLE
+
+volatile uint16 ir_data = 0; /*!< letztes komplett gelesenes RC5-Paket */
+
+/*!
+ * IR-Daten lesen
+ * @return Wert von ir_data, loescht anschliessend ir_data
+ */
+uint16 ir_read(void) {
+ uint16 retvalue = ir_data;
+ ir_data = 0;
+ return retvalue;
+}
+
+/*!
+ * Init IR-System
+ */
+void ir_init(void) {
+}
+#endif
+#endif
diff --git a/source/ct-Bot/pc/led_pc.c b/source/ct-Bot/pc/led_pc.c
new file mode 100644
index 0000000..7aadcad
--- /dev/null
+++ b/source/ct-Bot/pc/led_pc.c
@@ -0,0 +1,72 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file led_pc.c
+ * @brief Routinen zur LED-Steuerung
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+
+#include "ct-Bot.h"
+#include "bot-2-sim.h"
+#include "command.h"
+
+#ifdef PC
+
+#include "led.h"
+
+#ifdef LED_AVAILABLE
+uint8 led=0; /*!< Status der LEDs */
+/*!
+ * Initialisiert die LEDs
+ */
+void LED_init(){
+}
+
+/*!
+ * Schaltet einzelne LEDs an
+ * andere werden nicht beeinflusst
+ * @param LED Bitmaske der anzuschaltenden LEDs
+ */
+void LED_on(uint8 LED){
+ led |= LED;
+ LED_set(led);
+}
+
+/*!
+ * Schaltet einzelne LEDs aus
+ * andere werden nicht beeinflusst
+ * @param LED Bitmaske der anzuschaltenden LEDs
+ */
+void LED_off(uint8 LED){
+ led &= ~LED;
+ LED_set(led);
+}
+
+/*!
+ * Zeigt eine 8-Bit-Variable mit den LEDs an
+ * @param LED Wert, der gezeigt werden soll
+ */
+void LED_set(uint8 LED){
+ int16 led=LED;
+ command_write(CMD_AKT_LED, SUB_CMD_NORM ,&led,&led,0);
+}
+
+#endif
+#endif
diff --git a/source/ct-Bot/pc/mini-fat.c b/source/ct-Bot/pc/mini-fat.c
new file mode 100644
index 0000000..f806ceb
--- /dev/null
+++ b/source/ct-Bot/pc/mini-fat.c
@@ -0,0 +1,65 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file mini-fat.c
+ * @brief Routinen zum erstellen von markierten Files fuer eine MMC-Karte.
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 04.01.07
+*/
+
+#include "ct-Bot.h"
+#include "mini-fat.h"
+
+#ifdef PC
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/*!
+ * Erzeugt eine Datei, die an den ersten Bytes die ID enthaelt. Dann folgen 512 - sizeof(id) nullen
+ * Danach kommen so viele size kByte Nullen
+ * @param filename Der Dateiname der zu erzeugenden Datei
+ * @param id_string Die ID des Files, wie sie zu beginn steht
+ * @param size kByte Nutzdaten, die der MCU spaeter beschreiben darf
+ */
+void create_mini_fat_file(const char* filename, const char* id_string, uint32 size){
+ printf("Erstelle eine Mini-Fat-Datei mit dem Namen %s\n",filename);
+ FILE *fp = fopen(filename, "w");
+
+ /* Dateiparameter vorbereiten */
+ uint8 id_len = strlen(id_string) >= MMC_FILENAME_MAX ? 254 : strlen(id_string);
+ file_len_t length = {size*1024 - 512}; // im ersten Block stehen interne Daten
+
+ printf("Schreibe ID: \"%s\"\n",id_string);
+ fwrite(id_string,id_len,1,fp);
+
+ /* Dateilaenge in die Datei schreiben */
+ fseek(fp, 256, SEEK_SET);
+ int8 i;
+ for (i=3; i>=0; i--)
+ putc(length.u8[i], fp);
+
+ printf("Erzeuge Speicherplatz fuer %lu kByte Nutzdaten\n",size);
+ fseek(fp, size*1024-1, SEEK_SET); // Ans Dateiende springen
+ putc(0, fp); // eine Null schreiben
+ fclose(fp);
+}
+
+#endif
diff --git a/source/ct-Bot/pc/mmc-emu_pc.c b/source/ct-Bot/pc/mmc-emu_pc.c
new file mode 100644
index 0000000..9d265b3
--- /dev/null
+++ b/source/ct-Bot/pc/mmc-emu_pc.c
@@ -0,0 +1,200 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*!
+ * @file mmc-emu_pc.c
+ * @brief MMC / SD-Card Emulation fuer PC
+ * @author Timo Sandmann (mail@timosandmann.de)
+ * @date 10.12.2006
+ */
+
+/* Die PC-Emulation einer MMC / SD-Card ermoeglicht es, am PC dieselben Funktionen zu benutzen, wie bei einer echten
+ * MMC / SD-Card. Als Speichermedium dient hier eine Datei (MMC_EMU_FILE), deren Groesse sich mit MMC_EMU_SIZE in Byte
+ * einstellen laesst. Ist die Datei nicht vorhanden oder derzeit kleiner als MMC_EMU_SIZE, wird sie angelegt bzw.
+ * vergroessert. Achtung, startet man den C-Bot vom Sim aus, liegt die Datei, falls kein absoluter Pfad angegeben wurde, im
+ * Verzeichnis dem ct-Sims, von der Konsole aus gestartet erwartet / erzeugt der Code die Datei im Unterverzeichnis
+ * "Debug-Linux" bzw. "Debug-W32".
+ * Eine sinnvolle (und die derzeit einzig moegliche) Verwendung der Emulation ergibt sich im Zusammenspiel mit dem
+ * Virtual Memory Management fuer MMC. Ein Verhalten kann in diesem Fall immer auf dieselbe Art und Weise Speicher anfordern,
+ * je nach System liegt dieser physisch dann entweder auf einer MMC / SD-Card (MCU) oder in einer Datei (PC). Fuer das
+ * Verhalten ergibt sich kein Unterschied und es kann einfach derselbe Code verwendet werden.
+ * Moechte man die Funktion mmc_fopen() benutzen, also auf FAT16-Dateien zugreifen, so ist zu beachten, dass deren "Dateiname"
+ * in der Datei fuer die Emulation am Anfang eines 512 Byte grossen Blocks steht (denn auf einer echten MMC / SD-Card ezeugt
+ * ein Betriebssystem eine neue Datei immer am Anfang eines Clusters und mmc_fopen() sucht nur dort nach dem "Dateinamen").
+ * Im Moment gibt es noch keine Funktion zum Anlegen einer neuen Datei auf einer echten oder emulierten MMC / SD-Card.
+ * Die Code der Emulation ist voellig symmetrisch zum Code fuer eine echte MMC / SD-Card aufgebaut.
+ */
+
+#include "ct-Bot.h"
+#include <stdio.h>
+#include "mmc-emu.h"
+#include "mmc-vm.h"
+#include "display.h"
+
+#ifdef PC
+#ifdef MMC_VM_AVAILABLE
+
+#define MMC_EMU_SIZE 0x2000000 /*!< Groesse der emulierten Karte in Byte */
+#define MMC_EMU_FILE "mmc_emu.dat" /*!< Name / Pfad der Datei fuer die Emulation */
+
+volatile uint8 mmc_emu_init_state=1; /*!< Initialierungsstatus der Karte, 0: ok, 1: Fehler */
+static FILE* mmc_emu_file; /*!< Der Inhalt der emulierten Karte wird einfach in eine Datei geschrieben */
+
+/*!
+ * Checkt Initialisierung der emulierten Karte
+ * @return 0, wenn initialisiert
+ * @see mcu/mmc.c
+ * @date 29.12.2006
+ */
+inline uint8 mmc_emu_get_init_state(void){
+ return mmc_emu_init_state;
+}
+
+/*!
+ * Initialisiere die emulierte SD/MMC-Karte
+ * @return 0 wenn allles ok, sonst 1
+ * @see mcu/mmc.c
+ * @date 29.12.2006
+ */
+uint8 mmc_emu_init(void){
+ mmc_emu_init_state = 0;
+ mmc_emu_file = fopen(MMC_EMU_FILE, "r+"); // Datei versuchen zu oeffnen
+ if (mmc_emu_file == NULL){
+ /* Datei existiert noch nicht oder kann nicht erzeugt werden */
+ mmc_emu_file = fopen(MMC_EMU_FILE, "w+"); // Datei neu anlegen
+ if (mmc_emu_file == NULL) {
+ /* Datei kann nicht erzeugt werden */
+ mmc_emu_init_state = 1;
+ return 1;
+ }
+ }
+ if (mmc_emu_get_size() < MMC_EMU_SIZE){
+ /* vorhandene Datei ist zu klein, also auf MMC_EMU_SIZE vergroessern */
+ mmc_emu_init_state = 1;
+ if (fseek(mmc_emu_file, MMC_EMU_SIZE-1, SEEK_SET) != 0) return 2;
+ if (putc(0, mmc_emu_file) != 0) return 3;
+ if (fflush(mmc_emu_file) != 0) return 4;
+ mmc_emu_init_state = 0;
+ }
+ return 0;
+}
+
+/*!
+ * Liest einen Block von der emulierten Karte
+ * @param addr Nummer des 512-Byte Blocks
+ * @param buffer Puffer von mindestens 512 Byte
+ * @return 0 wenn alles ok ist
+ * @see mcu/mmc.c
+ * @date 10.12.2006
+ */
+uint8 mmc_emu_read_sector(uint32 addr, uint8* buffer){
+ if (mmc_emu_get_init_state() != 0 && mmc_emu_init() !=0) return 1;
+ if (fseek(mmc_emu_file, addr<<9, SEEK_SET) != 0) return 2; // Adresse in Byte umrechnen und an Dateiposition springen
+ if (fread(buffer, 512, 1, mmc_emu_file) != 1) return 3; // Block lesen
+ return 0;
+}
+
+/*!
+ * Schreibt einen 512-Byte Sektor auf die emulierte Karte
+ * @param addr Nummer des 512-Byte Blocks
+ * @param buffer Zeiger auf den Puffer
+ * @param async Wird bei der PC-Version nicht ausgewertet
+ * @return 0 wenn alles ok ist
+ * @date 10.12.2006
+ * @see mcu/mmc.c
+ */
+uint8 mmc_emu_write_sector(uint32 addr, uint8* buffer, uint8 async){
+ if (mmc_emu_get_init_state() != 0 && mmc_emu_init() !=0) return 1;
+ if (fseek(mmc_emu_file, addr<<9, SEEK_SET) != 0) return 2; // Adresse in Byte umrechnen und an Dateiposition springen
+ if (fwrite(buffer, 512, 1, mmc_emu_file) != 1) return 3; // Block schreiben
+ if (fflush(mmc_emu_file) != 0) return 4; // Puffer leeren
+ return 0;
+}
+
+/*!
+ * Liefert die Groesse der Karte zurueck
+ * @return Groesse der emulierten Karte in Byte.
+ * @date 29.12.2006
+ */
+uint32 mmc_emu_get_size(void){
+ if (mmc_emu_get_init_state() != 0 && mmc_emu_init() !=0) return 0;
+ if (fseek(mmc_emu_file, 0L, SEEK_END) != 0) return 0; // Groesse der emulierten Karte = Groesse der Datei
+ return ftell(mmc_emu_file)+1;
+}
+
+/*!
+ * Testet VM und MMC / SD-Card Emulation am PC
+ * @date 30.12.2006
+ */
+uint8 mmc_emu_test(void){
+ /* Initialisierung checken */
+ if (mmc_emu_init_state != 0 && mmc_emu_init() != 0) return 1;
+ uint16 i;
+ static uint16 pagefaults = 0;
+ /* virtuelle Adressen holen */
+ static uint32 v_addr1 = 0;
+ static uint32 v_addr2 = 0;
+ static uint32 v_addr3 = 0;
+ static uint32 v_addr4 = 0;
+ if (v_addr1 == 0) v_addr1 = mmcalloc(512, 1); // Testdaten 1
+ if (v_addr2 == 0) v_addr2 = mmcalloc(512, 1); // Testdaten 2
+ if (v_addr3 == 0) v_addr3 = mmcalloc(512, 1); // Dummy 1
+ if (v_addr4 == 0) v_addr4 = mmcalloc(512, 1); // Dummy 2
+ /* Pointer auf Puffer holen */
+ uint8* p_addr = mmc_get_data(v_addr1);
+ if (p_addr == NULL) return 2;
+ /* Testdaten schreiben */
+ for (i=0; i<512; i++)
+ p_addr[i] = (i & 0xff);
+ /* Pointer auf zweiten Speicherbereich holen */
+ p_addr = mmc_get_data(v_addr3);
+ if (p_addr == NULL) return 3;
+ /* Testdaten Teil 2 schreiben */
+ for (i=0; i<512; i++)
+ p_addr[i] = 255 - (i & 0xff);
+ /* kleiner LRU-Test */
+ p_addr = mmc_get_data(v_addr1);
+ p_addr = mmc_get_data(v_addr4);
+ p_addr = mmc_get_data(v_addr1);
+ p_addr = mmc_get_data(v_addr3);
+ p_addr = mmc_get_data(v_addr1);
+ p_addr = mmc_get_data(v_addr4);
+ /* Pointer auf Testdaten Teil 1 holen */
+ p_addr = mmc_get_data(v_addr1);
+ if (p_addr == NULL) return 4;
+ /* Testdaten 1 vergleichen */
+ for (i=0; i<512; i++)
+ if (p_addr[i] != (i & 0xff)) return 5;
+ /* Pointer auf Testdaten Teil 2 holen */
+ p_addr = mmc_get_data(v_addr3);
+ if (p_addr == NULL) return 6;
+ /* Testdaten 2 vergleichen */
+ for (i=0; i<512; i++)
+ if (p_addr[i] != (255 - (i & 0xff))) return 7;
+ /* Pagefaults merken */
+ pagefaults = mmc_get_pagefaults();
+ /* kleine Statistik ausgeben */
+ display_cursor(3,1);
+ display_printf("Pagefaults: %5u ", pagefaults);
+ // hierher kommen wir nur, wenn alles ok ist
+ return 0;
+}
+
+#endif // MMC_VM_AVAILABLE
+#endif // PC
diff --git a/source/ct-Bot/pc/motor-low_pc.c b/source/ct-Bot/pc/motor-low_pc.c
new file mode 100644
index 0000000..1bd7e80
--- /dev/null
+++ b/source/ct-Bot/pc/motor-low_pc.c
@@ -0,0 +1,81 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file motor-low_pc.c
+ * @brief Low-Level Routinen fuer die Motorsteuerung des c't-Bots
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 01.12.05
+*/
+
+#include "ct-Bot.h"
+
+#ifdef PC
+
+#include <stdlib.h>
+#include "command.h"
+#include "bot-2-sim.h"
+#include "motor-low.h"
+#include "motor.h"
+
+
+int16 motor_left; /*!< zuletzt gestellter Wert linker Motor */
+int16 motor_right; /*!< zuletzt gestellter Wert rechter Motor */
+
+/*!
+ * Initilisiert alles fuer die Motosteuerung
+ */
+void motor_low_init(){
+}
+
+/*!
+ * Unmittelbarer Zugriff auf die beiden Motoren,
+ * normalerweise NICHT verwenden!
+ * @param left PWM links
+ * @param right PWM rechts
+*/
+void bot_motor(int16 left, int16 right){
+ command_write(CMD_AKT_MOT, SUB_CMD_NORM ,&left,&right,0);
+
+ if (right < 0 )
+ direction.right= DIRECTION_BACKWARD;
+ if (right > 0 )
+ direction.right= DIRECTION_FORWARD;
+ if (left < 0 )
+ direction.left= DIRECTION_BACKWARD;
+ if (left > 0 )
+ direction.left= DIRECTION_FORWARD;
+
+ motor_left=left;
+ motor_right=right;
+
+}
+
+/*!
+ * Stellt die Servos
+ * Sinnvolle Werte liegen zwischen 8 und 16
+ * @param servo Nummer des Servos
+ * @param servo Zielwert
+ */
+void servo_low(uint8 servo, uint8 pos){
+ int16 p = pos;
+ int16 s = servo;
+ command_write(CMD_AKT_SERVO, SUB_CMD_NORM ,&s,&p,0);
+}
+
+#endif
diff --git a/source/ct-Bot/pc/mouse_pc.c b/source/ct-Bot/pc/mouse_pc.c
new file mode 100644
index 0000000..c8e1dda
--- /dev/null
+++ b/source/ct-Bot/pc/mouse_pc.c
@@ -0,0 +1,87 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file mouse.c
+ * @brief Routinen fuer die Ansteuerung eines opt. Maussensors
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+#include "global.h"
+
+#include "ct-Bot.h"
+#include "log.h"
+
+#ifdef PC
+
+uint8 mousePicture[18*18];
+
+/*!
+ * Initialisiere Maussensor
+ */
+void maus_sens_init(void){
+}
+
+uint16 pixIndex=0;
+
+/*!
+ * Bereitet das auslesen eines ganzen Bildes vor
+ */
+void maus_image_prepare(void){
+ pixIndex=0;
+
+ int x,y;
+ for (x=0; x<18;x++)
+ for (y=0; y<18;y++)
+ mousePicture[y + x*18] = 0x40 | y*4;
+
+ mousePicture[0]|= 0x80; // Start of Frame
+
+}
+
+/*!
+ * Liefert bei jedem Aufruf das naechste Pixel des Bildes
+ * Insgesamt gibt es 324 Pixel
+ * <pre>
+ * 18 36 ... 324
+ * .. .. ... ..
+ * 2 20 ... ..
+ * 1 19 ... 307
+ * </pre>
+ * Bevor diese Funktion aufgerufen wird, muss maus_image_prepare() aufgerufen werden!
+ * @return Die Pixeldaten (Bit 0 bis Bit5), Pruefbit, ob Daten gueltig (Bit6), Markierung fuer den Anfang eines Frames (Bit7)
+ */
+int8 maus_image_read(void){
+
+ if (pixIndex==324)
+ pixIndex =0;
+
+ return mousePicture[pixIndex++];
+}
+
+/*!
+ * Gibt den SQUAL-Wert zurueck. Dieser gibt an, wieviele Merkmale der Sensor
+ * im aktuell aufgenommenen Bild des Untergrunds wahrnimmt.
+ * Fuer simulierten Bot zur Zeit mit einem fixen Wert belegt, da fuer den
+ * Boden im Sim keine Texturen verwendet werden
+ */
+int8 maus_get_squal(void) {
+ return 70;
+}
+
+#endif
diff --git a/source/ct-Bot/pc/sensor-low_pc.c b/source/ct-Bot/pc/sensor-low_pc.c
new file mode 100644
index 0000000..b10e9ea
--- /dev/null
+++ b/source/ct-Bot/pc/sensor-low_pc.c
@@ -0,0 +1,45 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file sensor-low_pc.c
+ * @brief Low-Level Routinen fuer die Sensor Steuerung des c't-Bots
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 01.12.05
+*/
+
+#include "ct-Bot.h"
+
+#ifdef PC
+
+#include "sensor-low.h"
+
+/*!
+ * Initialisiere alle Sensoren
+ */
+void bot_sens_init(void){
+}
+
+/*!
+ * Alle Sensoren aktualisieren.
+ * Das geschieht auf der PC Seite anders -- in einem eigenen Thread.
+ * Diese Funktion ist nur ein Dummy zur Kompatibilitaet.
+ */
+void bot_sens_isr(void){
+}
+#endif
diff --git a/source/ct-Bot/pc/tcp-server.c b/source/ct-Bot/pc/tcp-server.c
new file mode 100644
index 0000000..7d1f53b
--- /dev/null
+++ b/source/ct-Bot/pc/tcp-server.c
@@ -0,0 +1,274 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file tcp-server.c
+ * @brief Demo-TCP-Server
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+#include "ct-Bot.h"
+
+#ifdef PC
+
+#include "bot-2-sim.h"
+#include "tcp.h"
+#include "display.h"
+#include "command.h"
+
+#include <time.h>
+#include <sys/time.h>
+
+
+/* Linux with glibc:
+ * _REENTRANT to grab thread-safe libraries
+ * _POSIX_SOURCE to get POSIX semantics
+ */
+#ifndef WIN32
+# define _REENTRANT
+//# define _POSIX_SOURCE
+#else
+// #define WIN32
+#endif
+
+/* Hack for LinuxThreads */
+#ifdef __linux__
+# define _P __P
+#endif
+
+#include <pthread.h>
+
+#ifdef WIN32
+ #include <winsock.h>
+#else
+ #include <arpa/inet.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+#endif
+
+#include <stdio.h> // for printf() and fprintf()
+#include <stdlib.h> // for atoi() and exit()
+#include <string.h> // for memset()
+#include <unistd.h> // for close()
+
+#include "global.h"
+
+int server; /*!< Server-Socket */
+
+struct sockaddr_in serverAddr; /*!< Lokale Adresse */
+struct sockaddr_in clientAddr; /*!< Client-Adresse */
+unsigned int clntLen; /*!< Laenge der Datenstruktur der Client-Adresse */
+
+/*!
+ * Init TCP-Server
+ */
+void tcp_server_init(void){
+ #ifdef DISPLAY_AVAILABLE
+// display_init();
+ #endif
+
+ #ifdef WIN32
+ WSADATA wsaData;
+ WORD wVersionRequested;
+ int err;
+
+ wVersionRequested = MAKEWORD( 2, 0 ); // 2.0 and above version of WinSock
+ err = WSAStartup( wVersionRequested, &wsaData );
+ if ( err != 0 ) {
+ fprintf(stderr, "Couldn't not find a usable WinSock DLL.\n");
+ exit(1);
+ }
+ #endif
+
+
+ // Create socket for incoming connections
+ if ((server = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){
+ printf("socket() failed\n");
+ exit(1);
+ }
+
+ int i=1;
+ setsockopt(server,SOL_SOCKET,SO_REUSEADDR,(char*)&i,sizeof(i));
+
+ memset(&serverAddr, 0, sizeof(serverAddr)); // Clean up
+ serverAddr.sin_family = AF_INET; // Internet address family
+ serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); // Any incoming interface
+ serverAddr.sin_port = htons(PORT); // Local port to listen on
+
+ // Bind to the local address
+ if (bind(server, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) <0 ){
+ printf("bind() failed\n");
+ exit(1);
+ }
+
+ // Mark the socket so it will listen for incoming connections
+ if (listen(server, 5) < 0){
+ printf("listen() failed\n");
+ exit(1);
+ }
+}
+
+/*!
+ * Hauptschleife des TCP-Servers
+ */
+int tcp_server_run (int runs){
+ char buffer[MAX_PAYLOAD]; // Buffer
+ struct timeval start, stop;
+ printf("TCP-Server alive\n");
+
+ int seq=0;
+// tcp_server_init();
+
+// printf("Initialized\n");
+
+ for(;;){
+ /* Set the size of the in-out parameter */
+ clntLen = sizeof(clientAddr);
+
+ printf("Waiting for client\n");
+ // Wait for a client to connect
+ if ((tcp_sock = accept(server, (struct sockaddr *) &clientAddr, &clntLen)) < 0)
+ printf("accept() failed");
+
+ printf("Connected to %s on Port: %d\n", inet_ntoa(clientAddr.sin_addr),PORT);
+
+ int16 simultime=0;
+ int i;
+ for(i=0;i<runs;i++){
+ simultime+=10;
+
+ command_write(CMD_SENS_IR, SUB_CMD_NORM ,(int16*)&simultime,(int16*)&simultime,0);
+ command_write(CMD_SENS_ENC, SUB_CMD_NORM ,(int16*)&simultime,(int16*)&simultime,0);
+ command_write(CMD_SENS_BORDER, SUB_CMD_NORM ,(int16*)&simultime,(int16*)&simultime,0);
+ command_write(CMD_SENS_LINE, SUB_CMD_NORM ,(int16*)&simultime,(int16*)&simultime,0);
+ command_write(CMD_SENS_LDR, SUB_CMD_NORM ,(int16*)&simultime,(int16*)&simultime,0);
+ command_write(CMD_SENS_TRANS, SUB_CMD_NORM ,(int16*)&simultime,0,0);
+ command_write(CMD_SENS_DOOR, SUB_CMD_NORM ,(int16*)&simultime,(int16*)&simultime,0);
+ command_write(CMD_SENS_MOUSE, SUB_CMD_NORM ,(int16*)&simultime,(int16*)&simultime,0);
+ command_write(CMD_SENS_ERROR, SUB_CMD_NORM ,(int16*)&simultime,(int16*)&simultime,0);
+ command_write(CMD_SENS_RC5, SUB_CMD_NORM ,0,0,0);
+
+ command_write(CMD_DONE, SUB_CMD_NORM ,(int16*)&simultime,0,0);
+ flushSendBuffer();
+
+ GETTIMEOFDAY(&stop, NULL);
+ int t2= (stop.tv_sec - start.tv_sec)*1000000 + stop.tv_usec - start.tv_usec;
+ printf("X-Token (%d) out after %d usec ",simultime,t2);
+
+
+ received_command.request.command =0;
+ while(received_command.request.command != CMD_DONE ){
+ if (command_read() != 0){
+ // Fehler
+ printf("Probleme beim Lesen eines Kommandos\n");
+ } else {
+ // Alles ok, evtl. muessen wir aber eine Payload abholen
+ if (received_command.payload != 0) {
+ // printf ("fetching payload (%d bytes)\n",received_command.payload);
+ low_read(buffer,received_command.payload);
+ }
+ if (received_command.seq != seq){
+ printf("Sequenzzaehler falsch! Erwartet: %d Empfangen %d \n",seq,received_command.seq);
+ }
+ }
+ seq=received_command.seq+1;
+ }
+ GETTIMEOFDAY(&start, NULL);
+
+
+ int t= (start.tv_sec - stop.tv_sec)*1000000 + start.tv_usec - stop.tv_usec;
+ printf("X-Token (%d) back after %d usec\n",received_command.data_l,t);
+
+
+ if (received_command.data_l != simultime){
+ printf("Falschen X-Frame erhalten ==> Exit\n");
+ exit(0);
+ }
+
+/*
+ printf("Rechenzeit: %d usec\n",(stop.tv_sec - start.tv_sec)*1000000 +stop.tv_usec - start.tv_usec);
+
+ command_read();
+ if
+ #ifdef LOG_AVAILABLE
+ command_display(&received_command);
+ #endif
+
+ received_command.request.direction=DIR_ANSWER;
+ tcp_send_cmd(&received_command);
+ */
+ }
+
+ printf("TCP-Server hat seine %d runs durch und beendet sich. So long and thanks for all the fish\n",runs);
+
+ #ifdef WIN32
+ WSACleanup();
+ #endif
+ exit(0);
+ }
+
+ return 1;
+}
+
+
+/*!
+ * Init TCP-test-Client
+ */
+void tcp_test_client_init(void){
+ tcp_init();
+ printf("Connecting Testclient to %s on Port: %d ", tcp_hostname, 10001);
+
+ if ((tcp_sock=tcp_openConnection(tcp_hostname)) != -1)
+ printf ("established \n");
+ else {
+ printf ("failed\n");
+ exit(1);
+ }
+}
+
+/*!
+ * Hauptschleife des TCP-Test-Clients
+ */
+int tcp_test_client_run (int runs){
+ char buffer[255];
+
+ int len=0;
+ int i=0;
+
+ if (runs > 0)
+ printf("Answering %d frames\n",runs);
+ else
+ printf("Answering all frames\n");
+
+ for(;;){
+ if ((runs > 0) && (i > runs))
+ break;
+ i++;
+ buffer[0]=0;
+ len=0;
+
+ len= tcp_read(&buffer,255);
+ tcp_write(&buffer,len);
+ }
+ printf("Finished %d frames\n",runs);
+
+ exit(1);
+ return 1;
+}
+
+#endif
diff --git a/source/ct-Bot/pc/tcp.c b/source/ct-Bot/pc/tcp.c
new file mode 100644
index 0000000..d654f3d
--- /dev/null
+++ b/source/ct-Bot/pc/tcp.c
@@ -0,0 +1,282 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file tcp.c
+ * @brief TCP/IP-Kommunikation
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+
+#include "ct-Bot.h"
+
+#define USE_SEND_BUFFER
+
+#ifdef PC
+
+/* Linux with glibc:
+ * _REENTRANT to grab thread-safe libraries
+ * _POSIX_SOURCE to get POSIX semantics
+ */
+#ifndef WIN32
+# define _REENTRANT
+//# define _POSIX_SOURCE
+#else
+// #define WIN32
+#endif
+
+/* Hack for LinuxThreads */
+#ifdef __linux__
+# define _P __P
+#endif
+
+#include <pthread.h>
+
+
+#ifdef WIN32
+ #include <winsock.h>
+#else
+ #include <arpa/inet.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <netdb.h> // for gethostbyname()
+ #include <netinet/tcp.h>
+#endif
+
+
+#include <stdio.h> // for printf() and fprintf()
+#include <stdlib.h> // for atoi() and exit()
+#include <string.h> // for memset()
+#include <unistd.h> // for close()
+
+#include "tcp.h"
+#include "display.h"
+
+int tcp_sock=0; /*!< Unser TCP-Socket */
+char *tcp_hostname = NULL; /*!< Hostname, auf dem ct-Sim laeuft */
+
+#ifdef PC
+ uint8 sendBuffer[1024]; /*!< Sendepuffer fuer ausgehende Packete */
+ int sendBufferPtr=0; /*!< Index in den Sendepuffer */
+#endif
+
+/*!
+ * Oeffnet eine TCP-Verbindung zum Server
+ * @param hostname Symbolischer Name des Host, auf dem ct-Sim laeuft
+ * @return Der Socket
+*/
+int tcp_openConnection(const char *hostname){
+ struct sockaddr_in servAddr; // server address
+ int sock=0; // Socket descriptor
+ struct hostent *he = gethostbyname(hostname);
+
+ // Ueberpruefen, ob der Hostname aufgeloest werden konnte
+ if (NULL == he) {
+ printf("gethostbyname() failed\n");
+ exit(1);
+ }
+
+ // Create a stream socket for TCP
+ if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){
+ printf("socket() failed");
+ exit(1);
+ }
+
+ int flag = 1;
+ setsockopt(sock, /* socket affected */
+ IPPROTO_TCP, /* set option at TCP level */
+ TCP_NODELAY, /* name of option */
+ (char *) &flag, /* the cast is historical
+ cruft */
+ sizeof(int)); /* length of option value */
+
+ // Prepare server address structure
+ memset(&servAddr, 0, sizeof(servAddr)); // Zero out structure
+ servAddr.sin_family = AF_INET; // Internet address
+ servAddr.sin_port = htons(PORT); // Port
+
+ // Die erste Adresse aus der Liste uebernehmen
+ memcpy(&servAddr.sin_addr, *(he->h_addr_list), sizeof(servAddr.sin_addr));
+
+ // Open Connection to the server
+ if (connect(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0){
+ printf("tcp_openConnection() to %s failed\n", inet_ntoa(servAddr.sin_addr));
+ exit(1);
+ }
+
+ return sock;
+}
+
+/*!
+ * Schliesst eine TCP-Connection
+ * @param sock Der Socket
+*/
+void tcp_closeConnection(int sock){
+ close(sock);
+ #ifdef WIN32
+ WSACleanup();
+ #endif
+}
+
+/*!
+ * Sende Kommando per TCP/IP im Little Endian
+ * Diese Funktion setzt vorraus, dass die Symbole BYTE_ORDER und BIG_ENDIAN
+ * bzw. LITTLE_ENDIAN definiert wurden. Damit dies auf Linux/Unix
+ * funktioniert darf _POSIX_SOURCE nicht definiert werden. Fuer Windows
+ * wird dies in der Headerdatei tcp.h erledigt.
+ * Getestet wurde dies bisher auf folgenden Systemen:
+ * - MacOSX (PPC, big endian)
+ * - Gentoo Linux (hppa, big endian)
+ * - OpenBSD (i386, little endian)
+ * - Windows 2000 (i386, little endian mit dem MinGW)
+ * Sollten in command_t weitere Werte mit mehr bzw. weniger als 8 bit
+ * aufgenommen werden muss hier eine entsprechende Anpassung erfolgen.
+ * @param cmd Zeiger auf das Kommando
+ * @return Anzahl der gesendete Bytes
+ */
+int tcp_send_cmd(command_t *cmd){
+#if BYTE_ORDER == BIG_ENDIAN
+ command_t le_cmd;
+
+ /* Kopieren des Kommandos und auf Little Endian wandeln */
+ memcpy(&le_cmd, cmd, sizeof(command_t));
+
+ /* Alle 16bit Werte in Little Endian wandeln */
+ le_cmd.data_l = cmd->data_l << 8;
+ le_cmd.data_l |= (cmd->data_l >> 8) & 0xff;
+ le_cmd.data_r = cmd->data_r << 8;
+ le_cmd.data_r |= (cmd->data_r >> 8) & 0xff;
+ le_cmd.seq = cmd->seq <<8;
+ le_cmd.seq |= (cmd->seq >> 8) & 0xff;
+
+ /* "Umdrehen" des Bitfields */
+ le_cmd.request.subcommand = cmd->request.subcommand >> 1;
+ le_cmd.request.direction = (cmd->request.subcommand & 1) << 7;
+
+ return tcp_write(&le_cmd, sizeof(command_t));
+#else
+ return tcp_write(cmd, sizeof(command_t));
+#endif
+}
+
+/*! Puffert daten im Sendepuffer zwischen
+ * @param data zeiger auf die daten
+ * @param length Anzahl der Bytes
+ * @return -1 wenn kein Platz mehr im Puffer ist, 0 wenn alles ok ist
+ */
+int copy2Buffer(uint8* data, int length){
+ int i;
+ uint8 * ptr = data;
+
+ if ((sendBufferPtr + length) > sizeof(sendBuffer))
+ return -1;
+
+// printf("Store %d bytes",length);
+ // Auf dem PC kopieren wir nur alles in den Ausgangspuffer
+ for (i=0; i< length ; i++){
+ sendBuffer[sendBufferPtr++]= *ptr++ ;
+ }
+// printf(" %d Bytes now in buffer\n",sendBufferPtr);
+ return 0;
+}
+
+/*!
+ * Uebertrage Daten per TCP/IP
+ * @param data Zeiger auf die Daten
+ * @param length Anzahl der Bytes
+ * @return 0 wenn alles ok, -1 wenn puffer voll
+*/
+int tcp_write(void* data, int length){
+ #ifdef USE_SEND_BUFFER
+ return copy2Buffer(data, length);
+ #else
+ if (send(tcp_sock,data,length,0) != length){
+ printf("send() sent a different number of bytes than expected");
+ return -1;
+ }
+ return length;
+ #endif
+}
+
+/*!
+ * Lese Daten von TCP/IP-Verbindung.
+ * Achtung: blockierend!
+ * @param data Zeiger auf die Daten
+ * @param length Anzahl der gewuenschten Bytes
+ * @return Anzahl der uebertragenen Bytes
+*/
+int tcp_read(void* data, int length){
+ int bytesReceived=0;
+
+ if ((bytesReceived = recv(tcp_sock, data, length, 0)) <= 0){
+ printf("recv() failed or connection closed prematurely\n");
+ exit(1);
+ return -1;
+ }
+
+ return bytesReceived;
+}
+
+/*!
+ * Initialisiere TCP/IP Verbindung
+ */
+void tcp_init(void){
+ #ifdef WIN32
+ WSADATA wsaData;
+ WORD wVersionRequested;
+ int err;
+
+ wVersionRequested = MAKEWORD( 2, 0 ); // 2.0 and above version of WinSock
+ err = WSAStartup( wVersionRequested, &wsaData );
+ if ( err != 0 ) {
+ fprintf(stderr, "Couldn't not find a usable WinSock DLL.\n");
+ exit(1);
+ }
+ #endif
+
+
+ if ((tcp_sock=tcp_openConnection(tcp_hostname)) != -1)
+ printf ("connection to %s established on Port: %d\n", tcp_hostname, PORT);
+ else {
+ printf ("connection to %s failed on Port: %d\n", tcp_hostname, PORT);
+ exit(1);
+ }
+
+}
+
+/*!
+ * Schreibt den Sendepuffer auf einen Schlag raus
+ * @return -1 bei Fehlern, sonst zahl der uebertragenen Bytes
+ */
+int flushSendBuffer(void){
+ #ifdef USE_SEND_BUFFER
+ // printf("Flushing Buffer with %d bytes\n",sendBufferPtr);
+
+ int length=sendBufferPtr;
+ sendBufferPtr=0; // Puffer auf jedenfall leeren
+ if (send(tcp_sock,(char*)&sendBuffer,length,0) != length){
+ printf("send() sent a different number of bytes than expected");
+ return -1;
+ }
+ return length;
+ #else
+ return 0;
+ #endif
+}
+
+#endif
diff --git a/source/ct-Bot/rc5.c b/source/ct-Bot/rc5.c
new file mode 100644
index 0000000..72cb20d
--- /dev/null
+++ b/source/ct-Bot/rc5.c
@@ -0,0 +1,502 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file rc5.c
+ * @brief RC5-Fernbedienung
+ * Um RC5-Codes fuer eine eigene Fernbedienung anzupassen, reicht es diese
+ * in eine Header-Datei auszulagern und anstatt der rc5code.h einzubinden.
+ * Die Maskierung fuer die Auswertung der Codes nicht vergessen!
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 20.12.05
+*/
+#include "bot-logic/bot-logik.h"
+#include "map.h"
+#include "ir-rc5.h"
+#include "display.h"
+#include "motor-low.h"
+
+#include "rc5-codes.h"
+
+
+
+#include <stdlib.h>
+
+#ifdef RC5_AVAILABLE
+
+/*!
+ * Dieser Typ definiert Parameter fuer RC5-Kommando-Code Funktionen.
+ */
+typedef struct {
+ uint16 value1; /*!< Wert 1 */
+ uint16 value2; /*!< Wert 2 */
+} RemCtrlFuncPar;
+
+/*! Dieser Typ definiert die RC5-Kommando-Code Funktion. */
+typedef void (*RemCtrlFunc)(RemCtrlFuncPar *par);
+
+/*! Dieser Typ definiert den RC5-Kommando-Code und die auszufuehrende Funktion. */
+typedef struct {
+ uint16 command; /*!< Kommando Code */
+ RemCtrlFunc func; /*!< Auszufuehrende Funktion */
+ RemCtrlFuncPar par; /*!< Parameter */
+} RemCtrlAction;
+
+/*!
+ * Diese Funktion setzt das Display auf eine andere Ausgabe.
+ * @param par Parameter mit dem zu setzenden Screen.
+ */
+#ifdef DISPLAY_SCREENS_AVAILABLE
+ static void rc5_screen_set(RemCtrlFuncPar *par);
+#endif
+
+#ifdef JOGDIAL
+/*!
+ * Diese Funktion setzt die Geschwindigkeit auf den angegebenen Wert.
+ * @param par Parameter mit den zu setzenden Geschwindigkeiten.
+ */
+static void rc5_bot_set_speed(RemCtrlFuncPar *par);
+#endif
+
+/*!
+ * Diese Funktion aendert die Geschwindigkeit um den angegebenen Wert.
+ * @param par Parameter mit den relativen Geschwindigkeitsaenderungen.
+ */
+#ifdef BEHAVIOUR_AVAILABLE
+ static void rc5_bot_change_speed(RemCtrlFuncPar *par);
+#endif
+
+/*!
+ * Diese Funktion wechselt zwischen verschiednen Verhalten
+ * @param par Parameter mit den zu setzenden Geschwindigkeiten.
+ */
+void rc5_bot_next_behaviour(RemCtrlFuncPar *par);
+
+
+/*!
+ * Diese Funktion stellt die Not-Aus-Funktion dar. Sie laesst den Bot anhalten
+ * und setzt alle Verhalten zurueck.
+ * @param par notwendiger Dummy-Parameter.
+ */
+static void rc5_emergency_stop(RemCtrlFuncPar *par);
+
+/*!
+* Verarbeitet die Zifferntasten in Abhaengigkeit vom eingestelltem Screen
+* @param par Parameter mit der betaetigten Zahlentaste.
+*/
+void rc5_number(RemCtrlFuncPar *par);
+
+#ifdef DISPLAY_BEHAVIOUR_AVAILABLE
+ /*!
+ * Diese Funktion setzt die Aktivitaeten der Verhalten nach der Auswahl.
+ * Hierdurch erfolgt der Startschuss fuer Umschaltung der Verhalten
+ */
+ #ifndef DISPLAY_DYNAMIC_BEHAVIOUR_AVAILABLE
+ static void rc5_set_all_behaviours(void) ;
+ #endif
+ /*!
+ * toggled ein Verhalten der Verhaltensliste an Position pos,
+ * die Aenderung erfolgt nur auf die Puffervariable
+ * @param i Verhaltens-Listenposition, entspricht der Taste 1-6 der gewaehlten Verhaltensseite
+ */
+ static void rc5_toggle_behaviour_new(int8 i);
+#endif
+
+/*! Steuert den Servo an
+ * @param par Parameter mit Servo-Nummer und -Position
+ */
+void rc5_bot_servo(RemCtrlFuncPar *par);
+
+uint16 RC5_Code; /*!< Letzter empfangener RC5-Code */
+
+/*! Fernbedienungsaktionen */
+static RemCtrlAction gRemCtrlAction[] = {
+ /* RC5-Code, Funktion, Parameter */
+ { RC5_CODE_PWR, rc5_emergency_stop, { 0, 0 } },
+ #ifdef BEHAVIOUR_AVAILABLE
+ { RC5_CODE_UP, rc5_bot_change_speed, { 10, 10 } },
+ { RC5_CODE_DOWN, rc5_bot_change_speed, { -10, -10 } },
+ { RC5_CODE_LEFT, rc5_bot_change_speed, { 0, 10 } },
+ { RC5_CODE_RIGHT, rc5_bot_change_speed, { 10, 0 } },
+ #endif
+
+ { RC5_CODE_0, rc5_number, { 0, 0 } },
+ { RC5_CODE_1, rc5_number, { 1, 1 } },
+ { RC5_CODE_2, rc5_number, { 2, 2 } },
+ { RC5_CODE_3, rc5_number, { 3, 3 } },
+ { RC5_CODE_4, rc5_number, { 4, 4 } },
+ { RC5_CODE_5, rc5_number, { 5, 5 } },
+ { RC5_CODE_6, rc5_number, { 6, 6 } },
+ { RC5_CODE_7, rc5_number, { 7, 7 } },
+ { RC5_CODE_8, rc5_number, { 8, 8 } },
+ { RC5_CODE_9, rc5_number, { 9, 9 } },
+ { RC5_CODE_I_II, rc5_bot_next_behaviour, { 0, 0 } },
+#ifdef BEHAVIOUR_SERVO_AVAILABLE
+ { RC5_CH_PLUS, rc5_bot_servo, { SERVO1, DOOR_CLOSE } },
+ { RC5_CH_MINUS, rc5_bot_servo, { SERVO1, DOOR_OPEN } },
+#endif
+#ifdef DISPLAY_SCREENS_AVAILABLE
+ { RC5_CODE_RED, rc5_screen_set, { 0, 0 } },
+ { RC5_CODE_GREEN, rc5_screen_set, { 1, 0 } },
+ { RC5_CODE_YELLOW, rc5_screen_set, { 2, 0 } },
+ { RC5_CODE_BLUE, rc5_screen_set, { 3, 0 } },
+ { RC5_CODE_TV_VCR, rc5_screen_set, { DISPLAY_SCREEN_TOGGLE, 0 } },
+#endif
+#ifdef JOGDIAL
+ { RC5_CODE_JOG_MID, rc5_bot_set_speed, { BOT_SPEED_MAX, BOT_SPEED_MAX } },
+ { RC5_CODE_JOG_L1, rc5_bot_set_speed, { BOT_SPEED_FAST, BOT_SPEED_MAX } },
+ { RC5_CODE_JOG_L2, rc5_bot_set_speed, { BOT_SPEED_NORMAL, BOT_SPEED_MAX } },
+ { RC5_CODE_JOG_L3, rc5_bot_set_speed, { BOT_SPEED_SLOW, BOT_SPEED_MAX } },
+ { RC5_CODE_JOG_L4, rc5_bot_set_speed, { BOT_SPEED_STOP, BOT_SPEED_MAX } },
+ { RC5_CODE_JOG_L5, rc5_bot_set_speed, { -BOT_SPEED_NORMAL, BOT_SPEED_MAX } },
+ { RC5_CODE_JOG_L6, rc5_bot_set_speed, { -BOT_SPEED_FAST, BOT_SPEED_MAX } },
+ { RC5_CODE_JOG_L7, rc5_bot_set_speed, { -BOT_SPEED_MAX, BOT_SPEED_MAX } },
+ { RC5_CODE_JOG_R1, rc5_bot_set_speed, { BOT_SPEED_MAX, BOT_SPEED_FAST } },
+ { RC5_CODE_JOG_R2, rc5_bot_set_speed, { BOT_SPEED_MAX, BOT_SPEED_NORMAL } },
+ { RC5_CODE_JOG_R3, rc5_bot_set_speed, { BOT_SPEED_MAX, BOT_SPEED_SLOW } },
+ { RC5_CODE_JOG_R4, rc5_bot_set_speed, { BOT_SPEED_MAX, BOT_SPEED_STOP } },
+ { RC5_CODE_JOG_R5, rc5_bot_set_speed, { BOT_SPEED_MAX, -BOT_SPEED_NORMAL } },
+ { RC5_CODE_JOG_R6, rc5_bot_set_speed, { BOT_SPEED_MAX, -BOT_SPEED_FAST } },
+ { RC5_CODE_JOG_R7, rc5_bot_set_speed, { BOT_SPEED_MAX, -BOT_SPEED_MAX } }
+#endif /* JOGDIAL */
+};
+
+/*!
+ * Diese Funktion setzt das Display auf eine andere Ausgabe.
+ * Fuer die Verhaltensausgabe werden hier die Verhalten durchgeblaettert
+ * @param par Parameter mit dem zu setzenden Screen.
+ */
+#ifdef DISPLAY_SCREENS_AVAILABLE
+static void rc5_screen_set(RemCtrlFuncPar *par) {
+ if (par) {
+ if (par->value1 == DISPLAY_SCREEN_TOGGLE) {
+
+ #ifdef DISPLAY_BEHAVIOUR_AVAILABLE
+ /* erst nachsehen, ob noch weitere Verhalten auf anderen Pages vorhanden sind */
+ /* nur neuer Screen, wenn alle Verhalten angezeigt wurden */
+ if ((display_screen == 2) && (another_behaviour_page())
+ )
+ behaviour_page++;
+ else {
+ display_screen ++;
+
+ if (display_screen == 1) {
+ behaviour_page = 1;
+ #ifndef DISPLAY_DYNAMIC_BEHAVIOUR_AVAILABLE
+ set_behaviours_equal();
+ #endif
+ }
+
+ }
+
+ #else
+ display_screen ++;
+ #endif
+
+
+ }
+ else
+ {
+ /* Screen direkt waehlen */
+ #ifdef DISPLAY_BEHAVIOUR_AVAILABLE
+
+ /* Screen direkt waehlen und Verhaltens-Puffervariablen abgleichen*/
+ display_screen = par->value1;
+
+ // bei dyn. Anzeige und Auswahl keine Ubernahme in Puffervariable benoetigt
+ #ifndef DISPLAY_DYNAMIC_BEHAVIOUR_AVAILABLE
+ if ((display_screen == 2)&& (behaviour_page == 1)) {
+ set_behaviours_equal();
+ }
+ #endif
+ behaviour_page = 1;
+
+ #else
+ /* Screen direkt waehlen */
+ display_screen = par->value1;
+ #endif
+ }
+
+
+ display_screen %= DISPLAY_SCREENS;
+ display_clear();
+
+ }
+}
+#endif
+
+#ifdef BEHAVIOUR_SERVO_AVAILABLE
+ /*! Steuert den Servo an
+ * @param par Parameter mit Servo-Nummer und -Position
+ */
+ void rc5_bot_servo(RemCtrlFuncPar *par){
+ bot_servo(0,par->value1,par->value2);
+ }
+#endif
+/*!
+ * Diese Funktion wechselt zwiaschen verschiednen Verhalten
+ * @param par Parameter mit den zu setzenden Geschwindigkeiten.
+ */
+void rc5_bot_next_behaviour(RemCtrlFuncPar *par) {
+
+ static uint8 state =0;
+
+ state++;
+
+ switch (state) {
+ case 0:
+ break;
+ #ifdef BEHAVIOUR_DRIVE_SQUARE_AVAILABLE
+ case 1: activateBehaviour(bot_drive_square_behaviour);
+ break;
+ #endif
+ case 2:
+ #ifdef BEHAVIOUR_DRIVE_SQUARE_AVAILABLE
+ deactivateBehaviour(bot_drive_square_behaviour);
+ #endif
+ #ifdef BEHAVIOUR_GOTO_AVAILABLE
+ deactivateBehaviour(bot_goto_behaviour);
+ #endif
+ #ifdef BEHAVIOUR_OLYMPIC_AVAILABLE
+ activateBehaviour(bot_olympic_behaviour);
+ #endif
+ break;
+ default:
+ #ifdef BEHAVIOUR_DRIVE_DISTANCE_AVAILABLE
+ deactivateBehaviour( bot_drive_distance_behaviour);
+ #endif
+ #ifdef BEHAVIOUR_TURN_AVAILABLE
+ deactivateBehaviour( bot_turn_behaviour);
+ #endif
+ #ifdef BEHAVIOUR_OLYMPIC_AVAILABLE
+ deactivateBehaviour(bot_olympic_behaviour);
+ deactivateBehaviour( bot_explore_behaviour);
+ deactivateBehaviour( bot_do_slalom_behaviour);
+ #endif
+
+ state=0;
+ }
+}
+
+#ifdef JOGDIAL
+/*!
+ * Diese Funktion setzt die Geschwindigkeit auf den angegebenen Wert.
+ * @param par Parameter mit den zu setzenden Geschwindigkeiten.
+ */
+static void rc5_bot_set_speed(RemCtrlFuncPar *par) {
+ if (par) {
+ target_speed_l = par->value1;
+ target_speed_r = par->value2;
+ }
+}
+#endif
+
+/*!
+ * Diese Funktion stellt die Not-Aus-Funktion dar. Sie laesst den Bot anhalten
+ * und setzt alle Verhalten zurueck mit Sicherung der vorherigen Aktivitaeten.
+ * @param par notwendiger Dummy-Parameter.
+ */
+ static void rc5_emergency_stop(RemCtrlFuncPar *par) {
+ #ifdef BEHAVIOUR_AVAILABLE
+ // Setzen der Geschwindigkeit auf 0
+ target_speed_l = 0 ;
+ target_speed_r = 0 ;
+
+ // Alle Verhalten deaktivieren
+ deactivateAllBehaviours(); // alle Verhalten deaktivieren mit vorheriger Sicherung
+ #ifdef DISPLAY_BEHAVIOUR_AVAILABLE
+ // bei dynamischer Verhaltensanzeige kein Sprung in Anzeigescreen
+ #ifndef DISPLAY_DYNAMIC_BEHAVIOUR_AVAILABLE
+ display_clear(); // Screen zuerst loeschen
+ display_screen = 2; // nach Notstop in den Verhaltensscreen mit Anzeige der alten Verhalten
+ #endif
+ #endif
+ #endif
+}
+
+/*!
+ * Diese Funktion aendert die Geschwindigkeit um den angegebenen Wert.
+ * @param par Parameter mit den relativen Geschwindigkeitsaenderungen.
+ */
+#ifdef BEHAVIOUR_AVAILABLE
+ static void rc5_bot_change_speed(RemCtrlFuncPar *par) {
+ int old;
+ if (par) {
+ old=target_speed_l;
+ target_speed_l += par->value1;
+ if ((target_speed_l < -BOT_SPEED_MAX)|| (target_speed_l > BOT_SPEED_MAX))
+ target_speed_l = old;
+
+ old=target_speed_r;
+ target_speed_r += par->value2;
+ if ((target_speed_r <-BOT_SPEED_MAX)||(target_speed_r > BOT_SPEED_MAX))
+ target_speed_r = old;
+ }
+ }
+#endif
+
+/*!
+ * Liest ein RC5-Codeword und wertet es aus
+ */
+void rc5_control(void){
+ uint16 run;
+ static uint16 RC5_Last_Toggle = 1; /*!< Toggle-Wert des zuletzt empfangenen RC5-Codes*/
+
+ uint16 rc5 = ir_read();
+
+ if (rc5 != 0) {
+ RC5_Code= rc5 & RC5_MASK; /* Alle uninteressanten Bits ausblenden */
+ /* Toggle kommt nicht im Simulator, immer gewechseltes Toggle Bit sicherstellen */
+ #ifdef PC
+ RC5_Last_Toggle = !(rc5 & RC5_TOGGLE);
+ #endif
+ /* Bei Aenderung des Toggle Bits, entspricht neuem Tastendruck, gehts nur weiter */
+ if ((rc5 & RC5_TOGGLE) != RC5_Last_Toggle) { /* Nur Toggle Bit abfragen, bei Ungleichheit weiter */
+ RC5_Last_Toggle = rc5 & RC5_TOGGLE; /* Toggle Bit neu belegen */
+
+ /* Suchen der auszufuehrenden Funktion */
+ for(run=0; run<sizeof(gRemCtrlAction)/sizeof(RemCtrlAction); run++) {
+ /* Funktion gefunden? */
+ if (gRemCtrlAction[run].command == RC5_Code) {
+ /* Funktion ausfuehren */
+ gRemCtrlAction[run].func(&gRemCtrlAction[run].par);
+ }
+ }
+ }
+ }
+}
+
+#ifdef DISPLAY_BEHAVIOUR_AVAILABLE
+/*!
+ * toggled ein Verhalten der Verhaltensliste an Position pos,
+ * die Aenderung erfolgt nur auf die Puffervariable
+ * @param i Verhaltens-Listenposition, entspricht der Taste 1-6 der gewaehlten Verhaltensseite
+ */
+ void rc5_toggle_behaviour_new(int8 i) {
+
+ toggleNewBehaviourPos(i);
+ }
+
+/*!
+ * Diese Funktion setzt die Aktivitaeten der Verhalten nach der Auswahl.
+ * Hierdurch erfolgt der Startschuss fuer Umschaltung der Verhalten
+ * nicht verwendet bei sofortiger Anzeige und Auswahl der Aktivitaet
+ */
+ #ifndef DISPLAY_DYNAMIC_BEHAVIOUR_AVAILABLE
+ static void rc5_set_all_behaviours(void) {
+
+ set_behaviours_active_to_new();
+
+ }
+ #endif
+#endif
+
+/*!
+ * Verarbeitet die Zifferntasten in Abhaengigkeit vom eingestelltem Screen
+ * @param par Parameter mit der betaetigten Zahlentaste.
+ */
+void rc5_number(RemCtrlFuncPar *par) {
+ #ifdef DISPLAY_SCREENS_AVAILABLE
+ switch (display_screen) {
+ #ifdef DISPLAY_BEHAVIOUR_AVAILABLE
+ case 2:
+ switch (par->value1) {
+ case 0: break;
+ case 1: rc5_toggle_behaviour_new(1); break;
+ case 2: rc5_toggle_behaviour_new(2); break;
+ case 3: rc5_toggle_behaviour_new(3); break;
+ case 4: rc5_toggle_behaviour_new(4); break;
+ case 5: rc5_toggle_behaviour_new(5); break;
+ case 6: rc5_toggle_behaviour_new(6); break;
+ case 7: break;
+ case 8: break;
+ case 9:
+ #ifndef DISPLAY_DYNAMIC_BEHAVIOUR_AVAILABLE
+ rc5_set_all_behaviours();
+ #endif
+ break;
+ }
+ break;
+ #endif
+ default:
+ #endif
+ switch (par->value1) {
+ #ifdef BEHAVIOUR_AVAILABLE
+ case 0:
+ target_speed_l=0;target_speed_r=0;break;
+ case 1: target_speed_l = BOT_SPEED_SLOW; target_speed_r = BOT_SPEED_SLOW; break;
+ #endif
+ #ifdef BEHAVIOUR_DRIVE_DISTANCE_AVAILABLE
+ case 2: bot_drive_distance(0, 0, BOT_SPEED_NORMAL, 10); break;
+ #endif
+ // case 3: target_speed_l = BOT_SPEED_NORMAL; target_speed_r = BOT_SPEED_NORMAL; break;
+ #ifdef MAP_AVAILABLE
+ case 3: print_map(); break;
+ #endif
+// case 4: bot_turn(0, 90); break;
+ #ifdef BEHAVIOUR_SCAN_AVAILABLE
+ case 4: bot_scan(0); break;
+ #endif
+// //case 5: bot_goto(0, 0, 0); break;
+// #ifdef MEASURE_MOUSE_AVAILABLE
+// case 5: bot_gotoxy(0,20,20);
+// #else
+
+ case 5: remote_call_list(); break;
+
+
+ #ifdef BEHAVIOUR_SOLVE_MAZE_AVAILABLE
+// case 5: bot_solve_maze(0); break;
+ #endif
+ #ifdef BEHAVIOUR_CATCH_PILLAR_AVAILABLE
+// case 5: bot_catch_pillar(0); break;
+ #endif
+
+// case 5: target_speed_l = BOT_SPEED_MAX; target_speed_r = BOT_SPEED_MAX; break;
+// #endif
+// case 5: bot_scan(0); break;
+ #ifdef BEHAVIOUR_TURN_AVAILABLE
+ case 6: bot_turn(0, -90); break;
+ case 7: bot_turn(0,180); break;
+ case 9: bot_turn(0, -180); break;
+ #endif
+ #ifdef BEHAVIOUR_DRIVE_DISTANCE_AVAILABLE
+ case 8: bot_drive_distance(0, 0, BOT_SPEED_NORMAL, 10); break;
+ #endif
+
+// case 0: target_speed_l=BOT_SPEED_STOP;target_speed_r=target_speed_l;break;
+// case 1: target_speed_l=BOT_SPEED_SLOW;target_speed_r=target_speed_l;break;
+// case 2: target_speed_l=BOT_SPEED_MEDIUM;target_speed_r=target_speed_l;break;
+// case 3: target_speed_l=BOT_SPEED_FAST;target_speed_r=target_speed_l;break;
+// case 4: target_speed_l=BOT_SPEED_MAX;target_speed_r=target_speed_l;break;
+
+// case 5: Kp++; break;
+// case 8: Kp--; break;
+// case 6: Ki++; break;
+// case 9: Ki--; break;
+
+// case 9: target_speed_l=-BOT_SPEED_MEDIUM;target_speed_r=target_speed_l;break;
+ }
+ #ifdef DISPLAY_SCREENS_AVAILABLE
+
+ break;
+
+ }
+ #endif
+ }
+#endif
diff --git a/source/ct-Bot/sensor.c b/source/ct-Bot/sensor.c
new file mode 100644
index 0000000..7029d42
--- /dev/null
+++ b/source/ct-Bot/sensor.c
@@ -0,0 +1,347 @@
+/*
+ * c't-Sim - Robotersimulator fuer den c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file sensor.c
+ * @brief Architekturunabhaengiger Teil der Sensorsteuerung
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 15.01.05
+*/
+#include <stdio.h>
+#include "ct-Bot.h"
+#include "timer.h"
+#include "bot-local.h"
+#include "math.h"
+#include "sensor_correction.h"
+#ifdef SRF10_AVAILABLE
+ #include "srf10.h"
+#endif
+
+// Defines einiger, haeufiger benoetigter Konstanten
+#define DEG2RAD (2*M_PI/360)
+
+
+int16 sensLDRL=0; /*!< Lichtsensor links */
+int16 sensLDRR=0; /*!< Lichtsensor rechts */
+
+int16 sensDistL=1023; /*!< Distanz linker IR-Sensor in [mm], wenn korrekt umgerechnet wird */
+int16 sensDistR=1023; /*!< Distanz rechter IR-Sensor in [mm], wenn korrekt umgerechnet wird */
+
+int16 sensBorderL=0; /*!< Abgrundsensor links */
+int16 sensBorderR=0; /*!< Abgrundsensor rechts */
+
+int16 sensLineL=0; /*!< Lininensensor links */
+int16 sensLineR=0; /*!< Lininensensor rechts */
+
+uint8 sensTrans=0; /*!< Sensor Ueberwachung Transportfach */
+
+uint8 sensDoor=0; /*!< Sensor Ueberwachung Klappe */
+
+uint8 sensError=0; /*!< Ueberwachung Motor oder Batteriefehler */
+
+#ifdef MAUS_AVAILABLE
+
+ int8 sensMouseDX; /*!< Maussensor Delta X, positive Werte zeigen querab der Fahrtrichtung nach rechts */
+ int8 sensMouseDY; /*!< Maussensor Delta Y, positive Werte zeigen in Fahrtrichtung */
+
+ int16 sensMouseX; /*!< Mausposition X, positive Werte zeigen querab der Fahrtrichtung nach rechts */
+ int16 sensMouseY; /*!< Mausposition Y, positive Werte zeigen in Fahrtrichtung */
+#endif
+
+volatile int16 sensEncL=0; /*!< Encoder linkes Rad */
+volatile int16 sensEncR=0; /*!< Encoder rechtes Rad */
+float heading_enc=0; /*!< Blickrichtung aus Encodern */
+float x_enc=0; /*!< X-Koordinate aus Encodern [mm] */
+float y_enc=0; /*!< Y-Koordinate aus Encodern [mm] */
+float v_enc_left=0; /*!< Abrollgeschwindigkeit des linken Rades in [mm/s] [-128 bis 127] relaisitisch [-50 bis 50] */
+float v_enc_right=0; /*!< Abrollgeschwindigkeit des linken Rades in [mm/s] [-128 bis 127] relaisitisch [-50 bis 50] */
+float v_enc_center=0; /*!< Schnittgeschwindigkeit ueber beide Raeder */
+
+#ifdef PC
+ uint16 simultime=0; /*! Simulierte Zeit */
+#endif
+
+#ifdef MEASURE_MOUSE_AVAILABLE
+ float heading_mou=0; /*!< Aktuelle Blickrichtung relativ zur Startposition aus Mausmessungen */
+ float x_mou=0; /*!< Aktuelle X-Koordinate in mm relativ zur Startposition aus Mausmessungen */
+ float y_mou=0; /*!< Aktuelle Y-Koordinate in mm relativ zur Startposition aus Mausmessungen */
+ float v_mou_center=0; /*!< Geschwindigkeit in mm/s ausschliesslich aus den Maussensorwerten berechnet */
+ float v_mou_left=0; /*!< ...aufgeteilt auf linkes Rad */
+ float v_mou_right=0; /*!< ...aufgeteilt auf rechtes Rad */
+#endif
+
+float heading=0; /*!< Aktuelle Blickrichtung aus Encoder-, Maus- oder gekoppelten Werten */
+float x_pos=0; /*!< Aktuelle X-Position aus Encoder-, Maus- oder gekoppelten Werten */
+float y_pos=0; /*!< Aktuelle Y-Position aus Encoder-, Maus- oder gekoppelten Werten */
+float v_left=0; /*!< Geschwindigkeit linkes Rad aus Encoder-, Maus- oder gekoppelten Werten */
+float v_right=0; /*!< Geschwindigkeit rechtes Rad aus Encoder-, Maus- oder gekoppelten Werten */
+float v_center=0; /*!< Geschwindigkeit im Zentrum des Bots aus Encoder-, Maus- oder gekoppelten Werten */
+
+int8 sensors_initialized = 0; /*!< Wird 1 sobald die Sensorwerte zur Verfügung stehen */
+
+#ifdef SRF10_AVAILABLE
+ uint16 sensSRF10; /*!< Messergebniss Ultraschallsensor */
+#endif
+
+
+/*! Linearisiert die Sensorwerte
+ * @param left Linker Rohwert [0-1023]
+ * @param right Rechter Rohwert [0-1023]
+ */
+void sensor_abstand(uint16 left, uint16 right){
+ if (left == SENSDISTOFFSETLEFT) // Vermeidet Div/0
+ left++;
+ sensDistL = SENSDISTSLOPELEFT / (left - SENSDISTOFFSETLEFT);
+ // Korrigieren, wenn ungueltiger Wert
+ if (sensDistL > SENS_IR_MAX_DIST || sensDistL<=0)
+ sensDistL=SENS_IR_INFINITE;
+
+ if (right == SENSDISTOFFSETRIGHT) // Vermeidet Div/0
+ right++;
+ sensDistR = SENSDISTSLOPERIGHT / (right - SENSDISTOFFSETRIGHT);
+ // Korrigieren, wenn ungueltiger Wert
+ if (sensDistR > SENS_IR_MAX_DIST || sensDistR<=0)
+ sensDistR=SENS_IR_INFINITE;
+}
+
+/*! Sensor_update
+* Kuemmert sich um die Weiterverarbeitung der rohen Sensordaten
+*/
+void sensor_update(void){
+ static uint16 old_pos=0; /*!< Ticks fuer Positionsberechnungsschleife */
+ static uint16 old_speed=0; /*!< Ticks fuer Geschwindigkeitsberechnungsschleife */
+ #ifdef MEASURE_MOUSE_AVAILABLE
+ static int16 lastMouseX=0; /*!< letzter Mauswert X fuer Positionsberechnung */
+ static int16 lastMouseY=0; /*!< letzter Mauswert Y fuer Positionsberechnung */
+ static float lastDistance=0; /*!< letzte gefahrene Strecke */
+ static float lastHead=0; /*!< letzter gedrehter Winkel */
+ static float oldHead=0; /*!< Winkel aus dem letzten Durchgang */
+ static float old_x=0; /*!< Position X aus dem letzten Durchgang */
+ static float old_y=0; /*!< Position Y aus dem letzten Durchgang */
+ float radius=0; /*!< errechneter Radius des Drehkreises */
+ float s1=0; /*!< Steigung der Achsengerade aus dem letzten Durchgang */
+ float s2=0; /*!< Steigung der aktuellen Achsengerade */
+ float a1=0; /*!< Y-Achsenabschnitt der Achsengerade aus dem letzten Durchgang */
+ float a2=0; /*!< Y-Achsenabschnitt der aktuellen Achsengerade */
+ float xd=0; /*!< X-Koordinate Drehpunkt */
+ float yd=0; /*!< Y-Koordinate Drehpunkt */
+ float right_radius=0; /*!< Radius des Drehkreises des rechten Rads */
+ float left_radius=0; /*!< Radius des Drehkreises des linken Rads */
+ #endif
+ static int16 lastEncL =0; /*!< letzter Encoderwert links fuer Positionsberechnung */
+ static int16 lastEncR =0; /*!< letzter Encoderwert rechts fuer Positionsberechnung */
+ static int16 lastEncL1=0; /*!< letzter Encoderwert links fuer Geschwindigkeitsberechnung */
+ static int16 lastEncR1=0; /*!< letzter Encoderwert rechts fuer Geschwindigkeitsberechnung */
+ float dHead=0; /*!< Winkeldifferenz aus Encodern */
+ float deltaY=0; /*!< errechneter Betrag Richtungsvektor aus Encodern */
+ int16 diffEncL; /*!< Differenzbildung linker Encoder */
+ int16 diffEncR; /*!< Differenzbildung rechter Encoder */
+ float sl; /*!< gefahrene Strecke linkes Rad */
+ float sr; /*!< gefahrene Strecke rechtes Rad */
+ #ifdef MEASURE_MOUSE_AVAILABLE
+ int16 dX; /*!< Differenz der X-Mauswerte */
+ int16 dY; /*!< Differenz der Y-Mauswerte */
+ int8 modifiedAngles=False; /*!< Wird True, wenn aufgrund 90 Grad oder 270 Grad die Winkel veraendert werden mussten */
+
+ sensMouseY += sensMouseDY; /*!< Mausdelta Y aufaddieren */
+ sensMouseX += sensMouseDX; /*!< Mausdelta X aufaddieren */
+ #endif
+
+ register uint16 ticks = TIMER_GET_TICKCOUNT_16;
+ if (ticks-old_pos > MS_TO_TICKS(50)){
+ old_pos = ticks;
+ /* Gefahrene Boegen aus Encodern berechnen */
+ diffEncL=sensEncL-lastEncL;
+ diffEncR=sensEncR-lastEncR;
+ lastEncL=sensEncL;
+ lastEncR=sensEncR;
+ sl=(float)diffEncL*WHEEL_PERIMETER/ENCODER_MARKS;
+ sr=(float)diffEncR*WHEEL_PERIMETER/ENCODER_MARKS;
+ /* Winkel berechnen */
+ dHead=(float)(sr-sl)/(2*WHEEL_DISTANCE);
+ /* Winkel ist hier noch im Bogenmass */
+ /* Position berechnen */
+ /* dazu Betrag des Vektors berechnen */
+ if (dHead==0) {
+ /* Geradeausfahrt, deltaY=diffEncL=diffEncR */
+ deltaY=sl;
+ } else {
+ /* Laenge berechnen aus alpha/2 */
+ deltaY=(sl+sr)*sin(dHead/2)/dHead;
+ }
+ /* Winkel in Grad umrechnen */
+ dHead=dHead/DEG2RAD;
+
+ /* neue Positionen berechnen */
+ heading_enc+=dHead;
+ while (heading_enc>=360) heading_enc=heading_enc-360;
+ while (heading_enc<0) heading_enc=heading_enc+360;
+
+ x_enc+=(float)deltaY*cos(heading_enc*DEG2RAD);
+ y_enc+=(float)deltaY*sin(heading_enc*DEG2RAD);
+ #ifdef MEASURE_MOUSE_AVAILABLE
+ dX=sensMouseX-lastMouseX;
+ /* heading berechnen */
+ dHead=(float)dX*360/MOUSE_FULL_TURN;
+ heading_mou+=dHead;
+ lastHead+=dHead;
+ if (heading_mou>=360) heading_mou=heading_mou-360;
+ if (heading_mou<0) heading_mou=heading_mou+360;
+ /* x/y pos berechnen */
+ dY=sensMouseY-lastMouseY;
+ x_mou+=(float)dY*cos(heading_mou*DEG2RAD)*25.4/MOUSE_CPI;
+ lastDistance+=dY*25.4/MOUSE_CPI;
+ y_mou+=(float)dY*sin(heading_mou*DEG2RAD)*25.4/MOUSE_CPI;
+
+ lastMouseX=sensMouseX;
+ lastMouseY=sensMouseY;
+ #endif
+ #ifdef MEASURE_COUPLED_AVAILABLE
+ /* Werte der Encoder und der Maus mit dem Faktor G_POS verrechnen */
+ x_pos=G_POS*x_mou+(1-G_POS)*x_enc;
+ y_pos=G_POS*y_mou+(1-G_POS)*y_enc;
+ /* Korrektur, falls mou und enc zu unterschiedlichen Seiten zeigen */
+ if (fabs(heading_mou-heading_enc) > 180) {
+ /* wir nutzen zum Rechnen zwei Drehrichtungen */
+ heading = heading_mou<=180 ? heading_mou*G_POS : (heading_mou-360)*G_POS;
+ heading += heading_enc<=180 ? heading_enc*(1-G_POS) : (heading_enc-360)*(1-G_POS);
+ /* wieder auf eine Drehrichtung zurueck */
+ if (heading < 0) heading += 360;
+ } else
+ heading = G_POS*heading_mou + (1-G_POS)*heading_enc;
+ if (heading >= 360) heading -= 360;
+ #else
+ #ifdef MEASURE_MOUSE_AVAILABLE
+ /* Mauswerte als Standardwerte benutzen */
+ heading=heading_mou;
+ x_pos=x_mou;
+ y_pos=y_mou;
+ #else
+ /* Encoderwerte als Standardwerte benutzen */
+ heading=heading_enc;
+ x_pos=x_enc;
+ y_pos=y_enc;
+ #endif
+ #endif
+ }
+ ticks = TIMER_GET_TICKCOUNT_16;
+ if (ticks-old_speed > MS_TO_TICKS(250)){
+ old_speed=ticks;
+ v_enc_left= (((sensEncL - lastEncL1) * WHEEL_PERIMETER) / ENCODER_MARKS)*4;
+ v_enc_right= (((sensEncR - lastEncR1) * WHEEL_PERIMETER) / ENCODER_MARKS)*4;
+ v_enc_center=(v_enc_left+v_enc_right)/2;
+ lastEncL1= sensEncL;
+ lastEncR1= sensEncR;
+ #ifdef MEASURE_MOUSE_AVAILABLE
+ /* Speed aufgrund Maussensormessungen */
+ v_mou_center=lastDistance*4;
+ /* Aufteilung auf die Raeder zum Vergleich mit den Radencodern */
+ /* Sonderfaelle pruefen */
+ if (oldHead==90 || oldHead==270 || heading_mou==90 || heading_mou==270) {
+ float temp;
+ /* winkel um 90 Grad vergroessern */
+ oldHead+=90;
+ heading_mou+=90;
+ // Koordinaten anpassen
+ temp=old_x;
+ old_x=old_y;
+ old_y=-temp;
+ temp=x_mou;
+ x_mou=y_mou;
+ y_mou=-temp;
+ modifiedAngles=True;
+ }
+
+ /* Steigungen berechnen */
+ s1=-tan(oldHead*DEG2RAD);
+ s2=-tan(heading_mou*DEG2RAD);
+
+ /* Geradeausfahrt? (s1==s2) */
+ if (s1==s2) {
+ /* Bei Geradeausfahrt ist v_left==v_right==v_center */
+ v_mou_left=v_mou_right=v_mou_center;
+ } else {
+ /* y-Achsenabschnitte berechnen */
+ a1=old_x-s1*old_y;
+ a2=x_mou-s2*y_mou;
+ /* Schnittpunkt berechnen */
+ yd=(a2-a1)/(s1-s2);
+ xd=s2*yd+a2;
+ /* Radius ermitteln */
+ radius=sqrt((x_mou-xd)*(x_mou-xd)+(y_mou-yd)*(y_mou-yd));
+ /* Vorzeichen des Radius feststellen */
+ if (lastHead<0) {
+ /* Drehung rechts, Drehpunkt liegt rechts vom Mittelpunkt
+ * daher negativer Radius */
+ radius=-radius;
+ }
+ if (v_mou_center<0) {
+ /* rueckwaerts => links und rechts vertauscht, daher VZ vom Radius umdrehen */
+ radius=-radius;
+ }
+ /* Geschwindigkeiten berechnen */
+ right_radius=radius+WHEEL_DISTANCE;
+ left_radius=radius-WHEEL_DISTANCE;
+ v_mou_right=lastHead/360*2*M_PI*right_radius*4;
+ v_mou_left=lastHead/360*2*M_PI*left_radius*4;
+ }
+ /* Falls Koordinaten/Winkel angepasst wurden, nun wieder korrigieren */
+ if (modifiedAngles){
+ float temp;
+ /* Winkel wieder um 90 Grad reduzieren */
+ oldHead-=90;
+ heading_mou-=90;
+ /* Koordinaten wieder korrigieren */
+ temp=old_x;
+ old_x=-old_y;
+ old_y=temp;
+ temp=x_mou;
+ x_mou=-y_mou;
+ y_mou=temp;
+ }
+ lastDistance=0;
+ lastHead=0;
+ old_x=x_mou;
+ old_y=y_mou;
+ oldHead=heading_mou;
+ #endif
+ #ifdef MEASURE_COUPLED_AVAILABLE
+ v_left=G_SPEED*v_mou_left+(1-G_SPEED)*v_enc_left;
+ v_right=G_SPEED*v_mou_right+(1-G_SPEED)*v_enc_left;
+ v_center=G_SPEED*v_mou_center+(1-G_SPEED)*v_enc_center;
+ #else
+ #ifdef MEASURE_MOUSE_AVAILABLE
+ /* Mauswerte als Standardwerte benutzen */
+ v_left=v_mou_left;
+ v_right=v_mou_right;
+ v_center=v_mou_center;
+ #else
+ /* Encoderwerte als Standardwerte benutzen */
+ v_left=v_enc_left;
+ v_right=v_enc_right;
+ v_center=v_enc_center;
+ #endif
+ #endif
+ #ifdef SRF10_AVAILABLE
+ sensSRF10 = srf10_get_measure(); /*!< Messung Ultraschallsensor */
+ #endif
+ }
+
+ sensors_initialized=1;
+}
+
diff --git a/source/ct-Bot/timer.c b/source/ct-Bot/timer.c
new file mode 100644
index 0000000..c7c3208
--- /dev/null
+++ b/source/ct-Bot/timer.c
@@ -0,0 +1,115 @@
+/*
+ * c't-Bot
+ *
+ * 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.
+ *
+ */
+
+/*! @file timer.c
+ * @brief Zeitmanagement
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 26.12.05
+*/
+
+#include "ct-Bot.h"
+#include "timer.h"
+
+#ifdef PC
+ #include <pthread.h>
+ #include "sensor.h"
+#endif /* PC */
+
+#ifdef PC
+ /*! Schuetzt die Zeitsynchronisation */
+ #define LOCK() pthread_mutex_lock(&timer_mutex);
+ /*! Hebt den Schutz fuer die Zeitsynchronisation wieder auf */
+ #define UNLOCK() pthread_mutex_unlock(&timer_mutex);
+#else
+ /*! Schuetzt die Zeitsynchronisation */
+ #define LOCK() /* ISR */
+ /*! Hebt den Schutz fuer die Zeitsynchronisation wieder auf */
+ #define UNLOCK() /* ISR */
+#endif /* PC */
+
+#ifdef PC
+ /*! Schuetzt die Zeitvariablen */
+ static pthread_mutex_t timer_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif /* PC */
+
+#ifdef MCU
+ volatile tickCount_t tickCount; /*!< ein Tick alle 176 us */
+#else
+ float tickCount=0;
+#endif
+
+#ifdef PC
+ inline uint16 timer_get_tickCount16(void){
+ uint16 temp;
+ LOCK();
+ temp = tickCount;
+ UNLOCK();
+ return temp;
+ }
+
+ inline uint32 timer_get_tickCount32(void){
+ uint32 temp;
+ LOCK();
+ temp = tickCount;
+ UNLOCK();
+ return temp;
+ }
+#endif
+
+#ifdef TIME_AVAILABLE
+ /*!
+ * Diese Funktion liefert den Millisekundenanteil der Systemzeit zurueck.
+ * @return uint16
+ */
+ uint16 timer_get_ms(void){
+ return ((TIMER_GET_TICKCOUNT_32*(TIMER_STEPS/8))/(1000/8))%1000;
+ }
+
+ /*!
+ * Diese Funktion liefert den Sekundenanteil der Systemzeit zurueck.
+ * @return uint16
+ */
+ uint16 timer_get_s(void){
+ return TIMER_GET_TICKCOUNT_32*(TIMER_STEPS/16)/(1000000/16);
+ }
+
+ /*!
+ * Liefert die Millisekunden zurueck, die seit old_s, old_ms verstrichen sind
+ * @param old_s alter Sekundenstand
+ * @param old_ms alter Millisekundenstand
+ */
+ uint16 timer_get_ms_since(uint16 old_s, uint16 old_ms){
+ return (timer_get_s()-old_s)*1000 + timer_get_ms()-old_ms;
+ }
+#endif // TIME_AVAILABLE
+
+#ifdef PC
+ /*!
+ * Funktion, die die TickCounts um die vergangene Simulzeit erhoeht
+ */
+ void system_time_isr(void){
+ LOCK();
+ /* TickCounter [176 us] erhoehen */
+ static uint16 last_simultime=0;
+ if (simultime < last_simultime) last_simultime -= 10000; // der Sim setzt simultime alle 10s zurueck auf 0
+ tickCount += MS_TO_TICKS((float)(simultime - last_simultime));
+ last_simultime = simultime;
+ UNLOCK();
+ }
+#endif
diff --git a/source/qFix/qfix.h b/source/qFix/qfix.h
new file mode 100644
index 0000000..0a5d039
--- /dev/null
+++ b/source/qFix/qfix.h
@@ -0,0 +1,96 @@
+//------------------------------------------------------------------
+// qfix.h
+//
+// This file contains general includes and definitions for the
+// family of qfix boards.
+//
+// Copyright 2004-2006 by KTB mechatronics GmbH
+// Author: Stefan Enderle
+//------------------------------------------------------------------
+
+#ifndef qfix_h
+#define qfix_h
+
+
+#include <inttypes.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+
+
+/* defines for compatibility */
+#ifndef cbi
+#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
+#endif
+#ifndef sbi
+#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
+#endif
+#ifndef BV
+#define BV _BV
+#endif
+
+
+
+/** Returns the absolute value of a
+*/
+inline
+int abs(int a)
+{
+ if (a>=0) return a;
+ else return -a;
+}
+
+
+
+/** Sleeps for sec seconds. (Note: this is tuned for
+* an Atmel ATmega32 running with 8 MHz.)
+*/
+inline
+void sleep(int sec)
+{
+ for (int s=0; s<sec; s++) {
+ for (long int i=0; i<702839; i++) {
+ asm volatile("nop");
+ }
+ }
+}
+
+
+/** Sleeps for msec milliseconds. (Note: this is tuned for
+* an Atmel ATmega32 running with 8 MHz.)
+*/
+inline
+void msleep(int msec)
+{
+ for (int s=0; s<msec; s++) {
+ for (long int i=0; i<703; i++) {
+ asm volatile("nop");
+ }
+ }
+}
+
+
+
+
+/** Translates the given number into a string which ends
+* with 0.
+*/
+inline
+void num2str(int num, char* str)
+{
+ bool showZero = false;
+ int i=0;
+ int n=abs(num);
+
+ if (num<0) str[i++]='-';
+
+ if (n>=10000 || showZero) { str[i++]=(n/10000)+'0'; n=n % 10000; showZero=true; }
+ if (n>=1000 || showZero) { str[i++]=(n/1000) +'0'; n=n % 1000; showZero=true; }
+ if (n>=100 || showZero) { str[i++]=(n/100) +'0'; n=n % 100; showZero=true; }
+ if (n>=10 || showZero) { str[i++]=(n/10) +'0'; n=n % 10; showZero=true; }
+ str[i++]=n +'0'; // last digit
+ str[i++]=0; // ending 0
+}
+
+
+#endif
+
diff --git a/source/qFix/qfixBobbyBoard.h b/source/qFix/qfixBobbyBoard.h
new file mode 100644
index 0000000..c2f04a4
--- /dev/null
+++ b/source/qFix/qfixBobbyBoard.h
@@ -0,0 +1,344 @@
+//------------------------------------------------------------------
+// qfixBobbyBoard.h
+//
+// This file contains the class BobbyBoard which represents the
+// physical BobbyBoard with all its inputs and outputs.
+//
+// Copyright 2004-2006 by KTB mechatronics GmbH
+// Author: Stefan Enderle
+//------------------------------------------------------------------
+
+
+#include "qfix.h"
+
+
+#ifndef qfixBobbyBoard_h
+#define qfixBobbyBoard_h
+
+
+static int speedMotor0 = 0;
+static int speedMotor1 = 0;
+
+
+/**
+* \class BobbyBoard
+* \brief Represents the controller board "BobbyBoard".
+* \author Stefan Enderle
+*
+* The class BobbyBoard represents the
+* physical BobbyBoard with all its inputs and outputs.
+* With this class it is possible to drive the motors,
+* put on LEDs, check the buttons and get data from the
+* analog and digital inputs.
+*/
+class BobbyBoard
+{
+
+public:
+ /** Constructor for the BobbyBoard class. All LEDs and motors are put off,
+ * the power outputs are put on.
+ */
+ BobbyBoard();
+
+ /** Puts on LED i. i must be 0..3
+ * \see ledOff
+ */
+ void ledOn(int i);
+
+ /** Puts off LED i. i must be 0..3
+ * \see ledOn
+ */
+ void ledOff(int i);
+
+ /** Puts off all LEDs.
+ */
+ void ledsOff();
+
+ /** Puts LED i on if state is true, else off. i must be 0..3
+ * \see ledOn, ledOff
+ */
+ void led(int i, bool state);
+
+ /** Puts the power output i on. i must be 0..3
+ * \see powerOff
+ */
+ void powerOn(int i);
+
+ /** Puts the power output i off. i must be 0..3
+ * \see powerOn
+ */
+ void powerOff(int i);
+
+ /** Puts the power output i on if state is true, else off. i must be 0..3
+ * \see powerOn, powerOff
+ */
+ void power(int i, bool state);
+
+ /** Checks the state of button i. If it is pressed, true is returned,
+ * else false. i must be 0..3
+ * \see waitForButton
+ */
+ bool button(int i);
+
+ /** Uses the four LEDs on the board to display the value i
+ * with 0 <= i <= 255
+ */
+ void ledMeter(int i);
+
+ /** Sets motor i to the given speed. -255 <= speed <= 255
+ * \see motors
+ */
+ void motor(int i, int speed);
+
+ /** Sets both motors to the given speed. -255 <= speed <= 255
+ * \see motor
+ */
+ void motors(int speed0, int speed1);
+
+ /** Puts off both motors.
+ * \see motor, motors
+ */
+ void motorsOff();
+
+ /** returns the value of the analog port i. i must be 0..3
+ * \see digital
+ */
+ int analog(int i);
+
+ /** returns true if the digital port is logical high, else false. i must be 0..3
+ * \see analog
+ */
+ bool digital(int i);
+
+ /** Waits until button i is pressed and released again. i must be 0..3
+ * \see button
+ */
+ void waitForButton(int i);
+
+ /** Waits for i seconds.
+ */
+ void sleep(int i);
+
+ /** Waits for i milliseconds.
+ */
+ void msleep(int i);
+};
+
+
+
+
+
+
+
+// PWM routine //
+SIGNAL (SIG_OVERFLOW0)
+{
+ const int OFFSET=50; // motor does not work with very low ratio
+ static int counter=255+OFFSET;
+
+ if (speedMotor0==0) cbi(PORTC, 2); // enable1 = 0
+ else if (abs(speedMotor0)+OFFSET >= counter) sbi(PORTC, 2); // enable1 = 1
+ else cbi(PORTC, 2); // enable1 = 0
+
+ if (speedMotor1==0) cbi(PORTC, 3); // enable1 = 0
+ else if (abs(speedMotor1)+OFFSET >= counter) sbi(PORTC, 3); // enable2 = 1
+ else cbi(PORTC, 3); // enable2 = 0
+
+ if (counter==0) counter=255+OFFSET;
+ else counter--;
+}
+
+
+
+void initTimer()
+{
+ TCCR0=1; // timer 0 for interrupt
+ TIMSK=1;
+ sei(); // enable interrupts
+}
+
+
+
+BobbyBoard::BobbyBoard()
+{
+ // PORT A: Analog In + buttons //
+ DDRA=0; // all bits input
+ PORTA=16+32+64+128; // set pullups for buttons
+ ADCSRA=128; // set A/D enable bit (ADEN)
+
+ // PORT B: LEDs + digital Input //
+ DDRB = 16+32+64+128; // upper bits output: LEDs
+ PORTB |= 16+32+64+128; // set bits 5 to 8 -> LEDs off
+ PORTB |= 1+2+4+8; // set pullups for digital inputs
+
+ // PORT C: I2C and motors //
+ DDRC = 255-1-2; // direction port C, all bits output except I2C
+ PORTC = 1+2; // clear bits 2-7 -> motors off; set bits 0,1 -> I2C pullUps
+
+ // PORT D: Power Output //
+ DDRD = 255; // direction port D, all bits output
+ PORTD = 0; // clear all bits -> power on
+
+ initTimer();
+}
+
+
+void BobbyBoard::ledOn(int i)
+{
+ if ((i<0) || (i>3)) return;
+ cbi(PORTB, i+4); // clear bit -> LED on
+}
+
+
+void BobbyBoard::ledOff(int i)
+{
+ if ((i<0) || (i>3)) return;
+ sbi(PORTB, i+4); // set bit -> LED off
+}
+
+void BobbyBoard::ledsOff()
+{
+ PORTB|=128+64+32+16; // set high bits -> LEDs off
+}
+
+
+void BobbyBoard::led(int i, bool state)
+{
+ if (state) ledOn(i); else ledOff(i);
+}
+
+
+void BobbyBoard::powerOn(int i)
+{
+ if ((i<0) || (i>7)) return;
+ cbi(PORTD, i);
+}
+
+
+void BobbyBoard::powerOff(int i)
+{
+ if ((i<0) || (i>7)) return;
+ sbi(PORTD, i);
+}
+
+
+void BobbyBoard::power(int i, bool state)
+{
+ if (state) powerOn(i); else powerOff(i);
+}
+
+
+bool BobbyBoard::button(int i)
+{
+ if ((i<0) || (i>3)) return false;
+ return ( (PINA & (16<<i)) == 0);
+}
+
+
+void BobbyBoard::ledMeter(int i)
+{
+ led(0, (i>50));
+ led(1, (i>100));
+ led(2, (i>150));
+ led(3, (i>200));
+}
+
+
+void BobbyBoard::motor(int i, int speed)
+{
+ if ((i<0) || (i>1)) return;
+
+ if (i==0) {
+ speedMotor0 = speed;
+ if (speed==0) {
+ cbi(PORTC, 4); // input1 = 0
+ cbi(PORTC, 5); // input2 = 0
+ }
+ else if (speed>0) {
+ sbi(PORTC, 4); // input1 = 1
+ cbi(PORTC, 5); // input2 = 0
+
+ }
+ else {
+ cbi(PORTC, 4); // input1 = 0
+ sbi(PORTC, 5); // input2 = 1
+ }
+ }
+
+ if (i==1) {
+ speedMotor1 = speed;
+ if (speed==0) {
+ cbi(PORTC, 6); // input3 = 0
+ cbi(PORTC, 7); // input4 = 0
+ }
+ else if (speed>0){
+ sbi(PORTC, 6); // input3 = 1
+ cbi(PORTC, 7); // input4 = 0
+ }
+ else {
+ cbi(PORTC, 6); // input3 = 0
+ sbi(PORTC, 7); // input4 = 1
+ }
+ }
+}
+
+
+void BobbyBoard::motors(int motor0, int motor1)
+{
+ motor(0,motor0);
+ motor(1,motor1);
+}
+
+
+void BobbyBoard::motorsOff()
+{
+ motor(0,0);
+ motor(1,0);
+}
+
+
+// return 0-255 //
+int BobbyBoard::analog(int i)
+{
+ if ((i<0) || (i>3)) return -1;
+
+ ADMUX=i; // select analog input and start A/D
+ sbi(ADMUX, ADLAR); // left adjust -> we use only ADCH
+ sbi(ADCSRA, ADSC); // start conversion
+ while (ADCSRA & 64); // wait until ADSC is low again
+ int value = ADCH; // read 8 bit value fom ADCH
+ return value;
+}
+
+
+bool BobbyBoard::digital(int i)
+{
+ if ((i<0) || (i>3)) return false; // bad solution...
+
+ return (PINB & (1<<i)) ;
+}
+
+
+void BobbyBoard::waitForButton(int i)
+{
+ if ((i<0) || (i>3)) return; // bad solution...
+ while (!button(i)) { /* do nothing */ }
+ while (button(i)) { /* do nothing */ }
+}
+
+
+void BobbyBoard::sleep(int i)
+{
+ ::sleep(i);
+}
+
+
+void BobbyBoard::msleep(int i)
+{
+ ::msleep(i);
+}
+
+
+
+#endif
+
diff --git a/source/qFix/qfixCAN128Board.h b/source/qFix/qfixCAN128Board.h
new file mode 100644
index 0000000..a10b288
--- /dev/null
+++ b/source/qFix/qfixCAN128Board.h
@@ -0,0 +1,322 @@
+//------------------------------------------------------------------
+// qfixCAN128Board.h
+//
+// This file contains the class CAN128Board which represents the
+// physical Can128Board with all its inputs and outputs.
+//
+// Copyright 2005-2006 by KTB mechatronics GmbH
+// Author: Stefan Enderle, Florian Schrapp
+//------------------------------------------------------------------
+
+
+#ifndef qfixCAN128Board_h
+#define qfixCAN128Board_h
+
+#include "qfix.h"
+
+
+static int speedMotor0 = 50;
+static int speedMotor1 = 50;
+
+
+
+class CAN128Board
+{
+public:
+ /** Constructor for the robot board class.
+ */
+ CAN128Board();
+
+ /** Puts on LED i
+ */
+ void ledOn(int i);
+
+ /** Puts off LED i
+ */
+ void ledOff(int i);
+
+ /** Puts off all LEDs
+ */
+ void ledsOff();
+
+ /** Puts LED i on if state is true, else off
+ */
+ void led(int i, bool state);
+
+ /** Uses the four LEDs on the board to display the value i
+ * with 0 <= i <= 255
+ */
+ void ledMeter(int i);
+
+ /** Puts the power output i on
+ */
+ void powerOn(int i);
+
+ /** Puts the power output i off
+ */
+ void powerOff(int i);
+
+ /** Puts the power output i on if state is true, else off
+ */
+ void power(int i, bool state);
+
+ /** Checks the state of button i. If it is pressed, true is returned,
+ * else false.
+ */
+ bool button(int i);
+
+ /** Sets motor i to the given speed. -255 <= speed <= 255
+ */
+ void motor(int i, int speed);
+
+ /** Sets both motors to the given speed. -255 <= speed <= 255
+ */
+ void motors(int speed0, int speed1);
+
+ /** Puts off both motors.
+ */
+ void motorsOff();
+
+ /** returns the value of the analog port i. 0 <= value <= 255
+ */
+ int analog(int i);
+
+ /** returns true if the digital port is logical high, else false.
+ */
+ bool digital(int i);
+
+};
+
+
+
+
+
+
+
+
+// PWM routine //
+SIGNAL (SIG_OVERFLOW0)
+{
+ const int OFFSET=50; // motor does not work with very low ratio
+ static int counter=255+OFFSET;
+
+ if (speedMotor1==0) cbi(PORTB, 6); // enable1 = 0
+ else if (abs(speedMotor1)+OFFSET >= counter) sbi(PORTB, 6); // enable1 = 1
+ else cbi(PORTB, 6); // enable1 = 0
+
+ if (speedMotor0==0) cbi(PORTB, 7); // enable2 = 0
+ else if (abs(speedMotor0)+OFFSET >= counter) sbi(PORTB, 7); // enable2 = 1
+ else cbi(PORTB, 7); // enable2 = 0
+
+ if (counter==0) counter=255+OFFSET;
+ else counter--;
+}
+
+
+
+void initTimer()
+{
+ TCCR0A=1; // timer 0 for interrupt
+ TIMSK1=1;
+ sei(); // enable interrupts
+}
+
+
+
+CAN128Board::CAN128Board()
+{
+ // Port A: motors output
+ DDRA = 4+8+16+64; // all motors output
+ PORTA = 0; // clear all bits = motors off
+
+ // Port B: motors enable
+ DDRB = 64+128; // upper bits output
+ PORTB = 0; // clear bit 6 and 7 = motors off
+
+ // Port C: power output
+ DDRC = 255; // default direction port C: all bits output
+ PORTC = 0; // clear all bits: power on
+
+ // Port D: I2C //
+ DDRD = 0; // all bits input
+ PORTD = 1+2; // set bits 0,1 -> I2C pullUps
+
+ // Port E: leds + buttons
+ DDRE = 4+8+16+32; // pin 2-5 leds output; pin 6+7 input for buttons 0+1
+ PORTE |= 4+8+16+32; // set leds off
+ PORTE |= 64+128; // set pullups for buttons 0+1
+
+ // Port F: analog in + digital in
+ DDRF = 0; // all bits input
+
+ // Port G: buttons
+ DDRG = 0; // pin 3+4 input for buttons 2+3
+ PORTG |= 8+16; // set pullups for buttons 3+4
+
+ initTimer();
+}
+
+
+void CAN128Board::ledOn(int i)
+{
+ if ((i<0) || (i>3)) return;
+ cbi(PORTE, i+2); // clear bit -> LED on
+}
+
+
+void CAN128Board::ledOff(int i)
+{
+ if ((i<0) || (i>3)) return;
+ sbi(PORTE, i+2); // set bit -> LED off
+}
+
+
+void CAN128Board::ledsOff()
+{
+ ledOff(0);
+ ledOff(1);
+ ledOff(2);
+ ledOff(3);
+}
+
+
+void CAN128Board::led(int i, bool state)
+{
+ if (state) ledOn(i); else ledOff(i);
+}
+
+
+void CAN128Board::ledMeter(int i)
+{
+ led(0, (i>50));
+ led(1, (i>100));
+ led(2, (i>150));
+ led(3, (i>200));
+}
+
+
+void CAN128Board::powerOn(int i)
+{
+ if ((i<0) || (i>7)) return;
+ cbi(PORTC, i);
+}
+
+
+void CAN128Board::powerOff(int i)
+{
+ if ((i<0) || (i>7)) return;
+ sbi(PORTC, i);
+}
+
+
+void CAN128Board::power(int i, bool state)
+{
+ if (state) powerOn(i); else powerOff(i);
+}
+
+
+bool CAN128Board::button(int i)
+{
+ if ((i<0) || (i>3)) return false;
+ else if (i==0 || i ==1){
+ return ((PINE & (64<<i)) == 0); //wenn pina=0 button gedrückt => 0&1=false, also 0==0 => true
+ }
+ else if (i==2 || i==3){
+ return ((PING & (2<<i)) == 0);
+ }
+ else return false;
+}
+
+
+void CAN128Board::motor(int i, int speed)
+{
+ if ((i<0) || (i>1)) return;
+
+ if (i==1) {
+ speedMotor1 = speed;
+ if (speed==0) {
+ cbi(PORTA, 2); // input1 = 0
+ cbi(PORTA, 3); // input2 = 0
+ //cbi(PORTB, 6); // enable1 = 0
+ }
+ else if (speed>0) {
+ sbi(PORTA, 2); // input1 = 1
+ cbi(PORTA, 3); // input2 = 0
+ //sbi(PORTB, 6); // enable1 = 1
+
+ }
+ else {
+ cbi(PORTA, 2); // input1 = 0
+ sbi(PORTA, 3); // input2 = 1
+ }
+ }
+
+ if (i==0) {
+ speedMotor0 = speed;
+ if (speed==0) {
+ cbi(PORTA, 4); // input3 = 0
+ cbi(PORTA, 5); // input4 = 0
+ //cbi(PORTB, 7); // enable2 = 0
+ }
+ else if (speed>0){
+ sbi(PORTA, 4); // input3 = 1
+ cbi(PORTA, 5); // input4 = 0
+ //sbi(PORTB, 7); // enable2 = 1
+ }
+ else {
+ cbi(PORTA, 4); // input3 = 0
+ sbi(PORTA, 5); // input4 = 1
+ }
+ }
+}
+
+
+void CAN128Board::motors(int motor0, int motor1)
+{
+ motor(0,motor0);
+ motor(1,motor1);
+}
+
+
+void CAN128Board::motorsOff()
+{
+ motor(0,0);
+ motor(1,0);
+}
+
+
+// return 0-255 //
+int CAN128Board::analog(int i)
+{
+ if ((i<0) || (i>7)) return -1;
+
+ ADCSRA=128; // set A/D enable bit (ADEN)
+ ADMUX=i; // select analog input and start A/D
+ sbi(ADMUX, ADLAR); // left adjust -> we use only ADCH
+ sbi(ADCSRA, ADSC); // start conversion
+ while (ADCSRA & 64); // wait until ADSC is low again
+ int value = ADCH; // read 8 bit value fom ADCH
+ return value;
+}
+
+
+
+bool CAN128Board::digital(int i)
+{
+ if ((i<0) || (i>7)) return false; // bad solution...
+ ADCSRA=0; // clear A/D enable bit (ADEN)
+ PORTF |= (1<<i); // set pullups for digital inputs
+
+ return (PINF & (1<<i)) ;
+}
+
+
+
+
+
+
+
+
+
+#endif
+
diff --git a/source/qFix/qfixI2C.h b/source/qFix/qfixI2C.h
new file mode 100644
index 0000000..2597dcc
--- /dev/null
+++ b/source/qFix/qfixI2C.h
@@ -0,0 +1,278 @@
+//------------------------------------------------------------------
+// qfixI2C.h
+//
+// This class is used for low-level I2C communication.
+//
+// For TW_ constants see compat/twi.h
+//
+// Copyright 2005-2006 by KTB mechatronics GmbH
+// Author: Stefan Enderle, Florian Schrapp
+//------------------------------------------------------------------
+
+#ifndef qfixI2C_h
+#define qfixI2C_h
+
+#include "qfix.h"
+#include "compat/twi.h"
+
+const int ACTION_SEND = 1;
+const int ACTION_GET = 2;
+const int ACTION_UNKNOWN = 3;
+
+
+const uint8_t ERROR_NO_ACK = 1;
+const uint8_t ERROR_NO_START = 2;
+const uint8_t ERROR_NOT_SENT = 3; // send() could not send byte(s)
+
+
+
+class I2C
+{
+private:
+ uint8_t err;
+ uint8_t adr;
+
+ void sendStartSLA_W(uint8_t address);
+ void sendStartSLA_R(uint8_t address);
+ void sendByte(uint8_t data);
+ void sendStop();
+ void readByte(uint8_t& data);
+
+public:
+ I2C();
+ uint8_t error();
+
+// master side //
+
+ void send(uint8_t address, uint8_t data);
+ void send(uint8_t address, uint8_t* data, int length);
+ void get(uint8_t address, uint8_t* data, int length);
+
+// slave side //
+
+ void setSlaveAdress(uint8_t address);
+ bool isAction();
+ bool isActionSend(); // true if master sent something
+ bool isActionGet(); // true if master wants to get something
+ int receive(uint8_t* data); // if action is send, receive the bytes
+ void returnBytes(uint8_t* data, int len, bool lastOne);
+};
+
+
+
+I2C::I2C()
+{
+ TWBR = 10; // I2C bitrate (must be 10 or higher)
+ TWCR = 4+64; // TWI enable bit + ackn
+ TWSR = 0; // prescaler
+
+ // I2C pull-ups are set in the board file //
+
+ err=0;
+}
+
+uint8_t I2C::error()
+{
+ return err;
+}
+
+
+void I2C::setSlaveAdress(uint8_t address)
+{
+ TWAR = address<<1; // slave address (shift by one since bit 0 has different meaning)
+}
+
+
+bool I2C::isAction()
+{
+ if (TWCR&(1<<TWINT)) return true;
+ else return false;
+}
+
+
+inline
+bool I2C::isActionGet()
+{
+ return ((TWSR&248)==TW_ST_SLA_ACK); // own I2C address received, read mode, ACK sent
+}
+
+
+inline
+bool I2C::isActionSend()
+{
+ return ((TWSR&248)==TW_SR_SLA_ACK); // own I2C address received, write mode, ACK sent
+}
+
+
+void I2C::sendStartSLA_W(uint8_t address)
+{
+ bool OK = false;
+ int counter = 0;
+
+ do {
+
+ TWCR |= BV(TWINT)|BV(TWSTA); // send start condition
+ while(!(TWCR&BV(TWINT))); // wait for OK
+
+ if ((TWSR&248)!=TW_START) { // start condition was sent -> OK
+ err=ERROR_NO_START;
+ return;
+ }
+
+ TWDR=(address<<1); // slave address + write mode
+ TWCR = BV(TWINT) | BV(TWEN) | BV(TWEA); // generate command
+
+ while(!(TWCR&128)) {}; // wait for OK
+ if ((TWSR&248)==TW_MT_SLA_ACK) OK=true; // SLA+W was sent, ACK received -> OK
+ if ((TWSR&248)==TW_MT_SLA_NACK) { // SLA+W was sent, ACK not received -> ERROR
+ counter++;
+
+ if (counter == 10) { // After 10 tries...
+ err=ERROR_NO_ACK; // ... return with ERROR_NO_ACK
+ return;
+ }
+ }
+
+ } while(!OK);
+
+ err=0; // OK
+}
+
+
+void I2C::sendStartSLA_R(uint8_t address)
+{
+ bool OK=false;
+ while (!OK) {
+ TWCR |= BV(TWINT)|BV(TWSTA); // send start condition
+// sbi(TWCR, TWSTA); // generate start condition
+ while(!(TWCR&128)); // wait for OK
+ if ((TWSR&248)==8); // start condition was sent -> OK
+
+ TWDR=(address<<1) | 1; // slave address + read mode
+ TWCR = BV(TWINT) | BV(TWEN) | BV(TWEA); // generate command
+
+ while(!(TWCR&128)); // wait for send OK + ACK/NACK from slave
+ if ((TWSR&248)==0x38); // Arbitration lost or NOT ACK -> ERROR
+ if ((TWSR&248)==0x40) OK=true; // SLA+R was sent, ACK received -> OK
+ if ((TWSR&248)==0x48); // SLA+W was sent, ACK not received -> ERROR
+ sbi(TWCR, TWINT); // OK
+ }
+}
+
+// This is used by send() called by the master //
+void I2C::sendByte(uint8_t data)
+{
+ TWDR = data; // send one data byte
+ TWCR = (1<<TWINT)|(1<<TWEA)|(1<<TWEN); // start transmission
+
+ while(!(TWCR&(1<<TWINT))); // wait for TWCR to become 0
+ if ((TWSR&248)==TW_MT_DATA_ACK); // data sent, ACK received -> OK
+ if ((TWSR&248)==TW_MT_DATA_NACK); // data sent, ACK not received -> ERROR
+}
+
+
+void I2C::sendStop()
+{
+ TWCR = BV(TWINT) | BV(TWEN) | BV(TWEA) | BV(TWSTO); // generate stop command
+}
+
+// Note: in qfix, the I2C address is the board identifier
+// and the first data byte ist the logical ID
+inline
+void I2C::send(uint8_t address, uint8_t data)
+{
+ send(address, &data, 1);
+}
+
+
+// Note: in qfix, the I2C address is the board identifier
+// and the first data byte ist the logical ID
+void I2C::send(uint8_t address, uint8_t* data, int length)
+{
+ sendStartSLA_W(address);
+ if (err!=0)
+ {
+ sendStop();
+ err = ERROR_NOT_SENT;
+ return;
+ }
+
+ for (int i=0; i<length; i++) {
+ sendByte(data[i]);
+ }
+ sendStop();
+ err = 0; // OK
+}
+
+
+
+int I2C::receive(uint8_t* data)
+{
+ TWCR = (1<<TWINT)|(1<<TWEA)|(1<<TWEN);
+
+ while(!(TWCR&(1<<TWINT))); // wait for something
+
+ int len = 0;
+ while ((TWSR&248)==TW_SR_DATA_ACK) { // data received (in TWDR), ACK sent
+ data[len] = TWDR; // read received byte
+ len++;
+ TWCR = (1<<TWINT)|(1<<TWEA)|(1<<TWEN);
+ while(!(TWCR&(1<<TWINT))) { } // wait for OK
+ }
+
+ if ((TWSR&248)==TW_SR_STOP) { } // STOP (or new START) received -> OK
+ TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); // generate command
+
+ return len;
+}
+
+
+void I2C::readByte(uint8_t& data)
+{
+ while(!isAction());
+
+ if ((TWSR&248)==0x50); // data received: NACK
+ if ((TWSR&248)==0x58); // data received: ACK
+ data = TWDR;
+ TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); // generate command
+}
+
+
+void I2C::get(uint8_t address, uint8_t* data, int length)
+{
+ sendStartSLA_R(address);
+ if (err!=0)
+ {
+ sendStop();
+ err = ERROR_NOT_SENT;
+ return;
+ }
+
+ for (int i=0; i<length; i++) {
+ readByte(data[i]);
+ }
+ sendStop();
+}
+
+
+
+
+void I2C::returnBytes(uint8_t* data, int len, bool lastOne)
+{
+ for (int i=0; i<len; i++) {
+ TWDR=data[i]; // byte to send
+
+ if (i==len-1) TWCR = (1<<TWINT) | (1<<TWEN); // command for last byte (no TWEA is correct!)
+ else TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); // command for all others
+
+ while(!(TWCR&(1<<TWINT))); // wait for OK
+
+ if ((TWSR&248)==0xB8); // data sent, ACK ACK received -> OK
+ if ((TWSR&248)==0xC0); // data sent, ACK not received -> ERROR
+ }
+ TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); // generate command
+}
+
+
+#endif
+
diff --git a/source/qFix/qfixI2CDefs.h b/source/qFix/qfixI2CDefs.h
new file mode 100644
index 0000000..5caa55c
--- /dev/null
+++ b/source/qFix/qfixI2CDefs.h
@@ -0,0 +1,21 @@
+//------------------------------------------------------------------
+// qfixI2CDefs.h
+//
+// This file contains definitions for the qfix I2C protocol.
+//
+// Copyright 2005 by KTB mechatronics GmbH
+// Author: Stefan Enderle
+//------------------------------------------------------------------
+
+
+#ifndef qfixI2CDefs_h
+#define qfixI2CDefs_h
+
+
+const uint8_t I2C_ADDR_BOBBYBOARD = 1;
+const uint8_t I2C_ADDR_LCD = 2;
+
+
+
+#endif
+
diff --git a/source/qFix/qfixI2CMaster.h b/source/qFix/qfixI2CMaster.h
new file mode 100644
index 0000000..63badd5
--- /dev/null
+++ b/source/qFix/qfixI2CMaster.h
@@ -0,0 +1,119 @@
+//------------------------------------------------------------------
+// qfixI2CMaster.h
+//
+// This is a convenience class for writing I2C master classes
+// (like SlaveBoard).
+// This class supports the qfix I2C protocol.
+//
+// Copyright 2005 by KTB mechatronics GmbH
+// Author: Stefan Enderle
+//------------------------------------------------------------------
+
+
+#ifndef qfixI2CMaster_h
+#define qfixI2CMaster_h
+
+#include "qfixI2C.h"
+#include "qfixI2CDefs.h"
+
+const uint8_t CMD_PARAMS = 255; // the same for all boards
+
+
+//---------------------------------------------------------------
+
+class I2CMaster
+{
+ I2C i2c;
+
+ uint8_t brdID; // board ID (what board)
+ uint8_t logID; // logical ID (which one of these boards)
+
+public:
+ /** boardID denotes the board (BobbyBoard, LCD, ...) that
+ * shall be used. The logical ID is set to 0.
+ */
+ I2CMaster(uint8_t boardID);
+
+ /** boardID denotes the board (BobbyBoard, LCD, ...) that
+ * shall be used. logicalID is the sub-ID (e.g. which LCD).
+ */
+ I2CMaster(uint8_t boardID, uint8_t logicalID);
+
+ void command(uint8_t cmd);
+ void command(uint8_t cmd, uint8_t param);
+ void command(uint8_t cmd, uint8_t param, uint8_t param2);
+ void command(uint8_t cmd, uint8_t param, uint8_t param2, uint8_t param3);
+ uint8_t request(uint8_t cmd, uint8_t param);
+};
+
+
+I2CMaster::I2CMaster(uint8_t boardID)
+: i2c(), brdID(boardID), logID(0)
+{
+}
+
+
+I2CMaster::I2CMaster(uint8_t boardID, uint8_t logicalID)
+: i2c(), brdID(boardID), logID(logicalID)
+{
+}
+
+
+
+void I2CMaster::command(uint8_t cmd)
+{
+ uint8_t buf[2];
+
+ buf[0] = logID;
+ buf[1] = cmd;
+ i2c.send(brdID, buf, 2);
+}
+
+void I2CMaster::command(uint8_t cmd, uint8_t param)
+{
+ uint8_t buf[3];
+
+ buf[0] = logID;
+ buf[1] = cmd;
+ buf[2] = param;
+ i2c.send(brdID, buf, 3);
+}
+
+void I2CMaster::command(uint8_t cmd, uint8_t param, uint8_t param2)
+{
+ uint8_t buf[4];
+
+ buf[0] = logID;
+ buf[1] = cmd;
+ buf[2] = param;
+ buf[3] = param2;
+ i2c.send(brdID, buf, 4);
+}
+
+void I2CMaster::command(uint8_t cmd, uint8_t param, uint8_t param2, uint8_t param3)
+{
+ uint8_t buf[5];
+
+ buf[0] = logID;
+ buf[1] = cmd;
+ buf[2] = param;
+ buf[3] = param2;
+ buf[4] = param3;
+ i2c.send(brdID, buf, 5);
+}
+
+
+uint8_t I2CMaster::request(uint8_t cmd, uint8_t param)
+{
+ // send command and params first //
+ command(CMD_PARAMS, cmd, param);
+
+ // get return value //
+ uint8_t buf[10];
+ i2c.get(brdID, buf, 1);
+ return(buf[0]);
+}
+
+
+#endif
+
diff --git a/source/qFix/qfixI2CSlave.h b/source/qFix/qfixI2CSlave.h
new file mode 100644
index 0000000..30151d3
--- /dev/null
+++ b/source/qFix/qfixI2CSlave.h
@@ -0,0 +1,113 @@
+//------------------------------------------------------------------
+// qfixI2CSlave.h
+//
+// This is a convenience class for writing I2C slave programs
+// (like slaveBoard.cc).
+// This class supports the qfix I2C protocol.
+//
+// Copyright 2005 by KTB mechatronics GmbH
+// Author: Stefan Enderle
+//------------------------------------------------------------------
+
+
+#ifndef qfixI2CSlave_h
+#define qfixI2CSlave_h
+
+#include "qfixI2C.h"
+#include "qfixI2CDefs.h"
+#include "qfixI2CMaster.h" // Only for constants
+
+
+//---------------------------------------------------------------
+
+class I2CSlave
+{
+public:
+ I2C i2c;
+
+ uint8_t brdID; // board ID (what board)
+ uint8_t logID; // logical ID (which one of these boards)
+
+ void (*commandPtr)(uint8_t cmd, uint8_t* params, uint8_t len);
+ void (*requestPtr)(uint8_t cmd, uint8_t* params, uint8_t len);
+
+
+ uint8_t params[100];
+ uint8_t data[100];
+
+public:
+ /** boardID denotes the board (BobbyBoard, LCD, ...) that
+ * shall be used. The logical ID is set to 0.
+ */
+ I2CSlave(uint8_t boardID);
+
+ /** boardID denotes the board (BobbyBoard, LCD, ...) that
+ * shall be used. logicalID is the sub-ID (e.g. which LCD).
+ */
+ I2CSlave(uint8_t boardID, uint8_t logicalID);
+
+ void setLogicalID(uint8_t logicalID);
+
+ void run();
+};
+
+
+I2CSlave::I2CSlave(uint8_t boardID)
+: i2c(), brdID(boardID), logID(0)
+{
+ i2c.setSlaveAdress(boardID);
+}
+
+
+I2CSlave::I2CSlave(uint8_t boardID, uint8_t logicalID)
+: i2c(), brdID(boardID), logID(logicalID)
+{
+ i2c.setSlaveAdress(boardID);
+}
+
+
+void I2CSlave::setLogicalID(uint8_t logicalID)
+{
+ logID = logicalID;
+}
+
+void I2CSlave::run()
+{
+ while (1) {
+
+ // wait for action on the I2C bus //
+ while (!i2c.isAction()) { }
+
+ // was it a command (send) //
+ if (i2c.isActionSend()) {
+
+ // receive bytes: 0=logical ID, 1=command, 2..n=params
+ int len = i2c.receive(data);
+
+ // if logical ID matches (or 255) -> execute //
+ if ( (data[0] == logID) || (data[0]==255) ) {
+
+ // is it the first part of a request ? -> save params //
+ if (data[1] == CMD_PARAMS) {
+ for (int i=0; i<len; i++) {
+ params[i] = data[i];
+ }
+ }
+
+ // it is a command -> call the given command function //
+ else commandPtr(data[1], data+2, len-2);
+ }
+ }
+
+ // or was it a request (get) //
+ else if (i2c.isActionGet()) {
+ requestPtr(params[2], params+3, 0); // call given rqs function
+ }
+
+ // else ERROR !
+ }
+}
+
+
+#endif
+
diff --git a/source/qFix/qfixLCD.h b/source/qFix/qfixLCD.h
new file mode 100644
index 0000000..9ecd93f
--- /dev/null
+++ b/source/qFix/qfixLCD.h
@@ -0,0 +1,216 @@
+//------------------------------------------------------------------
+// qfixLCD.h
+//
+// This file contains the class LCD which represents the
+// LCD display.
+//
+// Copyright 2004 by KTB mechatronics GmbH
+// Author: Stefan Enderle
+//------------------------------------------------------------------
+
+#ifndef qfixLCD_h
+#define qfixLCD_h
+
+
+#include "qfixI2C.h"
+#include "qfixI2CDefs.h"
+#include "string.h"
+
+
+static const uint8_t LCD_CMD_CHANGEID = 0;
+static const uint8_t LCD_CMD_CLEAR = 1;
+static const uint8_t LCD_CMD_PRINTSTR = 2;
+static const uint8_t LCD_CMD_PRINTSTRXY = 3;
+static const uint8_t LCD_CMD_LIGHTON = 4;
+static const uint8_t LCD_CMD_LIGHTOFF = 5;
+static const uint8_t LCD_CMD_PRINTINT = 6;
+static const uint8_t LCD_CMD_PRINTINTXY = 7;
+
+
+
+/**
+* \class LCD
+* \brief Represents the qfix LC-display.
+* \author Stefan Enderle
+*
+* The class LCD represents the
+* physical LC-display and can be used to output text.
+* The I2C bus is completely abstracted.
+*/
+class LCD
+{
+private:
+ I2C i2c;
+ uint8_t id;
+
+public:
+ /** Default constructor. If only one LC-display is used,
+ * this constructor can be used. It sets the internal ID to 0.
+ */
+ LCD();
+
+ /** Constructor with given ID.
+ * If two or more LC-displays are used,
+ * this constructor must be used. It sets the internal ID to the given value.
+ */
+ LCD(uint8_t ID);
+
+ /** Change logical device ID
+ */
+ void changeID(uint8_t newID);
+
+ /** Clears the display
+ */
+ void clear();
+
+ /** prints the string data at the current cursor position.
+ * The string must end with 0.
+ */
+ void print(char* data);
+
+ /** Prints the string data at position line/col. The string
+ * must end with 0.
+ */
+ void print(uint8_t line, uint8_t col, char* data);
+
+ /** prints the integer data at the current cursor position.
+ */
+ void print(int data);
+
+ /** Prints the integer data at position line/col.
+ */
+ void print(uint8_t line, uint8_t col, int data);
+
+ /** Puts on the backlight.
+ * \see lightOff
+ */
+ void lightOn();
+
+ /** Puts off the backlight.
+ * \see lightOff
+ */
+ void lightOff();
+};
+
+
+
+LCD::LCD() : i2c(), id(0)
+{
+}
+
+
+LCD::LCD(uint8_t ID) : i2c(), id(ID)
+{
+}
+
+
+void LCD::clear()
+{
+ uint8_t buf[2];
+
+ buf[0] = id;
+ buf[1] = LCD_CMD_CLEAR;
+ i2c.send(I2C_ADDR_LCD, buf, 2);
+}
+
+
+void LCD::print(char* data)
+{
+ int len=strlen(data);
+ uint8_t buf[len+2];
+
+ buf[0] = id;
+ buf[1] = LCD_CMD_PRINTSTR;
+ for (int i=0; i<len; i++) buf[i+2] = uint8_t(data[i]);
+
+ i2c.send(I2C_ADDR_LCD, buf, len+2);
+}
+
+
+void LCD::print(uint8_t line, uint8_t col, char* data)
+{
+ int len=strlen(data);
+ uint8_t buf[len+4];
+
+ buf[0] = id;
+ buf[1] = LCD_CMD_PRINTSTRXY;
+ buf[2] = line;
+ buf[3] = col;
+ for (int i=0; i<len; i++) buf[i+4] = uint8_t(data[i]);
+
+ i2c.send(I2C_ADDR_LCD, buf, len+4);
+}
+
+
+void LCD::print(int data)
+{
+ int len=sizeof(int);
+ uint8_t buf[len+2];
+ uint8_t* ptr = (uint8_t*) &data; // pointer to data
+
+ buf[0] = id;
+ buf[1] = LCD_CMD_PRINTINT;
+ for (int i=0; i<len; i++) {
+ buf[i+2] = *ptr;
+ ptr++;
+ }
+
+ i2c.send(I2C_ADDR_LCD, buf, len+2);
+}
+
+
+void LCD::print(uint8_t line, uint8_t col, int data)
+{
+ int len=sizeof(int);
+ uint8_t buf[len+4];
+ uint8_t* ptr = (uint8_t*) &data; // pointer to data
+
+ buf[0] = id;
+ buf[1] = LCD_CMD_PRINTINTXY;
+ buf[2] = line;
+ buf[3] = col;
+ for (int i=0; i<len; i++) {
+ buf[i+4] = *ptr;
+ ptr++;
+ }
+
+ i2c.send(I2C_ADDR_LCD, buf, len+4);
+}
+
+
+void LCD::lightOn()
+{
+ uint8_t buf[2];
+
+ buf[0] = id;
+ buf[1] = LCD_CMD_LIGHTON;
+ i2c.send(I2C_ADDR_LCD, buf, 2);
+}
+
+void LCD::lightOff()
+{
+ uint8_t buf[2];
+
+ buf[0] = id;
+ buf[1] = LCD_CMD_LIGHTOFF;
+ i2c.send(I2C_ADDR_LCD, buf, 2);
+}
+
+
+void LCD::changeID(uint8_t newID)
+{
+ uint8_t buf[3];
+
+ buf[0] = id;
+ buf[1] = LCD_CMD_CHANGEID;
+ buf[2] = newID;
+ i2c.send(I2C_ADDR_LCD, buf, 3);
+
+ id = newID;
+}
+
+
+#endif
+
+
+
diff --git a/source/qFix/qfixMega128Board.h b/source/qFix/qfixMega128Board.h
new file mode 100644
index 0000000..0a14e00
--- /dev/null
+++ b/source/qFix/qfixMega128Board.h
@@ -0,0 +1,323 @@
+//------------------------------------------------------------------
+// qfixMega128Board.h
+//
+// This file contains the class Mega128Board which represents the
+// physical Mega128Board with all its inputs and outputs.
+//
+// Copyright 2005 by KTB mechatronics GmbH
+// Author: Stefan Enderle, Florian Schrapp
+//------------------------------------------------------------------
+
+
+#include "qfix.h"
+
+
+#ifndef qfixMega128Board_h
+#define qfixMega128Board_h
+
+
+static int speedMotor0 = 50;
+static int speedMotor1 = 50;
+
+
+
+class Mega128Board
+{
+public:
+ /** Constructor for the robot board class.
+ */
+ Mega128Board();
+
+ /** Puts on LED i
+ */
+ void ledOn(int i);
+
+ /** Puts off LED i
+ */
+ void ledOff(int i);
+
+ /** Puts off all LEDs
+ */
+ void ledsOff();
+
+ /** Puts LED i on if state is true, else off
+ */
+ void led(int i, bool state);
+
+ /** Uses the four LEDs on the board to display the value i
+ * with 0 <= i <= 255
+ */
+ void ledMeter(int i);
+
+ /** Puts the power output i on
+ */
+ void powerOn(int i);
+
+ /** Puts the power output i off
+ */
+ void powerOff(int i);
+
+ /** Puts the power output i on if state is true, else off
+ */
+ void power(int i, bool state);
+
+ /** Checks the state of button i. If it is pressed, true is returned,
+ * else false.
+ */
+ bool button(int i);
+
+ /** Sets motor i to the given speed. -255 <= speed <= 255
+ */
+ void motor(int i, int speed);
+
+ /** Sets both motors to the given speed. -255 <= speed <= 255
+ */
+ void motors(int speed0, int speed1);
+
+ /** Puts off both motors.
+ */
+ void motorsOff();
+
+ /** returns the value of the analog port i. 0 <= value <= 255
+ */
+ int analog(int i);
+
+ /** returns true if the digital port is logical high, else false.
+ */
+ bool digital(int i);
+
+};
+
+
+
+
+
+
+
+
+// PWM routine //
+SIGNAL (SIG_OVERFLOW0)
+{
+ const int OFFSET=50; // motor does not work with very low ratio
+ static int counter=255+OFFSET;
+
+ if (speedMotor1==0) cbi(PORTB, 6); // enable1 = 0
+ else if (abs(speedMotor1)+OFFSET >= counter) sbi(PORTB, 6); // enable1 = 1
+ else cbi(PORTB, 6); // enable1 = 0
+
+ if (speedMotor0==0) cbi(PORTB, 7); // enable2 = 0
+ else if (abs(speedMotor0)+OFFSET >= counter) sbi(PORTB, 7); // enable2 = 1
+ else cbi(PORTB, 7); // enable2 = 0
+
+ if (counter==0) counter=255+OFFSET;
+ else counter--;
+}
+
+
+
+void initTimer()
+{
+ TCCR0=1; // timer 0 for interrupt
+ TIMSK=1;
+ sei(); // enable interrupts
+}
+
+
+
+Mega128Board::Mega128Board()
+{
+ // Port A: motors input
+ DDRA = 4+8+16+64; // all motors output
+ PORTA = 0; // clear all bits = motors off
+
+ // Port B: motors enable
+ DDRB = 64+128; // upper bits output
+ PORTB = 0; // clear bit 6 and 7 = motors off
+
+ // Port C: power output //
+ DDRC = 255; // default direction port C: all bits output
+ PORTC = 0; // clear all bits: power on
+
+ // Port D: I2C //
+ DDRD = 0; // all bits input
+ PORTD = 1+2; // set bits 0,1 -> I2C pullUps
+
+ // Port E: leds + buttons //
+ DDRE = 4+8+16+32; // pin 2-5 leds output; pin 6+7 input for buttons 0+1
+ PORTE |= 4+8+16+32; // set leds off
+ PORTE |= 64+128; // set pullups for buttons 0+1
+
+ // Port F: analog in + digital in //
+ DDRF = 0; // all bits input
+
+ // Port G: buttons //
+ DDRG = 0; // pin 3+4 input for buttons 2+3
+ PORTG |= 8+16; // set pullups for buttons 3+4
+
+ initTimer();
+}
+
+
+void Mega128Board::ledOn(int i)
+{
+ if ((i<0) || (i>3)) return;
+ cbi(PORTE, i+2); // clear bit -> LED on
+}
+
+
+void Mega128Board::ledOff(int i)
+{
+ if ((i<0) || (i>3)) return;
+ sbi(PORTE, i+2); // set bit -> LED off
+}
+
+
+void Mega128Board::ledsOff()
+{
+ ledOff(0);
+ ledOff(1);
+ ledOff(2);
+ ledOff(3);
+}
+
+
+void Mega128Board::led(int i, bool state)
+{
+ if (state) ledOn(i); else ledOff(i);
+}
+
+
+void Mega128Board::ledMeter(int i)
+{
+ led(0, (i>50));
+ led(1, (i>100));
+ led(2, (i>150));
+ led(3, (i>200));
+}
+
+
+void Mega128Board::powerOn(int i)
+{
+ if ((i<0) || (i>7)) return;
+ cbi(PORTC, i);
+}
+
+
+void Mega128Board::powerOff(int i)
+{
+ if ((i<0) || (i>7)) return;
+ sbi(PORTC, i);
+}
+
+
+void Mega128Board::power(int i, bool state)
+{
+ if (state) powerOn(i); else powerOff(i);
+}
+
+
+bool Mega128Board::button(int i)
+{
+ if ((i<0) || (i>3)) return false;
+ else if (i==0 || i ==1){
+ return ((PINE & (64<<i)) == 0); //wenn pina=0 button gedrückt => 0&1=false, also 0==0 => true
+ }
+ else if (i==2 || i==3){
+ return ((PING & (2<<i)) == 0);
+ }
+ else return false;
+}
+
+
+void Mega128Board::motor(int i, int speed)
+{
+ if ((i<0) || (i>1)) return;
+
+ if (i==1) {
+ speedMotor1 = speed;
+ if (speed==0) {
+ cbi(PORTA, 2); // input1 = 0
+ cbi(PORTA, 3); // input2 = 0
+ //cbi(PORTB, 6); // enable1 = 0
+ }
+ else if (speed>0) {
+ sbi(PORTA, 2); // input1 = 1
+ cbi(PORTA, 3); // input2 = 0
+ //sbi(PORTB, 6); // enable1 = 1
+
+ }
+ else {
+ cbi(PORTA, 2); // input1 = 0
+ sbi(PORTA, 3); // input2 = 1
+ }
+ }
+
+ if (i==0) {
+ speedMotor0 = speed;
+ if (speed==0) {
+ cbi(PORTA, 4); // input3 = 0
+ cbi(PORTA, 5); // input4 = 0
+ //cbi(PORTB, 7); // enable2 = 0
+ }
+ else if (speed>0){
+ sbi(PORTA, 4); // input3 = 1
+ cbi(PORTA, 5); // input4 = 0
+ //sbi(PORTB, 7); // enable2 = 1
+ }
+ else {
+ cbi(PORTA, 4); // input3 = 0
+ sbi(PORTA, 5); // input4 = 1
+ }
+ }
+}
+
+
+void Mega128Board::motors(int motor0, int motor1)
+{
+ motor(0,motor0);
+ motor(1,motor1);
+}
+
+
+void Mega128Board::motorsOff()
+{
+ motor(0,0);
+ motor(1,0);
+}
+
+
+// return 0-255 //
+int Mega128Board::analog(int i)
+{
+ if ((i<0) || (i>7)) return -1;
+
+ ADCSRA=128; // set A/D enable bit (ADEN)
+ ADMUX=i; // select analog input and start A/D
+ sbi(ADMUX, ADLAR); // left adjust -> we use only ADCH
+ sbi(ADCSRA, ADSC); // start conversion
+ while (ADCSRA & 64); // wait until ADSC is low again
+ int value = ADCH; // read 8 bit value fom ADCH
+ return value;
+}
+
+
+
+bool Mega128Board::digital(int i)
+{
+ if ((i<0) || (i>7)) return false; // bad solution...
+ ADCSRA=0; // clear A/D enable bit (ADEN)
+ PORTF |= (1<<i); // set pullups for digital inputs
+
+ return (PINF & (1<<i)) ;
+}
+
+
+
+
+
+
+
+
+
+#endif
+
diff --git a/source/qFix/qfixServoBoard4.h b/source/qFix/qfixServoBoard4.h
new file mode 100644
index 0000000..baaa2f9
--- /dev/null
+++ b/source/qFix/qfixServoBoard4.h
@@ -0,0 +1,89 @@
+//------------------------------------------------------------------
+// qfixServoBoard4.h
+//
+// This file contains the class ServoBoard4 which represents
+// four servos attached to the ServoBoard4.
+//
+// Copyright 2006 by KTB mechatronics GmbH
+// Author: Stefan Enderle
+//------------------------------------------------------------------
+
+#ifndef qfixServoBoard4_h
+#define qfixServoBoard4_h
+
+
+#include "qfixI2C.h"
+#include "qfixI2CDefs.h"
+#include "string.h"
+
+static const uint8_t I2C_ADDR_SERVO = 3;
+
+static const uint8_t SERVO_CMD_CHANGEID = 0;
+static const uint8_t SERVO_CMD_SET = 1;
+
+
+class ServoBoard4
+{
+private:
+ I2C i2c;
+ uint8_t id;
+
+public:
+ /** Constructor with default ID 0
+ */
+ ServoBoard4();
+
+ /** Constructor with given ID
+ */
+ ServoBoard4(uint8_t ID);
+
+ /** Change logical device ID
+ */
+ void changeID(uint8_t newID);
+
+ /**
+ */
+ void set(uint8_t index, uint8_t pwm);
+};
+
+
+
+ServoBoard4::ServoBoard4() : i2c(), id(0)
+{
+}
+
+
+ServoBoard4::ServoBoard4(uint8_t ID) : i2c(), id(ID)
+{
+}
+
+
+void ServoBoard4::set(uint8_t index, uint8_t pwm)
+{
+ uint8_t buf[5];
+
+ buf[0] = id;
+ buf[1] = SERVO_CMD_SET;
+ buf[2] = index;
+ buf[3] = pwm;
+ i2c.send(I2C_ADDR_SERVO, buf, 4);
+}
+
+
+void ServoBoard4::changeID(uint8_t newID)
+{
+ uint8_t buf[3];
+
+ buf[0] = id;
+ buf[1] = SERVO_CMD_CHANGEID;
+ buf[2] = newID;
+ i2c.send(I2C_ADDR_SERVO, buf, 3);
+
+ id = newID;
+}
+
+
+#endif
+
+
+
diff --git a/source/qFix/qfixSlaveBoard.h b/source/qFix/qfixSlaveBoard.h
new file mode 100644
index 0000000..ad781de
--- /dev/null
+++ b/source/qFix/qfixSlaveBoard.h
@@ -0,0 +1,157 @@
+//------------------------------------------------------------------
+// qfixSlaveBoard.h
+//
+// This file contains the class SlaveBoard which represents a kind
+// of remote control of a BobbyBoard via the I2C bus. The SlaveBoard
+// can be used like a local BobbyBoard with all its inputs and outputs.
+//
+// Copyright 2005 by KTB mechatronics GmbH
+// Author: Stefan Enderle
+//------------------------------------------------------------------
+
+
+#ifndef qfixSlaveBoard_h
+#define qfixSlaveBoard_h
+
+#include "qfixI2CMaster.h"
+#include "qfixI2CDefs.h"
+
+
+const uint8_t CMD_LEDON = 0;
+const uint8_t CMD_LEDOFF = 1;
+const uint8_t CMD_LEDSOFF = 2;
+const uint8_t CMD_POWERON = 3;
+const uint8_t CMD_POWEROFF = 4;
+const uint8_t CMD_MOTOR = 5;
+const uint8_t CMD_BUTTON = 6;
+const uint8_t CMD_ANALOG = 7;
+const uint8_t CMD_DIGITAL = 8;
+
+
+//----------------------------------------
+
+
+
+class SlaveBoard : I2CMaster
+{
+public:
+ SlaveBoard();
+ SlaveBoard(uint8_t logicalID);
+
+ /** Puts on LED i
+ */
+ void ledOn(uint8_t i);
+
+ /** Puts off LED i
+ */
+ void ledOff(uint8_t i);
+
+ /** Puts off all LEDs
+ */
+ void ledsOff();
+
+ /** Puts the power output i on
+ */
+ void powerOn(uint8_t i);
+
+ /** Puts the power output i off
+ */
+ void powerOff(uint8_t i);
+
+ /** Sets motor i to the given speed. -255 <= speed <= 255
+ */
+ void motor(uint8_t i, int speed);
+
+ /** Checks the state of button i. If it is pressed, true is returned,
+ * else false.
+ */
+ bool button(uint8_t i);
+
+ /** returns the value of the analog port i. 0 <= value <= 255
+ */
+ int analog(uint8_t i);
+
+ /** returns true if the digital port is logical high, else false.
+ */
+ bool digital(uint8_t i);
+};
+
+
+SlaveBoard::SlaveBoard() : I2CMaster(I2C_ADDR_BOBBYBOARD)
+{
+}
+
+
+SlaveBoard::SlaveBoard(uint8_t logicalID)
+: I2CMaster(I2C_ADDR_BOBBYBOARD, logicalID)
+{
+}
+
+
+void SlaveBoard::ledOn(uint8_t i)
+{
+ if (i>3) return;
+ command(CMD_LEDON, i);
+}
+
+
+void SlaveBoard::ledOff(uint8_t i)
+{
+ if (i>3) return;
+ command(CMD_LEDOFF, i);
+}
+
+
+void SlaveBoard::ledsOff()
+{
+ command(CMD_LEDSOFF);
+}
+
+
+void SlaveBoard::powerOn(uint8_t i)
+{
+ if (i>7) return;
+ command(CMD_POWERON, i);
+}
+
+
+void SlaveBoard::powerOff(uint8_t i)
+{
+ if (i>7) return;
+ command(CMD_POWEROFF, i);
+}
+
+
+void SlaveBoard::motor(uint8_t i, int speed)
+{
+ if (i>1) return;
+ uint8_t neg=(speed<0)?1:0;
+ uint8_t s;
+ if (speed>=0) s=uint8_t(speed); else s=-uint8_t(speed);
+ command(CMD_MOTOR, i, neg, s);
+}
+
+
+bool SlaveBoard::button(uint8_t i)
+{
+ if (i>3) return false; // better error handling!
+ return (request(CMD_BUTTON, i) == 1);
+}
+
+
+int SlaveBoard::analog(uint8_t i)
+{
+ if (i>3) return -1; // better error handling!
+ return (request(CMD_ANALOG, i));
+}
+
+
+bool SlaveBoard::digital(uint8_t i)
+{
+ if (i>3) return false; // better error handling!
+ return (request(CMD_DIGITAL, i) == 1);
+}
+
+
+#endif
+
diff --git a/source/qFix/qfixSoccerBoard.h b/source/qFix/qfixSoccerBoard.h
new file mode 100644
index 0000000..96570bd
--- /dev/null
+++ b/source/qFix/qfixSoccerBoard.h
@@ -0,0 +1,339 @@
+//------------------------------------------------------------------
+// qfixSoccerBoard.h
+//
+// This file contains the class SoccerBoard which represents the
+// physical SoccerBoard with all its inputs and outputs.
+//
+// Copyright 2004-2006 by KTB mechatronics GmbH
+// Author: Stefan Enderle
+//------------------------------------------------------------------
+
+
+#include "qfix.h"
+
+
+#ifndef qfixSoccerBoard_h
+#define qfixSoccerBoard_h
+
+
+static int speedMotor0 = 0;
+static int speedMotor1 = 0;
+static int speedMotor2 = 0;
+static int speedMotor3 = 0;
+static int speedMotor4 = 0;
+static int speedMotor5 = 0;
+
+
+/**
+* \class SoccerBoard
+* \brief Represents the controller board "SoccerBoard".
+* \author Stefan Enderle
+*
+* The class SoccerBoard represents the
+* physical SoccerBoard with all its inputs and outputs.
+* With this class it is possible to drive the motors,
+* put on LEDs, check the buttons and get data from the
+* analog and digital inputs.
+*/
+
+class SoccerBoard
+{
+
+public:
+ /** Constructor for the SoccerBoard class.
+ */
+ SoccerBoard();
+
+ /** Puts on LED i. i must be 0 or 1.
+ */
+ void ledOn(int i);
+
+ /** Puts off LED i. i must be 0 or 1.
+ */
+ void ledOff(int i);
+
+ /** Puts off all LEDs.
+ */
+ void ledsOff();
+
+ /** Puts LED i on if state is true, else off. i must be 0 or 1.
+ */
+ void led(int i, bool state);
+
+ /** Puts the power output i on
+ */
+ void powerOn(int i);
+
+ /** Puts the power output i off
+ */
+ void powerOff(int i);
+
+ /** Puts the power output i on if state is true, else off.
+ */
+ void power(int i, bool state);
+
+ /** Checks the state of button i. If it is pressed, true is returned,
+ * else false.
+ */
+ bool button(int i);
+
+ /** Uses the four LEDs on the board to display the value i
+ * with 0 <= i <= 255
+ */
+ void ledMeter(int i);
+
+ /** Sets motor i to the given speed. -255 <= speed <= 255.
+ */
+ void motor(int i, int speed);
+
+ /** Puts off all motors.
+ */
+ void motorsOff();
+
+ /** returns the value of the analog port i. 0 <= value <= 255.
+ */
+ int analog(int i);
+
+ /** returns true if the digital port is logical high, else false.
+ */
+ bool digital(int i);
+
+ /** Waits until button i is pressed and released again.
+ */
+ void waitForButton(int i);
+};
+
+
+
+
+
+// PWM routine //
+SIGNAL (SIG_OVERFLOW0)
+{
+ const int OFFSET=50; // motor does not work with very low ratio
+ static int counter=255+OFFSET;
+
+ if (speedMotor0==0) cbi(PORTB, 3); // enable1 = 0
+ else if (abs(speedMotor0)+OFFSET >= counter) sbi(PORTB, 3); // enable1 = 1
+ else cbi(PORTB, 3); // enable1 = 0
+
+ if (speedMotor1==0) cbi(PORTG, 2); // enable2 = 0
+ else if (abs(speedMotor1)+OFFSET >= counter) sbi(PORTG, 2); // enable2 = 1
+ else cbi(PORTG, 2); // enable2 = 0
+
+ if (speedMotor2==0) cbi(PORTB, 4); // enable3 = 0
+ else if (abs(speedMotor2)+OFFSET >= counter) sbi(PORTB, 4); // enable3 = 1
+ else cbi(PORTB, 4); // enable3 = 0
+
+ if (speedMotor3==0) cbi(PORTB, 6); // enable4 = 0
+ else if (abs(speedMotor3)+OFFSET >= counter) sbi(PORTB, 6); // enable4 = 1
+ else cbi(PORTB, 6); // enable4 = 0
+
+ if (speedMotor4==0) cbi(PORTB, 5); // enable5 = 0
+ else if (abs(speedMotor4)+OFFSET >= counter) sbi(PORTB, 5); // enable5 = 1
+ else cbi(PORTB, 5); // enable5 = 0
+
+ if (speedMotor5==0) cbi(PORTB, 7); // enable6 = 0
+ else if (abs(speedMotor5)+OFFSET >= counter) sbi(PORTB, 7); // enable6 = 1
+ else cbi(PORTB, 7); // enable6 = 0
+
+ if (counter==0) counter=255+OFFSET;
+ else counter--;
+}
+
+
+
+void initTimer()
+{
+ TCCR0A=1; // timer 0 for interrupt
+ TIMSK0=1;
+ sei(); // enable interrupts
+}
+
+
+
+
+SoccerBoard::SoccerBoard()
+{
+ // PORT A: Digital In (PA0, PA1) //
+ DDRA= 255 - (1+2); // all bits output (motor direction) except PA0,PA1 (digital in)
+ PORTA=1+2; // set pullups for digital in
+
+ // PORT B: LEDs (PB0, PB2), Motor enable (PB3-PB7) //
+ DDRB = 1+4; // PB0 + PB4 = LEDs -> output
+ DDRB |= 8+16+32+64+128; // PB3 - PB7 = Motor enable -> output
+ PORTB |= 1+4; // set bits 0 and 2 -> LEDs off
+ PORTB &= 255-(8+16+32+64+128); // clear bits 3-7 -> motor disable
+
+ // PORT C: Power Output //
+ DDRC = 255; // direction port D, all bits output
+ PORTC = 0; // clear all bits -> power on
+
+ // PORT D: I2C, USB, CAN //
+ DDRD = 0; // all bits input
+ PORTD = 1+2; // set bits 0,1 -> I2C pullUps
+
+ // PORT E: Digital In (PE2 - PE7) //
+ DDRE=0; // all bits input
+ PORTE=4+8+16+32+64+128; // set pullups for digital in
+
+ // PORT F: Analog In //
+ DDRF=0; // all bits input
+ ADCSRA=128; // set A/D enable bit (ADEN)
+
+ // PORT G: Buttons (PG3, PG4), motor enable (PG2)
+ DDRG = BV(PG2); // PG2 output
+ PORTG= BV(PG3)+BV(PG4); // set pullups for buttons
+ cbi(PORTG,PG2); // clear PG2 -> motor disable
+
+ initTimer();
+}
+
+
+void SoccerBoard::ledOn(int i)
+{
+ if (i==0) cbi(PORTB, PB0); // clear bit -> LED on
+ else if (i==1) cbi(PORTB, PB2); // clear bit -> LED on
+}
+
+
+void SoccerBoard::ledOff(int i)
+{
+ if (i==0) sbi(PORTB, PB0); // set bit -> LED off
+ else if (i==1) sbi(PORTB, PB2); // set bit -> LED off
+}
+
+void SoccerBoard::ledsOff()
+{
+ PORTB|=BV(PB0)+BV(PB2); // set bits -> LEDs off
+}
+
+
+void SoccerBoard::led(int i, bool state)
+{
+ if (state) ledOn(i); else ledOff(i);
+}
+
+
+void SoccerBoard::powerOn(int i)
+{
+ if ((i<0) || (i>7)) return;
+ cbi(PORTC, i);
+}
+
+
+void SoccerBoard::powerOff(int i)
+{
+ if ((i<0) || (i>7)) return;
+ sbi(PORTC, i);
+}
+
+
+void SoccerBoard::power(int i, bool state)
+{
+ if (state) powerOn(i); else powerOff(i);
+}
+
+
+bool SoccerBoard::button(int i)
+{
+ if (i==0) return ( (PING & BV(PG4)) == 0);
+ else if (i==1) return ( (PING & BV(PG3)) == 0);
+ else return false; // bad approach...
+}
+
+
+void SoccerBoard::ledMeter(int i)
+{
+ led(0, (i>100));
+ led(1, (i>200));
+}
+
+
+void SoccerBoard::motor(int i, int speed)
+{
+ if ((i<0) || (i>5)) return;
+
+ if (i==0) {
+ speedMotor0 = speed;
+ if (speed>0) sbi(PORTA, 3); // input1 = 1
+ else cbi(PORTA, 3); // input1 = 0
+ }
+
+ else if (i==1) {
+ speedMotor1 = speed;
+ if (speed>0) sbi(PORTA, 2); // input2 = 1
+ else cbi(PORTA, 2); // input2 = 0
+ }
+
+ else if (i==2) {
+ speedMotor2 = speed;
+ if (speed>0) sbi(PORTA, 5); // input3 = 1
+ else cbi(PORTA, 5); // input3 = 0
+ }
+
+ else if (i==3) {
+ speedMotor3 = speed;
+ if (speed>0) sbi(PORTA, 4); // input4 = 1
+ else cbi(PORTA, 4); // input4 = 0
+ }
+
+ else if (i==4) {
+ speedMotor4 = speed;
+ if (speed>0) sbi(PORTA, 7); // input5 = 1
+ else cbi(PORTA, 7); // input5 = 0
+ }
+
+ else if (i==5) {
+ speedMotor5 = speed;
+ if (speed>0) sbi(PORTA, 6); // input6 = 1
+ else cbi(PORTA, 6); // input6 = 0
+ }
+}
+
+
+void SoccerBoard::motorsOff()
+{
+ motor(0,0);
+ motor(1,0);
+ motor(2,0);
+ motor(3,0);
+ motor(4,0);
+ motor(5,0);
+}
+
+
+// return 0-255 //
+int SoccerBoard::analog(int i)
+{
+ if ((i<0) || (i>7)) return -1;
+
+ ADMUX=i; // select analog input and start A/D
+ sbi(ADMUX, ADLAR); // left adjust -> we use only ADCH
+ sbi(ADCSRA, ADSC); // start conversion
+ while (ADCSRA & 64); // wait until ADSC is low again
+ int value = ADCH; // read 8 bit value fom ADCH
+ return value;
+}
+
+
+bool SoccerBoard::digital(int i)
+{
+ if ((i<0) || (i>7)) return false; // bad solution...
+
+ if (i==0) return (PINA & 1);
+ else if (i==1) return (PINA & 2);
+ else return (PINE & (1<<i)) ;
+}
+
+
+void SoccerBoard::waitForButton(int i)
+{
+ if ((i<0) || (i>3)) return; // bad solution...
+ while (!button(i)) { /* do nothing */ }
+ while (button(i)) { /* do nothing */ }
+}
+
+
+#endif
+
diff --git a/source/qFix/qfixSonar.h b/source/qFix/qfixSonar.h
new file mode 100644
index 0000000..96d26ce
--- /dev/null
+++ b/source/qFix/qfixSonar.h
@@ -0,0 +1,107 @@
+//------------------------------------------------------------------
+// qfixSonar.h
+//
+// This file contains the class Sonar which represents a
+// sonar modul SFH04/08.
+//
+// Copyright 2005 by KTB mechatronics GmbH
+// Author: Florian Schrapp, Stefan Enderle
+// Version 1.0
+//------------------------------------------------------------------
+
+
+#ifndef qfixSonar_h
+#define qfixSonar_h
+
+#include "qfix.h"
+#include "qfixI2C.h"
+
+
+class Sonar
+{
+private:
+ uint8_t id;
+ I2C i2c;
+
+public:
+
+ /** Constructor with given ID
+ */
+ Sonar(uint8_t ID);
+
+ /** Change logical device ID
+ */
+ void changeID(uint8_t newID);
+
+ /** Returns the distance to the next object in millimeter
+ */
+ int distance();
+};
+
+
+
+Sonar::Sonar(uint8_t ID) : i2c()
+{
+ id = 112+ID;
+
+ uint8_t buf[10];
+ buf[0]=2; // register 2 = select range register
+ buf[1]=48; // set maximum range to 2107 mm (formula: range=(register*43)+43 mm)
+ i2c.send(id, buf, 2);
+
+ buf[0]=1; // register 1 = amplification
+ buf[1]=4; // improve detection along center axis
+ i2c.send(id, buf, 2);
+}
+
+
+void Sonar::changeID(uint8_t newID)
+{
+ if(newID>=0 && newID<=15){ // only 16 IDs allowed
+ uint8_t buf[10];
+
+ buf[0]=0;
+ buf[1]=160;
+ i2c.send(id, buf, 2);
+
+ buf[0]=0;
+ buf[1]=170;
+ i2c.send(id, buf, 2);
+
+ buf[0]=0;
+ buf[1]=165;
+ i2c.send(id, buf, 2);
+
+ buf[0]=0;
+ buf[1]=(newID*2)+224;
+ i2c.send(id, buf, 2);
+
+ id=112+newID;
+ } //else error!
+}
+
+
+int Sonar::distance()
+{
+ uint8_t buf[10];
+
+ buf[0]=0; // start measurement
+ buf[1]=81;
+ i2c.send(id, buf, 2);
+ msleep(70); // wait for echo!!! (about 65ms)
+
+ i2c.send(id, 3); // select byte to be read
+
+ i2c.get(id, buf, 1); // read first byte
+ uint8_t r1=buf[0];
+
+ i2c.send(id, 2); // select byte to be read
+
+ i2c.get(id, buf, 1); // read second byte
+ uint8_t r2=buf[0];
+
+ return ((r1+(256*r2))*10); // compute mm
+}
+
+
+#endif \ No newline at end of file