Conventions for contributing to this repository. The authoritative C++ formatter is
.clang-format; the points below cover what a formatter can't enforce.
- Use C++20 for
trigger_firmwareandcomm_protocol(the highest standard supported byarduino-esp32 3.xby default). Use C++23 forrecorder. - Build with CMake (
recorder,comm_protocol) and PlatformIO (trigger_firmware).recorderandtrigger_firmwarecompile on their own;comm_protocolis a library included by both but can also be configured standalone to build and run its unit tests. See Installation & compilation and Unit testing.
-
Use the style specified in
.clang-formatand.clang-tidy.clang-format (formatting): run periodically on all tracked source files from the repo root:
git ls-files '*.cc' '*.h' | xargs clang-format -iclang-tidy (naming and code quality): requires a built
recorder/build(forcompile_commands.json; this also coverscomm_protocol). This should take about a minute. Most warnings are probably related to external libraries and are already supressed; these are safe to ignore. Check:run-clang-tidy -quiet -p recorder/build '.*spotlight-control/(recorder|comm_protocol)/(src|tests)/.*'Apply fixes automatically:
run-clang-tidy -quiet -fix -p recorder/build '.*spotlight-control/(recorder|comm_protocol)/(src|tests)/.*' -
Use snake_case for file names, function names, variable names, and enum values, with
.ccand.hsuffixes. -
Use PascalCase for class, struct, enum, and type alias names (e.g.
RecorderConfig,FrameData). -
Private member variables end with a trailing underscore (e.g.
image_width_). Public members and all functions have no suffix. -
Namespaces are lowercase (e.g.
namespace config). -
Use Google style for documentation in header files:
//comment lines, not/* */blocks. -
When labelling arguments at a call site (e.g. for boolean flags or otherwise ambiguous literals), use the
/*name=*/valuestyle rather than a trailing// namecomment:// preferred (use new lines if needed) MuscleTriggerTiming timing(behavior_fps, /*sync_ratio=*/1, /*light_on=*/5000); // avoid MuscleTriggerTiming timing(behavior_fps, 1, // sync_ratio 5000 // light_on );
-
Keep documentation complete but concise. Assume the user has a certain level of technical know-how. Don't write docs just for the sake of it; make sure it's meaningful.
-
Use
#pragma onceinstead of#ifndefguards in header files. -
Use only ASCII characters except in
.mdfiles.
- Follow best practices in using
constand pass arguments by reference when applicable. - Write comments whenever the logic is unclear/non-trivial. Don't hard-code "magic numbers" or "magic logic."
- Mind overhead: prefer low overhead for
trigger_firmwareandcomm_protocol(andcomm_protocolmust avoid exceptions, to respect the linear workflow on the microcontroller). Forrecorder, be mindful of overhead since frame acquisition can run at up to ~500 FPS — but don't over-optimize at the cost of readability. - Write meaningful unit tests only. Don't write tests just for the sake of it, and don't bloat test files to test trivial things.