1
0
Fork 0
mirror of https://github.com/EdgeTX/edgetx.git synced 2025-07-23 16:25:12 +03:00

Spectrum analyser reworked (#6836)

* Spectrum analyser reworked

* Fix typo

* Cosmetics

* Cosmetics

* yet another overall look update

* T16 compilations fixes

* Various Taranis compile  fixes

* Cosmetics

* Cosmetics

* Cosmetics

* Cosmetics fixes
This commit is contained in:
3djc 2019-10-10 15:42:35 +02:00 committed by GitHub
parent 7094a744d6
commit 891c13e98d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 284 additions and 131 deletions

View file

@ -52,7 +52,7 @@ enum MenuRadioIndexes
{ {
MENU_RADIO_SETUP, MENU_RADIO_SETUP,
CASE_SDCARD(MENU_RADIO_SD_MANAGER) CASE_SDCARD(MENU_RADIO_SD_MANAGER)
#if defined(LUA) || defined(PXX2) #if defined(LUA) || defined(PXX2) || defined(MULTIMODULE)
MENU_RADIO_TOOLS, MENU_RADIO_TOOLS,
#endif #endif
MENU_RADIO_SPECIAL_FUNCTIONS, MENU_RADIO_SPECIAL_FUNCTIONS,

View file

@ -22,20 +22,41 @@
extern uint8_t g_moduleIdx; extern uint8_t g_moduleIdx;
enum SpectrumFields { enum SpectrumFields
{
SPECTRUM_FREQUENCY, SPECTRUM_FREQUENCY,
SPECTRUM_SPAN, SPECTRUM_SPAN,
SPECTRUM_TRACK,
SPECTRUM_FIELDS_MAX SPECTRUM_FIELDS_MAX
}; };
coord_t getAverage(uint8_t number, uint8_t * value)
{
uint16_t sum = 0;
for (uint8_t i = 0; i < number; i++) {
sum += value[i];
}
return sum / number;
}
#define SPECTRUM_ROW (isModuleMultimodule(g_moduleIdx) ? READONLY_ROW : (uint8_t)0)
constexpr uint8_t GREYBAR_HEIGHT = 12;
bool menuRadioSpectrumAnalyser(event_t event) bool menuRadioSpectrumAnalyser(event_t event)
{ {
SUBMENU(STR_MENU_SPECTRUM_ANALYSER, ICON_RADIO_SPECTRUM_ANALYSER, 1, {1}); SUBMENU(STR_MENU_SPECTRUM_ANALYSER, ICON_RADIO_SPECTRUM_ANALYSER, SPECTRUM_FIELDS_MAX, {
SPECTRUM_ROW, //Freq
SPECTRUM_ROW, //Span
0 //Track
});
if (menuEvent) { if (menuEvent) {
lcdDrawCenteredText(LCD_H/2, STR_STOPPING); lcdDrawCenteredText(LCD_H / 2, STR_STOPPING);
lcdRefresh(); lcdRefresh();
moduleState[g_moduleIdx].readModuleInformation(&reusableBuffer.moduleSetup.pxx2.moduleInformation, PXX2_HW_INFO_TX_ID, PXX2_HW_INFO_TX_ID); if (isModulePXX2(g_moduleIdx))
moduleState[g_moduleIdx].readModuleInformation(&reusableBuffer.moduleSetup.pxx2.moduleInformation, PXX2_HW_INFO_TX_ID, PXX2_HW_INFO_TX_ID);
else if (isModuleMultimodule((g_moduleIdx)))
moduleState[g_moduleIdx].mode = MODULE_MODE_NORMAL;
/* wait 1s to resume normal operation before leaving */ /* wait 1s to resume normal operation before leaving */
watchdogSuspend(1000); watchdogSuspend(1000);
RTOS_WAIT_MS(1000); RTOS_WAIT_MS(1000);
@ -44,7 +65,7 @@ bool menuRadioSpectrumAnalyser(event_t event)
if (moduleState[g_moduleIdx].mode != MODULE_MODE_SPECTRUM_ANALYSER) { if (moduleState[g_moduleIdx].mode != MODULE_MODE_SPECTRUM_ANALYSER) {
if (TELEMETRY_STREAMING()) { if (TELEMETRY_STREAMING()) {
lcdDrawCenteredText(LCD_H/2, STR_TURN_OFF_RECEIVER); POPUP_WARNING(STR_TURN_OFF_RECEIVER);
if (event == EVT_KEY_FIRST(KEY_EXIT)) { if (event == EVT_KEY_FIRST(KEY_EXIT)) {
killEvents(event); killEvents(event);
popMenu(); popMenu();
@ -62,7 +83,10 @@ bool menuRadioSpectrumAnalyser(event_t event)
reusableBuffer.spectrumAnalyser.freqMax = 930; reusableBuffer.spectrumAnalyser.freqMax = 930;
} }
else { 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.spanMax = 80;
reusableBuffer.spectrumAnalyser.freqDefault = 2440; // 2440MHz reusableBuffer.spectrumAnalyser.freqDefault = 2440; // 2440MHz
reusableBuffer.spectrumAnalyser.freqMin = 2400; reusableBuffer.spectrumAnalyser.freqMin = 2400;
@ -71,13 +95,14 @@ bool menuRadioSpectrumAnalyser(event_t event)
reusableBuffer.spectrumAnalyser.span = reusableBuffer.spectrumAnalyser.spanDefault * 1000000; reusableBuffer.spectrumAnalyser.span = reusableBuffer.spectrumAnalyser.spanDefault * 1000000;
reusableBuffer.spectrumAnalyser.freq = reusableBuffer.spectrumAnalyser.freqDefault * 1000000; reusableBuffer.spectrumAnalyser.freq = reusableBuffer.spectrumAnalyser.freqDefault * 1000000;
reusableBuffer.spectrumAnalyser.track = reusableBuffer.spectrumAnalyser.freq;
reusableBuffer.spectrumAnalyser.step = reusableBuffer.spectrumAnalyser.span / LCD_W; reusableBuffer.spectrumAnalyser.step = reusableBuffer.spectrumAnalyser.span / LCD_W;
reusableBuffer.spectrumAnalyser.dirty = true; reusableBuffer.spectrumAnalyser.dirty = true;
moduleState[g_moduleIdx].mode = MODULE_MODE_SPECTRUM_ANALYSER; moduleState[g_moduleIdx].mode = MODULE_MODE_SPECTRUM_ANALYSER;
} }
for (uint8_t i=0; i<SPECTRUM_FIELDS_MAX; i++) { for (uint8_t i = 0; i < SPECTRUM_FIELDS_MAX; i++) {
LcdFlags attr = (menuHorizontalPosition == i ? (s_editMode>0 ? INVERS|BLINK : INVERS) : 0); LcdFlags attr = (menuVerticalPosition == i ? (s_editMode > 0 ? INVERS | BLINK : INVERS) : 0);
switch (i) { switch (i) {
case SPECTRUM_FREQUENCY: { case SPECTRUM_FREQUENCY: {
@ -94,10 +119,10 @@ bool menuRadioSpectrumAnalyser(event_t event)
break; break;
} }
case SPECTRUM_SPAN: case SPECTRUM_SPAN: {
uint8_t span = reusableBuffer.spectrumAnalyser.span / 1000000; uint8_t span = reusableBuffer.spectrumAnalyser.span / 1000000;
lcdDrawText(MENUS_MARGIN_LEFT + 100, MENU_FOOTER_TOP, "S:", TEXT_INVERTED_COLOR); lcdDrawText(MENUS_MARGIN_LEFT + 100, MENU_FOOTER_TOP, "S:", TEXT_INVERTED_COLOR);
lcdDrawNumber(lcdNextPos + 2, MENU_FOOTER_TOP, reusableBuffer.spectrumAnalyser.span/1000000, attr | TEXT_INVERTED_COLOR); lcdDrawNumber(lcdNextPos + 2, MENU_FOOTER_TOP, reusableBuffer.spectrumAnalyser.span / 1000000, attr | TEXT_INVERTED_COLOR);
lcdDrawText(lcdNextPos + 2, MENU_FOOTER_TOP, "MHz", TEXT_INVERTED_COLOR); lcdDrawText(lcdNextPos + 2, MENU_FOOTER_TOP, "MHz", TEXT_INVERTED_COLOR);
if (attr) { if (attr) {
reusableBuffer.spectrumAnalyser.span = checkIncDec(event, span, 1, reusableBuffer.spectrumAnalyser.spanMax, 0) * 1000000; reusableBuffer.spectrumAnalyser.span = checkIncDec(event, span, 1, reusableBuffer.spectrumAnalyser.spanMax, 0) * 1000000;
@ -107,70 +132,72 @@ bool menuRadioSpectrumAnalyser(event_t event)
} }
} }
break; break;
}
case SPECTRUM_TRACK: {
uint16_t track = reusableBuffer.spectrumAnalyser.track / 1000000;
lcdDrawText(lcdNextPos + 10, MENU_FOOTER_TOP, "T:", TEXT_INVERTED_COLOR);
lcdDrawNumber(lcdNextPos + 2, MENU_FOOTER_TOP, reusableBuffer.spectrumAnalyser.track / 1000000, attr | TEXT_INVERTED_COLOR);
lcdDrawText(lcdNextPos + 2, MENU_FOOTER_TOP, "MHz", TEXT_INVERTED_COLOR);
if (attr) {
reusableBuffer.spectrumAnalyser.track = uint32_t(
checkIncDec(event, track, (reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2) / 1000000,
(reusableBuffer.spectrumAnalyser.freq + reusableBuffer.spectrumAnalyser.span / 2) / 1000000, 0)) * 1000000;
if (checkIncDec_Ret) {
reusableBuffer.spectrumAnalyser.dirty = true;
}
}
break;
}
} }
} }
// Draw fixed part (scale,..)
lcdDrawFilledRect(0, MENU_FOOTER_TOP - GREYBAR_HEIGHT, LCD_W, GREYBAR_HEIGHT, SOLID, CURVE_AXIS_COLOR);
for (uint32_t frequency = ((reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2) / 10000000) * 10000000 + 10000000; ; frequency += 10000000) { 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 offset = frequency - (reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2);
int x = offset / reusableBuffer.spectrumAnalyser.step; int x = offset / reusableBuffer.spectrumAnalyser.step;
if (x >= LCD_W - 1) if (x >= LCD_W - 1)
break; break;
lcdDrawVerticalLine(x, MENU_HEADER_HEIGHT, LCD_H - MENU_HEADER_HEIGHT - MENU_FOOTER_HEIGHT, STASHED, CURVE_AXIS_COLOR); lcdDrawVerticalLine(x, MENU_HEADER_HEIGHT, LCD_H - MENU_HEADER_HEIGHT - MENU_FOOTER_HEIGHT, STASHED, CURVE_AXIS_COLOR);
if ((frequency / 1000000) % 2 == 0) {
lcdDrawNumber(x, MENU_FOOTER_TOP - GREYBAR_HEIGHT - 1, frequency / 1000000, TINSIZE | TEXT_COLOR | CENTERED);
}
} }
for (uint8_t power = 20; ; power += 20) { for (uint8_t power = 20;; power += 20) {
int y = MENU_FOOTER_TOP - 1 - limit<int>(0, power << 1, LCD_H - MENU_HEADER_HEIGHT - MENU_FOOTER_HEIGHT); int y = MENU_FOOTER_TOP - 1 - limit<int>(0, power << 1, LCD_H - MENU_HEADER_HEIGHT - MENU_FOOTER_HEIGHT);
if (y <= MENU_HEADER_HEIGHT) if (y <= MENU_HEADER_HEIGHT)
break; break;
lcdDrawHorizontalLine(0, y, LCD_W, STASHED, CURVE_AXIS_COLOR); lcdDrawHorizontalLine(0, y, LCD_W, STASHED, CURVE_AXIS_COLOR);
} }
coord_t peak_y = LCD_H; // Draw Tracker
coord_t peak_x = 0; int offset = reusableBuffer.spectrumAnalyser.track - (reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2);
int x = offset / reusableBuffer.spectrumAnalyser.step;
lcdDrawVerticalLine(x, MENU_HEADER_HEIGHT, LCD_H - MENU_HEADER_HEIGHT - MENU_FOOTER_HEIGHT - GREYBAR_HEIGHT, SOLID, TEXT_COLOR);
coord_t prev_yv = (coord_t)-1; // Draw spectrum data
for (coord_t xv=0; xv<LCD_W; xv++) { constexpr uint8_t step = 4;
coord_t yv = MENU_FOOTER_TOP - 1 - limit<int>(0, reusableBuffer.spectrumAnalyser.bars[xv] << 1, LCD_H - MENU_HEADER_HEIGHT - MENU_FOOTER_HEIGHT);
if (prev_yv != (coord_t)-1) { for (coord_t xv = 0; xv <= LCD_W - step; xv += 4) {
if (yv < peak_y) { coord_t yv = MENU_FOOTER_TOP - 1 - limit<int>(0, getAverage(step, &reusableBuffer.spectrumAnalyser.bars[xv]) << 1, LCD_H - MENU_HEADER_HEIGHT - MENU_FOOTER_HEIGHT);
peak_x = xv; coord_t max_yv = MENU_FOOTER_TOP - 1 - limit<int>(0, getAverage(step, &reusableBuffer.spectrumAnalyser.max[xv]) << 1, LCD_H - MENU_HEADER_HEIGHT - MENU_FOOTER_HEIGHT);
peak_y = yv;
} // Signal bar
if (prev_yv < yv) { lcdDrawSolidFilledRect(xv, yv, step - 1, LCD_H - yv - MENU_FOOTER_HEIGHT - GREYBAR_HEIGHT, TEXT_INVERTED_BGCOLOR);
for (int y=prev_yv; y<=yv; y+=1) { lcdDrawRect(xv, yv, step - 1, LCD_H - yv - MENU_FOOTER_HEIGHT - GREYBAR_HEIGHT);
lcdDrawPoint(xv, y, TEXT_COLOR);
} // Signal max
} lcdDrawLine(xv, max_yv, xv + step, max_yv);
else {
for (int y=yv; y<=prev_yv; y+=1) { // Decay max values
lcdDrawPoint(xv, y, TEXT_COLOR); 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] -= 1;
} }
} }
prev_yv = yv;
} }
prev_yv = (coord_t)-1;
for (coord_t xv=0; xv<LCD_W; xv++) {
coord_t yv = MENU_FOOTER_TOP - 1 - limit<int>(0, reusableBuffer.spectrumAnalyser.max[xv] << 1, LCD_H - MENU_HEADER_HEIGHT - MENU_FOOTER_HEIGHT);
if (prev_yv != (coord_t)-1) {
if (prev_yv < yv) {
for (int y=prev_yv; y<=yv; y+=1) {
lcdDrawPoint(xv, y, TEXT_INVERTED_BGCOLOR);
}
}
else {
for (int y=yv; y<=prev_yv; y+=1) {
lcdDrawPoint(xv, y, TEXT_INVERTED_BGCOLOR);
}
}
}
prev_yv = yv;
}
coord_t y = max<coord_t>(MENU_HEADER_HEIGHT + 1, peak_y - FH);
lcdDrawNumber(limit<coord_t>(20, peak_x, LCD_W - 20), y, ((reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2) + peak_x * (reusableBuffer.spectrumAnalyser.span / LCD_W)) / 1000000, TINSIZE | CENTERED);
lcdDrawText(lcdNextPos, y, "M", TINSIZE);
return true; return true;
} }

View file

@ -85,17 +85,21 @@ bool menuRadioTools(event_t event)
uint8_t index = 0; uint8_t index = 0;
#if defined(PXX2) #if defined(INTERNAL_MODULE_PXX2)
if (isPXX2ModuleOptionAvailable(reusableBuffer.radioTools.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER)) if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER))
addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE); addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE);
if (isPXX2ModuleOptionAvailable(reusableBuffer.radioTools.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER)) if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER))
addRadioModuleTool(index++, STR_POWER_METER_INT, menuRadioPowerMeter, INTERNAL_MODULE); addRadioModuleTool(index++, STR_POWER_METER_INT, menuRadioPowerMeter, INTERNAL_MODULE);
#elif defined(INTERNAL_MODULE_MULTI)
if (isPXX2ModuleOptionAvailable(reusableBuffer.radioTools.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER)) addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE);
#endif
#if defined(PXX2)|| defined(MULTIMODULE)
if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER) || isModuleMultimodule(EXTERNAL_MODULE))
addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_EXT, menuRadioSpectrumAnalyser, EXTERNAL_MODULE); addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_EXT, menuRadioSpectrumAnalyser, EXTERNAL_MODULE);
#endif
if (isPXX2ModuleOptionAvailable(reusableBuffer.radioTools.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER)) #if defined(PXX2)
if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER))
addRadioModuleTool(index++, STR_POWER_METER_EXT, menuRadioPowerMeter, EXTERNAL_MODULE); addRadioModuleTool(index++, STR_POWER_METER_EXT, menuRadioPowerMeter, EXTERNAL_MODULE);
#endif #endif

View file

@ -18,7 +18,7 @@ set(GUI_SRC
model_curve_edit.cpp model_curve_edit.cpp
) )
if(PXX2 OR LUA) if(PXX2 OR LUA OR MULTIMODULE)
set(GUI_SRC ${GUI_SRC} ../common/stdlcd/radio_tools.cpp) set(GUI_SRC ${GUI_SRC} ../common/stdlcd/radio_tools.cpp)
endif() endif()
@ -36,8 +36,14 @@ endif()
if(PXX2) if(PXX2)
set(GUI_SRC set(GUI_SRC
${GUI_SRC} ${GUI_SRC}
../common/stdlcd/radio_spectrum_analyser.cpp
../common/stdlcd/radio_power_meter.cpp ../common/stdlcd/radio_power_meter.cpp
) )
endif() endif()
if(PXX2 OR MULTIMODULE)
set(GUI_SRC
${GUI_SRC}
../common/stdlcd/radio_spectrum_analyser.cpp
)
endif()

View file

@ -25,12 +25,19 @@ extern uint8_t g_moduleIdx;
enum SpectrumFields { enum SpectrumFields {
SPECTRUM_FREQUENCY, SPECTRUM_FREQUENCY,
SPECTRUM_SPAN, SPECTRUM_SPAN,
SPECTRUM_TRACK,
SPECTRUM_FIELDS_MAX SPECTRUM_FIELDS_MAX
}; };
#define SPECTRUM_ROW (isModuleMultimodule(g_moduleIdx) ? READONLY_ROW : (uint8_t)0)
void menuRadioSpectrumAnalyser(event_t event) void menuRadioSpectrumAnalyser(event_t event)
{ {
SUBMENU(STR_MENU_SPECTRUM_ANALYSER, 1, {1}); SUBMENU(STR_MENU_SPECTRUM_ANALYSER, SPECTRUM_FIELDS_MAX, {
SPECTRUM_ROW, //Freq
SPECTRUM_ROW, //Span
0 //Tracker
});
if (menuEvent) { if (menuEvent) {
lcdDrawCenteredText(LCD_H/2, STR_STOPPING); lcdDrawCenteredText(LCD_H/2, STR_STOPPING);
@ -62,7 +69,10 @@ void menuRadioSpectrumAnalyser(event_t event)
reusableBuffer.spectrumAnalyser.freqMax = 930; reusableBuffer.spectrumAnalyser.freqMax = 930;
} }
else { 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.spanMax = 80;
reusableBuffer.spectrumAnalyser.freqDefault = 2440; // 2440MHz reusableBuffer.spectrumAnalyser.freqDefault = 2440; // 2440MHz
reusableBuffer.spectrumAnalyser.freqMin = 2400; reusableBuffer.spectrumAnalyser.freqMin = 2400;
@ -71,20 +81,22 @@ void menuRadioSpectrumAnalyser(event_t event)
reusableBuffer.spectrumAnalyser.span = reusableBuffer.spectrumAnalyser.spanDefault * 1000000; reusableBuffer.spectrumAnalyser.span = reusableBuffer.spectrumAnalyser.spanDefault * 1000000;
reusableBuffer.spectrumAnalyser.freq = reusableBuffer.spectrumAnalyser.freqDefault * 1000000; reusableBuffer.spectrumAnalyser.freq = reusableBuffer.spectrumAnalyser.freqDefault * 1000000;
reusableBuffer.spectrumAnalyser.track = reusableBuffer.spectrumAnalyser.freq;
reusableBuffer.spectrumAnalyser.step = reusableBuffer.spectrumAnalyser.span / LCD_W; reusableBuffer.spectrumAnalyser.step = reusableBuffer.spectrumAnalyser.span / LCD_W;
reusableBuffer.spectrumAnalyser.dirty = true; reusableBuffer.spectrumAnalyser.dirty = true;
moduleState[g_moduleIdx].mode = MODULE_MODE_SPECTRUM_ANALYSER; moduleState[g_moduleIdx].mode = MODULE_MODE_SPECTRUM_ANALYSER;
} }
for (uint8_t i=0; i<SPECTRUM_FIELDS_MAX; i++) { for (uint8_t i=0; i<SPECTRUM_FIELDS_MAX; i++) {
LcdFlags attr = (menuHorizontalPosition == i ? (s_editMode>0 ? INVERS|BLINK : INVERS) : 0); uint8_t sub = menuVerticalPosition;
LcdFlags attr = (sub==i ? (s_editMode>0 ? BLINK|INVERS : INVERS) : 0);
switch (i) { switch (i) {
case SPECTRUM_FREQUENCY: { case SPECTRUM_FREQUENCY: {
uint16_t frequency = reusableBuffer.spectrumAnalyser.freq / 1000000; uint16_t frequency = reusableBuffer.spectrumAnalyser.freq / 1000000;
lcdDrawText(1, 10, "F:", 0); lcdDrawText(1, 10, "F:", SMLSIZE);
lcdDrawNumber(lcdLastRightPos + 2, 10, frequency, attr); lcdDrawNumber(lcdLastRightPos + 1, 10, frequency, attr|SMLSIZE);
lcdDrawText(lcdLastRightPos + 2, 10, "MHz", 0); lcdDrawText(lcdLastRightPos + 1, 10, "MHz", SMLSIZE);
if (attr) { if (attr) {
reusableBuffer.spectrumAnalyser.freq = uint32_t(checkIncDec(event, frequency, reusableBuffer.spectrumAnalyser.freqMin, reusableBuffer.spectrumAnalyser.freqMax, 0)) * 1000000; reusableBuffer.spectrumAnalyser.freq = uint32_t(checkIncDec(event, frequency, reusableBuffer.spectrumAnalyser.freqMin, reusableBuffer.spectrumAnalyser.freqMax, 0)) * 1000000;
if (checkIncDec_Ret) { if (checkIncDec_Ret) {
@ -94,11 +106,11 @@ void menuRadioSpectrumAnalyser(event_t event)
break; break;
} }
case SPECTRUM_SPAN: case SPECTRUM_SPAN: {
uint8_t span = reusableBuffer.spectrumAnalyser.span / 1000000; uint8_t span = reusableBuffer.spectrumAnalyser.span / 1000000;
lcdDrawText(lcdLastRightPos + 5, 10, "S:", 0); lcdDrawText(lcdLastRightPos + 2, 10, "S:", SMLSIZE);
lcdDrawNumber(lcdLastRightPos + 2, 10, reusableBuffer.spectrumAnalyser.span/1000000, attr); lcdDrawNumber(lcdLastRightPos + 1, 10, reusableBuffer.spectrumAnalyser.span / 1000000, attr | SMLSIZE);
lcdDrawText(lcdLastRightPos + 2, 10, "MHz", 0); lcdDrawText(lcdLastRightPos + 1, 10, "MHz", SMLSIZE);
if (attr) { if (attr) {
reusableBuffer.spectrumAnalyser.span = checkIncDec(event, span, 1, reusableBuffer.spectrumAnalyser.spanMax, 0) * 1000000; reusableBuffer.spectrumAnalyser.span = checkIncDec(event, span, 1, reusableBuffer.spectrumAnalyser.spanMax, 0) * 1000000;
if (checkIncDec_Ret) { if (checkIncDec_Ret) {
@ -107,21 +119,42 @@ void menuRadioSpectrumAnalyser(event_t event)
} }
} }
break; break;
}
case SPECTRUM_TRACK: {
uint16_t track = reusableBuffer.spectrumAnalyser.track / 1000000;
lcdDrawText(lcdNextPos + 2, 10, "T:", SMLSIZE);
lcdDrawNumber(lcdNextPos + 1, 10, reusableBuffer.spectrumAnalyser.track / 1000000, attr | SMLSIZE);
lcdDrawText(lcdNextPos + 1, 10, "MHz", SMLSIZE);
if (attr) {
reusableBuffer.spectrumAnalyser.track = uint32_t(
checkIncDec(event, track, (reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2) / 1000000,
(reusableBuffer.spectrumAnalyser.freq + reusableBuffer.spectrumAnalyser.span / 2) / 1000000, 0)) * 1000000;
if (checkIncDec_Ret) {
reusableBuffer.spectrumAnalyser.dirty = true;
}
}
break;
}
} }
} }
uint8_t peak_y = 1; // Signal bar
uint8_t peak_x = 0;
for (uint8_t i=0; i<LCD_W; i++) { for (uint8_t i=0; i<LCD_W; i++) {
uint8_t h = min<uint8_t >(reusableBuffer.spectrumAnalyser.bars[i] >> 1, LCD_H); uint8_t h = min<uint8_t >(reusableBuffer.spectrumAnalyser.bars[i] >> 1, LCD_H);
if (h > peak_y) {
peak_x = i;
peak_y = h;
}
lcdDrawSolidVerticalLine(i, LCD_H - h, h); lcdDrawSolidVerticalLine(i, LCD_H - h, h);
} }
int8_t y = max<int8_t>(FH, LCD_H - peak_y - FH); // Signal max
lcdDrawNumber(min<uint8_t>(100, peak_x), y, ((reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2) + peak_x * (reusableBuffer.spectrumAnalyser.span / LCD_W)) / 1000000, TINSIZE); for (uint8_t i=0; i<LCD_W; i++) {
lcdDrawText(lcdLastRightPos, y, "M", TINSIZE); uint8_t h = min<uint8_t >(reusableBuffer.spectrumAnalyser.max[i] >> 1, LCD_H);
} lcdDrawPoint(i, LCD_H - h);
if (reusableBuffer.spectrumAnalyser.max[i] > 1)
reusableBuffer.spectrumAnalyser.max[i] -= 1;
}
// Draw Tracker
int offset = reusableBuffer.spectrumAnalyser.track - (reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2);
int x = offset / reusableBuffer.spectrumAnalyser.step;
lcdDrawVerticalLine(x, 10+FH+1, LCD_H, SOLID);
}

View file

@ -82,17 +82,21 @@ void menuRadioTools(event_t event)
uint8_t index = 0; uint8_t index = 0;
#if defined(PXX2) #if defined(INTERNAL_MODULE_PXX2)
if (isPXX2ModuleOptionAvailable(reusableBuffer.radioTools.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER)) if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER))
addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE); addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE);
if (isPXX2ModuleOptionAvailable(reusableBuffer.radioTools.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER)) if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER))
addRadioModuleTool(index++, STR_POWER_METER_INT, menuRadioPowerMeter, INTERNAL_MODULE); addRadioModuleTool(index++, STR_POWER_METER_INT, menuRadioPowerMeter, INTERNAL_MODULE);
#elif defined(INTERNAL_MODULE_MULTI)
if (isPXX2ModuleOptionAvailable(reusableBuffer.radioTools.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER)) addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE);
#endif
#if defined(PXX2)|| defined(MULTIMODULE)
if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER) || isModuleMultimodule(EXTERNAL_MODULE))
addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_EXT, menuRadioSpectrumAnalyser, EXTERNAL_MODULE); addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_EXT, menuRadioSpectrumAnalyser, EXTERNAL_MODULE);
#endif
if (isPXX2ModuleOptionAvailable(reusableBuffer.radioTools.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER)) #if defined(PXX2)
if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER))
addRadioModuleTool(index++, STR_POWER_METER_EXT, menuRadioPowerMeter, EXTERNAL_MODULE); addRadioModuleTool(index++, STR_POWER_METER_EXT, menuRadioPowerMeter, EXTERNAL_MODULE);
#endif #endif

View file

@ -373,7 +373,7 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t
break; break;
case EVT_KEY_BREAK(KEY_ENTER): case EVT_KEY_BREAK(KEY_ENTER):
if (s_editMode > 1) if (s_editMode > 1)
break; break;
if (menuHorizontalPosition < 0 && maxcol > 0 && READ_ONLY_UNLOCKED()) { if (menuHorizontalPosition < 0 && maxcol > 0 && READ_ONLY_UNLOCKED()) {
l_posHorz = 0; l_posHorz = 0;
@ -545,4 +545,3 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t
menuHorizontalPosition = l_posHorz; menuHorizontalPosition = l_posHorz;
} }

View file

@ -1187,12 +1187,11 @@ union ReusableBuffer
struct { struct {
uint8_t bars[LCD_W]; uint8_t bars[LCD_W];
#if defined(COLORLCD)
uint8_t max[LCD_W]; uint8_t max[LCD_W];
#endif
uint32_t freq; uint32_t freq;
uint32_t span; uint32_t span;
uint32_t step; uint32_t step;
uint32_t track;
uint8_t spanDefault; uint8_t spanDefault;
uint8_t spanMax; uint8_t spanMax;
uint16_t freqDefault; uint16_t freqDefault;

View file

@ -37,7 +37,7 @@ void sendChannels(uint8_t moduleIdx);
static void sendMulti(uint8_t moduleIdx, uint8_t b) static void sendMulti(uint8_t moduleIdx, uint8_t b)
{ {
#if defined(INTERNAL_MODULE_MULTI) #if defined(HARDWARE_INTERNAL_MODULE)
if (moduleIdx == INTERNAL_MODULE) { if (moduleIdx == INTERNAL_MODULE) {
intmodulePulsesData.multi.sendByte(b); intmodulePulsesData.multi.sendByte(b);
} }
@ -171,6 +171,15 @@ void sendFrameProtocolHeader(uint8_t moduleIdx, bool failsafe)
int8_t optionValue = g_model.moduleData[moduleIdx].multi.optionValue; int8_t optionValue = g_model.moduleData[moduleIdx].multi.optionValue;
uint8_t protoByte = 0; uint8_t protoByte = 0;
if (moduleState[moduleIdx].mode == MODULE_MODE_SPECTRUM_ANALYSER) {
sendMulti(moduleIdx, (uint8_t) 0x54); // Header byte
sendMulti(moduleIdx, (uint8_t) 54); // Spectrum custom protocol
sendMulti(moduleIdx, (uint8_t) 0);
sendMulti(moduleIdx, (uint8_t) 0);
return;
}
if (moduleState[moduleIdx].mode == MODULE_MODE_BIND) if (moduleState[moduleIdx].mode == MODULE_MODE_BIND)
protoByte |= MULTI_SEND_BIND; protoByte |= MULTI_SEND_BIND;
else if (moduleState[moduleIdx].mode == MODULE_MODE_RANGECHECK) else if (moduleState[moduleIdx].mode == MODULE_MODE_RANGECHECK)

View file

@ -287,7 +287,7 @@ void setupPulsesExternalModule(uint8_t protocol)
} }
#if defined(HARDWARE_INTERNAL_MODULE) #if defined(HARDWARE_INTERNAL_MODULE)
void enablePulsesInternalModule(uint8_t protocol) static void enablePulsesInternalModule(uint8_t protocol)
{ {
// start new protocol hardware here // start new protocol hardware here

View file

@ -41,6 +41,12 @@
#define IS_DSM2_PROTOCOL(protocol) (0) #define IS_DSM2_PROTOCOL(protocol) (0)
#endif #endif
#if defined(DSM2_SERIAL)
#define IS_DSM2_SERIAL_PROTOCOL(protocol) (IS_DSM2_PROTOCOL(protocol))
#else
#define IS_DSM2_SERIAL_PROTOCOL(protocol) (0)
#endif
#if defined(MULTIMODULE) #if defined(MULTIMODULE)
#define IS_MULTIMODULE_PROTOCOL(protocol) (protocol==PROTOCOL_CHANNELS_MULTIMODULE) #define IS_MULTIMODULE_PROTOCOL(protocol) (protocol==PROTOCOL_CHANNELS_MULTIMODULE)
#if !defined(DSM2) #if !defined(DSM2)
@ -147,7 +153,8 @@ PACK(struct ModuleState {
uint8_t paused:1; uint8_t paused:1;
uint8_t spare:7; uint8_t spare:7;
uint16_t counter; uint16_t counter;
union { union
{
ModuleInformation * moduleInformation; ModuleInformation * moduleInformation;
ModuleSettings * moduleSettings; ModuleSettings * moduleSettings;
ReceiverSettings * receiverSettings; ReceiverSettings * receiverSettings;
@ -165,12 +172,14 @@ PACK(struct ModuleState {
moduleInformation->maximum = last; moduleInformation->maximum = last;
mode = MODULE_MODE_GET_HARDWARE_INFO; mode = MODULE_MODE_GET_HARDWARE_INFO;
} }
void readModuleSettings(ModuleSettings * destination) void readModuleSettings(ModuleSettings * destination)
{ {
moduleSettings = destination; moduleSettings = destination;
moduleSettings->state = PXX2_SETTINGS_READ; moduleSettings->state = PXX2_SETTINGS_READ;
mode = MODULE_MODE_MODULE_SETTINGS; mode = MODULE_MODE_MODULE_SETTINGS;
} }
void writeModuleSettings(ModuleSettings * source) void writeModuleSettings(ModuleSettings * source)
{ {
moduleSettings = source; moduleSettings = source;
@ -178,12 +187,14 @@ PACK(struct ModuleState {
moduleSettings->timeout = 0; moduleSettings->timeout = 0;
mode = MODULE_MODE_MODULE_SETTINGS; mode = MODULE_MODE_MODULE_SETTINGS;
} }
void readReceiverSettings(ReceiverSettings * destination) void readReceiverSettings(ReceiverSettings * destination)
{ {
receiverSettings = destination; receiverSettings = destination;
receiverSettings->state = PXX2_SETTINGS_READ; receiverSettings->state = PXX2_SETTINGS_READ;
mode = MODULE_MODE_RECEIVER_SETTINGS; mode = MODULE_MODE_RECEIVER_SETTINGS;
} }
void writeReceiverSettings(ReceiverSettings * source) void writeReceiverSettings(ReceiverSettings * source)
{ {
receiverSettings = source; receiverSettings = source;
@ -238,21 +249,21 @@ PACK(struct CrossfirePulsesData {
union InternalModulePulsesData { union InternalModulePulsesData {
#if defined(PXX1) #if defined(PXX1)
#if defined(INTMODULE_USART) #if defined(INTMODULE_USART)
UartPxx1Pulses pxx_uart; UartPxx1Pulses pxx_uart;
#else #else
PwmPxx1Pulses pxx; PwmPxx1Pulses pxx;
#endif #endif
#endif #endif
#if defined(PXX2) #if defined(PXX2)
Pxx2Pulses pxx2; Pxx2Pulses pxx2;
#endif #endif
#if defined(INTERNAL_MODULE_MULTI) //&& defined(INTMODULE_USART) #if defined(MULTIMODULE) //&& defined(INTMODULE_USART)
UartMultiPulses multi; UartMultiPulses multi;
#endif #endif
#if defined(INTERNAL_MODULE_PPM) #if defined(INTERNAL_MODULE_PPM)
PpmPulsesData<pulse_duration_t> ppm; PpmPulsesData<pulse_duration_t> ppm;
#endif #endif
@ -260,14 +271,14 @@ union InternalModulePulsesData {
union ExternalModulePulsesData { union ExternalModulePulsesData {
#if defined(PXX1) #if defined(PXX1)
#if defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML) #if defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML)
UartPxx1Pulses pxx_uart; UartPxx1Pulses pxx_uart;
#endif #endif
#if defined(PPM_PIN_SERIAL) #if defined(PPM_PIN_SERIAL)
SerialPxx1Pulses pxx; SerialPxx1Pulses pxx;
#else #else
PwmPxx1Pulses pxx; PwmPxx1Pulses pxx;
#endif #endif
#endif #endif
#if defined(PXX2) #if defined(PXX2)
@ -417,4 +428,4 @@ inline bool isModuleInBeepMode()
return false; return false;
} }
#endif // _PULSES_H_ #endif // _PULSES_H_

View file

@ -2,6 +2,7 @@ option(DISK_CACHE "Enable SD card disk cache" ON)
option(UNEXPECTED_SHUTDOWN "Enable the Unexpected Shutdown screen" ON) option(UNEXPECTED_SHUTDOWN "Enable the Unexpected Shutdown screen" ON)
option(PXX1 "PXX1 protocol support" ON) option(PXX1 "PXX1 protocol support" ON)
option(PXX2 "PXX2 protocol support" OFF) option(PXX2 "PXX2 protocol support" OFF)
option(MULTIMODULE "DIY Multiprotocol TX Module (https://github.com/pascallanger/DIY-Multiprotocol-TX-Module)" ON)
set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)") set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)")
set(CPU_TYPE STM32F4) set(CPU_TYPE STM32F4)
@ -146,16 +147,16 @@ set(GUI_SRC
rle.cpp rle.cpp
) )
if(PXX2 OR LUA) if(PXX2 OR LUA OR MULTIMODULE)
set(GUI_SRC ${GUI_SRC} radio_tools.cpp) set(GUI_SRC ${GUI_SRC} radio_tools.cpp)
endif() endif()
if(PXX2 OR MULTIMODULE)
set(GUI_SRC ${GUI_SRC} radio_spectrum_analyser.cpp)
endif()
if(PXX2) if(PXX2)
set(GUI_SRC set(GUI_SRC ${GUI_SRC} radio_power_meter.cpp)
${GUI_SRC}
radio_spectrum_analyser.cpp
radio_power_meter.cpp
)
endif() endif()
if(DISK_CACHE) if(DISK_CACHE)

View file

@ -49,7 +49,7 @@ void watchdogInit(unsigned int duration)
extern "C" void initialise_monitor_handles(); extern "C" void initialise_monitor_handles();
#endif #endif
#if defined(PCBX10) #if defined(PCBX10) && !defined(RADIO_T16)
void sportUpdateInit() void sportUpdateInit()
{ {
GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitTypeDef GPIO_InitStructure;
@ -171,7 +171,7 @@ void boardInit()
DBGMCU_APB1PeriphConfig(DBGMCU_IWDG_STOP|DBGMCU_TIM1_STOP|DBGMCU_TIM2_STOP|DBGMCU_TIM3_STOP|DBGMCU_TIM4_STOP|DBGMCU_TIM5_STOP|DBGMCU_TIM6_STOP|DBGMCU_TIM7_STOP|DBGMCU_TIM8_STOP|DBGMCU_TIM9_STOP|DBGMCU_TIM10_STOP|DBGMCU_TIM11_STOP|DBGMCU_TIM12_STOP|DBGMCU_TIM13_STOP|DBGMCU_TIM14_STOP, ENABLE); DBGMCU_APB1PeriphConfig(DBGMCU_IWDG_STOP|DBGMCU_TIM1_STOP|DBGMCU_TIM2_STOP|DBGMCU_TIM3_STOP|DBGMCU_TIM4_STOP|DBGMCU_TIM5_STOP|DBGMCU_TIM6_STOP|DBGMCU_TIM7_STOP|DBGMCU_TIM8_STOP|DBGMCU_TIM9_STOP|DBGMCU_TIM10_STOP|DBGMCU_TIM11_STOP|DBGMCU_TIM12_STOP|DBGMCU_TIM13_STOP|DBGMCU_TIM14_STOP, ENABLE);
#endif #endif
#if defined(PCBX10) #if defined(PCBX10) && !defined(RADIO_T16)
ledInit(); ledInit();
sportUpdateInit(); sportUpdateInit();
#endif #endif

View file

@ -569,7 +569,7 @@ void telemetryClearFifo();
extern uint32_t telemetryErrors; extern uint32_t telemetryErrors;
// Sport update driver // Sport update driver
#if defined(PCBX10) #if defined(PCBX10) && !defined(RADIO_T16)
void sportUpdatePowerOn(); void sportUpdatePowerOn();
void sportUpdatePowerOff(); void sportUpdatePowerOff();
#define SPORT_UPDATE_POWER_ON() sportUpdatePowerOn() #define SPORT_UPDATE_POWER_ON() sportUpdatePowerOn()

View file

@ -21,10 +21,12 @@
#include "telemetry.h" #include "telemetry.h"
#include "multi.h" #include "multi.h"
extern uint8_t g_moduleIdx;
enum MultiPacketTypes : uint8_t enum MultiPacketTypes : uint8_t
{ {
MultiStatus = 1, MultiStatus = 1,
FrSkySportTelemtry, FrSkySmoduleIdxTelemtry,
FrSkyHubTelemetry, FrSkyHubTelemetry,
SpektrumTelemetry, SpektrumTelemetry,
DSMBindPacket, DSMBindPacket,
@ -138,7 +140,14 @@ void setMultiTelemetryBufferState(uint8_t, MultiBufferState state)
static MultiBufferState guessProtocol(uint8_t module) static MultiBufferState guessProtocol(uint8_t module)
{ {
if (g_model.moduleData[module].getMultiProtocol(false) == MODULE_SUBTYPE_MULTI_DSM2) uint32_t moduleIdx = EXTERNAL_MODULE;
#if defined(INTERNAL_MODULE_MULTI)
if (isModuleMultimodule(INTERNAL_MODULE)) {
moduleIdx = INTERNAL_MODULE;
}
#endif
if (g_model.moduleData[moduleIdx].getMultiProtocol(false) == MODULE_SUBTYPE_MULTI_DSM2)
return SpektrumTelemetryFallback; return SpektrumTelemetryFallback;
else if (g_model.moduleData[module].getMultiProtocol(false) == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) else if (g_model.moduleData[module].getMultiProtocol(false) == MODULE_SUBTYPE_MULTI_FS_AFHDS2A)
return FlyskyTelemetryFallback; return FlyskyTelemetryFallback;
@ -146,6 +155,44 @@ static MultiBufferState guessProtocol(uint8_t module)
return FrskyTelemetryFallback; return FrskyTelemetryFallback;
} }
static void processMultiScannerPacket(const uint8_t *data)
{
uint8_t cur_channel = data[0];
if (moduleState[g_moduleIdx].mode == MODULE_MODE_SPECTRUM_ANALYSER) {
for (uint8_t channel = 0; channel <5; channel++) {
uint8_t power = max<int>(0,(data[channel+1] - 34) >> 1); // remove everything below -120dB
#if LCD_W == 480
coord_t x = cur_channel*2;
if (x < LCD_W) {
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;
}
#elif LCD_W == 212
coord_t x = cur_channel;
if (x <= LCD_W) {
reusableBuffer.spectrumAnalyser.bars[x] = power;
if (power > reusableBuffer.spectrumAnalyser.max[x]) {
reusableBuffer.spectrumAnalyser.max[x] = power;
}
#else
coord_t x = cur_channel/2 + 1;
if (x <= LCD_W) {
reusableBuffer.spectrumAnalyser.bars[x] = power;
if (power > reusableBuffer.spectrumAnalyser.max[x]) {
reusableBuffer.spectrumAnalyser.max[x] = power;
}
#endif
}
if (++cur_channel > MULTI_SCANNER_MAX_CHANNEL)
cur_channel = 0;
}
}
}
static void processMultiStatusPacket(const uint8_t * data, uint8_t module) static void processMultiStatusPacket(const uint8_t * data, uint8_t module)
{ {
MultiModuleStatus &status = getMultiModuleStatus(module); MultiModuleStatus &status = getMultiModuleStatus(module);
@ -248,11 +295,11 @@ static void processMultiTelemetryPaket(const uint8_t * packet, uint8_t module)
TRACE("[MP] Received Frsky HUB telemetry len %d < 4", len); TRACE("[MP] Received Frsky HUB telemetry len %d < 4", len);
break; break;
case FrSkySportTelemtry: case FrSkySmoduleIdxTelemtry:
if (len >= 4) if (len >= 4)
sportProcessTelemetryPacket(data); sportProcessTelemetryPacket(data);
else else
TRACE("[MP] Received sport telemetry len %d < 4", len); TRACE("[MP] Received smoduleIdx telemetry len %d < 4", len);
break; break;
case InputSync: case InputSync:
@ -269,11 +316,17 @@ static void processMultiTelemetryPaket(const uint8_t * packet, uint8_t module)
#if defined(LUA) #if defined(LUA)
case FrskySportPolling: case FrskySportPolling:
if (len >= 1 && outputTelemetryBuffer.destination == TELEMETRY_ENDPOINT_SPORT && data[0] == outputTelemetryBuffer.sport.physicalId) { if (len >= 1 && outputTelemetryBuffer.destination == TELEMETRY_ENDPOINT_SPORT && data[0] == outputTelemetryBuffer.sport.physicalId) {
TRACE("MP Sending sport data out."); TRACE("MP Sending smoduleIdx data out.");
sportSendBuffer(outputTelemetryBuffer.data, outputTelemetryBuffer.size); sportSendBuffer(outputTelemetryBuffer.data, outputTelemetryBuffer.size);
} }
break; break;
#endif #endif
case SpectrumScannerPacket:
if (len == 6)
processMultiScannerPacket(data);
else
TRACE("[MP] Received spectrum scanner len %d != 6", len);
break;
default: default:
TRACE("[MP] Unkown multi packet type 0x%02X, len %d", type, len); TRACE("[MP] Unkown multi packet type 0x%02X, len %d", type, len);
@ -319,7 +372,7 @@ void MultiModuleSyncStatus::calcAdjustedRefreshRate(uint16_t newRefreshRate, uin
return; return;
} }
// Caluclate how many samples went into the reported input Lag (*10) // Caluclate how many samples went into the remoduleIdxed input Lag (*10)
int numsamples = interval * 10000 / targetRefreshRate; int numsamples = interval * 10000 / targetRefreshRate;
// Convert lagDifference to ps // Convert lagDifference to ps

View file

@ -80,10 +80,17 @@ Type 0x06 Flysky AFHDS2 telemetry data
data[0] = RSSI value data[0] = RSSI value
data[1-28] telemetry data data[1-28] telemetry data
Type 0x0B Spectrum Scanner telemetry data
length: 6
data[0] = start channel (2400 + x*0.333 Mhz)
data[1-5] power levels
*/ */
void processMultiTelemetryData(uint8_t data, uint8_t module); void processMultiTelemetryData(uint8_t data, uint8_t module);
#define MULTI_SCANNER_MAX_CHANNEL 249
// This should be put into the Module definition if other modules gain this functionality // This should be put into the Module definition if other modules gain this functionality
struct MultiModuleSyncStatus { struct MultiModuleSyncStatus {
uint32_t adjustedRefreshRate; // in ps uint32_t adjustedRefreshRate; // in ps