Пример #1
0
void OscilloscopeView::drawLogicData( QPainter & p)
{
	const double pixelsPerSecond = Oscilloscope::self()->pixelsPerSecond();
	
	const LogicProbeDataMap::iterator end = Oscilloscope::self()->m_logicProbeDataMap.end();
	for( LogicProbeDataMap::iterator it = Oscilloscope::self()->m_logicProbeDataMap.begin(); it != end; ++it)
	{
		// When searching for the next logic value to display, we look along
		// until there is a recorded point which is at least one pixel along
		// If we are zoomed out far, there might be thousands of data points
		// between each pixel. It is time consuming searching for the next point
		// to display one at a time, so we record the average number of data points
		// between pixels ( = deltaAt / totalDeltaAt)
		int64_t deltaAt = 1;
		int totalDeltaAt = 1;
		
		LogicProbeData * probe = it.value();

		vector<LogicDataPoint> *data = probe->m_data;
		if(!data->size()) continue;
		
		const int midHeight = Oscilloscope::self()->probePositioner->probePosition(probe);
		const int64_t timeOffset = Oscilloscope::self()->scrollTime();
		
		// Draw the horizontal line indicating the midpoint of our output
		p.setPen( QColor( 228, 228, 228));
		p.drawLine( 0, midHeight, width(), midHeight);
		
		// Set the pen colour according to the colour the user has selected for the probe
		p.setPen( probe->color());
		
		// The smallest time step that will display in our oscilloscope
		const int minTimeStep = int(LOGIC_UPDATE_RATE/pixelsPerSecond);
		
		int64_t at = probe->findPos(timeOffset);
		const int64_t maxAt = probe->m_data->size();
		int64_t prevTime = (*data)[at].time;
		int prevX = (at > 0) ? 0 : int((prevTime - timeOffset)*(pixelsPerSecond/LOGIC_UPDATE_RATE));
		bool prevHigh = (*data)[at].value;
		int prevY = midHeight + int(prevHigh ? -m_halfOutputHeight : +m_halfOutputHeight);

		while ( at < maxAt) {
			// Search for the next pos which will show up at our zoom level
			int64_t previousAt = at;
			int64_t dAt = deltaAt / totalDeltaAt;
			
			while ( (dAt > 1) && (at < maxAt) && ( (int64_t((*data)[at].time) - prevTime) != minTimeStep))
			{
				// Search forwards until we overshoot
				while ( at < maxAt && ( int64_t((*data)[at].time) - prevTime) < minTimeStep)
					at += dAt;
				dAt /= 2;
				
				// Search backwards until we undershoot
				while ( (at < maxAt) && ( int64_t((*data)[at].time) - prevTime) > minTimeStep)
				{
					at -= dAt;
					if( at < 0)
						at = 0;
				}
				dAt /= 2;
			}
			
			// Possibly increment the value of at found by one (or more if this is the first go)
			while ( (previousAt == at) || ((at < maxAt) && ( int64_t((*data)[at].time) - prevTime) < minTimeStep))
				at++;

			if( at >= maxAt) break;

			// Update the average values
			deltaAt += at - previousAt;
			totalDeltaAt++;
			
			bool nextHigh = (*data)[at].value;
			if( nextHigh == prevHigh) continue;

			int64_t nextTime = (*data)[at].time;
			int nextX = int((nextTime - timeOffset)*(pixelsPerSecond/LOGIC_UPDATE_RATE));
			int nextY = midHeight + int(nextHigh ? -m_halfOutputHeight : +m_halfOutputHeight);
			
			p.drawLine( prevX, prevY, nextX, prevY);
			p.drawLine( nextX, prevY, nextX, nextY);

			prevHigh = nextHigh;
			prevTime = nextTime;
			prevX = nextX;
			prevY = nextY;

			if( nextX > width()) break;
		};
		
		// If we could not draw right to the end; it is because we exceeded
		// maxAt
		if( prevX < width())
			p.drawLine( prevX, prevY, width(), prevY);
	}
}
Пример #2
0
void ScopeScreenView::drawContents(QPainter * p)
{
	QRect cr = contentsRect();

	for(int i =1; i < m_intervalsX; i++)
	{
		int x = cr.left() + cr.width()*i/m_intervalsX;
		p->drawLine(x, cr.top(), x, cr.bottom());
	}
	const int ticksPerScreen = m_intervalsX * m_ticksPerIntervalX;
	const double pixelsPerTick = cr.width()/double(ticksPerScreen);
	const double ticksPerPixel = m_intervalsX * m_ticksPerIntervalX / cr.width();	
	//draw the current time
	int curTimeX = ((Simulator::self()->time() + m_offsetX) % (ticksPerScreen)) * pixelsPerTick;
	//kDebug() << curTimeX <<endl;
	p->drawLine(curTimeX, cr.top(), curTimeX, cr.bottom());
	
	//the following is liberally borrowed from OscilloscopeView::drawFloatingData
	const FloatingProbeDataMap::iterator end = Oscilloscope::self()->m_floatingProbeDataMap.end();
	for ( FloatingProbeDataMap::iterator it = Oscilloscope::self()->m_floatingProbeDataMap.begin(); it != end; ++it )
	{
		FloatingProbeData * probe = it.value();
		StoredData<float> * data = &(probe->m_data);
		
		if ( data->allocatedUpTo() == 0 )
			continue;
		
		bool logarithmic = probe->scaling() == FloatingProbeData::Logarithmic;
		double lowerAbsValue = probe->lowerAbsValue();
		double sf = ((cr.height()/Oscilloscope::self()->numberOfProbes())/2) / (logarithmic ? log(probe->upperAbsValue()/lowerAbsValue) : probe->upperAbsValue());
		
		const int midHeight = Oscilloscope::self()->probePositioner->probePosition(probe);
		//const int midHeight = cr.top() + cr.height()/2;		
		//const llong timeOffset = Oscilloscope::self()->scrollTime();
		const llong timeOffset = Simulator::self()->time() - (FADESPEED * m_intervalsX * m_ticksPerIntervalX);
		
		// Draw the horizontal line indicating the midpoint of our output
		p->setPen( QColor( 228, 228, 228 ) );
		p->drawLine( 0, midHeight, width(), midHeight );
		
		// Set the pen colour according to the colour the user has selected for the probe
		p->setPen( probe->color() );
		
		llong at = probe->findPos(timeOffset); 
		const llong maxAt = probe->insertPos();
		llong prevTime = probe->toTime(at);
		
		double v = data->dataAt((at>0)?at:0);
		int prevY = int(midHeight - (logarithmic ? ( (v>0) ? log(v/lowerAbsValue) : -log(-v/lowerAbsValue) ) : v) * sf);
		int prevX = (int((prevTime - timeOffset)*pixelsPerTick) + curTimeX) % cr.width();
		
		while ( at < maxAt-1 )
		{
			at++;
			
			ullong nextTime = probe->toTime(at);
			
			double v = data->dataAt((at>0)?at:0);
			int nextY = int(midHeight - (logarithmic ? ( (v>0) ? log(v/lowerAbsValue) : -log(-v/lowerAbsValue) ) : v) * sf);
			int nextX = (int((nextTime - timeOffset)*pixelsPerTick) + curTimeX) % cr.width();
			if(nextX < prevX)
			{
				prevX = 0;
			}
			//kDebug() <<at<<" "<<nextX<<" "<<nextY<<" "<<nextTime<<endl;
			p->drawLine( prevX, prevY, nextX, nextY );
			
			prevTime = nextTime;
			prevX = nextX;
			prevY = nextY;
			
			//if ( nextX > width() )
			//break;
		};
		
		// If we could not draw right to the end; it is because we exceeded
		// maxAt
		//if ( prevX < curTimeX )
		//	p->drawLine( prevX, prevY, curTimeX, prevY );
	}
	
	//and this was liberally borrowed from OscilloscopeView::DrawLogicData
	{
	const LogicProbeDataMap::iterator end = Oscilloscope::self()->m_logicProbeDataMap.end();
	for ( LogicProbeDataMap::iterator it = Oscilloscope::self()->m_logicProbeDataMap.begin(); it != end; ++it )
	{
		// When searching for the next logic value to display, we look along
		// until there is a recorded point which is at least one pixel along
		// If we are zoomed out far, there might be thousands of data points
		// between each pixel. It is time consuming searching for the next point
		// to display one at a time, so we record the average number of data points
		// between pixels ( = deltaAt / totalDeltaAt )
		llong deltaAt = 1;
		int totalDeltaAt = 1;
		
		LogicProbeData * probe = it.value();
		StoredData<LogicDataPoint> * data = &(probe->m_data);
		
		if ( data->allocatedUpTo() == 0 )
			continue;
		
		const int midHeight = Oscilloscope::self()->probePositioner->probePosition(probe);
		const llong timeOffset = Simulator::self()->time() - (FADESPEED * m_intervalsX * m_ticksPerIntervalX);//Oscilloscope::self()->scrollTime();
		
		const int halfOutputHeight = ((cr.height()/Oscilloscope::self()->numberOfProbes())/2);
		
		// Draw the horizontal line indicating the midpoint of our output
		p->setPen( QColor( 228, 228, 228 ) );
		p->drawLine( 0, midHeight, width(), midHeight );
		
		// Set the pen colour according to the colour the user has selected for the probe
		p->setPen( probe->color() );
		
		// The smallest time step that will display in our oscilloscope
		const int minTimeStep = ticksPerPixel;//int(LOGIC_UPDATE_RATE/pixelsPerSecond);
		
		llong at = probe->findPos(timeOffset);
		const llong maxAt = probe->insertPos();
		llong prevTime = data->dataAt(at).time;
		int prevX = (int((prevTime - timeOffset)*pixelsPerTick) + curTimeX) % cr.width();
		bool prevHigh = data->dataAt(at).value;
		int prevY = midHeight + int(prevHigh ? -halfOutputHeight : +halfOutputHeight);
		while ( at < maxAt )
		{
			// Search for the next pos which will show up at our zoom level
			llong previousAt = at;
			llong dAt = deltaAt / totalDeltaAt;
			
			while ( (dAt > 1) && (at < maxAt) && ( (llong(data->dataAt(at).time) - prevTime) != minTimeStep ) )
			{
				// Search forwards until we overshoot
				while ( at < maxAt && ( llong(data->dataAt(at).time) - prevTime ) < minTimeStep )
					at += dAt;
				dAt /= 2;
				
				// Search backwards until we undershoot
				while ( (at < maxAt) && ( llong(data->dataAt(at).time) - prevTime ) > minTimeStep )
				{
					at -= dAt;
					if ( at < 0 )
						at = 0;
				}
				dAt /= 2;
			}
			
			// Possibly increment the value of at found by one (or more if this is the first go)
			while ( (previousAt == at) || ((at < maxAt) && ( llong(data->dataAt(at).time) - prevTime ) < minTimeStep) )
				at++;
			
			if ( at >= maxAt )
				break;
			
			// Update the average values
			deltaAt += at - previousAt;
			totalDeltaAt++;
			
			bool nextHigh = data->dataAt(at).value;
			if ( nextHigh == prevHigh )
				continue;
			llong nextTime = data->dataAt(at).time;
			int nextX = (int((nextTime - timeOffset)*pixelsPerTick) + curTimeX) % cr.width();
			int nextY = midHeight + int(nextHigh ? -halfOutputHeight : +halfOutputHeight);
			
			p->drawLine( prevX, prevY, nextX, prevY );
			p->drawLine( nextX, prevY, nextX, nextY );
			
			prevHigh = nextHigh;
			prevTime = nextTime;
			prevX = nextX;
			prevY = nextY;
			
			if ( nextX > width() )
				break;
		};
		
		// If we could not draw right to the end; it is because we exceeded
		// maxAt
		//if ( prevX < width() )
		//	p->drawLine( prevX, prevY, width(), prevY );
	}
	}
}