2025-12-12: CosmicDetector Class - Class-Based Detection API (v1.15.7)¶
Status: Implemented ✅ Scope: Unified protocol path (ENABLE_DEVICE_RESPONSE=1 only) Impact: New class-based API, clean separation from legacy procedural API
Overview¶
Created a modern C++ class-based detection API (CosmicDetector) exclusively for the unified protocol path (ENABLE_DEVICE_RESPONSE=1). The legacy procedural cosmic_detector API remains unchanged, providing clean separation between two independent implementations.
Design Principle: Clean Separation
- Unified path (ENABLE_DEVICE_RESPONSE=1): New detector.h with CosmicDetector class
- Legacy path (ENABLE_DEVICE_RESPONSE=0): Existing cosmic_detector.h (unchanged)
- Zero coupling: No shared code, files, or dependencies between paths
Architecture¶
CosmicDetector Class (New)¶
Location: include/detector.h, src/detector.cpp
Pattern: Static class (similar to Command, DetectionProcessor, EventQueue)
class CosmicDetector {
public:
static void init(void);
static cosmic_detection_t read(void); // Fetches config from Command internally
static void reset(void);
private:
static int detector_hit1;
static int detector_hit2;
static int detector_hit3;
static unsigned long last_detection_time;
static void poll_gpio(uint16_t poll_count);
static bool check_deadtime(unsigned long current_time, uint16_t deadtime_ms);
};
Key Features¶
- Configuration Integration
- Fetches
poll_countfromCommand::getInstance().get_poll_count() - Fetches
deadtime_msfromCommand::getInstance().get_deadtime() -
Changes via Command take effect immediately on next
read() -
GPIO Abstraction
- Supports both direct register access (ENABLE_GPIO_ABSTRACTION=0, default)
- And HAL API via
gpio_get_level()(ENABLE_GPIO_ABSTRACTION=1) -
Same abstraction as original cosmic_detector
-
Deadtime Filtering
- Dynamic suppression of detections within configured deadtime window
- 0 ms = report all detections
-
0 ms = suppress detections within window since last reported detection
-
Clean API Surface
- No LED functions (delegated to led_manager)
- No configuration parameters (fetched internally)
- Three methods: init(), read(), reset()
Comparison: Legacy vs. Unified¶
| Aspect | Legacy (cosmic_detector.h) | Unified (detector.h) |
|---|---|---|
| Path | ENABLE_DEVICE_RESPONSE=0 | ENABLE_DEVICE_RESPONSE=1 |
| API | Procedural C functions | Static C++ class |
| Config source | runtime_config.h / config_get_*() | Command singleton |
| Compilation | Always compiled | Only in unified builds |
| LED functions | Included (led_feedback, led_off, led_set) | Removed (use led_manager) |
| Files | cosmic_detector.h/cpp | detector.h/cpp |
Implementation Details¶
Files Created¶
- include/detector.h (~200 lines)
- CosmicDetector class definition
- cosmic_detection_t type (duplicate of cosmic_detector.h)
- Comprehensive JSDoc documentation
-
Wrapped in
#if ENABLE_DEVICE_RESPONSEguard -
src/detector.cpp (~150 lines)
- Static member initialization
- Implementation of init(), read(), reset()
- Private helpers: poll_gpio(), check_deadtime()
- Wrapped in
#if ENABLE_DEVICE_RESPONSEguard
Files Modified¶
- src/detection_processor.cpp
- Changed include:
cosmic_detector.h→detector.h - Updated read_detection():
cosmic_detector_read()→CosmicDetector::read() -
Updated reset():
cosmic_detector_reset()→CosmicDetector::reset() -
src/main_next.cpp
- Changed include:
cosmic_detector.h→detector.h -
Updated setup():
cosmic_detector_init()→CosmicDetector::init() -
CLAUDE.md
- Added detector.h documentation to Core Modules section
- Clarified legacy vs. unified path APIs
- Cross-referenced both implementations
Files NOT Modified¶
- src/cosmic_detector.cpp - Unchanged (legacy path)
- include/cosmic_detector.h - Unchanged (legacy path)
- src/main.cpp - Unchanged (legacy path)
Testing¶
Build Verification¶
Both build paths tested successfully:
# Legacy path (ENABLE_DEVICE_RESPONSE=0)
task prod:build # SUCCESS ✅
task debug:build # SUCCESS ✅
# Unified path (ENABLE_DEVICE_RESPONSE=1)
task dev:build # SUCCESS ✅
Results: - Legacy build: 26.2% Flash (343KB), 8.1% RAM (26.5KB) - Unified build: 26.6% Flash (348KB), 8.8% RAM (28.7KB) - Size increase: +5KB Flash, +2KB RAM (acceptable overhead for unified protocol)
Runtime Testing¶
(To be completed upon hardware deployment)
- Test detection with
task dev:upload && task monitor - Verify LED feedback via led_manager
- Test dynamic configuration: SET_POLL_COUNT command
- Test dynamic deadtime: SET_DEADTIME command
- Verify config changes take effect immediately
Benefits¶
- Clean Architecture
- Matches established patterns (Command, DetectionProcessor, EventQueue)
- Unified protocol has modern C++ API
-
Legacy path unaffected by changes
-
No Configuration Coupling
- Detection logic independent of runtime_config.h
- Configuration fetched from single Command singleton
-
Changes via Command take effect immediately
-
Improved Separation of Concerns
- GPIO sampling: poll_gpio() private method
- Deadtime filtering: check_deadtime() private method
- Initialization: init() method
-
All responsibilities clearly separated
-
Reduced Code Duplication
- Removed LED functions from detection module
-
All callers use led_manager directly
-
Better Testability
- Static class interface clear and explicit
- Configuration source (Command) easy to understand
- No hidden global state in API
Code Examples¶
Setup (main_next.cpp)¶
void setup() {
// ... other initialization ...
CosmicDetector::init();
DetectionProcessor::init();
CommandQueue::init();
EventQueue::init();
}
Event Processing (detection_processor.cpp)¶
bool DetectionProcessor::read_detection(detection_result_t* result) {
cosmic_detection_t cosmic_detection = CosmicDetector::read();
result->hit1 = cosmic_detection.hit1;
result->hit2 = cosmic_detection.hit2;
result->hit3 = cosmic_detection.hit3;
result->detected = cosmic_detection.detected;
return cosmic_detection.detected;
}
Notes¶
-
No LED Functions: The unified path does not include LED functions from cosmic_detector. All LED control uses
led_manager.hfunctions instead (led_feedback, led_off, led_set). -
Configuration at Runtime: Unlike the procedural API, CosmicDetector always fetches configuration from Command at read() time. This enables immediate effect of SET_POLL_COUNT and SET_DEADTIME commands without re-initialization.
-
Dynamic Type Definition: cosmic_detection_t is defined in both detector.h and cosmic_detector.h. This duplication is intentional to maintain clean separation between paths.
-
Version Marker: This refactoring is marked as v1.15.7 in documentation, though the actual version bump (1.15.6 → 1.15.7) will occur when merged to main.
Future Considerations¶
- Unified Configuration Abstraction: Could create ConfigProvider interface to abstract Command access, further improving testability
- Unit Testing: detector.cpp is a good candidate for unit tests (static interface, clear dependencies)
- Optional Decoupling: Could pass configuration as parameters if needed for specific use cases
References¶
- Architecture: Similar patterns to
Commandclass,DetectionProcessorclass,EventQueueclass - GPIO Abstraction: Uses same ENABLE_GPIO_ABSTRACTION flag as cosmic_detector
- Configuration: Integrates with Command singleton (v1.13.0+)