Build: add GCC-13, Clang-14, Clang-15, Clang-16, Clang-17
[marnav.git] / src / marnav / seatalk / message_51.cpp
blobe9f0fa337a91828b2fa303a47511df5d001c81be
1 #include <marnav/seatalk/message_51.hpp>
2 #include <marnav/math/floatingpoint.hpp>
4 namespace marnav::seatalk
7 message_51::message_51()
8 : message(ID)
12 std::unique_ptr<message> message_51::parse(const raw & data)
14 check_size(data, SIZE);
16 std::unique_ptr<message> result = std::make_unique<message_51>();
17 auto & msg = static_cast<message_51 &>(*result);
19 // 51 Z2 XX YY YY
20 // raw 1 2 3 4
22 const uint32_t degrees = data[2];
23 uint32_t m = 0;
24 m += data[3];
25 m <<= 8;
26 m += data[4];
28 const uint32_t minutes = (m & 0x7fff) / 100;
29 const uint32_t seconds = (((m & 0x7fff) % 100) * 60) / 100;
30 const geo::longitude::hemisphere hemisphere
31 = (m & 0x8000) ? geo::longitude::hemisphere::east : geo::longitude::hemisphere::west;
33 msg.lon_ = geo::longitude{degrees, minutes, seconds, hemisphere};
35 // deliberately ignored 'Z'
37 return result;
40 raw message_51::get_data() const
42 uint16_t m = 0;
43 m += lon_.minutes() * 100;
44 m += math::float_cast<decltype(m)>((lon_.seconds() * 100) / 60);
45 if (lon_.hem() == geo::longitude::hemisphere::east)
46 m |= 0x8000;
48 return raw{static_cast<uint8_t>(ID), 0x02, static_cast<uint8_t>(lon_.degrees() & 0xff),
49 static_cast<uint8_t>((m >> 8) & 0xff), static_cast<uint8_t>((m >> 0) & 0xff)};