Skip to content

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

  1. Configuration Integration
  2. Fetches poll_count from Command::getInstance().get_poll_count()
  3. Fetches deadtime_ms from Command::getInstance().get_deadtime()
  4. Changes via Command take effect immediately on next read()

  5. GPIO Abstraction

  6. Supports both direct register access (ENABLE_GPIO_ABSTRACTION=0, default)
  7. And HAL API via gpio_get_level() (ENABLE_GPIO_ABSTRACTION=1)
  8. Same abstraction as original cosmic_detector

  9. Deadtime Filtering

  10. Dynamic suppression of detections within configured deadtime window
  11. 0 ms = report all detections
  12. 0 ms = suppress detections within window since last reported detection

  13. Clean API Surface

  14. No LED functions (delegated to led_manager)
  15. No configuration parameters (fetched internally)
  16. 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

  1. include/detector.h (~200 lines)
  2. CosmicDetector class definition
  3. cosmic_detection_t type (duplicate of cosmic_detector.h)
  4. Comprehensive JSDoc documentation
  5. Wrapped in #if ENABLE_DEVICE_RESPONSE guard

  6. src/detector.cpp (~150 lines)

  7. Static member initialization
  8. Implementation of init(), read(), reset()
  9. Private helpers: poll_gpio(), check_deadtime()
  10. Wrapped in #if ENABLE_DEVICE_RESPONSE guard

Files Modified

  1. src/detection_processor.cpp
  2. Changed include: cosmic_detector.hdetector.h
  3. Updated read_detection(): cosmic_detector_read()CosmicDetector::read()
  4. Updated reset(): cosmic_detector_reset()CosmicDetector::reset()

  5. src/main_next.cpp

  6. Changed include: cosmic_detector.hdetector.h
  7. Updated setup(): cosmic_detector_init()CosmicDetector::init()

  8. CLAUDE.md

  9. Added detector.h documentation to Core Modules section
  10. Clarified legacy vs. unified path APIs
  11. 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

  1. Clean Architecture
  2. Matches established patterns (Command, DetectionProcessor, EventQueue)
  3. Unified protocol has modern C++ API
  4. Legacy path unaffected by changes

  5. No Configuration Coupling

  6. Detection logic independent of runtime_config.h
  7. Configuration fetched from single Command singleton
  8. Changes via Command take effect immediately

  9. Improved Separation of Concerns

  10. GPIO sampling: poll_gpio() private method
  11. Deadtime filtering: check_deadtime() private method
  12. Initialization: init() method
  13. All responsibilities clearly separated

  14. Reduced Code Duplication

  15. Removed LED functions from detection module
  16. All callers use led_manager directly

  17. Better Testability

  18. Static class interface clear and explicit
  19. Configuration source (Command) easy to understand
  20. 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.h functions 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 Command class, DetectionProcessor class, EventQueue class
  • GPIO Abstraction: Uses same ENABLE_GPIO_ABSTRACTION flag as cosmic_detector
  • Configuration: Integrates with Command singleton (v1.13.0+)