c't Projekte - c't-Bot und c't-Sim -
Mailinglisten
[Voriger (Datum)]
[Nächster (Datum)]
[Voriger (Thread)]
[Nächster (Thread)]
[Nach Datum][Nach Thread]
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ü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ür den PC stellt das EEPROM des <I>Atmel
> +MEGA32(664) Prozessor</I> auch dem Simulierten ct-bot zur Verfügung.
> +Der Zugriff auf dieses EEPROM erfolgt über gleichnamige
> +Funktionen, wie sie auch der avr-gcc besitzt und auch die
> +Variablendefinition erfolgt über die gleichen Konstrukte. Eine
> +Unterscheidung über #ifdef's ist also nicht notwendig.<BR>Durch
> +diese EEPROM-Simulation, ist der Simulator dem realen Bot ein schritt
> +näher gekommen und Programme mit EEPROM-Zugriffe können mit
> +der Simulation getestet werden. Mehr noch, sie können auch das
> +Simulierte EEPROM auf den ct-bot übertragen oder das EEPROM vom
> +ct-bot abziehen und fü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äre Datei (genau 1K bzw. 2K gross) reprä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ürlich können Sie das jederzeit ändern,
> +dies geht ü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önnen
> +und nur ein Adressraum von 0 bis 1023(2047) entsteht, bedarf es bei
> +der PC Implementierung (mit PC ist allgemein der Kode für die
> +Simulation gemeint, mag das OS nun Win, Linux oder MacOS heißen)
> +eines Tricks. Die Emulation muss wissen welche Speicheradresse die
> +erste Variable hat.<BR>Dafü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ü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ß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ügt werden, die durch „managed make“ 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ü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ürlich umgekahr auch fü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ürlich hat der PC kein EEPROM, dies wird durch
> +eine Datei im Binary Format emuliert. Der Dateinamen und der Pfad
> +wird ü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 über
> +ein DEFINE der Prozessortyp festgelegt wird, entweder ATMega32 oder
> +ATMega664. Dieses DEFINE wird normalerweise beim PC Compiler nicht
> +übergeben. Standartmäßig wird von einem ATMega32 mit
> +1024 Byte EEPROM ausgegangen, der Simulator kennt aber die Konstante
> +für den ATMega664 und erhöht den EEPROM Speicher auf 2048
> +Bytes. Sollte schon eine 1K Datei fürs EEPROM bestehen, so muss
> +diese gelöscht werden, damit die Größere angelegt
> +wird. Wird direkt die erstellte <I>ct-bot.eep</I> Datei genutzt, ist
> +dies natü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äß
> +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ötigt keine weiteren Einträ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ürlich, das der Bot auch mit zuletzt
> + erstellten Programm bespielt ist. Natü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äche
> + map-Datei erstellt werden, dafü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 "(sec 5)" | grep
> + "(nx 0)" > 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="alloc,load"
> + --change-section-lma .eeprom=0 -O binary ct-Bot.elf
> + ct-Bot.eep;avr-objdump -t ct-bot.elf | grep "O \.eeprom" >
> + 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ürlich auch für MacOS oder Linux.
> + </P>
> + <P STYLE="margin-bottom: 0cm">Anhand dieser MAP-Datei können
> + die Routinen des EEPROM-Manager über eine
> + Konvertierungsfunktion die eeprom-Datei bot-kompatible halten.
> + Natü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ö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ür
> +das Debuggen von Zugriffen auf das EEPROM, stehen unter anderen die
> +DEFINES LOG_STORE und LOG_LOAD zur Verfü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 Überprüfen
> +mit –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ü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ür, das zukünftige Compiler
> +Versionen nicht die Reihenfolge der Variablen im Code ändern.
> +Ein Einfügen neuer EEPROM Variablen kann auch zu Verschiebungen
> +der Adressen führen. Nach solchen Ä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öschen).
> +Einmal erstellte Werte sind dann natürlich futsch. Wenn man den
> +Einfluss von Kodeergänzungen kontrollieren will, kann man dies
> +vor und nach der Änderungen mit objdump machen (oder falls Sie
> +die Befehle fü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önnen dann sehen, ob
> +die neuen Variablen nun hinten angehängt wurden (dann brauch das
> +eeprom nicht gelöscht werden) oder sie dazwischen gelandet sind
> +(dann sind die alten Daten unbrauchbar), dafür sollten sie aber
> +vorher in eclipse Projekt->clean aufrufen.<BR>Die Implementierung
> +des EEPROM auf den PC kontrolliert nicht, ob nicht 1K bzw. 2K an
> +Daten ü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ötig und initialisiert es, wenn gewünscht</P>
> +<P STYLE="margin-bottom: 0cm">init_eeprom_man() - Initialisiert die
> +EEPROM Emulation</P>
> +<P STYLE="margin-bottom: 0cm"><B>Zugriffsfunktionen fü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