[Turn] Android Hal layer GPS research summary
2011-09-22
A fast run may not win, a competitive battle may not win, a smart one may not win food, or a wise one may not win money, or a flexible one may not be excited. What came to the world was the opportunity.
In my life, if the twilight grass. /Eclair/hardware/libhardware_legacy/include/hardware_legacy/GPS. h
Typedef struct {
? ? /** Contains gpslocationflags bits .*/
? ? Uint16_t? ? ? ? Flags;
? ? /** Represents latitude in degrees .*/
? ? Double? ? ? ? ? Latitude;
? ? /** Represents longpolling in degrees .*/
? ? Double? ? ? ? ? Longpolling;
? ? /** Represents altitude in meters above the WGS 84 reference
? ? ? * Ellipsoid .*/
? ? Double? ? ? ? ? Altitude;
? ? /** Represents speed in meters per second .*/
? ? Float? ? ? ? ? Speed;
? ? /** Represents heading in degrees .*/
? ? Float? ? ? ? ? Bearing;
? ? /** Represents expected accuracy in meters .*/
? ? Float? ? ? ? ? Accuracy;
? ? /** Timestamp for the location fix .*/
? ? Gpsutctime? ? ? Timestamp;
} Gpslocation;
?
Flags is the identifier
# Define gps_location_has_lat_long? 0x0001 ,? When the bit0 value of flags is 1, the ID position information includes the longitude and latitude information.
/** Gpslocation has valid altitude .*/
# Define gps_location_has_altitude? 0x0002. When the bit1 value of flags is 1, the status information of the flag has a height. The following identifiers are similar.
/** Gpslocation has valid speed .*/
# Define gps_location_has_speed? ? ? Zero X 0004
/** Gpslocation has valid bearing .*/
# Define gps_location_has_bearing? ? Zero X 0008
/** Gpslocation has valid accuracy .*/
# Define gps_location_has_accuracy? Zero X 0010
Typedef void (* gps_status_callback) (gpsstatus * status );
You can use this function to submit the identification information.
Timestamp
Is a 64-bit unsigned integer. It defines the number of seconds from 00:00:00 on January 1, January 01, 1970 to the present in UTC. However, in Android Java, the date function must input a millisecond value, but the decimal value is second, so it must be multiplied by 1000.
Bearing
Corresponding to 8th data disconnections (from 0) of RMC. Course over ground)
Typedef struct {
? ? ? ? /** Number of SVS currently visible .*/
? ? ? ? Int? ? ? ? Num_svs;
? ? ? ? /** Contains an array of SV information .*/
? ? ? ? Gpssvinfo? Sv_list [gps_max_svs];
? ? ? ? /** Represents a bit mask indicating which SVS
? ? ? ? ? * Have ephemeris data.
? ? ? ? ? */
? ? ? ? Uint32_t? ? Ephemeris_mask;
? ? ? ? /** Represents a bit mask indicating which SVS
? ? ? ? ? * Have almanac data.
? ? ? ? ? */
? ? ? ? Uint32_t? ? Almanac_mask;
? ? ? ? /**
? ? ? ? ? * Represents a bit mask indicating which SVS
? ? ? ? ? * Were used for computing the most recent position fix.
? ? ? ? ? */
? ? ? ? Uint32_t? ? Used_in_fix_mask;
} Gpssvstatus;
?
Used_in_fix_mask
If you receive the following datagram ¥ gpgsa, A, 2.8, 1.5, 2.3, * 38
? ? ? 07, 19 ,? 08 ?, 03 ?, ? 16, 11 ,? 06 is a valid Satellite Number (PRN)Used_in_fix_mask
Bit? 6 ?, 18 ,? 7? , 2 ?, ? 15 ?, 10 ,? 5? It is 1, and the other bits are 0. (bit0 is also 0)
Ephemeris_mask, almanac_mask
These two masks are closely related to GSV information.
For example, the following information is received. (In order to facilitate data parsing, I have added a new line)
¥ Gpgsv, 3,1, 11,
19,79, 359,30 ,?
, 22,
, 46,
, 40, * 7b
Satellite No. (PRN ),
¥Gpgsv, 3,2, 11,
11,37, 180 ,,
, 29,
16,30, 050,35,
, 27, * 7A
Satellite Number (PRN ),
¥Gpgsv, 3,3, 11,
24, 17, 178 ,,
319,
28, 31, 02,133, * 4C
Satellite No. (PRN) 24, 08, 28
The BIT (, 22,10, 5, 15, 06,? , 07, 27) Is 1, and other bits are 0 (bit starts from 0th bits ),
The value of the mask is closely related to the Satellite Number.
In short, you must have a deep understanding of the data structure of the company.
Post the first code: eclair/hardware/libhardware_legacy/GPS/gps_qemu.c
Welcome to exchange.
<pre name="code" class="cpp">static voidnmea_reader_parse( NmeaReader* r ){D("%s,%d,%s",__FILE__,__LINE__,__FUNCTION__); /* we received a complete sentence, now parse it to generate * a new GPS fix... */ NmeaTokenizer tzer[1]; Token tok; D("Received: ""%.*s""", r->pos, r->in); if (r->pos < 9) { D("Too short. discarded."); return; } nmea_tokenizer_init(tzer, r->in, r->in + r->pos);#if GPS_DEBUG { int n; for (n = 0; n < tzer->count; n++) { Token tok = nmea_tokenizer_get(tzer,n); } }#endif tok = nmea_tokenizer_get(tzer, 0); if (tok.p + 5 > tok.end) { return; } /* ignore first two characters.*/ tok.p += 2; if ( !memcmp(tok.p, "GGA", 3) ) { /* GPS fix */D("may%s,%d,%s,gGA",__FILE__,__LINE__,__FUNCTION__); Token tok_time = nmea_tokenizer_get(tzer,1); Token tok_latitude = nmea_tokenizer_get(tzer,2); Token tok_latitudeHemi = nmea_tokenizer_get(tzer,3); Token tok_longitude = nmea_tokenizer_get(tzer,4); Token tok_longitudeHemi = nmea_tokenizer_get(tzer,5); Token tok_altitude = nmea_tokenizer_get(tzer,9); Token tok_altitudeUnits = nmea_tokenizer_get(tzer,10); nmea_reader__time(r, tok_time); nmea_reader__latlong(r, tok_latitude, tok_latitudeHemi.p[0], tok_longitude, tok_longitudeHemi.p[0]); nmea_reader__altitude(r, tok_altitude, tok_altitudeUnits); }else if ( !memcmp(tok.p, "GLL", 3) ) { Token tok_fixstaus = nmea_tokenizer_get(tzer,6); if (tok_fixstaus.p[0] == ""A"") { Token tok_latitude = nmea_tokenizer_get(tzer,1); Token tok_latitudeHemi = nmea_tokenizer_get(tzer,2); Token tok_longitude = nmea_tokenizer_get(tzer,3); Token tok_longitudeHemi = nmea_tokenizer_get(tzer,4); Token tok_time = nmea_tokenizer_get(tzer,5); nmea_reader__time(r, tok_time); nmea_reader__latlong(r, tok_latitude, tok_latitudeHemi.p[0], tok_longitude, tok_longitudeHemi.p[0]); } } #ifdef Svpnd_Version else if ( !memcmp(tok.p, "GSV", 3) ) {D("may%s,%d,%s,gsV",__FILE__,__LINE__,__FUNCTION__); Token tok_noSatellites = nmea_tokenizer_get(tzer, 3); int noSatellites = str2int(tok_noSatellites.p, tok_noSatellites.end); D("%d,inview=%d,",__LINE__,noSatellites); if (noSatellites > 0) { Token tok_noSentences = nmea_tokenizer_get(tzer, 1); Token tok_sentence = nmea_tokenizer_get(tzer, 2); int sentence = str2int(tok_sentence.p, tok_sentence.end); int totalSentences = str2int(tok_noSentences.p, tok_noSentences.end); D("%d,gsv_index=%d,gsv_total=%d",__LINE__,sentence,totalSentences); int curr; int i; if (sentence == 1) {D("msg_index=%d",sentence); // r->sv_status_changed = 0; r->sv_status.num_svs = 0;r->sv_status.ephemeris_mask=0ul;r->sv_status.almanac_mask=0ul; } curr = r->sv_status.num_svs; i = 0; while (i < 4 && r->sv_status.num_svs < noSatellites){ Token tok_prn = nmea_tokenizer_get(tzer, i * 4 + 4); Token tok_elevation = nmea_tokenizer_get(tzer, i * 4 + 5); Token tok_azimuth = nmea_tokenizer_get(tzer, i * 4 + 6); Token tok_snr = nmea_tokenizer_get(tzer, i * 4 + 7); r->sv_status.sv_list[curr].prn = str2int(tok_prn.p, tok_prn.end); r->sv_status.sv_list[curr].elevation = str2float(tok_elevation.p, tok_elevation.end); r->sv_status.sv_list[curr].azimuth = str2float(tok_azimuth.p, tok_azimuth.end); r->sv_status.sv_list[curr].snr = str2float(tok_snr.p, tok_snr.end); r->sv_status.ephemeris_mask|=(1ul << (r->sv_status.sv_list[curr].prn-1));r->sv_status.almanac_mask|=(1ul << (r->sv_status.sv_list[curr].prn-1)); r->sv_status.num_svs += 1; D("**********curr=%d",curr); D("%d,prn=%d:snr=%f",__LINE__,r->sv_status.sv_list[curr].prn,r->sv_status.sv_list[curr].snr); curr += 1; i += 1; } if (sentence == totalSentences) {D("msg=%d,msgindex=%d",totalSentences,sentence); #ifdef Svpnd_Versionr->callback.sv_status_cb=_gps_state->callbacks.sv_status_cb; if (r->sv_status_changed !=0) { if (r->callback.sv_status_cb) {#if GPS_DEBUGD("%d,SV_STATSU,change=%d",__LINE__,r->sv_status_changed);int nums=r->sv_status.num_svs;D("num_svs=%d,emask=%x,amask=%x,inusemask=%x",r->sv_status.num_svs,r->sv_status.ephemeris_mask,r->sv_status.almanac_mask,r->sv_status.used_in_fix_mask);D("************88");while(nums){nums--;D("prn=%d:snr=%f",r->sv_status.sv_list[nums].prn,r->sv_status.sv_list[nums].snr);}D("************88");#endif r->callback.sv_status_cb( &(r->sv_status) ); r->sv_status_changed = 0; }else { D("no callback, keeping status data until needed !"); } } #endif } D("%s: GSV message with total satellites %d", __FUNCTION__, noSatellites); } } #endif else if ( !memcmp(tok.p, "GSA", 3) ) { #ifdef Svpnd_Version /* do something ? */ {D("may%s,%d,%s,gsa",__FILE__,__LINE__,__FUNCTION__); Token tok_fixStatus = nmea_tokenizer_get(tzer, 2); int i; if (tok_fixStatus.p[0] != """" && tok_fixStatus.p[0] != ""1"") { Token tok_accuracy = nmea_tokenizer_get(tzer, 15);//position dilution of precision dop nmea_reader__accuracy(r, tok_accuracy); r->sv_status.used_in_fix_mask = 0ul;D(""); for (i = 3; i <= 14; ++i){ Token tok_prn = nmea_tokenizer_get(tzer, i); int prn = str2int(tok_prn.p, tok_prn.end);D("gsa,prn=%d,",prn); if (prn > 0){ r->sv_status.used_in_fix_mask |= (1ul << ( prn-1)); r->sv_status_changed = 1; } }D(""); D("%s: fix mask is %x", __FUNCTION__, r->sv_status.used_in_fix_mask); // D(" [log hit][%s:%d] fix.flags=0 x%x ", __FUNCTION__, __LINE__, r->fix.flags); } D(" [log hit][%s:%d] fix.flags=0 x%x ", __FUNCTION__, __LINE__, r->fix.flags); } #endif /* do something ? */ } else if ( !memcmp(tok.p, "RMC", 3) ) { Token tok_time = nmea_tokenizer_get(tzer,1); Token tok_fixStatus = nmea_tokenizer_get(tzer,2); Token tok_latitude = nmea_tokenizer_get(tzer,3); Token tok_latitudeHemi = nmea_tokenizer_get(tzer,4); Token tok_longitude = nmea_tokenizer_get(tzer,5); Token tok_longitudeHemi = nmea_tokenizer_get(tzer,6); Token tok_speed = nmea_tokenizer_get(tzer,7); Token tok_bearing = nmea_tokenizer_get(tzer,8); Token tok_date = nmea_tokenizer_get(tzer,9); D("in RMC, fixStatus=%c", tok_fixStatus.p[0]); if (tok_fixStatus.p[0] == ""A"") { nmea_reader__date( r, tok_date, tok_time ); nmea_reader__latlong( r, tok_latitude, tok_latitudeHemi.p[0], tok_longitude, tok_longitudeHemi.p[0] ); nmea_reader__bearing( r, tok_bearing ); nmea_reader__speed ( r, tok_speed ); #ifdef Svpnd_Versionr->callback.location_cb=_gps_state->callbacks.location_cb;r->callback.nmea_cb=_gps_state->callbacks.nmea_cb;r->callback.status_cb=_gps_state->callbacks.status_cb;if (r->callback.status_cb) {D("report,status,flags=%d",r->fix.flags); r->callback.status_cb( (struct GpsStatus *)&(r->fix.flags) ); } if (r->callback.location_cb) {D("location_cb report:r->fix.flags=%d,r->latitude=%f,r->longitude=%f,r->altitude=%f,r->speed=%f,r->bearing=%f,r->accuracy=%f",r->fix.flags,r->fix.latitude,r->fix.longitude,r->fix.altitude,r->fix.speed,r->fix.bearing,r->fix.accuracy); r->callback.location_cb( &r->fix );D("%d,cc=%d",__LINE__,cc);r->fix.flags = 0; }if (r->callback.nmea_cb) {D("report,timestamp=%llx,%llu",r->fix.timestamp,r->fix.timestamp); r->callback.nmea_cb( r->fix.timestamp,r->in,r->pos ); } #elser->callback=_gps_state.callbacks->location_cb;//r->callback.nmea_cb=_gps_state->callbacks.nmea_cb; if (r->callback) {D("if2 (r->callback.location_cb)"); r->callback( &r->fix ); r->fix.flags = 0; } #endif } } else if ( !memcmp(tok.p, "VTG", 3) ) { Token tok_fixStatus = nmea_tokenizer_get(tzer,9); if (tok_fixStatus.p[0] != """" && tok_fixStatus.p[0] != ""N"") { Token tok_bearing = nmea_tokenizer_get(tzer,1); Token tok_speed = nmea_tokenizer_get(tzer,5); nmea_reader__bearing( r, tok_bearing ); nmea_reader__speed ( r, tok_speed ); } } else if ( !memcmp(tok.p, "ZDA", 3) ) { Token tok_time; Token tok_year = nmea_tokenizer_get(tzer,4); if (tok_year.p[0] != """") { Token tok_day = nmea_tokenizer_get(tzer,2); Token tok_mon = nmea_tokenizer_get(tzer,3); nmea_reader__cdate( r, tok_day, tok_mon, tok_year ); } tok_time = nmea_tokenizer_get(tzer,1); if (tok_time.p[0] != """") nmea_reader__time(r, tok_time); } else { tok.p -= 2; D("unknown sentence ""%.*s", tok.end-tok.p, tok.p); }D("%s,%d,",__FILE__,__LINE__); if (r->fix.flags!=0) {#if GPS_DEBUGD("%d,flags=%d",__LINE__,r->fix.flags); char temp[256]; char* p = temp; char* end = p + sizeof(temp); struct tm utc; p += snprintf( p, end-p, "sending fix" ); if (r->fix.flags & GPS_LOCATION_HAS_LAT_LONG) { p += snprintf(p, end-p, " lat=%g lon=%g", r->fix.latitude, r->fix.longitude); } if (r->fix.flags & GPS_LOCATION_HAS_ALTITUDE) { p += snprintf(p, end-p, " altitude=%g", r->fix.altitude); } if (r->fix.flags & GPS_LOCATION_HAS_SPEED) { p += snprintf(p, end-p, " speed=%g", r->fix.speed); } if (r->fix.flags & GPS_LOCATION_HAS_BEARING) { p += snprintf(p, end-p, " bearing=%g", r->fix.bearing); } if (r->fix.flags & GPS_LOCATION_HAS_ACCURACY) { p += snprintf(p,end-p, " accuracy=%g", r->fix.accuracy); } gmtime_r( (time_t*) &r->fix.timestamp, &utc ); p += snprintf(p, end-p, " time=%s", asctime( &utc ) ); D(temp);//added by mayzhang for debugD("******************************1%s,%d:%s,may callback***************************",__FILE__,__LINE__,__FUNCTION__);#endifD("******************************2%s,%d:%s,may callback***************************",__FILE__,__LINE__,__FUNCTION__); } else { /* D("no callback, keeping data until needed !"); */ } }