INSTINCT Code Coverage Report


Directory: src/
File: util/Vendor/KVH/KvhUartSensor.cpp
Date: 2025-02-07 16:54:41
Exec Total Coverage
Lines: 11 154 7.1%
Functions: 2 9 22.2%
Branches: 3 202 1.5%

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 "KvhUartSensor.hpp"
10
11 #include "KvhUtilities.hpp"
12 #include "util/Logger.hpp"
13
14 112 NAV::vendor::kvh::KvhUartSensor::KvhUartSensor(std::string name)
15
2/4
✓ Branch 3 taken 112 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 112 times.
✗ Branch 7 not taken.
224 : _name(std::move(name)), _buffer(uart::sensors::UartSensor::DefaultReadBufferSize)
16 {
17
1/2
✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
112 resetTracking();
18 112 }
19
20 112 void NAV::vendor::kvh::KvhUartSensor::resetTracking()
21 {
22 112 _currentlyBuildingBinaryPacket = false;
23 112 _currentlyBuildingAsciiPacket = false;
24
25 112 _asciiEndChar1Found = false;
26 112 _packetType = HeaderType::FMT_UNKNOWN;
27
28 112 _buffer.resize(0);
29 112 }
30
31 NAV::vendor::kvh::KvhUartSensor::HeaderType NAV::vendor::kvh::KvhUartSensor::bFindImuHeader(uint8_t ui8Data)
32 {
33 if (_eState == SM_IDLE)
34 {
35 if (ui8Data == ((HEADER_FMT_A >> 24U) & 0xFFU))
36 // || ui8Data == ((HEADER_FMT_B >> 24U) & 0xFFU)
37 // || ui8Data == ((HEADER_FMT_C >> 24U) & 0xFFU)
38 // || ui8Data == ((HEADER_FMT_XBIT >> 24U) & 0xFFU)
39 // || ui8Data == ((HEADER_FMT_XBIT2 >> 24U) & 0xFFU))
40 {
41 _eState = SM_H1;
42 }
43 }
44 else if (_eState == SM_H1)
45 {
46 if (ui8Data == ((HEADER_FMT_A >> 16U) & 0xFFU))
47 {
48 _eState = SM_H2;
49 }
50 else
51 {
52 _eState = SM_IDLE;
53 }
54 }
55 else if (_eState == SM_H2)
56 {
57 if (ui8Data == ((HEADER_FMT_A >> 8U) & 0xFFU))
58 {
59 _eState = SM_H3;
60 }
61 else if (ui8Data == ((HEADER_FMT_XBIT >> 8U) & 0xFFU))
62 {
63 _eState = SM_X3;
64 }
65 else
66 {
67 _eState = SM_IDLE;
68 }
69 }
70 else if (_eState == SM_H3)
71 {
72 if (ui8Data == (HEADER_FMT_A & 0xFFU))
73 {
74 _eState = SM_IDLE;
75 return HeaderType::FMT_A;
76 }
77 if (ui8Data == (HEADER_FMT_B & 0xFFU))
78 {
79 _eState = SM_IDLE;
80 return HeaderType::FMT_B;
81 }
82 if (ui8Data == (HEADER_FMT_C & 0xFFU))
83 {
84 _eState = SM_IDLE;
85 return HeaderType::FMT_C;
86 }
87
88 _eState = SM_IDLE;
89 }
90 else if (_eState == SM_X3)
91 {
92 if (ui8Data == (HEADER_FMT_XBIT & 0xFFU))
93 {
94 _eState = SM_IDLE;
95 return HeaderType::FMT_XBIT;
96 }
97 if (ui8Data == (HEADER_FMT_XBIT2 & 0xFFU))
98 {
99 _eState = SM_IDLE;
100 return HeaderType::FMT_XBIT2;
101 }
102
103 _eState = SM_IDLE;
104 }
105 else
106 {
107 _eState = SM_IDLE;
108 }
109
110 return HeaderType::FMT_UNKNOWN;
111 }
112
113 std::unique_ptr<uart::protocol::Packet> NAV::vendor::kvh::KvhUartSensor::findPacket(uint8_t dataByte)
114 {
115 if (_buffer.size() == _buffer.capacity())
116 {
117 // Buffer is full
118 resetTracking();
119 LOG_ERROR("{}: Discarding current packet, because buffer is full.", _name);
120 }
121
122 auto binaryPacketType = bFindImuHeader(dataByte);
123 if (binaryPacketType != HeaderType::FMT_UNKNOWN)
124 {
125 resetTracking();
126 _packetType = binaryPacketType;
127 _currentlyBuildingBinaryPacket = true;
128 uint32_t header{};
129 switch (binaryPacketType)
130 {
131 case HeaderType::FMT_A:
132 header = uart::stoh(HEADER_FMT_A, ENDIANNESS);
133 break;
134 case HeaderType::FMT_B:
135 header = uart::stoh(HEADER_FMT_B, ENDIANNESS);
136 break;
137 case HeaderType::FMT_C:
138 header = uart::stoh(HEADER_FMT_C, ENDIANNESS);
139 break;
140 case HeaderType::FMT_XBIT:
141 header = uart::stoh(HEADER_FMT_XBIT, ENDIANNESS);
142 break;
143 case HeaderType::FMT_XBIT2:
144 header = uart::stoh(HEADER_FMT_XBIT2, ENDIANNESS);
145 break;
146 default:
147 break;
148 }
149 _buffer.resize(4);
150 memcpy(_buffer.data(), &header, 4);
151
152 return nullptr;
153 }
154
155 if (!_currentlyBuildingAsciiPacket && !_currentlyBuildingBinaryPacket)
156 {
157 resetTracking();
158 _currentlyBuildingAsciiPacket = true;
159 _buffer.push_back(dataByte);
160 }
161 else if (_currentlyBuildingBinaryPacket)
162 {
163 _buffer.push_back(dataByte);
164
165 if ((_packetType == HeaderType::FMT_A && _buffer.size() == 36)
166 || (_packetType == HeaderType::FMT_B && _buffer.size() == 40)
167 || (_packetType == HeaderType::FMT_C && _buffer.size() == 38)
168 || (_packetType == HeaderType::FMT_XBIT && _buffer.size() == 11)
169 || (_packetType == HeaderType::FMT_XBIT2 && _buffer.size() == 13))
170 {
171 // We have a possible binary packet!
172 auto p = std::make_unique<uart::protocol::Packet>(_buffer, &_sensor);
173
174 if (p->isValid())
175 {
176 // We have a valid binary packet!!!.
177 LOG_DATA("{}: Valid binary packet: Type={}, Length={}", _name, fmt::underlying(_packetType), _buffer.size());
178 resetTracking();
179 return p;
180 }
181 // Invalid packet!
182 LOG_DEBUG("{}: Invalid binary packet: Type={}, Length={}", _name, fmt::underlying(_packetType), _buffer.size());
183 resetTracking();
184 }
185 if (_buffer.size() >= 40)
186 {
187 resetTracking();
188 }
189 }
190 else if (_currentlyBuildingAsciiPacket)
191 {
192 _buffer.push_back(dataByte);
193
194 if (dataByte == ASCII_ESCAPE_CHAR)
195 {
196 resetTracking();
197 }
198 else if (dataByte == ASCII_END_CHAR_1)
199 {
200 _asciiEndChar1Found = true;
201 }
202 else if (_asciiEndChar1Found)
203 {
204 if (dataByte == ASCII_END_CHAR_2)
205 {
206 // We have a possible data packet
207 auto p = std::make_unique<uart::protocol::Packet>(_buffer, &_sensor);
208
209 if (p->isValid())
210 {
211 // We have a valid ascii packet!!!.
212 LOG_DATA("{}: Valid ascii packet: {}", _name, p->datastr().substr(0, p->getRawDataLength() - 2));
213 resetTracking();
214 return p;
215 }
216 // Invalid packet!
217 LOG_ERROR("{}: Invalid ascii packet: {}", _name, p->datastr());
218 }
219
220 resetTracking();
221 }
222
223 if (_buffer.size() >= MAX_SIZE_ASCII_PACKET)
224 {
225 LOG_ERROR("{}: Buffer exceeded the Maximum Ascii Packet Size", _name);
226 resetTracking();
227 }
228 }
229
230 return nullptr;
231 }
232
233 void NAV::vendor::kvh::KvhUartSensor::packetFinderFunction(const std::vector<uint8_t>& data, const uart::xplat::TimeStamp& timestamp, uart::sensors::UartSensor::ValidPacketFoundHandler dispatchPacket, void* dispatchPacketUserData, void* userData)
234 {
235 auto* sensor = static_cast<KvhUartSensor*>(userData);
236
237 for (size_t i = 0; i < data.size(); i++, sensor->_runningDataIndex++)
238 {
239 auto packetPointer = sensor->findPacket(data.at(i));
240
241 if (packetPointer != nullptr)
242 {
243 uart::protocol::Packet packet = *packetPointer;
244 dispatchPacket(dispatchPacketUserData, packet, sensor->_runningDataIndex, timestamp);
245 }
246 }
247 }
248
249 uart::protocol::Packet::Type NAV::vendor::kvh::KvhUartSensor::packetTypeFunction(const uart::protocol::Packet& packet)
250 {
251 if (packet.getRawDataLength() < 1)
252 {
253 LOG_CRITICAL("Packet does not contain any data.");
254 }
255
256 // Check for carriage return and line feed
257 if (packet.getRawData().at(packet.getRawDataLength() - 2) == uart::CARRIAGE_RETURN
258 && packet.getRawData().at(packet.getRawDataLength() - 1) == uart::LINE_FEED)
259 {
260 return uart::protocol::Packet::Type::TYPE_ASCII;
261 }
262
263 uint32_t data_zero{};
264 memcpy(&data_zero, packet.getRawData().data(), sizeof(uint32_t));
265 data_zero = uart::stoh(data_zero, ENDIANNESS);
266
267 if (data_zero == HEADER_FMT_A || data_zero == HEADER_FMT_B || data_zero == HEADER_FMT_C)
268 {
269 return uart::protocol::Packet::Type::TYPE_BINARY;
270 }
271
272 return uart::protocol::Packet::Type::TYPE_UNKNOWN;
273 }
274
275 bool NAV::vendor::kvh::KvhUartSensor::checksumFunction(const uart::protocol::Packet& packet)
276 {
277 // minumum binary packet is 9 bytes
278 if (packet.getRawDataLength() < 1)
279 {
280 return false;
281 }
282
283 if (packet.type() == uart::protocol::Packet::Type::TYPE_ASCII)
284 {
285 // Ascii does not have a checksum
286 return true;
287 }
288
289 if (packet.type() == uart::protocol::Packet::Type::TYPE_BINARY)
290 {
291 uint32_t checksumCalc = kvh::ui32CalcImuCRC(packet.getRawData());
292
293 uint32_t checksumPacket = 0;
294 memcpy(&checksumPacket, packet.getRawData().data() + packet.getRawDataLength() - sizeof(uint32_t), sizeof(uint32_t));
295 checksumPacket = uart::stoh(checksumPacket, ENDIANNESS);
296
297 return checksumPacket == checksumCalc;
298 }
299
300 LOG_CRITICAL("Can't calculate checksum of packet with unknown type");
301 return false;
302 }
303
304 bool NAV::vendor::kvh::KvhUartSensor::isErrorFunction([[maybe_unused]] const uart::protocol::Packet& packet)
305 {
306 return false;
307 }
308
309 bool NAV::vendor::kvh::KvhUartSensor::isResponseFunction([[maybe_unused]] const uart::protocol::Packet& packet)
310 {
311 return false;
312 }
313