Added lot's of code-files used during work
This commit is contained in:
parent
644121b478
commit
56d9bdd39e
155 changed files with 23423 additions and 0 deletions
241
source/ct-Bot/pc/bot-2-sim.c
Normal file
241
source/ct-Bot/pc/bot-2-sim.c
Normal file
|
@ -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
|
66
source/ct-Bot/pc/delay_pc.c
Normal file
66
source/ct-Bot/pc/delay_pc.c
Normal file
|
@ -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
|
175
source/ct-Bot/pc/display_pc.c
Normal file
175
source/ct-Bot/pc/display_pc.c
Normal file
|
@ -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
|
54
source/ct-Bot/pc/ir-rc5_pc.c
Normal file
54
source/ct-Bot/pc/ir-rc5_pc.c
Normal file
|
@ -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
|
72
source/ct-Bot/pc/led_pc.c
Normal file
72
source/ct-Bot/pc/led_pc.c
Normal file
|
@ -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
|
65
source/ct-Bot/pc/mini-fat.c
Normal file
65
source/ct-Bot/pc/mini-fat.c
Normal file
|
@ -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
|
200
source/ct-Bot/pc/mmc-emu_pc.c
Normal file
200
source/ct-Bot/pc/mmc-emu_pc.c
Normal file
|
@ -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
|
81
source/ct-Bot/pc/motor-low_pc.c
Normal file
81
source/ct-Bot/pc/motor-low_pc.c
Normal file
|
@ -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
|
87
source/ct-Bot/pc/mouse_pc.c
Normal file
87
source/ct-Bot/pc/mouse_pc.c
Normal file
|
@ -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
|
45
source/ct-Bot/pc/sensor-low_pc.c
Normal file
45
source/ct-Bot/pc/sensor-low_pc.c
Normal file
|
@ -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
|
274
source/ct-Bot/pc/tcp-server.c
Normal file
274
source/ct-Bot/pc/tcp-server.c
Normal file
|
@ -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
|
282
source/ct-Bot/pc/tcp.c
Normal file
282
source/ct-Bot/pc/tcp.c
Normal file
|
@ -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
|
Reference in a new issue