Skip to content

Commit 5c34e24

Browse files
committed
refactor download status API to live in InstrumentChannel, and separate UI concerns from data reporting concerns
1 parent ae4e328 commit 5c34e24

31 files changed

+190
-266
lines changed

scopehal/DemoOscilloscope.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -401,9 +401,6 @@ uint64_t DemoOscilloscope::GetSampleDepth()
401401
void DemoOscilloscope::SetSampleDepth(uint64_t depth)
402402
{
403403
m_depth = depth;
404-
// Another way to let GetChannelDownloadState() API know when to show progress bar is to
405-
// force its behaviour according to the current sample depth using SetShowChannelsDownloadProgress() method
406-
// SetShowChannelsDownloadProgress(depth>=10000000L);
407404
}
408405

409406
void DemoOscilloscope::SetSampleRate(uint64_t rate)
@@ -494,7 +491,7 @@ bool DemoOscilloscope::AcquireData()
494491
if(!m_triggerArmed)
495492
return false;
496493

497-
// Tell the GetChannelDownloadState() of Oscilloscope class that waveform download operation is starting
494+
// prepare all channels to be 'about to download'
498495
ChannelsDownloadStarted();
499496

500497
//cap waveform rate at 50 wfm/s to avoid saturating cpu
@@ -538,10 +535,11 @@ bool DemoOscilloscope::AcquireData()
538535
continue;
539536

540537
// Lambda passed to generate waveform methods to update "download" percentage
541-
auto updateProgress = [i,this](int percentage)
538+
auto updateProgress = [i,this](float progress)
542539
{
543-
this->UpdateChannelDownloadState(i,percentage);
540+
this->ChannelsDownloadStatusUpdate(i, InstrumentChannel::DownloadState::DOWNLOAD_IN_PROGRESS, progress);
544541
};
542+
this->ChannelsDownloadStatusUpdate(i, InstrumentChannel::DownloadState::DOWNLOAD_IN_PROGRESS, 0.0);
545543
switch(i)
546544
{
547545
case 0:
@@ -572,6 +570,7 @@ bool DemoOscilloscope::AcquireData()
572570
}
573571

574572
waveforms[i]->MarkModifiedFromCpu();
573+
this->ChannelsDownloadStatusUpdate(i, InstrumentChannel::DownloadState::DOWNLOAD_FINISHED, 1.0);
575574
}
576575

577576
SequenceSet s;

scopehal/InstrumentChannel.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,21 @@ bool InstrumentChannel::ShouldPersistWaveform()
151151
//Default to persisting everything
152152
return true;
153153
}
154+
155+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
156+
// Download progress
157+
158+
InstrumentChannel::DownloadState InstrumentChannel::GetDownloadState()
159+
{
160+
return DownloadState::DOWNLOAD_UNKNOWN;
161+
}
162+
163+
float InstrumentChannel::GetDownloadProgress()
164+
{
165+
return 0.0;
166+
}
167+
168+
double InstrumentChannel::GetDownloadStartTime()
169+
{
170+
return 0.0;
171+
}

scopehal/InstrumentChannel.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,32 @@ class InstrumentChannel : public FlowGraphNode
239239
VIS_SHOW,
240240
} m_visibilityMode;
241241

242+
/**
243+
@brief Enum values to be mapped to GetDownloadState() int result value for specific channel download states
244+
*/
245+
enum DownloadState
246+
{
247+
DOWNLOAD_UNKNOWN,
248+
DOWNLOAD_NONE, ///< No download is pending (e.g. the scope is in stop mode)
249+
DOWNLOAD_WAITING, ///< This channel is waiting to be downloaded (i.e. scope is triggered but previous channels are currently beeing downloaded)
250+
DOWNLOAD_IN_PROGRESS, ///< Download has started
251+
DOWNLOAD_FINISHED ///< Download is finished
252+
};
253+
254+
/**
255+
@brief Returns the current download state of this channel.
256+
257+
The returned int value can either be an integer ranging from 0 to 100 corresponding to the percentage of the waveform that has already been downloaded
258+
or a (negative) int value to be mapped to the OscilloscopeChannel::DownloadState enum
259+
*/
260+
virtual DownloadState GetDownloadState();
261+
262+
/// returns the current completion of the download (on the range [0, 1]), if not DOWNLOAD_UNKNOWN
263+
virtual float GetDownloadProgress();
264+
265+
/// returns the start time of a download, if we are DOWNLOAD_IN_PROGRESS; undefined, otherwise
266+
virtual double GetDownloadStartTime();
267+
242268
protected:
243269

244270
virtual void ClearStreams();

scopehal/Oscilloscope.cpp

Lines changed: 18 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -856,74 +856,31 @@ bool Oscilloscope::IsInverted(size_t /*i*/)
856856
return false;
857857
}
858858

859-
// In automatic download progress bar display mode (i.e. if the driver doens not call SetShowChannelsDownloadProgress() method)
860-
// this is the maximum download duration under which the download progress bar will not be shown.
861-
#define SHOW_DOWNLOAD_PROGRESS_BAR_DURATION 0.3
862-
863-
int Oscilloscope::GetChannelDownloadState(size_t i)
864-
{ // Surface check of channel index
865-
if(i >= m_channelDownloadStates.size())
866-
return OscilloscopeChannel::DownloadState::DOWNLOAD_NONE;
867-
868-
int result = m_channelDownloadStates[i];
869-
if(!m_forceShowChannelProgressBar && !m_downloadSpeedEvaluated &&
870-
result > OscilloscopeChannel::DownloadState::DOWNLOAD_STARTED && result < OscilloscopeChannel::DownloadState::DOWNLOAD_FINISHED)
871-
{ // Check duration since start
872-
double now = GetTime();
873-
if((now - m_downloadStartTime) > SHOW_DOWNLOAD_PROGRESS_BAR_DURATION)
874-
{ // We've been downloading for more than 300ms and are not finished yet => show progress bar
875-
m_showChannelProgressBar = true;
876-
m_downloadSpeedEvaluated = true;
877-
//LogWarning("Download speed evaluation done, show progress = true : start time = %f, now = %f, diff = %f, state = %d)\n",m_downloadStartTime, now,now - m_downloadStartTime,result);
878-
}
879-
}
880-
if(!m_showChannelProgressBar)
881-
return OscilloscopeChannel::DownloadState::DOWNLOAD_PROGRESS_DISABLED;
882-
return result;
883-
}
884-
885-
void Oscilloscope::SetShowChannelsDownloadProgress(bool show)
886-
{ // Let the driver decide whether the progress bar should be shown or not
887-
m_forceShowChannelProgressBar = true;
888-
m_showChannelProgressBar = show;
889-
}
890-
891859
void Oscilloscope::ChannelsDownloadStarted()
892-
{ // Set all channels to DOWNLOAD_WAITING state
893-
m_channelDownloadStates.assign(m_channels.size(),OscilloscopeChannel::DownloadState::DOWNLOAD_WAITING);
894-
if(!m_forceShowChannelProgressBar)
895-
{ // Not in force mode => check if the sample depth has changed since last download
896-
uint64_t newSampleDepth = GetSampleDepth();
897-
size_t newEnabledChannels = GetEnabledChannelCount();
898-
if((newSampleDepth != m_downloadSpeedEvalSampleDepth) || (newEnabledChannels != m_downloadSpeedEvalEnabledChannels))
899-
{ // Sample depth has changed => re-evaluate download speed
900-
m_downloadSpeedEvalSampleDepth = newSampleDepth;
901-
m_downloadSpeedEvalEnabledChannels = newEnabledChannels;
902-
m_downloadSpeedEvaluated = false;
903-
}
904-
else if(!m_downloadSpeedEvaluated)
905-
{ // See how log elapsed since last download start
906-
double now = GetTime();
907-
if((now-m_downloadStartTime)<=SHOW_DOWNLOAD_PROGRESS_BAR_DURATION)
908-
{ // Download fast enough, no need for a progress bar to be shown
909-
m_downloadSpeedEvaluated = true;
910-
m_showChannelProgressBar = false;
911-
//LogWarning("Download speed evaluation done, show = false : start time = %f, now = %f, diff = %f)\n",m_downloadStartTime, now,now - m_downloadStartTime);
912-
}
913-
}
860+
{
861+
for (size_t i = 0; i < m_channels.size(); i++)
862+
{
863+
auto chan = GetOscilloscopeChannel(i);
864+
if (chan == nullptr)
865+
continue;
866+
867+
chan->m_downloadState = InstrumentChannel::DownloadState::DOWNLOAD_WAITING;
868+
chan->m_downloadProgress = 0.0;
869+
chan->m_downloadStartTime = GetTime();
914870
}
915-
m_downloadStartTime = GetTime();
916871
}
917872

918-
void Oscilloscope::UpdateChannelDownloadState(size_t i, int downloadState)
873+
void Oscilloscope::ChannelsDownloadStatusUpdate(size_t ch, InstrumentChannel::DownloadState state, float progress)
919874
{
920-
if(i >= m_channelDownloadStates.size())
921-
{
922-
m_channelDownloadStates.resize(i+1,OscilloscopeChannel::DownloadState::DOWNLOAD_NONE);
923-
}
924-
m_channelDownloadStates[i]=downloadState;
875+
auto chan = GetOscilloscopeChannel(ch);
876+
if (chan == nullptr)
877+
return;
878+
879+
chan->m_downloadState = state;
880+
chan->m_downloadProgress = progress;
925881
}
926882

883+
927884
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
928885
// Trigger configuration
929886

scopehal/Oscilloscope.h

Lines changed: 3 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -384,63 +384,13 @@ class Oscilloscope : public virtual Instrument
384384
*/
385385
virtual bool IsInverted(size_t i);
386386

387-
/**
388-
@brief Gets the download state of the specified channel.
389-
390-
The returned int value can either be an integer ranging from 0 to 100 corresponding to the percentage of the waveform that has already been downloaded,
391-
or a (negative) int value to be mapped to the OscilloscopeChannel::DownloadState enum
392-
393-
@param i Zero-based index of channel
394-
*/
395-
virtual int GetChannelDownloadState(size_t i);
396-
397387
protected:
398388

399-
/**
400-
@brief Let the driver decide wehther channels download progress should be displayed or not, according to the current sample depth configuration.
401-
402-
If scope download speed is fast enough according the the currently set sample depth, progress should not be shown to prevent flickering effect on the download bar.
403-
404-
If this method is not called by the driver, Oscilloscope class will try and determine whether download progress bar should be shown or not automatically.
405-
406-
@param show true if the download progress bar should be displayed, false otherwise
407-
*/
408-
void SetShowChannelsDownloadProgress(bool show);
409-
410-
/**
411-
@brief Drivers should call this method at a download operation start to tell the Oscilloscope class to initialize all channel download states.
412-
413-
*/
389+
/// @brief Helper method called by drivers to reset all channels to "waiting to download" state.
414390
void ChannelsDownloadStarted();
415391

416-
/**
417-
@brief Updates the download state for the specified channel.
418-
419-
The provided int value can either be an integer ranging from 0 to 100 corresponding to the percentage of the waveform that has already been downloaded
420-
or a (negative) int value to be mapped to the OscilloscopeChannel::DownloadState enum
421-
422-
@param i Zero-based index of channel
423-
@param downloadState the download state value
424-
425-
*/
426-
void UpdateChannelDownloadState(size_t i, int downloadState);
427-
428-
// Handling of waveform downnload operation state
429-
private:
430-
// True when the download progress bar should be displayed (i.e. slow download speed)
431-
bool m_showChannelProgressBar = false;
432-
// True when the driver is handling download progressbar display state on its side
433-
bool m_forceShowChannelProgressBar = false;
434-
// Time of start of the latest download operation for this instrument
435-
double m_downloadStartTime = 0;
436-
// Sample depth that was set on this Oscilloscope the last time the download speed have been evaluated
437-
uint64_t m_downloadSpeedEvalSampleDepth = 0;
438-
// Number of enabled channels on this Oscilloscope the last time the download speed have been evaluated
439-
size_t m_downloadSpeedEvalEnabledChannels;
440-
// True whent the download speed has been evaluated
441-
bool m_downloadSpeedEvaluated = false;
442-
// Dowbload state for each channel of this Oscilloscope
443-
std::vector<int> m_channelDownloadStates;
392+
/// @brief Helper method called by drivers to set one channel's download status.
393+
void ChannelsDownloadStatusUpdate(size_t ch, InstrumentChannel::DownloadState state, float progress);
444394

445395
public:
446396
//Triggering

scopehal/OscilloscopeChannel.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ OscilloscopeChannel::OscilloscopeChannel(
6161
Stream::StreamType stype,
6262
size_t index)
6363
: InstrumentChannel(scope, hwname, color, xunit, yunit, stype, index)
64+
, m_downloadState(DownloadState::DOWNLOAD_UNKNOWN)
65+
, m_downloadProgress(0.0)
66+
, m_downloadStartTime(0.0)
6467
, m_refcount(0)
6568
{
6669
}
@@ -342,9 +345,17 @@ void OscilloscopeChannel::SetInputMux(size_t select)
342345
GetScope()->SetInputMux(m_index, select);
343346
}
344347

345-
int OscilloscopeChannel::GetDownloadState()
348+
InstrumentChannel::DownloadState OscilloscopeChannel::GetDownloadState()
346349
{
347-
if(m_instrument)
348-
return GetScope()->GetChannelDownloadState(m_index);
349-
return DownloadState::DOWNLOAD_PROGRESS_DISABLED;
350+
return m_downloadState;
351+
}
352+
353+
float OscilloscopeChannel::GetDownloadProgress()
354+
{
355+
return m_downloadProgress;
356+
}
357+
358+
double OscilloscopeChannel::GetDownloadStartTime()
359+
{
360+
return m_downloadStartTime;
350361
}

scopehal/OscilloscopeChannel.h

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -146,26 +146,15 @@ class OscilloscopeChannel : public InstrumentChannel
146146

147147
void SetDefaultDisplayName();
148148

149-
150-
/**
151-
@brief Enum values to be mapped to GetDownloadState() int result value for specific channel download states
152-
*/
153-
enum DownloadState : int
154-
{
155-
DOWNLOAD_PROGRESS_DISABLED = -3, // Tell the UI not to show a download progress bar (e.g. if downloading the whole waveform is fast enough)
156-
DOWNLOAD_NONE = -2, // No download is pending (e.g. the scope is in stop mode)
157-
DOWNLOAD_WAITING = -1, // This channel is waiting to be downloaded (i.e. scope is triggered but previous channels are currently beeing downloaded)
158-
DOWNLOAD_STARTED = 0, // Download as tarted
159-
DOWNLOAD_FINISHED = 100 // Download is finished
160-
};
161-
162-
/**
163-
@brief Returns the current download state of this channel.
164-
165-
The returned int value can either be an integer ranging from 0 to 100 corresponding to the percentage of the waveform that has already been downloaded
166-
or a (negative) int value to be mapped to the OscilloscopeChannel::DownloadState enum
167-
*/
168-
int GetDownloadState();
149+
virtual DownloadState GetDownloadState() override;
150+
virtual float GetDownloadProgress() override;
151+
virtual double GetDownloadStartTime() override;
152+
153+
private:
154+
// to be accessed by Oscilloscope to update download status
155+
DownloadState m_downloadState;
156+
float m_downloadProgress;
157+
double m_downloadStartTime;
169158

170159
protected:
171160
void SharedCtorInit(Unit unit);

scopehal/RigolOscilloscope.cpp

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -858,10 +858,7 @@ bool RigolOscilloscope::AcquireData()
858858
cap->m_startTimestamp = floor(now);
859859
cap->m_startFemtoseconds = (now - floor(now)) * FS_PER_SECOND;
860860

861-
// Determine the size of one percent of the data to be downloaded
862-
int percent = (m_highDefinition ? 2* npoints : npoints)/100;
863-
int percentage = 0;
864-
int restPercentage = 0;
861+
ChannelsDownloadStatusUpdate(i, InstrumentChannel::DownloadState::DOWNLOAD_IN_PROGRESS, 0.0);
865862

866863
//Downloading the waveform is a pain in the butt, because we can only pull 250K points at a time! (Unless you have a MSO5)
867864
for(size_t npoint = 0; npoint < npoints;)
@@ -942,28 +939,14 @@ bool RigolOscilloscope::AcquireData()
942939
//Read actual block content and decode it
943940
//Scale: (value - Yorigin - Yref) * Yinc
944941

945-
// Read it in slice so that we can smoothly update download progress bar
946942
size_t bytesToRead = header_blocksize_bytes + 1; //trailing newline after data block
947-
int slices = bytesToRead / percent;
948-
int sliceRest = bytesToRead % percent;
949-
size_t bytesRead = 0;
950-
for(int s = 0 ; s < slices ; s++)
951-
{ // Read each block corresponding to one percent of the total waveform
952-
bytesRead += m_transport->ReadRawData(percent, (temp_buf+bytesRead));
953-
percentage++;
954-
UpdateChannelDownloadState(i,percentage);
955-
}
956-
if(bytesRead < bytesToRead)
957-
{ // For the rest (bytesToRead % slices)
958-
m_transport->ReadRawData(bytesToRead-bytesRead, (temp_buf+bytesRead));
959-
restPercentage += sliceRest;
960-
if(restPercentage>=percent && percentage < OscilloscopeChannel::DownloadState::DOWNLOAD_FINISHED)
961-
{ // Accumulate leftover bytes untill we get a whole percent
962-
percentage++;
963-
UpdateChannelDownloadState(i,percentage);
964-
restPercentage = 0;
965-
}
966-
}
943+
auto downloadCallback = [i, this, npoint, npoints, bytesToRead] (float progress) {
944+
/* we get the percentage of this particular download; convert this into linear percentage across all chunks */
945+
float bytes_progress = npoint * (m_highDefinition ? 2 : 1) + progress * bytesToRead;
946+
float bytes_total = npoints * (m_highDefinition ? 2 : 1);
947+
ChannelsDownloadStatusUpdate(i, InstrumentChannel::DownloadState::DOWNLOAD_IN_PROGRESS, bytes_progress / bytes_total);
948+
};
949+
m_transport->ReadRawData(bytesToRead, temp_buf, downloadCallback);
967950

968951
double ydelta = yorigin + yreference;
969952
cap->Resize(cap->m_samples.size() + header_blocksize);
@@ -993,7 +976,7 @@ bool RigolOscilloscope::AcquireData()
993976
npoint += header_blocksize;
994977
}
995978
// Notify about end of download for this channel
996-
UpdateChannelDownloadState(i,OscilloscopeChannel::DownloadState::DOWNLOAD_FINISHED);
979+
ChannelsDownloadStatusUpdate(i, InstrumentChannel::DownloadState::DOWNLOAD_FINISHED, 1.0);
997980

998981
//Done, update the data
999982
if(cap)

scopehal/SCPILinuxGPIBTransport.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ void SCPILinuxGPIBTransport::SendRawData(size_t len, const unsigned char* buf)
146146
ibwrt(m_handle, (const char *)buf, len);
147147
}
148148

149-
size_t SCPILinuxGPIBTransport::ReadRawData(size_t len, unsigned char* buf)
149+
size_t SCPILinuxGPIBTransport::ReadRawData(size_t len, unsigned char* buf, std::function<void(float)> /*progress*/)
150150
{
151151
if (!IsConnected())
152152
return 0;

scopehal/SCPILinuxGPIBTransport.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class SCPILinuxGPIBTransport : public SCPITransport
5656
void FlushRXBuffer(void) override;
5757
bool SendCommand(const std::string& cmd) override;
5858
std::string ReadReply(bool endOnSemicolon = true) override;
59-
size_t ReadRawData(size_t len, unsigned char* buf) override;
59+
size_t ReadRawData(size_t len, unsigned char* buf, std::function<void(float)> progress = nullptr) override;
6060
void SendRawData(size_t len, const unsigned char* buf) override;
6161

6262
bool IsCommandBatchingSupported() override;

0 commit comments

Comments
 (0)