Esempio n. 1
0
size_t
convert_gcs(int igcfile_version, FILE *Ausgabedatei,
            const uint8_t *const bin_puffer, size_t length,
            bool oo_fillin)
{
    const uint8_t *const end = bin_puffer + length;

    IGCHEADER igcheader;
    C_RECORD task;
    struct
    {
        // All value directly from fix, before conversion
        char time[10];
        char valid;
        long lat;
        long lon;
    } igcfix;

    int l = 0;
    int ende;

    // relative time from the beginning of the logging
    long time_relative = 0;
    long temptime;
    long decl_time;
    tm firsttime;
    memset(&firsttime, 0, sizeof(firsttime));

    tm realtime;
    uint8_t Haupttyp;
    uint8_t Untertyp;
    const uint8_t *p;
    const uint8_t *p2;
    long pl;
    char PILOT[40];
    int tzh, tzm;
    // word           keysn;
    // binary data format version
    int bfv = 0;
    long delta_lat, delta_lon;
    // Timezone in minutes from FDT field
    int tzn = 4000;
    // Ini value for determination, whether the field existed
    float ftz = 0;
    // Flag, whether ftz is received from a valid position
    int tzset = 0;

    // long ggtz = timezone;

    if (igcfile_version == 0)
        igcfile_version = actual_conv_version;

    igcfix.lat = 0;
    igcfix.lon = 0;

    //igcfile_version = 0;
    igcheader.redirect(Ausgabedatei);
    //task.init();
    decl_time = -1;

    ende = 0;
    p = bin_puffer;

    do {
        if (p >= end)
            return 0;

        Haupttyp = p[0] & rectyp_msk;
        switch (Haupttyp) {
        case rectyp_tnd:
            if (p + 8 > end)
                return 0;

            // calculates backwards the time of the first fix
            time_relative += p[1];
            temptime = 65536L * p[2] + 256L * p[3] + p[4];
            firsttime.tm_sec = temptime % 3600;
            firsttime.tm_hour = temptime / 3600;
            firsttime.tm_min = 0;
            firsttime.tm_mday = 10 * (p[7] >> 4) + (p[7] & 0x0f);
            firsttime.tm_mon = 10 * (p[6] >> 4) + (p[6] & 0x0f) - 1;
            firsttime.tm_year = 10 * (p[5] >> 4) + (p[5] & 0x0f);

            // Y2K-patch
            if (igcfile_version >= 424)
                if (firsttime.tm_year < 80)
                    firsttime.tm_year += 100;

            firsttime.tm_isdst = -1;
            firsttime.tm_sec -= time_relative % 3600;
            firsttime.tm_hour -= time_relative / 3600;
            //xxxtime

            mktime(&firsttime);
            l = 8;
            break;
        /*
         case rectyp_pos : time_relative += p[2];
         l = pos_ds_size[bfv][0];
         break;
         case rectyp_poc :	if(p[2] & 0x80) { // Endebedingung
         ende = 1;
         l = 0;
         break;
         }
         time_relative += p[2];
         l = pos_ds_size[bfv][1];
         break;
         */
        case rectyp_pos:
        case rectyp_poc:
            if (p + 2 >= end)
                return 0;

            if (p[2] & 0x80) { // Endebedingung
                ende = 1;
                l = 0;
                break;
            }

            if (p + 8 > end)
                return 0;

            time_relative += p[2];
            igcfix.valid = ((p[0] & 0x10) >> 4) ? 'A' : 'V';
            if (Haupttyp == rectyp_pos) {
                l = pos_ds_size[bfv][0];
                igcfix.lon = ((unsigned long)p[6]) << 16 | ((unsigned long)p[7]) << 8
                             | p[8];
                if (p[9] & 0x80)
                    igcfix.lon = -igcfix.lon;
            } else {
                l = pos_ds_size[bfv][1];
                delta_lon = (((unsigned long)p[3] & 0x78) << 5) | p[5];
                if (p[6] & 0x80)
                    delta_lon = -delta_lon;
                igcfix.lon += delta_lon;
            }
            // ftz mit Längengrad füllen
            // der erste gültige ist der letzte,
            // der in ftz gespeichert wird
            if (!tzset) {
                ftz = float(igcfix.lon);
                if (igcfix.valid == 'A')
                    tzset = 1;
            }
            break;
        case rectyp_sep:
            time_relative = 0;
            bfv = p[0] & ~rectyp_msk;
            if (bfv > max_bfv) {
                // unsupported binary file version
                return 0;
            }
            l = 1;
            break;
        case 0xC0:
            l = 1; // Füllzeichen
            break;
        case rectyp_end:
            /* sp = (p - bin_puffer) + 1 */
            l = 41;
            ende = 1;
            break;
        case rectyp_vrb:
        case rectyp_vrt:
            if (p + 2 >= end)
                return 0;

            l = p[1];
            switch (Haupttyp) {
            case rectyp_vrb:
                p2 = p + 2;
                break;
            case rectyp_vrt:
                time_relative += p[2];
                p2 = p + 3;
                break;
            default:
                p2 = p;
                break;
            }

            if (p2 >= end)
                return 0;

            Untertyp = (p2[0]);
            switch (Untertyp) {

            case FLDNTP:
                if (p2 + 1 >= end)
                    return 0;

                task.NTP = p2[1];
                decl_time = time_relative;
                break;
            case FLDTID:
                if (p2 + 2 >= end)
                    return 0;

                task.TID = 256 * p2[1] + p2[2];
                if (igcfile_version >= 422)
                    decl_time = time_relative;
                break;
            case FLDFDT:
                if (p2 + 1 + sizeof(task.FDT) > end)
                    return 0;

                //_fmemcpy(&task.FDT,&p2[1],sizeof task.FDT);
                memcpy(&task.FDT, &p2[1], sizeof task.FDT);
                break;
            case FLDTZN: // Reading timezone offset
                if (p2 + 1 >= end)
                    return 0;

                if (p2[1] < 128)
                    tzn = 15 * p2[1];
                else
                    tzn = 15 * (p2[1] - 256);
                break;

            case FLDTKF:
                if (p2 + 1 + 12 > end)
                    return 0;

                task.TKF.packed2unpacked(&p2[1]);
                break;
            case FLDSTA:
                if (p2 + 1 + 12 > end)
                    return 0;

                task.STA.packed2unpacked(&p2[1]);
                break;
            case FLDFIN:
                if (p2 + 1 + 12 > end)
                    return 0;

                task.FIN.packed2unpacked(&p2[1]);
                break;
            case FLDLDG:
                if (p2 + 1 + 12 > end)
                    return 0;

                task.LDG.packed2unpacked(&p2[1]);
                break;
            case FLDTP1:
                if (p2 + 1 + 12 > end)
                    return 0;

                task.TP[0].packed2unpacked(&p2[1]);
                break;
            case FLDTP2:
                if (p2 + 1 + 12 > end)
                    return 0;

                task.TP[1].packed2unpacked(&p2[1]);
                break;
            case FLDTP3:
                if (p2 + 1 + 12 > end)
                    return 0;

                task.TP[2].packed2unpacked(&p2[1]);
                break;
            case FLDTP4:
                task.TP[3].packed2unpacked(&p2[1]);
                break;
            case FLDTP5:
                if (p2 + 1 + 12 > end)
                    return 0;

                task.TP[4].packed2unpacked(&p2[1]);
                break;
            case FLDTP6:
                if (p2 + 1 + 12 > end)
                    return 0;

                task.TP[5].packed2unpacked(&p2[1]);
                break;
            case FLDTP7:
                if (p2 + 1 + 12 > end)
                    return 0;

                task.TP[6].packed2unpacked(&p2[1]);
                break;
            case FLDTP8:
                if (p2 + 1 + 12 > end)
                    return 0;

                task.TP[7].packed2unpacked(&p2[1]);
                break;
            case FLDTP9:
                if (p2 + 1 + 12 > end)
                    return 0;

                task.TP[8].packed2unpacked(&p2[1]);
                break;
            case FLDTP10:
                if (p2 + 1 + 12 > end)
                    return 0;

                task.TP[9].packed2unpacked(&p2[1]);
                break;
            case FLDTP11:
                if (p2 + 1 + 12 > end)
                    return 0;

                task.TP[10].packed2unpacked(&p2[1]);
                break;
            case FLDTP12:
                if (p2 + 1 + 12 > end)
                    return 0;

                task.TP[11].packed2unpacked(&p2[1]);
                break;

            case FLDPLT1: // Reading pilotname
            case FLDPLT2: // Reading pilotname
            case FLDPLT3: // Reading pilotname
            case FLDPLT4: // Reading pilotname
                if (p2 + 1 + sizeof(PILOT) > end)
                    return 0;

                // _fmemcpy(igcheader.PLT, &p2[1], (sizeof igcheader.PLT));
                // igcheader.PLT[(sizeof igcheader.PLT)-1] = 0;
                //_fmemcpy(PILOT, &p2[1], (sizeof PILOT));
                memcpy(PILOT, &p2[1], (sizeof PILOT));
                PILOT[(sizeof PILOT) - 1] = 0;
                strcat(igcheader.PLT, PILOT);
                if (igcfile_version < 413)
                    strcat(igcheader.PLT, " ");
                break;
            case FLDGTY: // Reading plane type
                if (p2 + 1 + sizeof(igcheader.GTY) > end)
                    return 0;

                //_fmemcpy(igcheader.GTY, &p2[1], (sizeof igcheader.GTY));
                memcpy(igcheader.GTY, &p2[1], (sizeof igcheader.GTY));
                igcheader.GTY[(sizeof igcheader.GTY) - 1] = 0;
                break;
            case FLDGID: // Reading plane reg
                if (p2 + 1 + sizeof(igcheader.GID) > end)
                    return 0;

                //_fmemcpy(igcheader.GID, &p2[1], (sizeof igcheader.GID));
                memcpy(igcheader.GID, &p2[1], (sizeof igcheader.GID));
                igcheader.GID[(sizeof igcheader.GID) - 1] = 0;
                break;
            case FLDCCL: // Reading plane class
                if (p2 + 1 + sizeof(igcheader.CCL) > end)
                    return 0;

                //_fmemcpy(igcheader.CCL, &p2[1], (sizeof igcheader.CCL));
                memcpy(igcheader.CCL, &p2[1], (sizeof igcheader.CCL));
                igcheader.CCL[(sizeof igcheader.CCL) - 1] = 0;
                break;
            case FLDCID: // Reading plane competition sign
                if (p2 + 1 + sizeof(igcheader.CID) > end)
                    return 0;

                //_fmemcpy(igcheader.CID, &p2[1], (sizeof igcheader.CID));
                memcpy(igcheader.CID, &p2[1], (sizeof igcheader.CID));
                igcheader.CID[(sizeof igcheader.CID) - 1] = 0;
                break;
            case FLDHDR: // Reading serial number and other stuff
                // Public-Key erst mal löschen
                // 19.10.99 weggemacht, weil schon in main vorhanden
                //dsa_y_b[0] = 2; dsa_y_b[1] = 0;
                //memset(&dsa_y_b[2],0,(sizeof dsa_y_b)-2);

                if (p2 + 7 >= end)
                    return 0;

                // sonstiges einlesen
                wordtoserno(igcheader.A, 256 * p2[1] + p2[2]);

                sprintf(igcheader.DTM, "%03u", p2[3]);
                sprintf(igcheader.RHW, "%0X.%0X", p2[4] >> 4, (p2[4] & 0xf));
                sprintf(igcheader.RFW, "%0X.%0X", p2[5] >> 4, (p2[5] & 0xf));
                sprintf(igcheader.FXA, "%03u", p2[7]);

                // neuer obligatorischer H-Record
                if (igcfile_version >= 421)
                    sprintf(igcheader.FTY,
                            "GARRECHT INGENIEURGESELLSCHAFT,VOLKSLOGGER 1.0");
                break;
            }
            ;
            break;

        default:
            ende = 1;
            break;
        }
        p += l;
    } while (!ende);

    pl = p - bin_puffer;

    // Timezone/Hours = floor(LON + 7.5°) / 15° of the first fix
    ftz = ftz + 450000L;
    ftz = ftz / 900000L;
    task.zz_min = int(60 * floor(ftz));
    //  printf("theoretische Zeitzone = UTC %-d min\n",task.zz_min);
    //  getch();

    // for new files
    if ((igcfile_version >= 420) && (igcfile_version < 422))
        // if TZN field does not exist
        if (tzn == 4000)
            // emulate it with the calculated
            tzn = task.zz_min;

    // for all files
    // show TZN, if set
    if (tzn != 4000) {
        tzh = abs(tzn) / 60;
        tzm = abs(tzn) % 60;
        sprintf(igcheader.TZN, "UTC%c%02d:%02d", (tzn < 0 ? '-' : '+'), tzh, tzm);
    }

    strftime(igcheader.DTE,sizeof(igcheader.DTE),"%d%m%y",&firsttime);
    igcheader.output(igcfile_version, oo_fillin);

    if (igcfile_version >= 414 || (task.STA.koord.lat != 0)
            || (task.STA.koord.lon != 0)) {
        if (decl_time >= 0) {
            task.hasdeclaration = 1;
            memcpy(&task.TDECL, &firsttime, sizeof task.TDECL);
            task.TDECL.tm_sec += decl_time % 3600;
            task.TDECL.tm_hour += decl_time / 3600;
            task.TDECL.tm_isdst = -1;
            mktime(&task.TDECL);
            task.print(igcfile_version, Ausgabedatei);
        }
    }

    igcfix.lat = 0;
    igcfix.lon = 0;

    realtime = firsttime;
    ende = 0;
    p = bin_puffer;
    do {
        Haupttyp = p[0] & rectyp_msk;
        switch (Haupttyp) {
        case rectyp_sep:
            l = 1;
            if (bfv > max_bfv) {
                ende = 1;
                l = 0;
                break;
            }
            break;
        case 0xC0:
            l = 1;
            break;
        case rectyp_pos:
        case rectyp_poc: {
            if (p[2] & 0x80) { // Endebedingung
                ende = 1;
                l = 0;
                break;
            }
            time_relative += p[2];
            realtime.tm_sec += p[2];
            realtime.tm_isdst = -1;
            mktime(&realtime);
            igcfix.valid = ((p[0] & 0x10) >> 4) ? 'A' : 'V';
            const unsigned press = unsigned(p[0] & 0x0f) << 8 | p[1];
            unsigned gpalt, fxa, enl;
            if (Haupttyp == rectyp_pos) {
                l = pos_ds_size[bfv][0];
                igcfix.lat = ((unsigned long)p[3] & 0x7f) << 16 | ((unsigned long)p[4])
                             << 8 | p[5];
                if (p[3] & 0x80)
                    igcfix.lat = -igcfix.lat;

                igcfix.lon = ((unsigned long)p[6]) << 16 | ((unsigned long)p[7]) << 8
                             | p[8];
                if (p[9] & 0x80)
                    igcfix.lon = -igcfix.lon;

                gpalt = unsigned(p[9] & 0x70) << 4 | p[10];
                fxa = hdop2fxa(p[9] & 0x0f);
                enl = 4 * p[11];
            }

            else {
                l = pos_ds_size[bfv][1];
                delta_lat = (((unsigned long)p[3] & 0x07) << 8) | p[4];
                if (p[3] & 0x80)
                    delta_lat = -delta_lat;
                delta_lon = (((unsigned long)p[3] & 0x78) << 5) | p[5];
                if (p[6] & 0x80)
                    delta_lon = -delta_lon;

                igcfix.lat += delta_lat;
                igcfix.lon += delta_lon;
                gpalt = unsigned(p[6] & 0x70) << 4 | p[7];
                fxa = hdop2fxa(p[6] & 0x0f);
                enl = 4 * p[8];
            }

            const unsigned latdeg = labs(igcfix.lat) / 60000;
            const unsigned latmin = labs(igcfix.lat) % 60000;
            const unsigned londeg = labs(igcfix.lon) / 60000;
            const unsigned lonmin = labs(igcfix.lon) % 60000;

            long gps_alt = 10L * gpalt - 1000L;

            if (igcfile_version >= 423)
                enl = enlflt(enl);
            enl = enllim(enl);

            // Bei allen neuen Dateien auf Wunsch von IAN
            // aber dank neuer Regeln ab
            // Konverter Nr. 4.20 nicht mehr !!
            if ((igcfile_version >= 413) && (igcfile_version < 420))
                if (igcfix.valid == 'V')
                    gps_alt = 0;

            const long pressure_alt = pressure2altitude(press);

            strftime(igcfix.time,sizeof(igcfix.time),"%H%M%S",&realtime);
            fprintf(Ausgabedatei, "B%6s%02u%05u%c%03u%05u%c%c%05ld%05ld%03u",
                    igcfix.time,
                    latdeg, latmin, igcfix.lat < 0 ? 'S' : 'N',
                    londeg, lonmin, igcfix.lon < 0 ? 'W' : 'E',
                    igcfix.valid, pressure_alt, gps_alt,
                    fxa);

            // activate on ENL in I record
            if ((igcfile_version >= 413) && (igcfile_version < 416))
                fprintf(Ausgabedatei, "999");

            // have to be active, if sensor exists
            if (strcmp(igcheader.RHW, "3.3") >= 0)
                fprintf(Ausgabedatei, "%03u", enl);

            fprintf(Ausgabedatei, "\n");
        }
        break;

        case rectyp_vrb:
        case rectyp_vrt:
            l = p[1];
            switch (Haupttyp) {
            case rectyp_vrb:
                p2 = p + 2;
                break;
            case rectyp_vrt:
                realtime.tm_sec += p[2];
                realtime.tm_isdst = -1;
                mktime(&realtime);
                p2 = p + 3;
                break;
            default:
                p2 = p;
                break;
            }
            Untertyp = (p2[0]);
            switch (Untertyp) {
            case FLDEPEV:
                strftime(igcfix.time,sizeof(igcfix.time),"%H%M%S",&realtime);
                fprintf(Ausgabedatei, "E%6sPEVEVENTBUTTON PRESSED\n", igcfix.time);
                break;
            case FLDETKF:
                strftime(igcfix.time,sizeof(igcfix.time),"%H%M%S",&realtime);
                fprintf(Ausgabedatei, "LGCSTKF%6sTAKEOFF DETECTED\n", igcfix.time);
                break;
            }
            ;
            break;
        case rectyp_tnd:
            realtime.tm_sec += p[1];
            realtime.tm_isdst = -1;
            mktime(&realtime);
            l = 8;
            break;

        default:
            ende = 1;
            l = 0;
            break;
        }
        p += l;
    } while (!ende);
    return pl;
}
Esempio n. 2
0
long convert_gcs(int igcfile_version, FILE *Ausgabedatei, lpb bin_puffer, int oo_fillin, word *serno, long *sp) {
 IGCHEADER igcheader;
 C_RECORD task;
 struct { // Alle Werte direkt aus Fix, vor Umwandlung
   char time[10];
   char valid;
   long lat;
   word latdeg;
   word latmin;
   long lon;
   word londeg;
   word lonmin;
   word press;
   word gpalt;
   long pressure_alt;
   long gps_alt;
   word fxa;
   word hdop;
   word enl;
 } igcfix;

 int		l = 0;
 int    	ende;

 long   	time_relative = 0;  // relative Zeit vom Aufzeichnungsbeginn an
 long		temptime;
 long		decl_time;
 tm		firsttime;
 tm		realtime;
 byte 		Haupttyp;
 byte		Untertyp;
 lpb	 	p;
 lpb		p2;
 long 		pl;
 char		PILOT[40];
 int            tzh,tzm;
// word           keysn;
 int            bfv = 0; // Binärdatenformat-Version
 long           delta_lat,delta_lon;
 // Zeitzone in Minuten aus Feld FDT
 int            tzn = 4000; // Ini-Wert zur Erkennung, ob es das Feld gab
 // aus Position berechnete Zeitzone
 float          ftz = 0;
 // Flag, ob ftz aus gültiger Position stammt
 int		tzset = 0;

	// Initialize firsttime structure to fix compiler warning
	firsttime.tm_sec   = 0;
	firsttime.tm_hour  = 0;
	firsttime.tm_min   = 0;
	firsttime.tm_mday  = 0;
	firsttime.tm_mon   = 0;
	firsttime.tm_year  = 0;
	firsttime.tm_yday  = 0;
	firsttime.tm_wday  = 0;

 // long ggtz = timezone;

  if (igcfile_version == 0)
    igcfile_version = actual_conv_version;

  igcfix.lat = 0;
  igcfix.lon = 0;

  //igcfile_version = 0;
  igcheader.redirect(Ausgabedatei);
  //task.init();
  decl_time = -1;

  ende = 0;
  p = bin_puffer;

  do {
    Haupttyp = p[0] & rectyp_msk;
    switch (Haupttyp) {
      case rectyp_tnd :
	// errechnet rückwärts die Zeit des 1. Fixes
	time_relative += p[1];
	temptime = 65536L * p[2] + 256L * p[3] + p[4];
	firsttime.tm_sec   = temptime % 3600;
	firsttime.tm_hour  = temptime / 3600;
	firsttime.tm_min   = 0;
	firsttime.tm_mday  = 10*(p[7] >> 4) + (p[7] & 0x0f);
	firsttime.tm_mon   = 10*(p[6] >> 4) + (p[6] & 0x0f) - 1;
	firsttime.tm_year  = 10*(p[5] >> 4) + (p[5] & 0x0f);


	// Y2K-patch
	if(igcfile_version >= 424)
	  if(firsttime.tm_year < 80)
	    firsttime.tm_year += 100;

	firsttime.tm_isdst = -1;
	firsttime.tm_sec  -= time_relative % 3600;
	firsttime.tm_hour -= time_relative / 3600;
	//xxxtime
//JMW TODO	mktime(&firsttime);
	l = 8;
	break;
/*
      case rectyp_pos : time_relative += p[2];
			l = pos_ds_size[bfv][0];
			break;
      case rectyp_poc :	if(p[2] & 0x80) { // Endebedingung
			  ende = 1;
			  l = 0;
			  break;
			}
			time_relative += p[2];
			l = pos_ds_size[bfv][1];
			break;
*/
      case rectyp_pos :
      case rectyp_poc :	if (p[2] & 0x80) { // Endebedingung
			  ende = 1;
			  l = 0;
			  break;
			}
			time_relative += p[2];
			igcfix.valid = ((p[0] & 0x10) >> 4) ? 'A' : 'V';
			if (Haupttyp == rectyp_pos) {
			  l = pos_ds_size[bfv][0];
			  igcfix.lon   =   ((unsigned long)p[6] ) << 16
					 | ((unsigned long)p[7] ) << 8
					 | p[8];
			  if (p[9] & 0x80)
			    igcfix.lon = -igcfix.lon;
			}
			else {
			  l = pos_ds_size[bfv][1];
			  delta_lon = (((unsigned long)p[3] & 0x78) << 5) | p[5];
			  if (p[6] & 0x80)
			    delta_lon = -delta_lon;
			  igcfix.lon += delta_lon;
			}
			// ftz mit Längengrad füllen
			// der erste gültige ist der letzte,
			// der in ftz gespeichert wird
			if (!tzset) {
			  ftz = float(igcfix.lon);
			  if (igcfix.valid=='A')
			    tzset=1;
			}
			break;
      case rectyp_sep : time_relative = 0;
			bfv = p[0] & ~rectyp_msk;
			if (bfv > max_bfv) {
			  // unsupported binary file version
			  return 0;
			}
			l = 1;
			break;
      case 0xC0       : l = 1; // Füllzeichen
			break;
      case rectyp_end : *sp = (p-bin_puffer) + 1;
			l = 41;
			ende = 1;
			break;
      case rectyp_vrb :
      case rectyp_vrt : l = p[1];
			switch(Haupttyp) {
			  case rectyp_vrb : p2 = p+2; break;
			  case rectyp_vrt : time_relative += p[2];
					    p2 = p+3; break;
			  default	  : p2 = p; break;
			}
			Untertyp = (p2[0]);
			switch (Untertyp) {

			  case FLDNTP :
			    task.NTP = p2[1];
			    decl_time = time_relative;
			    break;
			  case FLDTID :
			    task.TID = 256*p2[1] + p2[2];
			    if (igcfile_version >= 422)
			      decl_time = time_relative;
			    break;
			  case FLDFDT :
			    //_fmemcpy(&task.FDT,&p2[1],sizeof task.FDT);
			    memcpy(&task.FDT,&p2[1],sizeof task.FDT);
			    break;
			  case FLDTZN :  // Zeitzonenoffset einlesen
			    if (p2[1] < 128)
			      tzn = 15 * p2[1];
			    else
			      tzn = 15 * (p2[1] - 256);
			    break;

			  case FLDTKF :
			    task.TKF.packed2unpacked(&p2[1]);
			    break;
			  case FLDSTA :
			    task.STA.packed2unpacked(&p2[1]);
			    break;
			  case FLDFIN :
			    task.FIN.packed2unpacked(&p2[1]);
			    break;
			  case FLDLDG :
			    task.LDG.packed2unpacked(&p2[1]);
			    break;
			  case FLDTP1 :
			    task.TP[0].packed2unpacked(&p2[1]);
			    break;
			  case FLDTP2 :
			    task.TP[1].packed2unpacked(&p2[1]);
			    break;
			  case FLDTP3 :
			    task.TP[2].packed2unpacked(&p2[1]);
			    break;
			  case FLDTP4 :
			    task.TP[3].packed2unpacked(&p2[1]);
			    break;
			  case FLDTP5 :
			    task.TP[4].packed2unpacked(&p2[1]);
			    break;
			  case FLDTP6 :
			    task.TP[5].packed2unpacked(&p2[1]);
			    break;
			  case FLDTP7 :
			    task.TP[6].packed2unpacked(&p2[1]);
			    break;
			  case FLDTP8 :
			    task.TP[7].packed2unpacked(&p2[1]);
			    break;
			  case FLDTP9 :
			    task.TP[8].packed2unpacked(&p2[1]);
			    break;
			  case FLDTP10 :
			    task.TP[9].packed2unpacked(&p2[1]);
			    break;
			  case FLDTP11 :
			    task.TP[10].packed2unpacked(&p2[1]);
			    break;
			  case FLDTP12 :
			    task.TP[11].packed2unpacked(&p2[1]);
			    break;

			  case FLDPLT1 :  // Pilotenname einlesen
			  case FLDPLT2 :  // Pilotenname einlesen
			  case FLDPLT3 :  // Pilotenname einlesen
			  case FLDPLT4 :  // Pilotenname einlesen
//			    _fmemcpy(igcheader.PLT, &p2[1], (sizeof igcheader.PLT));
//			    igcheader.PLT[(sizeof igcheader.PLT)-1] = 0;
			    //_fmemcpy(PILOT, &p2[1], (sizeof PILOT));
			    memcpy(PILOT, &p2[1], (sizeof PILOT));
			    PILOT[(sizeof PILOT)-1] = 0;
			    strcat(igcheader.PLT,PILOT);
			    if (igcfile_version < 413) // war in alten Dateien so !
			      strcat(igcheader.PLT," ");
			    break;
			  case FLDGTY :  // Flugzeugtyp einlesen
			    //_fmemcpy(igcheader.GTY, &p2[1], (sizeof igcheader.GTY));
			    memcpy(igcheader.GTY, &p2[1], (sizeof igcheader.GTY));
			    igcheader.GTY[(sizeof igcheader.GTY)-1] = 0;
			    break;
			  case FLDGID :  // Flugzeugkennzeichen einlesen
			    //_fmemcpy(igcheader.GID, &p2[1], (sizeof igcheader.GID));
			    memcpy(igcheader.GID, &p2[1], (sizeof igcheader.GID));
			    igcheader.GID[(sizeof igcheader.GID)-1] = 0;
			    break;
			  case FLDCCL :  // Wettbewerbsklasse einlesen
			    //_fmemcpy(igcheader.CCL, &p2[1], (sizeof igcheader.CCL));
			    memcpy(igcheader.CCL, &p2[1], (sizeof igcheader.CCL));
			    igcheader.CCL[(sizeof igcheader.CCL)-1] = 0;
			    break;
			  case FLDCID :  // Wettbewerbskennzeichen einlesen
			    //_fmemcpy(igcheader.CID, &p2[1], (sizeof igcheader.CID));
			    memcpy(igcheader.CID, &p2[1], (sizeof igcheader.CID));
			    igcheader.CID[(sizeof igcheader.CID)-1] = 0;
			    break;
			  case FLDHDR :  // Seriennummer und anderes einlesen
			    // Public-Key erst mal löschen
			    // 19.10.99 weggemacht, weil schon in main vorhanden
			    //dsa_y_b[0] = 2; dsa_y_b[1] = 0;
			    //memset(&dsa_y_b[2],0,(sizeof dsa_y_b)-2);

					*serno = (256L*p2[1]+p2[2]);

			    // sonstiges einlesen
			    strcpy(igcheader.A,wordtoserno(*serno));

			    sprintf(igcheader.DTM,"%03u",p2[3]);
			    sprintf(igcheader.RHW,"%0X.%0X",p2[4]>>4,(p2[4]&0xf));
			    sprintf(igcheader.RFW,"%0X.%0X",p2[5]>>4,(p2[5]&0xf));
			    sprintf(igcheader.FXA,"%03u",p2[7]);

			    // neuer obligatorischer H-Record
			    if (igcfile_version >= 421)
			      sprintf(igcheader.FTY,"GARRECHT INGENIEURGESELLSCHAFT,VOLKSLOGGER 1.0");
			    break;
			};
			break;

      default	      : ende = 1;
			break;
    }
    p += l;
  } while (!ende);

  pl = p - bin_puffer;


  // Zeitzone/Stunden = floor (LON+7.5°) / 15° des 1. gültigen Fixes
  ftz = ftz + 450000L;
  ftz = ftz / 900000L;
  task.zz_min = int(60 * floor(ftz));
//  printf("theoretische Zeitzone = UTC %-d min\n",task.zz_min);
//  getch();





  // bei neuen Dateien
  if ( (igcfile_version >= 420) && (igcfile_version<422) )

    // falls kein TZN-Feld existierte
    if (tzn == 4000)
      // dieses durch das errechnete emulieren
      tzn = task.zz_min;

  // bei allen Dateien
  // TZN anzeigen, wenn (auf welche Weise auch immer) gesetzt
  if (tzn != 4000) {
    tzh = abs(tzn) / 60;
    tzm = abs(tzn) % 60;
    sprintf(igcheader.TZN,"UTC%c%02d:%02d",(tzn<0 ? '-':'+'),tzh,tzm);
  }

  //JMWTODO  strftime(igcheader.DTE,sizeof(igcheader.DTE),"%d%m%y",&firsttime);
  igcheader.output(igcfile_version,oo_fillin);


  if ( igcfile_version >= 414 || (task.STA.koord.lat != 0) || (task.STA.koord.lon != 0) ) {
    if (decl_time >= 0) {
      task.hasdeclaration = 1;
      memcpy(&task.TDECL, &firsttime, sizeof task.TDECL);
      task.TDECL.tm_sec += decl_time %3600;
      task.TDECL.tm_hour += decl_time /3600;
	  task.TDECL.tm_isdst = -1;
          ////JMW TODO      mktime(&task.TDECL);
      task.print(igcfile_version,Ausgabedatei);
    }
  }


  igcfix.lat = 0;
  igcfix.lon = 0;



  realtime = firsttime;
  ende = 0;
  p = bin_puffer;
  do {
    Haupttyp = p[0] & rectyp_msk;
    switch(Haupttyp) {
      case rectyp_sep : l = 1;
			if (bfv > max_bfv) {
			  ende = 1;
			  l = 0;
			  break;
			}
			break;
      case 0xC0       : l = 1;
			break;
      case rectyp_pos :
      case rectyp_poc :	if (p[2] & 0x80) { // Endebedingung
			  ende = 1;
			  l = 0;
			  break;
			}
			time_relative += p[2];
			realtime.tm_sec += p[2];
			realtime.tm_isdst = -1;
                        ////JMW TODO			mktime(&realtime);
			igcfix.valid = ((p[0] & 0x10) >> 4) ? 'A' : 'V';
			igcfix.press =  ((word)p[0] & 0x0f) << 8
				       | p[1];
			if (Haupttyp == rectyp_pos) {
			  l = pos_ds_size[bfv][0];
			  igcfix.lat   =   ((unsigned long)p[3] & 0x7f) << 16
					 | ((unsigned long)p[4]       ) << 8
					 | p[5];
			  if (p[3] & 0x80)
			    igcfix.lat = -igcfix.lat;

			  igcfix.lon   =   ((unsigned long)p[6] ) << 16
					 | ((unsigned long)p[7] ) << 8
					 | p[8];
			  if (p[9] & 0x80)
			    igcfix.lon = -igcfix.lon;

			  igcfix.gpalt =  ((word)p[9] & 0x70) << 4
					 | p[10];
			  igcfix.fxa = hdop2fxa(p[9] & 0x0f);
			  igcfix.enl = 4*p[11];
			}

			else {
			  l = pos_ds_size[bfv][1];
			  delta_lat = (((unsigned long)p[3] & 0x07) << 8) | p[4];
			  if (p[3] & 0x80)
			    delta_lat = -delta_lat;
			  delta_lon = (((unsigned long)p[3] & 0x78) << 5) | p[5];
			  if (p[6] & 0x80)
			    delta_lon = -delta_lon;

			  igcfix.lat += delta_lat;
			  igcfix.lon += delta_lon;
			  igcfix.gpalt =  ((word)p[6] & 0x70) << 4
					 | p[7];
			  igcfix.fxa = hdop2fxa(p[6] & 0x0f);
			  igcfix.enl = 4*p[8];
			}
			igcfix.latdeg = labs(igcfix.lat) / 60000;
			igcfix.latmin = labs(igcfix.lat) % 60000;
			igcfix.londeg = labs(igcfix.lon) / 60000;
			igcfix.lonmin = labs(igcfix.lon) % 60000;

			igcfix.gps_alt = 10L * igcfix.gpalt - 1000L;

			if (igcfile_version >= 423)
			  igcfix.enl = enlflt(igcfix.enl);
			igcfix.enl = enllim(igcfix.enl);

			// Bei allen neuen Dateien auf Wunsch von IAN
			// aber dank neuer Regeln ab
			// Konverter Nr. 4.20 nicht mehr !!
			if ( (igcfile_version >= 413) && (igcfile_version < 420) )
			  if (igcfix.valid == 'V')
			    igcfix.gps_alt = 0;

			igcfix.pressure_alt = pressure2altitude(igcfix.press);

                        //JMWTODO			strftime(igcfix.time,sizeof(igcfix.time),"%H%M%S",&realtime);
			fprintf(Ausgabedatei,"B%6s%02u%05u%c%03u%05u%c%c%05ld%05ld%03u",
			      igcfix.time,
			      igcfix.latdeg, igcfix.latmin,
			      ((igcfix.lat<0) ? 'S':'N'),
			      igcfix.londeg, igcfix.lonmin,
			      ((igcfix.lon<0) ? 'W':'E'),
			      igcfix.valid,
			      igcfix.pressure_alt,
			      igcfix.gps_alt,
			      igcfix.fxa
			);

			if ( // erst bei ENL im I-Record aktivieren
			// waren irrtümlich schon mal aktiv
			(igcfile_version >= 413) && (igcfile_version <416))
			  fprintf(Ausgabedatei,"999");
			// müssen auf jeden Fall aktiv sein, wenn Sensor da
			if (strcmp(igcheader.RHW,"3.3")>=0)
			  fprintf(Ausgabedatei,"%03u",igcfix.enl);

			fprintf(Ausgabedatei,"\n");
			break;

      case rectyp_vrb :
      case rectyp_vrt : l = p[1];
			switch(Haupttyp) {
			  case rectyp_vrb : p2 = p+2; break;
			  case rectyp_vrt : realtime.tm_sec += p[2];
						realtime.tm_isdst = -1;
                                                ////JMW TODO						mktime(&realtime);
					    p2 = p+3; break;
			  default	  : p2 = p; break;
			}
			Untertyp = (p2[0]);
			switch (Untertyp) {
			case FLDEPEV : //JMWTODO strftime(igcfix.time,sizeof(igcfix.time),"%H%M%S",&realtime);
				       fprintf(Ausgabedatei,"E%6sPEVEVENTBUTTON PRESSED\n",igcfix.time);
				       break;
			case FLDETKF : //JMWTODO strftime(igcfix.time,sizeof(igcfix.time),"%H%M%S",&realtime);
				       fprintf(Ausgabedatei,"LGCSTKF%6sTAKEOFF DETECTED\n",igcfix.time);
				       break;
			};
			break;
     case rectyp_tnd :  realtime.tm_sec += p[1];
			realtime.tm_isdst = -1;
                        //JMW//JMW TODO		    mktime(&realtime);
			l = 8;
			break;

     default 	     :  ende = 1;
			l = 0;
			break;
    }
    p += l;
  } while (!ende);
  return pl;
}