diff --git a/src/openlcb/ConfigRenderer.hxx b/src/openlcb/ConfigRenderer.hxx index 34f5ce0aa..9d5ee7658 100644 --- a/src/openlcb/ConfigRenderer.hxx +++ b/src/openlcb/ConfigRenderer.hxx @@ -51,7 +51,8 @@ struct AtomConfigDefs DECLARE_OPTIONALARG(Name, name, const char *, 0, nullptr); DECLARE_OPTIONALARG(Description, description, const char *, 1, nullptr); DECLARE_OPTIONALARG(MapValues, mapvalues, const char *, 2, nullptr); - using Base = OptionalArg; + DECLARE_OPTIONALARG(SkipInit, skip_init, int, 15, 0); + using Base = OptionalArg; }; /// Configuration implementation class for CDI Atom elements (strings, events @@ -68,6 +69,9 @@ public: DEFINE_OPTIONALARG(Description, description, const char *); /// Represent the value enclosed in the "" tag of the data element. DEFINE_OPTIONALARG(MapValues, mapvalues, const char *); + /// When set to true, the event initializers will be skipped in this event + /// or group. + DEFINE_OPTIONALARG(SkipInit, skip_init, int); void render_cdi(std::string *r) const { @@ -132,7 +136,7 @@ struct NumericConfigDefs : public AtomConfigDefs DECLARE_OPTIONALARG(Max, maxvalue, int, 7, INT_MAX); DECLARE_OPTIONALARG(Default, defaultvalue, int, 8, INT_MAX); using Base = OptionalArg; + Min, Max, Default, SkipInit>; }; /// Definitions for the options for numeric CDI entries. @@ -152,6 +156,7 @@ public: DEFINE_OPTIONALARG(Min, minvalue, int); DEFINE_OPTIONALARG(Max, maxvalue, int); DEFINE_OPTIONALARG(Default, defaultvalue, int); + DEFINE_OPTIONALARG(SkipInit, skip_init, int); void render_cdi(std::string *r) const { @@ -289,6 +294,11 @@ public: } };*/ + constexpr int skip_init() + { + return 0; + } + /// /// @return true if this group is a toplevel CDI definition and shall only /// allow segments and other toplevel-compatible entries (but no data @@ -461,6 +471,11 @@ public: DEFINE_OPTIONALARG(Model, model, const char *); DEFINE_OPTIONALARG(HwVersion, hardware_version, const char *); DEFINE_OPTIONALARG(SwVersion, software_version, const char *); + + constexpr int skip_init() + { + return 0; + } }; /// Helper class for rendering the "" tag. diff --git a/src/openlcb/ConfigRepresentation.cxxtest b/src/openlcb/ConfigRepresentation.cxxtest index d3205db5d..777ab3890 100644 --- a/src/openlcb/ConfigRepresentation.cxxtest +++ b/src/openlcb/ConfigRepresentation.cxxtest @@ -38,6 +38,8 @@ #include "os/TempFile.hxx" #include "openlcb/EventHandler.hxx" +using ::testing::ElementsAre; + namespace openlcb { namespace @@ -105,20 +107,26 @@ TEST(GroupConfig, WithHoles) EXPECT_EQ(31u, cfg.last().offset()); } +using RepHoleTest = RepeatedGroup; + CDI_GROUP(IoBoardSegment, Segment(MemoryConfigDefs::SPACE_CONFIG), Offset(128)); CDI_GROUP_ENTRY(first, Uint8ConfigEntry); +CDI_GROUP_ENTRY(ev, EventConfigEntry); +CDI_GROUP_ENTRY(rgrp, RepHoleTest); CDI_GROUP_END(); CDI_GROUP(SecondSegment, Segment(MemoryConfigDefs::SPACE_CONFIG)); CDI_GROUP_ENTRY(first, Uint8ConfigEntry); +CDI_GROUP_ENTRY(ev, EventConfigEntry); +CDI_GROUP_ENTRY(evtwo, EventConfigEntry, SkipInit(true)); CDI_GROUP_END(); CDI_GROUP(ThirdSegment); CDI_GROUP_ENTRY(first, Uint8ConfigEntry); +CDI_GROUP_ENTRY(ev, EventConfigEntry); CDI_GROUP_END(); - CDI_GROUP(ConfigDef, MainCdi()); CDI_GROUP_ENTRY(ident, Identification); CDI_GROUP_ENTRY(acdi, Acdi); @@ -154,6 +162,17 @@ TEST(FullCdi, SegmentOffset) EXPECT_EQ(13, def.seg3_options().segment()); } +TEST(FullCdi, EventsList) +{ + ConfigDef def(0); + std::vector event_offsets; + def.handle_events([&event_offsets](unsigned o) + { + event_offsets.push_back(o); + }); + EXPECT_THAT(event_offsets, ElementsAre(129, 143, 161, 179, 1)); +} + TempDir dir; TEST(ReadTest, Integers) diff --git a/src/openlcb/ConfigRepresentation.hxx b/src/openlcb/ConfigRepresentation.hxx index 100991f65..92b7140a6 100644 --- a/src/openlcb/ConfigRepresentation.hxx +++ b/src/openlcb/ConfigRepresentation.hxx @@ -100,6 +100,7 @@ public: using Name = AtomConfigOptions::Name; using Description = AtomConfigOptions::Description; using MapValues = AtomConfigOptions::MapValues; + using SkipInit = AtomConfigOptions::SkipInit; using Min = NumericConfigOptions::Min; using Max = NumericConfigOptions::Max; using Default = NumericConfigOptions::Default; @@ -202,8 +203,8 @@ public: { \ return entry(openlcb::EntryMarker()); \ } \ - static constexpr typename decltype( \ - TYPE::config_renderer())::OptionsType NAME##_options() \ + static constexpr typename decltype(TYPE::config_renderer())::OptionsType \ + NAME##_options() \ { \ using SelfType = TYPE; \ using OptionsType = \ @@ -217,11 +218,17 @@ public: TYPE::config_renderer().render_cdi(s, ##__VA_ARGS__); \ } \ void __attribute__((always_inline)) \ - recursive_handle_events(const openlcb::EntryMarker &e, \ - const openlcb::EventOffsetCallback &fn) \ + recursive_handle_events(const openlcb::EntryMarker &e, \ + const openlcb::EventOffsetCallback &fn) \ { \ recursive_handle_events(openlcb::EntryMarker(), fn); \ - entry(e).handle_events(fn); \ + if ((!TYPE(0).group_opts(__VA_ARGS__).is_segment() || \ + TYPE(0).group_opts(__VA_ARGS__).segment() == \ + openlcb::MemoryConfigDefs::SPACE_CONFIG) && \ + NAME##_options().skip_init() == 0) \ + { \ + entry(e).handle_events(fn); \ + } \ } /// Helper macro to generate the code needed at the end of a group.