INSTINCT Code Coverage Report


Directory: src/
File: util/Vendor/Litton/Ln200UartSensor.cpp
Date: 2025-11-25 23:34:18
Exec Total Coverage
Lines: 0 81 0.0%
Functions: 0 10 0.0%
Branches: 0 96 0.0%

Line Branch Exec Source
1 // This file is part of INSTINCT, the INS Toolkit for Integrated
2 // Navigation Concepts and Training by the Institute of Navigation of
3 // the University of Stuttgart, Germany.
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9 #include "Ln200UartSensor.hpp"
10
11 #include "util/Logger.hpp"
12
13 ✗ NAV::vendor::ln::Ln200UartSensor::Ln200UartSensor(std::string name)
14 ✗ : _name(std::move(name)), _bitBuffer(uart::sensors::UartSensor::DefaultReadBufferSize), _flagWindow(8)
15 ✗ {}
16
17 ✗ std::unique_ptr<uart::protocol::Packet> NAV::vendor::ln::Ln200UartSensor::findPacket(uint8_t dataByte)
18 {
19 // If we receive a full idle byte (0xFF), mark the idle period.
20 ✗ if (dataByte == 0xFF)
21 {
22 ✗ _wasIdle = true;
23 }
24
25 // Define the lambda for byte-to-bits conversion.
26 ✗ auto byteToBits = [](uint8_t byte) -> std::vector<bool> {
27 ✗ std::vector<bool> bits(8);
28 ✗ for (uint8_t i = 0; i < 8; ++i)
29 {
30 ✗ bits[7 - i] = (byte >> i) & 0x1;
31 }
32 ✗ return bits;
33 ✗ };
34
35 // Lambda for checking the flag sequence.
36 ✗ auto isFlagSequence = [](const ScrollingBuffer<bool>& window) -> bool {
37 // The flag is 01111110.
38 ✗ constexpr std::bitset<8> flagPattern("01111110");
39
40 // Compare the available bits in the window with the corresponding bits in the flag pattern.
41 ✗ for (size_t i = 0; i < window.size(); ++i)
42 {
43 ✗ if (window.at(i) != flagPattern[i])
44 {
45 ✗ return false;
46 }
47 }
48 ✗ return true;
49 };
50
51 ✗ auto bitBufferToByteVector = [](const ScrollingBuffer<bool>& bitBuffer) -> std::vector<uint8_t> {
52 ✗ std::vector<uint8_t> byteVector((bitBuffer.size() + 7) / 8, 0); // Allocate enough bytes
53 ✗ for (size_t i = 0; i < bitBuffer.size(); ++i)
54 {
55 ✗ if (bitBuffer.at(i))
56 {
57 ✗ byteVector[i / 8] |= (1 << (7 - (i % 8))); // Set the corresponding bit in the byte
58 }
59 }
60 ✗ return byteVector;
61 ✗ };
62
63 // Convert the received byte to bits.
64 ✗ auto bits = byteToBits(dataByte);
65 ✗ for (auto bit : bits)
66 {
67 // Update the flag window (we use a sliding window of 8 bits).
68 ✗ _flagWindow.push_back(bit);
69 ✗ if (_flagWindow.size() > 8)
70 {
71 ✗ _flagWindow.pop_front();
72 }
73
74 // Check for flag sequence.
75 ✗ if (_flagWindow.size() == 8 && isFlagSequence(_flagWindow))
76 {
77 ✗ if (_state == State::Receiving)
78 {
79 // End of frame detected.
80 ✗ if (!_bitBuffer.empty())
81 {
82 // Remove the flag bits from the _bitBuffer (assume the last 7 bits are the flag).
83 ✗ if (_bitBuffer.size() >= 7)
84 {
85 ✗ for (int i = 0; i < 7; ++i)
86 {
87 ✗ _bitBuffer.pop_back();
88 }
89 }
90 ✗ std::vector<uint8_t> byteVector = bitBufferToByteVector(_bitBuffer);
91 LOG_DATA("{}: Valid binary packet: Length={}", _name, _bitBuffer.size());
92 ✗ auto p = std::make_unique<uart::protocol::Packet>(byteVector, &_sensor);
93 ✗ _bitBuffer.clear();
94 ✗ _state = State::Idle;
95 ✗ _consecutiveOnes = 0;
96 ✗ _wasIdle = false; // Clear the idle flag.
97 ✗ return p;
98 ✗ }
99 ✗ _state = State::Idle;
100 ✗ _wasIdle = false;
101 }
102 else // _state == Idle
103 {
104 // Only consider this flag as a start sequence if the bus was idle (0xFF) just before.
105 ✗ if (_wasIdle)
106 {
107 // Start of frame detected.
108 ✗ _state = State::Receiving;
109 ✗ _consecutiveOnes = 0;
110 ✗ _bitBuffer.clear(); // Clear any previous payload.
111 ✗ _wasIdle = false; // Reset the idle flag.
112 }
113 // If _wasIdle is false, then the flag might be an ending flag from a previous message.
114 }
115 ✗ continue;
116 ✗ }
117
118 ✗ if (_state == State::Receiving)
119 {
120 // If the current bit is false and it follows five consecutive ones,
121 // it's a stuffed zero which should be ignored.
122 ✗ if (!bit && _consecutiveOnes == 5)
123 {
124 ✗ _consecutiveOnes = 0;
125 ✗ continue;
126 }
127
128 // For a true bit, increment the counter; for a false bit, reset it.
129 ✗ _consecutiveOnes = bit ? (_consecutiveOnes + 1) : 0;
130
131 // Append the bit to the buffer.
132 ✗ _bitBuffer.push_back(bit);
133 }
134 }
135 ✗ return nullptr;
136 ✗ }
137
138 ✗ void NAV::vendor::ln::Ln200UartSensor::packetFinderFunction(const std::vector<uint8_t>& data, const uart::xplat::TimeStamp& timestamp, uart::sensors::UartSensor::ValidPacketFoundHandler dispatchPacket, void* dispatchPacketUserData, void* userData)
139 {
140 ✗ auto* sensor = static_cast<Ln200UartSensor*>(userData);
141
142 ✗ for (size_t i = 0; i < data.size(); ++i, sensor->_runningDataIndex++)
143 {
144 ✗ auto packetPointer = sensor->findPacket(data.at(i));
145
146 ✗ if (packetPointer != nullptr)
147 {
148 ✗ uart::protocol::Packet packet = *packetPointer;
149 ✗ dispatchPacket(dispatchPacketUserData, packet, sensor->_runningDataIndex, timestamp);
150 ✗ }
151 ✗ }
152 ✗ }
153
154 ✗ uart::protocol::Packet::Type NAV::vendor::ln::Ln200UartSensor::packetTypeFunction([[maybe_unused]] const uart::protocol::Packet& packet)
155 {
156 ✗ return uart::protocol::Packet::Type::TYPE_BINARY;
157 }
158
159 ✗ bool NAV::vendor::ln::Ln200UartSensor::checksumFunction(const uart::protocol::Packet& packet)
160 {
161 // TODO: Use 14th word of message as checksum
162 ✗ if (packet.type() == uart::protocol::Packet::Type::TYPE_BINARY)
163 {
164 ✗ return true;
165 }
166 ✗ LOG_CRITICAL("Can't calculate checksum of packet with unknown type");
167 return false;
168 }
169
170 ✗ bool NAV::vendor::ln::Ln200UartSensor::isErrorFunction([[maybe_unused]] const uart::protocol::Packet& packet)
171 {
172 ✗ return false;
173 }
174
175 ✗ bool NAV::vendor::ln::Ln200UartSensor::isResponseFunction([[maybe_unused]] const uart::protocol::Packet& packet)
176 {
177 ✗ return false;
178 }
179