Skip to content

Commit

Permalink
Merge branch 'ngscopeclient:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
mldulaney authored Oct 10, 2024
2 parents 91ebcc5 + 5711d44 commit 2510d1a
Show file tree
Hide file tree
Showing 14 changed files with 484 additions and 29 deletions.
6 changes: 6 additions & 0 deletions devdoc/Introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ End user documentation is located at https://www.ngscopeclient.org/manual/conten
\defgroup spectrometerdrivers Spectrometer drivers
\ingroup drivers

\defgroup matrixdrivers Switch matrix drivers
\ingroup drivers

\defgroup vnadrivers VNA drivers
\ingroup drivers

Expand All @@ -50,6 +53,9 @@ End user documentation is located at https://www.ngscopeclient.org/manual/conten
\defgroup math Basic math functions
\ingroup libscopeprotocols

\defgroup rf RF
\ingroup libscopeprotocols

\defgroup ngscopeclient Ngscopeclient (GUI)

\defgroup dialogs Dialog boxes
Expand Down
56 changes: 53 additions & 3 deletions src/ngscopeclient/FilterGraphEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ bool FilterGraphEditor::DoRender()
for(auto it : chans)
{
for(auto chan : it.second)
DoNodeForChannel(chan, it.first, multiInst);
DoNodeForChannel(chan, it.first, multiInst, 0); //TODO: acquisition time etc?
}

//Make a newly dragged node spawn at the mouse position
Expand All @@ -518,9 +518,10 @@ bool FilterGraphEditor::DoRender()

//Filters
auto filters = Filter::GetAllInstances();
auto filterperf = m_session.GetFilterGraphRuntime();
for(auto f : filters)
{
DoNodeForChannel(f, nullptr, false);
DoNodeForChannel(f, nullptr, false, filterperf[f]);

//Add a reference to the channel so even if we remove the last user of it this frame, it won't be deleted until we're ready
f->AddRef();
Expand Down Expand Up @@ -1942,8 +1943,14 @@ void FilterGraphEditor::DoNodeForTrigger(Trigger* trig)
TODO: this seems to fail hard if we do not have at least one input OR output on the node. Why?
*/
void FilterGraphEditor::DoNodeForChannel(InstrumentChannel* channel, shared_ptr<Instrument> inst, bool multiInst)
void FilterGraphEditor::DoNodeForChannel(
InstrumentChannel* channel,
shared_ptr<Instrument> inst,
bool multiInst,
int64_t runtime)
{
Unit fs(Unit::UNIT_FS);

//If the channel has no color, make it neutral gray
//(this is often true for e.g. external trigger)
string displaycolor = channel->m_displaycolor;
Expand Down Expand Up @@ -2136,6 +2143,49 @@ void FilterGraphEditor::DoNodeForChannel(InstrumentChannel* channel, shared_ptr<
headercolor,
headerText.c_str());

//TODO: add an option for toggling this
//TODO: add preference for colors
//Draw a bubble above the text with the runtime stats
if(runtime > 0)
{
auto runtimeText = fs.PrettyPrint(runtime);
auto runtimeSize = headerfont->CalcTextSizeA(headerfontsize, FLT_MAX, 0, runtimeText.c_str());

auto timebgColor = ColorFromString("#404040");
auto timeTextColor = ColorFromString("#ffffff");
float timespacing = 0.1 * headerheight;
float runtimeBot = pos.y - timespacing;
float bubbleHeight = runtimeSize.y + 2*ImGui::GetStyle().FramePadding.y;

ImVec2 clockiconpos(
pos.x + ImGui::GetStyle().FramePadding.x,
runtimeBot - bubbleHeight + ImGui::GetStyle().FramePadding.y);
ImVec2 clockiconsize(runtimeSize.y, runtimeSize.y);

ImVec2 textpos(
clockiconpos.x + clockiconsize.x + ImGui::GetStyle().ItemSpacing.x,
clockiconpos.y );

bgList->AddRectFilled(
ImVec2(pos.x + 1, runtimeBot - bubbleHeight),
ImVec2(textpos.x + runtimeSize.x + ImGui::GetStyle().FramePadding.y, runtimeBot),
timebgColor,
rounding,
ImDrawFlags_RoundCornersAll);

bgList->AddImage(
m_parent->GetTextureManager()->GetTexture("time"),
clockiconpos,
clockiconpos + clockiconsize );

bgList->AddText(
headerfont,
headerfontsize,
textpos,
timeTextColor,
runtimeText.c_str());
}

//Draw the force vector
if(ImGui::IsKeyDown(ImGuiKey_Q))
RenderForceVector(bgList, pos, size, m_nodeForces[id]);
Expand Down
6 changes: 5 additions & 1 deletion src/ngscopeclient/FilterGraphEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,11 @@ class FilterGraphEditor : public Dialog
void DoInternalLinksForGroup(std::shared_ptr<FilterGraphGroup> group);
void DoNodeForGroupOutputs(std::shared_ptr<FilterGraphGroup> group);
void DoNodeForGroupInputs(std::shared_ptr<FilterGraphGroup> group);
void DoNodeForChannel(InstrumentChannel* channel, std::shared_ptr<Instrument> inst, bool multiInst);
void DoNodeForChannel(
InstrumentChannel* channel,
std::shared_ptr<Instrument> inst,
bool multiInst,
int64_t runtime);
void DoNodeForTrigger(Trigger* trig);
bool HandleNodeProperties();
void HandleDoubleClicks();
Expand Down
13 changes: 13 additions & 0 deletions src/ngscopeclient/InstrumentThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ void InstrumentThread(InstrumentThreadArgs args)
auto bertstate = args.bertstate;
auto psustate = args.psustate;

bool triggerUpToDate = false;

while(!*args.shuttingDown)
{
//Flush any pending commands
Expand All @@ -86,15 +88,26 @@ void InstrumentThread(InstrumentThreadArgs args)
{
//LogTrace("Scope isn't armed, sleeping\n");
this_thread::sleep_for(chrono::milliseconds(5));
if(!triggerUpToDate)
{ // Check for trigger state change
auto stat = scope->PollTrigger();
session->GetInstrumentConnectionState(inst)->m_lastTriggerState = stat;
if(stat == Oscilloscope::TRIGGER_MODE_STOP || stat == Oscilloscope::TRIGGER_MODE_RUN || stat == Oscilloscope::TRIGGER_MODE_TRIGGERED)
{ // Final state
triggerUpToDate = true;
}
}
}

//Grab data if it's ready
//TODO: how is this going to play with reading realtime BER from BERT+scope deviecs?
else
{
auto stat = scope->PollTrigger();
session->GetInstrumentConnectionState(inst)->m_lastTriggerState = stat;
if(stat == Oscilloscope::TRIGGER_MODE_TRIGGERED)
scope->AcquireData();
triggerUpToDate = false;
}
}

Expand Down
11 changes: 9 additions & 2 deletions src/ngscopeclient/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1277,7 +1277,7 @@ void MainWindow::DockingArea()
rightPanelID = topNode->ChildNodes[1]->ID;
}
else
ImGui::DockBuilderSplitNode(topNode->ID, ImGuiDir_Left, 0.1, &leftPanelID, &rightPanelID);
ImGui::DockBuilderSplitNode(topNode->ID, ImGuiDir_Left, 0.2, &leftPanelID, &rightPanelID);

ImGui::DockBuilderDockWindow(m_streamBrowser->GetTitleAndID().c_str(), leftPanelID);
ImGui::DockBuilderDockWindow(m_initialWorkspaceDockRequest->GetTitleAndID().c_str(), rightPanelID);
Expand Down Expand Up @@ -1490,7 +1490,9 @@ void MainWindow::AddToRecentInstrumentList(shared_ptr<SCPIInstrument> inst)
if(inst == nullptr)
return;

LogTrace("Adding instrument \"%s\" to recent instrument list\n", inst->m_nickname.c_str());
LogTrace("Adding instrument \"%s\" to recent instrument list (had %zu)\n",
inst->m_nickname.c_str(), m_recentInstruments.size());
LogIndenter li;

auto now = time(NULL);

Expand All @@ -1499,6 +1501,7 @@ void MainWindow::AddToRecentInstrumentList(shared_ptr<SCPIInstrument> inst)
inst->GetDriverName() + ":" +
inst->GetTransportName() + ":" +
inst->GetTransportConnectionString();
LogTrace("Connection string: %s\n", connectionString.c_str());
m_recentInstruments[connectionString] = now;

//Delete anything old
Expand All @@ -1517,8 +1520,12 @@ void MainWindow::AddToRecentInstrumentList(shared_ptr<SCPIInstrument> inst)
}
}

LogTrace("Removing oldest instrument (%s) to make room\n", oldestPath.c_str());
m_recentInstruments.erase(oldestPath);
}

LogTrace("Added (now have %zu total recent instruments)\n", m_recentInstruments.size());
SaveRecentInstrumentList();
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/ngscopeclient/MainWindow_Icons.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ void MainWindow::LoadStatusBarIcons()
m_texmgr.LoadTexture("mouse_move", FindDataFile("icons/contrib/blender/24x24/mouse_move.png"));

m_texmgr.LoadTexture("mouse_wheel", FindDataFile("icons/contrib/blender/24x24/mouse_wheel.png"));

m_texmgr.LoadTexture("time", FindDataFile("icons/contrib/blender/24x24/time.png"));
}

/**
Expand Down
21 changes: 17 additions & 4 deletions src/ngscopeclient/MainWindow_Menus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,17 @@ void MainWindow::DoAddSubMenu(
for(auto cstring : cstrings)
{
auto fields = explode(cstring, ':');

//make sure it's well formed
if(fields.size() < 4)
continue;
{
//Special case: null transport allows 3 fields
if( (fields.size() == 3) && (fields[2] == "null") )
{}

else
continue;
}

auto nick = fields[0];
auto drivername = fields[1];
Expand All @@ -333,9 +342,13 @@ void MainWindow::DoAddSubMenu(
{
if(ImGui::MenuItem(nick.c_str()))
{
auto path = fields[3];
for(size_t j=4; j<fields.size(); j++)
path = path + ":" + fields[j];
string path;
if(fields.size() >= 4)
{
path = fields[3];
for(size_t j=4; j<fields.size(); j++)
path = path + ":" + fields[j];
}

auto transport = MakeTransport(transname, path);
if(transport != nullptr)
Expand Down
11 changes: 9 additions & 2 deletions src/ngscopeclient/Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ Session::Session(MainWindow* wnd)
, m_tPrimaryTrigger(0)
, m_triggerArmed(false)
, m_triggerOneShot(false)
, m_graphExecutor(/*8*/1)
, m_graphExecutor(4)
, m_lastFilterGraphExecTime(0)
, m_history(*this)
, m_multiScope(false)
Expand Down Expand Up @@ -3174,7 +3174,6 @@ size_t Session::GetFilterCount()
return filters.size();
}


/**
@brief Queues a request to refresh all filters the next time we poll stuff
*/
Expand Down Expand Up @@ -3239,6 +3238,10 @@ void Session::RefreshAllFilters()
}

m_lastFilterGraphExecTime = (GetTime() - tstart) * FS_PER_SECOND;
{
lock_guard<mutex> lock(m_lastFilterGraphRuntimeMutex);
m_lastFilterGraphRuntimeStats = m_graphExecutor.GetRunTimes();
}
}

/**
Expand Down Expand Up @@ -3291,6 +3294,10 @@ bool Session::RefreshDirtyFilters()
}

m_lastFilterGraphExecTime = (GetTime() - tstart) * FS_PER_SECOND;
{
lock_guard<mutex> lock(m_lastFilterGraphRuntimeMutex);
m_lastFilterGraphRuntimeStats = m_graphExecutor.GetRunTimes();
}

return true;
}
Expand Down
18 changes: 18 additions & 0 deletions src/ngscopeclient/Session.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class InstrumentConnectionState
m_shuttingDown = false;
args.shuttingDown = &m_shuttingDown;
m_thread = std::make_unique<std::thread>(InstrumentThread, args);
m_lastTriggerState = Oscilloscope::TRIGGER_MODE_WAIT;
}

~InstrumentConnectionState()
Expand All @@ -79,6 +80,9 @@ class InstrumentConnectionState

///@brief Thread for polling the instrument
std::unique_ptr<std::thread> m_thread;

///@brief Cached trigger state, to reflect in the UI
Oscilloscope::TriggerMode m_lastTriggerState;
};

/**
Expand Down Expand Up @@ -132,6 +136,7 @@ class Session

void AddInstrument(std::shared_ptr<Instrument> inst, bool createDialogs = true);
void RemoveInstrument(std::shared_ptr<Instrument> inst);
std::shared_ptr<InstrumentConnectionState> GetInstrumentConnectionState(std::shared_ptr<Instrument> inst) { return m_instrumentStates[inst]; }

bool IsMultiScope()
{ return m_multiScope; }
Expand Down Expand Up @@ -319,6 +324,13 @@ class Session

void OnMarkerChanged();

///@brief Return the last filter graph runtime stats
std::map<FlowGraphNode*, int64_t> GetFilterGraphRuntime()
{
std::lock_guard<std::mutex> lock(m_lastFilterGraphRuntimeMutex);
return m_lastFilterGraphRuntimeStats;
}

protected:
void UpdatePacketManagers(const std::set<FlowGraphNode*>& nodes);

Expand Down Expand Up @@ -440,6 +452,12 @@ class Session
///@brief Time spent on the last filter graph execution
std::atomic<int64_t> m_lastFilterGraphExecTime;

///@brief Mutex for controlling access to m_lastFilterGraphRuntimeStats
std::mutex m_lastFilterGraphRuntimeMutex;

///@brief Performance stats from last graph execution
std::map<FlowGraphNode*, int64_t> m_lastFilterGraphRuntimeStats;

///@brief Mutex for controlling access to performance counters
std::mutex m_perfClockMutex;

Expand Down
Loading

0 comments on commit 2510d1a

Please sign in to comment.