Renderer, ...: use PixelRect::GetCenter()
[xcsoar.git] / src / Device / Driver / BlueFlyVario.cpp
blobe043c4961c19cd59d25a925054c4228791a61883
1 /*
2 Copyright_License {
4 XCSoar Glide Computer - http://www.xcsoar.org/
5 Copyright (C) 2000-2012 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 "Device/Driver/BlueFlyVario.hpp"
25 #include "Device/Driver.hpp"
26 #include "Math/KalmanFilter1d.hpp"
27 #include "NMEA/Info.hpp"
29 #include <stdlib.h>
31 class BlueFlyDevice : public AbstractDevice {
32 public:
33 BlueFlyDevice();
35 void LinkTimeout() override;
37 virtual bool ParseNMEA(const char *line, struct NMEAInfo &info);
39 bool ParseBAT(const char *content, NMEAInfo &info);
40 bool ParsePRS(const char *content, NMEAInfo &info);
41 private:
42 KalmanFilter1d kalman_filter;
45 void
46 BlueFlyDevice::LinkTimeout()
48 kalman_filter.Reset();
51 bool
52 BlueFlyDevice::ParseBAT(const char *content, NMEAInfo &info)
54 // e.g.
55 // BAT 1234
57 char *endptr;
58 int mV = (int)strtol(content, &endptr, 16);
59 if (endptr == content) return true;
61 do {
62 // piecewise linear approximation
63 if (mV > 3900) {
64 info.battery_level = fixed(70 + (mV - 3900)/10);
65 break;
67 if (mV > 3700) {
68 info.battery_level = fixed(4 + (mV - 3700)/3);
69 break;
71 if (mV > 3600) {
72 info.battery_level = fixed(0.04) * (mV - 3600);
73 break;
75 // considered empty ...
76 info.battery_level = fixed(0);
77 break;
78 } while (0);
80 if (info.battery_level > fixed(100)) info.battery_level = fixed(100);
81 info.battery_level_available.Update(info.clock);
83 return true;
86 gcc_pure
87 static inline
88 fixed ComputeNoncompVario(const fixed pressure, const fixed d_pressure)
90 static constexpr fixed FACTOR(-2260.389548275485);
91 static constexpr fixed EXPONENT(-0.8097374740609689);
92 return fixed(FACTOR * pow(pressure, EXPONENT) * d_pressure);
95 bool
96 BlueFlyDevice::ParsePRS(const char *content, NMEAInfo &info)
98 // e.g. PRS 17CBA
100 char *endptr;
101 long value = strtol(content, &endptr, 16);
102 if (endptr != content) {
103 AtmosphericPressure pressure = AtmosphericPressure::Pascal(fixed(value));
105 kalman_filter.Update(pressure.GetHectoPascal(), fixed(0.25), fixed(0.02));
107 info.ProvideNoncompVario(ComputeNoncompVario(kalman_filter.GetXAbs(),
108 kalman_filter.GetXVel()));
109 info.ProvideStaticPressure(AtmosphericPressure::HectoPascal(kalman_filter.GetXAbs()));
112 return true;
115 bool
116 BlueFlyDevice::ParseNMEA(const char *line, NMEAInfo &info)
118 if (memcmp(line, "PRS ", 4) == 0)
119 return ParsePRS(line + 4, info);
120 else if (memcmp(line, "BAT ", 4) == 0)
121 return ParseBAT(line + 4, info);
122 else
123 return false;
126 BlueFlyDevice::BlueFlyDevice()
128 kalman_filter.SetAccelerationVariance(fixed(0.3));
132 static Device *
133 BlueFlyCreateOnPort(const DeviceConfig &config, Port &com_port)
135 return new BlueFlyDevice();
138 const struct DeviceRegister bluefly_driver = {
139 _T("BlueFly"),
140 _T("BlueFly Vario"),
142 BlueFlyCreateOnPort,