From: unknown author Date: Thu, 23 Apr 2009 15:15:19 +0000 (+0000) Subject: inital checkin X-Git-Url: https://git.realraum.at/?p=svn42.git;a=commitdiff_plain;h=2099456b39e30a6baa1e31cdd2be5c1f26b5faeb inital checkin --- 2099456b39e30a6baa1e31cdd2be5c1f26b5faeb diff --git a/firmware/Makefile b/firmware/Makefile new file mode 100755 index 0000000..9ff5f58 --- /dev/null +++ b/firmware/Makefile @@ -0,0 +1,209 @@ +## see README file + +TARGET = tuer +INSTALL_DIR = /flash/realraum/firmware/arduino +PORT = /dev/ttyUSB0 +UPLOAD_RATE = 19200 +AVRDUDE_PROGRAMMER = stk500v1 +MCU = atmega168 +F_CPU = 16000000 + +############################################################################ +# Below here nothing should be changed... + +ARDUINO = $(INSTALL_DIR)/hardware/cores/arduino +AVR_TOOLS_PATH = /usr/bin +SRC = $(ARDUINO)/pins_arduino.c $(ARDUINO)/wiring.c \ +$(ARDUINO)/wiring_analog.c $(ARDUINO)/wiring_digital.c \ +$(ARDUINO)/wiring_pulse.c $(ARDUINO)/wiring_serial.c \ +$(ARDUINO)/wiring_shift.c $(ARDUINO)/WInterrupts.c +CXXSRC = $(ARDUINO)/HardwareSerial.cpp $(ARDUINO)/Print.cpp $(ARDUINO)/WMath.cpp +FORMAT = ihex + + +# Name of this Makefile (used for "make depend"). +MAKEFILE = Makefile + +# 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 + +OPT = s + +# Place -D or -U options here +CDEFS = -DF_CPU=$(F_CPU) +CXXDEFS = -DF_CPU=$(F_CPU) + +# Place -I options here +CINCS = -I$(ARDUINO) +CXXINCS = -I$(ARDUINO) + +# 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 +CDEBUG = -g$(DEBUG) +CWARN = -Wall -Wstrict-prototypes +CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +#CEXTRA = -Wa,-adhlns=$(<:.c=.lst) + +CFLAGS = $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CSTANDARD) $(CEXTRA) +CXXFLAGS = $(CDEFS) $(CINCS) -O$(OPT) +#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs +LDFLAGS = -lm + + +# Programming support using avrdude. Settings and variables. +AVRDUDE_PORT = $(PORT) +AVRDUDE_WRITE_FLASH = -U flash:w:applet/$(TARGET).hex +AVRDUDE_FLAGS = -V -F -C $(INSTALL_DIR)/hardware/tools/avrdude.conf \ +-p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \ +-b $(UPLOAD_RATE) + +# Program settings +CC = $(AVR_TOOLS_PATH)/avr-gcc +CXX = $(AVR_TOOLS_PATH)/avr-g++ +OBJCOPY = $(AVR_TOOLS_PATH)/avr-objcopy +OBJDUMP = $(AVR_TOOLS_PATH)/avr-objdump +AR = $(AVR_TOOLS_PATH)/avr-ar +SIZE = $(AVR_TOOLS_PATH)/avr-size +NM = $(AVR_TOOLS_PATH)/avr-nm +AVRDUDE = $(AVR_TOOLS_PATH)/avrdude +REMOVE = rm -f +MV = mv -f + +# Define all object files. +OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o) + +# Define all listing files. +LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst) + +# Combine all necessary flags and optional flags. +# Add target processor to flags. +ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) +ALL_CXXFLAGS = -mmcu=$(MCU) -I. $(CXXFLAGS) +ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) + + +# Default target. +all: applet_files build sizeafter + +build: elf hex + +applet_files: $(TARGET).pde + # Here is the "preprocessing". + # It creates a .cpp file based with the same name as the .pde file. + # On top of the new .cpp file comes the WProgram.h header. + # At the end there is a generic main() function attached. + # Then the .cpp file will be compiled. Errors during compile will + # refer to this new, automatically generated, file. + # Not the original .pde file you actually edit... + test -d applet || mkdir applet + echo '#include "WProgram.h"' > applet/$(TARGET).cpp + cat $(TARGET).pde >> applet/$(TARGET).cpp + cat $(ARDUINO)/main.cxx >> applet/$(TARGET).cpp + +elf: applet/$(TARGET).elf +hex: applet/$(TARGET).hex +eep: applet/$(TARGET).eep +lss: applet/$(TARGET).lss +sym: applet/$(TARGET).sym + +# Program the device. +upload: applet/$(TARGET).hex + $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) + + + # Display size of file. +HEXSIZE = $(SIZE) --target=$(FORMAT) applet/$(TARGET).hex +ELFSIZE = $(SIZE) applet/$(TARGET).elf +sizebefore: + @if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(HEXSIZE); echo; fi + +sizeafter: + @if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(HEXSIZE); echo; fi + + +# 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: applet/$(TARGET).elf + $(COFFCONVERT) -O coff-avr applet/$(TARGET).elf $(TARGET).cof + + +extcoff: $(TARGET).elf + $(COFFCONVERT) -O coff-ext-avr applet/$(TARGET).elf $(TARGET).cof + + +.SUFFIXES: .elf .hex .eep .lss .sym + +.elf.hex: + $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ + +.elf.eep: + -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ + --change-section-lma .eeprom=0 -O $(FORMAT) $< $@ + +# Create extended listing file from ELF output file. +.elf.lss: + $(OBJDUMP) -h -S $< > $@ + +# Create a symbol table from ELF output file. +.elf.sym: + $(NM) -n $< > $@ + + # Link: create ELF output file from library. +applet/$(TARGET).elf: $(TARGET).pde applet/core.a + $(CC) $(ALL_CFLAGS) -o $@ applet/$(TARGET).cpp -L. applet/core.a $(LDFLAGS) + +applet/core.a: $(OBJ) + @for i in $(OBJ); do echo $(AR) rcs applet/core.a $$i; $(AR) rcs applet/core.a $$i; done + + + +# Compile: create object files from C++ source files. +.cpp.o: + $(CXX) -c $(ALL_CXXFLAGS) $< -o $@ + +# Compile: create object files from C source files. +.c.o: + $(CC) -c $(ALL_CFLAGS) $< -o $@ + + +# Compile: create assembler files from C source files. +.c.s: + $(CC) -S $(ALL_CFLAGS) $< -o $@ + + +# Assemble: create object files from assembler source files. +.S.o: + $(CC) -c $(ALL_ASFLAGS) $< -o $@ + + + +# Target: clean project. +clean: + $(REMOVE) applet/$(TARGET).hex applet/$(TARGET).eep applet/$(TARGET).cof applet/$(TARGET).elf \ + applet/$(TARGET).map applet/$(TARGET).sym applet/$(TARGET).lss applet/core.a \ + $(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d) + +depend: + if grep '^# DO NOT DELETE' $(MAKEFILE) >/dev/null; \ + then \ + sed -e '/^# DO NOT DELETE/,$$d' $(MAKEFILE) > \ + $(MAKEFILE).$$$$ && \ + $(MV) $(MAKEFILE).$$$$ $(MAKEFILE); \ + fi + echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' \ + >> $(MAKEFILE); \ + $(CC) -M -mmcu=$(MCU) $(CDEFS) $(CINCS) $(SRC) $(ASRC) >> $(MAKEFILE) + +.PHONY: all build elf hex eep lss sym program coff extcoff clean depend applet_files sizebefore sizeafter diff --git a/firmware/README b/firmware/README new file mode 100644 index 0000000..916af03 --- /dev/null +++ b/firmware/README @@ -0,0 +1,19 @@ +Realraum tuer instructions: + +1. install avr-gcc and tools: + $ sudo aptitude install gcc-avr avr-libc avrdude + +2. download arduino: + $ wget http://arduino.googlecode.com/files/arduino-0013-linux2.tgz + +3. unpack and add link: + $ tar -xzf arduino-0013-linux2.tgz + $ ln -s arduino-0013 arduino + +4. update Makefile variables INSTALL_DIR and PORT to your needs + +5. build it + $ make + +6. flash it (press reset) + $ make upload diff --git a/firmware/tuer.pde b/firmware/tuer.pde new file mode 100644 index 0000000..1808c88 --- /dev/null +++ b/firmware/tuer.pde @@ -0,0 +1,478 @@ +#include +#include + +//********************************************************************// + +#define HEARTBEAT_PIN 15 // blinking led indicating that system is active +#define HEARTBEAT_DURATION 10 // *10 ms, duration of heartbeat pulse +#define HEARTBEAT_DELAY 200 // *10 ms, 1/heartbeat-frequency +int heartbeat_cnt = 0; + +#define LEDS_ON 0xFC +#define LEDS_OFF 0x00 + +#define LEDS_GREEN_COMMON_PIN 16 +#define LEDS_RED_COMMON_PIN 17 +#define LED_DELAY 50 // *2 ms, between led shifts +int led_delay_cnt = 0; +byte next_led = 0; + +#define LIMIT_OPENED_PIN 18 // A4: limit switch for open +#define LIMIT_CLOSED_PIN 19 // A5: limit switch for close + +#define MANUAL_OPEN_PIN 12 // keys for manual open and close +#define MANUAL_CLOSE_PIN 13 // + +#define IDLE 0 // close and open may be called +#define OPENING 1 // opening, only 's' command is allowed +#define CLOSING 2 // closing, onyl 's' command is allowed +#define WAIT 3 // wait some time after open or close and hold last step +#define ERROR 4 // an error occured + +#define CMD_OPEN 'o' +#define CMD_CLOSE 'c' +#define CMD_STATUS 's' +#define CMD_RESET 'r' + +#define STEPPER_OFF 0x30 +byte current_state = IDLE; // current state of internal state machine +byte next_step = 0; // step counter 0 .. 3 +#define MOVING_TIMEOUT 1600 // *2 ms, in case limit switches don't work stop and report an error +int timeout_cnt = 0; // counts up to MOVING_TIMEOUT + +//********************************************************************// + +void init_limits() +{ + pinMode(LIMIT_OPENED_PIN, INPUT); // set pin to input + digitalWrite(LIMIT_OPENED_PIN, HIGH); // turn on pullup resistors + + pinMode(LIMIT_CLOSED_PIN, INPUT); // set pin to input + digitalWrite(LIMIT_CLOSED_PIN, HIGH); // turn on pullup resistors +} + +boolean is_opened() +{ + if(digitalRead(LIMIT_OPENED_PIN)) + return false; + + return true; +} + +boolean is_closed() +{ + if(digitalRead(LIMIT_CLOSED_PIN)) + return false; + + return true; +} + +//**********// + +void init_manual() +{ + pinMode(MANUAL_OPEN_PIN, INPUT); // set pin to input + digitalWrite(MANUAL_OPEN_PIN, HIGH); // turn on pullup resistors + + pinMode(MANUAL_CLOSE_PIN, INPUT); // set pin to input + digitalWrite(MANUAL_CLOSE_PIN, HIGH); // turn on pullup resistors +} + +boolean manual_open() +{ + if(digitalRead(MANUAL_OPEN_PIN)) + return false; + + return true; +} + +boolean manual_close() +{ + if(digitalRead(MANUAL_CLOSE_PIN)) + return false; + + return true; +} + +//********************************************************************// + +void reset_stepper() +{ + next_step = 0; + PORTB = STEPPER_OFF; + timeout_cnt = 0; +} + +void init_stepper() +{ + DDRB = 0x0F; // set PortB 3:0 as output + reset_stepper(); +} + +byte step_table(byte step) +{ + switch(step) { // 0011 xxxx, manual keys pull-ups stay active + case 0: return 0x33; + case 1: return 0x36; + case 2: return 0x3C; + case 3: return 0x39; + } + return STEPPER_OFF; +} + +//**********// + +void reset_leds() +{ + led_delay_cnt = 0; + next_led = 0; + PORTD = LEDS_OFF; + digitalWrite(LEDS_GREEN_COMMON_PIN, HIGH); + digitalWrite(LEDS_RED_COMMON_PIN, HIGH); +} + +void init_leds() +{ + DDRD = 0xFC; + pinMode(LEDS_GREEN_COMMON_PIN, OUTPUT); + pinMode(LEDS_RED_COMMON_PIN, OUTPUT); + reset_leds(); +} + +byte led_table(byte led) +{ + switch(led) { // xxxx xx00, leave RxD and TxD to 0 + case 0: return 0x04; + case 1: return 0x08; + case 2: return 0x10; + case 3: return 0x20; + case 4: return 0x40; + case 5: return 0x80; + } + return LEDS_OFF; +} + +void leds_green() +{ + digitalWrite(LEDS_GREEN_COMMON_PIN, LOW); + digitalWrite(LEDS_RED_COMMON_PIN, HIGH); +} + +void leds_red() +{ + digitalWrite(LEDS_GREEN_COMMON_PIN, HIGH); + digitalWrite(LEDS_RED_COMMON_PIN, LOW); +} + +void leds_toggle() +{ + if(digitalRead(LEDS_GREEN_COMMON_PIN) == HIGH) { + digitalWrite(LEDS_GREEN_COMMON_PIN, LOW); + digitalWrite(LEDS_RED_COMMON_PIN, HIGH); + } + else { + digitalWrite(LEDS_GREEN_COMMON_PIN, HIGH); + digitalWrite(LEDS_RED_COMMON_PIN, LOW); + } +} + +//**********// + +void start_step_timer() +{ + // timer 1: 2 ms, between stepper output state changes + TCCR1A = 0; // prescaler 1:256, WGM = 4 (CTC) + TCCR1B = 1< 2 ms @ 16 MHz + TCNT1 = 0; // reseting timer + TIMSK1 = 1< 250 ms @ 16 MHz + TCNT1 = 0; // reseting timer + TIMSK1 = 1< 500 ms @ 16 MHz + TCNT1 = 0; // reseting timer + TIMSK1 = 1<= MOVING_TIMEOUT) { + reset_stepper(); + stop_timer(); + current_state = ERROR; + Serial.println("Error: open/close took too long!"); + start_error_timer(); + leds_green(); + PORTD = LEDS_ON; + } + } + + if(current_state == OPENING) { // next step (open) + PORTB = step_table(next_step); + next_step++; + if(next_step >= 4) + next_step = 0; + } + else if(current_state == CLOSING) { // next step (close) + PORTB = step_table(next_step); + if(next_step == 0) + next_step = 3; + else + next_step--; + } + else if(current_state == WAIT) { // wait after last open/close finished -> idle + stop_timer(); + reset_stepper(); + current_state = IDLE; + return; + } + else if(current_state == ERROR) { + leds_toggle(); + return; + } + else { // timer is useless stop it + stop_timer(); + return; + } + + led_delay_cnt++; + if(led_delay_cnt >= LED_DELAY) { + led_delay_cnt = 0; + + PORTD = led_table(next_led); + + if(current_state == OPENING) { + if(next_led == 0) + next_led = 5; + else + next_led--; + } + else if(current_state == CLOSING) { + next_led++; + if(next_led >= 6) + next_led = 0; + } + } +} + +//********************************************************************// + +void reset_heartbeat() +{ + digitalWrite(HEARTBEAT_PIN, HIGH); + heartbeat_cnt = 0; +} + +void heartbeat_on() +{ + digitalWrite(HEARTBEAT_PIN, LOW); +} + +void heartbeat_off() +{ + digitalWrite(HEARTBEAT_PIN, HIGH); +} + +void init_heartbeat() +{ + pinMode(HEARTBEAT_PIN, OUTPUT); + reset_heartbeat(); + // timer 2: ~10 ms, timebase for heartbeat signal + TCCR2A = 1< ~10 ms @ 16 MHz + TCNT2 = 0; // reseting timer + TIMSK2 = 1<= HEARTBEAT_DELAY) { + heartbeat_on(); + heartbeat_cnt = 0; + } +} + +//********************************************************************// + +void reset_after_error() +{ + stop_timer(); + reset_leds(); + + leds_red(); + if(is_closed()) { + current_state = IDLE; + PORTD = LEDS_ON; + } + else { + current_state = CLOSING; + start_step_timer(); + } + Serial.println("Ok, closing now"); +} + +void start_open() +{ + if(is_opened()) { + Serial.println("Already open"); + return; + } + + reset_stepper(); + reset_leds(); + leds_green(); + current_state = OPENING; + start_step_timer(); + Serial.println("Ok"); +} + +void start_close() +{ + if(is_closed()) { + Serial.println("Already closed"); + return; + } + + reset_stepper(); + reset_leds(); + leds_red(); + current_state = CLOSING; + start_step_timer(); + Serial.println("Ok"); +} + +void print_status() +{ + Serial.print("Status: "); + if(is_opened()) + Serial.print("opened"); + else if(is_closed()) + Serial.print("closed"); + else + Serial.print("<->"); + + switch(current_state) { + case IDLE: Serial.println(", idle"); break; + case OPENING: Serial.println(", opening"); break; + case CLOSING: Serial.println(", closing"); break; + case WAIT: Serial.println(", waiting"); break; + default: Serial.println(", "); break; + } + +} + +//**********// + +void setup() +{ + init_limits(); + init_stepper(); + init_leds(); + init_heartbeat(); + + Serial.begin(9600); + + current_state = IDLE; + + // make sure door is locked after reset + leds_red(); + if(is_closed()) + PORTD = LEDS_ON; + else { + current_state = CLOSING; + start_step_timer(); + } +} + +void loop() +{ + if(Serial.available()) { + char command = Serial.read(); + + if(current_state == ERROR && command != CMD_RESET) { + Serial.println("Error: last open/close operation took to long!"); + } + else if (command == CMD_RESET) { + reset_after_error(); + } + else if (command == CMD_OPEN) { + if(current_state == IDLE) + start_open(); + else + Serial.println("Error: Operation in progress"); + } + else if (command == CMD_CLOSE) { + if(current_state == IDLE) + start_close(); + else + Serial.println("Error: Operation in progress"); + } + else if (command == CMD_STATUS) + print_status(); + else + Serial.println("Error: unknown command"); + } + if(manual_open() && !is_opened() && current_state == IDLE) { + Serial.println("open forced manually"); + start_open(); + } + if(manual_close() && !is_closed() && current_state == IDLE) { + Serial.println("close forced manually"); + start_close(); + } + if (current_state == IDLE) { + if(is_opened()) { + leds_green(); + PORTD = LEDS_ON; + } + if(is_closed()) { + leds_red(); + PORTD = LEDS_ON; + } + } +} diff --git a/mifare-read.c b/mifare-read.c new file mode 100644 index 0000000..7bfb50c --- /dev/null +++ b/mifare-read.c @@ -0,0 +1,177 @@ +/* mifare-tool - a small command-line tool for librfid mifare testing + * + * (C) 2006 by Harald Welte + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +//#include + +struct rfid_reader_handle *rh = NULL; +struct rfid_layer2_handle *l2h = NULL; +struct rfid_protocol_handle *ph = NULL; + + +void sigHandler(int sig) +{ + printf("sig handler called\n"); + +/* rfid_protocol_close(ph); */ +/* rfid_protocol_fini(ph); */ + + rfid_layer2_close(l2h); + rfid_layer2_fini(l2h); + + rfid_reader_close(rh); + exit(0); +} + +int l2_init(int layer2) +{ + int rc; + + l2h = rfid_layer2_init(rh, layer2); + if (!l2h) { + fprintf(stderr, "error during layer2(%d)_init (0=14a,1=14b,3=15)\n",layer2); + return -1; + } + + rc = rfid_layer2_open(l2h); + if (rc < 0) { + fprintf(stderr, "error during layer2_open\n"); + return rc; + } + + return 0; +} + +int l3_init(int protocol) +{ + ph = rfid_protocol_init(l2h, protocol); + if (!ph) { + fprintf(stderr, "error during protocol_init\n"); + return -1; + } + if (rfid_protocol_open(ph) < 0) { + fprintf(stderr, "error during protocol_open\n"); + return -1; + } + + return 0; +} + +static int mifare_cl_auth(unsigned char *key, int page) +{ + int rc; + + rc = mfcl_set_key(ph, key); + if (rc < 0) { + fprintf(stderr, "key format error\n"); + return rc; + } + rc = mfcl_auth(ph, RFID_CMD_MIFARE_AUTH1A, page); + if (rc < 0) { + fprintf(stderr, "mifare auth error\n"); + return rc; + } else +// printf("mifare auth succeeded!\n"); + + return 0; +} + +static void mifare_l3(void) +{ + while (l2_init(RFID_LAYER2_ISO14443A) < 0) ; + +// printf("ISO14443-3A anticollision succeeded\n"); + +// while (l3_init(RFID_PROTOCOL_MIFARE_CLASSIC) < 0) ; + +// printf("Mifare card available\n"); +} + +void print_hex(const unsigned char* buffer, int length) +{ + int i; + + if(length <= 0) return; + for(i=0; i=0) + printf("UID=%08X (len=%u)\n",uid,uid_len); + fflush(stdout); + +// rfid_layer2_close(l2h); +// rfid_layer2_fini(l2h); + + rfid_reader_close(rh); + exit(0); +} + diff --git a/reader.pl b/reader.pl new file mode 100755 index 0000000..6a417f4 --- /dev/null +++ b/reader.pl @@ -0,0 +1,42 @@ +#!/usr/bin/perl + +use strict; +my $fh; + +my $keys; +my %good; +my $status = 'c'; + +open $keys,'/flash/realraum/keys'; +while (<$keys>) +{ + my ($code,$comment) = split /\s/,$_,2; + $good{$code}=$comment; +} + +while (sleep 1) +{ + open $fh,'/flash/realraum/a.out 0 2>&1 |'; + while (<$fh>) + { + next unless /UID/; + my ($id) = /UID=(\S+)\s+/; + if ($good{$id}) + { + my $newstat; + if ($status eq 'o') + { + $newstat='c'; + + } else { + $newstat = 'o'; + } + print "$newstat: $good{$id}"; + system ( "echo -n $newstat > /dev/ttyUSB0"); + $status = $newstat; + } else { + print "boese\n"; + } + } + +} diff --git a/tuerschlitten.pl b/tuerschlitten.pl new file mode 100755 index 0000000..b78660e --- /dev/null +++ b/tuerschlitten.pl @@ -0,0 +1,4 @@ +#!/usr/bin/perl + +use strict; +