libtcspc C++ API
Streaming TCSPC and time tag data processing
Loading...
Searching...
No Matches
bh_spc.hpp
1/*
2 * This file is part of libtcspc
3 * Copyright 2019-2026 Board of Regents of the University of Wisconsin System
4 * SPDX-License-Identifier: MIT
5 */
6
7#pragma once
8
9#include "common.hpp"
10#include "core.hpp"
11#include "data_types.hpp"
12#include "int_arith.hpp"
13#include "int_types.hpp"
14#include "introspect.hpp"
15#include "npint.hpp"
16#include "npint_ops.hpp"
17#include "processor.hpp"
18#include "read_integers.hpp"
19#include "time_tagged_events.hpp"
20
21#include <array>
22#include <cstddef>
23#include <ostream>
24#include <span>
25#include <stdexcept>
26#include <type_traits>
27#include <utility>
28
29namespace tcspc {
30
31// Raw photon event data formats are documented in The bh TCSPC Handbook (see
32// section on FIFO Files in the chapter on Data file structure).
33
46 std::array<std::byte, 4> bytes;
47
51 static constexpr u32 macrotime_overflow_period = 1 << 12;
52
56 static constexpr bool has_markers = true;
57
62 [[nodiscard]] constexpr auto adc_value() const noexcept -> u16np {
63 return read_u16le_at<2>(std::span(bytes)) & 0x0fff_u16np;
64 }
65
70 [[nodiscard]] constexpr auto routing_signals() const noexcept -> u8np {
71 // The documentation somewhat confusingly says that these bits are
72 // "inverted", but what they mean is that the TTL inputs are active
73 // low. The bits in the FIFO data are not inverted.
74 return read_u8_at<1>(std::span(bytes)) >> 4;
75 }
76
80 [[nodiscard]] constexpr auto macrotime() const noexcept -> u16np {
81 return read_u16le_at<0>(std::span(bytes)) & 0x0fff_u16np;
82 }
83
87 [[nodiscard]] constexpr auto marker_flag() const noexcept -> bool {
88 return (read_u8_at<3>(std::span(bytes)) & (1_u8np << 4)) != 0_u8np;
89 }
90
94 [[nodiscard]] constexpr auto marker_bits() const noexcept -> u8np {
95 return routing_signals();
96 }
97
101 [[nodiscard]] constexpr auto gap_flag() const noexcept -> bool {
102 return (read_u8_at<3>(std::span(bytes)) & (1_u8np << 5)) != 0_u8np;
103 }
104
108 [[nodiscard]] constexpr auto macrotime_overflow_flag() const noexcept
109 -> bool {
110 return (read_u8_at<3>(std::span(bytes)) & (1_u8np << 6)) != 0_u8np;
111 }
112
116 [[nodiscard]] constexpr auto invalid_flag() const noexcept -> bool {
117 return (read_u8_at<3>(std::span(bytes)) & (1_u8np << 7)) != 0_u8np;
118 }
119
123 [[nodiscard]] constexpr auto
124 is_multiple_macrotime_overflow() const noexcept -> bool {
125 // Although documentation is not clear, a marker can share an event
126 // record with a (single) macrotime overflow, just as a photon can.
128 }
129
134 [[nodiscard]] constexpr auto
136 return read_u32le_at<0>(std::span(bytes)) & 0x0fff'ffff_u32np;
137 }
138
154 static constexpr auto make_photon(u16np macrotime, u16np adc_value,
155 u8np route,
156 bool macrotime_overflow = false)
157 -> bh_spc_event {
158 return make_from_fields(false, macrotime_overflow, false, false,
160 }
161
175 -> bh_spc_event {
176 // N.B. No MTOV.
177 return make_from_fields(true, false, false, false, adc_value, 0_u8np,
178 macrotime);
179 }
180
196 bool macrotime_overflow = false)
197 -> bh_spc_event {
198 return make_from_fields(true, macrotime_overflow, false, true, 0_u16np,
200 }
201
221 bool macrotime_overflow = false) -> bh_spc_event {
222 if ((marker_bits & 0x01_u8np) == 0_u8np)
223 throw std::invalid_argument(
224 "bit for marker 0 must be set in intensity counter event");
225 return make_from_fields(true, macrotime_overflow, false, true, count,
227 }
228
240 -> bh_spc_event {
241 constexpr auto flags = 0b1100'0000_u8np;
242 return bh_spc_event{{
243 std::byte(u8np(count >> 0).value()),
244 std::byte(u8np(count >> 8).value()),
245 std::byte(u8np(count >> 16).value()),
246 std::byte((flags | (u8np(count >> 24) & 0x0f_u8np)).value()),
247 }};
248 }
249
259 auto gap_flag(bool gap) noexcept -> bh_spc_event & {
260 static constexpr auto gap_bit = std::byte(0b0010'0000);
261 bytes[3] = (bytes[3] & ~gap_bit) | (gap ? gap_bit : std::byte(0));
262 return *this;
263 }
264
266 friend auto operator==(bh_spc_event const &lhs,
267 bh_spc_event const &rhs) noexcept -> bool = default;
268
270 friend auto operator<<(std::ostream &strm, bh_spc_event const &e)
271 -> std::ostream & {
272 return strm << "bh_spc(MT=" << e.macrotime()
273 << ", ROUT=" << unsigned(e.routing_signals().value())
274 << ", ADC=" << e.adc_value()
275 << ", INVALID=" << e.invalid_flag()
276 << ", MTOV=" << e.macrotime_overflow_flag()
277 << ", GAP=" << e.gap_flag() << ", MARK=" << e.marker_flag()
278 << ", CNT=" << e.multiple_macrotime_overflow_count()
279 << ")";
280 }
281
282 private:
283 static constexpr auto make_from_fields(bool invalid, bool mtov, bool gap,
284 bool mark, u16np adc, u8np rout,
285 u16np mt) -> bh_spc_event {
286 auto const flags = (u8np(u8(invalid)) << 7) | (u8np(u8(mtov)) << 6) |
287 (u8np(u8(gap)) << 5) | (u8np(u8(mark)) << 4);
288 return bh_spc_event{{
289 std::byte(u8np(mt).value()),
290 std::byte(((rout << 4) | (u8np(mt >> 8) & 0x0f_u8np)).value()),
291 std::byte(u8np(adc).value()),
292 std::byte((flags | (u8np(adc >> 8) & 0x0f_u8np)).value()),
293 }};
294 }
295};
296
307 std::array<std::byte, 6> bytes;
308
312 static constexpr u32 macrotime_overflow_period = 1 << 24;
313
317 static constexpr bool has_markers = false;
318
323 [[nodiscard]] constexpr auto adc_value() const noexcept -> u16np {
324 return read_u16le_at<0>(std::span(bytes)) & 0x0fff_u16np;
325 }
326
331 [[nodiscard]] constexpr auto routing_signals() const noexcept -> u8np {
332 return read_u8_at<3>(std::span(bytes));
333 }
334
338 [[nodiscard]] constexpr auto macrotime() const noexcept -> u32np {
339 auto const lo8 = u32np(read_u8_at<4>(std::span(bytes)));
340 auto const mid8 = u32np(read_u8_at<5>(std::span(bytes)));
341 auto const hi8 = u32np(read_u8_at<2>(std::span(bytes)));
342 return lo8 | (mid8 << 8) | (hi8 << 16);
343 }
344
348 [[nodiscard]] static constexpr auto marker_flag() noexcept -> bool {
349 return false;
350 }
351
355 [[nodiscard]] static constexpr auto marker_bits() noexcept -> u8np {
356 return 0_u8np;
357 }
358
362 [[nodiscard]] constexpr auto gap_flag() const noexcept -> bool {
363 return (read_u8_at<1>(std::span(bytes)) & (1_u8np << 6)) != 0_u8np;
364 }
365
369 [[nodiscard]] constexpr auto macrotime_overflow_flag() const noexcept
370 -> bool {
371 return (read_u8_at<1>(std::span(bytes)) & (1_u8np << 5)) != 0_u8np;
372 }
373
377 [[nodiscard]] constexpr auto invalid_flag() const noexcept -> bool {
378 return (read_u8_at<1>(std::span(bytes)) & (1_u8np << 4)) != 0_u8np;
379 }
380
384 [[nodiscard]] static constexpr auto
386 return false;
387 }
388
393 [[nodiscard]] static constexpr auto
395 return 0_u32np;
396 }
397
413 static constexpr auto make_photon(u32np macrotime, u16np adc_value,
414 u8np route,
415 bool macrotime_overflow = false)
417 return make_from_fields(macrotime, route, false, macrotime_overflow,
418 false, adc_value);
419 }
420
435 bool macrotime_overflow = false)
437 return make_from_fields(macrotime, 0_u8np, false, macrotime_overflow,
438 true, adc_value);
439 }
440
450 auto gap_flag(bool gap) noexcept -> bh_spc600_4096ch_event & {
451 static constexpr auto gap_bit = std::byte(0b0100'0000);
452 bytes[1] = (bytes[1] & ~gap_bit) | (gap ? gap_bit : std::byte(0));
453 return *this;
454 }
455
457 friend auto operator==(bh_spc600_4096ch_event const &lhs,
458 bh_spc600_4096ch_event const &rhs) noexcept
459 -> bool = default;
460
462 friend auto operator<<(std::ostream &strm, bh_spc600_4096ch_event const &e)
463 -> std::ostream & {
464 bool const unused_bit =
465 (read_u8_at<1>(std::span(e.bytes)) & (1_u8np << 7)) != 0_u8np;
466 return strm << "bh_spc600_4096ch(MT=" << e.macrotime()
467 << ", R=" << unsigned(e.routing_signals().value())
468 << ", ADC=" << e.adc_value()
469 << ", INVALID=" << e.invalid_flag()
470 << ", MTOV=" << e.macrotime_overflow_flag()
471 << ", GAP=" << e.gap_flag() << ", bit15=" << unused_bit
472 << ")";
473 }
474
475 private:
476 static constexpr auto make_from_fields(u32np mt, u8np r, bool gap,
477 bool mtov, bool invalid, u16np adc)
479 auto const flags = (u8np(u8(gap)) << 6) | (u8np(u8(mtov)) << 5) |
480 (u8np(u8(invalid)) << 4);
482 std::byte(u8np(adc).value()),
483 std::byte((flags | (u8np(adc >> 8) & 0x0f_u8np)).value()),
484 std::byte(u8np(mt >> 16).value()),
485 std::byte(r.value()),
486 std::byte(u8np(mt >> 0).value()),
487 std::byte(u8np(mt >> 8).value()),
488 }};
489 }
490};
491
502 std::array<std::byte, 4> bytes;
503
507 static constexpr u32 macrotime_overflow_period = 1 << 17;
508
512 static constexpr bool has_markers = false;
513
518 [[nodiscard]] constexpr auto adc_value() const noexcept -> u16np {
519 return u16np(read_u8_at<0>(std::span(bytes)));
520 }
521
526 [[nodiscard]] constexpr auto routing_signals() const noexcept -> u8np {
527 return (read_u8_at<3>(std::span(bytes)) & 0x0f_u8np) >> 1;
528 }
529
533 [[nodiscard]] constexpr auto macrotime() const noexcept -> u32np {
534 auto const lo8 = u32np(read_u8_at<1>(std::span(bytes)));
535 auto const mid8 = u32np(read_u8_at<2>(std::span(bytes)));
536 auto const hi1 = u32np(read_u8_at<3>(std::span(bytes))) & 1_u32np;
537 return lo8 | (mid8 << 8) | (hi1 << 16);
538 }
539
543 [[nodiscard]] static constexpr auto marker_flag() noexcept -> bool {
544 return false;
545 }
546
550 [[nodiscard]] static constexpr auto marker_bits() noexcept -> u8np {
551 return 0_u8np;
552 }
553
557 [[nodiscard]] constexpr auto gap_flag() const noexcept -> bool {
558 return (read_u8_at<3>(std::span(bytes)) & (1_u8np << 5)) != 0_u8np;
559 }
560
564 [[nodiscard]] constexpr auto macrotime_overflow_flag() const noexcept
565 -> bool {
566 return (read_u8_at<3>(std::span(bytes)) & (1_u8np << 6)) != 0_u8np;
567 }
568
572 [[nodiscard]] constexpr auto invalid_flag() const noexcept -> bool {
573 return (read_u8_at<3>(std::span(bytes)) & (1_u8np << 7)) != 0_u8np;
574 }
575
579 [[nodiscard]] constexpr auto
580 is_multiple_macrotime_overflow() const noexcept -> bool {
582 }
583
588 [[nodiscard]] constexpr auto
590 return read_u32le_at<0>(std::span(bytes)) & 0x0fff'ffff_u32np;
591 }
592
608 static constexpr auto make_photon(u32np macrotime, u8np adc_value,
609 u8np route,
610 bool macrotime_overflow = false)
612 return make_from_fields(false, macrotime_overflow, false, route,
614 }
615
630 // N.B. No MTOV.
631 return make_from_fields(true, false, false, 0_u8np, macrotime,
632 adc_value);
633 }
634
647 constexpr auto flags = 0b1100'0000_u8np;
648 return bh_spc600_256ch_event{{
649 std::byte(u8np(count >> 0).value()),
650 std::byte(u8np(count >> 8).value()),
651 std::byte(u8np(count >> 16).value()),
652 std::byte((flags | (u8np(count >> 24) & 0x0f_u8np)).value()),
653 }};
654 }
655
665 auto gap_flag(bool gap) noexcept -> bh_spc600_256ch_event & {
666 static constexpr auto gap_bit = std::byte(0b0010'0000);
667 bytes[3] = (bytes[3] & ~gap_bit) | (gap ? gap_bit : std::byte(0));
668 return *this;
669 }
670
672 friend auto operator==(bh_spc600_256ch_event const &lhs,
673 bh_spc600_256ch_event const &rhs) noexcept
674 -> bool = default;
675
677 friend auto operator<<(std::ostream &strm, bh_spc600_256ch_event const &e)
678 -> std::ostream & {
679 bool const unused_bit =
680 (read_u8_at<3>(std::span(e.bytes)) & (1_u8np << 4)) != 0_u8np;
681 return strm << "bh_spc600_256ch(MT=" << e.macrotime()
682 << ", R=" << unsigned(e.routing_signals().value())
683 << ", ADC=" << e.adc_value()
684 << ", INVALID=" << e.invalid_flag()
685 << ", MTOV=" << e.macrotime_overflow_flag()
686 << ", GAP=" << e.gap_flag() << ", bit28=" << unused_bit
687 << ", CNT=" << e.multiple_macrotime_overflow_count()
688 << ")";
689 }
690
691 private:
692 static constexpr auto make_from_fields(bool invalid, bool mtov, bool gap,
693 u8np r, u32np mt, u8np adc)
695 auto const flags = (u8np(u8(invalid)) << 7) | (u8np(u8(mtov)) << 6) |
696 (u8np(u8(gap)) << 5);
697 return bh_spc600_256ch_event{{
698 std::byte(adc.value()),
699 std::byte(u8np(mt).value()),
700 std::byte(u8np(mt >> 8).value()),
701 std::byte((flags | ((r << 1) & 0b1110_u8np) |
702 (u8np(mt >> 16) & 0x01_u8np))
703 .value()),
704 }};
705 }
706};
707
708namespace internal {
709
710// Common implementation for decode_bh_spc*.
711// BHEvent is the binary record event class.
712template <typename DataTypes, typename BHSPCEvent, bool HasIntensityCounter,
713 typename Downstream>
714class decode_bh_spc {
715 static_assert(
716 same_as_any_of<BHSPCEvent, bh_spc_event, bh_spc600_256ch_event,
717 bh_spc600_4096ch_event>);
718
719 static_assert(processor<Downstream, time_reached_event<DataTypes>,
720 time_correlated_detection_event<DataTypes>,
721 data_lost_event<DataTypes>, warning_event>);
722 static_assert(handler_for<Downstream, bulk_counts_event<DataTypes>> ||
723 not HasIntensityCounter);
724 static_assert(handler_for<Downstream, marker_event<DataTypes>> ||
725 not BHSPCEvent::has_markers);
726
727 // 32-bit abstime can work for a few seconds, though 64-bit is recommended.
728 static_assert(sizeof(typename DataTypes::abstime_type) >= 4);
729
730 static_assert(std::in_range<typename DataTypes::channel_type>(255) ||
731 (not std::is_same_v<BHSPCEvent, bh_spc600_4096ch_event> &&
732 std::in_range<typename DataTypes::channel_type>(15)));
733
734 static_assert(std::in_range<typename DataTypes::difftime_type>(4095) ||
735 (std::is_same_v<BHSPCEvent, bh_spc600_256ch_event> &&
736 std::in_range<typename DataTypes::difftime_type>(255)));
737
738 static_assert(std::in_range<typename DataTypes::count_type>(4095) ||
739 not HasIntensityCounter);
740
741 using abstime_type = typename DataTypes::abstime_type;
742
743 abstime_type abstime_base = 0; // Time of last overflow
744
745 Downstream downstream;
746
747 LIBTCSPC_NOINLINE void issue_warning(char const *message) {
748 downstream.handle(warning_event{message});
749 }
750
751 void handle_bh(BHSPCEvent const &event) {
752 if (event.is_multiple_macrotime_overflow()) {
753 abstime_base +=
754 abstime_type(BHSPCEvent::macrotime_overflow_period) *
755 event.multiple_macrotime_overflow_count().value();
756 if (event.gap_flag())
757 downstream.handle(data_lost_event<DataTypes>{abstime_base});
758 return downstream.handle(
759 time_reached_event<DataTypes>{abstime_base});
760 }
761
762 if (event.macrotime_overflow_flag())
763 abstime_base += BHSPCEvent::macrotime_overflow_period;
764 abstime_type const abstime = abstime_base + event.macrotime().value();
765
766 if (event.gap_flag())
767 downstream.handle(data_lost_event<DataTypes>{abstime});
768
769 if (not event.marker_flag()) {
770 if (not event.invalid_flag()) { // Valid photon
771 downstream.handle(time_correlated_detection_event<DataTypes>{
772 abstime, event.routing_signals().value(),
773 event.adc_value().value()});
774 } else { // Invalid photon
775 downstream.handle(time_reached_event<DataTypes>{abstime});
776 }
777 } else {
778 if (event.invalid_flag()) { // Marker
779 auto const bits = u32np(event.marker_bits());
780 if constexpr (HasIntensityCounter) { // SPC-160, 180N
781 if ((bits & 0x01_u32np) != 0_u32np) // Marker 0
782 downstream.handle(bulk_counts_event<DataTypes>{
783 abstime, -1, event.adc_value().value()});
784 }
785 if constexpr (BHSPCEvent::has_markers) {
786 for_each_set_bit(bits, [&](int b) {
787 downstream.handle(marker_event<DataTypes>{
788 abstime,
789 static_cast<typename DataTypes::channel_type>(b)});
790 });
791 }
792 } else {
793 // Although not clearly documented, the combination of
794 // INV=0, MARK=1 is not currently used.
795 issue_warning(
796 "unexpected BH SPC event flags: marker bit set but invalid bit cleared");
797 }
798 }
799 }
800
801 public:
802 explicit decode_bh_spc(Downstream downstream)
803 : downstream(std::move(downstream)) {}
804
805 [[nodiscard]] auto introspect_node() const -> processor_info {
806 return processor_info(this, "decode_bh_spc");
807 }
808
809 [[nodiscard]] auto introspect_graph() const -> processor_graph {
810 return downstream.introspect_graph().push_entry_point(this);
811 }
812
813 template <typename Event>
814 requires std::convertible_to<std::remove_cvref_t<Event>, BHSPCEvent>
815 void handle(Event &&event) {
816 handle_bh(event);
817 }
818
819 template <typename Event>
820 requires(
821 not std::convertible_to<std::remove_cvref_t<Event>, BHSPCEvent> and
822 handler_for<Downstream, std::remove_cvref_t<Event>>)
823 void handle(Event &&event) {
824 downstream.handle(std::forward<Event>(event));
825 }
826
827 void flush() { downstream.flush(); }
828};
829
830} // namespace internal
831
863template <typename DataTypes = default_data_types, typename Downstream>
864auto decode_bh_spc(Downstream downstream) {
865 return internal::decode_bh_spc<DataTypes, bh_spc_event, false, Downstream>(
866 std::move(downstream));
867}
868
896template <typename DataTypes = default_data_types, typename Downstream>
897auto decode_bh_spc_with_intensity_counter(Downstream downstream) {
898 return internal::decode_bh_spc<DataTypes, bh_spc_event, true, Downstream>(
899 std::move(downstream));
900}
901
925template <typename DataTypes = default_data_types, typename Downstream>
926auto decode_bh_spc600_4096ch(Downstream downstream) {
927 return internal::decode_bh_spc<DataTypes, bh_spc600_4096ch_event, false,
928 Downstream>(std::move(downstream));
929}
930
954template <typename DataTypes = default_data_types, typename Downstream>
955auto decode_bh_spc600_256ch(Downstream downstream) {
956 return internal::decode_bh_spc<DataTypes, bh_spc600_256ch_event, false,
957 Downstream>(std::move(downstream));
958}
959
960} // namespace tcspc
npint< u32 > u32np
Non-promoted unsigned 32-bit integer.
Definition npint.hpp:306
constexpr auto read_u8_at(std::span< T, N > bytes) noexcept -> u8np
Read an 8-bit unsigned integer from bytes at offset.
Definition read_integers.hpp:77
constexpr auto read_u32le_at(std::span< T, N > bytes) noexcept -> u32np
Read a little-endian 32-bit unsigned integer from bytes at offset.
Definition read_integers.hpp:102
npint< u8 > u8np
Non-promoted unsigned 8-bit integer.
Definition npint.hpp:292
npint< u16 > u16np
Non-promoted unsigned 16-bit integer.
Definition npint.hpp:299
constexpr auto read_u16le_at(std::span< T, N > bytes) noexcept -> u16np
Read a little-endian 16-bit unsigned integer from bytes at offset.
Definition read_integers.hpp:90
auto decode_bh_spc600_256ch(Downstream downstream)
Create a processor that decodes 32-bit FIFO records from Becker & Hickl SPC-600/630 in 256-channel mo...
Definition bh_spc.hpp:955
auto decode_bh_spc(Downstream downstream)
Create a processor that decodes FIFO records from most Becker & Hickl SPC models.
Definition bh_spc.hpp:864
auto decode_bh_spc600_4096ch(Downstream downstream)
Create a processor that decodes 48-bit FIFO records from Becker & Hickl SPC-600/630 in 4096-channel m...
Definition bh_spc.hpp:926
auto decode_bh_spc_with_intensity_counter(Downstream downstream)
Create a processor that decodes FIFO records from Becker & Hickl SPC-160 and SPC-180N with fast inten...
Definition bh_spc.hpp:897
auto route(Router router, Downstreams... downstreams)
Create a processor that routes events to different downstreams.
Definition route.hpp:250
auto count(access_tracker< count_access > &&tracker, Downstream downstream)
Create a processor that counts events of a given type.
Definition count.hpp:313
std::uint8_t u8
Short name for uint8_t.
Definition int_types.hpp:24
std::uint32_t u32
Short name for uint32_t.
Definition int_types.hpp:30
libtcspc namespace.
Definition acquire.hpp:29
Binary record interpretation for raw events from SPC-600/630 in 256-channel mode.
Definition bh_spc.hpp:498
static constexpr u32 macrotime_overflow_period
The macrotime overflow period of this event type.
Definition bh_spc.hpp:507
static constexpr auto marker_flag() noexcept -> bool
Read the 'marker' flag.
Definition bh_spc.hpp:543
constexpr auto macrotime_overflow_flag() const noexcept -> bool
Read the 'macrotime overflow' flag.
Definition bh_spc.hpp:564
static constexpr auto make_multiple_macrotime_overflow(u32np count) -> bh_spc600_256ch_event
Make an event representing a multiple macrotime overflow.
Definition bh_spc.hpp:645
static constexpr auto make_photon(u32np macrotime, u8np adc_value, u8np route, bool macrotime_overflow=false) -> bh_spc600_256ch_event
Make an event representing a valid photon event.
Definition bh_spc.hpp:608
std::array< std::byte, 4 > bytes
Bytes of the 32-bit raw device event.
Definition bh_spc.hpp:502
constexpr auto invalid_flag() const noexcept -> bool
Read the 'invalid' flag.
Definition bh_spc.hpp:572
constexpr auto macrotime() const noexcept -> u32np
Read the macrotime counter value (no rollover correction).
Definition bh_spc.hpp:533
constexpr auto gap_flag() const noexcept -> bool
Read the 'gap' (data lost) flag.
Definition bh_spc.hpp:557
auto gap_flag(bool gap) noexcept -> bh_spc600_256ch_event &
Set or clear the gap flag of this event.
Definition bh_spc.hpp:665
constexpr auto is_multiple_macrotime_overflow() const noexcept -> bool
Determine if this event represents multiple macrotime overflows.
Definition bh_spc.hpp:580
constexpr auto multiple_macrotime_overflow_count() const noexcept -> u32np
Read the macrotime overflow count if this event represents multiple macrotime overflows.
Definition bh_spc.hpp:589
friend auto operator<<(std::ostream &strm, bh_spc600_256ch_event const &e) -> std::ostream &
Stream insertion operator.
Definition bh_spc.hpp:677
constexpr auto adc_value() const noexcept -> u16np
Read the ADC value (i.e., difference time) if this event represents a photon.
Definition bh_spc.hpp:518
static constexpr bool has_markers
Whether this event type can represent marker events.
Definition bh_spc.hpp:512
constexpr auto routing_signals() const noexcept -> u8np
Read the routing signals (usually the detector channel) if this event represents a photon.
Definition bh_spc.hpp:526
friend auto operator==(bh_spc600_256ch_event const &lhs, bh_spc600_256ch_event const &rhs) noexcept -> bool=default
Equality comparison operator.
static constexpr auto make_invalid_photon(u32np macrotime, u8np adc_value) -> bh_spc600_256ch_event
Make an event representing an invalid photon event.
Definition bh_spc.hpp:628
static constexpr auto marker_bits() noexcept -> u8np
Read the marker bits (mask) if this event represents markers.
Definition bh_spc.hpp:550
Binary record interpretation for raw events from SPC-600/630 in 4096-channel mode.
Definition bh_spc.hpp:303
static constexpr auto make_photon(u32np macrotime, u16np adc_value, u8np route, bool macrotime_overflow=false) -> bh_spc600_4096ch_event
Make an event representing a valid photon event.
Definition bh_spc.hpp:413
constexpr auto macrotime() const noexcept -> u32np
Read the macrotime counter value (no rollover correction).
Definition bh_spc.hpp:338
static constexpr u32 macrotime_overflow_period
The macrotime overflow period of this event type.
Definition bh_spc.hpp:312
constexpr auto gap_flag() const noexcept -> bool
Read the 'gap' (data lost) flag.
Definition bh_spc.hpp:362
friend auto operator==(bh_spc600_4096ch_event const &lhs, bh_spc600_4096ch_event const &rhs) noexcept -> bool=default
Equality comparison operator.
static constexpr auto multiple_macrotime_overflow_count() noexcept -> u32np
Read the macrotime overflow count if this event represents multiple macrotime overflows.
Definition bh_spc.hpp:394
friend auto operator<<(std::ostream &strm, bh_spc600_4096ch_event const &e) -> std::ostream &
Stream insertion operator.
Definition bh_spc.hpp:462
auto gap_flag(bool gap) noexcept -> bh_spc600_4096ch_event &
Set or clear the gap flag of this event.
Definition bh_spc.hpp:450
static constexpr auto is_multiple_macrotime_overflow() noexcept -> bool
Determine if this event represents multiple macrotime overflows.
Definition bh_spc.hpp:385
static constexpr auto marker_bits() noexcept -> u8np
Read the marker bits (mask) if this event represents markers.
Definition bh_spc.hpp:355
static constexpr bool has_markers
Whether this event type can represent marker events.
Definition bh_spc.hpp:317
static constexpr auto make_invalid_photon(u32np macrotime, u16np adc_value, bool macrotime_overflow=false) -> bh_spc600_4096ch_event
Make an event representing an invalid photon event.
Definition bh_spc.hpp:434
std::array< std::byte, 6 > bytes
Bytes of the 48-bit raw device event.
Definition bh_spc.hpp:307
constexpr auto routing_signals() const noexcept -> u8np
Read the routing signals (usually the detector channel) if this event represents a photon.
Definition bh_spc.hpp:331
static constexpr auto marker_flag() noexcept -> bool
Read the 'marker' flag.
Definition bh_spc.hpp:348
constexpr auto macrotime_overflow_flag() const noexcept -> bool
Read the 'macrotime overflow' flag.
Definition bh_spc.hpp:369
constexpr auto adc_value() const noexcept -> u16np
Read the ADC value (i.e., difference time) if this event represents a photon.
Definition bh_spc.hpp:323
constexpr auto invalid_flag() const noexcept -> bool
Read the 'invalid' flag.
Definition bh_spc.hpp:377
Binary record interpretation for raw BH SPC event.
Definition bh_spc.hpp:42
static constexpr auto make_marker(u16np macrotime, u8np marker_bits, bool macrotime_overflow=false) -> bh_spc_event
Make an event representing a marker.
Definition bh_spc.hpp:195
std::array< std::byte, 4 > bytes
Bytes of the 32-bit raw device event.
Definition bh_spc.hpp:46
auto gap_flag(bool gap) noexcept -> bh_spc_event &
Set or clear the gap flag of this event.
Definition bh_spc.hpp:259
constexpr auto invalid_flag() const noexcept -> bool
Read the 'invalid' flag.
Definition bh_spc.hpp:116
constexpr auto macrotime_overflow_flag() const noexcept -> bool
Read the 'macrotime overflow' flag.
Definition bh_spc.hpp:108
static constexpr auto make_photon(u16np macrotime, u16np adc_value, u8np route, bool macrotime_overflow=false) -> bh_spc_event
Make an event representing a valid photon event.
Definition bh_spc.hpp:154
static constexpr auto make_invalid_photon(u16np macrotime, u16np adc_value) -> bh_spc_event
Make an event representing an invalid photon event.
Definition bh_spc.hpp:174
constexpr auto adc_value() const noexcept -> u16np
Read the ADC value (i.e., difference time) if this event represents a photon.
Definition bh_spc.hpp:62
friend auto operator==(bh_spc_event const &lhs, bh_spc_event const &rhs) noexcept -> bool=default
Equality comparison operator.
friend auto operator<<(std::ostream &strm, bh_spc_event const &e) -> std::ostream &
Stream insertion operator.
Definition bh_spc.hpp:270
constexpr auto marker_flag() const noexcept -> bool
Read the 'marker' flag.
Definition bh_spc.hpp:87
constexpr auto routing_signals() const noexcept -> u8np
Read the routing signals (usually the detector channel) if this event represents a photon.
Definition bh_spc.hpp:70
constexpr auto multiple_macrotime_overflow_count() const noexcept -> u32np
Read the macrotime overflow count if this event represents multiple macrotime overflows.
Definition bh_spc.hpp:135
constexpr auto macrotime() const noexcept -> u16np
Read the macrotime counter value (no rollover correction).
Definition bh_spc.hpp:80
constexpr auto marker_bits() const noexcept -> u8np
Read the marker bits (mask) if this event represents markers.
Definition bh_spc.hpp:94
static constexpr u32 macrotime_overflow_period
The macrotime overflow period of this event type.
Definition bh_spc.hpp:51
static constexpr auto make_multiple_macrotime_overflow(u32np count) -> bh_spc_event
Make an event representing a multiple macrotime overflow.
Definition bh_spc.hpp:239
constexpr auto is_multiple_macrotime_overflow() const noexcept -> bool
Determine if this event represents multiple macrotime overflows.
Definition bh_spc.hpp:124
static constexpr auto make_marker0_with_intensity_count(u16np macrotime, u8np marker_bits, u16np count, bool macrotime_overflow=false) -> bh_spc_event
Make an event representing a marker, with marker 0 intensity count as generated by SPC-160 and SPC-18...
Definition bh_spc.hpp:219
constexpr auto gap_flag() const noexcept -> bool
Read the 'gap' (data lost) flag.
Definition bh_spc.hpp:101
static constexpr bool has_markers
Whether this event type can represent marker events.
Definition bh_spc.hpp:56