diff --git a/src/pages/128x64x1/guiobj.h b/src/pages/128x64x1/guiobj.h
index e2e4bd468c..773f6ff5ad 100644
--- a/src/pages/128x64x1/guiobj.h
+++ b/src/pages/128x64x1/guiobj.h
@@ -120,6 +120,12 @@ struct reorder_obj {
guiScrollable_t scrollable;
};
+struct scanner_obj {
+ guiButton_t enable;
+ guiButton_t scan_mode;
+ guiButton_t attenuator;
+};
+
struct telemcfg_obj {
guiLabel_t msg;
guiLabel_t idx[7];
@@ -367,6 +373,9 @@ struct _gui_objs {
struct modelload_obj modelload;
struct modelpage_obj modelpage;
struct reorder_obj reorder;
+#if HAS_SCANNER
+ struct scanner_obj scanner;
+#endif
struct telemcfg_obj telemcfg;
struct telemtest_obj telemtest1;
struct timer_obj timer;
diff --git a/src/pages/128x64x1/pagelist.h b/src/pages/128x64x1/pagelist.h
index c0a523be74..3770c875fa 100644
--- a/src/pages/128x64x1/pagelist.h
+++ b/src/pages/128x64x1/pagelist.h
@@ -75,6 +75,9 @@ PAGEDEF(PAGEID_CHANMON, PAGE_ChantestInit, PAGE_ChantestEvent, PAGE_Chant
PAGEDEF(PAGEID_TELEMMON, PAGE_TelemtestInit, PAGE_TelemtestEvent, NULL, TX_MENU, _tr_noop("Telemetry monitor"))
#endif
PAGEDEF(PAGEID_RANGE, PAGE_RangeInit, NULL, PAGE_RangeExit, TX_MENU, _tr_noop("Range Test"))
+#if HAS_SCANNER
+PAGEDEF(PAGEID_SCANNER, PAGE_ScannerInit, PAGE_ScannerEvent, PAGE_ScannerExit, TX_MENU, _tr_noop("Scanner"))
+#endif
//-------------------
// Pages menu
diff --git a/src/pages/128x64x1/pages.h b/src/pages/128x64x1/pages.h
index 5d379c1614..2ccc9c0dd3 100644
--- a/src/pages/128x64x1/pages.h
+++ b/src/pages/128x64x1/pages.h
@@ -14,7 +14,9 @@ struct pagemem {
struct timer_page timer_page;
struct chantest_page chantest_page;
struct range_page range_page;
- //struct scanner_page scanner_page;
+#if HAS_SCANNER
+ struct scanner_page scanner_page;
+#endif
#if HAS_MUSIC_CONFIG
struct voiceconfig_page voiceconfig_page;
#endif
diff --git a/src/pages/128x64x1/scanner_page.c b/src/pages/128x64x1/scanner_page.c
new file mode 100644
index 0000000000..fb800295f6
--- /dev/null
+++ b/src/pages/128x64x1/scanner_page.c
@@ -0,0 +1,66 @@
+/*
+ This project is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Deviation is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Deviation. If not, see .
+ */
+
+#include "common.h"
+#include "protocol/interface.h"
+#include "pages.h"
+#include "config/model.h"
+
+#if HAS_SCANNER
+#include "../common/_scanner_page.c"
+
+static struct scanner_obj * const gui = &gui_objs.u.scanner;
+static const char *enablestr_cb(guiObject_t *obj, const void *data)
+{
+ (void)obj;
+ (void)data;
+ return sp->enable ? _tr("On") : _tr("Off");
+}
+
+static const char *modestr_cb(guiObject_t *obj, const void *data)
+{
+ (void)obj;
+ (void)data;
+ return sp->scan_mode ? _tr("Average") : _tr("Peak");
+}
+
+static const char *attstr_cb(guiObject_t *obj, const void *data)
+{
+ (void)obj;
+ (void)data;
+ return sp->attenuator ? _tr("-20dB") : _tr("0dB");
+}
+
+void _draw_page(u8 enable)
+{
+ (void)enable;
+ PAGE_ShowHeader(PAGE_GetName(PAGEID_SCANNER));
+ GUI_CreateButtonPlateText(&gui->enable, 0, HEADER_HEIGHT, 40, LINE_HEIGHT, &BUTTON_FONT, enablestr_cb, press_enable_cb, NULL);
+ GUI_CreateButtonPlateText(&gui->scan_mode, LCD_WIDTH/2 - 20, HEADER_HEIGHT, 40, LINE_HEIGHT, &BUTTON_FONT, modestr_cb, press_mode_cb, NULL);
+ GUI_CreateButtonPlateText(&gui->attenuator, LCD_WIDTH - 40, HEADER_HEIGHT, 40, LINE_HEIGHT, &BUTTON_FONT, attstr_cb, press_attenuator_cb, NULL);
+}
+
+void _draw_channels()
+{
+ const unsigned offset = HEADER_HEIGHT + LINE_HEIGHT;
+ // draw a line
+ int col = (LCD_WIDTH - (MAX_RADIOCHANNEL - MIN_RADIOCHANNEL)) / 2 + sp->channel;
+ int height = sp->channelnoise[sp->channel] * (LCD_HEIGHT - offset) / 0x1F;
+
+ LCD_DrawFastVLine(col, offset, LCD_HEIGHT - height, 0);
+ LCD_DrawFastVLine(col, LCD_HEIGHT - height, LCD_HEIGHT, Display.xygraph.grid_color);
+}
+
+#endif //HAS_SCANNER
diff --git a/src/pages/320x240x16/pages.h b/src/pages/320x240x16/pages.h
index 488897ffbc..e1bf70b6ac 100644
--- a/src/pages/320x240x16/pages.h
+++ b/src/pages/320x240x16/pages.h
@@ -2,7 +2,6 @@
#define _PAGES_H_
#include "../common/_pages.h"
-#include "scanner_page.h"
#include "icons.h"
#include "guiobj.h"
diff --git a/src/pages/320x240x16/scanner_page.c b/src/pages/320x240x16/scanner_page.c
index 71a66f2e22..d4763c3726 100644
--- a/src/pages/320x240x16/scanner_page.c
+++ b/src/pages/320x240x16/scanner_page.c
@@ -18,51 +18,10 @@
#include "pages.h"
#include "config/model.h"
+
#if HAS_SCANNER
-static struct scanner_page * const sp = &pagemem.u.scanner_page;
+#include "../common/_scanner_page.c"
static struct scanner_obj * const gui = &gui_objs.u.scanner;
-static u8 scanState = 0;
-
-u16 scan_cb()
-{
- int delay;
-
- if(scanState == 0) {
- if(sp->time_to_scan == 0) {
- CYRF_ConfigRFChannel(sp->channel + MIN_RADIOCHANNEL);
- if(sp->attenuator) {
- CYRF_WriteRegister(CYRF_06_RX_CFG, 0x0A);
- } else {
- CYRF_WriteRegister(CYRF_06_RX_CFG, 0x4A);
- }
- sp->time_to_scan = 1;
- }
- scanState = 1;
- delay = 300; //slow channel require 270usec for synthesizer to settle
- } else {
- if ( !(CYRF_ReadRegister(CYRF_05_RX_CTRL) & 0x80)) {
- CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x80); //Prepare to receive
- Delay(10);
- CYRF_ReadRegister(CYRF_13_RSSI); //dummy read
- Delay(15);
- }
- int rssi = CYRF_ReadRegister(CYRF_13_RSSI) & 0x1F;
- if(sp->scan_mode) {
- sp->channelnoise[sp->channel] = (sp->channelnoise[sp->channel] + rssi) / 2;
- } else {
- if(rssi > sp->channelnoise[sp->channel])
- sp->channelnoise[sp->channel] = rssi;
- }
- scanState++;
- delay = 300;
- if(scanState == 5) {
- scanState = 0;
- delay = 50;
- }
- }
- return delay;
-}
-
static s32 show_bar_cb(void *data)
{
long ch = (long)data;
@@ -90,44 +49,7 @@ static const char *attstr_cb(guiObject_t *obj, const void *data)
return sp->attenuator ? _tr("Att.: -20dB") : _tr("Att.: 0dB");
}
-static void press_enable_cb(guiObject_t *obj, const void *data)
-{
- (void)data;
-#ifndef ENABLE_MODULAR
- sp->enable ^= 1;
- if (sp->enable) {
- PROTOCOL_DeInit();
- DEVO_Cmds(0); //Switch to DEVO configuration
- PROTOCOL_SetBindState(0); //Disable binding message
- CLOCK_StopTimer();
- CYRF_SetTxRxMode(RX_EN); //Receive mode
- CLOCK_StartTimer(1250, scan_cb);
- } else {
- PROTOCOL_Init(0);
- }
-#endif
- GUI_Redraw(obj);
-}
-
-static void press_mode_cb(guiObject_t *obj, const void *data)
-{
- (void)data;
-#ifndef ENABLE_MODULAR
- sp->scan_mode ^= 1;
-#endif
- GUI_Redraw(obj);
-}
-
-static void press_attenuator_cb(guiObject_t *obj, const void *data)
-{
- (void)data;
-#ifndef ENABLE_MODULAR
- sp->attenuator ^= 1;
-#endif
- GUI_Redraw(obj);
-}
-
-void PAGE_ScannerInit(int page)
+void _draw_page(u8 enable)
{
enum {
SCANBARWIDTH = (LCD_WIDTH / (MAX_RADIOCHANNEL - MIN_RADIOCHANNEL + 1)),
@@ -135,44 +57,19 @@ void PAGE_ScannerInit(int page)
SCANBARHEIGHT = (LCD_HEIGHT - 78),
};
u8 i;
- (void)page;
- PAGE_SetModal(0);
+ (void)enable;
PAGE_ShowHeader(PAGE_GetName(PAGEID_SCANNER));
- sp->enable = 0;
GUI_CreateButton(&gui->enable, LCD_WIDTH/2 - 152, 40, BUTTON_96, enablestr_cb, press_enable_cb, NULL);
- sp->scan_mode = 0;
GUI_CreateButton(&gui->scan_mode, LCD_WIDTH/2 - 48, 40, BUTTON_96, modestr_cb, press_mode_cb, NULL);
- sp->attenuator = 0;
- GUI_CreateButton(&gui->attenuator, LCD_WIDTH/2 + 56, 40, BUTTON_96, attstr_cb, press_attenuator_cb, NULL);
- sp->channel = 0;
- sp->time_to_scan = 0;
+ GUI_CreateButton(&gui->attenuator, LCD_WIDTH/2 + 56, 40, BUTTON_96, attstr_cb, press_attenuator_cb, NULL);
for(i = 0; i < (MAX_RADIOCHANNEL - MIN_RADIOCHANNEL + 1); i++) {
GUI_CreateBarGraph(&gui->bar[i], SCANBARXOFFSET + i * SCANBARWIDTH, 70, SCANBARWIDTH, SCANBARHEIGHT, 2, 31, BAR_VERTICAL, show_bar_cb, (void *)((long)i));
- sp->channelnoise[i] = 0;
}
}
-void PAGE_ScannerEvent()
+void _draw_channels()
{
-#ifndef ENABLE_MODULAR
- if(! sp->enable)
- return;
GUI_Redraw(&gui->bar[sp->channel]);
- //printf("%02X : %d\n",sp->channel,sp->channelnoise[sp->channel]);
- sp->channel++;
- if(sp->channel == (MAX_RADIOCHANNEL - MIN_RADIOCHANNEL + 1))
- sp->channel = 0;
- sp->channelnoise[sp->channel] = 0;
- sp->time_to_scan = 0;
-#endif
-}
-
-void PAGE_ScannerExit()
-{
-#ifndef ENABLE_MODULAR
- if(sp->enable)
- PROTOCOL_Init(0);
-#endif
}
#endif //HAS_SCANNER
diff --git a/src/pages/480x272x16/scanner_page.h b/src/pages/480x272x16/scanner_page.h
deleted file mode 100644
index 635ff6a493..0000000000
--- a/src/pages/480x272x16/scanner_page.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "../320x240x16/scanner_page.h"
diff --git a/src/pages/common/_pages.h b/src/pages/common/_pages.h
index b7f2d63c65..4f3351b0b6 100644
--- a/src/pages/common/_pages.h
+++ b/src/pages/common/_pages.h
@@ -23,6 +23,7 @@
#include "config/display.h"
#include "rtc_config.h"
#include "voiceconfig_page.h"
+#include "scanner_page.h"
#define PAGE_NAME_MAX 10
diff --git a/src/pages/common/_scanner_page.c b/src/pages/common/_scanner_page.c
new file mode 100644
index 0000000000..f94b8b1b59
--- /dev/null
+++ b/src/pages/common/_scanner_page.c
@@ -0,0 +1,143 @@
+/*
+ This project is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Deviation is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Deviation. If not, see .
+ */
+
+static struct scanner_page * const sp = &pagemem.u.scanner_page;
+
+static void _draw_page(u8 enable);
+static void _draw_channels(void);
+static u16 scan_cb();
+
+#ifdef ENABLE_MODULAR
+#error "Not supported in MODULAR build"
+#endif
+
+// The high level interface to do the scan
+static void _scan_enable(int enable)
+{
+ if (enable) {
+ PROTOCOL_DeInit();
+ DEVO_Cmds(0); //Switch to DEVO configuration
+ PROTOCOL_SetBindState(0); //Disable binding message
+ CLOCK_StopTimer();
+ CYRF_SetTxRxMode(RX_EN); //Receive mode
+ CLOCK_StartTimer(1250, scan_cb);
+ } else {
+ PROTOCOL_Init(0);
+ }
+}
+
+static void _scan_next()
+{
+ CYRF_ConfigRFChannel(sp->channel + MIN_RADIOCHANNEL);
+ if(sp->attenuator) {
+ CYRF_WriteRegister(CYRF_06_RX_CFG, 0x0A);
+ } else {
+ CYRF_WriteRegister(CYRF_06_RX_CFG, 0x4A);
+ }
+}
+
+static int _scan_rssi()
+{
+ if ( !(CYRF_ReadRegister(CYRF_05_RX_CTRL) & 0x80)) {
+ CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x80); //Prepare to receive
+ Delay(10);
+ CYRF_ReadRegister(CYRF_13_RSSI); //dummy read
+ Delay(15);
+ }
+#ifdef EMULATOR
+ return rand32() % 0x1F;
+#else
+ return CYRF_ReadRegister(CYRF_13_RSSI) & 0x1F;
+#endif
+}
+
+u16 scan_cb()
+{
+ int delay;
+ if(sp->scanState == 0) {
+ if(sp->time_to_scan == 0) {
+ _scan_next();
+ sp->time_to_scan = 1;
+ }
+ sp->scanState = 1;
+ delay = 300; //slow channel require 270usec for synthesizer to settle
+ } else {
+ int rssi = _scan_rssi();
+ if(sp->scan_mode) {
+ sp->channelnoise[sp->channel] = (sp->channelnoise[sp->channel] + rssi) / 2;
+ } else {
+ if(rssi > sp->channelnoise[sp->channel])
+ sp->channelnoise[sp->channel] = rssi;
+ }
+ sp->scanState++;
+ delay = 300;
+ if(sp->scanState == 5) {
+ sp->scanState = 0;
+ delay = 50;
+ }
+ }
+ return delay;
+}
+
+static void press_enable_cb(guiObject_t *obj, const void *data)
+{
+ (void)data;
+ sp->enable ^= 1;
+ _scan_enable(sp->enable);
+ GUI_Redraw(obj);
+}
+
+static void press_mode_cb(guiObject_t *obj, const void *data)
+{
+ (void)data;
+ sp->scan_mode ^= 1;
+ GUI_Redraw(obj);
+}
+
+static void press_attenuator_cb(guiObject_t *obj, const void *data)
+{
+ (void)data;
+ sp->attenuator ^= 1;
+ GUI_Redraw(obj);
+}
+
+void PAGE_ScannerInit(int page)
+{
+ (void)page;
+ memset(sp, 0, sizeof(struct scanner_page));
+
+ PAGE_SetModal(0);
+ _draw_page(1);
+}
+
+void PAGE_ScannerEvent()
+{
+ if(! sp->enable)
+ return;
+
+ // draw the channels
+ _draw_channels();
+
+ sp->channel++;
+ if(sp->channel == (MAX_RADIOCHANNEL - MIN_RADIOCHANNEL + 1))
+ sp->channel = 0;
+ sp->channelnoise[sp->channel] = 0;
+ sp->time_to_scan = 0;
+}
+
+void PAGE_ScannerExit()
+{
+ _scan_enable(0);
+}
diff --git a/src/pages/320x240x16/scanner_page.h b/src/pages/common/scanner_page.h
similarity index 94%
rename from src/pages/320x240x16/scanner_page.h
rename to src/pages/common/scanner_page.h
index 7714b3df21..36e27668fd 100644
--- a/src/pages/320x240x16/scanner_page.h
+++ b/src/pages/common/scanner_page.h
@@ -7,6 +7,7 @@
struct scanner_page {
u8 channelnoise[MAX_RADIOCHANNEL - MIN_RADIOCHANNEL + 1];
u8 channel;
+ u8 scanState;
u8 time_to_scan;
u8 enable;
u8 scan_mode;
diff --git a/src/target/devo10/target_defs.h b/src/target/devo10/target_defs.h
index 3af5f3a111..14b35bb36b 100644
--- a/src/target/devo10/target_defs.h
+++ b/src/target/devo10/target_defs.h
@@ -18,7 +18,7 @@
#define HAS_VIBRATINGMOTOR 1
#define HAS_DATALOG 1
#define HAS_LAYOUT_EDITOR 1
-#define HAS_SCANNER 0
+#define HAS_SCANNER 1
#define HAS_EXTRA_SWITCHES 0
#define HAS_EXTRA_BUTTONS 0
#define HAS_MULTIMOD_SUPPORT 1
diff --git a/src/target/devo12e/target_defs.h b/src/target/devo12e/target_defs.h
index 91f845a840..e93c06719c 100644
--- a/src/target/devo12e/target_defs.h
+++ b/src/target/devo12e/target_defs.h
@@ -18,7 +18,7 @@
#define HAS_VIBRATINGMOTOR 1
#define HAS_DATALOG 1
#define HAS_LAYOUT_EDITOR 1
-#define HAS_SCANNER 0
+#define HAS_SCANNER 1
#define HAS_EXTRA_SWITCHES 0
#define HAS_EXTRA_BUTTONS 0
#define HAS_MULTIMOD_SUPPORT 1
diff --git a/src/target/devo7e-256/target_defs.h b/src/target/devo7e-256/target_defs.h
index 12710e8d7c..bcb4c8048a 100644
--- a/src/target/devo7e-256/target_defs.h
+++ b/src/target/devo7e-256/target_defs.h
@@ -17,7 +17,7 @@
#define HAS_RTC 0
#define HAS_VIBRATINGMOTOR 1
#define HAS_DATALOG 1
-#define HAS_SCANNER 0
+#define HAS_SCANNER 1
#define HAS_LAYOUT_EDITOR 1
#define HAS_EXTRA_SWITCHES OPTIONAL
#define HAS_SWITCHES_NOSTOCK 1
diff --git a/src/target/ir8m/target_defs.h b/src/target/ir8m/target_defs.h
index 171dfd4ccc..293686449f 100644
--- a/src/target/ir8m/target_defs.h
+++ b/src/target/ir8m/target_defs.h
@@ -17,7 +17,7 @@
#define HAS_RTC 0
#define HAS_VIBRATINGMOTOR 1
#define HAS_DATALOG 1
-#define HAS_SCANNER 0
+#define HAS_SCANNER 1
#define HAS_LAYOUT_EDITOR 1
#define HAS_EXTRA_SWITCHES OPTIONAL
#define HAS_SWITCHES_NOSTOCK 1
diff --git a/src/target/t8sg/target_defs.h b/src/target/t8sg/target_defs.h
index 340b61e6de..86d280ff0e 100644
--- a/src/target/t8sg/target_defs.h
+++ b/src/target/t8sg/target_defs.h
@@ -17,7 +17,7 @@
#define HAS_RTC 0
#define HAS_VIBRATINGMOTOR 1
#define HAS_DATALOG 1
-#define HAS_SCANNER 0
+#define HAS_SCANNER 1
#define HAS_LAYOUT_EDITOR 1
#define HAS_EXTRA_SWITCHES OPTIONAL
#define HAS_SWITCHES_NOSTOCK 1
diff --git a/src/target/t8sg_v2/target_defs.h b/src/target/t8sg_v2/target_defs.h
index 106460a122..6b767a4947 100644
--- a/src/target/t8sg_v2/target_defs.h
+++ b/src/target/t8sg_v2/target_defs.h
@@ -17,7 +17,7 @@
#define HAS_RTC 0
#define HAS_VIBRATINGMOTOR 1
#define HAS_DATALOG 1
-#define HAS_SCANNER 0
+#define HAS_SCANNER 1
#define HAS_LAYOUT_EDITOR 1
#define HAS_EXTRA_SWITCHES OPTIONAL
#define HAS_SWITCHES_NOSTOCK 1
diff --git a/src/target/t8sg_v2_plus/target_defs.h b/src/target/t8sg_v2_plus/target_defs.h
index a2c23aa3e7..da476dee82 100644
--- a/src/target/t8sg_v2_plus/target_defs.h
+++ b/src/target/t8sg_v2_plus/target_defs.h
@@ -17,7 +17,7 @@
#define HAS_RTC 0
#define HAS_VIBRATINGMOTOR 1
#define HAS_DATALOG 1
-#define HAS_SCANNER 0
+#define HAS_SCANNER 1
#define HAS_LAYOUT_EDITOR 1
#define HAS_EXTRA_SWITCHES OPTIONAL
#define HAS_SWITCHES_NOSTOCK 1