using System; using Microsoft.SPOT; namespace CPF { public class RawDegrees { public uint _billionths; public uint _deg; public bool _negative; public RawDegrees() { _deg = 0; _billionths = 0; _negative = false; } } public class NMEA_Location { private const byte _PERIOD = (byte)'.'; private const byte _ZERO = (byte)'0'; private bool _valid; private bool _updated; public RawDegrees _rawLatData; public RawDegrees _rawLngData; public RawDegrees _rawNewLatData; public RawDegrees _rawNewLngData; private long _lastCommitTime; public void SetLatitude(ByteString s) { ParseDegrees(s, ref _rawNewLatData); } public void SetLongitude(ByteString s) { ParseDegrees(s, ref _rawNewLngData); } public void Commit() { _rawLatData = _rawNewLatData; _rawLngData = _rawNewLngData; _lastCommitTime = Utils.MillisecondsSinceLastReboot(); _valid = true; _updated = true; } public bool IsValid() { return _valid; } public bool IsUpdated() { return _updated; } public long Age() { return _valid ? Utils.MillisecondsSinceLastReboot() - _lastCommitTime : Conversions.MAX_SIGNED; } public RawDegrees RawLat() { _updated = false; return _rawLatData; } public RawDegrees RawLng() { _updated = false; return _rawLngData; } public double Lat() { _updated = false; double value = _rawLatData._deg + (_rawLatData._billionths / 1000000000.0); return _rawLatData._negative ? -value : value; } public double Lng() { _updated = false; double value = _rawLngData._deg + (_rawLngData._billionths / 1000000000.0); return _rawLngData._negative ? -value : value; } // Parse degrees in that funny NMEA format DDMM.MMMM public void ParseDegrees(ByteString s, ref RawDegrees d) { uint leftOfDecimal = (uint)Conversions.ByteStringToInteger(s); uint minutes = (uint)(leftOfDecimal % 100); uint multiplier = 10000000; long tenMillionthsOfMinutes = minutes * multiplier; d._deg = leftOfDecimal / 100; while (Conversions.IsDigit(s.Deref())) s.Advance(1); if (s.Deref() == _PERIOD) while (Conversions.IsDigit(s.DerefPreInc())) { multiplier /= 10; tenMillionthsOfMinutes += (s.Deref() - _ZERO) * multiplier; } d._billionths = (uint)(5 * tenMillionthsOfMinutes + 1) / 3; d._negative = false; } public NMEA_Location() { _valid = false; _updated = false; _lastCommitTime = 0; _rawLatData = new RawDegrees(); _rawLngData = new RawDegrees(); _rawNewLatData = new RawDegrees(); _rawNewLngData = new RawDegrees(); } } }