Step 2 - LDF Loading: - ldfparser integration (Python) / custom regex parser (C++) - QTreeWidget with expandable signal rows, merged Value column - Hex/Dec toggle, FreeFormat schedule entries, auto-reload - Baud rate auto-detection from LDF Step 3 - Signal Editing: - Bit packing/unpacking (signal value ↔ frame bytes) - ReadOnlyColumnDelegate for per-column editability - Value clamping to signal width, recursion guard Step 4 - Rx Panel: - receive_rx_frame() API with timestamp, signal unpacking - Change highlighting (yellow), auto-scroll toggle, clear button - Dashboard view (in-place update per frame_id) Step 5 - Connection Panel: - ConnectionManager with state machine (Disconnected/Connecting/Connected/Error) - Port scanning (pyserial / QSerialPort), connect/disconnect with UI mapping Step 6 - BabyLIN Backend: - BabyLinBackend wrapping Lipowsky BabyLIN_library.py DLL - Mock mode for macOS/CI, device scan, SDF loading, signal access - Frame callbacks, raw command access Step 7 - Master Scheduler: - QTimer-based schedule execution with start/stop/pause - Frame sent callback with visual highlighting - Mock Rx simulation, manual send, global rate override Tests: Python 171 | C++ 124 (Steps 1-5 parity, Steps 6-7 Python-first) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
68 lines
3.0 KiB
Markdown
68 lines
3.0 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
LIN Master Simulator GUI for BabyLIN hardware devices. Two parallel implementations maintained in feature parity: **Python (PyQt6)** and **C++ (Qt6)**. Each implementation step is built, verified with tests, then the other language catches up before moving forward.
|
|
|
|
## Build & Run Commands
|
|
|
|
### Python
|
|
```bash
|
|
cd python
|
|
pip install -r requirements.txt # one-time setup
|
|
cd src && python main.py # run GUI
|
|
cd .. && python -m pytest tests/ -v # run all tests (from python/)
|
|
python -m pytest tests/test_main_window.py -v # single test file
|
|
python -m pytest tests/test_main_window.py::test_name # single test
|
|
```
|
|
|
|
### C++
|
|
```bash
|
|
cd cpp/build
|
|
cmake .. # one-time setup
|
|
cmake --build . # build (produces lin_simulator, test_main_window)
|
|
./lin_simulator # run GUI
|
|
./test_main_window # run tests
|
|
ctest -V # run tests via CTest
|
|
```
|
|
|
|
## Architecture
|
|
|
|
Both implementations mirror the same GUI layout:
|
|
- **LDF Toolbar** — file path, browse, auto-reload checkbox
|
|
- **Connection Dock** (left, detachable) — device dropdown, baud rate, connect/disconnect, status indicator
|
|
- **Tx Table** (center-top) — master-published frames: name, ID, length, interval, data (hex), signals
|
|
- **Rx Table** (center-bottom) — slave-published frames: timestamp, name, ID, data, signals
|
|
- **Control Bar** (bottom) — schedule table dropdown, global send rate, start/stop/pause, manual send
|
|
- **Status Bar** — connection status
|
|
|
|
### Python-specific
|
|
- `python/src/main.py` — entry point
|
|
- `python/src/main_window.py` — all GUI layout and logic in `MainWindow` class
|
|
- `python/src/ldf_handler.py` — adapter around `ldfparser` library, exports `parse_ldf() -> LdfData` with dataclasses (`LdfData`, `FrameInfo`, `SignalInfo`, `ScheduleTableInfo`)
|
|
|
|
### C++-specific
|
|
- `cpp/src/main.cpp` — entry point
|
|
- `cpp/src/main_window.h/.cpp` — `MainWindow` class with Qt `Q_OBJECT` macro
|
|
- C++ uses camelCase methods (`createMenuBar`) vs Python snake_case (`_create_menu_bar`)
|
|
- Widget member variables use `m_` prefix
|
|
- Uses Qt parent-child ownership for memory management
|
|
|
|
### Testing
|
|
- **Python:** pytest. Tests in `python/tests/`.
|
|
- **C++:** Qt Test (QTest), not GoogleTest. Tests in `cpp/tests/`. One test executable contains all test classes.
|
|
|
|
### Shared Resources
|
|
- `resources/sample.ldf` — test LDF file (LIN 2.1, 2 nodes, 4 frames, 2 schedules, 19200 baud)
|
|
|
|
## Key ldfparser API Notes
|
|
- `ldf.baudrate` is in bps (divide by 1000 for display as kbps)
|
|
- `frame.signal_map` returns list of `(bit_offset, LinSignal)` tuples
|
|
- `frame.publisher` is `LinMaster` or `LinSlave` instance — use `isinstance()` to classify Tx vs Rx
|
|
- Schedule entry `delay` is in seconds — multiply by 1000 for ms
|
|
|
|
## Implementation Roadmap
|
|
See `PLAN.md` for the 8-step plan. Each step is implemented in Python first, then C++, with full test coverage before proceeding.
|