Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ src/
│ ├── locomotive.rs # Locomotive datalogger CSV parser (TimeStamp/Customer/UnitNumber header)
│ ├── megasquirt.rs # MegaSquirt (MS1/MS2/MS3) TunerStudio CSV parser
│ ├── mhd.rs # MHD Tuning CSV parser (BMW N54/N55/S55/B58)
│ ├── msl.rs # TunerStudio MSL (legacy ASCII, tab-delimited) parser
│ ├── motorsport_electronics.rs # Motorsport Electronics ME221/ME442 (ME Tuner) CSV parser
│ ├── racechrono.rs # RaceChrono CSV v3 session export parser (GPS + sensors + OBD/CAN)
│ ├── bluedriver.rs # BlueDriver OBD-II scan tool CSV parser
Expand Down Expand Up @@ -291,6 +292,7 @@ The parser system uses a trait-based design for supporting multiple ECU formats:
- **`parsers/locomotive.rs`** - Locomotive datalogger CSV parser (detected via `TimeStamp:` / `Customer:` header lines, day-of-week-prefixed data rows)
- **`parsers/megasquirt.rs`** - MegaSquirt (MS1/MS2/MS3/MS3Pro) TunerStudio CSV parser
- **`parsers/mhd.rs`** - MHD Tuning CSV parser (BMW N54/N55/S55/B58 flashed with MHD)
- **`parsers/msl.rs`** - TunerStudio MSL parser (tab-delimited legacy ASCII datalog; header row + units row; also written by RealDash)
- **`parsers/motorsport_electronics.rs`** - Motorsport Electronics ME221/ME442 (ME Tuner) CSV parser
- **`parsers/racechrono.rs`** - RaceChrono CSV v3 session export parser (lap-timing app; GPS + phone sensors + OBD/CAN merged on a unix-time base)
- **`parsers/bluedriver.rs`** - BlueDriver OBD-II scan tool CSV parser (UTF-16 with BOM)
Expand All @@ -310,6 +312,7 @@ Note: `EcuType` also reserves `Aem`, `MaxxEcu`, and `MotEc` variants for formats
- Emerald K6/M3D (.lg1/.lg2 binary)
- MegaSquirt MS1/MS2/MS3 (TunerStudio CSV export)
- MHD Tuning (CSV export — BMW N54/N55/S55/B58)
- TunerStudio MSL (`.msl` legacy ASCII export — Speeduino/MegaSquirt via TunerStudio or RealDash)
- Motorsport Electronics ME221/ME442 (ME Tuner CSV export)
- RaceChrono / RaceChrono Pro (CSV v3 session export — lap-timing app)
- Woolich Racing Tuned (WRT CSV export — motorcycle ECUs)
Expand Down Expand Up @@ -355,6 +358,29 @@ because it also leads with a `Time` column, and only matches a first column of e
- **Duplicate column names are disambiguated by source, unique names stay raw** - RaceChrono exports the same column name once per source (`speed` from GPS and calc, `device_update_rate` from every sensor). Duplicates get the sources-row label appended (`speed (gps)`); unique names — including `latitude`/`longitude` — must stay exactly as exported because `find_gps_channels` in `src/ui/widgets/track_map.rs` matches those names *exactly* (lowercased), and a suffix would silently disable the GPS Track Map for RaceChrono logs. When the short labels themselves collide (two location devices both labeled `gps`), the first occurrence keeps its bare name — so `latitude` still survives — and later ones carry the full source tag (`latitude (101: gps)`).
- **Detection accepts any `Format,N` version; `parse` rejects non-v3** - so a v1/v2 export surfaces a clear "re-export as CSV v3" error instead of falling through to the Haltech default parser and failing cryptically.

**TunerStudio MSL parser load-bearing behaviors** (`src/parsers/msl.rs`):

- **Detection requires the header/units row *pair*** - `.msl` is tab-delimited with `Time` as
the first column, which several other formats also are. What makes MSL unambiguous is the
second row: it holds a unit per column and names a time unit (`sec`, `s`, `ms`, ...) under
`Time`. Dropping that requirement would make the parser claim tab-delimited ECUMaster and
generic `Time`-first exports. `Msl::detect` runs after `MegaSquirt::detect` and before
`EcuMaster::detect` in the `dispatch_text_content` chain.
- **Time scale comes from the units row, never assumed** - `sec`/`s`/`seconds` -> seconds,
`ms`/`msec`/`milliseconds` -> milliseconds. Same class of bug as issue #80's RomRaider
time-unit hardcode.
- **Non-numeric and blank fields carry the last known value forward** - MSL columns are not
all numeric: RealDash writes `GPS Date` as `18.8.2026` and leaves fields blank until the GPS
gets a fix. Substitution preserves column alignment, the same approach as
`parsers/haltech.rs` and `parsers/ecumaster.rs`. Clock-style fields (`HH:MM`, `HH:MM:SS`)
are the exception: they convert to seconds since midnight so `GPS Time` plots as a channel.
- **Times are forced monotonic** - a `.msl` can concatenate sessions, so a backwards jump in
`Time` accumulates an offset rather than being written through. Monotonic times are required
because computed-channel time-shift lookups binary-search the `times` vector.
- **GPS column names stay exactly as exported** - `GPS Latitude` / `GPS Longitude` are matched
by name (lowercased) in `find_gps_channels` (`src/ui/widgets/track_map.rs`); renaming or
suffixing them silently disables the Track Map for MSL logs.

**Haltech parser load-bearing behaviors** (`src/parsers/haltech.rs`, added for wall-clock-timestamped exports):

- **Last-known-value substitution** - Unparseable/blank fields are filled with the last successfully parsed value for that column (`0.0` before the first valid sample), matching the approach used in `parsers/ecumaster.rs`. This preserves column alignment instead of shifting subsequent columns when a field fails to parse.
Expand Down Expand Up @@ -417,7 +443,7 @@ The Track Map widget can draw map tile backgrounds. Tiles are **opt-in** (off by

## Key Features

- **Multi-ECU Support** - Haltech, ECUMaster, RomRaider, Speeduino, rusEFI, AiM, Link, Emerald, MegaSquirt, MHD Tuning, Motorsport Electronics, RaceChrono, Woolich Racing Tuned, BlueDriver, DynamicEFI, and Locomotive log formats
- **Multi-ECU Support** - Haltech, ECUMaster, RomRaider, Speeduino, rusEFI, AiM, Link, Emerald, MegaSquirt, TunerStudio MSL, MHD Tuning, Motorsport Electronics, RaceChrono, Woolich Racing Tuned, BlueDriver, DynamicEFI, and Locomotive log formats
- **Computed Channels** - Create virtual channels from mathematical formulas with time-shifting (e.g., `RPM[-1]`, `Boost@-0.5s`)
- **Analysis Algorithms** - AFR/Lambda drift and zone detection, derived metrics (VE, injector duty cycle), signal filters, and descriptive statistics (`src/analysis/`)
- **GPS Track Map** - Right-side data panel with a track map: lap detection, channel-colored polyline (Viridis/Turbo with editable range), hover-scrub/click-seek cursor sync, and opt-in Esri/OSM tile backgrounds (`src/ui/widgets/track_map.rs`, `src/tiles.rs`, `src/laps.rs`). GPS coordinate encodings are auto-detected and normalized to decimal degrees (`GpsCoordSpec` in `src/laps.rs`): NMEA `DDMM.mmmm`, milli/micro/1e-7-scaled integer degrees, and 0-360 longitude. Detection is conservative - values already in valid degree ranges are never transformed, and radians are deliberately not detected (ambiguous with genuine near-equator degree tracks).
Expand Down Expand Up @@ -499,6 +525,7 @@ Example log files are in `exampleLogs/` organized by ECU type:
- `exampleLogs/emerald/` - Emerald K6/M3D `.lg1`/`.lg2` files
- `exampleLogs/megasquirt/` - MegaSquirt TunerStudio CSV exports, plus a `_gps.mlg` fixture with synthetic GPS channels (generated by `examples/inject_fake_gps_mlg.rs`; the coordinates are a fake closed loop, not a real location)
- `exampleLogs/mhd/` - MHD Tuning CSV exports (VIN redacted)
- `exampleLogs/msl/` - TunerStudio MSL excerpt from issue #86 (RealDash logging a Speeduino; trimmed to 2000 data rows, keeping the leading no-GPS-fix rows where `GPS Date`/`GPS Time` are blank)
- `exampleLogs/motorsportElectronics/` - Motorsport Electronics ME Tuner CSV exports
- `exampleLogs/racechrono/` - RaceChrono CSV v3 session excerpt (user-contributed track session, trimmed; covers blank-heavy pit-lane rows, the genuine fragment 0->1 boundary where `elapsed_time` resets, and fully-populated on-track rows)
- `exampleLogs/bluedriver/` - BlueDriver OBD-II CSV exports
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ultralog"
version = "2.13.1"
version = "2.14.0"
edition = "2024"
# egui/eframe 0.36 is the binding constraint on the minimum supported Rust
# version; edition 2024 itself only needs 1.85.
Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ A high-performance, cross-platform ECU log viewer written in Rust.

![CI](https://github.com/ClassicMiniDIY/UltraLog/actions/workflows/ci.yml/badge.svg)
![License](https://img.shields.io/badge/license-AGPL--3.0-blue.svg)
![Version](https://img.shields.io/badge/version-2.13.1-green.svg)
![Version](https://img.shields.io/badge/version-2.14.0-green.svg)

---

Expand Down Expand Up @@ -145,6 +145,14 @@ Configurable units for 8 measurement categories:
- **Supported devices:** MegaSquirt MS1, MS2, MS3, MS3Pro, Honda Tuning Studio, and any TunerStudio-compatible ECU
- **Supported data:** RPM, MAP, TPS, injector duration/duty, ignition timing, ECT, IAT, AFR, battery voltage, boost, VSS, gear, and all logged channels

### TunerStudio MSL - Full Support

- **File type:** Tab-delimited legacy ASCII datalogs (`.msl`) from TunerStudio's Data Logging menu, and from third-party dashes that write the same dialect
- **Features:** Units read from the row beneath the header, optional firmware/capture-date preamble, `MARK` lines skipped, blank and non-numeric fields carried forward from the last known value, clock columns (`GPS Time`) converted to seconds since midnight, monotonic time enforced across concatenated sessions
- **Supported devices:** Speeduino, MegaSquirt, and any ECU logged through TunerStudio or RealDash (for example a Speeduino logged over Bluetooth by RealDash)
- **Supported data:** RPM, MAP, TPS, MAT, CLT, AFR/AFR2, EGO corrections, pulse width, VE, duty cycle, boost, and GPS latitude/longitude/altitude — GPS logs drive the Track Map out of the box
- **Note:** This is the tab-delimited `.msl` format. TunerStudio's comma-delimited CSV export is handled by the MegaSquirt parser above

### BlueDriver OBD-II - Full Support

- **File type:** CSV exports from BlueDriver Bluetooth OBD-II scanner app
Expand Down Expand Up @@ -624,6 +632,7 @@ UltraLog/
│ │ ├── emerald.rs # Emerald ECU parser
│ │ ├── bluedriver.rs # BlueDriver OBD-II parser
│ │ ├── mhd.rs # MHD Tuning parser
│ │ ├── msl.rs # TunerStudio MSL (legacy ASCII) parser
│ │ └── woolich.rs # Woolich Racing Tuned CSV parser
│ ├── analysis/ # Analysis tools
│ │ ├── filters.rs # Signal processing filters
Expand Down
24 changes: 16 additions & 8 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
<title>UltraLog - Free ECU Log Viewer & Analyzer | Haltech, ECUMaster, Speeduino, AiM & More</title>
<meta name="title" content="UltraLog - Free ECU Log Viewer & Analyzer | Haltech, ECUMaster, Speeduino, AiM & More">
<meta name="description"
content="UltraLog is a free, open-source ECU datalog viewer built with Rust. Analyze logs from Haltech, ECUMaster, RomRaider, Speeduino, rusEFI, AiM, Link, Emerald, BlueDriver, MegaSquirt, MHD, Woolich, and RaceChrono lap-timing sessions. Features include stacked plot areas, histogram heatmaps, scatter plots, computed channels, MCP server for AI integration, and professional analysis tools. Download for Windows, macOS, and Linux.">
content="UltraLog is a free, open-source ECU datalog viewer built with Rust. Analyze logs from Haltech, ECUMaster, RomRaider, Speeduino, rusEFI, AiM, Link, Emerald, BlueDriver, MegaSquirt, TunerStudio MSL, MHD, Woolich, and RaceChrono lap-timing sessions. Features include stacked plot areas, histogram heatmaps, scatter plots, computed channels, MCP server for AI integration, and professional analysis tools. Download for Windows, macOS, and Linux.">
<meta name="keywords"
content="ECU log viewer, datalog analyzer, Haltech NSP, ECUMaster EMU Pro, RomRaider, Speeduino MLG, rusEFI, AiM XRK DRK, Link ECU LLG, Emerald K6 M3D, automotive tuning software, engine tuning, AFR analysis, boost log, free tuning software, open source ECU, car data logger, dyno analysis, motorsport data, fuel map analysis, ignition timing, lambda analysis, volumetric efficiency, injector duty cycle, Butterworth filter, scatter plot, histogram heatmap, computed channels, Rust application, stacked plots, MCP server, Model Context Protocol, Claude Desktop, BlueDriver OBD-II, AI log analysis, RaceChrono CSV, lap timing analysis, track day data, GPS track map">
content="ECU log viewer, datalog analyzer, Haltech NSP, ECUMaster EMU Pro, RomRaider, Speeduino MLG, rusEFI, AiM XRK DRK, Link ECU LLG, Emerald K6 M3D, automotive tuning software, engine tuning, AFR analysis, boost log, free tuning software, open source ECU, car data logger, dyno analysis, motorsport data, fuel map analysis, ignition timing, lambda analysis, volumetric efficiency, injector duty cycle, Butterworth filter, scatter plot, histogram heatmap, computed channels, Rust application, stacked plots, MCP server, Model Context Protocol, Claude Desktop, BlueDriver OBD-II, AI log analysis, RaceChrono CSV, TunerStudio MSL, RealDash log, lap timing analysis, track day data, GPS track map">
<meta name="author" content="Cole Gentry">
<meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1">
<meta name="googlebot" content="index, follow">
Expand Down Expand Up @@ -107,13 +107,13 @@
"@type": "SoftwareApplication",
"name": "UltraLog",
"alternateName": ["UltraLog ECU Viewer", "UltraLog Datalog Analyzer"],
"description": "A high-performance, cross-platform ECU log viewer and analyzer built with Rust. Supports Haltech, ECUMaster, RomRaider, Speeduino, rusEFI, AiM, Link, Emerald, MegaSquirt, MHD, Motorsport Electronics, RaceChrono, Woolich, BlueDriver, DynamicEFI, and Locomotive log formats with advanced analysis tools.",
"description": "A high-performance, cross-platform ECU log viewer and analyzer built with Rust. Supports Haltech, ECUMaster, RomRaider, Speeduino, rusEFI, AiM, Link, Emerald, MegaSquirt, TunerStudio MSL, MHD, Motorsport Electronics, RaceChrono, Woolich, BlueDriver, DynamicEFI, and Locomotive log formats with advanced analysis tools.",
"url": "https://ultralog.co/",
"applicationCategory": "UtilitiesApplication",
"applicationSubCategory": "Automotive Software",
"operatingSystem": ["Windows 10", "Windows 11", "macOS", "Linux"],
"softwareVersion": "2.13.1",
"releaseNotes": "https://github.com/ClassicMiniDIY/UltraLog/releases/tag/v2.13.1",
"softwareVersion": "2.14.0",
"releaseNotes": "https://github.com/ClassicMiniDIY/UltraLog/releases/tag/v2.14.0",
"downloadUrl": "https://github.com/ClassicMiniDIY/UltraLog/releases/latest",
"installUrl": "https://github.com/ClassicMiniDIY/UltraLog/releases/latest",
"screenshot": [
Expand Down Expand Up @@ -1427,7 +1427,7 @@ <h1 id="hero-heading" class="tagline" itemprop="headline">Unlock Your Performanc
<div class="hero-badges">
<span class="version-badge">
<span class="new-tag">New</span>
v2.13.1
v2.14.0
</span>
<a href="https://github.com/ClassicMiniDIY/UltraLog" class="opensource-badge" target="_blank" rel="noopener noreferrer">
<i class="fa-brands fa-github" aria-hidden="true"></i> Open Source
Expand Down Expand Up @@ -1530,8 +1530,15 @@ <h3>Computed Math Channels</h3>
<!-- What's New -->
<section class="whats-new-section">
<h2>What's New</h2>
<p class="section-subtitle">RaceChrono lap-timing imports, GPS track maps with satellite imagery, stacked plots, AI-powered analysis via MCP, and more</p>
<p class="section-subtitle">TunerStudio MSL imports, RaceChrono lap-timing sessions, GPS track maps with satellite imagery, stacked plots, AI-powered analysis via MCP, and more</p>
<div class="new-features-grid">
<div class="new-feature-card">
<div class="feature-header">
<div class="feature-icon orange"><i class="fa-solid fa-file-lines" aria-hidden="true"></i></div>
<h3>TunerStudio MSL Imports</h3>
</div>
<p>Open <code>.msl</code> datalogs straight from TunerStudio's legacy ASCII logger — and from RealDash, which writes the same format when it logs a Speeduino over Bluetooth. Units come from the file, GPS columns feed the track map, and cable-free logging sessions load with no conversion step.</p>
</div>
<div class="new-feature-card">
<div class="feature-header">
<div class="feature-icon orange"><i class="fa-solid fa-flag-checkered" aria-hidden="true"></i></div>
Expand Down Expand Up @@ -1753,7 +1760,8 @@ <h2>Supported ECUs</h2>
<span class="ecu-badge supported"><i class="fa-solid fa-circle-check" aria-hidden="true"></i> Motorsport Electronics</span>
<span class="ecu-badge supported"><i class="fa-solid fa-circle-check" aria-hidden="true"></i> DynamicEFI</span>
<span class="ecu-badge supported"><i class="fa-solid fa-circle-check" aria-hidden="true"></i> Locomotive</span>
<span class="ecu-badge new"><i class="fa-solid fa-circle-check" aria-hidden="true"></i> RaceChrono</span>
<span class="ecu-badge supported"><i class="fa-solid fa-circle-check" aria-hidden="true"></i> RaceChrono</span>
<span class="ecu-badge new"><i class="fa-solid fa-circle-check" aria-hidden="true"></i> TunerStudio MSL</span>
</div>
</section>

Expand Down
2 changes: 1 addition & 1 deletion docs/sitemap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
<url>
<loc>https://ultralog.co/</loc>
<lastmod>2026-08-19</lastmod>
<lastmod>2026-08-26</lastmod>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
<image:image>
Expand Down
Loading