0.5.1
Loading...
Searching...
No Matches
Ln200UartSensor.cpp
Go to the documentation of this file.
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
14 : _name(std::move(name)), _bitBuffer(uart::sensors::UartSensor::DefaultReadBufferSize), _flagWindow(8)
15{}
16
17std::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 {
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();
96 _wasIdle = false; // Clear the idle flag.
97 return p;
98 }
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.
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
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 {
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
138void 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
154uart::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
159bool 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
170bool NAV::vendor::ln::Ln200UartSensor::isErrorFunction([[maybe_unused]] const uart::protocol::Packet& packet)
171{
172 return false;
173}
174
175bool NAV::vendor::ln::Ln200UartSensor::isResponseFunction([[maybe_unused]] const uart::protocol::Packet& packet)
176{
177 return false;
178}
Class to read out LN-200 Sensors.
Utility class for logging to console and file.
#define LOG_CRITICAL(...)
Critical Event, which causes the program to work entirely and throws an exception.
Definition Logger.hpp:75
#define LOG_DATA
All output which occurs repeatedly every time observations are received.
Definition Logger.hpp:29
A buffer which is overwriting itself from the start when full.
Abstract Uart Sensor Class.
State _state
Internal state of the sensor.
Ln200UartSensor()=default
Default constructor.
Ln200UartSensor(std::string name)
Constructor.
const std::string _name
Name of the Parent Node.
static uart::protocol::Packet::Type packetTypeFunction(const uart::protocol::Packet &packet)
Function which is called to determine the packet type (ascii/binary)
static bool isResponseFunction(const uart::protocol::Packet &packet)
Function which determines, if the packet is a Response.
static bool isErrorFunction(const uart::protocol::Packet &packet)
Function which determines, if the packet is an Error Packet.
static void packetFinderFunction(const std::vector< uint8_t > &data, const uart::xplat::TimeStamp &timestamp, uart::sensors::UartSensor::ValidPacketFoundHandler dispatchPacket, void *dispatchPacketUserData, void *userData)
Function which is called to find packets in the provided data buffer.
static bool checksumFunction(const uart::protocol::Packet &packet)
Function which is called to verify packet integrity.
int _consecutiveOnes
Counter for bit insertion.
std::unique_ptr< uart::protocol::Packet > findPacket(uint8_t dataByte)
Collects data bytes and searches for packages inside of them.
uart::sensors::UartSensor _sensor
UartSensor object which handles the UART interface.
bool _wasIdle
Flag to detect the start of a frame.
ScrollingBuffer< bool > _bitBuffer
Buffer to accumulate bits of the current frame.
ScrollingBuffer< bool > _flagWindow
Sliding window buffer to detect flags.
void move(std::vector< T > &v, size_t sourceIdx, size_t targetIdx)
Moves an element within a vector to a new position.
Definition Vector.hpp:27