apps/garminusb2nmea-0.12a/exifgen.c

Go to the documentation of this file.
00001 /*
00002 exifgen.c
00003    Garmin protocol to Exif GPS data conevrter
00004    exif_getutc() function is based on nmea_getutc(), found in
00005    nmeagen.c:
00006         Garmin protocol to NMEA 0183 converter
00007         Copyright (C) 2004 Manuel Kasper <mk@neon1.net>.
00008         All rights reserved.
00009 
00010 */
00011 
00012 #include "garmin.h"
00013 #include "nmeagen.h"
00014 #include "exifgen.h"
00015 
00016 #include <math.h>
00017 #include <stdio.h>
00018 #include <string.h>
00019 
00020 void exif_init_meta(struct meta_GPSInfo_t *meta) {
00021    meta->GPSLatitudeRef=       'N';
00022    meta->GPSLatitude_deg_nom=   __cpu_to_be32((int) 0);
00023    meta->GPSLatitude_deg_denom= __cpu_to_be32((int) 1);
00024    meta->GPSLatitude_min_nom=   __cpu_to_be32((int) 0);
00025    meta->GPSLatitude_min_denom= __cpu_to_be32((int) EXIF_GPS_MIN_DENOM);
00026    meta->GPSLongitudeRef=      'W';
00027    meta->GPSLongitude_deg_nom=  __cpu_to_be32((int) 0);
00028    meta->GPSLongitude_deg_denom=__cpu_to_be32((int) 1);
00029    meta->GPSLongitude_min_nom=  __cpu_to_be32((int) 0);
00030    meta->GPSLongitude_min_denom=__cpu_to_be32((int) EXIF_GPS_MIN_DENOM);
00031    meta->GPSAltitudeRef=        0; //byte, not ascii 0 - above sea level, 1 - below
00032    meta->GPSAltitude_nom=       __cpu_to_be32((int) 0);   //in meters
00033    meta->GPSAltitude_denom=     __cpu_to_be32((int) EXIF_GPS_METERS_DENOM);
00034    meta->GPSTimeStamp_hrs_nom=  __cpu_to_be32((int) 0);
00035    meta->GPSTimeStamp_hrs_denom=__cpu_to_be32((int) 1);
00036    meta->GPSTimeStamp_min_nom=  __cpu_to_be32((int) 0);
00037    meta->GPSTimeStamp_min_denom=__cpu_to_be32((int) 1);
00038    meta->GPSTimeStamp_sec_nom=  __cpu_to_be32((int) 0);
00039    meta->GPSMeasureMode=        '0';
00040    meta->GPSTimeStamp_sec_denom=__cpu_to_be32((int) EXIF_GPS_TIMESEC_DENOM);
00041 // meta->GPSDateStamp[10]; //1 less than defined - no '\0';
00042 
00043 }
00044 
00045 void exif_getutc(D800_Pvt_Data_Type *pvt,  struct meta_GPSInfo_t *meta) { // char *utctime, char *utcdate) {
00046    int      tmp = 0, dtmp=0;
00047    int      frac_sec;
00048    /* UTC time of position fix 
00049       Reminder:
00050          pvt->tow = seconds (including fractions) since the start of the week.
00051          pvt->wn_days = days since 31-DEC-1989 for the start of the current week
00052            (neither is adjusted for leap seconds)
00053          pvt->leap_scnds = leap second adjustment required.
00054    */
00055    tmp = (pvt->tow + 0.5/EXIF_GPS_TIMESEC_DENOM);
00056    frac_sec = ((pvt->tow + 0.5/EXIF_GPS_TIMESEC_DENOM) - tmp)*EXIF_GPS_TIMESEC_DENOM +0.5;
00057 
00058    dtmp = pvt->wn_days;
00059 
00060    /* 
00061       If the result is 604800, it's really the first sample
00062       of the new week, so zero out tmp and increment dtmp 
00063       by a week ( 7 days ).
00064    */
00065    if (tmp >= 604800)   
00066    {
00067       dtmp += 7;
00068       tmp = 0;
00069    }
00070    /*
00071       At this point we have tmp = seconds since the start
00072       of the week, and dtmp = the first day of the week.
00073       We now need to correct for leap seconds.  This may actually
00074       result in reversing the previous adjustment but the code
00075       required to combine the two operations wouldn't be clear.
00076    */
00077    tmp -= pvt->leap_scnds;
00078    if (tmp < 0)
00079    {
00080       tmp+= 604800;
00081       dtmp -= 7;
00082    }
00083 
00084    /*
00085       Now we have tmp = seconds since the start if the week, 
00086       and dtmp = the first day of the week, all corrected for
00087       rounding and leap seconds.
00088 
00089       We now convert dtmp to today's day number and tmp to
00090       seconds since midnignt. 
00091    */
00092 
00093    dtmp += (tmp / 86400);
00094    tmp %= 86400;
00095 // calculate time
00096    int h, m, s;
00097    h = tmp / 3600;
00098    m = (tmp - h*3600) / 60;
00099    s = ((tmp - h*3600 - m*60) * EXIF_GPS_TIMESEC_DENOM)+frac_sec;
00100 
00101    meta->GPSTimeStamp_hrs_nom=  __cpu_to_be32((int) h);
00102    meta->GPSTimeStamp_min_nom=  __cpu_to_be32((int) m);
00103    meta->GPSTimeStamp_sec_nom=  __cpu_to_be32((int) s);
00104 
00105       /* Garmin format: number of days since December 31, 1989 */
00106    unsigned long jd = dtmp + 2447892;
00107    unsigned long w, x, a, b, c, d, e, f;
00108    unsigned long day, month, year;
00109 
00110    w = (unsigned long)((jd - 1867216.25)/36524.25);
00111    x = w/4;
00112    a = jd + 1 + w - x;
00113    b = a + 1524;
00114    c = (unsigned long)((b - 122.1)/365.25);
00115    d = (unsigned long)(365.25 * c);
00116    e = (unsigned long)((b-d)/30.6001);
00117    f = (unsigned long)(30.6001 * e);
00118 
00119    day = b - d - f;
00120    month = e - 1;
00121    if (month > 12)                month -= 12;
00122    year = c - 4716;
00123    if (month == 1 || month == 2)  year++;
00124 //   year -= 2000;
00125    sprintf(meta->GPSDateStamp, "%04ld:%02ld:%02ld", year, month,day);
00126 }
00127 
00128 
00129 int exif_gen(D800_Pvt_Data_Type *pvt, cpo_sat_data *sat, struct meta_GPSInfo_t *meta) {
00130    int deg,m_scaled;
00131    exif_getutc( pvt, meta);
00132    meta->GPSMeasureMode= (pvt->fix >= 4)?'3':'2'; // '0' is not allowed
00134    m_scaled=rad2deg(pvt->lat)*60*EXIF_GPS_MIN_DENOM +0.5;
00135    meta->GPSLatitudeRef= (m_scaled >=0)?'N':'S';
00136    if (m_scaled<0) m_scaled=-m_scaled;
00137    deg     = m_scaled/(60*EXIF_GPS_MIN_DENOM);
00138    m_scaled -= deg*(60*EXIF_GPS_MIN_DENOM);
00139    meta->GPSLatitude_deg_nom=   __cpu_to_be32(deg);
00140    meta->GPSLatitude_min_nom=   __cpu_to_be32(m_scaled);
00142    m_scaled=rad2deg(pvt->lon)*60*EXIF_GPS_MIN_DENOM +0.5;
00143    meta->GPSLongitudeRef= (m_scaled >=0)?'E':'W';
00144    if (m_scaled<0) m_scaled=-m_scaled;
00145    deg     = m_scaled/(60*EXIF_GPS_MIN_DENOM);
00146    m_scaled -= deg*(60*EXIF_GPS_MIN_DENOM);
00147    meta->GPSLongitude_deg_nom=   __cpu_to_be32(deg);
00148    meta->GPSLongitude_min_nom=   __cpu_to_be32(m_scaled);
00150    m_scaled= (pvt->msl_hght + pvt->alt)*EXIF_GPS_METERS_DENOM +0.5;
00151    meta->GPSAltitudeRef= (m_scaled >=0)? 0 : 1;
00152    if (m_scaled<0) m_scaled=-m_scaled;
00153    meta->GPSAltitude_nom=       __cpu_to_be32(m_scaled);   //in meters
00154    return 0;
00155 }
00156 

Generated on Fri Nov 28 00:06:21 2008 for elphel by  doxygen 1.5.1