2025-03-09 10:16:40 +01:00
# include "dsp_flowgraph_handler.h"
2025-04-21 23:17:21 +02:00
# include "core/plugin.h"
2025-05-17 09:56:04 -03:00
# include "dsp/agc/agc.h"
2025-04-22 19:56:59 +02:00
# include "dsp/device/dev.h"
2025-05-17 09:56:04 -03:00
# include "dsp/fft/fft_pan.h"
2025-04-15 19:06:12 +01:00
# include "dsp/filter/rrc.h"
2025-05-17 09:56:04 -03:00
# include "dsp/io/file_source.h"
2025-06-06 08:12:02 +02:00
# include "dsp/path/splitter.h"
2025-03-09 10:16:40 +01:00
# include "imgui/imnodes/imnodes.h"
# include "logger.h"
# include "common/widgets/fft_plot.h"
# include "common/dsp/filter/firdes.h"
2025-04-15 19:06:12 +01:00
# include "dsp/filter/fir.h"
2025-03-09 10:16:40 +01:00
# include "dsp/clock_recovery/clock_recovery_mm.h"
2025-06-14 19:05:33 -03:00
# include "dsp/displays/const_disp.h"
# include "dsp/displays/hist_disp.h"
2025-04-15 19:06:12 +01:00
# include "dsp/pll/costas.h"
2025-03-09 10:16:40 +01:00
2025-05-07 20:16:25 -03:00
# include "dsp/utils/correct_iq.h"
2025-06-14 19:05:33 -03:00
# include "dsp/utils/cyclostationary_analysis.h"
2025-05-07 20:16:25 -03:00
# include "dsp/utils/delay_one_imag.h"
2025-05-17 09:56:04 -03:00
# include "dsp/utils/freq_shift.h"
2025-06-14 19:05:33 -03:00
# include "dsp/utils/hilbert.h"
# include "dsp/utils/quadrature_demod.h"
2025-05-18 18:21:35 -03:00
# include "dsp/utils/real_to_complex.h"
2025-05-07 20:16:25 -03:00
2025-03-09 10:16:40 +01:00
# include "nlohmann/json_utils.h"
2025-06-06 08:12:02 +02:00
# include <complex.h>
2025-05-07 20:16:25 -03:00
# include <memory>
2025-03-09 10:16:40 +01:00
2025-04-12 09:07:02 +02:00
// #include "dsp/device/airspy/airspy_dev.h"
2025-04-15 19:06:12 +01:00
2025-03-09 10:16:40 +01:00
namespace satdump
{
2025-05-19 22:26:32 +02:00
namespace handlers
2025-03-09 10:16:40 +01:00
{
class NodeTestFileSource : public ndsp : : NodeInternal
{
public :
2025-04-15 19:06:12 +01:00
NodeTestFileSource ( const ndsp : : Flowgraph * f ) : ndsp : : NodeInternal ( f , std : : make_shared < ndsp : : FileSourceBlock > ( ) ) { }
2025-03-09 10:16:40 +01:00
2025-04-21 23:17:21 +02:00
virtual bool render ( )
2025-03-09 10:16:40 +01:00
{
ndsp : : NodeInternal : : render ( ) ;
float prog = double ( ( ( ndsp : : FileSourceBlock * ) blk . get ( ) ) - > d_progress ) / double ( ( ( ndsp : : FileSourceBlock * ) blk . get ( ) ) - > d_filesize ) ;
ImGui : : ProgressBar ( prog , { 100 , 20 } ) ;
2025-04-21 23:17:21 +02:00
return false ;
2025-03-09 10:16:40 +01:00
}
} ;
class NodeTestConst : public ndsp : : NodeInternal
{
public :
2025-04-15 19:06:12 +01:00
NodeTestConst ( const ndsp : : Flowgraph * f ) : ndsp : : NodeInternal ( f , std : : make_shared < ndsp : : ConstellationDisplayBlock > ( ) ) { }
2025-03-09 10:16:40 +01:00
2025-04-21 23:17:21 +02:00
virtual bool render ( )
2025-03-09 10:16:40 +01:00
{
ndsp : : NodeInternal : : render ( ) ;
( ( ndsp : : ConstellationDisplayBlock * ) blk . get ( ) ) - > constel . draw ( ) ;
2025-04-21 23:17:21 +02:00
return false ;
2025-03-09 10:16:40 +01:00
}
} ;
class NodeTestFFT : public ndsp : : NodeInternal
{
private :
widgets : : FFTPlot fft ;
public :
2025-04-15 19:06:12 +01:00
NodeTestFFT ( const ndsp : : Flowgraph * f ) : ndsp : : NodeInternal ( f , std : : make_shared < ndsp : : FFTPanBlock > ( ) ) , fft ( ( ( ndsp : : FFTPanBlock * ) blk . get ( ) ) - > output_fft_buff , 8192 , - 150 , 150 )
2025-03-09 10:16:40 +01:00
{
( ( ndsp : : FFTPanBlock * ) blk . get ( ) ) - > set_fft_settings ( 8192 , 6e6 ) ;
}
2025-04-21 23:17:21 +02:00
virtual bool render ( )
2025-03-09 10:16:40 +01:00
{
ndsp : : NodeInternal : : render ( ) ;
fft . draw ( { 500 , 500 } ) ;
2025-04-21 23:17:21 +02:00
return false ;
2025-03-09 10:16:40 +01:00
}
} ;
2025-06-14 19:05:33 -03:00
class NodeTestHisto : public ndsp : : NodeInternal
{
public :
NodeTestHisto ( const ndsp : : Flowgraph * f ) : ndsp : : NodeInternal ( f , std : : make_shared < ndsp : : HistogramDisplayBlock > ( ) ) { }
virtual bool render ( )
{
ndsp : : NodeInternal : : render ( ) ;
( ( ndsp : : HistogramDisplayBlock * ) blk . get ( ) ) - > histo . draw ( ) ;
return false ;
}
} ;
2025-03-09 10:16:40 +01:00
DSPFlowGraphHandler : : DSPFlowGraphHandler ( )
{
// TODOREWORK
if ( ImNodes : : GetCurrentContext ( ) = = nullptr )
ImNodes : : CreateContext ( ) ;
2025-05-04 17:27:35 +02:00
handler_tree_icon = u8 " \uf92f " ;
2025-03-09 10:16:40 +01:00
2025-04-15 19:06:12 +01:00
flowgraph . node_internal_registry . insert ( { " file_source_cc " , { " IO/File Source " , [ ] ( const ndsp : : Flowgraph * f ) { return std : : make_shared < NodeTestFileSource > ( f ) ; } } } ) ;
flowgraph . node_internal_registry . insert (
{ " agc_cc " , { " Agc/Agc CC " , [ ] ( const ndsp : : Flowgraph * f ) { return std : : make_shared < ndsp : : NodeInternal > ( f , std : : make_shared < ndsp : : AGCBlock < complex_t > > ( ) ) ; } } } ) ;
flowgraph . node_internal_registry . insert ( { " fft_pan_cc " , { " FFT/FFT Pan " , [ ] ( const ndsp : : Flowgraph * f ) { return std : : make_shared < NodeTestFFT > ( f ) ; } } } ) ;
2025-03-09 10:16:40 +01:00
2025-04-15 19:06:12 +01:00
// flowgraph.node_internal_registry.insert({"fir_rrc_cc", {"Filter/FIR RRC Filter CC", [](const ndsp::Flowgraph *f) { return std::make_shared<NodeTestRRC>(f, true); }}});
// flowgraph.node_internal_registry.insert({"fir_rrc_ff", {"Filter/FIR RRC Filter FF", [](const ndsp::Flowgraph *f) { return std::make_shared<NodeTestRRC>(f, false); }}});
2025-03-09 10:16:40 +01:00
2025-04-15 19:06:12 +01:00
flowgraph . node_internal_registry . insert (
{ " costas_cc " , { " PLL/Costas Loop " , [ ] ( const ndsp : : Flowgraph * f ) { return std : : make_shared < ndsp : : NodeInternal > ( f , std : : make_shared < ndsp : : CostasBlock > ( ) ) ; } } } ) ;
2025-03-09 10:16:40 +01:00
2025-06-14 19:05:33 -03:00
flowgraph . node_internal_registry . insert ( { " const_disp_c " , { " View/Constellation Display " , [ ] ( const ndsp : : Flowgraph * f ) { return std : : make_shared < NodeTestConst > ( f ) ; } } } ) ;
flowgraph . node_internal_registry . insert ( { " histo_disp_c " , { " View/Histogram Display " , [ ] ( const ndsp : : Flowgraph * f ) { return std : : make_shared < NodeTestHisto > ( f ) ; } } } ) ;
2025-03-09 10:16:40 +01:00
2025-04-15 19:06:12 +01:00
flowgraph . node_internal_registry . insert (
{ " mm_clock_recovery_cc " ,
{ " PLL/Clock Recovery MM CC " , [ = ] ( const ndsp : : Flowgraph * f ) { return std : : make_shared < ndsp : : NodeInternal > ( f , std : : make_shared < ndsp : : MMClockRecoveryBlock < complex_t > > ( ) ) ; } } } ) ;
2025-03-22 16:24:29 +01:00
2025-04-15 19:06:12 +01:00
flowgraph . node_internal_registry . insert (
{ " rrc_fir_cc " , { " RRC FIR CC " , [ ] ( const ndsp : : Flowgraph * f ) { return std : : make_shared < ndsp : : NodeInternal > ( f , std : : make_shared < ndsp : : RRC_FIRBlock < complex_t > > ( ) ) ; } } } ) ;
2025-05-02 16:37:34 -03:00
flowgraph . node_internal_registry . insert (
{ " cyclostationary_analysis_cf " ,
2025-05-07 20:16:25 -03:00
{ " Utils/Cyclostationary Analysis " , [ ] ( const ndsp : : Flowgraph * f ) { return std : : make_shared < ndsp : : NodeInternal > ( f , std : : make_shared < ndsp : : CyclostationaryAnalysis > ( ) ) ; } } } ) ;
flowgraph . node_internal_registry . insert (
{ " delay_one_imag_cc " , { " Utils/Delay One Imag " , [ ] ( const ndsp : : Flowgraph * f ) { return std : : make_shared < ndsp : : NodeInternal > ( f , std : : make_shared < ndsp : : DelayOneImagBlock > ( ) ) ; } } } ) ;
flowgraph . node_internal_registry . insert (
{ " correct_iq_cc " , { " Utils/Correct IQ " , [ ] ( const ndsp : : Flowgraph * f ) { return std : : make_shared < ndsp : : NodeInternal > ( f , std : : make_shared < ndsp : : CorrectIQBlock < complex_t > > ( ) ) ; } } } ) ;
2025-05-02 16:37:34 -03:00
2025-05-17 13:06:53 -03:00
flowgraph . node_internal_registry . insert (
{ " freq_shift_cc " , { " Utils/Frequency Shift " , [ ] ( const ndsp : : Flowgraph * f ) { return std : : make_shared < ndsp : : NodeInternal > ( f , std : : make_shared < ndsp : : FreqShiftBlock > ( ) ) ; } } } ) ;
2025-05-17 09:56:04 -03:00
2025-05-18 18:21:35 -03:00
flowgraph . node_internal_registry . insert (
{ " real_to_complex_fc " , { " Utils/Real to Complex " , [ ] ( const ndsp : : Flowgraph * f ) { return std : : make_shared < ndsp : : NodeInternal > ( f , std : : make_shared < ndsp : : RealToComplexBlock > ( ) ) ; } } } ) ;
2025-06-14 19:05:33 -03:00
flowgraph . node_internal_registry . insert (
{ " quadrature_demod_cf " , { " Utils/Quadrature Demod " , [ ] ( const ndsp : : Flowgraph * f ) { return std : : make_shared < ndsp : : NodeInternal > ( f , std : : make_shared < ndsp : : QuadratureDemodBlock > ( ) ) ; } } } ) ;
flowgraph . node_internal_registry . insert (
{ " hilbert_fc " , { " Utils/Hilbert Transform " , [ ] ( const ndsp : : Flowgraph * f ) { return std : : make_shared < ndsp : : NodeInternal > ( f , std : : make_shared < ndsp : : HilbertBlock > ( ) ) ; } } } ) ;
2025-06-06 08:12:02 +02:00
flowgraph . node_internal_registry . insert (
{ " splitter_cc " , { " Utils/Splitter CC " , [ ] ( const ndsp : : Flowgraph * f ) { return std : : make_shared < ndsp : : NodeInternal > ( f , std : : make_shared < ndsp : : SplitterBlock < complex_t > > ( ) ) ; } } } ) ;
2025-04-15 19:06:12 +01:00
// flowgraph.node_internal_registry.insert({"airspy_dev_cc", {"Airspy Dev", [=](const ndsp::Flowgraph *f)
// { return std::make_shared<ndsp::NodeInternal>(f, std::make_shared<ndsp::AirspyDevBlock>()); }}});
2025-04-21 23:17:21 +02:00
eventBus - > fire_event < RegisterNodesEvent > ( { flowgraph . node_internal_registry } ) ;
2025-04-22 19:56:59 +02:00
#if 0
// Local devices!!
std : : vector < ndsp : : DeviceInfo > found_devices = ndsp : : getDeviceList ( ) ;
for ( auto & dev : found_devices )
{
flowgraph . node_internal_registry . insert ( { " idk_dev_cc " ,
{ " Local Devs/ " + dev . name , [ dev ] ( const ndsp : : Flowgraph * f )
{ return std : : make_shared < ndsp : : NodeInternal > ( f , ndsp : : getDeviceInstanceFromInfo ( dev , ndsp : : DeviceBlock : : MODE_NORMAL ) ) ; } } } ) ;
}
# endif
2025-03-09 10:16:40 +01:00
}
DSPFlowGraphHandler : : ~ DSPFlowGraphHandler ( )
{
if ( flow_thread . joinable ( ) )
flow_thread . join ( ) ;
}
void DSPFlowGraphHandler : : drawMenu ( )
{
bool running = flowgraph . is_running ;
if ( ImGui : : CollapsingHeader ( " Flowgraph " ) )
{
if ( running )
{
2025-03-10 20:05:31 +01:00
if ( ImGui : : Button ( " Stop " ) )
flowgraph . stop ( ) ;
}
else
{
if ( ImGui : : Button ( " Start " ) )
2025-03-09 10:16:40 +01:00
{
2025-03-10 20:05:31 +01:00
if ( flow_thread . joinable ( ) )
flow_thread . join ( ) ;
2025-04-15 19:06:12 +01:00
auto fun = [ & ] ( ) { flowgraph . run ( ) ; } ;
2025-03-10 20:05:31 +01:00
flow_thread = std : : thread ( fun ) ;
}
2025-03-09 10:16:40 +01:00
}
2025-03-10 20:05:31 +01:00
if ( running )
style : : beginDisabled ( ) ;
/*auto pos = ImGui::GetCursorPos();
ImGui : : Button ( " ##test " , { 50 , 50 } ) ;
pos . x + = 10 ;
ImGui : : GetWindowDrawList ( )
- > AddTriangleFilled ( { pos . x + 10 , pos . y + 43 } ,
{ pos . x + 10 , pos . y + 77 } ,
{ pos . x + 40 , pos . y + 60 } ,
ImColor ( 255 , 255 , 255 , 255 ) ) ; */
// needs_to_update |= TODO; // TODOREWORK move in top drawMenu?
2025-03-09 10:16:40 +01:00
if ( ImGui : : Button ( " To JSON " ) )
{
std : : string json = flowgraph . getJSON ( ) . dump ( 4 ) ;
ImGui : : SetClipboardText ( json . c_str ( ) ) ;
}
if ( ImGui : : Button ( " From JSON " ) )
{
nlohmann : : json v = nlohmann : : json : : parse ( ImGui : : GetClipboardText ( ) ) ;
flowgraph . setJSON ( v ) ;
}
if ( running )
style : : endDisabled ( ) ;
}
if ( ImGui : : CollapsingHeader ( " Variables " ) )
{
if ( running )
style : : beginDisabled ( ) ;
2025-04-15 19:06:12 +01:00
// flowgraph.var_manager_test.drawVariables();
2025-03-09 10:16:40 +01:00
if ( running )
style : : endDisabled ( ) ;
}
}
2025-04-15 19:06:12 +01:00
void DSPFlowGraphHandler : : drawContents ( ImVec2 win_size ) { flowgraph . render ( ) ; }
2025-05-19 22:26:32 +02:00
} // namespace handlers
2025-04-15 19:06:12 +01:00
} // namespace satdump