diff --git a/radio/src/gui/colorlcd/radio_spectrum_analyser.cpp b/radio/src/gui/colorlcd/radio_spectrum_analyser.cpp index 96648a279..ca100fe46 100644 --- a/radio/src/gui/colorlcd/radio_spectrum_analyser.cpp +++ b/radio/src/gui/colorlcd/radio_spectrum_analyser.cpp @@ -21,8 +21,20 @@ #include "radio_spectrum_analyser.h" #include "opentx.h" +extern uint8_t g_moduleIdx; #define SPECTRUM_HEIGHT 200 + +coord_t getAverage(uint8_t number, const uint8_t * value) +{ + uint16_t sum = 0; + for (uint8_t i = 0; i < number; i++) { + sum += value[i]; + } + return sum / number; +} + + class SpectrumWindow : public Window { public: @@ -38,20 +50,65 @@ class SpectrumWindow : public Window return; } - coord_t peak_y = 1; - coord_t peak_x = 0; - for (coord_t i = 0; i < LCD_W; i++) { - auto h = min(reusableBuffer.spectrumAnalyser.bars[i], SPECTRUM_HEIGHT); - if (h > peak_y) { - peak_x = i; - peak_y = h; +#if defined(SIMU) + // Geneate random data for simu + for(coord_t x= 0; x < width(); x++) { + uint8_t power = rand() % 80; + reusableBuffer.spectrumAnalyser.bars[x] = power; + reusableBuffer.spectrumAnalyser.bars[x+1] = power; + if (power > reusableBuffer.spectrumAnalyser.max[x]) { + reusableBuffer.spectrumAnalyser.max[x] = power; + reusableBuffer.spectrumAnalyser.max[x+1] = power; + } + } +#endif + + constexpr coord_t SCALE_HEIGHT = 12; + coord_t SCALE_TOP = height() - SCALE_HEIGHT - MENU_FOOTER_HEIGHT; + coord_t BARGRAPH_HEIGHT = height() - SCALE_HEIGHT; + + // Draw fixed part (scale,..) + dc->drawSolidFilledRect(0, SCALE_TOP, width(), SCALE_HEIGHT, CURVE_AXIS_COLOR); + for (uint32_t frequency = ((reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2) / 10000000) * 10000000 + 10000000; ; frequency += 10000000) { + int offset = frequency - (reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2); + int x = offset / reusableBuffer.spectrumAnalyser.step; + if (x >= LCD_W - 1) + break; + dc->drawVerticalLine(x, 0, height(), STASHED, CURVE_AXIS_COLOR); + + if ((frequency / 1000000) % 2 == 0) { + dc->drawNumber(x, SCALE_TOP - 2, frequency / 1000000, FONT(XS) | CENTERED); } - dc->drawVerticalLine(i, SPECTRUM_HEIGHT - h, h, SOLID, 0); } - auto y = max(FH, SPECTRUM_HEIGHT - peak_y - FH); - auto x = dc->drawNumber(min(100, peak_x), y, ((reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2) + peak_x * (reusableBuffer.spectrumAnalyser.span / 128)) / 1000000, FONT(XXS)); - dc->drawText(x, y, "M", FONT(XXS)); + for (uint8_t power = 20;; power += 20) { + int y = SCALE_TOP - 1 - limit(0, power << 1, SCALE_TOP); + if (y <= 0) + break; + dc->drawHorizontalLine(0, y, width(), STASHED, CURVE_AXIS_COLOR); + } + + // Draw spectrum data + constexpr uint8_t step = 4; + + for (coord_t xv = 0; xv < width(); xv += step) { + coord_t yv = SCALE_TOP - 1 - limit(0, getAverage(step, &reusableBuffer.spectrumAnalyser.bars[xv]) << 1, SCALE_TOP); + coord_t max_yv = SCALE_TOP - 1 - limit(0, getAverage(step, &reusableBuffer.spectrumAnalyser.max[xv]) << 1, SCALE_TOP); + + // Signal bar + dc->drawSolidFilledRect(xv, yv, step - 1, SCALE_TOP - yv, YELLOW); + // lcdDrawSolidRect(xv, yv, step - 1, SCALE_TOP - yv, 1, TEXT_COLOR); + + // Signal max + dc->drawSolidHorizontalLine(xv, max_yv, step - 1, BLACK); + + // Decay max values + if (max_yv < yv) { // Those value are INVERTED (MENU_FOOTER_TOP - value) + for (uint8_t i = 0; i < step; i++) { + reusableBuffer.spectrumAnalyser.max[xv + i] = max(0, reusableBuffer.spectrumAnalyser.max[xv + i] - 1); + } + } + } } protected: @@ -74,7 +131,14 @@ void RadioSpectrumAnalyser::buildBody(FormWindow * window) void RadioSpectrumAnalyser::start() { - if (isModuleR9MAccess(moduleIdx)) { +#if defined(INTERNAL_MODULE_MULTI) + if (g_moduleIdx == INTERNAL_MODULE && g_model.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_NONE) { + reusableBuffer.spectrumAnalyser.moduleOFF = true; + setModuleType(INTERNAL_MODULE, MODULE_TYPE_MULTIMODULE); + } +#endif + + if (isModuleR9MAccess(g_moduleIdx)) { reusableBuffer.spectrumAnalyser.spanDefault = 20; reusableBuffer.spectrumAnalyser.spanMax = 40; reusableBuffer.spectrumAnalyser.freqDefault = 890; @@ -82,23 +146,25 @@ void RadioSpectrumAnalyser::start() reusableBuffer.spectrumAnalyser.freqMax = 930; } else { - reusableBuffer.spectrumAnalyser.spanDefault = 40; // 40MHz + if (isModuleMultimodule(g_moduleIdx)) + reusableBuffer.spectrumAnalyser.spanDefault = 80; // 80MHz + else + reusableBuffer.spectrumAnalyser.spanDefault = 40; // 40MHz reusableBuffer.spectrumAnalyser.spanMax = 80; reusableBuffer.spectrumAnalyser.freqDefault = 2440; // 2440MHz reusableBuffer.spectrumAnalyser.freqMin = 2400; reusableBuffer.spectrumAnalyser.freqMax = 2485; } - if (moduleState[moduleIdx].mode != MODULE_MODE_SPECTRUM_ANALYSER) { - memclear(reusableBuffer.spectrumAnalyser.bars, sizeof(reusableBuffer.spectrumAnalyser.bars)); - reusableBuffer.spectrumAnalyser.span = reusableBuffer.spectrumAnalyser.spanDefault * 1000000; - reusableBuffer.spectrumAnalyser.freq = reusableBuffer.spectrumAnalyser.freqDefault * 1000000; - reusableBuffer.spectrumAnalyser.step = reusableBuffer.spectrumAnalyser.span / LCD_W; - reusableBuffer.spectrumAnalyser.dirty = true; - moduleState[moduleIdx].mode = MODULE_MODE_SPECTRUM_ANALYSER; - } + reusableBuffer.spectrumAnalyser.span = reusableBuffer.spectrumAnalyser.spanDefault * 1000000; + reusableBuffer.spectrumAnalyser.freq = reusableBuffer.spectrumAnalyser.freqDefault * 1000000; + reusableBuffer.spectrumAnalyser.track = reusableBuffer.spectrumAnalyser.freq; + reusableBuffer.spectrumAnalyser.step = reusableBuffer.spectrumAnalyser.span / LCD_W; + reusableBuffer.spectrumAnalyser.dirty = true; + moduleState[g_moduleIdx].mode = MODULE_MODE_SPECTRUM_ANALYSER; } + void RadioSpectrumAnalyser::stop() { new MessageDialog(STR_MODULE, STR_STOPPING);