diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml
index 62b33d2..d16543b 100644
--- a/.settings/language.settings.xml
+++ b/.settings/language.settings.xml
@@ -5,7 +5,7 @@
-
+
@@ -17,7 +17,7 @@
-
+
diff --git a/main.c b/main.c
index 9ff00dd..f8d3e97 100644
--- a/main.c
+++ b/main.c
@@ -1063,6 +1063,9 @@ void load_LCD_properties(void)
setting.waterfall = W_OFF;
memcpy(setting._trace, def_trace, sizeof(def_trace));
memcpy(setting._markers, def_markers, sizeof(def_markers));
+#ifdef __LIMITS__
+ memset(setting.limits, 0, sizeof(setting.limits));
+#endif
#ifdef __VNA__
setting._velocity_factor = 0.7;
#endif
diff --git a/nanovna.h b/nanovna.h
index dde7c6e..4e3576e 100644
--- a/nanovna.h
+++ b/nanovna.h
@@ -69,6 +69,7 @@
#define __QUASI_PEAK__ // Add quasi peak average option
#define __REMOTE_DESKTOP__ // Add remote desktop option
#define __LISTEN__
+//#define __LIMITS__
#ifdef TINYSA4
#define __HARMONIC__
#endif
@@ -291,6 +292,7 @@ void set_attenuation(float);
float get_attenuation(void);
float get_level(void);
void set_harmonic(int);
+void set_storage(void);
//extern int setting.harmonic;
int search_is_greater(void);
void set_auto_attenuation(void);
@@ -673,6 +675,18 @@ typedef struct {
freq_t frequency;
} marker_t;
+#ifdef __LIMITS__
+#define LIMITS_MAX 6
+typedef struct {
+ uint8_t enabled;
+ float level;
+ freq_t frequency;
+ int16_t index;
+} limit_t;
+extern uint8_t active_limit;
+extern void limits_update(void);
+#endif
+
#define MARKERS_MAX 4
#define MARKER_INVALID -1
@@ -952,7 +966,9 @@ typedef struct setting
float trace_refpos;
trace_t _trace[TRACES_MAX];
marker_t _markers[MARKERS_MAX];
-
+#ifdef __LIMITS__
+ limit_t limits[LIMITS_MAX];
+#endif
systime_t sweep_time_us;
systime_t measure_sweep_time_us;
systime_t actual_sweep_time_us;
@@ -1136,6 +1152,7 @@ void menu_move_top(void);
void draw_menu(void);
int check_touched(void);
int invoke_quick_menu(int);
+bool ui_process_listen_lever(void);
// Irq operation process set
#define OP_NONE 0x00
diff --git a/sa_core.c b/sa_core.c
index 98f8421..3ef77ca 100644
--- a/sa_core.c
+++ b/sa_core.c
@@ -772,6 +772,33 @@ void set_attenuation(float a) // Is used both only in high/low input mode
dirty = true;
}
+#ifdef __LIMITS__
+void limits_update(void)
+{
+ int j = 0;
+ bool active = false;
+ for (int i = 0; i 10 && test_value != 0 && test_value > saved_peakLevel - 1.5) {
test_prepare(TEST_RBW);
setting.spur_removal = S_OFF;
diff --git a/si4432.c b/si4432.c
index bb63324..caf15f3 100644
--- a/si4432.c
+++ b/si4432.c
@@ -725,22 +725,23 @@ void SI4432_Listen(int s)
uint16_t sel = SI_nSEL[SI4432_Sel];
uint8_t max = 0;
uint16_t count = 0;
+ operation_requested = OP_NONE;
do {
- uint8_t v;
- palClearPad(GPIOC, sel);
- shiftOut(SI4432_REG_RSSI);
- v = shiftIn();
- palSetPad(GPIOC, sel);
- if (max < v) // Peak
- max = v;
- if (count > 1000) { // Decay
- max -= 1;
- count = 0;
- } else
- count++;
- v = max - v;
- dacPutChannelX(&DACD2, 0, dBm_to_volt[v] << 4);
- } while((operation_requested & OP_LEVER) != OP_LEVER);
+ uint8_t v;
+ palClearPad(GPIOC, sel);
+ shiftOut(SI4432_REG_RSSI);
+ v = shiftIn();
+ palSetPad(GPIOC, sel);
+ if (max < v) // Peak
+ max = v;
+ if (count > 1000) { // Decay
+ max -= 1;
+ count = 0;
+ } else
+ count++;
+ v = max - v;
+ dacPutChannelX(&DACD2, 0, dBm_to_volt[v] << 4);
+ } while((operation_requested & OP_LEVER) != OP_LEVER);
count = 0;
dacPutChannelX(&DACD2, 0, 0);
}
diff --git a/ui.c b/ui.c
index 8a6d778..3e75cc7 100644
--- a/ui.c
+++ b/ui.c
@@ -2528,6 +2528,22 @@ ui_process_normal(void)
}
}
+#ifdef __LISTEN__
+bool
+ui_process_listen_lever(void)
+{
+ int status = btn_check();
+ if (status != 0) {
+ if (status & EVT_BUTTON_SINGLE_CLICK) {
+ return false;
+ } else {
+ lever_move_marker(status);
+ }
+ }
+ return true;
+}
+#endif
+
static void
ui_process_menu(void)
{
diff --git a/ui_sa.c b/ui_sa.c
index 1bf3201..8cc876d 100644
--- a/ui_sa.c
+++ b/ui_sa.c
@@ -425,6 +425,9 @@ enum {
KM_ATTACK,
#ifdef TINYSA4
KM_LPF,
+#endif
+#ifdef __LIMITS__
+ KM_LIMIT_FREQ, KM_LIMIT_LEVEL,
#endif
// #35
KM_NONE // always at enum end
@@ -473,6 +476,10 @@ static const struct {
#ifdef TINYSA4
{keypads_freq , "ULTRA\nSTART"}, // KM_LPF
#endif
+#ifdef __LIMITS__
+ {keypads_freq , "END\nFREQ"}, // KM_LIMIT_FREQ
+ {keypads_plusmin_unit , "LEVEL"}, // KM_LIMIT_LEVEL
+#endif
};
#if 0 // Not used
@@ -495,6 +502,7 @@ static const menuitem_t menu_modulation[];
static const menuitem_t menu_top[];
static const menuitem_t menu_reffer[];
static const menuitem_t menu_modulation[];
+static const menuitem_t menu_limit_modify[];
//static const menuitem_t menu_drive_wide[];
#ifdef TINYSA4
static const menuitem_t menu_settings3[];
@@ -683,7 +691,12 @@ static UI_FUNCTION_CALLBACK(menu_listen_cb)
{
(void)data;
(void)item;
- SI4432_Listen(MODE_SELECT(setting.mode));
+ if (markers[active_marker].enabled == M_ENABLED) {
+ do {
+ perform(false,0,frequencies[markers[active_marker].index], false);
+ SI4432_Listen(MODE_SELECT(setting.mode));
+ } while (ui_process_listen_lever());
+ }
}
#endif
@@ -1162,6 +1175,24 @@ static UI_FUNCTION_ADV_CALLBACK(menu_marker_select_acb)
redraw_marker(active_marker);
}
+#ifdef __LIMITS__
+uint8_t active_limit = 0;
+static UI_FUNCTION_ADV_CALLBACK(menu_limit_select_acb)
+{
+ (void)item;
+ if(b){
+ b->icon = setting.limits[data-1].enabled ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK;
+ b->param_1.i = data;
+ return;
+ }
+ active_limit = data -1;
+ setting.limits[active_limit].enabled = true;
+ limits_update();
+ menu_push_submenu(menu_limit_modify);
+}
+
+#endif
+
static UI_FUNCTION_ADV_CALLBACK(menu_marker_modify_acb)
{
(void)item;
@@ -1212,6 +1243,19 @@ static UI_FUNCTION_CALLBACK(menu_marker_delete_cb)
}
}
+#ifdef __LIMITS__
+static UI_FUNCTION_CALLBACK(menu_limit_disable_cb)
+{
+ (void)item;
+ (void)data;
+ if (active_limit