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:
parent
7094a744d6
commit
891c13e98d
16 changed files with 284 additions and 131 deletions
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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_
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue