heise online · c't · iX · Technology Review · Telepolis · mobil · Security · Netze · heise open · heise resale · Autos · c't-TV · Jobs · Kiosk
Zum Inhalt
c't

c't Projekte - c't-Bot und c't-Sim - Mailinglisten

c't-Bot und c't-Sim


[Voriger (Datum)] [Nächster (Datum)] [Voriger (Thread)] [Nächster (Thread)]
[Nach Datum][Nach Thread]

Re: [ct-bot] eeprom@pc

Absender: Benjamin Benz
Datum: Fr, 22.06.2007 16:27:10
In-reply-to: <46756694.9010906@xxxxxx>
References: <BCF016D5ED5AC34FBB655D109519ABCF083EBE@xxxxxxxxxxxxxxxxxxxx> <45ED3B46.4030400@xxxxxx> <45EF385C.3080609@xxxxxx> <A2ED0A68-A8F1-438A-B1E3-18033ED489E3@xxxxxxxxxxxxxxx> <45F135B9.5030203@xxxxxx> <45F13A91.6090904@xxxxxxxx> <D053B7F5-6BDD-4052-B45F-28FCF0EF45F8@xxxxxxxxxxxxxxx> <45F2B74F.8090706@xxxxxx> <38A4BFD9-CA32-436A-9A1E-B4E6E0652A5D@xxxxxxxxxxxxxxx> <463E0782.1050406@xxxxxx> <0FBD95CF-DA3B-461B-B12B-9FDCD84984D2@xxxxxxxxxxxxxxx> <463F3E0A.7020605@xxxxxx> <8D5B90F4-74FD-45D4-B5B8-DDCAC0B81932@xxxxxxxxxxxxxxx> <464092F7.30605@xxxxxx> <465DB1F9.5030404@xxxxxx> <CF925D4D-FD5A-4581-8480-1C5D35EFEDC9@xxxxxxxxxxxxxxx> <4663027F.4040301@xxxxxx> <F71477F0-03AD-4F06-87E3-AC5DA5BFD1B2@xxxxxxxxxxxxxxx> <466D6849.1020109@xxxxxx> <46756694.9010906@xxxxxx>


Hi,

danke erst einmal für den Patch. Leider könnte es noch ein wenig dauern,
 bis wir ihn getestet haben und er dann einen Weg ins SVN-Repository
findet. Die Projekt-Maintainer haben leider alle gerade viel anderes um
die Ohren. Bis dahin habe ich den Patch aber einmal auf die neue
"Leserpatches-Seite im Wiki
(http://www.heise.de/ct/projekte/machmit/ctbot/wiki/Patches)
eingetragen. Vielleicht will ihn ja noch wer anders ausprobieren.

MfG Benjamin Benz

Achim Pankalla wrote:
> hallo,
> wie angekündigt nun eine neue version von der eeprom-emulation. sie
> benötigt kein linker-script mehr und auch keine zusätzlichen tools, nur
> die schon mitgelieferten. compiler und linker versionen sollten keine
> rolle spielen.
> unter w32 geht alles wunderbar, erfahrung unter linux und macos fehlen
> noch, da wäre ich noch für infos dankbar.
> alles weitere findet ihr in der docu.
> der patch enthält die eeprom-emulation und einige anpassungen an den
> restlichen kode, weil bisher kein eeprom unter dem pc da war. getestet
> habe ich es mit bot_turn und der sensor-kalibrierung.
> viel spass damit
>    achim pankalla
> 
> 
> ------------------------------------------------------------------------
> 
> Index: E:/eclipse/ct-bot test/ct-Bot/bot-logic/behaviour_calibrate_sharps.c
> ===================================================================
> --- E:/eclipse/ct-bot test/ct-Bot/bot-logic/behaviour_calibrate_sharps.c	(revision 1162)
> +++ E:/eclipse/ct-bot test/ct-Bot/bot-logic/behaviour_calibrate_sharps.c	(working copy)
> @@ -1,314 +1,312 @@
> -/*
> - * c't-Bot
> - * 
> - * This program is free software; you can redistribute it
> - * and/or modify it under the terms of the GNU General
> - * Public License as published by the Free Software
> - * Foundation; either version 2 of the License, or (at your
> - * option) any later version. 
> - * This program is distributed in the hope that it will be 
> - * useful, but WITHOUT ANY WARRANTY; without even the implied
> - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
> - * PURPOSE. See the GNU General Public License for more details.
> - * You should have received a copy of the GNU General Public 
> - * License along with this program; if not, write to the Free 
> - * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> - * MA 02111-1307, USA.
> - * 
> - */
> -
> -/*! 
> - * @file 	behaviour_calibrate_sharps.c
> - * @brief 	Kalibriert die Distanzsensoren des Bots
> - * 
> - * Einige Zeilen sind auskommentiert. Sie waren dazu gedacht, die Kalibrierung zu automatisieren, 
> - * das geht aber zurzeit (noch) nicht, weil die Positionsbestimmung fuer kleine Distanzen etwas
> - * zu ungenau ist (=> Encoderdatenauswertung checken!)
> - * 
> - * @author 	Timo Sandmann (mail@xxxxxxxxxxxxxxx)
> - * @date 	21.04.2007
> - */
> -
> -#include "bot-logic/bot-logik.h"
> -
> -#ifdef BEHAVIOUR_CALIBRATE_SHARPS_AVAILABLE
> -#include <math.h>
> -#include <stdio.h>
> -#include <string.h>
> -
> -#include "sensor.h"
> -#include "display.h"
> -#include "gui.h"
> -#include "rc5-codes.h"
> -#include "log.h"
> -
> -#ifdef MCU
> -	#include <avr/eeprom.h>
> -#else
> -	/* derzeit kein EEPROM fuer PC vorhanden, Daten liegen einfach im RAM */
> -	#define eeprom_write_byte(ptr, x)	*ptr = x
> -	#define eeprom_write_block(pRam, pEeprom, n)	memcpy(pEeprom, pRam, n)	// eeprom_write_block ist andersrum!
> -#endif
> -
> -//static Behaviour_t* data = NULL;
> -//static float start_x = 0;
> -//static float start_head = 0;
> -static uint8_t last_toggle = 0;			/*!< letztes Toggle-Bit der Distsensoren */
> -static uint8_t step = 0;				/*!< Abstand zum naechsten Messpunkt [cm] */
> -static uint8_t count = 0;				/*!< aktueller Messpunkt */
> -static int16_t distL = 0;				/*!< Rohdaten des linken Sharps */
> -static int16_t distR = 0;				/*!< Rohdaten des rechten Sharps */
> -static uint8_t distance = 0;			/*!< Entfernung zum Hindernis [cm] */
> -static int8_t measure_count = 0;		/*!< Counter fuer Sharp-Messungen */
> -static uint8_t userinput_done = 0;		/*!< 1: User war schon fleissig, 0: warten */
> -
> -static distSens_t buffer[2][14];		/*!< Puffer des Kalibrierungsergebnisses im RAM */
> -static uint8_t volt_offset = 0;			/*!< Offset des Spannungswertes */
> -
> -static void (* pNextJob)(void) = NULL;	/*!< naechste Teilaufgabe */
> -static void (* pLastJob)(void) = NULL;	/*!< letzte Teilaufgabe (vor Stopp) */
> -
> -static void goto_next_pos(void);		/*!< Stellt den Bot auf die naechste Position bzw. laesst den User das tun */
> -
> -static const uint8_t max_steps = 14;	/*!< Anzahl der Entfernungen, an denen gemessen wird */
> -
> -///*!
> -// * @brief	Hilfsfunktion fuer wait_for_stop()
> -// * @see		wait_for_stop()
> -// */
> -//static void wait_for_stop_helper(void) {
> -//	speedWishLeft = BOT_SPEED_STOP;
> -//	speedWishRight = BOT_SPEED_STOP;
> -//	
> -//	/* Nachlauf abwarten */
> -//	if (fabs(v_enc_left) < 1.0f && fabs(v_enc_right) < 1.0f) {
> -//		/* zurueck zum Aufrufer */
> -//		pNextJob = pLastJob;	// wurde zuvor von wait_for_stop() gerettet
> -//	}
> -//}
> -//
> -///*!
> -// * @brief	Haelt den Bot an und wartet den Nachlauf ab
> -// * anschliessend geht's mit dem Aufrufer weiter
> -// */
> -//static inline void wait_for_stop(void) {
> -//	pLastJob = pNextJob;
> -//	pNextJob = wait_for_stop_helper;
> -//}
> -
> -/*!
> - * @brief	Hilfsfunktion fuer wait_for_userinput()
> - * @see		wait_for_userinput()
> - */
> -static void wait_for_userinput_helper(void) {
> -	/* Einagbe abwarten */
> -	if (userinput_done) {
> -		userinput_done = 0;
> -		/* zurueck zum Aufrufer */
> -		pNextJob = pLastJob;	// wurde zuvor von wait_for_userinput() gerettet
> -	}
> -}
> -
> -/*!
> - * @brief	Haelt den Bot an und wartet eine Useraktion ab
> - * anschliessend geht's mit dem Aufrufer weiter
> - */
> -static inline void wait_for_userinput(void) {
> -	pLastJob = pNextJob;
> -	pNextJob = wait_for_userinput_helper;
> -}  
> -
> -/*!
> - * @brief			Berechnet die aktuelle Entfernung eines Sensors zum Ausganspunkt / dem Hindernis	
> - * @param sensor	0: links, 1: rechts
> - */
> -static int16_t calc_distance(uint8_t sensor) {
> -//	float dHead = (start_head - heading) * 2.0f*M_PI/360.0f;
> -//	float dX = start_x - x_enc;
> -//	float s_m = dX / cos(dHead);
> -//	float dS = tan(dHead) * DISTSENSOR_POS_SW;
> -//	float result = sensor == 0 ? s_m - dS : s_m + dS;
> -//	return result;
> -	return distance * 10;	// cm in mm umrechnen
> -}
> -
> -/*!
> - * @brief	Schreibt Spannung und Entfernung in den RAM-Puffer
> - */
> -static void update_data(void) {
> -	int16_t dist = calc_distance(0);
> -//	LOG_INFO("%u: links: %d", count, dist);
> -	buffer[0][count].dist = dist/5;
> -	buffer[0][count].voltage = distL;
> -	dist = calc_distance(1);
> -//	LOG_INFO("%u: rechts: %d", count, dist);
> -	buffer[1][count].dist = dist/5;
> -	buffer[1][count].voltage = distR;
> -	
> -	if (count != max_steps-1)
> -		/* neue Entfernung */ 
> -		pNextJob = goto_next_pos;		
> -	else {
> -		/* fertig */
> -		count++;
> -		pNextJob = NULL;
> -	}
> -}
> -
> -/*!
> - * @brief	Misst die Entfernung mit den Sharps
> - */
> -static void measure_distance(void) {
> -	if (last_toggle != sensDistLToggle) {
> -		/* auf neue Messung pruefen */
> -		last_toggle = sensDistLToggle;
> -		measure_count++;
> -	}
> -	/* zweimal vier Messungen abwarten */
> -	if (measure_count == 4) {
> -		distL = (float)sensDistL / 8.0f - volt_offset;
> -		distR = (float)sensDistR / 8.0f - volt_offset;
> -	} else if (measure_count == 8) {
> -		distL += (float)sensDistL / 8.0f - volt_offset;
> -		distR += (float)sensDistR / 8.0f - volt_offset;
> -		distL >>= 1;
> -		distR >>= 1;	
> -		if (distL > 255 || distR > 255) {
> -			/* Offset zu kleine => erhoehen und neu messen */
> -			volt_offset += 5;
> -//			LOG_INFO("Offset-Update auf %u", volt_offset);
> -		} else {
> -			/* Messwerte ok */
> -			last_toggle = 1;
> -			pNextJob = update_data;
> -		}
> -		measure_count = 0;
> -	}
> -}
> -
> -/*!
> - * @brief	Stellt den Bot auf die naechste Position bzw. laesst den User das tun
> - */
> -static void goto_next_pos(void) {
> -	//bot_drive_distance(data, 0, -50, step);	// step cm zurueck
> -	distance += step;
> -	count++;
> -	pNextJob = measure_distance;
> -	wait_for_userinput();
> -}
> -
> -/*!
> - * @brief			Ersetzt die Sensorauswertungsfunktion, damit wir hier die Rohdaten bekommen
> - * @param p_sens	Zeiger auf den (Ziel-)Sensorwert
> - * @param p_toggle	Zeiger auf die Toggle-Variable des Zielsensors
> - * @param ptr		Zeiger auf auf Sensorrohdaten im EEPROM fuer p_sens
> - * @param volt		Spannungs-Ist-Wert, zu dem die Distanz gesucht wird 
> - */ 
> -void sensor_dist_direct(int16_t *const p_sens, uint8_t *const p_toggle, const distSens_t *ptr, int16_t volt) {
> -	*p_sens = volt;	
> -	*p_toggle = ~*p_toggle;
> -}
> -
> -/*!
> - * @brief		Das eigentliche Verhalten
> - * @param data	Zeiger auf den Verhaltensdatensatz des Aufrufers
> - * @see			bot_calibrate_sharps()
> - * Die Funktionalitaet des Verhaltens ist aufgeteilt in: 
> - * @see goto_next_pos(), @see measure_distance(), @see update_data()
> - */
> -void bot_calibrate_sharps_behaviour(Behaviour_t *data) {
> -	if (pNextJob) pNextJob();
> -	else {
> -		/* fertig! */
> -		display_clear();
> -		sensor_update_distance = sensor_dist_lookup;	// Sensorauswertung wieder aktivieren
> -		/* Puffer ins EEPROM schreiben */
> -		eeprom_write_byte((uint8_t*)&sensDistOffset, volt_offset);
> -		eeprom_write_block(buffer[0], (uint8_t*)sensDistDataL, max_steps*sizeof(distSens_t));
> -		eeprom_write_block(buffer[1], (uint8_t*)sensDistDataR, max_steps*sizeof(distSens_t));
> -		return_from_behaviour(data);
> -		/* Fuer sensor_correction.h formatierte Logausgabe, erleichtert das Speichern der Init-EEPROM- / Sim-Werte */
> -		LOG_INFO("SENSDIST_OFFSET %u", volt_offset);
> -		char tmp_s[14*7+1];	// 14 Zeichen pro Durchlauf + '\0'
> -		uint8_t i, j, k;
> -		LOG_INFO("SENSDIST_DATA_LEFT:");
> -		for (k=0; k<2; k++) {
> -			for (j=0; j<2; j++) {
> -				tmp_s[0] = '\0';
> -				for (i=0; i<max_steps/2; i++) {
> -					sprintf(tmp_s, "%s{%u/2,%u/5},", tmp_s, buffer[k][i+j*max_steps/2].voltage*2, buffer[k][i+j*max_steps/2].dist*5);		
> -				}
> -				if (j==1) tmp_s[strlen(tmp_s)-1] = '\0';	// kein Komma ausgeben, falls letzter Wert
> -				LOG_INFO("%s \\", tmp_s);
> -			}
> -			if (k==0) LOG_INFO("SENSDIST_DATA_RIGHT:");
> -		}
> -	}
> -}
> -
> -/*!
> - * @brief			Kalibriert die Distanzsensoren des ct-Bots
> - * @param caller	Zeiger auf den Verhaltensdatensatz des Aufrufers
> - */
> -void bot_calibrate_sharps(Behaviour_t *caller) {
> -	/* Inits */
> -//	data = caller;
> -//	start_head = heading;
> -//	start_x = x_enc + 100;
> -	last_toggle = 1;
> -	measure_count = -4;
> -	step = 5;
> -	distance = 10;
> -	volt_offset = 0;
> -	count = 0;
> -	userinput_done = 0;
> -	
> -	sensor_update_distance = sensor_dist_direct;	// Sensorauswertung deaktivieren
> -	
> -	uint8_t i;
> -	for (i=0; i<sizeof(screen_functions)/sizeof(screen_functions[0]); i++) {
> -		if (screen_functions[i] == bot_calibrate_sharps_display) break;
> -	}
> -	display_screen = i;
> -	display_clear();
> -	
> -	/* Als erstes Entfernung / Spannung messen */
> -	pNextJob = measure_distance;
> -	
> -	wait_for_userinput();
> -	
> -	/* Verhalten an */
> -	switch_to_behaviour(caller, bot_calibrate_sharps_behaviour, OVERRIDE);
> -}
> -
> -/*!
> - * @brief	Displayhandler fuer bot_calibrate_sharps-Verhalten
> - */
> -void bot_calibrate_sharps_display(void) {
> -	/* Displayausgabe */
> -	display_cursor(1,1);
> -	if (count != max_steps && pNextJob == wait_for_userinput_helper) {
> -		display_printf("Sharp-Kalibr. %2u/%2u", count+1 , max_steps);
> -		display_cursor(2,1);
> -		display_printf("Bot bitte auf %2u cm", distance);
> -		display_cursor(3,1);
> -		display_printf("stellen und mit");
> -		display_cursor(4,1);
> -		display_printf("\"Mute\" bestaetigen");
> -		
> -		/* Keyhandler */
> -		if (RC5_Code == RC5_CODE_MUTE) {
> -			userinput_done = 1;
> -			RC5_Code = 0;
> -		}
> -	} else if (pNextJob != NULL) {
> -		display_cursor(2,1);
> -		display_printf("thinking...         ");
> -	} else if (count == max_steps) {
> -		display_printf("fertig :-)");
> -	} else {
> -		display_printf("run calibrate_sharps");	
> -	}
> -}
> -
> -#endif	// BEHAVIOUR_CALIBRATE_SHARPS_AVAILABLE
> +/*
> + * c't-Bot
> + * 
> + * This program is free software; you can redistribute it
> + * and/or modify it under the terms of the GNU General
> + * Public License as published by the Free Software
> + * Foundation; either version 2 of the License, or (at your
> + * option) any later version. 
> + * This program is distributed in the hope that it will be 
> + * useful, but WITHOUT ANY WARRANTY; without even the implied
> + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
> + * PURPOSE. See the GNU General Public License for more details.
> + * You should have received a copy of the GNU General Public 
> + * License along with this program; if not, write to the Free 
> + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307, USA.
> + * 
> + */
> +
> +/*! 
> + * @file 	behaviour_calibrate_sharps.c
> + * @brief 	Kalibriert die Distanzsensoren des Bots
> + * 
> + * Einige Zeilen sind auskommentiert. Sie waren dazu gedacht, die Kalibrierung zu automatisieren, 
> + * das geht aber zurzeit (noch) nicht, weil die Positionsbestimmung fuer kleine Distanzen etwas
> + * zu ungenau ist (=> Encoderdatenauswertung checken!)
> + * 
> + * @author 	Timo Sandmann (mail@xxxxxxxxxxxxxxx)
> + * @date 	21.04.2007
> + */
> +
> +#include "bot-logic/bot-logik.h"
> +
> +#ifdef BEHAVIOUR_CALIBRATE_SHARPS_AVAILABLE
> +#include <math.h>
> +#include <stdio.h>
> +#include <string.h>
> +
> +#include "sensor.h"
> +#include "display.h"
> +#include "gui.h"
> +#include "rc5-codes.h"
> +#include "log.h"
> +
> +#ifdef MCU
> +	#include <avr/eeprom.h>
> +#else
> +	#include "eeprom-emu.h"
> +#endif
> +
> +//static Behaviour_t* data = NULL;
> +//static float start_x = 0;
> +//static float start_head = 0;
> +static uint8_t last_toggle = 0;			/*!< letztes Toggle-Bit der Distsensoren */
> +static uint8_t step = 0;				/*!< Abstand zum naechsten Messpunkt [cm] */
> +static uint8_t count = 0;				/*!< aktueller Messpunkt */
> +static int16_t distL = 0;				/*!< Rohdaten des linken Sharps */
> +static int16_t distR = 0;				/*!< Rohdaten des rechten Sharps */
> +static uint8_t distance = 0;			/*!< Entfernung zum Hindernis [cm] */
> +static int8_t measure_count = 0;		/*!< Counter fuer Sharp-Messungen */
> +static uint8_t userinput_done = 0;		/*!< 1: User war schon fleissig, 0: warten */
> +
> +static distSens_t buffer[2][14];		/*!< Puffer des Kalibrierungsergebnisses im RAM */
> +static uint8_t volt_offset = 0;			/*!< Offset des Spannungswertes */
> +
> +static void (* pNextJob)(void) = NULL;	/*!< naechste Teilaufgabe */
> +static void (* pLastJob)(void) = NULL;	/*!< letzte Teilaufgabe (vor Stopp) */
> +
> +static void goto_next_pos(void);		/*!< Stellt den Bot auf die naechste Position bzw. laesst den User das tun */
> +
> +static const uint8_t max_steps = 14;	/*!< Anzahl der Entfernungen, an denen gemessen wird */
> +
> +///*!
> +// * @brief	Hilfsfunktion fuer wait_for_stop()
> +// * @see		wait_for_stop()
> +// */
> +//static void wait_for_stop_helper(void) {
> +//	speedWishLeft = BOT_SPEED_STOP;
> +//	speedWishRight = BOT_SPEED_STOP;
> +//	
> +//	/* Nachlauf abwarten */
> +//	if (fabs(v_enc_left) < 1.0f && fabs(v_enc_right) < 1.0f) {
> +//		/* zurueck zum Aufrufer */
> +//		pNextJob = pLastJob;	// wurde zuvor von wait_for_stop() gerettet
> +//	}
> +//}
> +//
> +///*!
> +// * @brief	Haelt den Bot an und wartet den Nachlauf ab
> +// * anschliessend geht's mit dem Aufrufer weiter
> +// */
> +//static inline void wait_for_stop(void) {
> +//	pLastJob = pNextJob;
> +//	pNextJob = wait_for_stop_helper;
> +//}
> +
> +/*!
> + * @brief	Hilfsfunktion fuer wait_for_userinput()
> + * @see		wait_for_userinput()
> + */
> +static void wait_for_userinput_helper(void) {
> +	/* Einagbe abwarten */
> +	if (userinput_done) {
> +		userinput_done = 0;
> +		/* zurueck zum Aufrufer */
> +		pNextJob = pLastJob;	// wurde zuvor von wait_for_userinput() gerettet
> +	}
> +}
> +
> +/*!
> + * @brief	Haelt den Bot an und wartet eine Useraktion ab
> + * anschliessend geht's mit dem Aufrufer weiter
> + */
> +static inline void wait_for_userinput(void) {
> +	pLastJob = pNextJob;
> +	pNextJob = wait_for_userinput_helper;
> +}  
> +
> +/*!
> + * @brief			Berechnet die aktuelle Entfernung eines Sensors zum Ausganspunkt / dem Hindernis	
> + * @param sensor	0: links, 1: rechts
> + */
> +static int16_t calc_distance(uint8_t sensor) {
> +//	float dHead = (start_head - heading) * 2.0f*M_PI/360.0f;
> +//	float dX = start_x - x_enc;
> +//	float s_m = dX / cos(dHead);
> +//	float dS = tan(dHead) * DISTSENSOR_POS_SW;
> +//	float result = sensor == 0 ? s_m - dS : s_m + dS;
> +//	return result;
> +	return distance * 10;	// cm in mm umrechnen
> +}
> +
> +/*!
> + * @brief	Schreibt Spannung und Entfernung in den RAM-Puffer
> + */
> +static void update_data(void) {
> +	int16_t dist = calc_distance(0);
> +//	LOG_INFO("%u: links: %d", count, dist);
> +	buffer[0][count].dist = dist/5;
> +	buffer[0][count].voltage = distL;
> +	dist = calc_distance(1);
> +//	LOG_INFO("%u: rechts: %d", count, dist);
> +	buffer[1][count].dist = dist/5;
> +	buffer[1][count].voltage = distR;
> +	
> +	if (count != max_steps-1)
> +		/* neue Entfernung */ 
> +		pNextJob = goto_next_pos;		
> +	else {
> +		/* fertig */
> +		count++;
> +		pNextJob = NULL;
> +	}
> +}
> +
> +/*!
> + * @brief	Misst die Entfernung mit den Sharps
> + */
> +static void measure_distance(void) {
> +	if (last_toggle != sensDistLToggle) {
> +		/* auf neue Messung pruefen */
> +		last_toggle = sensDistLToggle;
> +		measure_count++;
> +	}
> +	/* zweimal vier Messungen abwarten */
> +	if (measure_count == 4) {
> +		distL = (float)sensDistL / 8.0f - volt_offset;
> +		distR = (float)sensDistR / 8.0f - volt_offset;
> +	} else if (measure_count == 8) {
> +		distL += (float)sensDistL / 8.0f - volt_offset;
> +		distR += (float)sensDistR / 8.0f - volt_offset;
> +		distL >>= 1;
> +		distR >>= 1;	
> +		if (distL > 255 || distR > 255) {
> +			/* Offset zu kleine => erhoehen und neu messen */
> +			volt_offset += 5;
> +//			LOG_INFO("Offset-Update auf %u", volt_offset);
> +		} else {
> +			/* Messwerte ok */
> +			last_toggle = 1;
> +			pNextJob = update_data;
> +		}
> +		measure_count = 0;
> +	}
> +}
> +
> +/*!
> + * @brief	Stellt den Bot auf die naechste Position bzw. laesst den User das tun
> + */
> +static void goto_next_pos(void) {
> +	//bot_drive_distance(data, 0, -50, step);	// step cm zurueck
> +	distance += step;
> +	count++;
> +	pNextJob = measure_distance;
> +	wait_for_userinput();
> +}
> +
> +/*!
> + * @brief			Ersetzt die Sensorauswertungsfunktion, damit wir hier die Rohdaten bekommen
> + * @param p_sens	Zeiger auf den (Ziel-)Sensorwert
> + * @param p_toggle	Zeiger auf die Toggle-Variable des Zielsensors
> + * @param ptr		Zeiger auf auf Sensorrohdaten im EEPROM fuer p_sens
> + * @param volt		Spannungs-Ist-Wert, zu dem die Distanz gesucht wird 
> + */ 
> +void sensor_dist_direct(int16_t *const p_sens, uint8_t *const p_toggle, const distSens_t *ptr, int16_t volt) {
> +	*p_sens = volt;	
> +	*p_toggle = ~*p_toggle;
> +}
> +
> +/*!
> + * @brief		Das eigentliche Verhalten
> + * @param data	Zeiger auf den Verhaltensdatensatz des Aufrufers
> + * @see			bot_calibrate_sharps()
> + * Die Funktionalitaet des Verhaltens ist aufgeteilt in: 
> + * @see goto_next_pos(), @see measure_distance(), @see update_data()
> + */
> +void bot_calibrate_sharps_behaviour(Behaviour_t *data) {
> +	if (pNextJob) pNextJob();
> +	else {
> +		/* fertig! */
> +		display_clear();
> +		sensor_update_distance = sensor_dist_lookup;	// Sensorauswertung wieder aktivieren
> +		/* Puffer ins EEPROM schreiben */
> +		eeprom_write_byte((uint8_t*)&sensDistOffset, volt_offset);
> +		eeprom_write_block(buffer[0], (uint8_t*)sensDistDataL, max_steps*sizeof(distSens_t));
> +		eeprom_write_block(buffer[1], (uint8_t*)sensDistDataR, max_steps*sizeof(distSens_t));
> +		return_from_behaviour(data);
> +		/* Fuer sensor_correction.h formatierte Logausgabe, erleichtert das Speichern der Init-EEPROM- / Sim-Werte */
> +		LOG_INFO("SENSDIST_OFFSET %u", volt_offset);
> +		char tmp_s[14*7+1];	// 14 Zeichen pro Durchlauf + '\0'
> +		uint8_t i, j, k;
> +		LOG_INFO("SENSDIST_DATA_LEFT:");
> +		for (k=0; k<2; k++) {
> +			for (j=0; j<2; j++) {
> +				tmp_s[0] = '\0';
> +				for (i=0; i<max_steps/2; i++) {
> +					sprintf(tmp_s, "%s{%u/2,%u/5},", tmp_s, buffer[k][i+j*max_steps/2].voltage*2, buffer[k][i+j*max_steps/2].dist*5);		
> +				}
> +				if (j==1) tmp_s[strlen(tmp_s)-1] = '\0';	// kein Komma ausgeben, falls letzter Wert
> +				LOG_INFO("%s \\", tmp_s);
> +			}
> +			if (k==0) LOG_INFO("SENSDIST_DATA_RIGHT:");
> +		}
> +	}
> +}
> +
> +/*!
> + * @brief			Kalibriert die Distanzsensoren des ct-Bots
> + * @param caller	Zeiger auf den Verhaltensdatensatz des Aufrufers
> + */
> +void bot_calibrate_sharps(Behaviour_t *caller) {
> +	/* Inits */
> +//	data = caller;
> +//	start_head = heading;
> +//	start_x = x_enc + 100;
> +	last_toggle = 1;
> +	measure_count = -4;
> +	step = 5;
> +	distance = 10;
> +	volt_offset = 0;
> +	count = 0;
> +	userinput_done = 0;
> +	
> +	sensor_update_distance = sensor_dist_direct;	// Sensorauswertung deaktivieren
> +	
> +	uint8_t i;
> +	for (i=0; i<sizeof(screen_functions)/sizeof(screen_functions[0]); i++) {
> +		if (screen_functions[i] == bot_calibrate_sharps_display) break;
> +	}
> +	display_screen = i;
> +	display_clear();
> +	
> +	/* Als erstes Entfernung / Spannung messen */
> +	pNextJob = measure_distance;
> +	
> +	wait_for_userinput();
> +	
> +	/* Verhalten an */
> +	switch_to_behaviour(caller, bot_calibrate_sharps_behaviour, OVERRIDE);
> +}
> +
> +/*!
> + * @brief	Displayhandler fuer bot_calibrate_sharps-Verhalten
> + */
> +void bot_calibrate_sharps_display(void) {
> +	/* Displayausgabe */
> +	display_cursor(1,1);
> +	if (count != max_steps && pNextJob == wait_for_userinput_helper) {
> +		display_printf("Sharp-Kalibr. %2u/%2u", count+1 , max_steps);
> +		display_cursor(2,1);
> +		display_printf("Bot bitte auf %2u cm", distance);
> +		display_cursor(3,1);
> +		display_printf("stellen und mit");
> +		display_cursor(4,1);
> +		display_printf("\"Mute\" bestaetigen");
> +		
> +		/* Keyhandler */
> +		if (RC5_Code == RC5_CODE_MUTE) {
> +			userinput_done = 1;
> +			RC5_Code = 0;
> +		}
> +	} else if (pNextJob != NULL) {
> +		display_cursor(2,1);
> +		display_printf("thinking...         ");
> +	} else if (count == max_steps) {
> +		display_printf("fertig :-)");
> +	} else {
> +		display_printf("run calibrate_sharps");	
> +	}
> +}
> +
> +#endif	// BEHAVIOUR_CALIBRATE_SHARPS_AVAILABLE
> Index: E:/eclipse/ct-bot test/ct-Bot/bot-logic/behaviour_turn.c
> ===================================================================
> --- E:/eclipse/ct-bot test/ct-Bot/bot-logic/behaviour_turn.c	(revision 1162)
> +++ E:/eclipse/ct-bot test/ct-Bot/bot-logic/behaviour_turn.c	(working copy)
> @@ -33,16 +33,14 @@
>  	#include <avr/eeprom.h>
>  	#define ANGLE_CORRECT	1						/*!< Drehfehler-Init */
>  #else
> -	/* derzeit kein EEPROM fuer PC vorhanden, Daten liegen einfach im RAM */
> -	#define eeprom_read_byte(x)			*x			/*!< Pseudo-EEPROM-Funktion fuer PC */
> -	#define eeprom_write_byte(ptr, x)	*ptr = x	/*!< Pseudo-EEPROM-Funktion fuer PC */
> +	#include "eeprom-emu.h"
>  	#define ANGLE_CORRECT	0						/*!< Drehfehler-Init */
>  #endif	// MCU
>  
>  /* EEPROM-Variablen immer deklarieren, damit die Adressen sich nicht veraendern je nach #define */
> -uint8 EE_SECTION err15=ANGLE_CORRECT	*1;			/*!< Fehler bei Drehungen unter 15 Grad */
> -uint8 EE_SECTION err45=ANGLE_CORRECT	*2;			/*!< Fehler bei Drehungen zwischen 15 und 45 Grad */
> -uint8 EE_SECTION err_big=ANGLE_CORRECT	*4;			/*!< Fehler bei groesseren Drehungen */
> +uint8 EEPROM err15=ANGLE_CORRECT	*1;			/*!< Fehler bei Drehungen unter 15 Grad */
> +uint8 EEPROM err45=ANGLE_CORRECT	*2;			/*!< Fehler bei Drehungen zwischen 15 und 45 Grad */
> +uint8 EEPROM err_big=ANGLE_CORRECT	*4;			/*!< Fehler bei groesseren Drehungen */
>  
>  
>  #ifdef BEHAVIOUR_TURN_AVAILABLE
> Index: E:/eclipse/ct-bot test/ct-Bot/motor.c
> ===================================================================
> --- E:/eclipse/ct-bot test/ct-Bot/motor.c	(revision 1162)
> +++ E:/eclipse/ct-bot test/ct-Bot/motor.c	(working copy)
> @@ -46,6 +46,9 @@
>  #ifdef MCU
>  	#include <avr/eeprom.h>
>  #endif
> +#ifdef PC
> +	#include "eeprom-emu.h"
> +#endif
>  
>  int16 speed_l = 0;	/*!< Sollgeschwindigkeit linker Motor */
>  int16 speed_r = 0;	/*!< Sollgeschwindigkeit rechter Motor */
> @@ -86,11 +89,9 @@
>  //	static volatile uint8 acc_test[2];			/*!< nur Testcase */
>  //	static volatile uint16 acc_test_dt[2];		/*!< nur Testcase */
>  #endif	// SPEED_CONTROL_AVAILABLE
> -#ifdef MCU
> -	/* EEPROM-Variable immer deklarieren, damit die Adresse sich nicht veraendert je nach #define */
> -	/*! EEPROM-Kopie von pwm_values */
> -	uint8_t __attribute__ ((section (".eeprom"),aligned (1))) pwmSlow[4] = {255, 255, 255, 255};
> -#endif
> +
> +/* EEPROM-Variable immer deklarieren, damit die Adresse sich nicht veraendert je nach #define */
> +uint8_t EEPROM pwmSlow[4] = {255, 255, 255, 255};	/*!< EEPROM-Kopie von pwm_values */
>  	
>  direction_t direction;		/*!< Drehrichtung der Motoren */
>  
> Index: E:/eclipse/ct-bot test/ct-Bot/include/eeprom-emu.h
> ===================================================================
> --- E:/eclipse/ct-bot test/ct-Bot/include/eeprom-emu.h	(revision 0)
> +++ E:/eclipse/ct-bot test/ct-Bot/include/eeprom-emu.h	(revision 0)
> @@ -0,0 +1,67 @@
> +/*
> + * 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 	eeprom-emu.h  
> + * @brief 	Low-Level Routinen fuer den Zugriff auf das EEPROM des c't-Bots
> + * @author 	Achim Pankalla (achim.pankalla@xxxxxx)
> + * @date 	01.03.07
> +*/
> +#ifndef eeprom_emu_H_
> +#define eeprom_emu_H_
> +
> +#ifdef PC
> +#include <stddef.h>
> +
> +/*!
> + * Flagge die bei Wahr die EEPROM Datei mit den Werten der EEP Datei initialisiert.
> + */
> +extern uint8 eeprom_init;
> +
> +/*!
> + * Initialisiert den EEPROM-Manager fuer den Simulierten Bot. Danach steht dem PC-Bot
> + * auch ein EEPROM zur Verfuegung.
> + */ 
> +extern void init_eeprom_man(void);
> +
> +/*!
> + * Speichern Daten im EEPROM.
> + * @param address Adresse im EEPROM zwischen 0 und 1023.
> + * @param data Variable mit den abzulegenen Daten.
> + */ 
> +extern void eeprom_write_byte(uint8  *adr, uint8 value);
> +extern void eeprom_write_word(uint16 *adr, uint16 value);
> +
> +/*! 
> + * Laden Daten aus dem EEPROM.
> + * @param address Adresse im EEPROM zwischen 0 und 1023.
> + * @return Wert der Speicheraddresse im EEPROM
> + */ 
> +extern uint8  eeprom_read_byte(uint8  *adr);
> +extern uint16 eeprom_read_word(uint16 *adr);
> +
> +/*! 
> + * Kopiert ein Block aus den EEPROM oder in das EEPROM
> + * @param address Adresse im Speicher.
> + * @param address Adresse im EEPROM.
> + */ 
> +extern void eeprom_read_block(void *pointer_ram, const void *pointer_eeprom, size_t size);
> +extern void eeprom_write_block(const void *pointer_ram, void *pointer_eeprom, size_t size);
> +
> +#endif
> +#endif
> Index: E:/eclipse/ct-bot test/ct-Bot/include/global.h
> ===================================================================
> --- E:/eclipse/ct-bot test/ct-Bot/include/global.h	(revision 1162)
> +++ E:/eclipse/ct-bot test/ct-Bot/include/global.h	(working copy)
> @@ -60,11 +60,12 @@
>  	#define On                    1		/*!< An */
>  	#define Off                   0		/*!< Aus */
>  
> +	#ifdef PC							/*!< Unterscheidung der EEPROM definition */
> +		#define EEPROM __attribute__ ((section (".eeprom"),aligned(1)))
> +	#endif
>  	#ifdef MCU
> -		#define EE_SECTION	__attribute__ ((section (".eeprom"),aligned (1)))	/*!< Shortcut fuer EEPROM-Section */
> -	#else
> -		#define EE_SECTION														/*!< Shortcut fuer EEPROM-Section */
> -	#endif	// MCU
> +		#define EEPROM __attribute__ ((section (".eeprom")))
> +	#endif
>  
>  	#define binary(var,bit) ((var >> bit)&1)	/*!< gibt das Bit "bit" von "var" zurueck */
>  	
> Index: E:/eclipse/ct-bot test/ct-Bot/include/gui.h
> ===================================================================
> --- E:/eclipse/ct-bot test/ct-Bot/include/gui.h	(revision 1162)
> +++ E:/eclipse/ct-bot test/ct-Bot/include/gui.h	(working copy)
> @@ -31,9 +31,7 @@
>  
>  extern int8 max_screens;	/*!< Anzahl der zurzeit registrierten Screens */
>  extern void (* screen_functions[DISPLAY_SCREENS])(void);	/*!< hier liegen die Zeiger auf die Display-Funktionen */
> -#ifdef MCU
> -	extern uint8 __attribute__ ((section (".eeprom"))) resetsEEPROM;	/*!< Reset-Counter-Wert im EEPROM */
> -#endif
> +extern uint8 EEPROM resetsEEPROM;	/*!< Reset-Counter-Wert im EEPROM */
>  
>  /*! 
>   * @brief 			Display-Screen Anzeige
> Index: E:/eclipse/ct-bot test/ct-Bot/mcu/mini-fat.c
> ===================================================================
> --- E:/eclipse/ct-bot test/ct-Bot/mcu/mini-fat.c	(revision 1162)
> +++ E:/eclipse/ct-bot test/ct-Bot/mcu/mini-fat.c	(working copy)
> @@ -31,7 +31,7 @@
>  #ifdef MCU
>  #include "avr/eeprom.h"
>  /* EEPROM-Variable immer deklarieren, damit die Adresse sich nicht veraendert je nach #define */
> -uint32 __attribute__ ((section (".eeprom"))) eefat[10] = {0};	/*!< EEPROM-Cache fuer FAT-Eintraege */
> +uint32 EEPROM eefat[10] = {0};	/*!< EEPROM-Cache fuer FAT-Eintraege */
>  
>  #ifdef MMC_AVAILABLE	
>  
> Index: E:/eclipse/ct-bot test/ct-Bot/sensor.c
> ===================================================================
> --- E:/eclipse/ct-bot test/ct-Bot/sensor.c	(revision 1162)
> +++ E:/eclipse/ct-bot test/ct-Bot/sensor.c	(working copy)
> @@ -41,9 +41,8 @@
>  #ifdef MCU
>  	#include <avr/eeprom.h>
>  #else
> -	/* derzeit kein EEPROM fuer PC vorhanden, Daten liegen einfach im RAM */
> -	#define eeprom_read_byte(x)	*x											/*!< Pseudo-EEPROM-Funktion fuer PC */
> -#endif	// MCU
> +	#include "eeprom-emu.h"
> +#endif
>  
>  // Defines einiger, haeufiger benoetigter Konstanten
>  #define DEG2RAD (2*M_PI/360)	/*!< Umrechnung von Grad nach Bogenmass */ 
> @@ -59,9 +58,9 @@
>  /*! Zeiger auf die Auswertungsfunktion fuer die Distanzsensordaten, const. solange sie nicht kalibriert werden */
>  void (* sensor_update_distance)(int16* const p_sens, uint8* const p_toggle, const distSens_t* ptr, int16 volt) = sensor_dist_lookup;
>  
> -distSens_t EE_SECTION sensDistDataL[] = SENSDIST_DATA_LEFT;		/*!< kalibrierte Referenzdaten fuer linken IR-Sensor */
> -distSens_t EE_SECTION sensDistDataR[] = SENSDIST_DATA_RIGHT;	/*!< kalibrierte Referenzdaten fuer rechten IR-Sensor */
> -uint8_t EE_SECTION sensDistOffset = SENSDIST_OFFSET;			/*!< Spannungs-Offset IR-Sensoren */
> +distSens_t EEPROM sensDistDataL[] = SENSDIST_DATA_LEFT;		/*!< kalibrierte Referenzdaten fuer linken IR-Sensor */
> +distSens_t EEPROM sensDistDataR[] = SENSDIST_DATA_RIGHT;	/*!< kalibrierte Referenzdaten fuer rechten IR-Sensor */
> +uint8_t EEPROM sensDistOffset = SENSDIST_OFFSET;			/*!< Spannungs-Offset IR-Sensoren */
>  
>  int16 sensBorderL=0;	/*!< Abgrundsensor links */
>  int16 sensBorderR=0;	/*!< Abgrundsensor rechts */
> @@ -163,7 +162,7 @@
>  	else  volt = (volt_16 >> 3) - offset;
>  	
>  	/* Spannung in LT-Table suchen */
> -	uint8 pivot = eeprom_read_byte(&ptr[n-1].voltage);	// in welcher Region muessen wir suchen?
> +	uint8 pivot = eeprom_read_byte((uint8*)&ptr[n-1].voltage);	// in welcher Region muessen wir suchen?
>  	if (volt > pivot) {
>  		/* in unterer Haelfte suchen */
>  		i = 0;
> @@ -175,7 +174,7 @@
>  	}
>  	uint8_t tmp=0;
>  	for (; i<n; i++) {
> -		tmp = eeprom_read_byte(&ptr->voltage);
> +		tmp = eeprom_read_byte((uint8*)&ptr->voltage);
>  		if (volt > tmp)	// aufsteigend suchen, damit der kritische Fall (kleine Entfernung) schneller gefunden wird
>  			break;	// ptr zeigt jetzt auf die naechst kleinere Spannung
>  		ptr++; 
> @@ -187,7 +186,7 @@
>  	} 
>  	
>  	/* Entfernung berechnen und speichern */
> -	uint8 distance = lin_interpolate(eeprom_read_byte(&(ptr-1)->voltage), eeprom_read_byte(&(ptr-1)->dist), tmp, eeprom_read_byte(&ptr->dist), volt);
> +	uint8 distance = lin_interpolate(eeprom_read_byte((uint8*)&(ptr-1)->voltage), eeprom_read_byte((uint8*)&(ptr-1)->dist), tmp, eeprom_read_byte((uint8*)&ptr->dist), volt);
>  	*p_sens = distance >= SENS_IR_MAX_DIST/5 ? SENS_IR_INFINITE : distance * 5;	// Distanz ist gefuenftelt in den Ref.-Daten;
>  	
>  	/* Sensorupdate-Info toggeln */
> Index: E:/eclipse/ct-bot test/ct-Bot/pc/mini-fat.c
> ===================================================================
> --- E:/eclipse/ct-bot test/ct-Bot/pc/mini-fat.c	(revision 1162)
> +++ E:/eclipse/ct-bot test/ct-Bot/pc/mini-fat.c	(working copy)
> @@ -36,6 +36,9 @@
>  #include "mmc-vm.h"
>  #include "mmc-emu.h"
>  
> +/* EEPROM-Variable immer deklarieren, damit die Adresse sich nicht veraendert je nach #define */
> +uint32 EEPROM eefat[10] = {0};	/*!< EEPROM-Cache fuer FAT-Eintraege */
> +
>  /*! 
>   * Erzeugt eine Datei, die an den ersten Bytes die ID enthaelt. Dann folgen 512 - sizeof(id) nullen
>   * Danach kommen so viele size kByte Nullen
> Index: E:/eclipse/ct-bot test/ct-Bot/pc/eeprom-emu_pc.c
> ===================================================================
> --- E:/eclipse/ct-bot test/ct-Bot/pc/eeprom-emu_pc.c	(revision 0)
> +++ E:/eclipse/ct-bot test/ct-Bot/pc/eeprom-emu_pc.c	(revision 0)
> @@ -0,0 +1,455 @@
> +/*
> + * 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 	eeprom-emu_pc.c  
> + * @brief 	Low-Level Routinen fuer den Zugriff auf das emulierte EEPROM des Sim-c't-Bots
> + * @author 	Achim Pankalla (achim.pankalla@xxxxxx)
> + * @date 	07.06.2007
> +*/
> +
> +#include "ct-Bot.h"
> +
> +#ifdef PC
> +
> +#include <stdio.h>
> +#include <string.h>
> +
> +#include "log.h"
> +
> +extern uint8 EEPROM resetsEEPROM;	/*!< Reset-Counter-Wert im EEPROM als Sectionreferenz*/
> +extern uint8 __attribute__ ((section (".s1eeprom"))) __attribute__((aligned(1))) _eeprom_start1__;
> +extern uint8 __attribute__ ((section (".s2eeprom"))) __attribute__((aligned(1))) _eeprom_start2__;
> +
> +/*! Normiert PC EEPROM Adressen*/
> +#define EEPROM_ADDR(x) ((uint32)x - (uint32)&_eeprom_start2__ - ((uint32)&_eeprom_start2__ - (uint32)&_eeprom_start1__))
> +/*! Defines zum Mitloggen von EEPROM Zugriffen*/
> +#define LOG_LOAD 	if(addrconv) {LOG_DEBUG("LOAD: %s : %d", ctab[lastctabi].varname, (uint16)dataline[0] + (uint16)dataline[1]*256);}\
> +					else {LOG_DEBUG("load-addr=0x%x/%d", address,(uint16)dataline[0] + (uint16)dataline[1]*256);}
> +#define LOG_STORE 	if(addrconv) {LOG_DEBUG("STORE: %s : %d", ctab[lastctabi].varname, data);}\
> +					else {LOG_DEBUG("load-addr=0x%x/%d", address, data);}
> +									
> +#ifdef __AVR_ATmega644__  /*! Dieser Prozessor hat 2048Bytes EEPROM*/
> +	#define EE_SIZE 2048
> +#else
> +	#define EE_SIZE 1024
> +#endif
> +
> +#define EEPROM_FILENAME	"./eeprom.bin" 		/*<! Name und Pfad der EEPROM Datei. Verzeichnis muss existieren. Backslash doppeln!*/
> +#define MAX_VAR 200  						/*<! Maximale Anszahl von Variablen*/
> +#define EEMAP_MCU "../debug-mcu-w32/eeprom_mcu.map"  /*<! Pfade fuer MAP / EEP Dateien */ 
> +#define EEMAP_PC  "./eeprom_pc.map"
> +#define EEP_PC    "./ct-bot.eep"
> +
> +typedef struct addrtab {					/*<! Spezieller Datentype fuer Adresskonvertierung*/
> +	char varname[20];
> +	uint32 simaddr;
> +	uint32 botaddr;
> +	uint32 size;
> +	uint32 access;
> +	} AddrCTab;
> +
> +static AddrCTab ctab[MAX_VAR]; 				/*<! Adresskonvertierungstabelle */
> +static uint16 tsize=0; 						/*<! Anzahl Eintraege in der Tabelle */
> +static uint8 addrconv = 0;                  /*<! Adresskonvertierung ein-/ausschalten*/
> +static uint16 lastctabi = 0;                /*<! Letzter Zugriffsindex auf ctab*/
> +uint8 eeprom_init = 0;						/*<! Flagge fuer EEPROM Initialsierung*/
> +
> +/*! 
> + * Diese Funktion konvertiert die Adressen der EEPROM Variablen des PC so,
> + * das sie den Adressen im realen ct-bot entsprechen. Dafuer wird mit der Funktion
> + * create_ctab ein Adresstabelle angelegt, diese nutzt diese Funktion.
> + * @param address Adresse im EEPROM zwischen 0 und EE_SIZE-1.
> + * @return Die neue Adresse für den realen Bot.
> + */
> +static uint32 conv_eeaddr(uint32 addr){
> +	int8 i;
> +	int32 adiff;
> +
> +	if(!addrconv) //Keine Adresskonvertierung
> +		return(addr);
> +	for(i=0; i<tsize; i++){
> +		adiff = addr - ctab[i].simaddr;
> +		if(adiff < 0)
> +			return(0xffffffff);
> +		if(adiff < ctab[i].size){
> +			lastctabi = i; //Letzer guelten Index merken
> +			return(ctab[i].botaddr + adiff);
> +		}
> +	}
> +	return(0xffffffff);
> +}
> +
> +/*!
> + * Diese Funktion uberprueft das vorhanden sein der eeprom.bin und initialisiert sie
> + * gegebenenfalls mit der Initwerten der eep Datei.
> + * Es wird dabei die Adresskovertierung benutzt, wenn die EEPROM Simulation im MCU-Modus 
> + * ist.
> + * -----
> + *  0 = EEPROM Datei OK
> + *  1 = Fehler aufgetreten
> + * -----
> + * @param initfile EEP Datei des PC Kodes.
> + * @return Status der Funktion
> + */
> +static uint16 check_eeprom_file(char *initfile){
> +	FILE *fpr, *fpw; //Filepointer fuer Dateizugriffe
> +	uint16 i; //Laufvariable
> +	char data[2]; //Datenspeicher
> +	
> +	/*eeprom file vorhanden*/
> +	if(!(fpw = fopen(EEPROM_FILENAME, "r+b"))){ //Testen, ob Datei vorhanden ist.
> +		int16 i; //Laufvariable
> +		
> +		if(!(fpw = fopen(EEPROM_FILENAME, "w+b"))){ //wenn nicht, dann erstellen
> +			LOG_INFO("->Kann EEPROM-Datei nicht erstellen");
> +			return(1);
> +		}
> +		for(i = 0; i < EE_SIZE; i++) //Leeres EEPROM erstellen
> +			fwrite("\377", 1, 1, fpw);
> +		fclose(fpw);
> +		LOG_INFO("->Leere EEPROM-Datei erstellt");
> + 	}
> +	
> +	/*Initialsieren der eeprom.bin, wenn gewuenscht*/
> +	if(eeprom_init){
> +		if(!(fpr = fopen(initfile, "rb"))){ //Datei oeffnen
> +			LOG_INFO("->EEP nicht gefunden");
> +			return(1);
> +		}
> +		if(!(fpw = fopen(EEPROM_FILENAME, "rb+"))){ //Datei oeffnen
> +			LOG_INFO("->EEPROM-Datei kann nicht beschrieben werden");
> +			return(1);
> +		}
> +		
> +		/*EEP-Datei in EEPROM-Datei kopieren*/
> +		for(i=0; i<EE_SIZE; i++){
> +			/*Daten kopieren*/
> +			if(!fread(data, 1, 1, fpr))
> +				break;
> +			if(addrconv){ //EEPROM-Datei im MCU-Modus
> +				uint32 naddr;//Konvertierte Adresse
> +				
> +				naddr = conv_eeaddr((uint32)i);
> +				if(naddr != 0xffffffff){
> +					fseek(fpw, (int32)naddr, SEEK_SET);
> +				}
> +				else{
> +					continue; //Nichts schreiben Adresse nicht belegt
> +				}
> +			}
> +			fwrite(data, 1, 1, fpw);
> +		}
> +		fclose(fpr);
> +		fclose(fpw);
> +		LOG_INFO("->EEPROM-Datei mit Daten init.");
> +	}
> +	return(0);
> +}
> +
> +/*!
> + * Diese Funktion erstellt aus den beiden im Post erstellten MAP Dateien eine Tabelle
> + * zum umrechnen der PC-Adressen in die des Winavr Compiler. Dadurch kann die EEPROM 
> + * Datei in einen zum EEPROM des Bot kompatiblen Format gehalten werden.
> + * Wichtige Informationen werden über LOG_INFO angezeigt.
> + * ----
> + * Ergebniskodes der Funktion
> + * 0 = Fehlerfrei
> + * 1 = Sim Mapfile nicht vorhanden
> + * 2 = Bot Mapfile nicht vorhanden
> + * 3 = Unterschiedlicher Variablenbestand
> + * 4 = Zuviele Variablen
> + * 5 = EEPROM voll
> + * 6 = Unterschiedliche Variablenanzahl
> + * 
> + * @param simfile MAP mit den Adressen der EEPROM-Variablen in der PC EXE.
> + * @param botfile MAP mit den Adressen der EEPROM-Variablen im MCU EXE.
> + * @return Statuskodes.
> + */
> +static uint16 create_ctab(char *simfile, char *botfile){
> +	FILE *fps, *fpb;
> +	char sline[250], bline[250]; //Textzeilen aus Dateien
> +	char d[30], d1[30], d2[30], vname_s[30], vname_b[20]; //Dummy und Variablennamen
> +	int32 addr_s, addr_b; //Adressen der Variablen
> +	char saddr[30], ssize[30]; //Stringvarianten fuer die Bot Daten
> +	uint32 size; //Variablengroesse
> +	int16 i, ii; //Laufvariablen
> +	uint16 vc = 0; //Variablenzaehler
> +
> +	/*Dateien oeffnen*/
> +	if(!(fps=fopen(simfile,"r"))){
> +		LOG_INFO("->EEPROM-MAP fuer PC fehlt");
> +		return(1);
> +	}
> +	if(!(fpb=fopen(botfile,"r"))){
> +		LOG_INFO("->EEPROM-MAP fuer MCU fehlt");		
> +		return(2);
> +	}
> +
> +	/*Anzahl Variablen vergleichen*/
> +	while(fgets(sline, 249, fps)) vc++;
> +	while(fgets(sline, 249, fpb)) vc--;
> +	if(vc){
> +		fclose(fps);
> +		fclose(fpb);
> +		LOG_INFO("->Unterschiedliche Variablenanzahl");
> +		return(6);
> +	}
> +	rewind(fps);
> +	rewind(fpb);
> +
> +	/*Tabelle erstellen*/
> +	while(fgets(sline, 249, fps)){
> +		rewind(fpb);
> +		sscanf(&sline[47], "%x %s", &addr_s, vname_s);
> +		while(fgets(bline, 249, fpb)){
> +			/*Variablennamen suchen*/
> +			sscanf(&bline[4], "%s %s %s %s %s %s", d1, d, d, d, d2, vname_b);
> +			sprintf(saddr, "0x%s", d1);
> +			sscanf(saddr, "%x", &addr_b);
> +			sprintf(ssize, "0x%s", &d2[4]);
> +			sscanf(ssize, "%x", &size);
> +			if(!strcmp(&vname_s[1], vname_b)){
> +				/*Daten kopieren*/
> +				strcpy(ctab[tsize].varname, vname_b);
> +				ctab[tsize].simaddr = addr_s;
> +				ctab[tsize].botaddr = addr_b;
> +				ctab[tsize].size    = size;
> +				ctab[tsize++].access  = 0;
> +
> +				/*Fehlerabbrueche*/
> +				if(tsize == MAX_VAR){
> +					LOG_INFO("->Mehr als %n Variablen",MAX_VAR);
> +					return(4);
> +				}
> +				if(addr_s > EE_SIZE){
> +					LOG_INFO("->EEPROM voll");
> +					return(5);
> +				}
> +				
> +				/*Erfolg markieren*/
> +				addr_b = -1;
> +				break;
> +			}
> +		}
> +		if(addr_b > -1){ //Keine passende Variable gefunden
> +			LOG_INFO("->Unterschiedliche Variablen");
> +			return(3);
> +		}
> +	}
> +
> +	/*Dateien schliessen*/
> +	fclose(fps);
> +	fclose(fpb);
> +	
> +	/*Tabelle nach Sim-Adressen sortieren*/
> +	for(ii=tsize-1; ii > 0; ii--){
> +		for(i=0; i < ii; i++){
> +			if(ctab[i].simaddr > ctab[i+1].simaddr){
> +				long simaddr, botaddr, size;
> +				char vname[30];
> +			
> +				/*Daten umkopieren*/
> +				strcpy(vname, ctab[i+1].varname);
> +				simaddr = ctab[i+1].simaddr;
> +				botaddr = ctab[i+1].botaddr;
> +				size    = ctab[i+1].size;
> +
> +				strcpy(ctab[i+1].varname, ctab[i].varname);
> +				ctab[i+1].simaddr = ctab[i].simaddr;
> +				ctab[i+1].botaddr = ctab[i].botaddr;
> +				ctab[i+1].size    = ctab[i].size;
> +
> +				strcpy(ctab[i].varname, vname);
> +				ctab[i].simaddr = simaddr;
> +				ctab[i].botaddr = botaddr;
> +				ctab[i].size    = size;
> +			}
> +		}
> +	}
> +	return(0);
> +}
> +
> +/*! 
> + * Diese Funktion initialisiert die eeprom-emulation. Sie sorgt für die Erstellung der
> + * eeprom.bin, falls nicht vorhanden und erstellt ueber eine Hilfsfunktion eine Adress-
> + * konvertierungstabelle fuer die EEPROM-Adressen, wenn die benoetigten Daten vorliegen.
> + * Statusinformationen werden ueber DEBUG_INFO angezeigt.
> + */
> +void init_eeprom_man(void){
> +	uint16 status; //Status von create_ctab
> +	uint16 sflag; //Sectionstatus
> +	
> +	LOG_INFO("EEPROM-Manager");
> +
> +	/*Adresskonvertierungstabelle anlegen*/
> +	if((status=create_ctab(EEMAP_PC, EEMAP_MCU))){
> +			LOG_INFO("->EEPROM im PC-Modus");
> +	}
> +	else {
> +			LOG_INFO("->EEPROM im MCU-Modus");
> +			addrconv = 1;
> +	}
> +	
> +	/*Sections ueberpruefen*/
> +	if((&_eeprom_start2__ - &_eeprom_start1__) > 0 && (&resetsEEPROM - &_eeprom_start2__) >0){
> +		LOG_INFO("->Sections liegen wohl korrekt");
> +		LOG_INFO("->Section Abstand 0x%X", (&_eeprom_start2__ - &_eeprom_start1__));
> +		sflag = 0;
> +	}
> +	else{
> +		LOG_INFO("->Sections liegen falsch");
> +		sflag = 1;
> +	}
> +	
> +	/*eeprom.bin checken*/ 
> +	if(sflag || check_eeprom_file(EEP_PC)){
> +		LOG_INFO("EEPROM-Emulation fehlerhaft");
> +	}
> +	else{
> +		LOG_INFO("->EEPROM Groesse %d Bytes", EE_SIZE);
> +		LOG_INFO("EEPROM-Emulation einsatzbereit");
> +	}
> +	return;
> +}
> +
> +/*! 
> + * Traegt die uebergebenen Daten in das simulierte EEPROM ein. Dieses simulierte EEPROM 
> + * besteht aus einer Datei. 
> + * Es koennen Bytes (uint8 size = 1) und Integer (uint16 size = 2) uebergeben werden.
> + * @param address Adresse im EEPROM zwischen 0 und EE_SIZE-1.
> + * @param data Daten die abgelegt werden sollen.
> + * @param size Groesse der Daten in Byte.
> + */  
> +static void store_parameter(uint16 address, uint16 data, uint8 size) {
> +	FILE  *fpw; 	//Dateizeiger
> +	uint8 dataline[2];	//Speicher fuer Datenausgabe
> +
> +//	LOG_STORE
> +	if(address > (size == 1 ? EE_SIZE-1 : EE_SIZE-2)) //Adresse checken
> +		return;
> +
> +	if(!(fpw = fopen(EEPROM_FILENAME, "r+b"))){ //Testen, ob Datei vorhanden ist.
> +			return;
> +	}
> +
> +	//Daten eintragen
> +	fseek(fpw, address, SEEK_SET); //Schreibzeiger setzen
> +	dataline[0] = data%256;
> +	dataline[1] = data/256;
> +	fwrite(dataline, 1, size, fpw);	//Daten schreiben
> +
> +	fclose(fpw);
> +	return;	
> +}
> +
> +/*! 
> + * Liest die gewuenschten Daten aus eine simulierten EEPROM. Dieses simulierte EEPROM 
> + * besteht aus der Datei eeprom.bin. 
> + * @param address Adresse im EEPROM zwischen 0 und EE_SIZE-1.
> + * @param size Groesse der Daten in Byte.
> + * @return Aus dem EEPROM gelesener Wert.
> + */  
> +static uint16 load_parameter(uint16 address, uint8 size) {
> +	FILE *fpr; 	//Dateizeiger
> +	uint8 dataline[2] = {0,0};	//String fuer Datenausgabe
> +
> +	if(address > (size == 1 ? EE_SIZE-1 : EE_SIZE-2)) //Adresse checken
> +		return((size == 1 ? 0xff : 0xffff));
> +
> +	if(!(fpr = fopen(EEPROM_FILENAME, "rb"))){ //Datei oeffnen
> +		return((size == 1 ? 0xff : 0xffff));
> +	}
> +
> +	//Daten eintragen
> +	fseek(fpr, address, SEEK_SET); //Lesezeiger setzen
> +	fread(dataline, 1, size, fpr);	//Daten lesen);
> +	fclose(fpr);
> +//	LOG_LOAD
> +	return((uint16)dataline[0] + (uint16)dataline[1]*256);	
> +}
> +
> +/*!
> + * Liest ein Byte aus den simulierten EEPROM
> + * @param addr Adresse im EEPROM
> + * @return Aus dem EEPROM gelesener Wert.
> + */  
> +uint8 eeprom_read_byte(uint8 *addr) {
> +	return((uint8)load_parameter((uint16)conv_eeaddr(EEPROM_ADDR(addr)), 1));
> +}
> +
> +/*!
> + * Liest ein Word aus den simulierten EEPROM
> + * @param addr Adresse im EEPROM
> + * @return Aus dem EEPROM gelesener Wert.
> + */  
> +uint16 eeprom_read_word(uint16 *addr) {
> +	return(load_parameter((uint16)conv_eeaddr(EEPROM_ADDR(addr)), 2));
> +}
> +
> +/*!
> + * Schreibt ein Byte in das simulierte EEPROM
> + * @param addr Adresse im EEPROM
> + * @param Zu schreibender Wert.
> + */  
> +void eeprom_write_byte(uint8 *addr, uint8 value) {
> +	store_parameter((uint16)conv_eeaddr(EEPROM_ADDR(addr)), (uint16)value, 1);
> +}
> +
> +/*!
> + * Schreibt ein Word in das simulierte EEPROM
> + * @param addr Adresse im EEPROM
> + * @param Zu schreibender Wert.
> + */  
> +void eeprom_write_word(uint16 *addr, uint16 value) {
> +	store_parameter((uint16)conv_eeaddr(EEPROM_ADDR(addr)), value, 2);
> +}
> +
> +/*!
> + * Liest ein Speicherblock aus dem simulierte EEPROM
> + * @param pointer_ram Adresse im Hauptspeicher
> + * @param pointer_eeprom Adresse im EEPROM
> + * @param Groesze des Block.
> + */  
> +void eeprom_read_block (void *pointer_ram, const void *pointer_eeprom, size_t size) {
> +	uint32 i;
> +	uint8 *ram;
> +	
> +	ram = (uint8 *)pointer_ram;
> +	for(i=0; i< size; i++){
> +		ram[i]=(uint16)load_parameter((uint16)conv_eeaddr(EEPROM_ADDR(pointer_eeprom)) + i, 1);
> +	}
> +}
> +
> +/*!
> + * Schreibt ein Speicherblock in das simulierte EEPROM
> + * @param pointer_ram Adresse im Hauptspeicher
> + * @param pointer_eeprom Adresse im EEPROM
> + * @param Groesze des Block.
> + */  
> +void eeprom_write_block (const void *pointer_ram, void *pointer_eeprom, size_t size) {
> +	uint32 i;
> +	uint8 *ram;
> +	
> +	ram = (uint8 *)pointer_ram;
> +	for(i=0; i< size; i++){
> +		store_parameter((uint16)conv_eeaddr(EEPROM_ADDR(pointer_eeprom)) + i, (uint16)ram[i] ,1);
> +	}
> +}
> +
> +#endif
> Index: E:/eclipse/ct-bot test/ct-Bot/Documentation/eeprom-simulation.html
> ===================================================================
> --- E:/eclipse/ct-bot test/ct-Bot/Documentation/eeprom-simulation.html	(revision 0)
> +++ E:/eclipse/ct-bot test/ct-Bot/Documentation/eeprom-simulation.html	(revision 0)
> @@ -0,0 +1,245 @@
> +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
> +<HTML>
> +<HEAD>
> +	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=windows-1252">
> +	<TITLE></TITLE>
> +	<META NAME="GENERATOR" CONTENT="OpenOffice.org 2.2  (Win32)">
> +	<META NAME="AUTHOR" CONTENT="Achim Pankalla">
> +	<META NAME="CREATED" CONTENT="20060528;19455600">
> +	<META NAME="CHANGEDBY" CONTENT="Achim Pankalla">
> +	<META NAME="CHANGED" CONTENT="20070617;18142584">
> +	<STYLE TYPE="text/css">
> +	<!--
> +		@page { size: 21cm 29.7cm; margin: 2cm }
> +		P { margin-bottom: 0.21cm }
> +	-->
> +	</STYLE>
> +</HEAD>
> +<BODY LANG="de-DE" DIR="LTR">
> +<P ALIGN=CENTER STYLE="margin-bottom: 0cm"><B>EEPROM Simulation f&uuml;r
> +PC</B></P>
> +<P STYLE="margin-bottom: 0cm"><BR>
> +</P>
> +<P STYLE="margin-bottom: 0cm"><FONT SIZE=3><B>Author: </B></FONT>
> +</P>
> +<P STYLE="margin-bottom: 0cm"><FONT SIZE=3>Achim Pankalla
> +(achim.pankalla@xxxxxx)</FONT></P>
> +<P STYLE="margin-bottom: 0cm"><BR>
> +</P>
> +<P STYLE="margin-bottom: 0cm"><B>Beschreibung:</B></P>
> +<P ALIGN=LEFT STYLE="margin-bottom: 0cm; font-style: normal">Die
> +EEPROM Simulation f&uuml;r den PC stellt das EEPROM des <I>Atmel
> +MEGA32(664) Prozessor</I> auch dem Simulierten ct-bot zur Verf&uuml;gung.
> +Der Zugriff auf dieses EEPROM erfolgt &uuml;ber gleichnamige
> +Funktionen, wie sie auch der avr-gcc besitzt und auch die
> +Variablendefinition erfolgt &uuml;ber die gleichen Konstrukte. Eine
> +Unterscheidung &uuml;ber #ifdef's ist also nicht notwendig.<BR>Durch
> +diese EEPROM-Simulation, ist der Simulator dem realen Bot ein schritt
> +n&auml;her gekommen und Programme mit EEPROM-Zugriffe k&ouml;nnen mit
> +der Simulation getestet werden. Mehr noch, sie k&ouml;nnen auch das
> +Simulierte EEPROM auf den ct-bot &uuml;bertragen oder das EEPROM vom
> +ct-bot abziehen und f&uuml;r die Simulation nutzen.</P>
> +<P ALIGN=LEFT STYLE="margin-bottom: 0cm"><BR>
> +</P>
> +<P STYLE="margin-bottom: 0cm; font-style: normal"><B>Implementierung:</B></P>
> +<P STYLE="margin-bottom: 0cm">Alle Funktionen und Einstellungen der
> +EEPROM Simulation findet Sie in den Dateien <I>pc/eeprom-emu_pc.c</I>
> +und <I>include/eeprom-emu.h</I>. Das EEPROM selbst wird durch eine
> +Bin&auml;re Datei (genau 1K bzw. 2K gross) repr&auml;sentiert (und
> +kann so mit einen HexEditor bearbeitet werden), deren Pfad in der
> +C-Datei festgelegt wird. Standard Pfad ist das Heimatverzeichnis des
> +Ct-Sim. Nat&uuml;rlich k&ouml;nnen Sie das jederzeit &auml;ndern,
> +dies geht &uuml;ber die Konstante <FONT COLOR="#000000"><FONT FACE="Courier New, monospace"><FONT SIZE=2>EEPROM_FILENAME.</FONT></FONT></FONT>
> +<FONT FACE="Times New Roman, serif">Der Name </FONT><FONT FACE="Times New Roman, serif"><I>eeprom.bin</I></FONT>
> +<FONT FACE="Times New Roman, serif">sollte dabei belassen werden.</FONT><BR>Die
> +Datei wird automatisch neu angelegt, wenn sie noch nicht existiert.
> +Dann besteht der Inhalt nur aus 0xFF, wie es auch beim
> +unintialisierten EEPROM des Atmel der Fall ist.<BR>Damit die
> +EEPROM-Funktionen des PC korrekt auf die Datei zugreifen k&ouml;nnen
> +und nur ein Adressraum von 0 bis 1023(2047) entsteht, bedarf es bei
> +der PC Implementierung (mit PC ist allgemein der Kode f&uuml;r die
> +Simulation gemeint, mag das OS nun Win, Linux oder MacOS hei&szlig;en)
> +eines Tricks. Die Emulation muss wissen welche Speicheradresse die
> +erste Variable hat.<BR>Daf&uuml;r gibt es die beiden Variablen
> +<I>_eeprom_start1__</I> und <I>_eeprom_start2_</I><SPAN STYLE="font-style: normal">_
> +in </SPAN><I>ctbot.c</I><SPAN STYLE="font-style: normal">. Diese
> +stehen dort, damit sie auf jeden Fall vor der ersten EEPROM Variable
> +definiert werden und damit ihre Sections (.</SPAN><I>s1eeprom</I> <SPAN STYLE="font-style: normal">+
> +.</SPAN><I>s2eeprom</I><SPAN STYLE="font-style: normal">) auf jeden
> +Fall vor der Section .</SPAN><I>eeprom</I> <SPAN STYLE="font-style: normal">liegen.
> +Sie d&uuml;rfen also auf keine Fall eine EEPROM Variable vor diesen
> +definieren. Deshalb sind auch solche Variablen in </SPAN><I><B>command</B></I><SPAN STYLE="font-style: normal"><B>.</B></SPAN><I><B>c</B></I>
> +im Moment <SPAN STYLE="font-style: normal">tabu (au&szlig;er die
> +Abarbeitung im Makefile erfolgt nach </SPAN><I>ctbot.c</I><SPAN STYLE="font-style: normal">,
> +was im Moment nicht der Fall ist). Sollten einmal eine neue Datei
> +hinzugef&uuml;gt werden, die durch &bdquo;managed make&ldquo; vor
> +</SPAN><I>ctbot.c</I> <SPAN STYLE="font-style: normal">landen und
> +eeprom Variablen enthalten, muss man wahrscheinlich dieses
> +Startvariablen in die neue Datei verlegen, vor deren EEPROM
> +Variablen.</SPAN></P>
> +<P STYLE="margin-bottom: 0cm; font-style: normal">Durch diesen Trick
> +kann die Speicheradresse der ersten EEPROM Variable auch ohne
> +Linkerscript ermittelt werden und auch verschiedene
> +Section-Alignments (im Moment bei MinGW und Linux unterschiedlich)
> +der Linker haben keine Auswirkung.</P>
> +<P STYLE="margin-bottom: 0cm; font-style: normal">Auch beim
> +Generieren eines neuen ct-bot.exe wird eine EEP mit den
> +Initialisierungen der EEPROM-Variablen im post-build angelegt. Diese
> +Datei kann die EEPROM-Simulation auch als Initialisierung f&uuml;r
> +ihr MCU-Kompatibles EEPROM benutzen oder diese Datei kann direkt als
> +EEPROM-Datei benutzt werden, wenn die Simulation im PC-Modus ist,
> +gleiches gilt nat&uuml;rlich umgekahr auch f&uuml;r die EEP Datei des
> +MCU Exe.</P>
> +<P STYLE="margin-bottom: 0cm"><BR>
> +</P>
> +<P STYLE="margin-bottom: 0cm"><B>Nutzung der EEPROM Simulation</B>.</P>
> +<P STYLE="margin-bottom: 0cm">Die EEPROM-Simulation unterscheidet
> +sich nur in ein paar Details von den realen Funktionen unter WinAVR
> +und ct-bot. Nat&uuml;rlich hat der PC kein EEPROM, dies wird durch
> +eine Datei im Binary Format emuliert. Der Dateinamen und der Pfad
> +wird &uuml;ber die Konstante EEPROM_FILENAME in <I>eeprom</I>-<I>emu</I>_<I>pc</I>.<I>c</I>
> +festgelegt. Ein weiterer Unterschied ist, das beim WinAVR &uuml;ber
> +ein DEFINE der Prozessortyp festgelegt wird, entweder ATMega32 oder
> +ATMega664. Dieses DEFINE wird normalerweise beim PC Compiler nicht
> +&uuml;bergeben. Standartm&auml;&szlig;ig wird von einem ATMega32 mit
> +1024 Byte EEPROM ausgegangen, der Simulator kennt aber die Konstante
> +f&uuml;r den ATMega664 und erh&ouml;ht den EEPROM Speicher auf 2048
> +Bytes. Sollte schon eine 1K Datei f&uuml;rs EEPROM bestehen, so muss
> +diese gel&ouml;scht werden, damit die Gr&ouml;&szlig;ere angelegt
> +wird. Wird direkt die erstellte <I>ct-bot.eep</I> Datei genutzt, ist
> +dies nat&uuml;rlich nicht notwendig.</P>
> +<P STYLE="margin-bottom: 0cm">Alle wichtigen Informationen werden
> +beim Start des ct-bot.exe im Log-Fenster angezeigt, dort sieht man
> +auch alle eventuellen Fehler und ob die Simulation ordnungsgem&auml;&szlig;
> +arbeiten kann. Es erfolgt kein beenden des <I>ct-bot.exe</I> bei
> +Problemen, ein Funktion des EEPROM ist dann aber nicht gegeben.</P>
> +<P STYLE="margin-bottom: 0cm">Generell unterscheidet die Simulation
> +zwei Modi:</P>
> +<OL>
> +	<LI><P STYLE="margin-bottom: 0cm">PC-Modus</P>
> +	<P STYLE="margin-bottom: 0cm">In diesen Modus entspricht die
> +	eeprom.bin nicht dem EEPROM des realen ct-bot und darf deshalb auch
> +	nicht auf ihn aufgespielt werden. Dieser Modus wird ohne jedes zu
> +	tun erreicht. Er ben&ouml;tigt keine weiteren Eintr&auml;ge in Post
> +	build. 
> +	</P>
> +	<P STYLE="margin-bottom: 0cm">Wenn eine ct-bot.eep erstellt im
> +	Binary Format, so kann diese direkt benutzt werden.</P>
> +	<LI><P STYLE="margin-bottom: 0cm">MCU-Modus</P>
> +	<P STYLE="margin-bottom: 0cm">Ist dieser Modus erreicht, kann man
> +	als EEPROM-Datei einen EEPROM Abzug vom ct-bot verwenden.
> +	Voraussetzung ist nat&uuml;rlich, das der Bot auch mit zuletzt
> +	erstellten Programm bespielt ist. Nat&uuml;lich kann man auch die
> +	EEPROM-Datei auf den Bot nutzen.<BR>Der MCU-Modus kann nur erreicht
> +	werden, wenn sowohl beim avr-ggc als auch unter der PC Oberfl&auml;che
> +	map-Datei erstellt werden, daf&uuml;r sind im Post Build die
> +	folgenden Befehle einzutragen:</P>
> +	<P STYLE="margin-bottom: 0cm">Debug-W32: <B>objcopy -j .eeprom
> +	--change-section-lma .eeprom=0 -O binary ct-Bot.exe
> +	ct-Bot.eep;objdump -t ct-bot.exe | grep &quot;(sec  5)&quot; | grep
> +	&quot;(nx 0)&quot; &gt; eeprom_pc.map</B></P>
> +	<P STYLE="margin-bottom: 0cm">Debug-MCU-W32: <B>avr-objcopy -O ihex
> +	-R .eeprom ct-Bot.elf ct-Bot.hex; avr-objcopy -j .eeprom
> +	--set-section-flags=.eeprom=&quot;alloc,load&quot;
> +	--change-section-lma .eeprom=0 -O binary ct-Bot.elf
> +	ct-Bot.eep;avr-objdump -t ct-bot.elf | grep &quot;O \.eeprom&quot; &gt;
> +	eeprom_mcu.map</B></P>
> +	<P STYLE="margin-bottom: 0cm"><B>(Achtung! Zwischen sec und 5 zwei
> +	Spaces)</B></P>
> +	<P STYLE="margin-bottom: 0cm">Diese Befehlssequence des PC gelten
> +	nat&uuml;rlich auch f&uuml;r MacOS oder Linux. 
> +	</P>
> +	<P STYLE="margin-bottom: 0cm">Anhand dieser MAP-Datei k&ouml;nnen
> +	die Routinen des EEPROM-Manager &uuml;ber eine
> +	Konvertierungsfunktion die eeprom-Datei bot-kompatible halten.
> +	Nat&uuml;rlich kann man trotzdem dieses EEPROM mit der EEP-Datei
> +	initialisieren.</P>
> +</OL>
> +<P STYLE="margin-bottom: 0cm"><BR>
> +</P>
> +<P STYLE="margin-bottom: 0cm">M&ouml;chte man die vorhandene oder
> +noch nicht vorhandene EEPROM-Datei mit den Daten aus der EEP-Datei
> +initialisieren, so muss man die ct-bot.exe mit dem Parameter <I>-i
> +</I>starten, dabein spielt es keine Rolle in welchen Modus die
> +Emulation arbeitet. Der Pfad der EEP-Datei wird in der Konstante
> +<FONT COLOR="#000000"><FONT FACE="Courier New, monospace"><FONT SIZE=2>EEP_PC
> +</FONT></FONT></FONT><FONT COLOR="#000000"><FONT FACE="Times New Roman, serif"><FONT SIZE=3>eingetragen.</FONT></FONT></FONT></P>
> +<P STYLE="margin-bottom: 0cm"><FONT COLOR="#000000"><FONT FACE="Times New Roman, serif"><FONT SIZE=3>F&uuml;r
> +das Debuggen von Zugriffen auf das EEPROM, stehen unter anderen die
> +DEFINES LOG_STORE und LOG_LOAD zur Verf&uuml;gung, die im MCU Modus
> +sogar den Variablennamen anzeigen. Andere Variationen sind auch noch
> +denkbar.</FONT></FONT></FONT></P>
> +<P STYLE="margin-bottom: 0cm"><BR>
> +</P>
> +<P STYLE="margin-bottom: 0cm; font-style: normal"><B>Grenzen der
> +Implementierung</B></P>
> +<P STYLE="margin-bottom: 0cm; font-style: normal; font-weight: medium">
> +Im Moment erstellen gleiche Compilerversionen (zu &Uuml;berpr&uuml;fen
> +mit &ndash;version) auch (fast) gleiche EEPROM-Sections. Damit es
> +auch mit verschiedenen Compiler Version geht (und ich mich auch nicht
> +auf die gleichen Versionen verlasssen will) habe ich die
> +Adresskonvertierung eingef&uuml;hrt, damit dies kein Problem mehr
> +ist.</P>
> +<P STYLE="margin-bottom: 0cm; font-style: normal; font-weight: medium">
> +Es gibt aber keine Garantien daf&uuml;r, das zuk&uuml;nftige Compiler
> +Versionen nicht die Reihenfolge der Variablen im Code &auml;ndern.
> +Ein Einf&uuml;gen neuer EEPROM Variablen kann auch zu Verschiebungen
> +der Adressen f&uuml;hren. Nach solchen &Auml;nderungen ist man nur
> +auf der sicheren Seite, wenn das EEPROM initialisiert wird (sprich
> +Sie Ihre alte eeprom.bin bzw. auf den Atmel das EEPROM l&ouml;schen).
> +Einmal erstellte Werte sind dann nat&uuml;rlich futsch. Wenn man den
> +Einfluss von Kodeerg&auml;nzungen kontrollieren will, kann man dies
> +vor und nach der &Auml;nderungen mit objdump machen (oder falls Sie
> +die Befehle f&uuml;r die MAP-Dateien im Post-Build benutzen, schauen
> +Sie in die MAP-Dateien), mit den richtigen Parametern kann man sich
> +die Adressverteilung anzeigen lassen. Sie k&ouml;nnen dann sehen, ob
> +die neuen Variablen nun hinten angeh&auml;ngt wurden (dann brauch das
> +eeprom nicht gel&ouml;scht werden) oder sie dazwischen gelandet sind
> +(dann sind die alten Daten unbrauchbar), daf&uuml;r sollten sie aber
> +vorher in eclipse Projekt-&gt;clean aufrufen.<BR>Die Implementierung
> +des EEPROM auf den PC kontrolliert nicht, ob nicht 1K bzw. 2K an
> +Daten &uuml;berschritten wird. Der EEPROM-Manager meckert dann aber
> +im LOG. (Der avg-gcc wird dann aber auch meckern). 
> +</P>
> +<P STYLE="margin-bottom: 0cm"><BR>
> +</P>
> +<P STYLE="margin-bottom: 0cm"><B>Funktionen</B></P>
> +<P STYLE="margin-bottom: 0cm"><B>Nur in eeprom-emu_pc.c sichtbare
> +Funktionen</B></P>
> +<P STYLE="margin-bottom: 0cm">store_parameter() - Speichern von
> +Informationen im simulierten EEPROM</P>
> +<P STYLE="margin-bottom: 0cm">load_parameter() - Laden von
> +Informationen aus dem simulierten EEPROM</P>
> +<P STYLE="margin-bottom: 0cm">init_eeprom() - Erstellt
> +Adresskonvertierungstabelle</P>
> +<P STYLE="margin-bottom: 0cm">conv_eeaddr() - Wandelt PC Adresse in
> +ct-bot Adresse</P>
> +<P STYLE="margin-bottom: 0cm">create_ctab() - Erstellt
> +Adresskonvertierungstabelle</P>
> +<P STYLE="margin-bottom: 0cm">check_eeprom_file() - Erstellt leeres
> +EEPROM, wenn n&ouml;tig und initialisiert es, wenn gew&uuml;nscht</P>
> +<P STYLE="margin-bottom: 0cm">init_eeprom_man() - Initialisiert die
> +EEPROM Emulation</P>
> +<P STYLE="margin-bottom: 0cm"><B>Zugriffsfunktionen f&uuml;r den PC
> +(Identisch zu denen von WinAVR)</B></P>
> +<P STYLE="margin-bottom: 0cm">eeprom_read_byte()</P>
> +<P STYLE="margin-bottom: 0cm">eeprom_write_byte()</P>
> +<P STYLE="margin-bottom: 0cm">eeprom_read_word()</P>
> +<P STYLE="margin-bottom: 0cm">eeprom_write_word()</P>
> +<P STYLE="margin-bottom: 0cm">eeprom_write_block()</P>
> +<P STYLE="margin-bottom: 0cm">eeprom_read_block()</P>
> +<P STYLE="margin-bottom: 0cm"><BR>
> +</P>
> +<P STYLE="margin-bottom: 0cm"><FONT SIZE=3><B>Dateien:</B></FONT></P>
> +<P STYLE="margin-bottom: 0cm"><FONT SIZE=3>eeprom-emu.h Include
> +Dateinamen mit Funktionsparameter</FONT></P>
> +<P STYLE="margin-bottom: 0cm"><FONT SIZE=3>eeprom-emu_pc.c Funktionen
> +fuer den ct-Sim</FONT></P>
> +<P STYLE="margin-bottom: 0cm"><BR>
> +</P>
> +<P STYLE="margin-bottom: 0cm"><BR>
> +</P>
> +<P STYLE="margin-bottom: 0cm"><BR>
> +</P>
> +</BODY>
> +</HTML>
> \ No newline at end of file
> Index: E:/eclipse/ct-bot test/ct-Bot/ct-Bot.c
> ===================================================================
> --- E:/eclipse/ct-bot test/ct-Bot/ct-Bot.c	(revision 1162)
> +++ E:/eclipse/ct-bot test/ct-Bot/ct-Bot.c	(working copy)
> @@ -39,6 +39,7 @@
>  	#include "bot-2-sim.h"
>  	#include "tcp.h"
>  	#include "tcp-server.h"
> +	#include "eeprom-emu.h"
>  	#include <pthread.h>
>  	#include <unistd.h>
>  	#include <stdlib.h>
> @@ -83,6 +84,12 @@
>  #include "gui.h"
>  #include "ui/available_screens.h"
>  
> +//Moeglichst frueh section erzwingen, damit sie VOR .eeprom liegt!!!
> +#ifdef PC
> +	uint8 __attribute__ ((section (".s1eeprom"))) _eeprom_start1__ = 0;
> +	uint8 __attribute__ ((section (".s2eeprom"))) _eeprom_start2__ = 0;
> +#endif
> +
>  /*!
>   * Der Mikrocontroller und der PC-Simulator brauchen ein paar Einstellungen, 
>   * bevor wir loslegen koennen.
> @@ -93,7 +100,7 @@
>  		PORTB=0; DDRB=0;
>  		PORTC=0; DDRC=0;
>  		PORTD=0; DDRD=0;
> -			
> +
>  		wdt_disable();	// Watchdog aus!
>  		timer_2_init();
>  		
> @@ -133,6 +140,7 @@
>  
>  	#ifdef PC
>  		bot_2_sim_init();
> +		init_eeprom_man();
>  	#endif
>  
>  	#ifdef DISPLAY_AVAILABLE
> @@ -237,6 +245,7 @@
>  		puts("\t-d \tLoescht eine Mini-Fat-Datei fuer den Sim (emulierte MMC).");		
>  		puts("\t   ID  \tDie ID aus ASCII-Zeichen");		
>  		puts("\t-l \tKonvertiert eine SpeedLog-Datei in eine txt-Datei");
> +		puts("\t-i \t Initialisiert das EEPROM mit den Daten der EEP-Datei"); 
>  		puts("\t-h\tZeigt diese Hilfe an");
>  		exit(1);
>  	}
> @@ -271,7 +280,6 @@
>  		int slog	=0;
>  		char *from = NULL;	/*!< Speichert den per -M uebergebenen Quellnamen zwischen */
>  
> -
>  		/* Die Kommandozeilenargumente komplett verarbeiten */
>  		while ((ch = getopt(argc, argv, "hsTt:M:c:l:e:d:")) != -1) {
>  			switch (ch) {
> @@ -348,6 +356,9 @@
>  					slog=1;					
>  				}				
>  				break;			
> +			case 'i':
> +				eeprom_init = 1;
> +				break;
>  			case 'h':
>  			default:
>  				/* -h oder falscher Parameter, Usage anzeigen */
> Index: E:/eclipse/ct-bot test/ct-Bot/ui/misc.c
> ===================================================================
> --- E:/eclipse/ct-bot test/ct-Bot/ui/misc.c	(revision 1162)
> +++ E:/eclipse/ct-bot test/ct-Bot/ui/misc.c	(working copy)
> @@ -32,11 +32,11 @@
>  #include "timer.h"
>  #ifdef MCU
>  	#include <avr/eeprom.h>
> +#else
> +	#include "eeprom-emu.h"
>  #endif
>  
> -#ifdef MCU
> -	uint8 __attribute__ ((section (".eeprom"))) resetsEEPROM = 0;	/*!< Reset-Counter-Wert im EEPROM */
> -#endif
> +uint8 EEPROM resetsEEPROM = 0;	/*!< Reset-Counter-Wert im EEPROM */
>  
>  #ifdef DISPLAY_AVAILABLE
>  	#ifdef MISC_DISPLAY_AVAILABLE
> Index: E:/eclipse/ct-bot test/ct-Bot/ct-Bot.h
> ===================================================================
> --- E:/eclipse/ct-bot test/ct-Bot/ct-Bot.h	(revision 1162)
> +++ E:/eclipse/ct-bot test/ct-Bot/ct-Bot.h	(working copy)
> @@ -31,7 +31,7 @@
>  /************************************************************
>  * Module switches, to make code smaller if features are not needed
>  ************************************************************/
> -//#define LOG_CTSIM_AVAILABLE		/*!< Logging zum ct-Sim (PC und MCU) */
> +#define LOG_CTSIM_AVAILABLE		/*!< Logging zum ct-Sim (PC und MCU) */
>  //#define LOG_DISPLAY_AVAILABLE		/*!< Logging ueber das LCD-Display (PC und MCU) */
>  //#define LOG_UART_AVAILABLE		/*!< Logging ueber UART (NUR fuer MCU) */
>  //#define LOG_STDOUT_AVAILABLE 		/*!< Logging auf die Konsole (NUR fuer PC) */
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> ct-bot-entwickler Mailingliste
> ct-bot-entwickler@xxxxxxxxxxxxxxxxx
> http://www.heise.de/bin/newsletter/listinfo/ct-bot-entwickler


-- 
Benjamin Benz
Heise Zeitschriften Verlag
Redaktion c't
eMail: bbe@xxxxxxxx
WWW  : http://www.heise.de

Heise Zeitschriften Verlag GmbH & Co. KG
Registergericht: Amtsgericht Hannover HRA 26709

Persönlich haftende Gesellschafterin:
Heise Zeitschriften Verlag Geschäftsführung GmbH
Registergericht: Amtsgericht Hannover, HRB 60405
Geschäftsführer: Ansgar Heise, Steven P. Steinkraus, Dr. Alfons Schräder




Copyright © 2007 Heise Zeitschriften Verlag Kritik, Anregungen bitte an c't-WWW Datenschutzhinweis   Impressum