Week 4 ended with the minimal waterfall sink. This week it landed on main and caught up to the line sink having complex and float inputs, a Display Domain dropdown, the same cyber_context lifecycle. Then I removed a GRC option that turned out to do nothing, fixed a binding-order bug.

Waterfall sink

The minimal waterfall from week 4 merged via PR #4. Once it was on main, bringing it up to the line sink’s level was mostly applying patterns that already existed.

Input types first. The same recipe the line sink got in week 4, a class template with per-type explicit instantiations and a GRC dropdown mapping:

typedef cyber_waterfall_sink<gr_complex> cyber_waterfall_sink_c;
typedef cyber_waterfall_sink<float>      cyber_waterfall_sink_f;

Float inputs get imag = 0 on the way into the CF32 display tensor, exactly like the line sink. The only thing waterfall-specific is the height option and that Superluminal runs the FFT internally when display = Frequency.

Removing the Operation dropdown

Same day I added two GRC options to both sinks: Display Domain (Time / Frequency) and Operation (Real / Imaginary / Amplitude / Phase). Display Domain is real, it picks whether Superluminal shows the raw time series or inserts an FFT and shows the spectrum. It works.

Operation does not. Reading Superluminal’s line and waterfall pipeline builders, the enum never reaches the render path both collapse a complex sample to |z| regardless of what you pass. So the operation argument is gone from both make() signatures, the GRC blocks, and the bindings.

// before
static sptr make(size_t buffer_size, const std::string& name,
                 Domain display = Domain::Time,
                 Operation operation = Operation::Real);   // ← ignored downstream

// after
static sptr make(size_t buffer_size, const std::string& name,
                 Domain display = Domain::Time);

A pybind ordering bug

Splitting the enums out surfaced a subtle one. The sink bindings use Superluminal’s enums (Domain, DeviceType) as default argument values in their pybind signatures. pybind has to know those enum types at the moment it builds the sink’s function signature. If the enum isn’t registered yet, the import throws.

The fix is just call order in python_bindings.cc: bind_cyber_context (which registers the enums) has to run before any sink binding that names them.

bind_cyber_context(m);        // registers DeviceType, Domain first
bind_cyber_lineplot_sink(m);  // so these can use them as defaults
bind_cyber_waterfall_sink(m);

Removing the null sink

The last cleanup was the oldest code in the repo. cyber_null_sink was the very first block I wrote just to prove the build worked correcly and it has no use now.

Next week

  • Understand the mosaic and implement a kind of translation unit to better support multi sink visualliztion.
  • Improve the documentation and add building from source guide.
  • Add QA tests.

Repo: gr-cyberethermain
Mentors: Luigi Cruz (CyberEther), Håkon Vågsether (GNU Radio).