heise online
  • c't
  • iX
  • Technology Review
  • Mac & i
  • mobil
  • Security
  • Netze
  • Open Source
  • Developer
  • c't-TV
  • Download
  • Telepolis
  • Resale
  • Foto
  • Autos
  • Preisvergleich
  • Stellenmarkt
  • Abo
  • weitere Angebote
    • Shop
    • Artikel-Archiv
    • Veranstaltungen
    • Whitepapers
    • heise-marktplatz
    • IT-Markt
    • Tarifrechner
    • Jobs bei Heise

c't Magazin
  • Startseite
  • Artikel
  • c't-Projekte
  • Hotline & FAQ
  • Treiber & mehr
  • Kolumnen
Software zu Projekten Allgemeine Hinweise
Archiv-Suche Newsletter RSS-FeedRSS

c't › c't-Projekte

Trac
  • Login
  • Help/Guide
  • About Trac
  • Preferences
  • Wiki
  • Timeline
  • Roadmap
  • Browse Source
  • View Tickets
  • Search

Context Navigation

  • Back to Patches

Patches: eeprom_emu_v1.patch

File eeprom_emu_v1.patch, 61.4 KB (added by bbe, 5 years ago)

Patch zur EEPROM Emulation

Line 
1Index: E:/eclipse/ct-bot test/ct-Bot/bot-logic/behaviour_calibrate_sharps.c
2===================================================================
3--- E:/eclipse/ct-bot test/ct-Bot/bot-logic/behaviour_calibrate_sharps.c        (revision 1162)
4+++ E:/eclipse/ct-bot test/ct-Bot/bot-logic/behaviour_calibrate_sharps.c        (working copy)
5@@ -1,314 +1,312 @@
6-/*
7- * c't-Bot
8- *
9- * This program is free software; you can redistribute it
10- * and/or modify it under the terms of the GNU General
11- * Public License as published by the Free Software
12- * Foundation; either version 2 of the License, or (at your
13- * option) any later version.
14- * This program is distributed in the hope that it will be
15- * useful, but WITHOUT ANY WARRANTY; without even the implied
16- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
17- * PURPOSE. See the GNU General Public License for more details.
18- * You should have received a copy of the GNU General Public
19- * License along with this program; if not, write to the Free
20- * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21- * MA 02111-1307, USA.
22- *
23- */
24-
25-/*!
26- * @file       behaviour_calibrate_sharps.c
27- * @brief      Kalibriert die Distanzsensoren des Bots
28- *
29- * Einige Zeilen sind auskommentiert. Sie waren dazu gedacht, die Kalibrierung zu automatisieren,
30- * das geht aber zurzeit (noch) nicht, weil die Positionsbestimmung fuer kleine Distanzen etwas
31- * zu ungenau ist (=> Encoderdatenauswertung checken!)
32- *
33- * @author     Timo Sandmann (mail@timosandmann.de)
34- * @date       21.04.2007
35- */
36-
37-#include "bot-logic/bot-logik.h"
38-
39-#ifdef BEHAVIOUR_CALIBRATE_SHARPS_AVAILABLE
40-#include <math.h>
41-#include <stdio.h>
42-#include <string.h>
43-
44-#include "sensor.h"
45-#include "display.h"
46-#include "gui.h"
47-#include "rc5-codes.h"
48-#include "log.h"
49-
50-#ifdef MCU
51-       #include <avr/eeprom.h>
52-#else
53-       /* derzeit kein EEPROM fuer PC vorhanden, Daten liegen einfach im RAM */
54-       #define eeprom_write_byte(ptr, x)       *ptr = x
55-       #define eeprom_write_block(pRam, pEeprom, n)    memcpy(pEeprom, pRam, n)        // eeprom_write_block ist andersrum!
56-#endif
57-
58-//static Behaviour_t* data = NULL;
59-//static float start_x = 0;
60-//static float start_head = 0;
61-static uint8_t last_toggle = 0;                        /*!< letztes Toggle-Bit der Distsensoren */
62-static uint8_t step = 0;                               /*!< Abstand zum naechsten Messpunkt [cm] */
63-static uint8_t count = 0;                              /*!< aktueller Messpunkt */
64-static int16_t distL = 0;                              /*!< Rohdaten des linken Sharps */
65-static int16_t distR = 0;                              /*!< Rohdaten des rechten Sharps */
66-static uint8_t distance = 0;                   /*!< Entfernung zum Hindernis [cm] */
67-static int8_t measure_count = 0;               /*!< Counter fuer Sharp-Messungen */
68-static uint8_t userinput_done = 0;             /*!< 1: User war schon fleissig, 0: warten */
69-
70-static distSens_t buffer[2][14];               /*!< Puffer des Kalibrierungsergebnisses im RAM */
71-static uint8_t volt_offset = 0;                        /*!< Offset des Spannungswertes */
72-
73-static void (* pNextJob)(void) = NULL; /*!< naechste Teilaufgabe */
74-static void (* pLastJob)(void) = NULL; /*!< letzte Teilaufgabe (vor Stopp) */
75-
76-static void goto_next_pos(void);               /*!< Stellt den Bot auf die naechste Position bzw. laesst den User das tun */
77-
78-static const uint8_t max_steps = 14;   /*!< Anzahl der Entfernungen, an denen gemessen wird */
79-
80-///*!
81-// * @brief    Hilfsfunktion fuer wait_for_stop()
82-// * @see              wait_for_stop()
83-// */
84-//static void wait_for_stop_helper(void) {
85-//     speedWishLeft = BOT_SPEED_STOP;
86-//     speedWishRight = BOT_SPEED_STOP;
87-//     
88-//     /* Nachlauf abwarten */
89-//     if (fabs(v_enc_left) < 1.0f && fabs(v_enc_right) < 1.0f) {
90-//             /* zurueck zum Aufrufer */
91-//             pNextJob = pLastJob;    // wurde zuvor von wait_for_stop() gerettet
92-//     }
93-//}
94-//
95-///*!
96-// * @brief    Haelt den Bot an und wartet den Nachlauf ab
97-// * anschliessend geht's mit dem Aufrufer weiter
98-// */
99-//static inline void wait_for_stop(void) {
100-//     pLastJob = pNextJob;
101-//     pNextJob = wait_for_stop_helper;
102-//}
103-
104-/*!
105- * @brief      Hilfsfunktion fuer wait_for_userinput()
106- * @see                wait_for_userinput()
107- */
108-static void wait_for_userinput_helper(void) {
109-       /* Einagbe abwarten */
110-       if (userinput_done) {
111-               userinput_done = 0;
112-               /* zurueck zum Aufrufer */
113-               pNextJob = pLastJob;    // wurde zuvor von wait_for_userinput() gerettet
114-       }
115-}
116-
117-/*!
118- * @brief      Haelt den Bot an und wartet eine Useraktion ab
119- * anschliessend geht's mit dem Aufrufer weiter
120- */
121-static inline void wait_for_userinput(void) {
122-       pLastJob = pNextJob;
123-       pNextJob = wait_for_userinput_helper;
124-} 
125-
126-/*!
127- * @brief                      Berechnet die aktuelle Entfernung eines Sensors zum Ausganspunkt / dem Hindernis       
128- * @param sensor       0: links, 1: rechts
129- */
130-static int16_t calc_distance(uint8_t sensor) {
131-//     float dHead = (start_head - heading) * 2.0f*M_PI/360.0f;
132-//     float dX = start_x - x_enc;
133-//     float s_m = dX / cos(dHead);
134-//     float dS = tan(dHead) * DISTSENSOR_POS_SW;
135-//     float result = sensor == 0 ? s_m - dS : s_m + dS;
136-//     return result;
137-       return distance * 10;   // cm in mm umrechnen
138-}
139-
140-/*!
141- * @brief      Schreibt Spannung und Entfernung in den RAM-Puffer
142- */
143-static void update_data(void) {
144-       int16_t dist = calc_distance(0);
145-//     LOG_INFO("%u: links: %d", count, dist);
146-       buffer[0][count].dist = dist/5;
147-       buffer[0][count].voltage = distL;
148-       dist = calc_distance(1);
149-//     LOG_INFO("%u: rechts: %d", count, dist);
150-       buffer[1][count].dist = dist/5;
151-       buffer[1][count].voltage = distR;
152-       
153-       if (count != max_steps-1)
154-               /* neue Entfernung */
155-               pNextJob = goto_next_pos;               
156-       else {
157-               /* fertig */
158-               count++;
159-               pNextJob = NULL;
160-       }
161-}
162-
163-/*!
164- * @brief      Misst die Entfernung mit den Sharps
165- */
166-static void measure_distance(void) {
167-       if (last_toggle != sensDistLToggle) {
168-               /* auf neue Messung pruefen */
169-               last_toggle = sensDistLToggle;
170-               measure_count++;
171-       }
172-       /* zweimal vier Messungen abwarten */
173-       if (measure_count == 4) {
174-               distL = (float)sensDistL / 8.0f - volt_offset;
175-               distR = (float)sensDistR / 8.0f - volt_offset;
176-       } else if (measure_count == 8) {
177-               distL += (float)sensDistL / 8.0f - volt_offset;
178-               distR += (float)sensDistR / 8.0f - volt_offset;
179-               distL >>= 1;
180-               distR >>= 1;   
181-               if (distL > 255 || distR > 255) {
182-                       /* Offset zu kleine => erhoehen und neu messen */
183-                       volt_offset += 5;
184-//                     LOG_INFO("Offset-Update auf %u", volt_offset);
185-               } else {
186-                       /* Messwerte ok */
187-                       last_toggle = 1;
188-                       pNextJob = update_data;
189-               }
190-               measure_count = 0;
191-       }
192-}
193-
194-/*!
195- * @brief      Stellt den Bot auf die naechste Position bzw. laesst den User das tun
196- */
197-static void goto_next_pos(void) {
198-       //bot_drive_distance(data, 0, -50, step);       // step cm zurueck
199-       distance += step;
200-       count++;
201-       pNextJob = measure_distance;
202-       wait_for_userinput();
203-}
204-
205-/*!
206- * @brief                      Ersetzt die Sensorauswertungsfunktion, damit wir hier die Rohdaten bekommen
207- * @param p_sens       Zeiger auf den (Ziel-)Sensorwert
208- * @param p_toggle     Zeiger auf die Toggle-Variable des Zielsensors
209- * @param ptr          Zeiger auf auf Sensorrohdaten im EEPROM fuer p_sens
210- * @param volt         Spannungs-Ist-Wert, zu dem die Distanz gesucht wird
211- */
212-void sensor_dist_direct(int16_t *const p_sens, uint8_t *const p_toggle, const distSens_t *ptr, int16_t volt) {
213-       *p_sens = volt;
214-       *p_toggle = ~*p_toggle;
215-}
216-
217-/*!
218- * @brief              Das eigentliche Verhalten
219- * @param data Zeiger auf den Verhaltensdatensatz des Aufrufers
220- * @see                        bot_calibrate_sharps()
221- * Die Funktionalitaet des Verhaltens ist aufgeteilt in:
222- * @see goto_next_pos(), @see measure_distance(), @see update_data()
223- */
224-void bot_calibrate_sharps_behaviour(Behaviour_t *data) {
225-       if (pNextJob) pNextJob();
226-       else {
227-               /* fertig! */
228-               display_clear();
229-               sensor_update_distance = sensor_dist_lookup;    // Sensorauswertung wieder aktivieren
230-               /* Puffer ins EEPROM schreiben */
231-               eeprom_write_byte((uint8_t*)&sensDistOffset, volt_offset);
232-               eeprom_write_block(buffer[0], (uint8_t*)sensDistDataL, max_steps*sizeof(distSens_t));
233-               eeprom_write_block(buffer[1], (uint8_t*)sensDistDataR, max_steps*sizeof(distSens_t));
234-               return_from_behaviour(data);
235-               /* Fuer sensor_correction.h formatierte Logausgabe, erleichtert das Speichern der Init-EEPROM- / Sim-Werte */
236-               LOG_INFO("SENSDIST_OFFSET %u", volt_offset);
237-               char tmp_s[14*7+1];     // 14 Zeichen pro Durchlauf + '\0'
238-               uint8_t i, j, k;
239-               LOG_INFO("SENSDIST_DATA_LEFT:");
240-               for (k=0; k<2; k++) {
241-                       for (j=0; j<2; j++) {
242-                               tmp_s[0] = '\0';
243-                               for (i=0; i<max_steps/2; i++) {
244-                                       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);               
245-                               }
246-                               if (j==1) tmp_s[strlen(tmp_s)-1] = '\0';        // kein Komma ausgeben, falls letzter Wert
247-                               LOG_INFO("%s \\", tmp_s);
248-                       }
249-                       if (k==0) LOG_INFO("SENSDIST_DATA_RIGHT:");
250-               }
251-       }
252-}
253-
254-/*!
255- * @brief                      Kalibriert die Distanzsensoren des ct-Bots
256- * @param caller       Zeiger auf den Verhaltensdatensatz des Aufrufers
257- */
258-void bot_calibrate_sharps(Behaviour_t *caller) {
259-       /* Inits */
260-//     data = caller;
261-//     start_head = heading;
262-//     start_x = x_enc + 100;
263-       last_toggle = 1;
264-       measure_count = -4;
265-       step = 5;
266-       distance = 10;
267-       volt_offset = 0;
268-       count = 0;
269-       userinput_done = 0;
270-       
271-       sensor_update_distance = sensor_dist_direct;    // Sensorauswertung deaktivieren
272-       
273-       uint8_t i;
274-       for (i=0; i<sizeof(screen_functions)/sizeof(screen_functions[0]); i++) {
275-               if (screen_functions[i] == bot_calibrate_sharps_display) break;
276-       }
277-       display_screen = i;
278-       display_clear();
279-       
280-       /* Als erstes Entfernung / Spannung messen */
281-       pNextJob = measure_distance;
282-       
283-       wait_for_userinput();
284-       
285-       /* Verhalten an */
286-       switch_to_behaviour(caller, bot_calibrate_sharps_behaviour, OVERRIDE);
287-}
288-
289-/*!
290- * @brief      Displayhandler fuer bot_calibrate_sharps-Verhalten
291- */
292-void bot_calibrate_sharps_display(void) {
293-       /* Displayausgabe */
294-       display_cursor(1,1);
295-       if (count != max_steps && pNextJob == wait_for_userinput_helper) {
296-               display_printf("Sharp-Kalibr. %2u/%2u", count+1 , max_steps);
297-               display_cursor(2,1);
298-               display_printf("Bot bitte auf %2u cm", distance);
299-               display_cursor(3,1);
300-               display_printf("stellen und mit");
301-               display_cursor(4,1);
302-               display_printf("\"Mute\" bestaetigen");
303-               
304-               /* Keyhandler */
305-               if (RC5_Code == RC5_CODE_MUTE) {
306-                       userinput_done = 1;
307-                       RC5_Code = 0;
308-               }
309-       } else if (pNextJob != NULL) {
310-               display_cursor(2,1);
311-               display_printf("thinking...         ");
312-       } else if (count == max_steps) {
313-               display_printf("fertig :-)");
314-       } else {
315-               display_printf("run calibrate_sharps");
316-       }
317-}
318-
319-#endif // BEHAVIOUR_CALIBRATE_SHARPS_AVAILABLE
320+/*
321+ * c't-Bot
322+ *
323+ * This program is free software; you can redistribute it
324+ * and/or modify it under the terms of the GNU General
325+ * Public License as published by the Free Software
326+ * Foundation; either version 2 of the License, or (at your
327+ * option) any later version.
328+ * This program is distributed in the hope that it will be
329+ * useful, but WITHOUT ANY WARRANTY; without even the implied
330+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
331+ * PURPOSE. See the GNU General Public License for more details.
332+ * You should have received a copy of the GNU General Public
333+ * License along with this program; if not, write to the Free
334+ * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
335+ * MA 02111-1307, USA.
336+ *
337+ */
338+
339+/*!
340+ * @file       behaviour_calibrate_sharps.c
341+ * @brief      Kalibriert die Distanzsensoren des Bots
342+ *
343+ * Einige Zeilen sind auskommentiert. Sie waren dazu gedacht, die Kalibrierung zu automatisieren,
344+ * das geht aber zurzeit (noch) nicht, weil die Positionsbestimmung fuer kleine Distanzen etwas
345+ * zu ungenau ist (=> Encoderdatenauswertung checken!)
346+ *
347+ * @author     Timo Sandmann (mail@timosandmann.de)
348+ * @date       21.04.2007
349+ */
350+
351+#include "bot-logic/bot-logik.h"
352+
353+#ifdef BEHAVIOUR_CALIBRATE_SHARPS_AVAILABLE
354+#include <math.h>
355+#include <stdio.h>
356+#include <string.h>
357+
358+#include "sensor.h"
359+#include "display.h"
360+#include "gui.h"
361+#include "rc5-codes.h"
362+#include "log.h"
363+
364+#ifdef MCU
365+       #include <avr/eeprom.h>
366+#else
367+       #include "eeprom-emu.h"
368+#endif
369+
370+//static Behaviour_t* data = NULL;
371+//static float start_x = 0;
372+//static float start_head = 0;
373+static uint8_t last_toggle = 0;                        /*!< letztes Toggle-Bit der Distsensoren */
374+static uint8_t step = 0;                               /*!< Abstand zum naechsten Messpunkt [cm] */
375+static uint8_t count = 0;                              /*!< aktueller Messpunkt */
376+static int16_t distL = 0;                              /*!< Rohdaten des linken Sharps */
377+static int16_t distR = 0;                              /*!< Rohdaten des rechten Sharps */
378+static uint8_t distance = 0;                   /*!< Entfernung zum Hindernis [cm] */
379+static int8_t measure_count = 0;               /*!< Counter fuer Sharp-Messungen */
380+static uint8_t userinput_done = 0;             /*!< 1: User war schon fleissig, 0: warten */
381+
382+static distSens_t buffer[2][14];               /*!< Puffer des Kalibrierungsergebnisses im RAM */
383+static uint8_t volt_offset = 0;                        /*!< Offset des Spannungswertes */
384+
385+static void (* pNextJob)(void) = NULL; /*!< naechste Teilaufgabe */
386+static void (* pLastJob)(void) = NULL; /*!< letzte Teilaufgabe (vor Stopp) */
387+
388+static void goto_next_pos(void);               /*!< Stellt den Bot auf die naechste Position bzw. laesst den User das tun */
389+
390+static const uint8_t max_steps = 14;   /*!< Anzahl der Entfernungen, an denen gemessen wird */
391+
392+///*!
393+// * @brief    Hilfsfunktion fuer wait_for_stop()
394+// * @see              wait_for_stop()
395+// */
396+//static void wait_for_stop_helper(void) {
397+//     speedWishLeft = BOT_SPEED_STOP;
398+//     speedWishRight = BOT_SPEED_STOP;
399+//     
400+//     /* Nachlauf abwarten */
401+//     if (fabs(v_enc_left) < 1.0f && fabs(v_enc_right) < 1.0f) {
402+//             /* zurueck zum Aufrufer */
403+//             pNextJob = pLastJob;    // wurde zuvor von wait_for_stop() gerettet
404+//     }
405+//}
406+//
407+///*!
408+// * @brief    Haelt den Bot an und wartet den Nachlauf ab
409+// * anschliessend geht's mit dem Aufrufer weiter
410+// */
411+//static inline void wait_for_stop(void) {
412+//     pLastJob = pNextJob;
413+//     pNextJob = wait_for_stop_helper;
414+//}
415+
416+/*!
417+ * @brief      Hilfsfunktion fuer wait_for_userinput()
418+ * @see                wait_for_userinput()
419+ */
420+static void wait_for_userinput_helper(void) {
421+       /* Einagbe abwarten */
422+       if (userinput_done) {
423+               userinput_done = 0;
424+               /* zurueck zum Aufrufer */
425+               pNextJob = pLastJob;    // wurde zuvor von wait_for_userinput() gerettet
426+       }
427+}
428+
429+/*!
430+ * @brief      Haelt den Bot an und wartet eine Useraktion ab
431+ * anschliessend geht's mit dem Aufrufer weiter
432+ */
433+static inline void wait_for_userinput(void) {
434+       pLastJob = pNextJob;
435+       pNextJob = wait_for_userinput_helper;
436+} 
437+
438+/*!
439+ * @brief                      Berechnet die aktuelle Entfernung eines Sensors zum Ausganspunkt / dem Hindernis       
440+ * @param sensor       0: links, 1: rechts
441+ */
442+static int16_t calc_distance(uint8_t sensor) {
443+//     float dHead = (start_head - heading) * 2.0f*M_PI/360.0f;
444+//     float dX = start_x - x_enc;
445+//     float s_m = dX / cos(dHead);
446+//     float dS = tan(dHead) * DISTSENSOR_POS_SW;
447+//     float result = sensor == 0 ? s_m - dS : s_m + dS;
448+//     return result;
449+       return distance * 10;   // cm in mm umrechnen
450+}
451+
452+/*!
453+ * @brief      Schreibt Spannung und Entfernung in den RAM-Puffer
454+ */
455+static void update_data(void) {
456+       int16_t dist = calc_distance(0);
457+//     LOG_INFO("%u: links: %d", count, dist);
458+       buffer[0][count].dist = dist/5;
459+       buffer[0][count].voltage = distL;
460+       dist = calc_distance(1);
461+//     LOG_INFO("%u: rechts: %d", count, dist);
462+       buffer[1][count].dist = dist/5;
463+       buffer[1][count].voltage = distR;
464+       
465+       if (count != max_steps-1)
466+               /* neue Entfernung */
467+               pNextJob = goto_next_pos;               
468+       else {
469+               /* fertig */
470+               count++;
471+               pNextJob = NULL;
472+       }
473+}
474+
475+/*!
476+ * @brief      Misst die Entfernung mit den Sharps
477+ */
478+static void measure_distance(void) {
479+       if (last_toggle != sensDistLToggle) {
480+               /* auf neue Messung pruefen */
481+               last_toggle = sensDistLToggle;
482+               measure_count++;
483+       }
484+       /* zweimal vier Messungen abwarten */
485+       if (measure_count == 4) {
486+               distL = (float)sensDistL / 8.0f - volt_offset;
487+               distR = (float)sensDistR / 8.0f - volt_offset;
488+       } else if (measure_count == 8) {
489+               distL += (float)sensDistL / 8.0f - volt_offset;
490+               distR += (float)sensDistR / 8.0f - volt_offset;
491+               distL >>= 1;
492+               distR >>= 1;   
493+               if (distL > 255 || distR > 255) {
494+                       /* Offset zu kleine => erhoehen und neu messen */
495+                       volt_offset += 5;
496+//                     LOG_INFO("Offset-Update auf %u", volt_offset);
497+               } else {
498+                       /* Messwerte ok */
499+                       last_toggle = 1;
500+                       pNextJob = update_data;
501+               }
502+               measure_count = 0;
503+       }
504+}
505+
506+/*!
507+ * @brief      Stellt den Bot auf die naechste Position bzw. laesst den User das tun
508+ */
509+static void goto_next_pos(void) {
510+       //bot_drive_distance(data, 0, -50, step);       // step cm zurueck
511+       distance += step;
512+       count++;
513+       pNextJob = measure_distance;
514+       wait_for_userinput();
515+}
516+
517+/*!
518+ * @brief                      Ersetzt die Sensorauswertungsfunktion, damit wir hier die Rohdaten bekommen
519+ * @param p_sens       Zeiger auf den (Ziel-)Sensorwert
520+ * @param p_toggle     Zeiger auf die Toggle-Variable des Zielsensors
521+ * @param ptr          Zeiger auf auf Sensorrohdaten im EEPROM fuer p_sens
522+ * @param volt         Spannungs-Ist-Wert, zu dem die Distanz gesucht wird
523+ */
524+void sensor_dist_direct(int16_t *const p_sens, uint8_t *const p_toggle, const distSens_t *ptr, int16_t volt) {
525+       *p_sens = volt;
526+       *p_toggle = ~*p_toggle;
527+}
528+
529+/*!
530+ * @brief              Das eigentliche Verhalten
531+ * @param data Zeiger auf den Verhaltensdatensatz des Aufrufers
532+ * @see                        bot_calibrate_sharps()
533+ * Die Funktionalitaet des Verhaltens ist aufgeteilt in:
534+ * @see goto_next_pos(), @see measure_distance(), @see update_data()
535+ */
536+void bot_calibrate_sharps_behaviour(Behaviour_t *data) {
537+       if (pNextJob) pNextJob();
538+       else {
539+               /* fertig! */
540+               display_clear();
541+               sensor_update_distance = sensor_dist_lookup;    // Sensorauswertung wieder aktivieren
542+               /* Puffer ins EEPROM schreiben */
543+               eeprom_write_byte((uint8_t*)&sensDistOffset, volt_offset);
544+               eeprom_write_block(buffer[0], (uint8_t*)sensDistDataL, max_steps*sizeof(distSens_t));
545+               eeprom_write_block(buffer[1], (uint8_t*)sensDistDataR, max_steps*sizeof(distSens_t));
546+               return_from_behaviour(data);
547+               /* Fuer sensor_correction.h formatierte Logausgabe, erleichtert das Speichern der Init-EEPROM- / Sim-Werte */
548+               LOG_INFO("SENSDIST_OFFSET %u", volt_offset);
549+               char tmp_s[14*7+1];     // 14 Zeichen pro Durchlauf + '\0'
550+               uint8_t i, j, k;
551+               LOG_INFO("SENSDIST_DATA_LEFT:");
552+               for (k=0; k<2; k++) {
553+                       for (j=0; j<2; j++) {
554+                               tmp_s[0] = '\0';
555+                               for (i=0; i<max_steps/2; i++) {
556+                                       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);               
557+                               }
558+                               if (j==1) tmp_s[strlen(tmp_s)-1] = '\0';        // kein Komma ausgeben, falls letzter Wert
559+                               LOG_INFO("%s \\", tmp_s);
560+                       }
561+                       if (k==0) LOG_INFO("SENSDIST_DATA_RIGHT:");
562+               }
563+       }
564+}
565+
566+/*!
567+ * @brief                      Kalibriert die Distanzsensoren des ct-Bots
568+ * @param caller       Zeiger auf den Verhaltensdatensatz des Aufrufers
569+ */
570+void bot_calibrate_sharps(Behaviour_t *caller) {
571+       /* Inits */
572+//     data = caller;
573+//     start_head = heading;
574+//     start_x = x_enc + 100;
575+       last_toggle = 1;
576+       measure_count = -4;
577+       step = 5;
578+       distance = 10;
579+       volt_offset = 0;
580+       count = 0;
581+       userinput_done = 0;
582+       
583+       sensor_update_distance = sensor_dist_direct;    // Sensorauswertung deaktivieren
584+       
585+       uint8_t i;
586+       for (i=0; i<sizeof(screen_functions)/sizeof(screen_functions[0]); i++) {
587+               if (screen_functions[i] == bot_calibrate_sharps_display) break;
588+       }
589+       display_screen = i;
590+       display_clear();
591+       
592+       /* Als erstes Entfernung / Spannung messen */
593+       pNextJob = measure_distance;
594+       
595+       wait_for_userinput();
596+       
597+       /* Verhalten an */
598+       switch_to_behaviour(caller, bot_calibrate_sharps_behaviour, OVERRIDE);
599+}
600+
601+/*!
602+ * @brief      Displayhandler fuer bot_calibrate_sharps-Verhalten
603+ */
604+void bot_calibrate_sharps_display(void) {
605+       /* Displayausgabe */
606+       display_cursor(1,1);
607+       if (count != max_steps && pNextJob == wait_for_userinput_helper) {
608+               display_printf("Sharp-Kalibr. %2u/%2u", count+1 , max_steps);
609+               display_cursor(2,1);
610+               display_printf("Bot bitte auf %2u cm", distance);
611+               display_cursor(3,1);
612+               display_printf("stellen und mit");
613+               display_cursor(4,1);
614+               display_printf("\"Mute\" bestaetigen");
615+               
616+               /* Keyhandler */
617+               if (RC5_Code == RC5_CODE_MUTE) {
618+                       userinput_done = 1;
619+                       RC5_Code = 0;
620+               }
621+       } else if (pNextJob != NULL) {
622+               display_cursor(2,1);
623+               display_printf("thinking...         ");
624+       } else if (count == max_steps) {
625+               display_printf("fertig :-)");
626+       } else {
627+               display_printf("run calibrate_sharps");
628+       }
629+}
630+
631+#endif // BEHAVIOUR_CALIBRATE_SHARPS_AVAILABLE
632Index: E:/eclipse/ct-bot test/ct-Bot/bot-logic/behaviour_turn.c
633===================================================================
634--- E:/eclipse/ct-bot test/ct-Bot/bot-logic/behaviour_turn.c    (revision 1162)
635+++ E:/eclipse/ct-bot test/ct-Bot/bot-logic/behaviour_turn.c    (working copy)
636@@ -33,16 +33,14 @@
637        #include <avr/eeprom.h>
638        #define ANGLE_CORRECT   1                                               /*!< Drehfehler-Init */
639 #else
640-       /* derzeit kein EEPROM fuer PC vorhanden, Daten liegen einfach im RAM */
641-       #define eeprom_read_byte(x)                     *x                      /*!< Pseudo-EEPROM-Funktion fuer PC */
642-       #define eeprom_write_byte(ptr, x)       *ptr = x        /*!< Pseudo-EEPROM-Funktion fuer PC */
643+       #include "eeprom-emu.h"
644        #define ANGLE_CORRECT   0                                               /*!< Drehfehler-Init */
645 #endif // MCU
646 
647 /* EEPROM-Variablen immer deklarieren, damit die Adressen sich nicht veraendern je nach #define */
648-uint8 EE_SECTION err15=ANGLE_CORRECT   *1;                     /*!< Fehler bei Drehungen unter 15 Grad */
649-uint8 EE_SECTION err45=ANGLE_CORRECT   *2;                     /*!< Fehler bei Drehungen zwischen 15 und 45 Grad */
650-uint8 EE_SECTION err_big=ANGLE_CORRECT *4;                     /*!< Fehler bei groesseren Drehungen */
651+uint8 EEPROM err15=ANGLE_CORRECT       *1;                     /*!< Fehler bei Drehungen unter 15 Grad */
652+uint8 EEPROM err45=ANGLE_CORRECT       *2;                     /*!< Fehler bei Drehungen zwischen 15 und 45 Grad */
653+uint8 EEPROM err_big=ANGLE_CORRECT     *4;                     /*!< Fehler bei groesseren Drehungen */
654 
655 
656 #ifdef BEHAVIOUR_TURN_AVAILABLE
657Index: E:/eclipse/ct-bot test/ct-Bot/motor.c
658===================================================================
659--- E:/eclipse/ct-bot test/ct-Bot/motor.c       (revision 1162)
660+++ E:/eclipse/ct-bot test/ct-Bot/motor.c       (working copy)
661@@ -46,6 +46,9 @@
662 #ifdef MCU
663        #include <avr/eeprom.h>
664 #endif
665+#ifdef PC
666+       #include "eeprom-emu.h"
667+#endif
668 
669 int16 speed_l = 0;     /*!< Sollgeschwindigkeit linker Motor */
670 int16 speed_r = 0;     /*!< Sollgeschwindigkeit rechter Motor */
671@@ -86,11 +89,9 @@
672 //     static volatile uint8 acc_test[2];                      /*!< nur Testcase */
673 //     static volatile uint16 acc_test_dt[2];          /*!< nur Testcase */
674 #endif // SPEED_CONTROL_AVAILABLE
675-#ifdef MCU
676-       /* EEPROM-Variable immer deklarieren, damit die Adresse sich nicht veraendert je nach #define */
677-       /*! EEPROM-Kopie von pwm_values */
678-       uint8_t __attribute__ ((section (".eeprom"),aligned (1))) pwmSlow[4] = {255, 255, 255, 255};
679-#endif
680+
681+/* EEPROM-Variable immer deklarieren, damit die Adresse sich nicht veraendert je nach #define */
682+uint8_t EEPROM pwmSlow[4] = {255, 255, 255, 255};      /*!< EEPROM-Kopie von pwm_values */
683       
684 direction_t direction;         /*!< Drehrichtung der Motoren */
685 
686Index: E:/eclipse/ct-bot test/ct-Bot/include/eeprom-emu.h
687===================================================================
688--- E:/eclipse/ct-bot test/ct-Bot/include/eeprom-emu.h  (revision 0)
689+++ E:/eclipse/ct-bot test/ct-Bot/include/eeprom-emu.h  (revision 0)
690@@ -0,0 +1,67 @@
691+/*
692+ * c't-Bot
693+ *
694+ * This program is free software; you can redistribute it
695+ * and/or modify it under the terms of the GNU General
696+ * Public License as published by the Free Software
697+ * Foundation; either version 2 of the License, or (at your
698+ * option) any later version.
699+ * This program is distributed in the hope that it will be
700+ * useful, but WITHOUT ANY WARRANTY; without even the implied
701+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
702+ * PURPOSE. See the GNU General Public License for more details.
703+ * You should have received a copy of the GNU General Public
704+ * License along with this program; if not, write to the Free
705+ * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
706+ * MA 02111-1307, USA.
707+ *
708+ */
709+
710+/* @file       eeprom-emu.h 
711+ * @brief      Low-Level Routinen fuer den Zugriff auf das EEPROM des c't-Bots
712+ * @author     Achim Pankalla (achim.pankalla@gmx.de)
713+ * @date       01.03.07
714+*/
715+#ifndef eeprom_emu_H_
716+#define eeprom_emu_H_
717+
718+#ifdef PC
719+#include <stddef.h>
720+
721+/*!
722+ * Flagge die bei Wahr die EEPROM Datei mit den Werten der EEP Datei initialisiert.
723+ */
724+extern uint8 eeprom_init;
725+
726+/*!
727+ * Initialisiert den EEPROM-Manager fuer den Simulierten Bot. Danach steht dem PC-Bot
728+ * auch ein EEPROM zur Verfuegung.
729+ */
730+extern void init_eeprom_man(void);
731+
732+/*!
733+ * Speichern Daten im EEPROM.
734+ * @param address Adresse im EEPROM zwischen 0 und 1023.
735+ * @param data Variable mit den abzulegenen Daten.
736+ */
737+extern void eeprom_write_byte(uint8  *adr, uint8 value);
738+extern void eeprom_write_word(uint16 *adr, uint16 value);
739+
740+/*!
741+ * Laden Daten aus dem EEPROM.
742+ * @param address Adresse im EEPROM zwischen 0 und 1023.
743+ * @return Wert der Speicheraddresse im EEPROM
744+ */
745+extern uint8  eeprom_read_byte(uint8  *adr);
746+extern uint16 eeprom_read_word(uint16 *adr);
747+
748+/*!
749+ * Kopiert ein Block aus den EEPROM oder in das EEPROM
750+ * @param address Adresse im Speicher.
751+ * @param address Adresse im EEPROM.
752+ */
753+extern void eeprom_read_block(void *pointer_ram, const void *pointer_eeprom, size_t size);
754+extern void eeprom_write_block(const void *pointer_ram, void *pointer_eeprom, size_t size);
755+
756+#endif
757+#endif
758Index: E:/eclipse/ct-bot test/ct-Bot/include/global.h
759===================================================================
760--- E:/eclipse/ct-bot test/ct-Bot/include/global.h      (revision 1162)
761+++ E:/eclipse/ct-bot test/ct-Bot/include/global.h      (working copy)
762@@ -60,11 +60,12 @@
763        #define On                    1         /*!< An */
764        #define Off                   0         /*!< Aus */
765 
766+       #ifdef PC                                                       /*!< Unterscheidung der EEPROM definition */
767+               #define EEPROM __attribute__ ((section (".eeprom"),aligned(1)))
768+       #endif
769        #ifdef MCU
770-               #define EE_SECTION      __attribute__ ((section (".eeprom"),aligned (1)))       /*!< Shortcut fuer EEPROM-Section */
771-       #else
772-               #define EE_SECTION                                                                                                              /*!< Shortcut fuer EEPROM-Section */
773-       #endif  // MCU
774+               #define EEPROM __attribute__ ((section (".eeprom")))
775+       #endif
776 
777        #define binary(var,bit) ((var >> bit)&1)        /*!< gibt das Bit "bit" von "var" zurueck */
778       
779Index: E:/eclipse/ct-bot test/ct-Bot/include/gui.h
780===================================================================
781--- E:/eclipse/ct-bot test/ct-Bot/include/gui.h (revision 1162)
782+++ E:/eclipse/ct-bot test/ct-Bot/include/gui.h (working copy)
783@@ -31,9 +31,7 @@
784 
785 extern int8 max_screens;       /*!< Anzahl der zurzeit registrierten Screens */
786 extern void (* screen_functions[DISPLAY_SCREENS])(void);       /*!< hier liegen die Zeiger auf die Display-Funktionen */
787-#ifdef MCU
788-       extern uint8 __attribute__ ((section (".eeprom"))) resetsEEPROM;        /*!< Reset-Counter-Wert im EEPROM */
789-#endif
790+extern uint8 EEPROM resetsEEPROM;      /*!< Reset-Counter-Wert im EEPROM */
791 
792 /*!
793  * @brief                      Display-Screen Anzeige
794Index: E:/eclipse/ct-bot test/ct-Bot/mcu/mini-fat.c
795===================================================================
796--- E:/eclipse/ct-bot test/ct-Bot/mcu/mini-fat.c        (revision 1162)
797+++ E:/eclipse/ct-bot test/ct-Bot/mcu/mini-fat.c        (working copy)
798@@ -31,7 +31,7 @@
799 #ifdef MCU
800 #include "avr/eeprom.h"
801 /* EEPROM-Variable immer deklarieren, damit die Adresse sich nicht veraendert je nach #define */
802-uint32 __attribute__ ((section (".eeprom"))) eefat[10] = {0};  /*!< EEPROM-Cache fuer FAT-Eintraege */
803+uint32 EEPROM eefat[10] = {0}; /*!< EEPROM-Cache fuer FAT-Eintraege */
804 
805 #ifdef MMC_AVAILABLE   
806 
807Index: E:/eclipse/ct-bot test/ct-Bot/sensor.c
808===================================================================
809--- E:/eclipse/ct-bot test/ct-Bot/sensor.c      (revision 1162)
810+++ E:/eclipse/ct-bot test/ct-Bot/sensor.c      (working copy)
811@@ -41,9 +41,8 @@
812 #ifdef MCU
813        #include <avr/eeprom.h>
814 #else
815-       /* derzeit kein EEPROM fuer PC vorhanden, Daten liegen einfach im RAM */
816-       #define eeprom_read_byte(x)     *x                                                                                      /*!< Pseudo-EEPROM-Funktion fuer PC */
817-#endif // MCU
818+       #include "eeprom-emu.h"
819+#endif
820 
821 // Defines einiger, haeufiger benoetigter Konstanten
822 #define DEG2RAD (2*M_PI/360)   /*!< Umrechnung von Grad nach Bogenmass */
823@@ -59,9 +58,9 @@
824 /*! Zeiger auf die Auswertungsfunktion fuer die Distanzsensordaten, const. solange sie nicht kalibriert werden */
825 void (* sensor_update_distance)(int16* const p_sens, uint8* const p_toggle, const distSens_t* ptr, int16 volt) = sensor_dist_lookup;
826 
827-distSens_t EE_SECTION sensDistDataL[] = SENSDIST_DATA_LEFT;            /*!< kalibrierte Referenzdaten fuer linken IR-Sensor */
828-distSens_t EE_SECTION sensDistDataR[] = SENSDIST_DATA_RIGHT;   /*!< kalibrierte Referenzdaten fuer rechten IR-Sensor */
829-uint8_t EE_SECTION sensDistOffset = SENSDIST_OFFSET;                   /*!< Spannungs-Offset IR-Sensoren */
830+distSens_t EEPROM sensDistDataL[] = SENSDIST_DATA_LEFT;                /*!< kalibrierte Referenzdaten fuer linken IR-Sensor */
831+distSens_t EEPROM sensDistDataR[] = SENSDIST_DATA_RIGHT;       /*!< kalibrierte Referenzdaten fuer rechten IR-Sensor */
832+uint8_t EEPROM sensDistOffset = SENSDIST_OFFSET;                       /*!< Spannungs-Offset IR-Sensoren */
833 
834 int16 sensBorderL=0;   /*!< Abgrundsensor links */
835 int16 sensBorderR=0;   /*!< Abgrundsensor rechts */
836@@ -163,7 +162,7 @@
837        else  volt = (volt_16 >> 3) - offset;
838       
839        /* Spannung in LT-Table suchen */
840-       uint8 pivot = eeprom_read_byte(&ptr[n-1].voltage);      // in welcher Region muessen wir suchen?
841+       uint8 pivot = eeprom_read_byte((uint8*)&ptr[n-1].voltage);      // in welcher Region muessen wir suchen?
842        if (volt > pivot) {
843                /* in unterer Haelfte suchen */
844                i = 0;
845@@ -175,7 +174,7 @@
846        }
847        uint8_t tmp=0;
848        for (; i<n; i++) {
849-               tmp = eeprom_read_byte(&ptr->voltage);
850+               tmp = eeprom_read_byte((uint8*)&ptr->voltage);
851                if (volt > tmp) // aufsteigend suchen, damit der kritische Fall (kleine Entfernung) schneller gefunden wird
852                        break;  // ptr zeigt jetzt auf die naechst kleinere Spannung
853                ptr++;
854@@ -187,7 +186,7 @@
855        }
856       
857        /* Entfernung berechnen und speichern */
858-       uint8 distance = lin_interpolate(eeprom_read_byte(&(ptr-1)->voltage), eeprom_read_byte(&(ptr-1)->dist), tmp, eeprom_read_byte(&ptr->dist), volt);
859+       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);
860        *p_sens = distance >= SENS_IR_MAX_DIST/5 ? SENS_IR_INFINITE : distance * 5;     // Distanz ist gefuenftelt in den Ref.-Daten;
861       
862        /* Sensorupdate-Info toggeln */
863Index: E:/eclipse/ct-bot test/ct-Bot/pc/mini-fat.c
864===================================================================
865--- E:/eclipse/ct-bot test/ct-Bot/pc/mini-fat.c (revision 1162)
866+++ E:/eclipse/ct-bot test/ct-Bot/pc/mini-fat.c (working copy)
867@@ -36,6 +36,9 @@
868 #include "mmc-vm.h"
869 #include "mmc-emu.h"
870 
871+/* EEPROM-Variable immer deklarieren, damit die Adresse sich nicht veraendert je nach #define */
872+uint32 EEPROM eefat[10] = {0}; /*!< EEPROM-Cache fuer FAT-Eintraege */
873+
874 /*!
875  * Erzeugt eine Datei, die an den ersten Bytes die ID enthaelt. Dann folgen 512 - sizeof(id) nullen
876  * Danach kommen so viele size kByte Nullen
877Index: E:/eclipse/ct-bot test/ct-Bot/pc/eeprom-emu_pc.c
878===================================================================
879--- E:/eclipse/ct-bot test/ct-Bot/pc/eeprom-emu_pc.c    (revision 0)
880+++ E:/eclipse/ct-bot test/ct-Bot/pc/eeprom-emu_pc.c    (revision 0)
881@@ -0,0 +1,455 @@
882+/*
883+ * c't-Bot
884+ *
885+ * This program is free software; you can redistribute it
886+ * and/or modify it under the terms of the GNU General
887+ * Public License as published by the Free Software
888+ * Foundation; either version 2 of the License, or (at your
889+ * option) any later version.
890+ * This program is distributed in the hope that it will be
891+ * useful, but WITHOUT ANY WARRANTY; without even the implied
892+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
893+ * PURPOSE. See the GNU General Public License for more details.
894+ * You should have received a copy of the GNU General Public
895+ * License along with this program; if not, write to the Free
896+ * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
897+ * MA 02111-1307, USA.
898+ *
899+ */
900+
901+/* @file       eeprom-emu_pc.c 
902+ * @brief      Low-Level Routinen fuer den Zugriff auf das emulierte EEPROM des Sim-c't-Bots
903+ * @author     Achim Pankalla (achim.pankalla@gmx.de)
904+ * @date       07.06.2007
905+*/
906+
907+#include "ct-Bot.h"
908+
909+#ifdef PC
910+
911+#include <stdio.h>
912+#include <string.h>
913+
914+#include "log.h"
915+
916+extern uint8 EEPROM resetsEEPROM;      /*!< Reset-Counter-Wert im EEPROM als Sectionreferenz*/
917+extern uint8 __attribute__ ((section (".s1eeprom"))) __attribute__((aligned(1))) _eeprom_start1__;
918+extern uint8 __attribute__ ((section (".s2eeprom"))) __attribute__((aligned(1))) _eeprom_start2__;
919+
920+/*! Normiert PC EEPROM Adressen*/
921+#define EEPROM_ADDR(x) ((uint32)x - (uint32)&_eeprom_start2__ - ((uint32)&_eeprom_start2__ - (uint32)&_eeprom_start1__))
922+/*! Defines zum Mitloggen von EEPROM Zugriffen*/
923+#define LOG_LOAD       if(addrconv) {LOG_DEBUG("LOAD: %s : %d", ctab[lastctabi].varname, (uint16)dataline[0] + (uint16)dataline[1]*256);}\
924+                                       else {LOG_DEBUG("load-addr=0x%x/%d", address,(uint16)dataline[0] + (uint16)dataline[1]*256);}
925+#define LOG_STORE      if(addrconv) {LOG_DEBUG("STORE: %s : %d", ctab[lastctabi].varname, data);}\
926+                                       else {LOG_DEBUG("load-addr=0x%x/%d", address, data);}
927+                                                                       
928+#ifdef __AVR_ATmega644__  /*! Dieser Prozessor hat 2048Bytes EEPROM*/
929+       #define EE_SIZE 2048
930+#else
931+       #define EE_SIZE 1024
932+#endif
933+
934+#define EEPROM_FILENAME        "./eeprom.bin"          /*<! Name und Pfad der EEPROM Datei. Verzeichnis muss existieren. Backslash doppeln!*/
935+#define MAX_VAR 200                                            /*<! Maximale Anszahl von Variablen*/
936+#define EEMAP_MCU "../debug-mcu-w32/eeprom_mcu.map"  /*<! Pfade fuer MAP / EEP Dateien */
937+#define EEMAP_PC  "./eeprom_pc.map"
938+#define EEP_PC    "./ct-bot.eep"
939+
940+typedef struct addrtab {                                       /*<! Spezieller Datentype fuer Adresskonvertierung*/
941+       char varname[20];
942+       uint32 simaddr;
943+       uint32 botaddr;
944+       uint32 size;
945+       uint32 access;
946+       } AddrCTab;
947+
948+static AddrCTab ctab[MAX_VAR];                                 /*<! Adresskonvertierungstabelle */
949+static uint16 tsize=0;                                                 /*<! Anzahl Eintraege in der Tabelle */
950+static uint8 addrconv = 0;                  /*<! Adresskonvertierung ein-/ausschalten*/
951+static uint16 lastctabi = 0;                /*<! Letzter Zugriffsindex auf ctab*/
952+uint8 eeprom_init = 0;                                         /*<! Flagge fuer EEPROM Initialsierung*/
953+
954+/*!
955+ * Diese Funktion konvertiert die Adressen der EEPROM Variablen des PC so,
956+ * das sie den Adressen im realen ct-bot entsprechen. Dafuer wird mit der Funktion
957+ * create_ctab ein Adresstabelle angelegt, diese nutzt diese Funktion.
958+ * @param address Adresse im EEPROM zwischen 0 und EE_SIZE-1.
959+ * @return Die neue Adresse fÌr den realen Bot.
960+ */
961+static uint32 conv_eeaddr(uint32 addr){
962+       int8 i;
963+       int32 adiff;
964+
965+       if(!addrconv) //Keine Adresskonvertierung
966+               return(addr);
967+       for(i=0; i<tsize; i++){
968+               adiff = addr - ctab[i].simaddr;
969+               if(adiff < 0)
970+                       return(0xffffffff);
971+               if(adiff < ctab[i].size){
972+                       lastctabi = i; //Letzer guelten Index merken
973+                       return(ctab[i].botaddr + adiff);
974+               }
975+       }
976+       return(0xffffffff);
977+}
978+
979+/*!
980+ * Diese Funktion uberprueft das vorhanden sein der eeprom.bin und initialisiert sie
981+ * gegebenenfalls mit der Initwerten der eep Datei.
982+ * Es wird dabei die Adresskovertierung benutzt, wenn die EEPROM Simulation im MCU-Modus
983+ * ist.
984+ * -----
985+ *  0 = EEPROM Datei OK
986+ *  1 = Fehler aufgetreten
987+ * -----
988+ * @param initfile EEP Datei des PC Kodes.
989+ * @return Status der Funktion
990+ */
991+static uint16 check_eeprom_file(char *initfile){
992+       FILE *fpr, *fpw; //Filepointer fuer Dateizugriffe
993+       uint16 i; //Laufvariable
994+       char data[2]; //Datenspeicher
995+       
996+       /*eeprom file vorhanden*/
997+       if(!(fpw = fopen(EEPROM_FILENAME, "r+b"))){ //Testen, ob Datei vorhanden ist.
998+               int16 i; //Laufvariable
999+               
1000+               if(!(fpw = fopen(EEPROM_FILENAME, "w+b"))){ //wenn nicht, dann erstellen
1001+                       LOG_INFO("->Kann EEPROM-Datei nicht erstellen");
1002+                       return(1);
1003+               }
1004+               for(i = 0; i < EE_SIZE; i++) //Leeres EEPROM erstellen
1005+                       fwrite("\377", 1, 1, fpw);
1006+               fclose(fpw);
1007+               LOG_INFO("->Leere EEPROM-Datei erstellt");
1008+       }
1009+       
1010+       /*Initialsieren der eeprom.bin, wenn gewuenscht*/
1011+       if(eeprom_init){
1012+               if(!(fpr = fopen(initfile, "rb"))){ //Datei oeffnen
1013+                       LOG_INFO("->EEP nicht gefunden");
1014+                       return(1);
1015+               }
1016+               if(!(fpw = fopen(EEPROM_FILENAME, "rb+"))){ //Datei oeffnen
1017+                       LOG_INFO("->EEPROM-Datei kann nicht beschrieben werden");
1018+                       return(1);
1019+               }
1020+               
1021+               /*EEP-Datei in EEPROM-Datei kopieren*/
1022+               for(i=0; i<EE_SIZE; i++){
1023+                       /*Daten kopieren*/
1024+                       if(!fread(data, 1, 1, fpr))
1025+                               break;
1026+                       if(addrconv){ //EEPROM-Datei im MCU-Modus
1027+                               uint32 naddr;//Konvertierte Adresse
1028+                               
1029+                               naddr = conv_eeaddr((uint32)i);
1030+                               if(naddr != 0xffffffff){
1031+                                       fseek(fpw, (int32)naddr, SEEK_SET);
1032+                               }
1033+                               else{
1034+                                       continue; //Nichts schreiben Adresse nicht belegt
1035+                               }
1036+                       }
1037+                       fwrite(data, 1, 1, fpw);
1038+               }
1039+               fclose(fpr);
1040+               fclose(fpw);
1041+               LOG_INFO("->EEPROM-Datei mit Daten init.");
1042+       }
1043+       return(0);
1044+}
1045+
1046+/*!
1047+ * Diese Funktion erstellt aus den beiden im Post erstellten MAP Dateien eine Tabelle
1048+ * zum umrechnen der PC-Adressen in die des Winavr Compiler. Dadurch kann die EEPROM
1049+ * Datei in einen zum EEPROM des Bot kompatiblen Format gehalten werden.
1050+ * Wichtige Informationen werden Ìber LOG_INFO angezeigt.
1051+ * ----
1052+ * Ergebniskodes der Funktion
1053+ * 0 = Fehlerfrei
1054+ * 1 = Sim Mapfile nicht vorhanden
1055+ * 2 = Bot Mapfile nicht vorhanden
1056+ * 3 = Unterschiedlicher Variablenbestand
1057+ * 4 = Zuviele Variablen
1058+ * 5 = EEPROM voll
1059+ * 6 = Unterschiedliche Variablenanzahl
1060+ *
1061+ * @param simfile MAP mit den Adressen der EEPROM-Variablen in der PC EXE.
1062+ * @param botfile MAP mit den Adressen der EEPROM-Variablen im MCU EXE.
1063+ * @return Statuskodes.
1064+ */
1065+static uint16 create_ctab(char *simfile, char *botfile){
1066+       FILE *fps, *fpb;
1067+       char sline[250], bline[250]; //Textzeilen aus Dateien
1068+       char d[30], d1[30], d2[30], vname_s[30], vname_b[20]; //Dummy und Variablennamen
1069+       int32 addr_s, addr_b; //Adressen der Variablen
1070+       char saddr[30], ssize[30]; //Stringvarianten fuer die Bot Daten
1071+       uint32 size; //Variablengroesse
1072+       int16 i, ii; //Laufvariablen
1073+       uint16 vc = 0; //Variablenzaehler
1074+
1075+       /*Dateien oeffnen*/
1076+       if(!(fps=fopen(simfile,"r"))){
1077+               LOG_INFO("->EEPROM-MAP fuer PC fehlt");
1078+               return(1);
1079+       }
1080+       if(!(fpb=fopen(botfile,"r"))){
1081+               LOG_INFO("->EEPROM-MAP fuer MCU fehlt");               
1082+               return(2);
1083+       }
1084+
1085+       /*Anzahl Variablen vergleichen*/
1086+       while(fgets(sline, 249, fps)) vc++;
1087+       while(fgets(sline, 249, fpb)) vc--;
1088+       if(vc){
1089+               fclose(fps);
1090+               fclose(fpb);
1091+               LOG_INFO("->Unterschiedliche Variablenanzahl");
1092+               return(6);
1093+       }
1094+       rewind(fps);
1095+       rewind(fpb);
1096+
1097+       /*Tabelle erstellen*/
1098+       while(fgets(sline, 249, fps)){
1099+               rewind(fpb);
1100+               sscanf(&sline[47], "%x %s", &addr_s, vname_s);
1101+               while(fgets(bline, 249, fpb)){
1102+                       /*Variablennamen suchen*/
1103+                       sscanf(&bline[4], "%s %s %s %s %s %s", d1, d, d, d, d2, vname_b);
1104+                       sprintf(saddr, "0x%s", d1);
1105+                       sscanf(saddr, "%x", &addr_b);
1106+                       sprintf(ssize, "0x%s", &d2[4]);
1107+                       sscanf(ssize, "%x", &size);
1108+                       if(!strcmp(&vname_s[1], vname_b)){
1109+                               /*Daten kopieren*/
1110+                               strcpy(ctab[tsize].varname, vname_b);
1111+                               ctab[tsize].simaddr = addr_s;
1112+                               ctab[tsize].botaddr = addr_b;
1113+                               ctab[tsize].size    = size;
1114+                               ctab[tsize++].access  = 0;
1115+
1116+                               /*Fehlerabbrueche*/
1117+                               if(tsize == MAX_VAR){
1118+                                       LOG_INFO("->Mehr als %n Variablen",MAX_VAR);
1119+                                       return(4);
1120+                               }
1121+                               if(addr_s > EE_SIZE){
1122+                                       LOG_INFO("->EEPROM voll");
1123+                                       return(5);
1124+                               }
1125+                               
1126+                               /*Erfolg markieren*/
1127+                               addr_b = -1;
1128+                               break;
1129+                       }
1130+               }
1131+               if(addr_b > -1){ //Keine passende Variable gefunden
1132+                       LOG_INFO("->Unterschiedliche Variablen");
1133+                       return(3);
1134+               }
1135+       }
1136+
1137+       /*Dateien schliessen*/
1138+       fclose(fps);
1139+       fclose(fpb);
1140+       
1141+       /*Tabelle nach Sim-Adressen sortieren*/
1142+       for(ii=tsize-1; ii > 0; ii--){
1143+               for(i=0; i < ii; i++){
1144+                       if(ctab[i].simaddr > ctab[i+1].simaddr){
1145+                               long simaddr, botaddr, size;
1146+                               char vname[30];
1147+                       
1148+                               /*Daten umkopieren*/
1149+                               strcpy(vname, ctab[i+1].varname);
1150+                               simaddr = ctab[i+1].simaddr;
1151+                               botaddr = ctab[i+1].botaddr;
1152+                               size    = ctab[i+1].size;
1153+
1154+                               strcpy(ctab[i+1].varname, ctab[i].varname);
1155+                               ctab[i+1].simaddr = ctab[i].simaddr;
1156+                               ctab[i+1].botaddr = ctab[i].botaddr;
1157+                               ctab[i+1].size    = ctab[i].size;
1158+
1159+                               strcpy(ctab[i].varname, vname);
1160+                               ctab[i].simaddr = simaddr;
1161+                               ctab[i].botaddr = botaddr;
1162+                               ctab[i].size    = size;
1163+                       }
1164+               }
1165+       }
1166+       return(0);
1167+}
1168+
1169+/*!
1170+ * Diese Funktion initialisiert die eeprom-emulation. Sie sorgt fÌr die Erstellung der
1171+ * eeprom.bin, falls nicht vorhanden und erstellt ueber eine Hilfsfunktion eine Adress-
1172+ * konvertierungstabelle fuer die EEPROM-Adressen, wenn die benoetigten Daten vorliegen.
1173+ * Statusinformationen werden ueber DEBUG_INFO angezeigt.
1174+ */
1175+void init_eeprom_man(void){
1176+       uint16 status; //Status von create_ctab
1177+       uint16 sflag; //Sectionstatus
1178+       
1179+       LOG_INFO("EEPROM-Manager");
1180+
1181+       /*Adresskonvertierungstabelle anlegen*/
1182+       if((status=create_ctab(EEMAP_PC, EEMAP_MCU))){
1183+                       LOG_INFO("->EEPROM im PC-Modus");
1184+       }
1185+       else {
1186+                       LOG_INFO("->EEPROM im MCU-Modus");
1187+                       addrconv = 1;
1188+       }
1189+       
1190+       /*Sections ueberpruefen*/
1191+       if((&_eeprom_start2__ - &_eeprom_start1__) > 0 && (&resetsEEPROM - &_eeprom_start2__) >0){
1192+               LOG_INFO("->Sections liegen wohl korrekt");
1193+               LOG_INFO("->Section Abstand 0x%X", (&_eeprom_start2__ - &_eeprom_start1__));
1194+               sflag = 0;
1195+       }
1196+       else{
1197+               LOG_INFO("->Sections liegen falsch");
1198+               sflag = 1;
1199+       }
1200+       
1201+       /*eeprom.bin checken*/
1202+       if(sflag || check_eeprom_file(EEP_PC)){
1203+               LOG_INFO("EEPROM-Emulation fehlerhaft");
1204+       }
1205+       else{
1206+               LOG_INFO("->EEPROM Groesse %d Bytes", EE_SIZE);
1207+               LOG_INFO("EEPROM-Emulation einsatzbereit");
1208+       }
1209+       return;
1210+}
1211+
1212+/*!
1213+ * Traegt die uebergebenen Daten in das simulierte EEPROM ein. Dieses simulierte EEPROM
1214+ * besteht aus einer Datei.
1215+ * Es koennen Bytes (uint8 size = 1) und Integer (uint16 size = 2) uebergeben werden.
1216+ * @param address Adresse im EEPROM zwischen 0 und EE_SIZE-1.
1217+ * @param data Daten die abgelegt werden sollen.
1218+ * @param size Groesse der Daten in Byte.
1219+ */ 
1220+static void store_parameter(uint16 address, uint16 data, uint8 size) {
1221+       FILE  *fpw;     //Dateizeiger
1222+       uint8 dataline[2];      //Speicher fuer Datenausgabe
1223+
1224+//     LOG_STORE
1225+       if(address > (size == 1 ? EE_SIZE-1 : EE_SIZE-2)) //Adresse checken
1226+               return;
1227+
1228+       if(!(fpw = fopen(EEPROM_FILENAME, "r+b"))){ //Testen, ob Datei vorhanden ist.
1229+                       return;
1230+       }
1231+
1232+       //Daten eintragen
1233+       fseek(fpw, address, SEEK_SET); //Schreibzeiger setzen
1234+       dataline[0] = data%256;
1235+       dataline[1] = data/256;
1236+       fwrite(dataline, 1, size, fpw); //Daten schreiben
1237+
1238+       fclose(fpw);
1239+       return;
1240+}
1241+
1242+/*!
1243+ * Liest die gewuenschten Daten aus eine simulierten EEPROM. Dieses simulierte EEPROM
1244+ * besteht aus der Datei eeprom.bin.
1245+ * @param address Adresse im EEPROM zwischen 0 und EE_SIZE-1.
1246+ * @param size Groesse der Daten in Byte.
1247+ * @return Aus dem EEPROM gelesener Wert.
1248+ */ 
1249+static uint16 load_parameter(uint16 address, uint8 size) {
1250+       FILE *fpr;      //Dateizeiger
1251+       uint8 dataline[2] = {0,0};      //String fuer Datenausgabe
1252+
1253+       if(address > (size == 1 ? EE_SIZE-1 : EE_SIZE-2)) //Adresse checken
1254+               return((size == 1 ? 0xff : 0xffff));
1255+
1256+       if(!(fpr = fopen(EEPROM_FILENAME, "rb"))){ //Datei oeffnen
1257+               return((size == 1 ? 0xff : 0xffff));
1258+       }
1259+
1260+       //Daten eintragen
1261+       fseek(fpr, address, SEEK_SET); //Lesezeiger setzen
1262+       fread(dataline, 1, size, fpr);  //Daten lesen);
1263+       fclose(fpr);
1264+//     LOG_LOAD
1265+       return((uint16)dataline[0] + (uint16)dataline[1]*256); 
1266+}
1267+
1268+/*!
1269+ * Liest ein Byte aus den simulierten EEPROM
1270+ * @param addr Adresse im EEPROM
1271+ * @return Aus dem EEPROM gelesener Wert.
1272+ */ 
1273+uint8 eeprom_read_byte(uint8 *addr) {
1274+       return((uint8)load_parameter((uint16)conv_eeaddr(EEPROM_ADDR(addr)), 1));
1275+}
1276+
1277+/*!
1278+ * Liest ein Word aus den simulierten EEPROM
1279+ * @param addr Adresse im EEPROM
1280+ * @return Aus dem EEPROM gelesener Wert.
1281+ */ 
1282+uint16 eeprom_read_word(uint16 *addr) {
1283+       return(load_parameter((uint16)conv_eeaddr(EEPROM_ADDR(addr)), 2));
1284+}
1285+
1286+/*!
1287+ * Schreibt ein Byte in das simulierte EEPROM
1288+ * @param addr Adresse im EEPROM
1289+ * @param Zu schreibender Wert.
1290+ */ 
1291+void eeprom_write_byte(uint8 *addr, uint8 value) {
1292+       store_parameter((uint16)conv_eeaddr(EEPROM_ADDR(addr)), (uint16)value, 1);
1293+}
1294+
1295+/*!
1296+ * Schreibt ein Word in das simulierte EEPROM
1297+ * @param addr Adresse im EEPROM
1298+ * @param Zu schreibender Wert.
1299+ */ 
1300+void eeprom_write_word(uint16 *addr, uint16 value) {
1301+       store_parameter((uint16)conv_eeaddr(EEPROM_ADDR(addr)), value, 2);
1302+}
1303+
1304+/*!
1305+ * Liest ein Speicherblock aus dem simulierte EEPROM
1306+ * @param pointer_ram Adresse im Hauptspeicher
1307+ * @param pointer_eeprom Adresse im EEPROM
1308+ * @param Groesze des Block.
1309+ */ 
1310+void eeprom_read_block (void *pointer_ram, const void *pointer_eeprom, size_t size) {
1311+       uint32 i;
1312+       uint8 *ram;
1313+       
1314+       ram = (uint8 *)pointer_ram;
1315+       for(i=0; i< size; i++){
1316+               ram[i]=(uint16)load_parameter((uint16)conv_eeaddr(EEPROM_ADDR(pointer_eeprom)) + i, 1);
1317+       }
1318+}
1319+
1320+/*!
1321+ * Schreibt ein Speicherblock in das simulierte EEPROM
1322+ * @param pointer_ram Adresse im Hauptspeicher
1323+ * @param pointer_eeprom Adresse im EEPROM
1324+ * @param Groesze des Block.
1325+ */ 
1326+void eeprom_write_block (const void *pointer_ram, void *pointer_eeprom, size_t size) {
1327+       uint32 i;
1328+       uint8 *ram;
1329+       
1330+       ram = (uint8 *)pointer_ram;
1331+       for(i=0; i< size; i++){
1332+               store_parameter((uint16)conv_eeaddr(EEPROM_ADDR(pointer_eeprom)) + i, (uint16)ram[i] ,1);
1333+       }
1334+}
1335+
1336+#endif
1337Index: E:/eclipse/ct-bot test/ct-Bot/Documentation/eeprom-simulation.html
1338===================================================================
1339--- E:/eclipse/ct-bot test/ct-Bot/Documentation/eeprom-simulation.html  (revision 0)
1340+++ E:/eclipse/ct-bot test/ct-Bot/Documentation/eeprom-simulation.html  (revision 0)
1341@@ -0,0 +1,245 @@
1342+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
1343+<HTML>
1344+<HEAD>
1345+       <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=windows-1252">
1346+       <TITLE></TITLE>
1347+       <META NAME="GENERATOR" CONTENT="OpenOffice.org 2.2  (Win32)">
1348+       <META NAME="AUTHOR" CONTENT="Achim Pankalla">
1349+       <META NAME="CREATED" CONTENT="20060528;19455600">
1350+       <META NAME="CHANGEDBY" CONTENT="Achim Pankalla">
1351+       <META NAME="CHANGED" CONTENT="20070617;18142584">
1352+       <STYLE TYPE="text/css">
1353+       <!--
1354+               @page { size: 21cm 29.7cm; margin: 2cm }
1355+               P { margin-bottom: 0.21cm }
1356+       -->
1357+       </STYLE>
1358+</HEAD>
1359+<BODY LANG="de-DE" DIR="LTR">
1360+<P ALIGN=CENTER STYLE="margin-bottom: 0cm"><B>EEPROM Simulation f&uuml;r
1361+PC</B></P>
1362+<P STYLE="margin-bottom: 0cm"><BR>
1363+</P>
1364+<P STYLE="margin-bottom: 0cm"><FONT SIZE=3><B>Author: </B></FONT>
1365+</P>
1366+<P STYLE="margin-bottom: 0cm"><FONT SIZE=3>Achim Pankalla
1367+(achim.pankalla@gmx.de)</FONT></P>
1368+<P STYLE="margin-bottom: 0cm"><BR>
1369+</P>
1370+<P STYLE="margin-bottom: 0cm"><B>Beschreibung:</B></P>
1371+<P ALIGN=LEFT STYLE="margin-bottom: 0cm; font-style: normal">Die
1372+EEPROM Simulation f&uuml;r den PC stellt das EEPROM des <I>Atmel
1373+MEGA32(664) Prozessor</I> auch dem Simulierten ct-bot zur Verf&uuml;gung.
1374+Der Zugriff auf dieses EEPROM erfolgt &uuml;ber gleichnamige
1375+Funktionen, wie sie auch der avr-gcc besitzt und auch die
1376+Variablendefinition erfolgt &uuml;ber die gleichen Konstrukte. Eine
1377+Unterscheidung &uuml;ber #ifdef's ist also nicht notwendig.<BR>Durch
1378+diese EEPROM-Simulation, ist der Simulator dem realen Bot ein schritt
1379+n&auml;her gekommen und Programme mit EEPROM-Zugriffe k&ouml;nnen mit
1380+der Simulation getestet werden. Mehr noch, sie k&ouml;nnen auch das
1381+Simulierte EEPROM auf den ct-bot &uuml;bertragen oder das EEPROM vom
1382+ct-bot abziehen und f&uuml;r die Simulation nutzen.</P>
1383+<P ALIGN=LEFT STYLE="margin-bottom: 0cm"><BR>
1384+</P>
1385+<P STYLE="margin-bottom: 0cm; font-style: normal"><B>Implementierung:</B></P>
1386+<P STYLE="margin-bottom: 0cm">Alle Funktionen und Einstellungen der
1387+EEPROM Simulation findet Sie in den Dateien <I>pc/eeprom-emu_pc.c</I>
1388+und <I>include/eeprom-emu.h</I>. Das EEPROM selbst wird durch eine
1389+Bin&auml;re Datei (genau 1K bzw. 2K gross) repr&auml;sentiert (und
1390+kann so mit einen HexEditor bearbeitet werden), deren Pfad in der
1391+C-Datei festgelegt wird. Standard Pfad ist das Heimatverzeichnis des
1392+Ct-Sim. Nat&uuml;rlich k&ouml;nnen Sie das jederzeit &auml;ndern,
1393+dies geht &uuml;ber die Konstante <FONT COLOR="#000000"><FONT FACE="Courier New, monospace"><FONT SIZE=2>EEPROM_FILENAME.</FONT></FONT></FONT>
1394+<FONT FACE="Times New Roman, serif">Der Name </FONT><FONT FACE="Times New Roman, serif"><I>eeprom.bin</I></FONT>
1395+<FONT FACE="Times New Roman, serif">sollte dabei belassen werden.</FONT><BR>Die
1396+Datei wird automatisch neu angelegt, wenn sie noch nicht existiert.
1397+Dann besteht der Inhalt nur aus 0xFF, wie es auch beim
1398+unintialisierten EEPROM des Atmel der Fall ist.<BR>Damit die
1399+EEPROM-Funktionen des PC korrekt auf die Datei zugreifen k&ouml;nnen
1400+und nur ein Adressraum von 0 bis 1023(2047) entsteht, bedarf es bei
1401+der PC Implementierung (mit PC ist allgemein der Kode f&uuml;r die
1402+Simulation gemeint, mag das OS nun Win, Linux oder MacOS hei&szlig;en)
1403+eines Tricks. Die Emulation muss wissen welche Speicheradresse die
1404+erste Variable hat.<BR>Daf&uuml;r gibt es die beiden Variablen
1405+<I>_eeprom_start1__</I> und <I>_eeprom_start2_</I><SPAN STYLE="font-style: normal">_
1406+in </SPAN><I>ctbot.c</I><SPAN STYLE="font-style: normal">. Diese
1407+stehen dort, damit sie auf jeden Fall vor der ersten EEPROM Variable
1408+definiert werden und damit ihre Sections (.</SPAN><I>s1eeprom</I> <SPAN STYLE="font-style: normal">+
1409+.</SPAN><I>s2eeprom</I><SPAN STYLE="font-style: normal">) auf jeden
1410+Fall vor der Section .</SPAN><I>eeprom</I> <SPAN STYLE="font-style: normal">liegen.
1411+Sie d&uuml;rfen also auf keine Fall eine EEPROM Variable vor diesen
1412+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>
1413+im Moment <SPAN STYLE="font-style: normal">tabu (au&szlig;er die
1414+Abarbeitung im Makefile erfolgt nach </SPAN><I>ctbot.c</I><SPAN STYLE="font-style: normal">,
1415+was im Moment nicht der Fall ist). Sollten einmal eine neue Datei
1416+hinzugef&uuml;gt werden, die durch &bdquo;managed make&ldquo; vor
1417+</SPAN><I>ctbot.c</I> <SPAN STYLE="font-style: normal">landen und
1418+eeprom Variablen enthalten, muss man wahrscheinlich dieses
1419+Startvariablen in die neue Datei verlegen, vor deren EEPROM
1420+Variablen.</SPAN></P>
1421+<P STYLE="margin-bottom: 0cm; font-style: normal">Durch diesen Trick
1422+kann die Speicheradresse der ersten EEPROM Variable auch ohne
1423+Linkerscript ermittelt werden und auch verschiedene
1424+Section-Alignments (im Moment bei MinGW und Linux unterschiedlich)
1425+der Linker haben keine Auswirkung.</P>
1426+<P STYLE="margin-bottom: 0cm; font-style: normal">Auch beim
1427+Generieren eines neuen ct-bot.exe wird eine EEP mit den
1428+Initialisierungen der EEPROM-Variablen im post-build angelegt. Diese
1429+Datei kann die EEPROM-Simulation auch als Initialisierung f&uuml;r
1430+ihr MCU-Kompatibles EEPROM benutzen oder diese Datei kann direkt als
1431+EEPROM-Datei benutzt werden, wenn die Simulation im PC-Modus ist,
1432+gleiches gilt nat&uuml;rlich umgekahr auch f&uuml;r die EEP Datei des
1433+MCU Exe.</P>
1434+<P STYLE="margin-bottom: 0cm"><BR>
1435+</P>
1436+<P STYLE="margin-bottom: 0cm"><B>Nutzung der EEPROM Simulation</B>.</P>
1437+<P STYLE="margin-bottom: 0cm">Die EEPROM-Simulation unterscheidet
1438+sich nur in ein paar Details von den realen Funktionen unter WinAVR
1439+und ct-bot. Nat&uuml;rlich hat der PC kein EEPROM, dies wird durch
1440+eine Datei im Binary Format emuliert. Der Dateinamen und der Pfad
1441+wird &uuml;ber die Konstante EEPROM_FILENAME in <I>eeprom</I>-<I>emu</I>_<I>pc</I>.<I>c</I>
1442+festgelegt. Ein weiterer Unterschied ist, das beim WinAVR &uuml;ber
1443+ein DEFINE der Prozessortyp festgelegt wird, entweder ATMega32 oder
1444+ATMega664. Dieses DEFINE wird normalerweise beim PC Compiler nicht
1445+&uuml;bergeben. Standartm&auml;&szlig;ig wird von einem ATMega32 mit
1446+1024 Byte EEPROM ausgegangen, der Simulator kennt aber die Konstante
1447+f&uuml;r den ATMega664 und erh&ouml;ht den EEPROM Speicher auf 2048
1448+Bytes. Sollte schon eine 1K Datei f&uuml;rs EEPROM bestehen, so muss
1449+diese gel&ouml;scht werden, damit die Gr&ouml;&szlig;ere angelegt
1450+wird. Wird direkt die erstellte <I>ct-bot.eep</I> Datei genutzt, ist
1451+dies nat&uuml;rlich nicht notwendig.</P>
1452+<P STYLE="margin-bottom: 0cm">Alle wichtigen Informationen werden
1453+beim Start des ct-bot.exe im Log-Fenster angezeigt, dort sieht man
1454+auch alle eventuellen Fehler und ob die Simulation ordnungsgem&auml;&szlig;
1455+arbeiten kann. Es erfolgt kein beenden des <I>ct-bot.exe</I> bei
1456+Problemen, ein Funktion des EEPROM ist dann aber nicht gegeben.</P>
1457+<P STYLE="margin-bottom: 0cm">Generell unterscheidet die Simulation
1458+zwei Modi:</P>
1459+<OL>
1460+       <LI><P STYLE="margin-bottom: 0cm">PC-Modus</P>
1461+       <P STYLE="margin-bottom: 0cm">In diesen Modus entspricht die
1462+       eeprom.bin nicht dem EEPROM des realen ct-bot und darf deshalb auch
1463+       nicht auf ihn aufgespielt werden. Dieser Modus wird ohne jedes zu
1464+       tun erreicht. Er ben&ouml;tigt keine weiteren Eintr&auml;ge in Post
1465+       build.
1466+       </P>
1467+       <P STYLE="margin-bottom: 0cm">Wenn eine ct-bot.eep erstellt im
1468+       Binary Format, so kann diese direkt benutzt werden.</P>
1469+       <LI><P STYLE="margin-bottom: 0cm">MCU-Modus</P>
1470+       <P STYLE="margin-bottom: 0cm">Ist dieser Modus erreicht, kann man
1471+       als EEPROM-Datei einen EEPROM Abzug vom ct-bot verwenden.
1472+       Voraussetzung ist nat&uuml;rlich, das der Bot auch mit zuletzt
1473+       erstellten Programm bespielt ist. Nat&uuml;lich kann man auch die
1474+       EEPROM-Datei auf den Bot nutzen.<BR>Der MCU-Modus kann nur erreicht
1475+       werden, wenn sowohl beim avr-ggc als auch unter der PC Oberfl&auml;che
1476+       map-Datei erstellt werden, daf&uuml;r sind im Post Build die
1477+       folgenden Befehle einzutragen:</P>
1478+       <P STYLE="margin-bottom: 0cm">Debug-W32: <B>objcopy -j .eeprom
1479+       --change-section-lma .eeprom=0 -O binary ct-Bot.exe
1480+       ct-Bot.eep;objdump -t ct-bot.exe | grep &quot;(sec  5)&quot; | grep
1481+       &quot;(nx 0)&quot; &gt; eeprom_pc.map</B></P>
1482+       <P STYLE="margin-bottom: 0cm">Debug-MCU-W32: <B>avr-objcopy -O ihex
1483+       -R .eeprom ct-Bot.elf ct-Bot.hex; avr-objcopy -j .eeprom
1484+       --set-section-flags=.eeprom=&quot;alloc,load&quot;
1485+       --change-section-lma .eeprom=0 -O binary ct-Bot.elf
1486+       ct-Bot.eep;avr-objdump -t ct-bot.elf | grep &quot;O \.eeprom&quot; &gt;
1487+       eeprom_mcu.map</B></P>
1488+       <P STYLE="margin-bottom: 0cm"><B>(Achtung! Zwischen sec und 5 zwei
1489+       Spaces)</B></P>
1490+       <P STYLE="margin-bottom: 0cm">Diese Befehlssequence des PC gelten
1491+       nat&uuml;rlich auch f&uuml;r MacOS oder Linux.
1492+       </P>
1493+       <P STYLE="margin-bottom: 0cm">Anhand dieser MAP-Datei k&ouml;nnen
1494+       die Routinen des EEPROM-Manager &uuml;ber eine
1495+       Konvertierungsfunktion die eeprom-Datei bot-kompatible halten.
1496+       Nat&uuml;rlich kann man trotzdem dieses EEPROM mit der EEP-Datei
1497+       initialisieren.</P>
1498+</OL>
1499+<P STYLE="margin-bottom: 0cm"><BR>
1500+</P>
1501+<P STYLE="margin-bottom: 0cm">M&ouml;chte man die vorhandene oder
1502+noch nicht vorhandene EEPROM-Datei mit den Daten aus der EEP-Datei
1503+initialisieren, so muss man die ct-bot.exe mit dem Parameter <I>-i
1504+</I>starten, dabein spielt es keine Rolle in welchen Modus die
1505+Emulation arbeitet. Der Pfad der EEP-Datei wird in der Konstante
1506+<FONT COLOR="#000000"><FONT FACE="Courier New, monospace"><FONT SIZE=2>EEP_PC
1507+</FONT></FONT></FONT><FONT COLOR="#000000"><FONT FACE="Times New Roman, serif"><FONT SIZE=3>eingetragen.</FONT></FONT></FONT></P>
1508+<P STYLE="margin-bottom: 0cm"><FONT COLOR="#000000"><FONT FACE="Times New Roman, serif"><FONT SIZE=3>F&uuml;r
1509+das Debuggen von Zugriffen auf das EEPROM, stehen unter anderen die
1510+DEFINES LOG_STORE und LOG_LOAD zur Verf&uuml;gung, die im MCU Modus
1511+sogar den Variablennamen anzeigen. Andere Variationen sind auch noch
1512+denkbar.</FONT></FONT></FONT></P>
1513+<P STYLE="margin-bottom: 0cm"><BR>
1514+</P>
1515+<P STYLE="margin-bottom: 0cm; font-style: normal"><B>Grenzen der
1516+Implementierung</B></P>
1517+<P STYLE="margin-bottom: 0cm; font-style: normal; font-weight: medium">
1518+Im Moment erstellen gleiche Compilerversionen (zu &Uuml;berpr&uuml;fen
1519+mit &ndash;version) auch (fast) gleiche EEPROM-Sections. Damit es
1520+auch mit verschiedenen Compiler Version geht (und ich mich auch nicht
1521+auf die gleichen Versionen verlasssen will) habe ich die
1522+Adresskonvertierung eingef&uuml;hrt, damit dies kein Problem mehr
1523+ist.</P>
1524+<P STYLE="margin-bottom: 0cm; font-style: normal; font-weight: medium">
1525+Es gibt aber keine Garantien daf&uuml;r, das zuk&uuml;nftige Compiler
1526+Versionen nicht die Reihenfolge der Variablen im Code &auml;ndern.
1527+Ein Einf&uuml;gen neuer EEPROM Variablen kann auch zu Verschiebungen
1528+der Adressen f&uuml;hren. Nach solchen &Auml;nderungen ist man nur
1529+auf der sicheren Seite, wenn das EEPROM initialisiert wird (sprich
1530+Sie Ihre alte eeprom.bin bzw. auf den Atmel das EEPROM l&ouml;schen).
1531+Einmal erstellte Werte sind dann nat&uuml;rlich futsch. Wenn man den
1532+Einfluss von Kodeerg&auml;nzungen kontrollieren will, kann man dies
1533+vor und nach der &Auml;nderungen mit objdump machen (oder falls Sie
1534+die Befehle f&uuml;r die MAP-Dateien im Post-Build benutzen, schauen
1535+Sie in die MAP-Dateien), mit den richtigen Parametern kann man sich
1536+die Adressverteilung anzeigen lassen. Sie k&ouml;nnen dann sehen, ob
1537+die neuen Variablen nun hinten angeh&auml;ngt wurden (dann brauch das
1538+eeprom nicht gel&ouml;scht werden) oder sie dazwischen gelandet sind
1539+(dann sind die alten Daten unbrauchbar), daf&uuml;r sollten sie aber
1540+vorher in eclipse Projekt-&gt;clean aufrufen.<BR>Die Implementierung
1541+des EEPROM auf den PC kontrolliert nicht, ob nicht 1K bzw. 2K an
1542+Daten &uuml;berschritten wird. Der EEPROM-Manager meckert dann aber
1543+im LOG. (Der avg-gcc wird dann aber auch meckern).
1544+</P>
1545+<P STYLE="margin-bottom: 0cm"><BR>
1546+</P>
1547+<P STYLE="margin-bottom: 0cm"><B>Funktionen</B></P>
1548+<P STYLE="margin-bottom: 0cm"><B>Nur in eeprom-emu_pc.c sichtbare
1549+Funktionen</B></P>
1550+<P STYLE="margin-bottom: 0cm">store_parameter() - Speichern von
1551+Informationen im simulierten EEPROM</P>
1552+<P STYLE="margin-bottom: 0cm">load_parameter() - Laden von
1553+Informationen aus dem simulierten EEPROM</P>
1554+<P STYLE="margin-bottom: 0cm">init_eeprom() - Erstellt
1555+Adresskonvertierungstabelle</P>
1556+<P STYLE="margin-bottom: 0cm">conv_eeaddr() - Wandelt PC Adresse in
1557+ct-bot Adresse</P>
1558+<P STYLE="margin-bottom: 0cm">create_ctab() - Erstellt
1559+Adresskonvertierungstabelle</P>
1560+<P STYLE="margin-bottom: 0cm">check_eeprom_file() - Erstellt leeres
1561+EEPROM, wenn n&ouml;tig und initialisiert es, wenn gew&uuml;nscht</P>
1562+<P STYLE="margin-bottom: 0cm">init_eeprom_man() - Initialisiert die
1563+EEPROM Emulation</P>
1564+<P STYLE="margin-bottom: 0cm"><B>Zugriffsfunktionen f&uuml;r den PC
1565+(Identisch zu denen von WinAVR)</B></P>
1566+<P STYLE="margin-bottom: 0cm">eeprom_read_byte()</P>
1567+<P STYLE="margin-bottom: 0cm">eeprom_write_byte()</P>
1568+<P STYLE="margin-bottom: 0cm">eeprom_read_word()</P>
1569+<P STYLE="margin-bottom: 0cm">eeprom_write_word()</P>
1570+<P STYLE="margin-bottom: 0cm">eeprom_write_block()</P>
1571+<P STYLE="margin-bottom: 0cm">eeprom_read_block()</P>
1572+<P STYLE="margin-bottom: 0cm"><BR>
1573+</P>
1574+<P STYLE="margin-bottom: 0cm"><FONT SIZE=3><B>Dateien:</B></FONT></P>
1575+<P STYLE="margin-bottom: 0cm"><FONT SIZE=3>eeprom-emu.h Include
1576+Dateinamen mit Funktionsparameter</FONT></P>
1577+<P STYLE="margin-bottom: 0cm"><FONT SIZE=3>eeprom-emu_pc.c Funktionen
1578+fuer den ct-Sim</FONT></P>
1579+<P STYLE="margin-bottom: 0cm"><BR>
1580+</P>
1581+<P STYLE="margin-bottom: 0cm"><BR>
1582+</P>
1583+<P STYLE="margin-bottom: 0cm"><BR>
1584+</P>
1585+</BODY>
1586+</HTML>
1587\ No newline at end of file
1588Index: E:/eclipse/ct-bot test/ct-Bot/ct-Bot.c
1589===================================================================
1590--- E:/eclipse/ct-bot test/ct-Bot/ct-Bot.c      (revision 1162)
1591+++ E:/eclipse/ct-bot test/ct-Bot/ct-Bot.c      (working copy)
1592@@ -39,6 +39,7 @@
1593        #include "bot-2-sim.h"
1594        #include "tcp.h"
1595        #include "tcp-server.h"
1596+       #include "eeprom-emu.h"
1597        #include <pthread.h>
1598        #include <unistd.h>
1599        #include <stdlib.h>
1600@@ -83,6 +84,12 @@
1601 #include "gui.h"
1602 #include "ui/available_screens.h"
1603 
1604+//Moeglichst frueh section erzwingen, damit sie VOR .eeprom liegt!!!
1605+#ifdef PC
1606+       uint8 __attribute__ ((section (".s1eeprom"))) _eeprom_start1__ = 0;
1607+       uint8 __attribute__ ((section (".s2eeprom"))) _eeprom_start2__ = 0;
1608+#endif
1609+
1610 /*!
1611  * Der Mikrocontroller und der PC-Simulator brauchen ein paar Einstellungen,
1612  * bevor wir loslegen koennen.
1613@@ -93,7 +100,7 @@
1614                PORTB=0; DDRB=0;
1615                PORTC=0; DDRC=0;
1616                PORTD=0; DDRD=0;
1617-                       
1618+
1619                wdt_disable();  // Watchdog aus!
1620                timer_2_init();
1621               
1622@@ -133,6 +140,7 @@
1623 
1624        #ifdef PC
1625                bot_2_sim_init();
1626+               init_eeprom_man();
1627        #endif
1628 
1629        #ifdef DISPLAY_AVAILABLE
1630@@ -237,6 +245,7 @@
1631                puts("\t-d \tLoescht eine Mini-Fat-Datei fuer den Sim (emulierte MMC).");               
1632                puts("\t   ID  \tDie ID aus ASCII-Zeichen");           
1633                puts("\t-l \tKonvertiert eine SpeedLog-Datei in eine txt-Datei");
1634+               puts("\t-i \t Initialisiert das EEPROM mit den Daten der EEP-Datei");
1635                puts("\t-h\tZeigt diese Hilfe an");
1636                exit(1);
1637        }
1638@@ -271,7 +280,6 @@
1639                int slog        =0;
1640                char *from = NULL;      /*!< Speichert den per -M uebergebenen Quellnamen zwischen */
1641 
1642-
1643                /* Die Kommandozeilenargumente komplett verarbeiten */
1644                while ((ch = getopt(argc, argv, "hsTt:M:c:l:e:d:")) != -1) {
1645                        switch (ch) {
1646@@ -348,6 +356,9 @@
1647                                        slog=1;                                 
1648                                }                               
1649                                break;                 
1650+                       case 'i':
1651+                               eeprom_init = 1;
1652+                               break;
1653                        case 'h':
1654                        default:
1655                                /* -h oder falscher Parameter, Usage anzeigen */
1656Index: E:/eclipse/ct-bot test/ct-Bot/ui/misc.c
1657===================================================================
1658--- E:/eclipse/ct-bot test/ct-Bot/ui/misc.c     (revision 1162)
1659+++ E:/eclipse/ct-bot test/ct-Bot/ui/misc.c     (working copy)
1660@@ -32,11 +32,11 @@
1661 #include "timer.h"
1662 #ifdef MCU
1663        #include <avr/eeprom.h>
1664+#else
1665+       #include "eeprom-emu.h"
1666 #endif
1667 
1668-#ifdef MCU
1669-       uint8 __attribute__ ((section (".eeprom"))) resetsEEPROM = 0;   /*!< Reset-Counter-Wert im EEPROM */
1670-#endif
1671+uint8 EEPROM resetsEEPROM = 0; /*!< Reset-Counter-Wert im EEPROM */
1672 
1673 #ifdef DISPLAY_AVAILABLE
1674        #ifdef MISC_DISPLAY_AVAILABLE
1675Index: E:/eclipse/ct-bot test/ct-Bot/ct-Bot.h
1676===================================================================
1677--- E:/eclipse/ct-bot test/ct-Bot/ct-Bot.h      (revision 1162)
1678+++ E:/eclipse/ct-bot test/ct-Bot/ct-Bot.h      (working copy)
1679@@ -31,7 +31,7 @@
1680 /************************************************************
1681 * Module switches, to make code smaller if features are not needed
1682 ************************************************************/
1683-//#define LOG_CTSIM_AVAILABLE          /*!< Logging zum ct-Sim (PC und MCU) */
1684+#define LOG_CTSIM_AVAILABLE            /*!< Logging zum ct-Sim (PC und MCU) */
1685 //#define LOG_DISPLAY_AVAILABLE                /*!< Logging ueber das LCD-Display (PC und MCU) */
1686 //#define LOG_UART_AVAILABLE           /*!< Logging ueber UART (NUR fuer MCU) */
1687 //#define LOG_STDOUT_AVAILABLE                 /*!< Logging auf die Konsole (NUR fuer PC) */

Download in other formats:

  • Original Format

Trac Powered

Powered by Trac 0.11.7
By Edgewall Software.

http://www.ctmagazin.de/
http://www.ctmagazin.de/projekte/

  • Datenschutzhinweis
  • Impressum
  • Kritik, Anregungen bitte an c't-WWW
  • Mediadaten
  • Copyright © 2011 Heise Zeitschriften Verlag
  • International: The H, The H Security, The H Open Source