#include "Scope.hpp" #include ScopeBuffer::ScopeBuffer(QObject *parent) : QObject(parent) { // timer is set in qml } ScopeBuffer::ScopeBuffer(ConfigService* config, LoggerService* logger, size_t size) : config_(config), logger_(logger), buffer_(size) { } void ScopeBuffer::push(float sample) { size_t w = writeIndex_.fetch_add(1, std::memory_order_relaxed); buffer_[w % buffer_.size()] = sample; } void ScopeBuffer::read(std::vector& out) { size_t w = writeIndex_.load(std::memory_order_relaxed); for(size_t i = 0; i < buffer_.size(); i++) { size_t idx = (w + trigger_ + i * wavelength_ / out.size()) % buffer_.size(); out[i] = buffer_[idx]; } } Scope::Scope(QQuickItem *parent) : QQuickPaintedItem(parent) { setAntialiasing(true); } void Scope::setBuffer(ScopeBuffer* scopeBuffer) { scopeBuffer_ = scopeBuffer; buffer_ = std::vector(scopeBuffer_->size()); } void Scope::paint(QPainter *painter) { while(scopeBuffer_->spinlock()) { // wait } if(scopeBuffer_ != nullptr) scopeBuffer_->read(buffer_); // TODO: scale to max amplitude ? probably make it configurable if you want to make scope options float maxAmp = 1.0f; /* for(float s : buffer_) { maxAmp = std::max(maxAmp, std::abs(s)); } */ float scaleY = (height() * 0.45f) / maxAmp; float midY = height() / 2.0f; painter->fillRect(0, 0, width(), height(), QColor(20, 20, 20)); QPen pen; pen.setWidthF(3.0f); QColor green(50, 255, 70); pen.setColor(green); painter->setPen(pen); painter->setRenderHint(QPainter::Antialiasing); for(size_t i = 1; i < buffer_.size(); i++) { painter->drawLine( i * width() / buffer_.size(), midY + buffer_[i-1] * scaleY, i * width() / buffer_.size(), midY + buffer_[i] * scaleY ); } }