diff --git a/src/Scope.cpp b/src/Scope.cpp index 3f85c05..cd2ce7c 100644 --- a/src/Scope.cpp +++ b/src/Scope.cpp @@ -36,26 +36,15 @@ struct Scope : Module { }; struct Point { - float minX[16] = {}; - float maxX[16] = {}; - float minY[16] = {}; - float maxY[16] = {}; - - Point() { - for (int c = 0; c < 16; c++) { - minX[c] = INFINITY; - maxX[c] = -INFINITY; - minY[c] = INFINITY; - maxY[c] = -INFINITY; - } - } + float min = INFINITY; + float max = -INFINITY; }; - Point pointBuffer[BUFFER_SIZE]; + Point pointBuffer[BUFFER_SIZE][2][PORT_MAX_CHANNELS]; + Point currentPoint[2][PORT_MAX_CHANNELS]; int channelsX = 0; int channelsY = 0; int bufferIndex = 0; int frameIndex = 0; - Point currentPoint; dsp::SchmittTrigger triggers[16]; @@ -85,7 +74,11 @@ struct Scope : Module { void onReset() override { for (int i = 0; i < BUFFER_SIZE; i++) { - pointBuffer[i] = Point(); + for (int w = 0; w < 2; w++) { + for (int c = 0; c < 16; c++) { + pointBuffer[i][w][c] = Point(); + } + } } } @@ -158,21 +151,29 @@ struct Scope : Module { // Get input for (int c = 0; c < channelsX; c++) { float x = inputs[X_INPUT].getVoltage(c); - currentPoint.minX[c] = std::min(currentPoint.minX[c], x); - currentPoint.maxX[c] = std::max(currentPoint.maxX[c], x); + currentPoint[0][c].min = std::min(currentPoint[0][c].min, x); + currentPoint[0][c].max = std::max(currentPoint[0][c].max, x); } for (int c = 0; c < channelsY; c++) { float y = inputs[Y_INPUT].getVoltage(c); - currentPoint.minY[c] = std::min(currentPoint.minY[c], y); - currentPoint.maxY[c] = std::max(currentPoint.maxY[c], y); + currentPoint[1][c].min = std::min(currentPoint[1][c].min, y); + currentPoint[1][c].max = std::max(currentPoint[1][c].max, y); } if (++frameIndex >= frameCount) { frameIndex = 0; // Push current point - pointBuffer[bufferIndex] = currentPoint; + for (int w = 0; w < 2; w++) { + for (int c = 0; c < 16; c++) { + pointBuffer[bufferIndex][w][c] = currentPoint[w][c]; + } + } // Reset current point - currentPoint = Point(); + for (int w = 0; w < 2; w++) { + for (int c = 0; c < 16; c++) { + currentPoint[w][c] = Point(); + } + } bufferIndex++; } } @@ -199,6 +200,24 @@ struct Scope : Module { }; +Scope::Point DEMO_POINT_BUFFER[BUFFER_SIZE]; + +void demoPointBufferInit() { + static bool init = false; + if (init) + return; + init = true; + + // Calculate demo point buffer + for (size_t i = 0; i < BUFFER_SIZE; i++) { + float phase = float(i) / BUFFER_SIZE; + Scope::Point point; + point.min = point.max = 4.f * std::sin(2 * M_PI * phase * 2.f); + DEMO_POINT_BUFFER[i] = point; + } +} + + struct ScopeDisplay : LedDisplay { Scope* module; ModuleWidget* moduleWidget; @@ -214,6 +233,8 @@ struct ScopeDisplay : LedDisplay { ScopeDisplay() { fontPath = asset::system("res/fonts/ShareTechMono-Regular.ttf"); + + demoPointBufferInit(); } void calculateStats(Stats& stats, int wave, int channels) { @@ -225,32 +246,18 @@ struct ScopeDisplay : LedDisplay { stats = Stats(); for (int i = 0; i < BUFFER_SIZE; i++) { - Scope::Point point = module->pointBuffer[i]; for (int c = 0; c < channels; c++) { - float max = (wave == 0) ? point.maxX[c] : point.maxY[c]; - float min = (wave == 0) ? point.minX[c] : point.minY[c]; - - stats.max = std::fmax(stats.max, max); - stats.min = std::fmin(stats.min, min); + Scope::Point point = module->pointBuffer[i][wave][c]; + stats.max = std::fmax(stats.max, point.max); + stats.min = std::fmin(stats.min, point.min); } } } void drawWave(const DrawArgs& args, int wave, int channel, float offset, float gain) { - // Copy point buffer to stack to prevent min/max values being different phase. - // This is currently only 256*4*16*4 = 64 kiB. Scope::Point pointBuffer[BUFFER_SIZE]; - if (module) { - std::copy(std::begin(module->pointBuffer), std::end(module->pointBuffer), std::begin(pointBuffer)); - } - else { - for (size_t i = 0; i < BUFFER_SIZE; i++) { - float phase = float(i) / BUFFER_SIZE; - Scope::Point point; - point.minX[0] = point.maxX[0] = 4.f * std::sin(2 * M_PI * phase * 2.f) + 5.f; - point.minY[0] = point.maxY[0] = 4.f * std::sin(2 * M_PI * phase * 2.f) - 5.f; - pointBuffer[i] = point; - } + for (int i = 0; i < BUFFER_SIZE; i++) { + pointBuffer[i] = module ? module->pointBuffer[i][wave][channel] : DEMO_POINT_BUFFER[i]; } nvgSave(args.vg); @@ -260,7 +267,7 @@ struct ScopeDisplay : LedDisplay { // Draw max points on top for (int i = 0; i < BUFFER_SIZE; i++) { const Scope::Point& point = pointBuffer[i]; - float max = (wave == 0) ? point.maxX[channel] : point.maxY[channel]; + float max = point.max; if (!std::isfinite(max)) max = 0.f; @@ -277,7 +284,7 @@ struct ScopeDisplay : LedDisplay { // Draw min points on bottom for (int i = BUFFER_SIZE - 1; i >= 0; i--) { const Scope::Point& point = pointBuffer[i]; - float min = (wave == 0) ? point.minX[channel] : point.minY[channel]; + float min = point.min; if (!std::isfinite(min)) min = 0.f; @@ -301,8 +308,12 @@ struct ScopeDisplay : LedDisplay { if (!module) return; - Scope::Point pointBuffer[BUFFER_SIZE]; - std::copy(std::begin(module->pointBuffer), std::end(module->pointBuffer), std::begin(pointBuffer)); + Scope::Point pointBufferX[BUFFER_SIZE]; + Scope::Point pointBufferY[BUFFER_SIZE]; + for (int i = 0; i < BUFFER_SIZE; i++) { + pointBufferX[i] = module->pointBuffer[i][0][channel]; + pointBufferY[i] = module->pointBuffer[i][1][channel]; + } nvgSave(args.vg); Rect b = box.zeroPos().shrink(Vec(0, 15)); @@ -311,9 +322,10 @@ struct ScopeDisplay : LedDisplay { int bufferIndex = module->bufferIndex; for (int i = 0; i < BUFFER_SIZE; i++) { // Get average point - const Scope::Point& point = pointBuffer[(i + bufferIndex) % BUFFER_SIZE]; - float avgX = (point.minX[channel] + point.maxX[channel]) / 2; - float avgY = (point.minY[channel] + point.maxY[channel]) / 2; + const Scope::Point& pointX = pointBufferX[(i + bufferIndex) % BUFFER_SIZE]; + const Scope::Point& pointY = pointBufferY[(i + bufferIndex) % BUFFER_SIZE]; + float avgX = (pointX.min + pointX.max) / 2; + float avgY = (pointY.min + pointY.max) / 2; if (!std::isfinite(avgX) || !std::isfinite(avgY)) continue; @@ -430,8 +442,8 @@ struct ScopeDisplay : LedDisplay { gainX = std::pow(2.f, std::round(gainX)) / 10.f; float gainY = module ? module->params[Scope::Y_SCALE_PARAM].getValue() : 0.f; gainY = std::pow(2.f, std::round(gainY)) / 10.f; - float offsetX = module ? module->params[Scope::X_POS_PARAM].getValue() : 0.f; - float offsetY = module ? module->params[Scope::Y_POS_PARAM].getValue() : 0.f; + float offsetX = module ? module->params[Scope::X_POS_PARAM].getValue() : 5.f; + float offsetY = module ? module->params[Scope::Y_POS_PARAM].getValue() : -5.f; // Get input colors PortWidget* inputX = moduleWidget->getInput(Scope::X_INPUT);