summaryrefslogtreecommitdiffstats
path: root/source/ct-Bot/pc
diff options
context:
space:
mode:
Diffstat (limited to 'source/ct-Bot/pc')
-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
12 files changed, 1642 insertions, 0 deletions
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