Program Listing for File parallel_port_trigger.hpp#
↰ Return to documentation for file (src/trigger/parallel_port_trigger.hpp)
#pragma once
#include <QObject>
#include <memory>
#include "core/settings.hpp"
#include "trigger/trigger_types.hpp"
namespace mosaic {
// Monitors a parallel port data register (LPT) for bit-level changes and
// fires TriggerEvents on rising and falling edges.
//
// Implementation:
// Windows + MOSAIC_HAVE_PARALLEL_PORT: dynamically loads InpOut32.dll;
// polls at the rate specified in ParallelPortConfig.pollRateMs.
// All other configurations: stub (always inactive, logs a warning).
//
// Each of the 8 data bits generates its own TriggerEvent with
// source = "parallel_port"
// label = "D<bit>_<RISE|FALL>" e.g. "D3_RISE"
// value = 1.0 (rising) or 0.0 (falling)
//
// Bit polarity: invertLogic = false → active-high (default).
// invertLogic = true → active-low (common in TTL circuits).
class ParallelPortTrigger : public QObject {
Q_OBJECT
public:
explicit ParallelPortTrigger(const ParallelPortConfig& config, QObject* parent = nullptr);
~ParallelPortTrigger() override;
// Loads InpOut32 and starts the polling timer.
[[nodiscard]] bool start();
void stop();
[[nodiscard]] bool is_active() const;
[[nodiscard]] int events_fired() const;
// Drives the Control register's INIT pin (bit 2, portAddr+2) high or low
// — physically separate pins from the Data register this class reads,
// so safe to call regardless of poll state, with no bus-contention risk.
// Bit 2 (INIT) is used deliberately: unlike Control-register bits 0/1/3
// (Strobe/Auto-Feed/Select-In), it is not historically hardware-inverted
// at the DB25 connector on a standard parallel port, so "true → pin high"
// holds without a confusing surprise. No-op if the port failed to open
// or config().sendRecordingMarker is false — callers (TriggerManager)
// should check the latter themselves before calling, but this method
// stays safe to call unconditionally either way.
void set_recording_marker(bool active);
// The configuration this instance was constructed with — lets callers
// (e.g. TriggerManager::start_recording()/stop_recording()) check
// sendRecordingMarker per-instance without needing separate index
// bookkeeping, since portTriggers only contains *enabled* ports.
[[nodiscard]] const ParallelPortConfig& config() const;
signals:
void triggered(mosaic::TriggerEvent event);
void error_occurred(QString message);
private:
struct Impl;
std::unique_ptr<Impl> d;
};
} // namespace mosaic