4 XCSoar Glide Computer - http://www.xcsoar.org/
5 Copyright (C) 2000-2013 The XCSoar Project
6 A detailed list of copyright holders can be found in the file "AUTHORS".
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include "NMEA/Info.hpp"
25 #include "OS/Clock.hpp"
26 #include "Atmosphere/AirDensity.hpp"
31 fix_quality
= FixQuality::NO_FIX
;
32 fix_quality_available
.Clear();
36 android_internal_gps
= false;
38 satellites_used_available
.Clear();
39 satellite_ids_available
.Clear();
44 GPSState::Expire(fixed now
)
46 if (fix_quality_available
.Expire(now
, fixed(5)))
47 fix_quality
= FixQuality::NO_FIX
;
49 satellites_used_available
.Expire(now
, fixed(5));
50 satellite_ids_available
.Expire(now
, fixed(60));
54 NMEAInfo::UpdateClock()
56 clock
= fixed(MonotonicClockMS()) / 1000;
60 NMEAInfo::GetDateTimeAt(fixed other_time
) const
62 if (negative(other_time
))
63 return BrokenDateTime::Invalid();
65 if (!time_available
|| !date_available
)
66 return BrokenDateTime(BrokenDate::Invalid(),
67 BrokenTime::FromSecondOfDayChecked(int(other_time
)));
69 return date_time_utc
+ int(other_time
- time
);
73 NMEAInfo::ProvideTime(fixed _time
)
75 assert(!negative(_time
));
78 time_available
.Update(clock
);
80 unsigned t
= (unsigned)_time
;
81 date_time_utc
.second
= t
% 60;
84 date_time_utc
.minute
= t
% 60;
87 date_time_utc
.hour
= t
% 24;
91 NMEAInfo::ProvideDate(const BrokenDate
&date
)
93 assert(date
.Plausible());
95 date_time_utc
.year
= date
.year
;
96 date_time_utc
.month
= date
.month
;
97 date_time_utc
.day
= date
.day
;
98 date_available
= true;
102 NMEAInfo::ProvideTrueAirspeedWithAltitude(fixed tas
, fixed altitude
)
105 indicated_airspeed
= true_airspeed
/ AirDensityRatio(altitude
);
106 airspeed_available
.Update(clock
);
107 airspeed_real
= true;
111 NMEAInfo::ProvideIndicatedAirspeedWithAltitude(fixed ias
, fixed altitude
)
113 indicated_airspeed
= ias
;
114 true_airspeed
= indicated_airspeed
* AirDensityRatio(altitude
);
115 airspeed_available
.Update(clock
);
116 airspeed_real
= true;
120 NMEAInfo::ProvideTrueAirspeed(fixed tas
)
122 auto any_altitude
= GetAnyAltitude();
124 if (any_altitude
.first
)
125 ProvideTrueAirspeedWithAltitude(tas
, any_altitude
.second
);
127 /* no altitude; dirty fallback */
128 ProvideBothAirspeeds(tas
, tas
);
132 NMEAInfo::ProvideIndicatedAirspeed(fixed ias
)
134 auto any_altitude
= GetAnyAltitude();
136 if (any_altitude
.first
)
137 ProvideIndicatedAirspeedWithAltitude(ias
, any_altitude
.second
);
139 /* no altitude; dirty fallback */
140 ProvideBothAirspeeds(ias
, ias
);
151 acceleration
.Reset();
154 location_available
.Clear();
156 track
= Angle::Zero();
157 track_available
.Clear();
159 ground_speed_available
.Clear();
160 airspeed_available
.Clear();
161 ground_speed
= true_airspeed
= indicated_airspeed
= fixed(0);
162 airspeed_real
= false;
164 gps_altitude_available
.Clear();
166 static_pressure_available
.Clear();
167 dyn_pressure_available
.Clear();
168 pitot_pressure_available
.Clear();
169 sensor_calibration_available
.Clear();
171 baro_altitude_available
.Clear();
172 baro_altitude
= fixed(0);
174 pressure_altitude_available
.Clear();
175 pressure_altitude
= fixed(0);
177 date_available
= false;
179 time_available
.Clear();
181 date_time_utc
.hour
= date_time_utc
.minute
= date_time_utc
.second
= 0;
183 noncomp_vario_available
.Clear();
184 total_energy_vario_available
.Clear();
185 netto_vario_available
.Clear();
189 external_wind_available
.Clear();
191 temperature_available
= false;
192 humidity_available
= false;
194 engine_noise_level_available
.Clear();
196 voltage_available
.Clear();
197 battery_level_available
.Clear();
199 switch_state
.Reset();
201 stall_ratio_available
.Clear();
206 secondary_device
.Clear();
211 NMEAInfo::ExpireWallClock()
219 if (gps
.android_internal_gps
)
220 /* the Android internal GPS does not expire */
224 alive
.Expire(clock
, fixed(10));
226 time_available
.Clear();
230 time_available
.Expire(clock
, fixed(10));
237 location_available
.Expire(clock
, fixed(10));
238 track_available
.Expire(clock
, fixed(10));
239 ground_speed_available
.Expire(clock
, fixed(10));
241 if (airspeed_available
.Expire(clock
, fixed(30)))
242 airspeed_real
= false;
244 gps_altitude_available
.Expire(clock
, fixed(30));
245 static_pressure_available
.Expire(clock
, fixed(30));
246 dyn_pressure_available
.Expire(clock
, fixed(30));
247 pitot_pressure_available
.Expire(clock
, fixed(30));
248 sensor_calibration_available
.Expire(clock
, fixed(3600));
249 baro_altitude_available
.Expire(clock
, fixed(30));
250 pressure_altitude_available
.Expire(clock
, fixed(30));
251 noncomp_vario_available
.Expire(clock
, fixed(5));
252 total_energy_vario_available
.Expire(clock
, fixed(5));
253 netto_vario_available
.Expire(clock
, fixed(5));
254 settings
.Expire(clock
);
255 external_wind_available
.Expire(clock
, fixed(600));
256 engine_noise_level_available
.Expire(clock
, fixed(30));
257 voltage_available
.Expire(clock
, fixed(300));
258 battery_level_available
.Expire(clock
, fixed(300));
261 attitude
.Expire(clock
);
265 NMEAInfo::Complement(const NMEAInfo
&add
)
268 /* if there is no heartbeat on the other object, there cannot be
269 useful information */
276 alive
.Complement(add
.alive
);
278 if (time_available
.Complement(add
.time_available
)) {
280 date_time_utc
= add
.date_time_utc
;
281 date_available
= add
.date_available
;
284 acceleration
.Complement(add
.acceleration
);
285 attitude
.Complement(add
.attitude
);
287 if (location_available
.Complement(add
.location_available
))
288 location
= add
.location
;
290 if (track_available
.Complement(add
.track_available
))
293 if (ground_speed_available
.Complement(add
.ground_speed_available
))
294 ground_speed
= add
.ground_speed
;
296 if ((add
.airspeed_real
|| !airspeed_real
) &&
297 airspeed_available
.Complement(add
.airspeed_available
)) {
298 true_airspeed
= add
.true_airspeed
;
299 indicated_airspeed
= add
.indicated_airspeed
;
300 airspeed_real
= add
.airspeed_real
;
303 if (gps_altitude_available
.Complement(add
.gps_altitude_available
))
304 gps_altitude
= add
.gps_altitude
;
306 if (static_pressure_available
.Complement(add
.static_pressure_available
))
307 static_pressure
= add
.static_pressure
;
309 if (dyn_pressure_available
.Complement(add
.dyn_pressure_available
))
310 dyn_pressure
= add
.dyn_pressure
;
312 if (pitot_pressure_available
.Complement(add
.pitot_pressure_available
))
313 pitot_pressure
= add
.pitot_pressure
;
315 if (sensor_calibration_available
.Complement(add
.sensor_calibration_available
)) {
316 sensor_calibration_factor
= add
.sensor_calibration_factor
;
317 sensor_calibration_offset
= add
.sensor_calibration_offset
;
320 if (baro_altitude_available
.Complement(add
.baro_altitude_available
))
321 baro_altitude
= add
.baro_altitude
;
323 if (pressure_altitude_available
.Complement(add
.pressure_altitude_available
))
324 pressure_altitude
= add
.pressure_altitude
;
326 if (noncomp_vario_available
.Complement(add
.noncomp_vario_available
))
327 noncomp_vario
= add
.noncomp_vario
;
329 if (total_energy_vario_available
.Complement(add
.total_energy_vario_available
))
330 total_energy_vario
= add
.total_energy_vario
;
332 if (netto_vario_available
.Complement(add
.netto_vario_available
))
333 netto_vario
= add
.netto_vario
;
335 settings
.Complement(add
.settings
);
337 if (external_wind_available
.Complement(add
.external_wind_available
))
338 external_wind
= add
.external_wind
;
340 if (!temperature_available
&& add
.temperature_available
) {
341 temperature
= add
.temperature
;
342 temperature_available
= add
.temperature_available
;
345 if (!humidity_available
&& add
.humidity_available
) {
346 humidity
= add
.humidity
;
347 humidity_available
= add
.humidity_available
;
350 if (voltage_available
.Complement(add
.voltage_available
))
351 voltage
= add
.voltage
;
353 if (battery_level_available
.Complement(add
.battery_level_available
))
354 battery_level
= add
.battery_level
;
356 switch_state
.Complement(add
.switch_state
);
358 if (!stall_ratio_available
&& add
.stall_ratio_available
)
359 stall_ratio
= add
.stall_ratio
;
361 flarm
.Complement(add
.flarm
);