1
/***************************************************************************
2
* Copyright (C) 2020 by santiago González *
3
* santigoro@gmail.com *
5
* This program is free software; you can redistribute it and/or modify *
6
* it under the terms of the GNU General Public License as published by *
7
* the Free Software Foundation; either version 3 of the License, or *
8
* (at your option) any later version. *
10
* This program is distributed in the hope that it will be useful, *
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13
* GNU General Public License for more details. *
15
* You should have received a copy of the GNU General Public License *
16
* along with this program; if not, see <http://www.gnu.org/licenses/>. *
18
***************************************************************************/
20
#include "oscopechannel.h"
22
#include "simulator.h"
24
OscopeChannel::OscopeChannel( QString id )
35
m_points = &m_pointsA;
37
OscopeChannel::~OscopeChannel() { }
39
void OscopeChannel::initialize()
41
//qDebug() <<"OscopeChannel::resetState";
73
//DataChannel::updateStep();
74
m_dataPlotW->m_data1Label[m_channel]->setText( "---" );
75
m_dataPlotW->m_data2Label[m_channel]->setText( "---" );
76
m_dataPlotW->m_display->update();
79
void OscopeChannel::runEvent()
81
if( !m_runEvent ) return;
83
Simulator::self()->addEvent( m_hTick/20, this );
86
void OscopeChannel::updateStep()
90
uint64_t simTime = Simulator::self()->circTime();
92
if( !m_reading ) // There is data set ready to display
95
m_dataPlotW->m_display->setData( m_channel, m_points );
97
if( m_points == &m_pointsA ) m_points = &m_pointsB;
98
else m_points = &m_pointsA;
100
m_dataPlotW->m_display->update();
103
if( m_numMax > 1 ) // Got enought maximums to calculate Freq
105
m_freq = 1e12/((double)m_totalP/(double)(m_numMax-1));
110
if( m_period > 10 ) // We have a wave
114
uint64_t stepsPF = Simulator::self()->circuitRate()*1e6;
115
uint64_t lost = m_period*2;
116
if( lost < stepsPF ) lost = stepsPF*2;
118
if( simTime-m_lastMax > lost ) // Wave lost
135
else if( !m_runEvent ) // No wave, then read voltages in runEvent
137
if( !m_dataPlotW->m_paOnCond )
140
Simulator::self()->addEvent( m_hTick/20, this );
144
if( m_ampli > 1e-6 ) m_dataPlotW->m_display->setMaxMin( m_channel, m_dispMax, m_dispMin );
146
double freq = m_freq;
149
QString unit = " Hz";
153
freq /= 1e3; unit = " KHz";
154
if( freq > 999 ) { freq /= 1e3; unit = " MHz"; }
156
if ( freq < 10 ) Fdecs = 4;
157
else if( freq < 100 ) Fdecs = 3;
158
m_dataPlotW->m_data1Label[m_channel]->setText( " "+QString::number( freq, 'f', Fdecs )+unit );
161
double val = m_ampli;
169
if ( val < 10 ) Vdecimals = 2;
170
else if( val < 100 ) Vdecimals = 1;
171
m_dataPlotW->m_data2Label[m_channel]->setText( "Amp "+QString::number( val,'f', Vdecimals )+unit );
173
DataChannel::updateStep();
177
void OscopeChannel::voltChanged()
179
uint64_t simTime = Simulator::self()->circTime();
181
double data = m_ePin[0]->getVolt() + m_ePin[1]->getVolt();
183
if( data > m_maxVal ) m_maxVal = data;
184
if( data < m_minVal ) m_minVal = data;
186
if( ++m_bufferCounter >= m_buffer.size() ) m_bufferCounter = 0;
187
m_buffer[m_bufferCounter] = data;
188
uint64_t time = simTime;
189
m_time[m_bufferCounter] = time;
191
double delta = data-m_lastValue;
193
if( delta > 0 ) // Rising
195
if( delta > m_filter )
197
if( m_falling && !m_rising ) // Min To Rising
199
if( m_numMax > 0 ) m_totalP += simTime-m_lastMax;
206
if( m_dataPlotW->m_paOnCond )
208
if( (m_chCond == Rising) || (m_chCond == High) ) // Pause on Rising or High
211
m_dataPlotW->m_plotB->pauseOnCond();
212
if( m_chCond == Rising ) m_chCondFlag = false;
214
else if( m_chCond == Low ) m_chCondFlag = false;
217
else if( m_dataPlotW->m_paOnCond )
219
if( m_chCond == Rising ) m_chCondFlag = false;
224
if( m_nCycles > 1 ) // Wait for a full wave
226
m_ampli = m_maxVal-m_minVal;
227
double mid = m_minVal + m_ampli/2;
229
if( data >= mid ) // Rising edge
231
m_dispMax = m_maxVal;
232
m_dispMin = m_minVal;
237
if( m_risEdge > 0 ) m_period = simTime-m_risEdge; // period = this_edge_time - last_edge_time
243
if( m_dataPlotW->m_auto == m_channel )
246
m_vTick = m_ampli/10;
247
if ( m_vTick > 1000 ) m_vTick = 1000;
248
else if( m_vTick < 0.001 ) m_vTick = 0.001;
250
m_hTick = abs( (double)m_period/5 );
251
if( m_hTick < 1 ) m_hTick = 1;
257
else if( delta < -m_filter ) // Falling
259
if( m_rising && !m_falling ) // Max Found
263
if( m_dataPlotW->m_paOnCond )
265
if( (m_chCond == Falling) || (m_chCond == Low) ) // Pause on Falling or Low
268
m_dataPlotW->m_plotB->pauseOnCond();
269
if( m_chCond == Falling ) m_chCondFlag = false;
271
else if( m_chCond == High ) m_chCondFlag = false;
274
else if( m_dataPlotW->m_paOnCond )
276
if( m_chCond == Falling ) m_chCondFlag = false;
281
if( m_dataPlotW->m_paOnCond ) return;
284
if( m_trigger < 2 ) // We want wave
286
if( m_trigger == m_channel ) // We drive trigger
288
if( m_period > 10 ) // We have wave
289
m_dataPlotW->m_plotB->fetchData( m_channel, m_risEdge );
290
else // We don't have a wave, trigger just now
291
m_dataPlotW->m_plotB->fetchData( m_channel, time );
296
fetchData( m_channel, time );
301
void OscopeChannel::fetchData( int ch, uint64_t edge )
303
//if( m_trigger && ch != m_channel ) return; // we have our own trigger
304
if( !m_reading ) return;
306
uint64_t period = m_period;
307
if( m_period <= 10 ) period = m_hTick/20;
308
if( m_dataPlotW->m_paOnCond ) period = m_hTick/20;// Pause on Condition
310
uint64_t timeFrame = m_hTick*10;
311
uint64_t nCycles = timeFrame/period;
312
if( timeFrame%period ) nCycles++;
313
if( nCycles%2 ) nCycles++;
315
uint64_t orig = edge-nCycles*period/2-timeFrame/2;
316
uint64_t origAbs = edge-(nCycles+1)*period;
318
if( m_dataPlotW->m_paOnCond ) // Pause on Condition
320
uint64_t size = edge-origAbs;
321
if( size < m_dataSize )
323
if( edge < m_dataSize) origAbs = 0;
324
else origAbs = edge - m_dataSize;
327
int pos = m_bufferCounter;
332
m_points->prepend( QPointF( edge-orig, m_buffer[pos] )); // First poit at current time
334
for( int i=0; i<m_buffer.size(); ++i ) // Read Backwards
336
timeAbs = m_time.at(pos);
338
m_points->prepend( QPointF( time, m_buffer[pos] ));
339
if( timeAbs < origAbs ) break; // End of data
342
if( pos < 0 ) pos += m_buffer.size();
344
//m_dataPlotW->m_display->setXFrame( m_channel, timeFrame );