Build: add GCC-13, Clang-14, Clang-15, Clang-16, Clang-17
[marnav.git] / src / marnav / ais / message_01.cpp
blob46d95757f12cb2df1834fcd76f1dd058bbb7dcba
1 #include <marnav/ais/message_01.hpp>
2 #include <marnav/ais/angle.hpp>
3 #include <cmath>
5 namespace marnav::ais
7 constexpr message_id message_01::ID;
8 constexpr std::size_t message_01::SIZE_BITS;
10 message_01::message_01()
11 : message_01(ID)
15 message_01::message_01(message_id id)
16 : message(id)
20 message_01::message_01(const raw & bits)
21 : message_01(ID)
23 if (bits.size() != SIZE_BITS)
24 throw std::invalid_argument{"invalid number of bits in ais/message_01"};
25 read_data(bits);
28 std::optional<geo::longitude> message_01::get_lon() const
30 if (longitude_minutes_ == longitude_not_available)
31 return std::make_optional<geo::longitude>();
32 return to_geo_longitude(longitude_minutes_, longitude_minutes_.count, angle_scale::I4);
35 std::optional<geo::latitude> message_01::get_lat() const
37 if (latitude_minutes_ == latitude_not_available)
38 return std::make_optional<geo::latitude>();
39 return to_geo_latitude(latitude_minutes_, latitude_minutes_.count, angle_scale::I4);
42 void message_01::set_lon_unavailable()
44 longitude_minutes_ = longitude_not_available;
47 void message_01::set_lat_unavailable()
49 latitude_minutes_ = latitude_not_available;
52 void message_01::set_lon(const geo::longitude & t)
54 longitude_minutes_ = to_longitude_minutes(t, longitude_minutes_.count, angle_scale::I4);
57 void message_01::set_lat(const geo::latitude & t)
59 latitude_minutes_ = to_latitude_minutes(t, latitude_minutes_.count, angle_scale::I4);
62 std::optional<units::knots> message_01::get_sog() const noexcept
64 // ignores special value of 1022 = 102.2 knots or faster
66 if (sog_ == sog_not_available)
67 return {};
68 return units::knots{0.1 * sog_};
71 void message_01::set_sog_unavailable()
73 sog_ = sog_not_available;
76 void message_01::set_sog(units::velocity t)
78 if (t.value() < 0.0)
79 throw std::invalid_argument{"SOG less than zero"};
81 const auto v = t.get<units::knots>();
82 sog_ = std::min(sog_max, static_cast<uint32_t>(round(v * 10).value()));
85 /// Returns course over ground in degrees true north.
86 std::optional<double> message_01::get_cog() const noexcept
88 if (cog_ == cog_not_available)
89 return {};
90 return 0.1 * cog_;
93 void message_01::set_cog(std::optional<double> t) noexcept
95 cog_ = !t ? cog_not_available : static_cast<uint32_t>(std::round(*t / 0.1));
98 /// Returns heading in degrees.
99 std::optional<uint32_t> message_01::get_hdg() const noexcept
101 if (hdg_ == hdg_not_available)
102 return {};
103 return {hdg_};
106 void message_01::set_hdg(std::optional<uint32_t> t) noexcept
108 hdg_ = !t ? hdg_not_available : *t;
111 rate_of_turn message_01::get_rot() const noexcept
113 return rate_of_turn(rot_);
116 void message_01::set_rot(rate_of_turn t) noexcept
118 rot_ = t.raw();
121 void message_01::read_data(const raw & bits)
123 get(bits, repeat_indicator_);
124 get(bits, mmsi_);
125 get(bits, nav_status_);
126 get(bits, rot_);
127 get(bits, sog_);
128 get(bits, position_accuracy_);
129 get(bits, longitude_minutes_);
130 get(bits, latitude_minutes_);
131 get(bits, cog_);
132 get(bits, hdg_);
133 get(bits, timestamp_);
134 get(bits, maneuver_indicator_);
135 get(bits, raim_);
136 get(bits, radio_status_);
139 raw message_01::get_data() const
141 raw bits(SIZE_BITS);
143 bits.set(type(), 0, 6);
144 set(bits, repeat_indicator_);
145 set(bits, mmsi_);
146 set(bits, nav_status_);
147 set(bits, rot_);
148 set(bits, sog_);
149 set(bits, position_accuracy_);
150 set(bits, longitude_minutes_);
151 set(bits, latitude_minutes_);
152 set(bits, cog_);
153 set(bits, hdg_);
154 set(bits, timestamp_);
155 set(bits, maneuver_indicator_);
156 set(bits, raim_);
157 set(bits, radio_status_);
159 return bits;