LEcture GPS Xbee sous interruption

Committer:
pascalreygner
Date:
Thu Aug 09 09:30:22 2018 +0000
Revision:
3:9a24090ff482
Parent:
2:824735b4c3a3
BUG

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pascalreygner 0:0a05d691ce34 1 /* Gestion carte GPS au format XBEE
pascalreygner 0:0a05d691ce34 2 * fournisseur : Embedded Artists
pascalreygner 0:0a05d691ce34 3 * Réf : EA-ACC-023
pascalreygner 0:0a05d691ce34 4 * utilise Chipset MT3339 (Mediatek Labs)
pascalreygner 0:0a05d691ce34 5 */
pascalreygner 0:0a05d691ce34 6
pascalreygner 0:0a05d691ce34 7 #include <gps-ea-acc023.h>
pascalreygner 0:0a05d691ce34 8 #include "mbed.h"
pascalreygner 0:0a05d691ce34 9 #include <stdlib.h>
pascalreygner 0:0a05d691ce34 10 #include <stdio.h>
pascalreygner 0:0a05d691ce34 11
pascalreygner 0:0a05d691ce34 12 using namespace gpsxbee_MT3339;
pascalreygner 0:0a05d691ce34 13 static GpsXbee gpsxbee;
pascalreygner 0:0a05d691ce34 14 RawSerial gps_uart(P4_22, P4_23);
pascalreygner 0:0a05d691ce34 15
pascalreygner 0:0a05d691ce34 16 void GpsXbee::GpsXbeeInit(void)
pascalreygner 0:0a05d691ce34 17 {
pascalreygner 0:0a05d691ce34 18 NmeaSentence = NMEA_INVALID;
pascalreygner 1:fba6b514d8d7 19 gpsTrameRMC = TRAME_WAIT;
pascalreygner 1:fba6b514d8d7 20 gpsTrameGGA = TRAME_WAIT;
pascalreygner 0:0a05d691ce34 21 gpsState = StateStartGps;
pascalreygner 0:0a05d691ce34 22 gpsBufPos =0;
pascalreygner 0:0a05d691ce34 23
pascalreygner 0:0a05d691ce34 24 gps_uart.baud(9600);
pascalreygner 0:0a05d691ce34 25 gps_uart.attach(this,&GpsXbee::lecture,gps_uart.RxIrq);
pascalreygner 0:0a05d691ce34 26 }
pascalreygner 0:0a05d691ce34 27
pascalreygner 0:0a05d691ce34 28 GpsXbee::~GpsXbee()
pascalreygner 0:0a05d691ce34 29 {
pascalreygner 0:0a05d691ce34 30 gps_uart.attach(NULL);// bloque IRQ réception GPS
pascalreygner 0:0a05d691ce34 31
pascalreygner 0:0a05d691ce34 32 }
pascalreygner 0:0a05d691ce34 33
pascalreygner 0:0a05d691ce34 34 void GpsXbee::InitRMC(void)
pascalreygner 0:0a05d691ce34 35 {
pascalreygner 0:0a05d691ce34 36 rmc_hours =0;
pascalreygner 0:0a05d691ce34 37 rmc_minutes =0;
pascalreygner 0:0a05d691ce34 38 rmc_seconds =0;
pascalreygner 0:0a05d691ce34 39 rmc_milliseconds =0;
pascalreygner 0:0a05d691ce34 40 rmc_warning = 'V';
pascalreygner 0:0a05d691ce34 41 rmc_latitude =0;
pascalreygner 0:0a05d691ce34 42 rmc_longitude =0;
pascalreygner 0:0a05d691ce34 43 rmc_nsIndicator = 'N';
pascalreygner 0:0a05d691ce34 44 rmc_ewIndicator = 'W';
pascalreygner 0:0a05d691ce34 45 rmc_speedKnots =0;
pascalreygner 0:0a05d691ce34 46 rmc_jours =0 ;
pascalreygner 0:0a05d691ce34 47 rmc_mois =0 ;
pascalreygner 0:0a05d691ce34 48 rmc_ans =0 ;
pascalreygner 0:0a05d691ce34 49 }
pascalreygner 0:0a05d691ce34 50
pascalreygner 0:0a05d691ce34 51 void GpsXbee::InitGGA(void)
pascalreygner 0:0a05d691ce34 52 {
pascalreygner 0:0a05d691ce34 53 gga_hours = 0;
pascalreygner 0:0a05d691ce34 54 gga_minutes = 0;
pascalreygner 0:0a05d691ce34 55 gga_seconds = 0;
pascalreygner 0:0a05d691ce34 56 gga_milliseconds = 0;
pascalreygner 0:0a05d691ce34 57 gga_latitude = 0;
pascalreygner 0:0a05d691ce34 58 gga_longitude = 0;
pascalreygner 0:0a05d691ce34 59 gga_nsIndicator = 0;
pascalreygner 0:0a05d691ce34 60 gga_ewIndicator = 0;
pascalreygner 0:0a05d691ce34 61 gga_fix = 0;
pascalreygner 0:0a05d691ce34 62 gga_satellites = 0;
pascalreygner 0:0a05d691ce34 63 gga_hdop = 0;
pascalreygner 0:0a05d691ce34 64 gga_altitude = 0;
pascalreygner 0:0a05d691ce34 65 gga_geoidal = 0;
pascalreygner 0:0a05d691ce34 66 }
pascalreygner 0:0a05d691ce34 67
pascalreygner 0:0a05d691ce34 68 void GpsXbee::lecture(void) // réception d'un caractère - analyse trame
pascalreygner 0:0a05d691ce34 69 {
pascalreygner 0:0a05d691ce34 70 char car=0;
pascalreygner 0:0a05d691ce34 71 if((LPC_UART2->LSR & 0x01)==1) { // solution si getc fonctionne pas
pascalreygner 0:0a05d691ce34 72 car = LPC_UART2->RBR;
pascalreygner 0:0a05d691ce34 73 // if(gps_uart -> readable() == 1) {
pascalreygner 0:0a05d691ce34 74 // d = gps_uart -> getc(); // lecture caractère reçu
pascalreygner 0:0a05d691ce34 75 switch(gpsState) {
pascalreygner 0:0a05d691ce34 76 case StateStartGps:
pascalreygner 0:0a05d691ce34 77 if (car == '$') {
pascalreygner 0:0a05d691ce34 78 gpsBuf[0] = '$';
pascalreygner 0:0a05d691ce34 79 gpsBufPos = 1;
pascalreygner 0:0a05d691ce34 80 gpsState = StateDataGps;
pascalreygner 0:0a05d691ce34 81 }
pascalreygner 0:0a05d691ce34 82 break;
pascalreygner 0:0a05d691ce34 83 case StateDataGps:
pascalreygner 0:0a05d691ce34 84 if (gpsBufPos >= MTK3339_BUF_SZ) { // erreur trame
pascalreygner 0:0a05d691ce34 85 gpsState = StateStartGps;
pascalreygner 1:fba6b514d8d7 86 gpsTrameRMC = TRAME_ERR;
pascalreygner 1:fba6b514d8d7 87 gpsTrameGGA = TRAME_ERR;
pascalreygner 0:0a05d691ce34 88 } else if (car == '\r') { // fin de trame
pascalreygner 0:0a05d691ce34 89 gpsBuf[gpsBufPos] = 0;
pascalreygner 0:0a05d691ce34 90 gpsState = StateStartGps;
pascalreygner 0:0a05d691ce34 91 parseData(gpsBuf, gpsBufPos); // analyse trame
pascalreygner 0:0a05d691ce34 92
pascalreygner 0:0a05d691ce34 93 if (NmeaSentence == NmeaRmc ) { // décodage trame type "RMC"
pascalreygner 0:0a05d691ce34 94 if (rmc_warning == 'A') { // si données GPS valables : les afficher
pascalreygner 2:824735b4c3a3 95 sprintf(gpsDataRMC,"%.2i/%.2i/%.2i:%.2iH%.2imn%.2is - Lat. = %f%c - Long. = %f%c",rmc_jours,rmc_mois,rmc_ans,rmc_hours,rmc_minutes,rmc_seconds,getLatitudeAsDegrees(rmc_latitude,rmc_nsIndicator),rmc_nsIndicator,getLongitudeAsDegrees(rmc_longitude,rmc_ewIndicator),rmc_ewIndicator);
pascalreygner 1:fba6b514d8d7 96 gpsTrameRMC = TRAME_OK; // Trame complète OK
pascalreygner 1:fba6b514d8d7 97
pascalreygner 0:0a05d691ce34 98 } else {
pascalreygner 2:824735b4c3a3 99 sprintf(gpsDataRMC,"NMEARMC : %.2i/%.2i/%.2i:%.2iH%.2imn%.2is --- Valeurs GPS incorrectes",rmc_jours,rmc_mois,rmc_ans,rmc_hours,rmc_minutes,rmc_seconds);
pascalreygner 0:0a05d691ce34 100 }
pascalreygner 0:0a05d691ce34 101 }
pascalreygner 0:0a05d691ce34 102 /* pour afficher les autres protocoles */
pascalreygner 1:fba6b514d8d7 103 else if (NmeaSentence == NmeaGga) { // décodage trame type "RMC"
pascalreygner 1:fba6b514d8d7 104 if (gga_fix == 1) {// si données GPS valables : les afficher
pascalreygner 2:824735b4c3a3 105 sprintf(gpsDataGGA,"%.2iH%.2imn%.2is --- Latitude = %f%c --- Longitude = %f%c - Nb sat = %i",gga_hours,gga_minutes,gga_seconds,getLatitudeAsDegrees(gga_latitude,gga_nsIndicator),gga_nsIndicator,getLongitudeAsDegrees(gga_longitude,gga_ewIndicator),gga_ewIndicator,gga_satellites);
pascalreygner 1:fba6b514d8d7 106 gpsTrameGGA = TRAME_OK; // Trame complète OK
pascalreygner 1:fba6b514d8d7 107 } else
pascalreygner 2:824735b4c3a3 108 sprintf(gpsDataGGA,"NMEAGGA : %.2iH%.2imn%.2is --- Valeurs GPS incorrectes",gga_hours,gga_minutes,gga_seconds);
pascalreygner 1:fba6b514d8d7 109 } // pour les autres types (VTG/GGA/GSV) affiche uniquement la trame reçue
pascalreygner 2:824735b4c3a3 110 else memcpy(gpsDataRMC,gpsBuf,sizeof(gpsBuf));
pascalreygner 0:0a05d691ce34 111 } else {
pascalreygner 0:0a05d691ce34 112 gpsBuf[gpsBufPos++] = car; // enregistre caractère suivant de la trame
pascalreygner 0:0a05d691ce34 113 }
pascalreygner 0:0a05d691ce34 114 break;
pascalreygner 0:0a05d691ce34 115 }
pascalreygner 0:0a05d691ce34 116 }
pascalreygner 0:0a05d691ce34 117 }
pascalreygner 0:0a05d691ce34 118
pascalreygner 0:0a05d691ce34 119
pascalreygner 0:0a05d691ce34 120 /*
pascalreygner 0:0a05d691ce34 121 $GPRMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,ddmmyy,x.x,a*hh
pascalreygner 0:0a05d691ce34 122 1 = UTC of position fix
pascalreygner 0:0a05d691ce34 123 2 = Data status (V=navigation receiver warning)
pascalreygner 0:0a05d691ce34 124 3 = Latitude of fix
pascalreygner 0:0a05d691ce34 125 4 = N or S
pascalreygner 0:0a05d691ce34 126 5 = Longitude of fix
pascalreygner 0:0a05d691ce34 127 6 = E or W
pascalreygner 0:0a05d691ce34 128 7 = Speed over ground in knots
pascalreygner 0:0a05d691ce34 129 8 = Track made good in degrees True
pascalreygner 0:0a05d691ce34 130 9 = UT date
pascalreygner 0:0a05d691ce34 131 10 = Magnetic variation degrees (Easterly var. subtracts from true course)
pascalreygner 0:0a05d691ce34 132 11 = E or W
pascalreygner 0:0a05d691ce34 133 12 = Checksum
pascalreygner 0:0a05d691ce34 134 */
pascalreygner 0:0a05d691ce34 135 void GpsXbee::parseRMC(char* data, int dataLen)
pascalreygner 0:0a05d691ce34 136 {
pascalreygner 0:0a05d691ce34 137 double tm = 0;
pascalreygner 0:0a05d691ce34 138 char* p = data;
pascalreygner 0:0a05d691ce34 139 int pos = 0;
pascalreygner 0:0a05d691ce34 140
pascalreygner 0:0a05d691ce34 141 InitRMC();
pascalreygner 0:0a05d691ce34 142
pascalreygner 0:0a05d691ce34 143 p = strchr(p, ',');
pascalreygner 0:0a05d691ce34 144 while (p != NULL && *p != 0) {
pascalreygner 0:0a05d691ce34 145 p++;
pascalreygner 0:0a05d691ce34 146
pascalreygner 0:0a05d691ce34 147 switch(pos) {
pascalreygner 0:0a05d691ce34 148 case 0: // time: hhmmss.ss (heure GMT)
pascalreygner 0:0a05d691ce34 149 tm = strtod(p, NULL);
pascalreygner 0:0a05d691ce34 150 rmc_hours = (int)(tm / 10000);
pascalreygner 0:0a05d691ce34 151 rmc_hours+=2; // remise à l'heure d'été Paris
pascalreygner 0:0a05d691ce34 152 if (rmc_hours == 24) rmc_hours = 0;
pascalreygner 0:0a05d691ce34 153 if (rmc_hours == 25) rmc_hours = 1;
pascalreygner 0:0a05d691ce34 154 rmc_minutes = ((int)tm % 10000) / 100;
pascalreygner 0:0a05d691ce34 155 rmc_seconds = ((int)tm % 100);
pascalreygner 0:0a05d691ce34 156 rmc_milliseconds = (int)(tm * 100) % 100;
pascalreygner 0:0a05d691ce34 157 break;
pascalreygner 0:0a05d691ce34 158 case 1: // V = warning
pascalreygner 0:0a05d691ce34 159 rmc_warning = *p;
pascalreygner 0:0a05d691ce34 160 break;
pascalreygner 0:0a05d691ce34 161 case 2: // latitude: ddmm.mmmm
pascalreygner 0:0a05d691ce34 162 rmc_latitude = strtod(p, NULL);
pascalreygner 0:0a05d691ce34 163 break;
pascalreygner 0:0a05d691ce34 164 case 3: // N/S indicator (north or south)
pascalreygner 0:0a05d691ce34 165 if (*p == 'N' || *p == 'S') {
pascalreygner 0:0a05d691ce34 166 rmc_nsIndicator = *p;
pascalreygner 0:0a05d691ce34 167 } else rmc_nsIndicator = '?';
pascalreygner 0:0a05d691ce34 168 break;
pascalreygner 0:0a05d691ce34 169 case 4: // longitude: dddmm.mm
pascalreygner 0:0a05d691ce34 170 rmc_longitude = strtod(p, NULL);
pascalreygner 0:0a05d691ce34 171 break;
pascalreygner 0:0a05d691ce34 172 case 5: // E/W indicator (east or west)
pascalreygner 0:0a05d691ce34 173 if (*p == 'E' || *p == 'W') {
pascalreygner 0:0a05d691ce34 174 rmc_ewIndicator = *p;
pascalreygner 0:0a05d691ce34 175 } else rmc_ewIndicator = '?';
pascalreygner 0:0a05d691ce34 176 break;
pascalreygner 0:0a05d691ce34 177 case 6: // speed in knots
pascalreygner 0:0a05d691ce34 178 rmc_speedKnots = strtod(p, NULL);
pascalreygner 0:0a05d691ce34 179 break;
pascalreygner 0:0a05d691ce34 180 case 7: // ?
pascalreygner 0:0a05d691ce34 181 break;
pascalreygner 0:0a05d691ce34 182 case 8: // Date : ddmmyy
pascalreygner 0:0a05d691ce34 183 tm = strtod(p, NULL);
pascalreygner 0:0a05d691ce34 184 rmc_jours = (int)(tm / 10000);
pascalreygner 0:0a05d691ce34 185 rmc_mois = ((int)tm % 10000) / 100;
pascalreygner 0:0a05d691ce34 186 rmc_ans = ((int)tm % 100);
pascalreygner 0:0a05d691ce34 187 break;
pascalreygner 0:0a05d691ce34 188 }
pascalreygner 0:0a05d691ce34 189 pos++;
pascalreygner 0:0a05d691ce34 190 p = strchr(p, ',');
pascalreygner 0:0a05d691ce34 191 }
pascalreygner 0:0a05d691ce34 192 }
pascalreygner 0:0a05d691ce34 193
pascalreygner 0:0a05d691ce34 194 void GpsXbee::parseGGA(char* data, int dataLen)
pascalreygner 0:0a05d691ce34 195 {
pascalreygner 0:0a05d691ce34 196 //http://aprs.gids.nl/nmea/#gga
pascalreygner 0:0a05d691ce34 197
pascalreygner 0:0a05d691ce34 198 double tm = 0;
pascalreygner 0:0a05d691ce34 199
pascalreygner 0:0a05d691ce34 200 InitGGA();
pascalreygner 0:0a05d691ce34 201
pascalreygner 0:0a05d691ce34 202 char* p = data;
pascalreygner 0:0a05d691ce34 203 int pos = 0;
pascalreygner 0:0a05d691ce34 204
pascalreygner 0:0a05d691ce34 205 p = strchr(p, ',');
pascalreygner 0:0a05d691ce34 206 while (p != NULL && *p != 0) {
pascalreygner 0:0a05d691ce34 207 p++;
pascalreygner 0:0a05d691ce34 208
pascalreygner 0:0a05d691ce34 209 switch(pos) {
pascalreygner 0:0a05d691ce34 210 case 0: // time: hhmmss.sss
pascalreygner 0:0a05d691ce34 211 tm = strtod(p, NULL);
pascalreygner 0:0a05d691ce34 212 gga_hours = (int)(tm / 10000);
pascalreygner 0:0a05d691ce34 213 gga_minutes = ((int)tm % 10000) / 100;
pascalreygner 0:0a05d691ce34 214 gga_seconds = ((int)tm % 100);
pascalreygner 0:0a05d691ce34 215 gga_milliseconds = (int)(tm * 1000) % 1000;
pascalreygner 0:0a05d691ce34 216 break;
pascalreygner 0:0a05d691ce34 217 case 1: // latitude: ddmm.mmmm
pascalreygner 0:0a05d691ce34 218 gga_latitude = strtod(p, NULL);
pascalreygner 0:0a05d691ce34 219 break;
pascalreygner 0:0a05d691ce34 220 case 2: // N/S indicator (north or south)
pascalreygner 0:0a05d691ce34 221 if (*p == 'N' || *p == 'S') {
pascalreygner 0:0a05d691ce34 222 gga_nsIndicator = *p;
pascalreygner 0:0a05d691ce34 223 }
pascalreygner 0:0a05d691ce34 224 break;
pascalreygner 0:0a05d691ce34 225 case 3: // longitude: dddmm.mmmm
pascalreygner 0:0a05d691ce34 226 gga_longitude = strtod(p, NULL);
pascalreygner 0:0a05d691ce34 227 break;
pascalreygner 0:0a05d691ce34 228 case 4: // E/W indicator (east or west)
pascalreygner 0:0a05d691ce34 229 if (*p == 'E' || *p == 'W') {
pascalreygner 0:0a05d691ce34 230 gga_ewIndicator = *p;
pascalreygner 0:0a05d691ce34 231 }
pascalreygner 0:0a05d691ce34 232 break;
pascalreygner 0:0a05d691ce34 233 case 5: // position indicator (1=no fix, 2=GPS fix, 3=Differential)
pascalreygner 0:0a05d691ce34 234 gga_fix = strtol(p, NULL, 10);
pascalreygner 0:0a05d691ce34 235 break;
pascalreygner 0:0a05d691ce34 236 case 6: // num satellites
pascalreygner 0:0a05d691ce34 237 gga_satellites = strtol(p, NULL, 10);
pascalreygner 0:0a05d691ce34 238 break;
pascalreygner 0:0a05d691ce34 239 case 7: // hdop
pascalreygner 0:0a05d691ce34 240 gga_hdop = strtod(p, NULL);
pascalreygner 0:0a05d691ce34 241 break;
pascalreygner 0:0a05d691ce34 242 case 8: // altitude
pascalreygner 0:0a05d691ce34 243 gga_altitude = strtod(p, NULL);
pascalreygner 0:0a05d691ce34 244 break;
pascalreygner 0:0a05d691ce34 245 case 9: // units
pascalreygner 0:0a05d691ce34 246 // ignore units
pascalreygner 0:0a05d691ce34 247 break;
pascalreygner 0:0a05d691ce34 248 case 10: // geoidal separation
pascalreygner 0:0a05d691ce34 249 gga_geoidal = strtod(p, NULL);
pascalreygner 0:0a05d691ce34 250 break;
pascalreygner 0:0a05d691ce34 251 }
pascalreygner 0:0a05d691ce34 252 pos++;
pascalreygner 0:0a05d691ce34 253
pascalreygner 0:0a05d691ce34 254 p = strchr(p, ',');
pascalreygner 0:0a05d691ce34 255 }
pascalreygner 0:0a05d691ce34 256
pascalreygner 0:0a05d691ce34 257 }
pascalreygner 0:0a05d691ce34 258
pascalreygner 0:0a05d691ce34 259 int GpsXbee::parseData(char* data, int len)
pascalreygner 0:0a05d691ce34 260 {
pascalreygner 0:0a05d691ce34 261 // verify checksum
pascalreygner 0:0a05d691ce34 262 if (len < 3 || (len > 3 && data[len-3] != '*')) { // invalid data
pascalreygner 0:0a05d691ce34 263 return(-1);
pascalreygner 0:0a05d691ce34 264 }
pascalreygner 0:0a05d691ce34 265 int sum = strtol(&data[len-2], NULL, 16);
pascalreygner 0:0a05d691ce34 266 for(int i = 1; i < len-3; i++) {
pascalreygner 0:0a05d691ce34 267 sum ^= data[i];
pascalreygner 0:0a05d691ce34 268 }
pascalreygner 0:0a05d691ce34 269 if (sum != 0) {
pascalreygner 0:0a05d691ce34 270 return(-1);
pascalreygner 0:0a05d691ce34 271 }
pascalreygner 0:0a05d691ce34 272
pascalreygner 0:0a05d691ce34 273 NmeaSentence = NMEA_INVALID;
pascalreygner 0:0a05d691ce34 274 if (strncmp("$GPGGA", data, 6) == 0 ) {
pascalreygner 0:0a05d691ce34 275 parseGGA(data,len);
pascalreygner 0:0a05d691ce34 276 NmeaSentence = NmeaGga;
pascalreygner 0:0a05d691ce34 277 }
pascalreygner 0:0a05d691ce34 278
pascalreygner 0:0a05d691ce34 279 else if (strncmp("$GPRMC", data, 6) == 0) {
pascalreygner 0:0a05d691ce34 280 parseRMC(data, len);
pascalreygner 0:0a05d691ce34 281 NmeaSentence = NmeaRmc;
pascalreygner 0:0a05d691ce34 282 }
pascalreygner 0:0a05d691ce34 283
pascalreygner 0:0a05d691ce34 284 return(0);
pascalreygner 0:0a05d691ce34 285 }
pascalreygner 0:0a05d691ce34 286
pascalreygner 0:0a05d691ce34 287 double GpsXbee::getLatitudeAsDegrees(double l,char ns)
pascalreygner 0:0a05d691ce34 288 {
pascalreygner 0:0a05d691ce34 289 // convert from ddmm.mmmm to degrees only
pascalreygner 0:0a05d691ce34 290 // 60 minutes is 1 degree
pascalreygner 0:0a05d691ce34 291
pascalreygner 0:0a05d691ce34 292 int deg = (int)(l / 100);
pascalreygner 0:0a05d691ce34 293 l = (l - deg*100.0) / 60.0;
pascalreygner 0:0a05d691ce34 294 l = deg + l;
pascalreygner 0:0a05d691ce34 295 if (ns == 'S') l = -l;
pascalreygner 0:0a05d691ce34 296
pascalreygner 0:0a05d691ce34 297 return l;
pascalreygner 0:0a05d691ce34 298 }
pascalreygner 0:0a05d691ce34 299
pascalreygner 0:0a05d691ce34 300 double GpsXbee::getLongitudeAsDegrees(double l,char ew)
pascalreygner 0:0a05d691ce34 301 {
pascalreygner 0:0a05d691ce34 302 // convert from ddmm.mmmm to degrees only
pascalreygner 0:0a05d691ce34 303 // 60 minutes is 1 degree
pascalreygner 0:0a05d691ce34 304
pascalreygner 0:0a05d691ce34 305 int deg = (int)(l / 100);
pascalreygner 0:0a05d691ce34 306 l = (l - deg*100) / 60;
pascalreygner 0:0a05d691ce34 307 l = deg + l;
pascalreygner 0:0a05d691ce34 308 if (ew == 'W') l = -l;
pascalreygner 0:0a05d691ce34 309
pascalreygner 0:0a05d691ce34 310 return l;
pascalreygner 0:0a05d691ce34 311 }
pascalreygner 0:0a05d691ce34 312