forked from IQ.Lvbs/IQ.Pilot
IQ.Pilot Release Commit @ b6534c0
This commit is contained in:
46
iqpilot/tools/cabana/core/can_data.h
Normal file
46
iqpilot/tools/cabana/core/can_data.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "tools/cabana/core/color.h"
|
||||
#include "tools/cabana/core/message_id.h"
|
||||
|
||||
struct CanData {
|
||||
void compute(const MessageId &msg_id, const uint8_t *data, int size, double current_sec,
|
||||
double playback_speed, const std::vector<uint8_t> &mask, double frequency = 0);
|
||||
|
||||
double ts = 0.;
|
||||
uint32_t count = 0;
|
||||
double freq = 0;
|
||||
std::vector<uint8_t> dat;
|
||||
std::vector<CabanaColor> colors;
|
||||
|
||||
struct ByteLastChange {
|
||||
double ts = 0;
|
||||
int delta = 0;
|
||||
int same_delta_counter = 0;
|
||||
bool suppressed = false;
|
||||
};
|
||||
std::vector<ByteLastChange> last_changes;
|
||||
std::vector<std::array<uint32_t, 8>> bit_flip_counts;
|
||||
double last_freq_update_ts = 0;
|
||||
};
|
||||
|
||||
struct CanEvent {
|
||||
uint8_t src;
|
||||
uint32_t address;
|
||||
uint64_t mono_time;
|
||||
uint8_t size;
|
||||
uint8_t dat[];
|
||||
};
|
||||
|
||||
struct CompareCanEvent {
|
||||
constexpr bool operator()(const CanEvent *const event, uint64_t ts) const { return event->mono_time < ts; }
|
||||
constexpr bool operator()(uint64_t ts, const CanEvent *const event) const { return ts < event->mono_time; }
|
||||
};
|
||||
|
||||
using MessageEventsMap = std::unordered_map<MessageId, std::vector<const CanEvent *>>;
|
||||
using CanEventIter = std::vector<const CanEvent *>::const_iterator;
|
||||
79
iqpilot/tools/cabana/core/color.h
Normal file
79
iqpilot/tools/cabana/core/color.h
Normal file
@@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
|
||||
struct CabanaColor {
|
||||
uint8_t r = 0;
|
||||
uint8_t g = 0;
|
||||
uint8_t b = 0;
|
||||
uint8_t a = 255;
|
||||
|
||||
constexpr CabanaColor() = default;
|
||||
constexpr CabanaColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = 255)
|
||||
: r(red), g(green), b(blue), a(alpha) {}
|
||||
|
||||
static CabanaColor fromHsv(float hue, float saturation, float value, float alpha = 1.0f) {
|
||||
const float h = hue - std::floor(hue);
|
||||
const float c = value * saturation;
|
||||
const float x = c * (1.0f - std::fabs(std::fmod(h * 6.0f, 2.0f) - 1.0f));
|
||||
const float m = value - c;
|
||||
float red = 0, green = 0, blue = 0;
|
||||
switch (static_cast<int>(h * 6.0f) % 6) {
|
||||
case 0: red = c; green = x; break;
|
||||
case 1: red = x; green = c; break;
|
||||
case 2: green = c; blue = x; break;
|
||||
case 3: green = x; blue = c; break;
|
||||
case 4: red = x; blue = c; break;
|
||||
default: red = c; blue = x; break;
|
||||
}
|
||||
auto channel = [m](float v) { return static_cast<uint8_t>(std::clamp((v + m) * 255.0f, 0.0f, 255.0f) + 0.5f); };
|
||||
return {channel(red), channel(green), channel(blue),
|
||||
static_cast<uint8_t>(std::clamp(alpha * 255.0f, 0.0f, 255.0f) + 0.5f)};
|
||||
}
|
||||
|
||||
CabanaColor darker(int factor = 200) const {
|
||||
if (factor <= 0) return *this;
|
||||
if (factor < 100) return lighter(10000 / factor);
|
||||
auto [hue, saturation, value] = hsv();
|
||||
return fromHsv(hue, saturation, value * 100.0f / factor, a / 255.0f);
|
||||
}
|
||||
|
||||
CabanaColor lighter(int factor = 150) const {
|
||||
if (factor <= 0) return *this;
|
||||
if (factor < 100) return darker(10000 / factor);
|
||||
auto [hue, saturation, value] = hsv();
|
||||
const float scaled_value = value * factor / 100.0f;
|
||||
if (scaled_value > 1.0f) saturation = std::max(0.0f, saturation - (scaled_value - 1.0f));
|
||||
return fromHsv(hue, saturation, std::min(1.0f, scaled_value), a / 255.0f);
|
||||
}
|
||||
|
||||
constexpr int red() const { return r; }
|
||||
constexpr int green() const { return g; }
|
||||
constexpr int blue() const { return b; }
|
||||
constexpr int alpha() const { return a; }
|
||||
float alphaF() const { return a / 255.0f; }
|
||||
void setAlphaF(float alpha) { a = static_cast<uint8_t>(std::clamp(alpha * 255.0f, 0.0f, 255.0f) + 0.5f); }
|
||||
|
||||
constexpr bool operator==(const CabanaColor &other) const {
|
||||
return r == other.r && g == other.g && b == other.b && a == other.a;
|
||||
}
|
||||
|
||||
private:
|
||||
struct Hsv { float hue; float saturation; float value; };
|
||||
Hsv hsv() const {
|
||||
const float red = r / 255.0f, green = g / 255.0f, blue = b / 255.0f;
|
||||
const float maximum = std::max({red, green, blue});
|
||||
const float minimum = std::min({red, green, blue});
|
||||
const float delta = maximum - minimum;
|
||||
float hue = 0;
|
||||
if (delta > 0) {
|
||||
if (maximum == red) hue = std::fmod((green - blue) / delta, 6.0f) / 6.0f;
|
||||
else if (maximum == green) hue = ((blue - red) / delta + 2.0f) / 6.0f;
|
||||
else hue = ((red - green) / delta + 4.0f) / 6.0f;
|
||||
if (hue < 0) hue += 1.0f;
|
||||
}
|
||||
return {hue, maximum == 0 ? 0 : delta / maximum, maximum};
|
||||
}
|
||||
};
|
||||
27
iqpilot/tools/cabana/core/message_id.h
Normal file
27
iqpilot/tools/cabana/core/message_id.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
constexpr int INVALID_SOURCE = 0xff;
|
||||
|
||||
struct MessageId {
|
||||
uint8_t source = 0;
|
||||
uint32_t address = 0;
|
||||
std::string toString() const { char b[64]; snprintf(b, sizeof(b), "%u:%X", source, address); return b; }
|
||||
static MessageId fromString(const std::string &s) {
|
||||
const auto p = s.find(':');
|
||||
if (p == std::string::npos) return {};
|
||||
return {.source = static_cast<uint8_t>(std::stoul(s.substr(0, p))), .address = static_cast<uint32_t>(std::stoul(s.substr(p + 1), nullptr, 16))};
|
||||
}
|
||||
bool operator==(const MessageId &o) const { return source == o.source && address == o.address; }
|
||||
bool operator!=(const MessageId &o) const { return !(*this == o); }
|
||||
bool operator<(const MessageId &o) const { return std::tie(source, address) < std::tie(o.source, o.address); }
|
||||
bool operator>(const MessageId &o) const { return o < *this; }
|
||||
};
|
||||
|
||||
template <> struct std::hash<MessageId> {
|
||||
size_t operator()(const MessageId &id) const noexcept { return std::hash<uint8_t>{}(id.source) ^ (std::hash<uint32_t>{}(id.address) << 1); }
|
||||
};
|
||||
34
iqpilot/tools/cabana/core/settings.h
Normal file
34
iqpilot/tools/cabana/core/settings.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
constexpr int LIGHT_THEME = 1;
|
||||
constexpr int DARK_THEME = 2;
|
||||
|
||||
struct CabanaSettingsState {
|
||||
enum DragDirection { MsbFirst, LsbFirst, AlwaysLE, AlwaysBE };
|
||||
|
||||
bool absolute_time = false;
|
||||
int fps = 10;
|
||||
int max_cached_minutes = 30;
|
||||
int chart_height = 200;
|
||||
int chart_column_count = 1;
|
||||
int chart_range = 3 * 60;
|
||||
int chart_series_type = 0;
|
||||
int theme = 0;
|
||||
int sparkline_range = 15;
|
||||
bool multiple_lines_hex = false;
|
||||
bool log_livestream = true;
|
||||
bool suppress_defined_signals = false;
|
||||
std::string log_path;
|
||||
std::string last_dir;
|
||||
std::string last_route_dir;
|
||||
std::vector<std::string> recent_files;
|
||||
DragDirection drag_direction = MsbFirst;
|
||||
|
||||
std::string recent_dbc_file;
|
||||
std::string active_msg_id;
|
||||
std::vector<std::string> selected_msg_ids;
|
||||
std::vector<std::string> active_charts;
|
||||
};
|
||||
Reference in New Issue
Block a user