From dbee03f1c1dfa4eefcb72d77185ee961fbc8a6ae Mon Sep 17 00:00:00 2001 From: erikkaashoek Date: Tue, 29 Nov 2022 10:50:20 +0100 Subject: [PATCH] Merged ui_sa.c into ui.c --- ui.c | 4450 +++++++++++++++++++++++++++++++++++++++++++++++++++++- ui_sa.c | 4463 ------------------------------------------------------- 2 files changed, 4449 insertions(+), 4464 deletions(-) delete mode 100644 ui_sa.c diff --git a/ui.c b/ui.c index bb95617..d595e7c 100644 --- a/ui.c +++ b/ui.c @@ -1,4 +1,5 @@ /* Copyright (c) 2014-2015, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com + * Copyright (c) 2020-2022, Erik Kaashoek * All rights reserved. * * This is free software; you can redistribute it and/or modify @@ -795,7 +796,4454 @@ active_marker_select(int item) // used only to select an active marker from the } } -#include "ui_sa.c" +//----------------------- iu_sa.c inserted ------------------- + +#define FORM_ICON_WIDTH 16 +#define FORM_ICON_HEIGHT 16 + +static const uint8_t left_icons [] = +{ +#define I_EMPTY (0*16) + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000001), + _BMP16(0b0000000000000001), + _BMP16(0b0000000000000001), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000001), + _BMP16(0b0000000000000001), + _BMP16(0b0000000000000001), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + +#define I_HIGH_INPUT (1*16) + // +----------------+ + _BMP16(0b0000000000000000), // | | + _BMP16(0b0000000000000000), // | | + _BMP16(0b0000000001100000), // | ** | + _BMP16(0b0000000000111001), // | *** *| + _BMP16(0b0000111111111111), // | *************| + _BMP16(0b0000000000111001), // | *** *| + _BMP16(0b0000000001100000), // | ** | + _BMP16(0b0000000000000000), // | | + _BMP16(0b0000000000000000), // | | + _BMP16(0b0000000000000000), // | | + _BMP16(0b0000000000000001), // | | + _BMP16(0b0000000000000001), // | | + _BMP16(0b0000000000000001), // | | + _BMP16(0b0000000000000000), // | | + _BMP16(0b0000000000000000), // | | + _BMP16(0b0000000000000000), // | | + // +----------------+ +#define I_LOW_INPUT (2*16) + // +----------------+ + _BMP16(0b0000000000000000), // | | + _BMP16(0b0000000000000000), // | | + _BMP16(0b0000000000000000), // | | + _BMP16(0b0000000000000001), // | | + _BMP16(0b0000000000000001), // | | + _BMP16(0b0000000000000001), // | | + _BMP16(0b0000000000000000), // | | + _BMP16(0b0000000000000000), // | | + _BMP16(0b0000000000000000), // | | + _BMP16(0b0000000001100000), // | ** | + _BMP16(0b0000000000111001), // | **** *| + _BMP16(0b0000111111111111), // | *************| + _BMP16(0b0000000000111001), // | **** *| + _BMP16(0b0000000001100000), // | ** | + _BMP16(0b0000000000000000), // | | + _BMP16(0b0000000000000000), // | | + // +----------------+ +#define I_LOW_OUTPUT (3*16) + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000001), + _BMP16(0b0000000000000001), + _BMP16(0b0000000000000001), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000110000000), + _BMP16(0b0000011100000001), + _BMP16(0b0000111111111111), + _BMP16(0b0000011100000001), + _BMP16(0b0000000110000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + +#define I_HIGH_OUTPUT (4*16) + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000110000000), + _BMP16(0b0000011100000001), + _BMP16(0b0000111111111111), + _BMP16(0b0000011100000001), + _BMP16(0b0000000110000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000001), + _BMP16(0b0000000000000001), + _BMP16(0b0000000000000001), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + +#define I_CONNECT (5*16) + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000110000), + _BMP16(0b0000000000111101), + _BMP16(0b0000001111111111), + _BMP16(0b0000010000111101), + _BMP16(0b0000100000110000), + _BMP16(0b0001000000000000), + _BMP16(0b0001000000000000), + _BMP16(0b0000100000110000), + _BMP16(0b0000010000111101), + _BMP16(0b0000001111111111), + _BMP16(0b0000000000111101), + _BMP16(0b0000000000110000), + _BMP16(0b0000000000000000), + _BMP16(0b0000000000000000), +}; + +const uint8_t right_icons [] = +{ +#define I_SA 0 + // +----------------+ + _BMP16(0b0000000000000000), // | | + _BMP16(0b0111111111111111), // | ***************| + _BMP16(0b0100000000000001), // | * *| + _BMP16(0b1100000000000001), // |** *| + _BMP16(0b1100000000000001), // |** * *| + _BMP16(0b1100000000000001), // |** * *| + _BMP16(0b0100100000000001), // | * * * *| + _BMP16(0b0100100000000001), // | * * * *| + _BMP16(0b0100101010001001), // | * * * * *| + _BMP16(0b0100101010101001), // | * * * * * *| + _BMP16(0b1100101010101001), // |** * * * * * *| + _BMP16(0b1101111111111101), // |** * * * * * *| + _BMP16(0b1100000000000001), // |** *********** *| + _BMP16(0b0100000000000001), // | * *| + _BMP16(0b0111111111111111), // | ***************| + _BMP16(0b0000000000000000), // | | + // +----------------+ + +#define I_GEN 1 + // +----------------+ + _BMP16(0b0000000000000000), // | | + _BMP16(0b0111111111111111), // | ***************| + _BMP16(0b0100000000000001), // | * *| + _BMP16(0b1100000000000001), // |** *| + _BMP16(0b1100111110001101), // |** ***** ** *| + _BMP16(0b1100100010001001), // |** * * * *| + _BMP16(0b0100100010001001), // | * * * * *| + _BMP16(0b0100100010001001), // | * * * * *| + _BMP16(0b0100100010001001), // | * * * * *| + _BMP16(0b0100100010001001), // | * * * * *| + _BMP16(0b1100100010001001), // |** * * * *| + _BMP16(0b1101100011111001), // |** ** ***** *| + _BMP16(0b1100000000000001), // |** *| + _BMP16(0b0100000000000001), // | * *| + _BMP16(0b0111111111111111), // | ***************| + _BMP16(0b0000000000000000), // | | + // +----------------+ +#define I_CONFIG 2 + _BMP16(0b0000000000000000), + _BMP16(0b0111111111111111), + _BMP16(0b0100000000000001), + _BMP16(0b1100000010000001), + _BMP16(0b1100001111000001), + _BMP16(0b1100011110001001), + _BMP16(0b0100011100011101), + _BMP16(0b0100011110111001), + _BMP16(0b0100001111111001), + _BMP16(0b0100011111110001), + _BMP16(0b1100111110000001), + _BMP16(0b1101111100000001), + _BMP16(0b1100111000000001), + _BMP16(0b0100000000000001), + _BMP16(0b0111111111111111), + _BMP16(0b0000000000000000), + +#define I_SINUS 3 + _BMP16(0b0000000000000000), + _BMP16(0b0111111111111111), // 1 + _BMP16(0b0100000000000001), // 2 + _BMP16(0b1100000000000001), // 3 + _BMP16(0b1100000000110001), // 4 + _BMP16(0b1100000001001001), // 5 + _BMP16(0b0100000010000101), // 6 + _BMP16(0b0101000010000101), // 7 + _BMP16(0b0101000010000101), // 8 + _BMP16(0b0101000010000001), // 9 + _BMP16(0b1100100100000001), //10 + _BMP16(0b1100011000000001), //11 + _BMP16(0b1100000000000001), //12 + _BMP16(0b0100000000000001), //13 + _BMP16(0b0111111111111111), //14 + _BMP16(0b0000000000000000), +}; + +#define KP_X(x) (48*(x) + 2 + (LCD_WIDTH-BUTTON_WIDTH-192)) +#define KP_Y(y) (48*(y) + 2) + + +#define KP_PERIOD 10 +#define KP_MINUS 11 +#define KP_X1 12 +#define KP_K 13 +#define KP_M 14 +#define KP_G 15 +#define KP_BS 16 +#define KP_INF 17 +#define KP_DB 18 +#define KP_PLUSMINUS 19 +#define KP_KEYPAD 20 +#define KP_m 21 +#define KP_u 22 +#define KP_n 23 +#define KP_p 24 + +#define KP_0 31 +#define KP_1 32 +#define KP_2 33 +#define KP_5 34 +#define KP_10 35 +#define KP_20 36 +#define KP_50 37 +#define KP_100 38 +#define KP_200 39 +#define KP_500 40 + + +typedef struct { + uint8_t x:4; + uint8_t y:4; + int8_t c; +} keypads_t; + +static const keypads_t *keypads; + +// 7 8 9 G +// 4 5 6 M +// 1 2 3 k +// 0 . < x + +static const keypads_t keypads_freq[] = { + { 1, 3, KP_PERIOD }, + { 0, 3, 0 }, + { 0, 2, 1 }, + { 1, 2, 2 }, + { 2, 2, 3 }, + { 0, 1, 4 }, + { 1, 1, 5 }, + { 2, 1, 6 }, + { 0, 0, 7 }, + { 1, 0, 8 }, + { 2, 0, 9 }, + { 3, 0, KP_G }, + { 3, 1, KP_M }, + { 3, 2, KP_K }, + { 3, 3, KP_X1 }, + { 2, 3, KP_BS }, + { 0, 0, -1 } +}; + +// 7 8 9 +// 4 5 6 +// 1 2 3 +// 0 . < x + +static const keypads_t keypads_positive[] = { + { 1, 3, KP_PERIOD }, + { 0, 3, 0 }, + { 0, 2, 1 }, + { 1, 2, 2 }, + { 2, 2, 3 }, + { 0, 1, 4 }, + { 1, 1, 5 }, + { 2, 1, 6 }, + { 0, 0, 7 }, + { 1, 0, 8 }, + { 2, 0, 9 }, + { 3, 3, KP_X1 }, + { 2, 3, KP_BS }, + { 0, 0, -1 } +}; + +// 100 200 500 n +// 10 20 50 u +// 1 2 5 m +// 0 . < x + +static const keypads_t keypads_pos_unit[] = { + { 1, 3, KP_PERIOD }, + { 0, 3, 0 }, + { 0, 2, 1 }, + { 1, 2, 2 }, + { 2, 2, 5 }, + { 0, 1, KP_10 }, + { 1, 1, KP_20 }, + { 2, 1, KP_50 }, + { 0, 0, KP_100 }, + { 1, 0, KP_200 }, + { 2, 0, KP_500 }, + { 3, 0, KP_n }, + { 3, 1, KP_u }, + { 3, 2, KP_m }, + { 3, 3, KP_X1 }, + { 2, 3, KP_BS }, + { 0, 0, -1 } +}; + +// 7 8 9 m +// 4 5 6 u +// 1 2 3 - +// 0 . < x + +static const keypads_t keypads_plusmin_unit[] = { + { 1, 3, KP_PERIOD }, + { 0, 3, 0 }, + { 0, 2, 1 }, + { 1, 2, 2 }, + { 2, 2, 3 }, + { 0, 1, 4 }, + { 1, 1, 5 }, + { 2, 1, 6 }, + { 0, 0, 7 }, + { 1, 0, 8 }, + { 2, 0, 9 }, + { 3, 0, KP_u}, + { 3, 1, KP_m}, + { 3, 2, KP_MINUS }, + { 3, 3, KP_X1 }, + { 2, 3, KP_BS }, + { 0, 0, -1 } +}; +// 7 8 9 +// 4 5 6 +// 1 2 3 - +// 0 . < x + +static const keypads_t keypads_plusmin[] = { + { 1, 3, KP_PERIOD }, + { 0, 3, 0 }, + { 0, 2, 1 }, + { 1, 2, 2 }, + { 2, 2, 3 }, + { 0, 1, 4 }, + { 1, 1, 5 }, + { 2, 1, 6 }, + { 0, 0, 7 }, + { 1, 0, 8 }, + { 2, 0, 9 }, + { 3, 0, KP_u}, + { 3, 1, KP_m}, + { 3, 2, KP_MINUS }, + { 3, 3, KP_X1 }, + { 2, 3, KP_BS }, + { 0, 0, -1 } +}; + +// 7 8 9 +// 4 5 6 +// 1 2 3 m +// 0 . < x +static const keypads_t keypads_time[] = { + { 1, 3, KP_PERIOD }, + { 0, 3, 0 }, + { 0, 2, 1 }, + { 1, 2, 2 }, + { 2, 2, 3 }, + { 0, 1, 4 }, + { 1, 1, 5 }, + { 2, 1, 6 }, + { 0, 0, 7 }, + { 1, 0, 8 }, + { 2, 0, 9 }, +// { 3, 0, KP_n}, +// { 3, 1, KP_u}, + { 3, 2, KP_m }, + { 3, 3, KP_X1 }, + { 2, 3, KP_BS }, + { 0, 0, -1 } +}; + +enum { + KM_START, KM_STOP, KM_CENTER, KM_SPAN, KM_CW, // These must be first to share common help text + //#5 + KM_REFLEVEL, KM_SCALE, KM_ATTENUATION, KM_ACTUALPOWER, KM_IF, + // #10 + KM_SAMPLETIME, KM_LOWOUTLEVEL, KM_DECAY, KM_NOISE, +#ifdef TINYSA4 + KM_FREQ_CORR, +#else + KM_10MHZ, +#endif + // #15 + KM_REPEAT, KM_EXT_GAIN, KM_TRIGGER, KM_LEVELSWEEP, KM_SWEEP_TIME, + // #20 + KM_OFFSET_DELAY, KM_FAST_SPEEDUP, KM_GRIDLINES, KM_MARKER, KM_MODULATION, + // #25 + KM_HIGHOUTLEVEL, +#ifdef TINYSA4 + KM_COR_AM, KM_COR_WFM, KM_COR_NFM, + KM_DEVIATION, KM_DEPTH, + KM_IF2, + // #30 + KM_R,KM_MOD,KM_CP, +#endif + KM_ATTACK, +#ifdef __ULTRA__ + KM_ULTRA_START, +#endif +#ifdef TINYSA4 + KM_EXP_AVER, +#endif + KM_LEVEL, +#ifdef __LIMITS__ + KM_LIMIT_FREQ, KM_LIMIT_LEVEL, +#endif + KM_MARKER_TIME, + // #35 + KM_VAR, +#ifdef __NOISE_FIGURE__ + KM_NF, +#endif + KM_LINEAR_SCALE, +#ifdef TINYSA4 + KM_DIRECT_START, + KM_DIRECT_STOP, +#ifdef __USE_RTC__ + KM_RTC_DATE, + KM_RTC_TIME, +#endif +#endif + KM_CODE, + KM_NONE // always at enum end +}; + +static const struct { + const keypads_t *keypad_type; + char * name; +} keypads_mode_tbl[KM_NONE] = { +[KM_START] = {keypads_freq , "START"}, // start +[KM_STOP] = {keypads_freq , "STOP"}, // stop +[KM_CENTER] = {keypads_freq , "CENTER"}, // center +[KM_SPAN] = {keypads_freq , "SPAN"}, // span +[KM_CW] = {keypads_freq , "FREQ"}, // cw freq +[KM_REFLEVEL] = {keypads_plusmin_unit, "REF\nLEVEL"}, // reflevel #5 +[KM_SCALE] = {keypads_pos_unit , "SCALE"}, // scale +[KM_ATTENUATION] = {keypads_positive , "ATTENUATE"}, // attenuation +[KM_ACTUALPOWER] = {keypads_plusmin_unit, "ACTUAL\nPOWER"}, // actual power +[KM_IF] = {keypads_freq , "IF"}, // IF +[KM_SAMPLETIME] = {keypads_positive , "SAMPLE\nDELAY"}, // sample delay #10 +[KM_LOWOUTLEVEL] = {keypads_plusmin , "OUTPUT\nLEVEL"}, // KM_LOWOUTLEVEL +[KM_DECAY] = {keypads_positive , "DECAY"}, // KM_DECAY +[KM_NOISE] = {keypads_positive , "NOISE\nLEVEL"}, // KM_NOISE +#ifdef TINYSA4 +[KM_FREQ_CORR] = {keypads_plusmin , "PPB"}, // KM_FREQ_CORR +#else +[KM_10MHZ] = {keypads_freq , "FREQ"}, // KM_10MHz +#endif +[KM_REPEAT] = {keypads_positive , "SAMPLE\nREPEAT"}, // KM_REPEA #15 +[KM_EXT_GAIN] = {keypads_plusmin , "EXT\nGAIN"}, // KM_EXT_GAIN +[KM_TRIGGER] = {keypads_plusmin_unit, "LEVEL"}, // KM_TRIGGER +[KM_LEVELSWEEP] = {keypads_plusmin , "LEVEL\nSWEEP"}, // KM_LEVELSWEEP +[KM_SWEEP_TIME] = {keypads_time , "SWEEP\nSECONDS"}, // KM_SWEEP_TIME +[KM_OFFSET_DELAY] = {keypads_positive , "OFFSET\nDELAY"}, // KM_OFFSET_DELAY #20 +[KM_FAST_SPEEDUP] = {keypads_positive , "FAST\nSPEEDUP"}, // KM_FAST_SPEEDUP +[KM_GRIDLINES] = {keypads_positive , "MINIMUM\nGRIDLINES"}, // KM_GRIDLINES +[KM_MARKER] = {keypads_freq , "MARKER\nFREQ"}, // KM_MARKER +[KM_MODULATION] = {keypads_freq , "MODULATION\nFREQ"}, // KM_MODULATION +[KM_HIGHOUTLEVEL] = {keypads_plusmin , "OUTPUT\nLEVEL"}, // KM_HIGHOUTLEVEL #25 +#ifdef TINYSA4 +[KM_COR_AM] = {keypads_plusmin , "COR\nAM"}, // KM_COR_AM +[KM_COR_WFM] = {keypads_plusmin , "COR\nWFM"}, // KM_COR_WFM +[KM_COR_NFM] = {keypads_plusmin , "COR\nNFM"}, // KM_COR_NFM +[KM_DEVIATION] = {keypads_freq , "DEVIATION"}, // KM_DEVIATION +[KM_DEPTH] = {keypads_positive , "DEPTH%"}, // KM_DEPTH +[KM_IF2] = {keypads_freq , "IF2"}, // KM_IF2 +[KM_R] = {keypads_plusmin , "R"}, // KM_R #30 +[KM_MOD] = {keypads_positive , "MODULO"}, // KM_MOD +[KM_CP] = {keypads_positive , "CP"}, // KM_CP +#endif +[KM_ATTACK] = {keypads_positive , "ATTACK"}, // KM_ATTACK +#ifdef __ULTRA__ +[KM_ULTRA_START] = {keypads_freq , "ULTRA\nSTART"}, // KM_ULTRA_START +#endif +#ifdef TINYSA4 +[KM_EXP_AVER] = {keypads_positive , "EXPONENTIAL\nAVERAGING"}, //KM_EXP_AVER +#endif +[KM_LEVEL] = {keypads_plusmin , "LEVEL"}, // KM_LEVEL +#ifdef __LIMITS__ +[KM_LIMIT_FREQ] = {keypads_freq , "FREQ"}, // KM_LIMIT_FREQ +[KM_LIMIT_LEVEL] = {keypads_plusmin_unit , "LEVEL"}, // KM_LIMIT_LEVEL +#endif +[KM_MARKER_TIME] = {keypads_time , "MARKER\nTIME"}, // KM_MARKER_TIME +[KM_VAR] = {keypads_freq , "JOG\nSTEP"}, // jog step +#ifdef __NOISE_FIGURE__ +[KM_NF] = {keypads_plusmin , "NOISE\nFIGURE"}, // noise figure of tinySA +#endif +[KM_LINEAR_SCALE] = {keypads_plusmin , "SCALE"}, // scale for linear units +#ifdef TINYSA4 +[KM_DIRECT_START] = {keypads_freq , "DIRECT\nSTART"}, // KM_DIRECT_START +[KM_DIRECT_STOP] = {keypads_freq , "DIRECT\nSTOP"}, // KM_DIRECT_STOP +#ifdef __USE_RTC__ +[KM_RTC_DATE] = {keypads_positive , "SET DATE\n YYMMDD"}, // Date +[KM_RTC_TIME] = {keypads_positive , "SET TIME\n HHMMSS"}, // Time +#endif +#endif +[KM_CODE] = {keypads_positive , "CODE"}, // KM_CODE +}; + +#if 0 // Not used +enum { SL_GENLOW_FREQ, SL_GENHIGH_FREQ, SL_GENLOW_LEVEL, SL_GENHIGH_LEVEL }; +ui_slider_t ui_sliders [] = +{ + { KM_CENTER, true, 0, 1000000, 0, 350000000, M_GENLOW}, + { KM_CENTER, true, 0, 1000000, 240000000, 960000000, M_GENHIGH}, + { KM_LOWOUTLEVEL, false,0, 1, -76, -6, M_GENLOW}, + { KM_HIGHOUTLEVEL, false,0, 1, -38, +6, M_GENHIGH}, +}; +#endif + + +// ===[MENU CALLBACKS]========================================================= +const menuitem_t menu_lowoutputmode[]; +const menuitem_t menu_highoutputmode[]; +const menuitem_t menu_mode[]; +static const menuitem_t menu_modulation[]; +static const menuitem_t menu_top[]; +static const menuitem_t menu_trace[]; +static const menuitem_t menu_marker_trace[]; +static const menuitem_t menu_subtract_trace[]; +#ifdef __LIMITS__ +static const menuitem_t menu_limit_modify[]; +static const menuitem_t menu_limit_select[]; +#endif +static const menuitem_t menu_average[]; +static const menuitem_t menu_reffer[]; +static const menuitem_t menu_sweep_points[]; +static const menuitem_t menu_sweep_points_form[]; +static const menuitem_t menu_modulation[]; +static const menuitem_t menu_marker_ref_select[]; +#ifdef __USE_SERIAL_CONSOLE__ +static const menuitem_t menu_connection[]; +#endif +//static const menuitem_t menu_drive_wide[]; +static const menuitem_t menu_config[]; +#ifdef TINYSA4 +static const menuitem_t menu_settings3[]; +static const menuitem_t menu_curve[]; +static const menuitem_t menu_curve_confirm[]; +static const menuitem_t menu_measure_noise_figure[]; +static const menuitem_t menu_calibrate_harmonic[]; +#endif +static const menuitem_t menu_sweep[]; +static const menuitem_t menu_settings[]; +static const menuitem_t menu_settings2[]; +static const menuitem_t menu_lowoutput_settings[]; +extern bool dirty; +char range_text[20]; + +#ifdef TINYSA4 +int input_is_calibrated(void) +{ + if (config.input_is_calibrated) + return true; + drawMessageBox("Error", "First calibrate 100kHz to 5.34GHz input", 2000); + redraw_request|= REDRAW_AREA; + return false; +} + +int output_is_calibrated(void) +{ + if (config.output_is_calibrated) + return true; + drawMessageBox("Error", "First calibrate 30MHz output", 2000); + redraw_request|= REDRAW_AREA; + return false; +} + +static int unlock_internals = 0; + +static UI_FUNCTION_ADV_CALLBACK(menu_internals_acb) +{ + (void)data; + (void)item; + if (b){ + return; + } + if (unlock_internals != 5432) { + kp_help_text = "Internals access code"; + ui_mode_keypad(KM_CODE); + if (uistat.value != 5432) { + return; + } + unlock_internals = 5432; + } + menu_push_submenu(menu_settings2); +} + +#endif + +static UI_FUNCTION_ADV_CALLBACK(menu_sweep_acb) +{ + (void)data; + (void)item; + if (b){ + if (setting.level_sweep != 0 || get_sweep_frequency(ST_SPAN) != 0) { + plot_printf(b->text, sizeof b->text, "SW:%3.2fMHz %+ddB %.3Fs", + get_sweep_frequency(ST_SPAN) / 1000000.0, + (int)setting.level_sweep, + setting.sweep_time_us/(float)ONE_SECOND_TIME); + } + else + plot_printf(b->text, sizeof b->text, "SWEEP: OFF"); + return; + } + menu_push_submenu(menu_sweep); +} + +#ifdef __SWEEP_RESTART__ +static UI_FUNCTION_ADV_CALLBACK(menu_restart_acb){ + (void)item; + (void)data; + if(b){ + if (setting.sweep) { + if (current_index >= 0) { + float current_level = setting.level + ((float)current_index)* setting.level_sweep / (float)sweep_points; + plot_printf(b->text, sizeof b->text, "STOP %5.3QHz %+.1fdBm", getFrequency(current_index), current_level); + } else + plot_printf(b->text, sizeof b->text, "STOP SWEEP"); + } + else + plot_printf(b->text, sizeof b->text, "START SWEEP"); + return; + } + setting.sweep = !setting.sweep; + dirty = true; +} +#endif + +#ifdef TINYSA4 + +float local_actual_level; +int current_curve; +int current_curve_index; + +static UI_FUNCTION_ADV_CALLBACK(menu_curve_acb) + { + (void)item; + int old_m; + if (b){ + plot_printf(b->text, sizeof b->text, "%8.3QHz %+4.1fdB", + config.correction_frequency[current_curve][data], + config.correction_value[current_curve][data]); + return; + } + switch(current_curve) { + case CORRECTION_LOW_OUT: + old_m = setting.mode; + reset_settings(M_GENLOW); + set_level(-35); + set_sweep_frequency(ST_CW, config.correction_frequency[current_curve][data]); + setting.mute = false; + perform(false, 0, config.correction_frequency[current_curve][data], false); + perform(false, 1, config.correction_frequency[current_curve][data], false); + plot_printf(uistat.text, sizeof uistat.text, "Level of %.3QHz output", + config.correction_frequency[current_curve][data]); + kp_help_text = uistat.text; + kp_buf[0]=0; + ui_mode_keypad(KM_LEVEL); + + if (kp_buf[0] != 0) { + float new_offset = (-35.0) - uistat.value + config.correction_value[current_curve][data]; // calculate offset based on difference between measured peak level and known peak level + if (new_offset > -25 && new_offset < 25) { + config.correction_value[current_curve][data] = new_offset; + config_save(); + } + } + reset_settings(old_m); + break; + case CORRECTION_LNA: + reset_settings(M_LOW); + setting.extra_lna = true; + goto common; + case CORRECTION_LOW: + reset_settings(M_LOW); + common: + set_sweep_frequency(ST_SPAN, 1000000); + set_sweep_frequency(ST_CENTER, config.correction_frequency[current_curve][data]); + setting.step_delay_mode = SD_PRECISE; + current_curve_index = data; + menu_push_submenu(menu_curve_confirm); + break; + } +} + +extern float peakLevel; + +UI_FUNCTION_CALLBACK(menu_curve_confirm_cb) +{ + (void)item; + if (data) { + float new_offset = local_actual_level - peakLevel + config.correction_value[current_curve][current_curve_index]; // calculate offset based on difference between measured peak level and known peak level + if (new_offset > -30 && new_offset < 30) { + config.correction_value[current_curve][current_curve_index] = new_offset; + config_save(); + } + } + menu_move_back(false); +} + +float measured_noise_figure; + +#if 0 +UI_FUNCTION_CALLBACK(menu_noise_figure_confirm_cb) +{ + (void)item; + if (data) { + if (measured_noise_figure > 3 && measured_noise_figure < 15) { + config.noise_figure = measured_noise_figure; + config_save(); + nf_gain = 0.00001; // almost zero + set_measurement(M_NF_VALIDATE); // Continue to validate + return; + } + } + menu_move_back(false); +} +#endif + +static UI_FUNCTION_CALLBACK(menu_input_curve_prepare_cb) +{ + (void)item; + (void)data; + if (!input_is_calibrated()) + return; + kp_help_text = "Enter actual input level"; + kp_buf[0]=0; + ui_mode_keypad(KM_LEVEL); + if (kp_buf[0] != 0) { + local_actual_level = uistat.value; + current_curve = CORRECTION_LOW; + menu_push_submenu(menu_curve); + } +} + +static UI_FUNCTION_CALLBACK(menu_lna_curve_prepare_cb) +{ + (void)item; + (void)data; + if (!input_is_calibrated()) + return; + kp_help_text = "Enter actual input level"; + kp_buf[0]=0; + ui_mode_keypad(KM_LEVEL); + if (kp_buf[0] != 0) { + local_actual_level = uistat.value; + current_curve = CORRECTION_LNA; + menu_push_submenu(menu_curve); + } +} + +static UI_FUNCTION_CALLBACK(menu_lna_u_curve_prepare_cb) +{ + (void)item; + (void)data; + if (!input_is_calibrated()) + return; + kp_help_text = "Enter actual input level"; + kp_buf[0]=0; + ui_mode_keypad(KM_LEVEL); + if (kp_buf[0] != 0) { + local_actual_level = uistat.value; + current_curve = CORRECTION_LNA_ULTRA; + menu_push_submenu(menu_curve); + } +} + +static UI_FUNCTION_CALLBACK(menu_ultra_curve_prepare_cb) +{ + (void)item; + (void)data; + if (!input_is_calibrated()) + return; + kp_help_text = "Enter actual input level"; + kp_buf[0]=0; + ui_mode_keypad(KM_LEVEL); + if (kp_buf[0] != 0) { + local_actual_level = uistat.value; + current_curve = CORRECTION_LOW_ULTRA; + menu_push_submenu(menu_curve); + } +} + +static UI_FUNCTION_CALLBACK(menu_output_curve_prepare_cb) +{ + (void)item; + (void)data; + if (!output_is_calibrated()) + return; + current_curve = CORRECTION_LOW_OUT; + menu_push_submenu(menu_curve); +} + +#endif + +static UI_FUNCTION_ADV_CALLBACK(menu_output_level_acb) +{ + (void)item; + (void)data; + if (b){ + return; + } + int old_m = setting.mode; + reset_settings(M_GENLOW); +#ifdef TINYSA4 +#define TEST_LEVEL -30 +#else +#define TEST_LEVEL -25 +#endif + set_level(TEST_LEVEL); + set_sweep_frequency(ST_CW, 30000000); + setting.mute = false; + perform(false, 0, 30000000, false); + perform(false, 1, 30000000, false); + kp_help_text = "Enter actual level of 30MHz output"; + kp_buf[0]=0; + ui_mode_keypad(KM_LEVEL); + if (kp_buf[0] != 0) { + float old_offset = config.low_level_output_offset; + if (!config.input_is_calibrated) old_offset = 0; + float new_offset = uistat.value - (TEST_LEVEL) + old_offset; // calculate offset based on difference between measured peak level and known peak level + if (uistat.value == 100) { new_offset = 0; config.input_is_calibrated = false; } + if (new_offset > -15 && new_offset < 15) { + config.output_is_calibrated = true; + config.low_level_output_offset = new_offset; + config_save(); + } + } + reset_settings(old_m); +} + +#ifdef TINYSA4 +static UI_FUNCTION_ADV_CALLBACK(menu_output_level2_acb) +{ + (void)item; + (void)data; + if (b){ + return; + } + if (!output_is_calibrated()) + return; + int old_m = setting.mode; + reset_settings(M_GENLOW); + set_level(-30); + set_sweep_frequency(ST_CW, 1000000000); + setting.mute = false; + perform(false, 0, 1000000000, false); + perform(false, 1, 1000000000, false); + kp_help_text = "Enter actual level of 1GHz output"; + kp_buf[0]=0; + ui_mode_keypad(KM_LEVEL); + if (kp_buf[0] != 0) { + float old_offset = config.direct_level_output_offset; + float new_offset = (-30.0) - uistat.value + old_offset; // calculate offset based on difference between measured peak level and known peak level + if (new_offset > -10 && new_offset < 10) { + config.direct_level_output_offset = new_offset; + config_save(); + } + } + reset_settings(old_m); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_output_level3_acb) +{ + (void)item; + (void)data; + if (b){ + return; + } + if (!output_is_calibrated()) + return; + int old_m = setting.mode; + reset_settings(M_GENLOW); + + force_signal_path = true; + test_path = PATH_LEAKAGE; + test_output_drive = -1; + + set_level(-30); + set_sweep_frequency(ST_CW, 1200000000); + setting.mute = false; + perform(false, 0, 1200000000, false); + perform(false, 1, 1200000000, false); + kp_help_text = "Enter actual level of 1.2GHz output"; + kp_buf[0]=0; + ui_mode_keypad(KM_LEVEL); + if (kp_buf[0] != 0) { + float old_offset = config.adf_level_offset; + float new_offset = (-30.0) - uistat.value + old_offset; // calculate offset based on difference between measured peak level and known peak level + if (new_offset > -10 && new_offset < 10) { + config.adf_level_offset = new_offset; + config_save(); + } + } + force_signal_path = false; + reset_settings(old_m); +} + +#endif + +#ifdef TINYSA4 +static const int item_to_mode[2] = { 0,2 }; +#else +static const int item_to_mode[4] = { 0,1,2,3 }; +#endif +static UI_FUNCTION_ADV_CALLBACK(menu_mode_acb) +{ + (void)data; + item = item_to_mode[item]; + if (b){ + if (item == setting.mode) { + b->param_1.text = "Return"; + b->bg = LCD_MENU_ACTIVE_COLOR; + b->border = BUTTON_BORDER_FALLING | MENU_BUTTON_BORDER; + } + else + b->param_1.text = "Switch"; + return; + } + set_mode(item); +// draw_cal_status(); + switch (item) { + case 0: +// if (setting.mode != M_LOW) +// set_mode(M_LOW); + menu_move_back(true); + break; + case 1: +// if (setting.mode != M_HIGH) +// set_mode(M_HIGH); + menu_move_back(true); + break; + case 2: + menu_push_submenu(menu_lowoutputmode); + break; + case 3: + menu_push_submenu(menu_highoutputmode); + break; + } + redraw_request |= REDRAW_CAL_STATUS; +} + +static UI_FUNCTION_ADV_CALLBACK(menu_load_preset_acb) +{ + (void)item; + if(b){ + setting_t *p = caldata_pointer(data); + if (p) + plot_printf(b->text, sizeof(b->text), "%.6FHz\n%.6FHz", (float)p->frequency0, (float)p->frequency1); + else + plot_printf(b->text, sizeof(b->text), "EMPTY %d", (int)data); + return; + } + if (caldata_recall(data) == -1) { + if (data == 0) + reset_settings(setting.mode); // Restore factory defaults + } + menu_move_back(true); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_store_preset_acb) +{ + (void)item; + if(b){ + b->param_1.u = data; + return; + } + if (data == 100) { + reset_settings(M_LOW); // Restore all defaults in Low mode + set_refer_output(-1); + // setting.mode = -1; + data = 0; + } + caldata_save(data); + menu_move_back(true); +} + +#ifdef __SD_CARD_LOAD__ +UI_FUNCTION_CALLBACK(menu_load_config_cb) +{ + (void)item; + (void)data; + sd_card_load_config("config.ini"); + ui_mode_normal(); +} +#endif + +UI_FUNCTION_CALLBACK(menu_autosettings_cb) +{ + (void)item; + (void)data; + reset_settings(setting.mode); + + markers_reset(); + // set_refer_output(1); + + // SetPowerLevel(100); // Reset +// set_clear_storage(); + dirty = true; + // menu_move_back(true); // stay in input menu + ui_mode_normal(); +// draw_cal_status(); +} + +static UI_FUNCTION_CALLBACK(menu_scale_cb) +{ + (void)item; + (void)data; + kp_help_text = "Enter scale"; + kp_buf[0]=0; + + if (UNIT_IS_LINEAR(setting.unit)) + ui_mode_keypad(KM_LINEAR_SCALE); + else + ui_mode_keypad(KM_SCALE); + ui_mode_normal(); +} + +#ifdef __CALIBRATE__ +static UI_FUNCTION_CALLBACK(menu_calibrate_cb) +{ + (void)data; + (void)item; + switch (data) { + case 1: + sweep_mode = SWEEP_CALIBRATE; +#ifdef TINYSA4 + menu_move_back(false); +#endif + menu_move_back(true); + break; + case 2: + reset_calibration(); + break; +#ifdef TINYSA4 + case 3: + if (!input_is_calibrated()) + return; + sweep_mode = SWEEP_CALIBRATE_HARMONIC; + menu_move_back(false); + menu_move_back(true); + break; +#endif + } +} +#endif + +static UI_FUNCTION_ADV_CALLBACK(menu_scanning_speed_acb) +{ + (void)item; + if(b){ + b->icon = data == setting.step_delay_mode ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + return; + } + set_step_delay(data); +// menu_move_back(false); + ui_mode_normal(); +} + +#define CONFIG_MENUITEM_TOUCH_CAL 0 +#define CONFIG_MENUITEM_TOUCH_TEST 1 +#define CONFIG_MENUITEM_SELFTEST 2 +#define CONFIG_MENUITEM_VERSION 3 +static UI_FUNCTION_CALLBACK(menu_config_cb) +{ + (void)item; + switch (data) { + case CONFIG_MENUITEM_TOUCH_CAL: + touch_cal_exec(); + break; + case CONFIG_MENUITEM_TOUCH_TEST: + touch_draw_test(); + break; + case CONFIG_MENUITEM_SELFTEST: + sweep_mode = 0; // Suspend sweep to save time + menu_move_back(true); + setting.test = 0; + setting.test_argument = 0; + sweep_mode = SWEEP_SELFTEST; + return; + case CONFIG_MENUITEM_VERSION: + show_version(); + break; + } + ui_mode_normal(); + redraw_frame(); + request_to_redraw_grid(); +} +#ifndef TINYSA4 +static UI_FUNCTION_CALLBACK(menu_dfu_cb) +{ + (void)data; + (void)item; + enter_dfu(); +} +#endif + +#ifdef __LISTEN__ +static UI_FUNCTION_ADV_CALLBACK(menu_listen_acb) +{ + (void)data; + (void)item; + if (b){ + b->icon = (sweep_mode & SWEEP_LISTEN) ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + return; + } + if (sweep_mode & SWEEP_LISTEN) { + sweep_mode = SWEEP_ENABLE; + } else { + sweep_mode = SWEEP_LISTEN; + } + ui_mode_normal(); + redraw_frame(); + request_to_redraw_grid(); + +#if 0 + 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 +} +#endif +#ifdef TINYSA4 + + +static UI_FUNCTION_ADV_CALLBACK(menu_lowoutput_settings_acb) +{ + static char mode_string[26]; + (void)item; + if (b){ + if (data == 255) { + plot_printf(mode_string, sizeof mode_string, "%s %s %s %s", + (!force_signal_path ? "" : path_text[test_path]), + (get_sweep_frequency(ST_START) < MINIMUM_DIRECT_FREQ ? "SINUS" : "" ), + (get_sweep_frequency(ST_STOP) >= MINIMUM_DIRECT_FREQ ? "SQUARE WAVE" : ""), + (get_sweep_frequency(ST_STOP) > MAX_LOW_OUTPUT_FREQ && setting.mixer_output ? "MIXER" : "")); + b->param_1.text = mode_string; + return; } + b->icon = data == setting.mixer_output ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + return; + } + switch(data) { + case 255: + menu_push_submenu(menu_lowoutput_settings); + return; + case 0: + setting.mixer_output = false; + dirty = true; + break; + case 1: + setting.mixer_output = true; + dirty = true; + break; + } + menu_move_back(false); +} + +#endif +// const int menu_modulation_value[]={MO_NONE,MO_AM, MO_NFM, MO_WFM, MO_EXTERNAL}; +const char *menu_modulation_text[MO_MAX]= +{ "None", "AM 30%", +#ifdef TINYSA4 + "FM 2.5kHz", + "FM 3kHz", + "FM 5kHz", +#else + "FM 4kHz", +#endif + "FM 75kHz", "External"}; + +static UI_FUNCTION_ADV_CALLBACK(menu_modulation_acb) +{ + (void)item; + if (b){ + plot_printf(b->text, sizeof b->text, "%s", menu_modulation_text[data]); + b->icon = data == setting.modulation ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + return; + } +//Serial.println(item); + if (data) { + set_sweep_frequency(ST_SPAN, 0); // No other scanning allowed when modulation is on!!!!! + set_level_sweep(0); + } + set_modulation(data); +// menu_move_back(false); // Don't move back +} + +static UI_FUNCTION_ADV_CALLBACK(menu_smodulation_acb){ + (void)item; + (void)data; + if(b){ + if (setting.modulation == MO_NONE || setting.modulation == MO_EXTERNAL) + plot_printf(b->text, sizeof b->text, "MOD: %s", menu_modulation_text[setting.modulation]); + else { +#ifdef TINYSA4 + if (setting.modulation == MO_AM) + plot_printf(b->text, sizeof b->text, "MOD: %4dHz AM %d%%", (int)(setting.modulation_frequency), setting.modulation_depth_x100); + else + plot_printf(b->text, sizeof b->text, "MOD: %4dHz FM %4QHz", (int)(setting.modulation_frequency), (freq_t)(setting.modulation_deviation_div100*100)); +#else + plot_printf(b->text, sizeof b->text, "MOD: %4dHz %s", (int)(setting.modulation_frequency), menu_modulation_text[setting.modulation]); +#endif + } + return; + } + menu_push_submenu(menu_modulation); +} + +// 0 1 2 3 4 5 6 7 +const char *menu_reffer_text[]={"OFF","30MHz","15MHz","10MHz","4MHz","3MHz","2MHz","1MHz"}; +static UI_FUNCTION_ADV_CALLBACK(menu_reffer_acb) +{ + (void)item; + if (b){ + b->icon = setting.refer == ((int)data-1) ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + b->param_1.text = menu_reffer_text[data]; + return; + } +//Serial.println(item); + set_refer_output((int)data - 1); + menu_move_back(false); +// ui_mode_normal(); // Stay in menu mode +// draw_cal_status(); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_sreffer_acb){ + (void)item; + (void)data; + if(b){ + b->param_1.text = menu_reffer_text[setting.refer+1]; + return; + } + menu_push_submenu(menu_reffer); +} + +#ifdef TINYSA3 +static UI_FUNCTION_ADV_CALLBACK(menu_lo_drive_acb) +{ + (void)item; + if(b){ + b->param_1.i = drive_dBm[data]; + b->icon = data == setting.lo_drive ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + return; + } +//Serial.println(item); + set_lo_drive(data); + menu_move_back(false); +// ui_mode_normal(); +// draw_cal_status(); +} +#else +static UI_FUNCTION_ADV_CALLBACK(menu_mixer_drive_acb) +{ + (void)item; + if(b){ + b->param_1.i = data; + b->icon = data == setting.lo_drive ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + return; + } +//Serial.println(item); + set_lo_drive(data); + menu_move_back(false); +// ui_mode_normal(); +// draw_cal_status(); +} +#endif + +#if 0 +static UI_FUNCTION_ADV_CALLBACK(menu_sdrive_acb){ + (void)item; + (void)data; + if(b){ +#ifdef TINYSA4 + b->param_1.i = setting.lo_drive; +#else + b->param_1.i = drive_dBm[setting.lo_drive] + (setting.mode==M_GENHIGH ? setting.external_gain : 0); +#endif + return; + } + menu_push_submenu(menu_drive_wide); +} +#endif + +#ifdef __SPUR__ +static UI_FUNCTION_ADV_CALLBACK(menu_spur_acb) +{ + (void)data; + (void)item; + if (b){ + if (setting.mode == M_LOW) { + b->param_1.text = "SPUR\nREMOVAL"; + b->icon = AUTO_ICON(setting.spur_removal); + } else { + b->param_1.text = "MIRROR\nMASKING"; +#ifdef TINYSA4 + b->icon = AUTO_ICON(setting.mirror_masking ? 1 : 0); // mirror_masking does not yet have an auto mode so this is never an auto icon +#else + b->icon = setting.mirror_masking == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; +#endif + } + return; + } + if (setting.mode == M_LOW) { + toggle_spur(); + } else + toggle_mirror_masking(); + // menu_move_back(false); + ui_mode_normal(); +} +#if 0 +#ifdef __HARMONIC__ +static UI_FUNCTION_ADV_CALLBACK(menu_harmonic_spur_acb) +{ + (void)data; + (void)item; + if (b){ + b->icon = AUTO_ICON(setting.spur_removal); + return; + } + toggle_spur(); + ui_mode_normal(); +}#endif +#endif +#endif +#endif + +#ifdef __ULTRA__ +static UI_FUNCTION_ADV_CALLBACK(menu_debug_spur_acb) +{ + (void)data; + (void)item; + if (b){ + b->icon = debug_spur == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; + return; + } + toggle_debug_spur(); + // menu_move_back(); + ui_mode_normal(); +} +#endif + +#ifdef TINYSA4 +static UI_FUNCTION_ADV_CALLBACK(menu_hide_21MHz_acb) +{ + (void)data; + (void)item; + if (b){ + b->icon = config.hide_21MHz == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; + return; + } + config.hide_21MHz = ! config.hide_21MHz; + // menu_move_back(); + ui_mode_normal(); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_progress_bar_acb) +{ + (void)data; + (void)item; + if (b){ + b->icon = progress_bar == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; + return; + } + progress_bar = !progress_bar; + // menu_move_back(); + ui_mode_normal(); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_extra_lna_acb) +{ + (void)data; + (void)item; + if (b){ + b->icon = setting.extra_lna == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; + return; + } + toggle_extra_lna(); + // menu_move_back(false); + ui_mode_normal(); +} +#ifndef __NEW_SWITCHES__ +static UI_FUNCTION_ADV_CALLBACK(menu_adf_out_acb) +{ + (void)data; + (void)item; + if (b){ + b->icon = config.high_out_adf4350 == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; + return; + } + toggle_high_out_adf4350(); + // menu_move_back(false); + ui_mode_normal(); +} +#endif + +#ifdef __WAIT_CTS_WHILE_SLEEPING__ +volatile int sleep = 0; +static UI_FUNCTION_ADV_CALLBACK(menu_sleep_acb) +{ + (void)data; + (void)item; + if (b){ + b->icon = sleep == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; + return; + } + sleep = !sleep; +} +#endif + +static UI_FUNCTION_ADV_CALLBACK(menu_debug_avoid_acb) +{ + (void)data; + (void)item; + if (b){ + b->icon = debug_avoid == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; + return; + } + toggle_debug_avoid(); + // menu_move_back(); + ui_mode_normal(); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_debug_freq_acb) +{ + (void)data; + (void)item; + if (b){ + b->icon = debug_frequencies == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; + return; + } + debug_frequencies = ! debug_frequencies; + // menu_move_back(); + ui_mode_normal(); +} + + +static UI_FUNCTION_ADV_CALLBACK(menu_linear_averaging_acb) +{ + (void)data; + (void)item; + if (b){ + b->icon = linear_averaging == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; + return; + } + linear_averaging = ! linear_averaging; + dirty = true; + // menu_move_back(); + ui_mode_normal(); +} + + +#endif + +#ifdef __ULTRA__ +static UI_FUNCTION_ADV_CALLBACK(menu_ultra_acb) +{ + (void)data; + (void)item; + if (b){ + b->icon = config.ultra == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; + return; + } + if (!config.ultra) { + drawMessageBox("Info", "Visit tinysa.org/ultra for unlock code", 2000); + + kp_help_text = "Ultra unlock code"; + ui_mode_keypad(KM_CODE); + if (uistat.value != 4321) + return; + } + config.ultra = !config.ultra; + config_save(); + reset_settings(M_LOW); + if (config.ultra){ + set_sweep_frequency(ST_START, 0); + set_sweep_frequency(ST_STOP, 3000000000ULL); + } + // menu_move_back(false); + ui_mode_normal(); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_direct_acb) +{ + (void)data; + (void)item; + if (b){ + b->icon = config.direct == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; + return; + } + config.direct = !config.direct; + config_save(); + // menu_move_back(false); + ui_mode_normal(); +} + +#endif + +static UI_FUNCTION_CALLBACK(menu_clearconfig_cb) +{ + (void)data; + (void)item; + kp_help_text = "Clear unlock code"; + ui_mode_keypad(KM_CODE); + if (uistat.value != 1234) + return; + clear_all_config_prop_data(); +#ifndef TINYSA4 +#define SCB_AIRCR_VECTKEYSTAT_LSB 16 +#define SCB_AIRCR_VECTKEYSTAT (0xFFFF << SCB_AIRCR_VECTKEYSTAT_LSB) +#define SCB_AIRCR_VECTKEY (0x05FA << SCB_AIRCR_VECTKEYSTAT_LSB) +#define SCB_AIRCR_SYSRESETREQ (1 << 2) + SCB->AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_SYSRESETREQ; + while(true); +#else + rccEnableWWDG(FALSE); + WWDG->CFR = 0x60; + WWDG->CR = 0xff; + /* wait forever */ +#endif + while (1) + ; +} + +float nf_gain; +const char * const averageText[] = { "OFF", "MINH", "MAXH", "MAXD", " AVER4", "A16", "AVER", "QUASI", "TABLE", "DECONV"}; + +static UI_FUNCTION_ADV_CALLBACK(menu_measure_acb) +{ + (void)item; + if (b){ + b->icon = data == setting.measurement ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + return; + } + menu_move_back(false); + markers_reset(); + + if ((data != M_OFF && setting.measurement != M_OFF) || data == M_OFF ) + { + // reset_settings(setting.mode); + if (0) { + no_measurement: + drawMessageBox("Error", "Incorrect input", 2000); + redraw_request|= REDRAW_AREA; + + data = M_OFF; + } + if (setting.measurement == M_LINEARITY) { + TRACE_DISABLE(TRACE_STORED_FLAG); + } + set_average(0,AV_OFF); + set_external_gain(0.0); +#ifdef TINYSA4 + set_extra_lna(false); +#endif + } + switch(data) { + case M_OFF: // Off +// set_measurement(M_OFF); + break; + case M_IMD: // IMD + reset_settings(setting.mode); + for (int i = 1; i< MARKERS_MAX; i++) { + markers[i].mtype = M_DELTA; + } + kp_help_text = "Frequency of fundamental"; + ui_mode_keypad(KM_CENTER); + set_sweep_frequency(ST_START, 0); + set_sweep_frequency(ST_STOP, uistat.value*(MARKERS_MAX+1)); + set_average(0,AV_4); +// set_measurement(M_IMD); + break; + case M_OIP3: // OIP3 + reset_settings(setting.mode); + for (int i = 0; i< 4; i++) { + markers[i].enabled = M_ENABLED; + } + markers[1].mtype = M_TRACKING; + kp_help_text = "Frequency of left signal"; + ui_mode_keypad(KM_CENTER); + freq_t left = uistat.value; + kp_help_text = "Right signal"; + ui_mode_keypad(KM_CENTER); + freq_t right = uistat.value; + set_sweep_frequency(ST_CENTER, (left+right)/2); + freq_t local_span = (right - left)*10; +#ifdef TINYSA4 + if (local_span < 3000) + local_span = 3000; +#else + if (local_span < 30000) + local_span = 30000; +#endif + set_sweep_frequency(ST_SPAN, local_span); + set_average(0,AV_4); +// set_measurement(M_OIP3); + break; + case M_PHASE_NOISE: // Phase noise + reset_settings(setting.mode); + markers[1].enabled = M_ENABLED; + markers[1].mtype = M_DELTA | M_NOISE; + kp_help_text = "Frequency of signal"; + ui_mode_keypad(KM_CENTER); + kp_help_text = "Frequency offset"; + ui_mode_keypad(KM_SPAN); + set_sweep_frequency(ST_SPAN, uistat.value*4); +// set_measurement(M_PHASE_NOISE); + set_average(0,AV_4); + + break; + case M_SNR: // STop band measurement + reset_settings(setting.mode); + kp_help_text = "Frequency of signal"; + ui_mode_keypad(KM_CENTER); + kp_help_text = "Bandwidth"; + ui_mode_keypad(KM_SPAN); + set_sweep_frequency(ST_SPAN, uistat.value*3); +// set_measurement(M_SNR); + set_average(0,AV_4); + + break; + case M_PASS_BAND: // pass band measurement +// reset_settings(setting.mode); + markers[1].enabled = M_ENABLED; + markers[2].enabled = M_ENABLED; +// kp_help_text = "Frequency of signal"; +// ui_mode_keypad(KM_CENTER); +// kp_help_text = "Width of signal"; +// ui_mode_keypad(KM_SPAN); +// set_sweep_frequency(ST_SPAN, uistat.value*2); + set_measurement(M_PASS_BAND); +// SetAverage(4); + + break; +#ifdef __LINEARITY__ + case M_LINEARITY: + TRACE_ENABLE(TRACE_STORED_FLAG); +// set_measurement(M_LINEARITY); + break; +#endif + case M_AM: // AM + reset_settings(setting.mode); + for (int i = 1; i< 3; i++) { + markers[i].enabled = M_ENABLED; +#ifdef TINYSA4 + markers[i].mtype = M_DELTA| M_TRACKING; +#else +// markers[i].mtype = M_DELTA;// | M_TRACKING; +#endif + } +#ifdef TINYSA4 + freq_t span; +#else + freq_t center, span; + markers[0].mtype = M_NORMAL; // M_REFERENCE | M_TRACKING; // Not M_TRACKING!!!! +#endif + kp_help_text = "Frequency of signal"; + ui_mode_keypad(KM_CENTER); +#ifdef TINYSA3 + center = uistat.value; +#endif +#ifdef TINYSA4 + kp_help_text = "Modulation frequency: 500hz .. 10kHz"; +#else + kp_help_text = "Modulation frequency: 3 .. 10kHz"; +#endif + ui_mode_keypad(KM_SPAN); + span = uistat.value; +#ifdef TINYSA4 + if (span < 500 || span > 10000) + goto no_measurement; +#endif +#ifdef TINYSA4 + set_RBW((span * 5 / 50) / 100); +#endif + set_sweep_frequency(ST_SPAN, span * 5); +// update_frequencies(); // To ensure markers are positioned right!!!!!! +// set_measurement(M_AM); +#ifndef TINYSA4 + set_marker_frequency(0, center); + set_marker_frequency(1, center-span); + set_marker_frequency(2, center+span); +#endif + set_average(0,AV_4); + break; + case M_FM: // FM + reset_settings(setting.mode); + for (int i = 1; i< 3; i++) { + markers[i].enabled = M_ENABLED; + } + markers[0].mtype = M_NORMAL; /// Not M_TRACKING !!!! + kp_help_text = "Frequency of signal"; + ui_mode_keypad(KM_CENTER); + set_marker_frequency(0, uistat.value); +#ifdef TINYSA4 + kp_help_text = "Modulation frequency: 500Hz .. 10kHz"; + ui_mode_keypad(KM_SPAN); + if (uistat.value < 500 || uistat.value > 10000) + goto no_measurement; + set_RBW(uistat.value/300); +#else + kp_help_text = "Modulation frequency: 1 .. 2.5kHz"; + ui_mode_keypad(KM_SPAN); + if (uistat.value < 1000 || uistat.value > 2500) + goto no_measurement; + set_RBW(uistat.value/100); +#endif + // actual_rbw_x10 +#ifdef TINYSA4 + kp_help_text = "Frequency deviation: 3 .. 500kHz"; +#define MINIMUM_DEVIATION 1500 +#else + kp_help_text = "Frequency deviation: 500Hz .. 500kHz"; +#define MINIMUM_DEVIATION 12000 +#endif + ui_mode_keypad(KM_SPAN); + if (uistat.value < MINIMUM_DEVIATION) + uistat.value = MINIMUM_DEVIATION; // minimum span + set_sweep_frequency(ST_SPAN, uistat.value*4); +// set_measurement(M_FM); + break; + case M_THD: + set_average(0,AV_4); +// set_measurement(M_THD); + break; +#ifdef __CHANNEL_POWER__ + case M_CP: // channel power + reset_settings(setting.mode); + markers[0].enabled = M_DISABLED; + kp_help_text = "Channel frequency"; + ui_mode_keypad(KM_CENTER); + kp_help_text = "Channel width"; + ui_mode_keypad(KM_SPAN); + set_sweep_frequency(ST_SPAN, uistat.value*3); +// set_measurement(M_CP); + break; +#endif +#ifdef __NOISE_FIGURE__ + case M_NF_TINYSA: + reset_settings(setting.mode); + set_refer_output(-1); + nf_gain = 0; + goto noise_figure; + case M_NF_STORE: + if (measured_noise_figure > 2 && measured_noise_figure < 20) { + config.noise_figure = measured_noise_figure; + config_save(); + data = M_NF_VALIDATE; // Continue to validate + goto validate; + } else { + drawMessageBox("Error", "NF out of range",1000); + data = M_NF_TINYSA; // Continue to measure + } + break; + case M_NF_VALIDATE: +validate: + nf_gain = 0.00001; // almost zero + goto noise_figure; + case M_NF_AMPLIFIER: // noise figure +#if 0 + reset_settings(setting.mode); + set_refer_output(-1); +#endif + kp_help_text = "Amplifier Gain "; + float old_gain = setting.external_gain; + ui_mode_keypad(KM_EXT_GAIN); + nf_gain = setting.external_gain; + setting.external_gain = old_gain; + noise_figure: + markers[0].enabled = M_ENABLED; + markers[0].mtype = M_NOISE | M_AVER; // Not tracking + set_extra_lna(true); + set_attenuation(0); + if (data == M_NF_TINYSA) { + kp_help_text = "Noise center frequency"; + ui_mode_keypad(KM_CENTER); + set_marker_frequency(0, uistat.value); +#if 0 + kp_help_text = "Noise span"; + ui_mode_keypad(KM_SPAN); +#else + set_sweep_frequency(ST_SPAN, 100000); +#endif + set_RBW(1000); // 300kHz + } + +// set_sweep_frequency(ST_SPAN, 0); + set_average(0,AV_100); + if (data == M_NF_TINYSA || data == M_NF_VALIDATE ) { + menu_push_submenu(menu_measure_noise_figure); + goto leave; + } + break; +#endif +#ifdef __FFT_DECONV__ + case M_DECONV: + set_average(0,AV_DECONV); + break; +#endif + } + +// selection = -1; + ui_mode_normal(); + goto leave; // to get rid of warning +leave: + set_measurement(data); +// draw_cal_status(); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_atten_acb) +{ + (void)item; + (void)data; + if(b){ + if (MODE_HIGH(setting.mode)) { + b->param_1.text = "0dB"; + b->icon = (setting.atten_step*30 == data) ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + } + else { + b->param_1.text = "AUTO"; + b->icon = setting.auto_attenuation ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + } + return; + } + if (MODE_HIGH(setting.mode)) { + setting.auto_attenuation = false; + set_attenuation(0); + } else + set_auto_attenuation(); + menu_move_back(true); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_atten_high_acb) +{ + (void)item; + if(b){ + b->icon = (setting.atten_step*30 == data) ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + return; + } + setting.auto_attenuation = false; + set_attenuation(data); + menu_move_back(true); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_reflevel_acb) +{ + (void)item; + (void)data; + if(b){ + b->icon = setting.auto_reflevel ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + return; + } + set_auto_reflevel(true); + menu_move_back(true); +} + +static uint8_t current_trace = TRACE_ACTUAL; + +static UI_FUNCTION_ADV_CALLBACK(menu_average_acb) +{ + (void)item; + if (b){ + b->icon = setting.average[current_trace] == data ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + return; + } + set_average(current_trace,data); + if (data == AV_TABLE) + menu_push_submenu(menu_limit_select); + else { + ui_mode_normal(); + } +// menu_move_back(true); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_trace_acb) +{ + (void)item; + if(b){ + b->param_1.i = data+1; + b->icon = (data == current_trace) ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + b->bg = LCD_TRACE_1_COLOR+data; + return; + } + if (setting.normalized_trace != -1 && data == TRACE_TEMP) { + drawMessageBox("Error", "Disable normalization first", 2000); + redraw_request|= REDRAW_AREA; + } else + current_trace = data; + menu_move_back(false); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_marker_trace_acb) +{ + (void)item; + if(b){ + b->param_1.i = data+1; + b->icon = (data == markers[active_marker].trace) ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + b->bg = LCD_TRACE_1_COLOR+data; + return; + } + markers[active_marker].trace = data; + menu_move_back(false); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_store_trace_acb) +{ + (void)item; + if(b){ + plot_printf(b->text, sizeof(b->text), S_RARROW"TRACE %d", data+1); + b->bg = LCD_TRACE_1_COLOR+data; + if (current_trace == data) + b->fg = LCD_DARK_GREY; + return; + } + store_trace(current_trace,data); + menu_move_back(false); +} + + +static UI_FUNCTION_ADV_CALLBACK(menu_subtract_trace_acb) +{ + (void)item; + if(b){ + if (data) { + plot_printf(b->text, sizeof(b->text), "SUBTRACT\nTRACE %d", data); + b->bg = LCD_TRACE_1_COLOR+data-1; + } + else + plot_printf(b->text, sizeof(b->text), "SUBTRACT\nOFF"); + b->icon = (data == setting.subtract[current_trace]) ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + if (data - 1 == current_trace) + b->fg = LCD_DARK_GREY; + return; + } + subtract_trace(current_trace,data-1); + menu_move_back(false); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_traces_acb) +{ + (void)item; + int count = 0; + if(b){ + if (data == 0) { // Select trace + b->param_1.i = current_trace+1; + b->bg = LCD_TRACE_1_COLOR+current_trace; + } else if (data == 1) { // View + b->icon = IS_TRACE_ENABLE(current_trace) ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + } + else if (data == 2) // freeze + b->icon = setting.stored[current_trace] ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + else if (data == 5) { + if (setting.subtract[current_trace]) { + b->icon = BUTTON_ICON_CHECK; + plot_printf(b->text, sizeof(b->text), "SUBTRACT\nTRACE %d", setting.subtract[current_trace]); + } else { + b->icon = BUTTON_ICON_NOCHECK; + plot_printf(b->text, sizeof(b->text), "SUBTRACT\nOFF"); + } + // b->icon = setting.subtract[current_trace] ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; // icon not needed + } else if (data == 4) { + if (current_trace == TRACES_MAX-1) + b->fg = LCD_DARK_GREY; + else + b->icon = setting.normalized[current_trace] ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + } else if (data == 3) { + b->icon = setting.average[current_trace] != AV_OFF ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + plot_printf(b->text, sizeof(b->text), "CALC\n%s", averageText[setting.average[current_trace]]); + // b->icon = setting.average[current_trace] ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; // icon not needed + } + return; + } + switch(data) { + case 0: + menu_push_submenu(menu_trace); + return; + case 1: + for (int i=0;i 1) { // Always 1 trace enabled + TRACE_DISABLE(1<icon = BUTTON_ICON_CHECK; + if (setting.subtract[0]){ + if (data == 2 && setting.show_stored) + b->icon = BUTTON_ICON_CHECK; + if (data == 3 && !setting.show_stored) + b->icon = BUTTON_ICON_CHECK; + } + return; + } + switch(data) { + case 0: + store_trace(0,2); + break; + case 1: + set_clear_storage(); + break; + case 2: + set_subtract_storage(); + break; + case 3: + toggle_normalize(); + if (setting.subtract[0]) { + kp_help_text = "Ref level"; + ui_mode_keypad(KM_REFLEVEL); +// setting.normalize_level = uistat.value; + } else + set_auto_reflevel(true); + break; +#ifdef TINYSA4 + case 4: + save_to_sd(1+2); // frequencies + actual + break; + case 5: + save_to_sd(1+4); // frequencies + stored + break; +#endif + } + ui_mode_normal(); +// draw_cal_status(); +} +#endif + +static UI_FUNCTION_ADV_CALLBACK(menu_waterfall_acb){ + (void)item; + (void)data; + if (b){ +#ifdef TINYSA4 + if (!(sweep_mode & SWEEP_ENABLE)){ + b->icon = (sweep_mode & SWEEP_ONCE) ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + plot_printf(b->text, sizeof(b->text), "SINGLE\nSWEEP"); + } else { + b->icon = setting.waterfall ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + plot_printf(b->text, sizeof(b->text), "WATER\nFALL"); + } +#else + b->icon = setting.waterfall ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + plot_printf(b->text, sizeof(b->text), "WATER\nFALL"); +#endif + return; + } +#ifdef TINYSA4 + if (is_paused()) { + resume_once(1); + } else +#endif + { + setting.waterfall++; if (setting.waterfall>W_BIG)setting.waterfall = W_OFF; + if (setting.waterfall != W_OFF) + setting.level_meter = false; + set_waterfall(); + ui_mode_normal(); + } +} + +#ifdef __LEVEL_METER__ +static UI_FUNCTION_ADV_CALLBACK(menu_level_meter_acb){ + (void)item; + (void)data; + if (b){ + b->icon = setting.level_meter ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + return; + } + setting.level_meter = !setting.level_meter; + if (setting.level_meter) + setting.waterfall = W_OFF; + set_level_meter(); + ui_mode_normal(); +} +#endif + + +#ifdef __LIMITS__ +uint8_t active_limit = 0; +static UI_FUNCTION_ADV_CALLBACK(menu_limit_select_acb) +{ + (void)item; + if(b){ + int count = 0; + for (int i=0;iicon = (setting.limits[current_trace][data].enabled?BUTTON_ICON_CHECK:BUTTON_ICON_NOCHECK) ; + plot_printf(b->text, sizeof(b->text), "%.6FHz\n%.2F%s", (float)setting.limits[current_trace][data].frequency, value(setting.limits[current_trace][data].level),unit_string[setting.unit]); + return; + } + active_limit = data; + setting.limits[current_trace][active_limit].enabled = true; + dirty = true; + limits_update(); + menu_push_submenu(menu_limit_modify); +} + +#endif + +extern const menuitem_t menu_marker_select[]; + +static UI_FUNCTION_ADV_CALLBACK(menu_marker_modify_acb) +{ + (void)item; + if (active_marker == MARKER_INVALID) return; + if(b){ + uistat.text[0] = 0; + uistat.text[1] = 0; + switch(data) { + case 0: + uistat.text[0] = active_marker+'1'; + break; + case M_DELTA: + uistat.text[0] = markers[active_marker].ref+'1'; + /* fall through */ + case M_NOISE: + case M_TRACKING: + case M_AVER: + b->icon = BUTTON_ICON_NOCHECK; + if (markers[active_marker].mtype & data) + b->icon = BUTTON_ICON_CHECK; + break; + case M_STORED: + uistat.text[0] = markers[active_marker].trace+'1'; + b->bg = LCD_TRACE_1_COLOR+markers[active_marker].trace; + break; + } + b->param_1.text = uistat.text; + return; + } + if (data == M_DELTA && !(markers[active_marker].mtype & M_DELTA)) { // Not yet set + menu_push_submenu(menu_marker_ref_select); + goto set_delta; + return; + } else if (data == M_STORED) { + current_trace = 0; + menu_push_submenu(menu_marker_trace); + return; + } else if (markers[active_marker].mtype & data) + markers[active_marker].mtype &= ~data; + else if (data) { + set_delta: + markers[active_marker].mtype |= data; + } else + menu_push_submenu(menu_marker_select); + markmap_all_markers(); +// redraw_marker(active_marker, TRUE); +// menu_move_back(false); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_marker_ref_select_acb) +{ + (void)item; + if(b){ +// b->icon = markers[data-1].enabled ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + b->icon = (markers[active_marker].ref == data-1 ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP ); + b->param_1.i = data; + return; + } + markers[data-1].enabled = true; +// interpolate_maximum(data-1); // possibly not a maximum + set_marker_index(data-1, markers[data-1].index); + markers[active_marker].ref = data-1; + redraw_marker(active_marker); + menu_move_back(false); +} + +extern const menuitem_t menu_marker_modify[]; +static UI_FUNCTION_ADV_CALLBACK(menu_marker_select_acb) +{ + (void)item; + if(b){ + b->icon = markers[data-1].enabled ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + b->param_1.i = data; + return; + } + markers[data-1].enabled = true; +// interpolate_maximum(data-1); // possibly not a maximum + set_marker_index(data-1, markers[data-1].index); + active_marker_select(data-1); +// menu_push_submenu(menu_marker_modify); + redraw_marker(active_marker); + menu_move_back(false); +} + +static UI_FUNCTION_CALLBACK(menu_marker_delete_cb) +{ + (void)item; + (void)data; + if (active_marker>=0){ + for (int i = 0; iparam_1.text = rbwsel_text[data]; +#else + b->param_1.u = rbwsel_x10[data]/10; +#endif + b->icon = setting.rbw_x10 == rbwsel_x10[data] ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + return; + } + set_RBW(rbwsel_x10[data]); + menu_move_back(true); +} + +#ifdef __VBW__ +static UI_FUNCTION_ADV_CALLBACK(menu_vbw_acb) +{ + (void)item; + if (b){ + b->param_1.f = vbwsel_x100[data] > 0 ? 1.0f/vbwsel_x100[data] : 0; + b->icon = setting.vbw_x100 == vbwsel_x100[data] ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + return; + } + set_VBW(vbwsel_x100[data]); + menu_move_back(true); +} + +#endif + +static UI_FUNCTION_ADV_CALLBACK(menu_unit_acb) +{ + (void)item; + if (b){ + b->icon = data == setting.unit ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + return; + } + set_unit(data); + menu_move_back(true); +} + +#if 0 +enum { + S_20,S_10,S_5,S_2,S_1,S_P5,S_P2,S_P1,S_P05,S_P02,S_P01 +}; +static const float menu_scale_per_value[11]={20,10,5,2,1,0.5,0.2,0.1,0.05,0.02,0.01}; + +static UI_FUNCTION_ADV_CALLBACK(menu_scale_per_acb) +{ + (void)item; + if(b){ + return; + } + set_scale(menu_scale_per_value[data]); + menu_move_back(true); +} +#endif + +const char *mode_text[] = {"PRE","POST","MID"}; + +static UI_FUNCTION_ADV_CALLBACK(menu_trigger_acb) +{ + (void)item; + if(b){ + if (data == T_MODE) { + b->param_1.text = mode_text[setting.trigger_mode - T_PRE]; + } else if (data == T_UP || data == T_DOWN) + b->icon = setting.trigger_direction == data ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + else + b->icon = setting.trigger == data ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + return; + } + if (data == T_MODE) { + setting.trigger_mode += 1; + if (setting.trigger_mode > T_MID) + setting.trigger_mode = T_PRE; + set_trigger(setting.trigger_mode); + } else if (data != T_DONE) { + set_trigger(data); +// menu_move_back(false); + ui_mode_normal(); + } + completed = true; +} + +#if 0 +static void choose_active_trace(void) +{ + int i; + if (trace[uistat.current_trace].enabled) + // do nothing + return; + for (i = 0; i < TRACE_COUNT ; i++) + if (trace[i].enabled) { + uistat.current_trace = i; + return; + } +} +#endif +static void choose_active_marker(void) +{ + int i; + for (i = 0; i < MARKER_COUNT; i++) + if (markers[i].enabled == M_ENABLED) { + active_marker = i; + return; + } + active_marker = MARKER_INVALID; +} +#ifdef TINYSA4 +#define __HARMONIC__ +#endif + +#ifdef __HARMONIC__ +static UI_FUNCTION_ADV_CALLBACK(menu_harmonic_acb) +{ + (void)item; + if(b){ + b->icon = setting.harmonic == data ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + return; + } + set_harmonic(data); +} +#endif + + +static UI_FUNCTION_ADV_CALLBACK(menu_settings_agc_acb){ + (void)item; + (void)data; + if(b){ + b->icon = AUTO_ICON(setting.agc); + return; + } + toggle_AGC(); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_settings_lna_acb){ + (void)item; + (void)data; + if(b){ + if (S_IS_AUTO(setting.lna)) + b->icon = BUTTON_ICON_CHECK_AUTO; + else + b->icon = setting.lna ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + return; + } + toggle_LNA(); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_settings_bpf_acb){ + (void)item; + (void)data; + if(b){ + b->icon = setting.tracking ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + return; + } + toggle_tracking(); +} + +#ifdef __LCD_BRIGHTNESS__ +static UI_FUNCTION_CALLBACK(menu_brightness_cb) +{ + (void)item; + (void)data; + int16_t value = config._brightness; + ili9341_set_foreground(LCD_MENU_TEXT_COLOR); + ili9341_set_background(LCD_MENU_COLOR); + ili9341_fill(LCD_WIDTH/2-80, LCD_HEIGHT/2-20, 160, 40); + ili9341_drawstring_7x13("BRIGHTNESS", LCD_WIDTH/2-35, LCD_HEIGHT/2-13); + ili9341_drawstring_7x13(S_LARROW" USE LEVELER BUTTON "S_RARROW, LCD_WIDTH/2-72, LCD_HEIGHT/2+2); + while (TRUE) { + int status = btn_check(); + if (status & (EVT_UP|EVT_DOWN)) { + do { + if (status & EVT_UP ) value+=5; + if (status & EVT_DOWN) value-=5; + if (value < 0) value = 0; + if (value > 100) value = 100; + lcd_setBrightness(value); + status = btn_wait_release(); + } while (status != 0); + } + if (status == EVT_BUTTON_SINGLE_CLICK) + break; + } + config._brightness = (uint8_t)value; + lcd_setBrightness(value); + redraw_request|= REDRAW_AREA; + ui_mode_normal(); +} +#endif + +static UI_FUNCTION_ADV_CALLBACK(menu_settings_pulse_acb){ + (void)item; + (void)data; + if(b){ + b->icon = setting.pulse ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + return; + } + toggle_pulse(); +} + +#ifdef __DRAW_LINE__ +static UI_FUNCTION_ADV_CALLBACK(menu_settings_draw_line_acb){ + (void)item; + (void)data; + if(b){ + b->icon = setting.draw_line ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + return; + } + toggle_draw_line(); + if (setting.draw_line) { + kp_help_text = "Level"; + ui_mode_keypad(KM_TRIGGER); + set_trigger(T_AUTO); + } +} +#endif +#ifdef __HAM_BAND__ +static UI_FUNCTION_ADV_CALLBACK(menu_settings_ham_bands){ + (void)item; + (void)data; + if(b){ + b->icon = config.hambands ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + return; + } + toggle_hambands(); +} +#endif + +static UI_FUNCTION_ADV_CALLBACK(menu_settings_below_if_acb){ + (void)item; + (void)data; + if(b){ + if (S_IS_AUTO(setting.below_IF)) + b->icon = BUTTON_ICON_CHECK_AUTO; + else + b->icon = setting.below_IF ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + return; + } + toggle_below_IF(); +} + +#if 0 +static UI_FUNCTION_ADV_CALLBACK(menu_settings_ultra_acb){ + (void)item; + (void)data; + if(b){ + if (S_IS_AUTO(setting.ultra)) + b->icon = BUTTON_ICON_CHECK_AUTO; + else + b->icon = setting.ultra ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + return; + } + toggle_ultra(); +} +#endif + +static UI_FUNCTION_ADV_CALLBACK(menu_lo_output_acb){ + (void)item; + (void)data; + if(b){ + b->icon = setting.tracking_output ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + return; + } + toggle_tracking_output(); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_pause_acb) +{ + (void) data; + (void) item; + if (b){ + b->icon = !(sweep_mode & SWEEP_ENABLE) ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + return; + } + toggle_sweep(); +// menu_move_back(true); +// draw_cal_status(); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_flip_acb) +{ + (void) data; + (void) item; + if (b){ + return; + } + config.flip = ! config.flip; + ili9341_flip(config.flip); + config_save(); + redraw_request|= REDRAW_AREA | REDRAW_FREQUENCY | REDRAW_CAL_STATUS; +} + +static UI_FUNCTION_ADV_CALLBACK(menu_shift_acb) +{ + (void) data; + (void) item; + if (b){ + b->icon = setting.frequency_offset != FREQUENCY_SHIFT ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + return; + } + if (setting.frequency_offset != FREQUENCY_SHIFT) { + setting.frequency_offset = FREQUENCY_SHIFT; + } else { + if (FREQ_IS_STARTSTOP()) { + freq_t old_start = get_sweep_frequency(ST_START); + freq_t old_stop = get_sweep_frequency(ST_STOP); + kp_help_text = "Actual start frequency"; + ui_mode_keypad(KM_START); + setting.frequency_offset = uistat.value - old_start + FREQUENCY_SHIFT; + set_sweep_frequency(ST_START, old_start); + set_sweep_frequency(ST_STOP, old_stop); + } else { + freq_t old_center = get_sweep_frequency(ST_CENTER); + freq_t old_span = get_sweep_frequency(ST_SPAN); + kp_help_text = "Actual center frequency"; + ui_mode_keypad(KM_CENTER); + setting.frequency_offset = uistat.value - old_center + FREQUENCY_SHIFT; + set_sweep_frequency(ST_CENTER, old_center); + set_sweep_frequency(ST_SPAN, old_span); + } + } + ui_mode_normal(); +// menu_move_back(true); +// draw_cal_status(); +} + +#ifdef __REMOTE_DESKTOP__ +#if 0 // Not used in UI +static UI_FUNCTION_ADV_CALLBACK(menu_send_display_acb) +{ + (void) data; + (void) item; + if (b){ + b->icon = auto_capture ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; + return; + } + auto_capture = ! auto_capture; + // Update all screen to CPU + if (auto_capture) + redraw_request|=REDRAW_AREA|REDRAW_BATTERY|REDRAW_FREQUENCY|REDRAW_CAL_STATUS; +} +#endif +#endif + +static UI_FUNCTION_ADV_CALLBACK(menu_outputmode_acb) +{ + (void) data; + (void) item; + if(b){ + b->param_1.text = setting.mute ? "OFF" : "ON"; + return; + } + toggle_mute(); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_enter_marker_acb) +{ + (void) data; + (void) item; + if(b){ + b->param_1.text = FREQ_IS_CW() ? "TIME" : "FREQUENCY"; + return; + } + if (FREQ_IS_CW()) + ui_mode_keypad(KM_MARKER_TIME); + else + ui_mode_keypad(KM_MARKER); +} + +#ifdef TINYSA4 +static const uint16_t points_setting[] = {51, 101, 201, 256, 290, 450}; +#else +static const uint16_t points_setting[] = {51, 101, 145, 290}; +#endif +static UI_FUNCTION_ADV_CALLBACK(menu_points_acb){ + (void)item; + if(b){ + b->icon = points_setting[data] == sweep_points ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + b->param_1.i = points_setting[data]; + return; + } + set_sweep_points(points_setting[data]); +} + +#ifdef __USE_SERIAL_CONSOLE__ +static UI_FUNCTION_ADV_CALLBACK(menu_serial_speed_acb) +{ + static const uint32_t usart_speed[] = {19200, 38400, 57600, 115200, 230400, 460800, 921600, 1843200, 2000000, 3000000}; + (void)item; + uint32_t speed = usart_speed[data]; + if (b){ + b->icon = config._serial_speed == speed ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + b->param_1.u = speed; + return; + } + config._serial_speed = speed; + shell_update_speed(); +} + +static UI_FUNCTION_ADV_CALLBACK(menu_connection_acb) +{ + (void)item; + if (b){ + b->icon = (config._mode&_MODE_CONNECTION_MASK) == data ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; + return; + } + config._mode&=~_MODE_CONNECTION_MASK; + config._mode|=data; + config_save(); + shell_reset_console(); +} +#endif +// ===[MENU DEFINITION]========================================================= +// Back button submenu list + +static const menuitem_t menu_back[] = { + { MT_CANCEL, 0, S_LARROW" BACK", NULL }, + { MT_NONE, 0, NULL, NULL } // sentinel +}; + +static const menuitem_t menu_store_preset[] = +{ + { MT_ADV_CALLBACK, 0, "STORE AS\nSTARTUP",menu_store_preset_acb}, + { MT_ADV_CALLBACK |MT_REPEATS, DATA_STARTS_REPEATS(1,4), "STORE %d", menu_store_preset_acb}, + { MT_ADV_CALLBACK, 100,"FACTORY\nDEFAULTS",menu_store_preset_acb}, + { MT_NONE, 0, NULL,menu_back} // next-> menu_back +}; + +static const menuitem_t menu_load_preset[] = +{ + { MT_ADV_CALLBACK, 0, "LOAD\nSTARTUP", menu_load_preset_acb}, + { MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(1,4), MT_CUSTOM_LABEL, menu_load_preset_acb}, + { MT_SUBMENU, 0, "STORE" , menu_store_preset}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; +#ifdef TINYSA4 +static const menuitem_t menu_mixer_drive[] = { + { MT_ADV_CALLBACK, 4, "Auto", menu_mixer_drive_acb}, + { MT_ADV_CALLBACK, 3, "%+ddBm", menu_mixer_drive_acb}, + { MT_ADV_CALLBACK, 2, "%+ddBm", menu_mixer_drive_acb}, + { MT_ADV_CALLBACK, 1, "%+ddBm", menu_mixer_drive_acb}, + { MT_ADV_CALLBACK, 0, "%+ddBm", menu_mixer_drive_acb}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; +#else +static const menuitem_t menu_lo_drive[] = { + { MT_ADV_CALLBACK, 15, "%+ddBm", menu_lo_drive_acb}, + { MT_ADV_CALLBACK, 14, "%+ddBm", menu_lo_drive_acb}, + { MT_ADV_CALLBACK, 13, "%+ddBm", menu_lo_drive_acb}, + { MT_ADV_CALLBACK, 12, "%+ddBm", menu_lo_drive_acb}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; +#endif + +static const menuitem_t menu_modulation[] = { + { MT_FORM | MT_TITLE, 0, "MODULATION",NULL}, + { MT_FORM | MT_ADV_CALLBACK, MO_NONE, MT_CUSTOM_LABEL, menu_modulation_acb}, + { MT_FORM | MT_ADV_CALLBACK | MT_LOW, MO_AM, "AM", menu_modulation_acb}, +#ifdef TINYSA4 + { MT_FORM | MT_ADV_CALLBACK, MO_WFM, "FM", menu_modulation_acb}, + { MT_FORM | MT_KEYPAD, KM_MODULATION, "FREQ: %s", "50Hz..5kHz"}, + { MT_FORM | MT_KEYPAD, KM_DEPTH, "AM DEPTH: %s%%", "0..100"}, + { MT_FORM | MT_KEYPAD, KM_DEVIATION, "FM DEVIATION: %s", "1kHz..300kHz"}, +// { MT_FORM | MT_ADV_CALLBACK, MO_NFM2, MT_CUSTOM_LABEL, menu_modulation_acb}, +// { MT_FORM | MT_ADV_CALLBACK, MO_NFM3, MT_CUSTOM_LABEL, menu_modulation_acb}, +#else + { MT_FORM | MT_ADV_CALLBACK, MO_NFM, MT_CUSTOM_LABEL, menu_modulation_acb}, + { MT_FORM | MT_ADV_CALLBACK, MO_WFM, MT_CUSTOM_LABEL, menu_modulation_acb}, + { MT_FORM | MT_ADV_CALLBACK | MT_LOW, MO_EXTERNAL,MT_CUSTOM_LABEL, menu_modulation_acb}, + { MT_FORM | MT_KEYPAD, KM_MODULATION, "FREQ: %s", "50Hz..5kHz"}, +#endif + { MT_FORM | MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_sweep[] = { + { MT_FORM | MT_KEYPAD, KM_SPAN, "SPAN: %s", VARIANT("0..350MHz", range_text)}, + { MT_FORM | MT_KEYPAD | MT_LOW, KM_LEVELSWEEP,"LEVEL CHANGE: %s", VARIANT("-70..70","-90..90")}, + { MT_FORM | MT_KEYPAD, KM_SWEEP_TIME, "SWEEP TIME: %s", "0..600 seconds"}, + { MT_FORM | MT_SUBMENU, 0, "SWEEP POINTS", menu_sweep_points_form}, + { MT_FORM | MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; +#ifdef TINYSA4 +static const menuitem_t menu_lowoutput_settings[] = { + { MT_FORM | MT_ADV_CALLBACK, 0, "Cleanest signal, max 4.4GHz", menu_lowoutput_settings_acb}, + { MT_FORM | MT_ADV_CALLBACK, 1, "Highest accuracy, max 5.4GHz", menu_lowoutput_settings_acb}, + { MT_FORM | MT_SUBMENU, 255, S_RARROW"Config", menu_config}, + { MT_FORM | MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; +#endif + +char low_level_help_text[12] = "-76..-6"; +char center_text[18] = "FREQ: %s"; + +const menuitem_t menu_lowoutputmode[] = { + { MT_FORM | MT_ADV_CALLBACK, 0, "LOW OUTPUT %s", menu_outputmode_acb}, +// { MT_FORM | MT_ADV_CALLBACK, 0, "MOD: %s", menu_smodulation_acb}, + { MT_FORM | MT_KEYPAD, KM_CENTER, center_text, VARIANT("10kHz..350MHz","10kHz..850MHz")}, + { MT_FORM | MT_KEYPAD, KM_LOWOUTLEVEL, "LEVEL: %s", low_level_help_text}, + { MT_FORM | MT_ADV_CALLBACK, 0, MT_CUSTOM_LABEL, menu_smodulation_acb}, + { MT_FORM | MT_ADV_CALLBACK, 0, MT_CUSTOM_LABEL, menu_sweep_acb}, +#ifdef __SWEEP_RESTART__ + { MT_FORM | MT_ADV_CALLBACK, 0, MT_CUSTOM_LABEL, menu_restart_acb}, +#endif + { MT_FORM | MT_KEYPAD, KM_EXT_GAIN, "EXTERNAL GAIN: %s", "-100..+100"}, +#ifdef TINYSA4 + { MT_FORM | MT_ADV_CALLBACK, 255, "OUTPUT: %s", menu_lowoutput_settings_acb}, +#endif + { MT_FORM | MT_CANCEL, 0, "MODE", NULL }, + { MT_FORM | MT_NONE, 0, NULL, NULL } // sentinel +}; + +const menuitem_t menu_highoutputmode[] = { + { MT_FORM | MT_ADV_CALLBACK, 0, "HIGH OUTPUT %s", menu_outputmode_acb}, + { MT_FORM | MT_KEYPAD, KM_CENTER, center_text, VARIANT("240MHz..959MHz",range_text)}, + { MT_FORM | MT_KEYPAD, KM_HIGHOUTLEVEL, "LEVEL: %s", low_level_help_text /* "-76..-6" */}, + { MT_FORM | MT_ADV_CALLBACK, 0, MT_CUSTOM_LABEL, menu_smodulation_acb}, + { MT_FORM | MT_ADV_CALLBACK, 0, MT_CUSTOM_LABEL, menu_sweep_acb}, +#ifdef __SWEEP_RESTART__ + { MT_FORM | MT_ADV_CALLBACK, 0, MT_CUSTOM_LABEL, menu_restart_acb}, +#endif + { MT_FORM | MT_KEYPAD, KM_EXT_GAIN, "EXTERNAL GAIN: %s", "-100..+100"}, +#ifdef TINYSA4 + { MT_FORM | MT_SUBMENU, 255, S_RARROW" Settings", menu_settings3}, +#endif + { MT_FORM | MT_CANCEL, 0, "MODE", NULL }, + { MT_FORM | MT_NONE, 0, NULL, NULL } // sentinel +}; + +static const menuitem_t menu_average[] = { + { MT_ADV_CALLBACK, AV_OFF, "OFF", menu_average_acb}, + { MT_ADV_CALLBACK, AV_MIN, "MIN\nHOLD", menu_average_acb}, + { MT_ADV_CALLBACK, AV_MAX_HOLD, "MAX\nHOLD", menu_average_acb}, + { MT_ADV_CALLBACK, AV_MAX_DECAY, "MAX\nDECAY", menu_average_acb}, + { MT_ADV_CALLBACK, AV_4, "AVER 4", menu_average_acb}, + { MT_ADV_CALLBACK, AV_16, "AVER 16", menu_average_acb}, +#ifdef TINYSA4 + { MT_ADV_CALLBACK, AV_100, "AVER", menu_average_acb}, +#endif +#ifdef __QUASI_PEAK__ + { MT_ADV_CALLBACK, AV_QUASI, "QUASI\nPEAK", menu_average_acb}, +#endif +#ifdef __LIMITS__ + { MT_ADV_CALLBACK, AV_TABLE, "TABLE"S_RARROW"\nTRACE", menu_average_acb}, +#endif + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_rbw[] = { + { MT_ADV_CALLBACK, 0, " AUTO", menu_rbw_acb}, +#ifdef TINYSA4 + { MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(1,9), "%sHz", menu_rbw_acb}, +#else + { MT_ADV_CALLBACK | MT_REPEATS, DATA_STARTS_REPEATS(1,6), "%4dkHz", menu_rbw_acb}, +#endif + { MT_NONE, 0, NULL, menu_back} // next-> menu_back + +}; + +#ifdef __VBW__ +static const menuitem_t menu_vbw[] = { + { MT_ADV_CALLBACK, 0, " AUTO", menu_vbw_acb}, + { MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(1,5), "%b.2f RBW", menu_vbw_acb}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; +#endif + +static const menuitem_t menu_reffer[] = { + { MT_FORM | MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(0,8), "%s", menu_reffer_acb}, + { MT_FORM | MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_atten[] = { + { MT_ADV_CALLBACK, 0, "%s", menu_atten_acb}, + { MT_KEYPAD | MT_LOW, KM_ATTENUATION, "MANUAL\n\b%s", "0 - 30dB"}, +// { MT_ADV_CALLBACK | MT_HIGH,0, "0dB", menu_atten_high_acb}, + { MT_ADV_CALLBACK | MT_HIGH,30, "22.5 - 40dB", menu_atten_high_acb}, + { MT_FORM | MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_reflevel[] = { + { MT_ADV_CALLBACK,0, "AUTO", menu_reflevel_acb}, + { MT_KEYPAD, KM_REFLEVEL, "MANUAL\n\b%s", NULL}, + { MT_CANCEL, 0, S_LARROW" BACK", NULL }, + { MT_NONE, 0, NULL, NULL } // sentinel +}; + +const menuitem_t menu_marker_search[] = { + { MT_CALLBACK, 4, "PEAK\n SEARCH", menu_marker_search_cb }, + { MT_CALLBACK, 0, "MIN\n" S_LARROW" LEFT", menu_marker_search_cb }, + { MT_CALLBACK, 1, "MIN\n" S_RARROW" RIGHT", menu_marker_search_cb }, + { MT_CALLBACK, 2, "MAX\n" S_LARROW" LEFT", menu_marker_search_cb }, + { MT_CALLBACK, 3, "MAX\n" S_RARROW" RIGHT", menu_marker_search_cb }, + { MT_ADV_CALLBACK, 0, "ENTER\n%s", menu_enter_marker_acb}, + { MT_ADV_CALLBACK, M_TRACKING, "TRACKING",menu_marker_modify_acb }, +#ifdef TINYSA4 + { MT_KEYPAD, KM_NOISE, "PEAK\n\b%s", "2..20 dB"}, +#endif + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +const menuitem_t menu_marker_modify[] = { + { MT_ADV_CALLBACK, 0, "MARKER %s", menu_marker_modify_acb}, + { MT_ADV_CALLBACK, M_DELTA, "DELTA %s", menu_marker_modify_acb}, + { MT_ADV_CALLBACK, M_NOISE, "NOISE", menu_marker_modify_acb}, + { MT_ADV_CALLBACK, M_TRACKING, "TRACKING", menu_marker_modify_acb}, + { MT_ADV_CALLBACK, M_STORED, "TRACE %s", menu_marker_modify_acb}, + { MT_ADV_CALLBACK, M_AVER, "TRACE\nAVERAGE", menu_marker_modify_acb}, + { MT_SUBMENU, 0, "SEARCH", menu_marker_search}, + { MT_CALLBACK, M_DELETE, "DELETE", menu_marker_delete_cb}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +#ifdef __LIMITS__ +static const menuitem_t menu_limit_modify[] = +{ + { MT_KEYPAD, KM_LIMIT_FREQ, "FREQUENCY\n\b%s", "Frequency"}, + { MT_KEYPAD, KM_LIMIT_LEVEL, "LEVEL\n\b%s", "Level"}, + { MT_CALLBACK, 0, "DISABLE", menu_limit_disable_cb}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_limit_select[] = { + { MT_ADV_CALLBACK | MT_REPEATS, DATA_STARTS_REPEATS(0,LIMITS_MAX), MT_CUSTOM_LABEL, menu_limit_select_acb }, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; +#endif + +#if 0 +const menuitem_t menu_marker_sel[] = { + { MT_CALLBACK, 1, "MARKER %d", menu_marker_sel_cb }, + { MT_CALLBACK, 2, "MARKER %d", menu_marker_sel_cb }, + { MT_CALLBACK, 3, "MARKER %d", menu_marker_sel_cb }, + { MT_CALLBACK, 4, "MARKER %d", menu_marker_sel_cb }, +// { MT_CALLBACK, 0, "ALL OFF", menu_marker_sel_cb }, + { MT_CALLBACK, 0, "DELTA", menu_marker_sel_cb }, + { MT_CALLBACK, 0, "NOISE", menu_marker_sel_cb }, + { MT_CALLBACK, 0, "TRACKING", menu_marker_sel_cb }, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; +#endif + +const menuitem_t menu_marker_select[] = { + { MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(1,MARKER_COUNT), "MARKER %d", menu_marker_select_acb }, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_marker_ref_select[] = { + { MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(1,MARKER_COUNT), S_RARROW"MARKER %d", menu_marker_ref_select_acb }, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +const menuitem_t menu_marker_ops[] = { + { MT_CALLBACK, ST_START, S_RARROW" START", menu_marker_op_cb }, + { MT_CALLBACK, ST_STOP, S_RARROW" STOP", menu_marker_op_cb }, + { MT_CALLBACK, ST_CENTER, S_RARROW" CENTER", menu_marker_op_cb }, + { MT_CALLBACK, ST_SPAN, S_RARROW" SPAN", menu_marker_op_cb }, + { MT_CALLBACK, 4, S_RARROW" REF LEVEL",menu_marker_op_cb }, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_marker[] = { +// { MT_SUBMENU, 0, "SELECT\nMARKER", menu_marker_sel}, + { MT_SUBMENU, 0, "MODIFY\nMARKERS", menu_marker_modify}, + { MT_SUBMENU, 0, "MARKER\nOPS", menu_marker_ops}, + { MT_SUBMENU, 0, "SEARCH\nMARKER", menu_marker_search}, + { MT_CALLBACK, 0, "RESET\nMARKERS", menu_markers_reset_cb}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +#ifndef TINYSA4 +static const menuitem_t menu_dfu[] = { + { MT_FORM | MT_CALLBACK, 0, "ENTER DFU", menu_dfu_cb}, + { MT_FORM | MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; +#endif + +#ifdef __HARMONIC__ +static const menuitem_t menu_harmonic[] = +{ + { MT_ADV_CALLBACK, 0, "OFF", menu_harmonic_acb}, + { MT_ADV_CALLBACK, 2, "2", menu_harmonic_acb}, + { MT_ADV_CALLBACK, 3, "3", menu_harmonic_acb}, + { MT_ADV_CALLBACK, 4, "4", menu_harmonic_acb}, + { MT_ADV_CALLBACK, 5, "5", menu_harmonic_acb}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; +#endif + + +static const menuitem_t menu_scanning_speed[] = +{ +// { MT_ADV_CALLBACK, SD_NORMAL, "NORMAL", menu_scanning_speed_acb}, // order must match definition of enum +// { MT_ADV_CALLBACK, SD_PRECISE, PRECISE", menu_scanning_speed_acb}, +// { MT_ADV_CALLBACK | MT_LOW,SD_FAST, "FAST", menu_scanning_speed_acb}, +// { MT_KEYPAD | MT_LOW,KM_FAST_SPEEDUP, "FAST\nSPEEDUP", "2..20"}, + { MT_KEYPAD, KM_SAMPLETIME, "SDELAY\n\b%s", "250..10000, 0=auto"}, // This must be item 4 to match highlighting + { MT_KEYPAD, KM_OFFSET_DELAY, "ODELAY\n\b%s", "250..10000, 0=auto"}, // This must be item 5 to match highlighting + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_sweep_points[] = { +#ifdef TINYSA4 + { MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(0,6), "%3d point", menu_points_acb }, +#else + { MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(0,4), "%3d point", menu_points_acb }, +#endif + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_sweep_points_form[] = { +#ifdef TINYSA4 + { MT_FORM|MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(0,6), "%3d point", menu_points_acb }, +#else + { MT_FORM|MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(0,4), "%3d point", menu_points_acb }, +#endif + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_sweep_speed[] = +{ + { MT_ADV_CALLBACK, SD_NORMAL, "NORMAL", menu_scanning_speed_acb}, // order must match definition of enum + { MT_ADV_CALLBACK, SD_PRECISE, "PRECISE", menu_scanning_speed_acb}, +#ifdef TINYSA4 + { MT_ADV_CALLBACK, SD_FAST, "FAST", menu_scanning_speed_acb}, +#else + { MT_ADV_CALLBACK | MT_LOW,SD_FAST, "FAST", menu_scanning_speed_acb}, +#endif + { MT_ADV_CALLBACK, SD_NOISE_SOURCE, "NOISE\nSOURCE", menu_scanning_speed_acb}, +#ifdef TINYSA4 + { MT_KEYPAD, KM_FAST_SPEEDUP,"SPEEDUP\n\b%s", "2..20, 0=disable"}, +#else + { MT_KEYPAD | MT_LOW,KM_FAST_SPEEDUP,"SPEEDUP\n\b%s", "2..20, 0=disable"}, +#endif + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +#ifdef TINYSA4 +static const menuitem_t menu_curve3[] = { + { MT_FORM | MT_ADV_CALLBACK | MT_REPEATS, DATA_STARTS_REPEATS(14,6), MT_CUSTOM_LABEL, menu_curve_acb }, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_curve2[] = { + { MT_FORM | MT_ADV_CALLBACK | MT_REPEATS, DATA_STARTS_REPEATS(7,7), MT_CUSTOM_LABEL, menu_curve_acb }, + { MT_FORM | MT_SUBMENU, 0, S_RARROW" MORE", menu_curve3}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_curve[] = { + { MT_FORM | MT_ADV_CALLBACK | MT_REPEATS, DATA_STARTS_REPEATS(0,7), MT_CUSTOM_LABEL, menu_curve_acb }, + { MT_FORM | MT_SUBMENU, 0, S_RARROW" MORE", menu_curve2}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_curve_confirm[] = { + { MT_CALLBACK, 1, "OK", menu_curve_confirm_cb }, + { MT_CALLBACK, 0, "CANCEL", menu_curve_confirm_cb }, + { MT_NONE, 0, NULL, NULL } // sentinel +}; +#if 0 +static const menuitem_t menu_noise_figure_confirm[] = { + { MT_CALLBACK, 1, "STORE\nTINYSA NF", menu_noise_figure_confirm_cb }, + { MT_CALLBACK, 0, "CANCEL", menu_noise_figure_confirm_cb }, + { MT_NONE, 0, NULL, NULL } // sentinel +}; +#endif +#endif + +#ifdef TINYSA4 +static const menuitem_t menu_actual_power2[] = +{ + { MT_ADV_CALLBACK, 0, "30MHz\nLEVEL", menu_output_level_acb}, + { MT_ADV_CALLBACK, 0, "1GHz\nLEVEL", menu_output_level2_acb}, + { MT_ADV_CALLBACK, 0, "1.2GHz\nLEVEL", menu_output_level3_acb}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; +#endif + +static const menuitem_t menu_actual_power[] = +{ + { MT_KEYPAD, KM_ACTUALPOWER, "INPUT\nLEVEL", "Enter actual level under marker"}, +#ifdef TINYSA4 + { MT_SUBMENU, 0, "OUTPUT\nLEVEL", menu_actual_power2}, + { MT_CALLBACK, 0, "INPUT\nCURVE", menu_input_curve_prepare_cb}, + { MT_CALLBACK, 0, "LNA\nCURVE", menu_lna_curve_prepare_cb}, + { MT_CALLBACK, 0, "ULTRA\nCURVE", menu_ultra_curve_prepare_cb}, + { MT_CALLBACK, 0, "LNA_U\nCURVE", menu_lna_u_curve_prepare_cb}, + { MT_CALLBACK, 0, "OUTPUT\nCURVE", menu_output_curve_prepare_cb}, +#else + { MT_ADV_CALLBACK, 0, "OUTPUT\nLEVEL", menu_output_level_acb}, +#endif + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +#ifdef TINYSA4 +static const menuitem_t menu_settings4[]; +#endif + +#ifdef TINYSA4 +static const menuitem_t menu_settings4[] = +{ + { MT_ADV_CALLBACK, 0, "DEBUG\nFREQ", menu_debug_freq_acb}, + { MT_ADV_CALLBACK, 0, "DEBUG\nAVOID", menu_debug_avoid_acb}, + { MT_ADV_CALLBACK, 0, "DEBUG\nSPUR", menu_debug_spur_acb}, + { MT_ADV_CALLBACK, 0, "HIDE\n21MHz", menu_hide_21MHz_acb}, +#if 0 // only used during development + { MT_KEYPAD, KM_COR_AM, "COR\nAM", "Enter AM modulation correction"}, + { MT_KEYPAD, KM_COR_WFM, "COR\nWFM", "Enter WFM modulation correction"}, + { MT_KEYPAD, KM_COR_NFM, "COR\nNFM", "Enter NFM modulation correction"}, +#endif +// { MT_CALLBACK, 0 , "CLEAR\nCONFIG", menu_clearconfig_cb}, +// { MT_SUBMENU, 0, S_RARROW" MORE", menu_settings3}, + { MT_KEYPAD, KM_DIRECT_START, "DSTART\n\b%s", ""}, + { MT_KEYPAD, KM_DIRECT_STOP, "DSTOP\n\b%s", ""}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; +#endif + +static const menuitem_t menu_settings3[] = +{ +#ifdef TINYSA4 +// { MT_KEYPAD, KM_GRIDLINES, "MINIMUM\nGRIDLINES", "Enter minimum horizontal grid divisions"}, +#ifndef __NEW_SWITCHES__ + { MT_ADV_CALLBACK, 0, "ADF OUT", menu_adf_out_acb}, +#endif + { MT_KEYPAD, KM_ULTRA_START,"ULTRASTART\n\b%s", "10G=auto"}, +// { MT_KEYPAD | MT_LOW, KM_IF2, "IF2 FREQ", "Set to zero for no IF2"}, + { MT_KEYPAD, KM_R, "R\n\b%s", "Set R"}, + { MT_KEYPAD, KM_MOD, "MODULO\n\b%s", "Set MODULO"}, + { MT_KEYPAD, KM_CP, "CP", "Set CP"}, +#ifdef __WAIT_CTS_WHILE_SLEEPING__ + { MT_ADV_CALLBACK, 0, "SLEEP\nWAIT", menu_sleep_acb}, +#endif +#ifdef __HARMONIC__ + { MT_SUBMENU ,0, "HARMONIC", menu_harmonic}, +#endif +// { MT_ADV_CALLBACK | MT_LOW, 0, "ULTRA\nMODE", menu_settings_ultra_acb}, +#ifdef __HAM_BAND__ + { MT_ADV_CALLBACK, 0, "HAM\nBANDS", menu_settings_ham_bands}, +#endif + { MT_SUBMENU, 0, S_RARROW" MORE", menu_settings4}, +#else +#ifdef __ULTRA__ + { MT_ADV_CALLBACK, 0, "ENABLE\nULTRA", menu_ultra_acb}, + { MT_KEYPAD, KM_ULTRA_START, "ULTRA\nSTART", "Enter ULTRA mode start freq"}, + { MT_ADV_CALLBACK, 0, "DEBUG\nSPUR", menu_debug_spur_acb}, +#endif +#ifdef __HARMONIC__ + { MT_SUBMENU | MT_HIGH,0, "HARMONIC", menu_harmonic}, +// { MT_ADV_CALLBACK,0, "SPUR\nREMOVAL", menu_harmonic_spur_acb}, +#endif +#ifdef __HAM_BAND__ + { MT_ADV_CALLBACK, 0, "HAM\nBANDS", menu_settings_ham_bands}, +#endif +#endif // TINYSA4 + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_settings2[] = +{ + { MT_ADV_CALLBACK, 0, "AGC", menu_settings_agc_acb}, + { MT_ADV_CALLBACK, 0, "LNA", menu_settings_lna_acb}, + { MT_ADV_CALLBACK | MT_LOW, 0, "BPF", menu_settings_bpf_acb}, + { MT_ADV_CALLBACK | MT_LOW, 0, "BELOW IF", menu_settings_below_if_acb}, + { MT_KEYPAD | MT_LOW, KM_IF, "IF FREQ\n\b%s", "0=auto IF"}, +#ifdef TINYSA4 + #ifdef __QUASI_PEAK__ + { MT_KEYPAD, KM_DECAY, "DECAY\n\b%s", "0..1000000ms or sweeps"}, + { MT_KEYPAD, KM_ATTACK, "ATTACK\n\b%s", "0..100000ms"}, +#endif +#endif + { MT_SUBMENU,0, "SCAN\nSPEED", menu_scanning_speed}, +#ifdef TINYSA4 + { MT_SUBMENU | MT_LOW,0, "MIXER\nDRIVE", menu_mixer_drive}, + { MT_SUBMENU, 0, S_RARROW" MORE", menu_settings3}, +#else + { MT_SUBMENU | MT_LOW,0, "MIXER\nDRIVE", menu_lo_drive}, + { MT_KEYPAD, KM_10MHZ, "CORRECT\nFREQUENCY", "Enter actual l0MHz frequency"}, +#endif + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + + +static const menuitem_t menu_settings[] = +{ +#ifdef TINYSA4 + { MT_ADV_CALLBACK,0, "PROGRESS\nBAR", menu_progress_bar_acb}, + { MT_ADV_CALLBACK, 0, "DIRECT\nMODE", menu_direct_acb}, + { MT_ADV_CALLBACK, 0, "LINEAR\nAVERAGING", menu_linear_averaging_acb}, + { MT_KEYPAD, KM_FREQ_CORR, "FREQ CORR\n\b%s", "Enter ppb correction"}, +// { MT_SUBMENU, 0, "CALIBRATE\nHARMONIC", menu_calibrate_harmonic}, +#endif +#ifdef __NOISE_FIGURE__ + { MT_KEYPAD, KM_NF, "NF\n\b%s", "Enter tinySA noise figure"}, +#endif +#ifdef __SD_CARD_LOAD__ + { MT_CALLBACK, 0 , "LOAD\nCONFIG.INI", menu_load_config_cb}, +// { MT_CALLBACK, 1 , "LOAD\nSETTING.INI", menu_load_config_cb}, +#endif +#ifdef TINYSA4 + { MT_ADV_CALLBACK, 0, "INTERNALS", menu_internals_acb}, +#endif + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +#ifdef __NOISE_FIGURE__ +static const menuitem_t menu_measure_noise_figure[] = +{ + { MT_ADV_CALLBACK, M_NF_TINYSA, "MEASURE\nTINYSA NF",menu_measure_acb}, + { MT_ADV_CALLBACK, M_NF_STORE, "STORE\nTINYSA NF",menu_measure_acb}, + { MT_ADV_CALLBACK, M_NF_VALIDATE, "VALIDATE\nTINYSA NF",menu_measure_acb}, + { MT_ADV_CALLBACK, M_NF_AMPLIFIER, "MEASURE\nAMP NF",menu_measure_acb}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; +#endif + +static const menuitem_t menu_measure2[] = { + { MT_ADV_CALLBACK, M_AM, "AM", menu_measure_acb}, + { MT_ADV_CALLBACK, M_FM, "FM", menu_measure_acb}, + { MT_ADV_CALLBACK, M_THD, "THD", menu_measure_acb}, +#ifdef __CHANNEL_POWER__ + { MT_ADV_CALLBACK, M_CP, "CHANNEL\nPOWER",menu_measure_acb}, +#endif +#ifdef __LINEARITY__ +{ MT_ADV_CALLBACK | MT_LOW, M_LINEARITY, "LINEAR", menu_measure_acb}, +#endif +#ifdef __NOISE_FIGURE__ +{ MT_SUBMENU | MT_LOW, 0, "NOISE\nFIGURE", menu_measure_noise_figure}, +#endif +#ifdef __FFT_DECONV__ + { MT_ADV_CALLBACK, M_DECONV, "DECONV", menu_measure_acb}, +#endif + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_measure[] = { + { MT_ADV_CALLBACK, M_OFF, "OFF", menu_measure_acb}, + { MT_ADV_CALLBACK, M_IMD, "HARMONIC", menu_measure_acb}, + { MT_ADV_CALLBACK, M_OIP3, "OIP3", menu_measure_acb}, + { MT_ADV_CALLBACK, M_PHASE_NOISE,"PHASE\nNOISE", menu_measure_acb}, + { MT_ADV_CALLBACK, M_SNR, "SNR", menu_measure_acb}, + { MT_ADV_CALLBACK, M_PASS_BAND, "-3dB\nWIDTH", menu_measure_acb}, + { MT_SUBMENU, 0, S_RARROW" MORE", menu_measure2}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +#ifdef __CALIBRATE__ +#ifdef TINYSA4 +static const menuitem_t menu_calibrate_harmonic[] = +{ + { MT_FORM | MT_TITLE, 0, "Connect 5.34GHz at -50 to -10dBm", NULL}, +#ifdef TINYSA4 + { MT_FORM | MT_CALLBACK, 3, "CALIBRATE", menu_calibrate_cb}, +#endif + { MT_FORM | MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_calibrate_normal[] = +{ + { MT_FORM | MT_TITLE, 0, "Connect CAL and RF", NULL}, +#ifdef TINYSA4 + { MT_FORM | MT_CALLBACK, 1, "CALIBRATE", menu_calibrate_cb}, +#endif + { MT_FORM | MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_calibrate[] = +{ + { MT_FORM | MT_SUBMENU, 1, "CALIBRATE 100kHz to 5.34GHz", menu_calibrate_normal}, + { MT_FORM | MT_SUBMENU, 1, "CALIBRATE above 5.34GHz", menu_calibrate_harmonic}, + { MT_FORM | MT_CALLBACK, 2, "RESET CALIBRATION", menu_calibrate_cb}, + { MT_FORM | MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +#else +static const menuitem_t menu_calibrate[] = +{ + { MT_FORM | MT_TITLE, 0, "Connect HIGH and LOW", NULL}, + { MT_FORM | MT_CALLBACK, 1, "CALIBRATE", menu_calibrate_cb}, + { MT_FORM | MT_CALLBACK, 2, "RESET CALIBRATION", menu_calibrate_cb}, + { MT_FORM | MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; +#endif + +#endif + +#ifdef __USE_SERIAL_CONSOLE__ +const menuitem_t menu_serial_speed[] = { + { MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(0,10), "%u", menu_serial_speed_acb }, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_connection[] = { + { MT_ADV_CALLBACK, _MODE_USB, "USB", menu_connection_acb }, + { MT_ADV_CALLBACK, _MODE_SERIAL, "SERIAL", menu_connection_acb }, + { MT_SUBMENU, 0, "SERIAL\nSPEED", menu_serial_speed }, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; +#endif + +const menuitem_t menu_touch[] = { + { MT_CALLBACK, CONFIG_MENUITEM_TOUCH_CAL, "TOUCH CAL", menu_config_cb}, + { MT_CALLBACK, CONFIG_MENUITEM_TOUCH_TEST, "TOUCH TEST", menu_config_cb}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +#ifdef __USE_RTC__ +const menuitem_t menu_date_time[] = { + { MT_KEYPAD, KM_RTC_TIME, "SET TIME\n\b%s", 0 }, // MUST BE BEFORE DATE + { MT_KEYPAD, KM_RTC_DATE, "SET DATE\n\b%s", 0 }, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; +#endif + +static const menuitem_t menu_config2[] = +{ + { MT_ADV_CALLBACK, 0, "PULSE\nHIGH", menu_settings_pulse_acb}, + { MT_ADV_CALLBACK | MT_LOW, 0,"LO OUTPUT", menu_lo_output_acb}, +#ifdef __ULTRA__ + { MT_ADV_CALLBACK, 0, "ENABLE\nULTRA", menu_ultra_acb}, +#endif + { MT_KEYPAD, KM_GRIDLINES, "MINIMUM\nGRIDLINES", "Enter minimum horizontal grid divisions"}, + { MT_KEYPAD, KM_VAR, "JOG STEP\n\b%s","0 = AUTO"}, + { MT_CALLBACK, 0 , "CLEAR\nCONFIG", menu_clearconfig_cb}, +#ifdef __USE_SERIAL_CONSOLE__ + { MT_SUBMENU, 0, "CONNECTION", menu_connection}, +#endif + { MT_SUBMENU, 0, "LEVEL\nCORRECTION", menu_actual_power}, +#ifdef TINYSA4 + { MT_SUBMENU, 0, "EXPERT\nCONFIG", menu_settings}, +#else + { MT_SUBMENU, 0, "EXPERT\nCONFIG", menu_settings2}, +#endif + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_config[] = { + { MT_SUBMENU, 0, "TOUCH", menu_touch}, + { MT_CALLBACK, CONFIG_MENUITEM_SELFTEST, "SELF TEST", menu_config_cb}, +#ifdef __CALIBRATE__ + { MT_SUBMENU, 0, "LEVEL CAL", menu_calibrate}, +#endif + { MT_CALLBACK, CONFIG_MENUITEM_VERSION, "VERSION", menu_config_cb}, +#ifdef __SPUR__ + { MT_ADV_CALLBACK,0, "%s", menu_spur_acb}, +#endif + { MT_KEYPAD, KM_REPEAT, "SAMPLE REP\n\b%s", "1..100"}, +#ifdef __LCD_BRIGHTNESS__ + { MT_CALLBACK, 0, "BRIGHTNESS", menu_brightness_cb}, +#endif +#ifdef __USE_RTC__ + { MT_SUBMENU, 0, "DATE\nTIME", menu_date_time}, +#endif +#ifndef TINYSA4 + { MT_SUBMENU, 0, S_RARROW" DFU", menu_dfu}, +#endif + { MT_SUBMENU, 0, S_RARROW"MORE", menu_config2}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; +#if 0 +static const menuitem_t menu_storage[] = +{ + { MT_ADV_CALLBACK,0, "TRACE %d", menu_storage_acb}, + { MT_ADV_CALLBACK,1, "%s", menu_storage_acb}, + { MT_ADV_CALLBACK,1, "DISPLAY", menu_storage_acb}, + { MT_ADV_CALLBACK,2, "COPY\nFROM", menu_storage_acb}, + { MT_ADV_CALLBACK,3, "SUBTRACT", menu_storage_acb}, + { MT_ADV_CALLBACK,4, "NORMALIZE", menu_storage_acb}, + { MT_ADV_CALLBACK,5, "WRITE\n"S_RARROW"SD",menu_storage_acb}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; +#endif +static const menuitem_t menu_trace[] = +{ + { MT_ADV_CALLBACK|MT_REPEATS,DATA_STARTS_REPEATS(0,TRACES_MAX), "TRACE %d", menu_trace_acb}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_marker_trace[] = +{ + { MT_ADV_CALLBACK|MT_REPEATS,DATA_STARTS_REPEATS(0,TRACES_MAX), "TRACE %d", menu_marker_trace_acb}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_store_trace[] = +{ + { MT_ADV_CALLBACK|MT_REPEATS,DATA_STARTS_REPEATS(0,TRACES_MAX), MT_CUSTOM_LABEL, menu_store_trace_acb}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_subtract_trace[] = +{ + { MT_ADV_CALLBACK|MT_REPEATS,DATA_STARTS_REPEATS(0,TRACES_MAX+1), MT_CUSTOM_LABEL, menu_subtract_trace_acb}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_traces[] = +{ + { MT_ADV_CALLBACK,0, "TRACE %d", menu_traces_acb}, + { MT_ADV_CALLBACK,1, "ENABLE", menu_traces_acb}, + { MT_ADV_CALLBACK,2, "FREEZE", menu_traces_acb}, + { MT_ADV_CALLBACK,3, MT_CUSTOM_LABEL, menu_traces_acb}, // Calc + { MT_ADV_CALLBACK,4, "NORMALIZE", menu_traces_acb}, + { MT_ADV_CALLBACK,5, MT_CUSTOM_LABEL, menu_traces_acb}, // Trace Math + { MT_SUBMENU, 0, "COPY\n"S_RARROW"TRACE", menu_store_trace}, +#ifdef TINYSA4 + { MT_ADV_CALLBACK,6, "WRITE\n"S_RARROW"SD", menu_traces_acb}, +#endif + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_display[] = { + { MT_ADV_CALLBACK,0, "PAUSE\nSWEEP", menu_pause_acb}, + { MT_ADV_CALLBACK,1, MT_CUSTOM_LABEL, menu_waterfall_acb}, +#ifdef __LEVEL_METER__ + { MT_ADV_CALLBACK,1, "BIG\nNUMBER", menu_level_meter_acb}, +#endif +#ifdef __DRAW_LINE__ + { MT_ADV_CALLBACK,1, "DRAW\nLINE", menu_settings_draw_line_acb}, +#endif + { MT_KEYPAD, KM_SWEEP_TIME, "SWEEP\nTIME", "0..600s, 0=disable"}, // This must be item 3 to match highlighting + { MT_SUBMENU, 0, "SWEEP\nPOINTS", menu_sweep_points}, + { MT_SUBMENU, 0, "SWEEP\nACCURACY", menu_sweep_speed}, + { MT_ADV_CALLBACK,0, "ROTATE\nDISPLAY", menu_flip_acb}, +//#ifdef __REMOTE_DESKTOP__ +// { MT_ADV_CALLBACK,0, "SEND\nDISPLAY", menu_send_display_acb}, +//#endif +// { MT_KEYPAD, KM_SWEEP_TIME, "SWEEP\nTIME", NULL}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_unit[] = +{ + { MT_ADV_CALLBACK,U_DBM, "dBm", menu_unit_acb}, + { MT_ADV_CALLBACK,U_DBMV, "dBmV", menu_unit_acb}, + { MT_ADV_CALLBACK,U_DBUV, "dB"S_MICRO"V", menu_unit_acb}, + { MT_ADV_CALLBACK,U_VOLT, "Volt", menu_unit_acb}, +//{ MT_ADV_CALLBACK,U_UVOLT, S_MICRO"Volt", menu_unit_acb}, + { MT_ADV_CALLBACK,U_WATT, "Watt", menu_unit_acb}, +//{ MT_ADV_CALLBACK,U_UWATT, S_MICRO"Watt", menu_unit_acb}, +#ifdef TINYSA4 + { MT_ADV_CALLBACK,U_RAW, "RAW", menu_unit_acb}, +#endif + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_trigger[] = { + { MT_ADV_CALLBACK, T_AUTO, "AUTO", menu_trigger_acb}, + { MT_ADV_CALLBACK, T_NORMAL, "NORMAL", menu_trigger_acb}, + { MT_ADV_CALLBACK, T_SINGLE, "SINGLE", menu_trigger_acb}, +// { MT_ADV_CALLBACK, T_DONE, "READY", menu_trigger_acb}, + { MT_KEYPAD, KM_TRIGGER, "TRIGGER LEV\n\b%s", NULL}, + { MT_ADV_CALLBACK, T_UP, "UP\nEDGE", menu_trigger_acb}, + { MT_ADV_CALLBACK, T_DOWN, "DOWN\nEDGE", menu_trigger_acb}, + { MT_ADV_CALLBACK, T_MODE, "%s\nTRIGGER", menu_trigger_acb}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_level[] = { + { MT_SUBMENU, 0, "REF LEVEL", menu_reflevel}, +//{ MT_SUBMENU, 0, "SCALE/DIV", menu_scale_per}, + { MT_CALLBACK,0, "SCALE/DIV", menu_scale_cb}, + { MT_SUBMENU, 0, "ATTENUATE", menu_atten}, +// { MT_SUBMENU,0, "CALC", menu_average}, + { MT_SUBMENU, 0, "UNIT", menu_unit}, + { MT_KEYPAD, KM_EXT_GAIN, "EXT GAIN\n\b%s",NULL}, +#ifdef TINYSA4 + { MT_ADV_CALLBACK | MT_LOW ,0,"LNA", menu_extra_lna_acb}, + #endif + { MT_SUBMENU, 0, "TRIGGER", menu_trigger}, +#ifdef __LISTEN__ + { MT_ADV_CALLBACK, 0, "LISTEN", menu_listen_acb}, +#endif + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +static const menuitem_t menu_stimulus[] = { + { MT_KEYPAD, KM_START, "START\n\b%s", NULL}, + { MT_KEYPAD, KM_STOP, "STOP\n\b%s", NULL}, + { MT_KEYPAD, KM_CENTER, "CENTER\n\b%s", NULL}, + { MT_KEYPAD, KM_SPAN, "SPAN\n\b%s", NULL}, + { MT_KEYPAD, KM_CW, "ZERO SPAN", NULL}, + { MT_SUBMENU,0, "RBW", menu_rbw}, +#ifdef __VBW__ + { MT_SUBMENU, 0, "VBW", menu_vbw}, +#endif + { MT_ADV_CALLBACK,0, "SHIFT\nFREQ", menu_shift_acb}, + { MT_NONE, 0, NULL, menu_back} // next-> menu_back +}; + +#ifdef TINYSA4 +const menuitem_t menu_mode[] = { +// { MT_FORM | MT_TITLE, 0, "tinySA MODE", NULL}, + { MT_FORM | MT_ADV_CALLBACK | MT_ICON, I_LOW_INPUT+I_SA, "Spectrum Analyzer", menu_mode_acb}, + { MT_FORM | MT_ADV_CALLBACK | MT_ICON, I_LOW_OUTPUT+I_SINUS, "Signal Generator", menu_mode_acb}, +// { MT_FORM | MT_ADV_CALLBACK | MT_ICON, I_HIGH_OUTPUT+I_GEN, "%s to HIGH out", menu_mode_acb}, + { MT_FORM | MT_ADV_CALLBACK | MT_ICON, I_CONNECT+I_GEN, "Calibration Output: %s", menu_sreffer_acb}, + { MT_FORM | MT_NONE, 0, NULL, NULL } // sentinel +}; +#else +const menuitem_t menu_mode[] = { +// { MT_FORM | MT_TITLE, 0, "tinySA MODE", NULL}, + { MT_FORM | MT_ADV_CALLBACK | MT_ICON, I_LOW_INPUT+I_SA, "%s to LOW in", menu_mode_acb}, + { MT_FORM | MT_ADV_CALLBACK | MT_ICON, I_HIGH_INPUT+I_SA, "%s to HIGH in", menu_mode_acb}, + { MT_FORM | MT_ADV_CALLBACK | MT_ICON, I_LOW_OUTPUT+I_SINUS, "%s to LOW out", menu_mode_acb}, + { MT_FORM | MT_ADV_CALLBACK | MT_ICON, I_HIGH_OUTPUT+I_GEN, "%s to HIGH out", menu_mode_acb}, + { MT_FORM | MT_ADV_CALLBACK | MT_ICON, I_CONNECT+I_GEN, "Cal. output: %s", menu_sreffer_acb}, +// { MT_SUBMENU, 0, "EXPERT\nCONFIG", menu_settings3}, +// { MT_FORM | MT_CANCEL, 0, S_RARROW" BACK", NULL }, + { MT_FORM | MT_NONE, 0, NULL, NULL } // sentinel +}; +#endif + +static const menuitem_t menu_top[] = { + { MT_SUBMENU, 0, "PRESET", menu_load_preset}, + { MT_SUBMENU, 0, "FREQUENCY", menu_stimulus}, + { MT_SUBMENU, 0, "LEVEL", menu_level}, + { MT_SUBMENU, 0, "TRACE", menu_traces}, + { MT_SUBMENU, 0, "DISPLAY", menu_display}, + { MT_SUBMENU, 0, "MARKER", menu_marker}, + { MT_SUBMENU, 0, "MEASURE", menu_measure}, + { MT_SUBMENU, 0, "CONFIG", menu_config}, + { MT_SUBMENU, 0, "MODE", menu_mode}, + { MT_NONE, 0, NULL, NULL } // sentinel, + // MENUITEM_CLOSE, +}; + +// ===[MENU DEFINITION END]====================================================== + +#define ACTIVE_COLOR RGBHEX(0x007FFF) + +static void menu_item_modify_attribute( // To modify menu buttons with keypad modes + const menuitem_t *menu, int item, ui_button_t *button) +{ + if (menu == menu_display) { + if (item == 5) + button->icon = setting.sweep_time_us != 0 ? BUTTON_ICON_CHECK_MANUAL : BUTTON_ICON_CHECK_AUTO; +// } else if (menu == menu_sweep_speed) { +// if (item == 3) +// button->icon = setting.fast_speedup != 0 ? BUTTON_ICON_CHECK_MANUAL : BUTTON_ICON_CHECK_AUTO; + } else if (menu == menu_reflevel) { + if (item == 1) + button->icon = setting.auto_reflevel ? BUTTON_ICON_GROUP: BUTTON_ICON_GROUP_CHECKED; + } else if (menu == menu_atten) { + if (item == 1) + button->icon = setting.auto_attenuation ? BUTTON_ICON_GROUP: BUTTON_ICON_GROUP_CHECKED; + } +} + +static void fetch_numeric_target(uint8_t mode) +{ + switch (mode) { + case KM_START: + uistat.freq_value = get_sweep_frequency(ST_START) + (setting.frequency_offset - FREQUENCY_SHIFT); + plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); + break; + case KM_STOP: + uistat.freq_value = get_sweep_frequency(ST_STOP) + (setting.frequency_offset - FREQUENCY_SHIFT); + plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); + break; + case KM_CENTER: + uistat.freq_value = get_sweep_frequency(ST_CENTER) + (setting.frequency_offset - FREQUENCY_SHIFT); + plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); + break; + case KM_SPAN: + uistat.freq_value = get_sweep_frequency(ST_SPAN); + plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); + break; + case KM_CW: + uistat.freq_value = get_sweep_frequency(ST_CW) + (setting.frequency_offset - FREQUENCY_SHIFT); + plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); + break; + case KM_SCALE: + case KM_LINEAR_SCALE: + uistat.value = setting.scale; + plot_printf(uistat.text, sizeof uistat.text, "%f/", uistat.value); + break; + case KM_REFLEVEL: + uistat.value = setting.reflevel; + plot_printf(uistat.text, sizeof uistat.text, "%.3F", uistat.value); + break; + case KM_ATTENUATION: + uistat.value = get_attenuation(); + plot_printf(uistat.text, sizeof uistat.text, "%ddB", ((int32_t)uistat.value)); + break; + case KM_ACTUALPOWER: + uistat.value = get_level_offset(); + plot_printf(uistat.text, sizeof uistat.text, "%ddB", ((int32_t)uistat.value)); + break; + case KM_IF: + uistat.freq_value = setting.frequency_IF; + if (!setting.auto_IF) + plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); + else + plot_printf(uistat.text, sizeof uistat.text, "AUTO"); + break; +#ifdef TINYSA4 + case KM_IF2: + uistat.freq_value = config.frequency_IF2; + plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); + break; + case KM_R: + uistat.value = setting.R; + if (setting.R) + plot_printf(uistat.text, sizeof uistat.text, "%d", setting.R); + else + plot_printf(uistat.text, sizeof uistat.text, "AUTO"); + break; + case KM_MOD: + if (local_modulo) + plot_printf(uistat.text, sizeof uistat.text, "%d", local_modulo); + else + plot_printf(uistat.text, sizeof uistat.text, "AUTO"); + break; + case KM_CP: + uistat.value = ADF4350_modulo; + plot_printf(uistat.text, sizeof uistat.text, "%d", ADF4350_modulo); + break; +#endif + case KM_SAMPLETIME: + uistat.value = setting.step_delay; + if (uistat.value) + plot_printf(uistat.text, sizeof uistat.text, "%dus", ((int32_t)uistat.value)); + else + plot_printf(uistat.text, sizeof uistat.text, "AUTO"); + break; + case KM_FAST_SPEEDUP: + uistat.value = setting.fast_speedup; + plot_printf(uistat.text, sizeof uistat.text, "%d", ((int32_t)uistat.value)); + break; + case KM_REPEAT: + uistat.value = setting.repeat; + plot_printf(uistat.text, sizeof uistat.text, "%d", ((int32_t)uistat.value)); + break; + case KM_LOWOUTLEVEL: + uistat.value = get_level(); // compensation for dB offset during low output mode + float end_level = ((int32_t)uistat.value)+setting.level_sweep; + if (end_level < level_min()) + end_level = level_min(); + if (end_level > level_max()) + end_level = level_max(); + uistat.value += setting.external_gain; + end_level += setting.external_gain; + if (setting.level_sweep != 0) + plot_printf(uistat.text, sizeof uistat.text, "%.1f to %.1fdBm", uistat.value, end_level); + else +#ifdef TINYSA4 + plot_printf(uistat.text, sizeof uistat.text, "%+.1fdBm %s", uistat.value, (setting.disable_correction?"Uncorrected":"")); +#else + plot_printf(uistat.text, sizeof uistat.text, "%+.1fdBm", uistat.value); +#endif + break; + case KM_HIGHOUTLEVEL: + uistat.value = get_level(); // compensation for dB offset during low output mode + uistat.value += setting.external_gain; + plot_printf(uistat.text, sizeof uistat.text, "%+.1fdBm", uistat.value); + break; + case KM_DECAY: + uistat.value = setting.decay; + plot_printf(uistat.text, sizeof uistat.text, "%d", ((int32_t)uistat.value)); + break; +#ifdef __QUASI_PEAK__ + case KM_ATTACK: + uistat.value = setting.attack; + plot_printf(uistat.text, sizeof uistat.text, "%d", ((int32_t)uistat.value)); + break; +#endif +#ifdef __ULTRA__ + case KM_ULTRA_START: + uistat.freq_value = config.ultra_start; + if (config.ultra_start == ULTRA_AUTO) + plot_printf(uistat.text, sizeof uistat.text, "AUTO"); + else + plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value ); + break; + case KM_DIRECT_START: + uistat.freq_value = config.direct_start; + plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); + break; + case KM_DIRECT_STOP: + uistat.freq_value = config.direct_stop; + plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); + break; +#endif +#ifdef __LIMITS__ + case KM_LIMIT_FREQ: + uistat.freq_value = setting.limits[current_trace][active_limit].frequency; + plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); + break; + case KM_LIMIT_LEVEL: + uistat.value = value(setting.limits[current_trace][active_limit].level); + plot_printf(uistat.text, sizeof uistat.text, "%.1f", uistat.value); + break; +#endif + case KM_NOISE: + uistat.value = setting.noise; + plot_printf(uistat.text, sizeof uistat.text, "%d", ((int32_t)uistat.value)); + break; +#ifdef TINYSA4 + case KM_FREQ_CORR: + if (config.setting_frequency_30mhz >= 3000000000ULL) + uistat.value = (config.setting_frequency_30mhz - 3000000000ULL)/3; + else + uistat.value = - ((int)(3000000000ULL - config.setting_frequency_30mhz))/3; + + plot_printf(uistat.text, sizeof uistat.text, "%d", (int32_t)uistat.value); + break; +#else + case KM_10MHZ: + uistat.freq_value = config.setting_frequency_10mhz; + plot_printf(uistat.text, sizeof uistat.text, "%3.6fMHz", uistat.freq_value); + break; +#endif + case KM_EXT_GAIN: + uistat.value = setting.external_gain; + plot_printf(uistat.text, sizeof uistat.text, "%.1fdB", uistat.value); + break; + case KM_LEVELSWEEP: + uistat.value = setting.level_sweep; + plot_printf(uistat.text, sizeof uistat.text, "%.1fdB", uistat.value); + break; + case KM_SWEEP_TIME: +// if (setting.sweep_time_us < calc_min_sweep_time_us()) +// uistat.value = calc_min_sweep_time_us(); +// else + uistat.value = setting.sweep_time_us; + uistat.value /= (float)ONE_SECOND_TIME; + plot_printf(uistat.text, sizeof uistat.text, "%.3Fs", uistat.value); + break; + case KM_TRIGGER: + uistat.value = value(setting.trigger_level); + char *format; + if (UNIT_IS_LINEAR(setting.unit)) + format = "%.3F%s"; // 5 characters incl u, m, etc... + else + format = "%.1f%s"; + plot_printf(uistat.text, sizeof uistat.text, format, uistat.value,unit_string[setting.unit]); + break; + case KM_MARKER: + if (active_marker >=0) { + uistat.freq_value = markers[active_marker].frequency; + plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); + } + break; + case KM_MODULATION: + if (active_marker >=0) { + uistat.value = setting.modulation_frequency; + plot_printf(uistat.text, sizeof uistat.text, "%7.0fHz", uistat.value); + } + break; +#ifdef TINYSA4 + case KM_DEVIATION: + uistat.freq_value = setting.modulation_deviation_div100 * 100; + plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); + break; + case KM_DEPTH: + uistat.value = setting.modulation_depth_x100; + plot_printf(uistat.text, sizeof uistat.text, "%3d", (int)uistat.value); + break; +#endif + case KM_VAR: + uistat.freq_value = setting.frequency_var; + if ( setting.frequency_var) + plot_printf(uistat.text, sizeof uistat.text, "%.4QHz", setting.frequency_var); + else + plot_printf(uistat.text, sizeof uistat.text, "AUTO"); + + break; +#ifdef __NOISE_FIGURE__ + case KM_NF: + uistat.value = config.noise_figure; + plot_printf(uistat.text, sizeof uistat.text, "%.1fdB", uistat.value); + break; +#endif +#ifdef __USE_RTC__ + case KM_RTC_TIME: + { + uint32_t tr = rtc_get_tr_bin(); // TR read first + plot_printf(uistat.text, sizeof uistat.text, "%02d:%02d:%02d", + RTC_TR_HOUR(dr), + RTC_TR_MIN(dr), + RTC_TR_SEC(dr)); + } + break; + case KM_RTC_DATE: + { + uint32_t dr = rtc_get_dr_bin(); // DR read second + plot_printf(uistat.text, sizeof uistat.text, "20%02d/%02d/%02d", + RTC_DR_YEAR(dr), + RTC_DR_MONTH(dr), + RTC_DR_DAY(dr)); + } + break; +#endif + } +} + +static void +set_numeric_value(void) +{ + switch (keypad_mode) { + case KM_START: + set_sweep_frequency(ST_START, uistat.freq_value - (setting.frequency_offset - FREQUENCY_SHIFT)); + break; + case KM_STOP: + set_sweep_frequency(ST_STOP, (freq_t)(uistat.freq_value - (setting.frequency_offset - FREQUENCY_SHIFT))); + break; + case KM_CENTER: + set_sweep_frequency(ST_CENTER, uistat.freq_value - (setting.frequency_offset - FREQUENCY_SHIFT)); + break; + case KM_SPAN: + setting.modulation = MO_NONE; + set_sweep_frequency(ST_SPAN, uistat.freq_value); + break; + case KM_CW: + set_sweep_frequency(ST_CW, uistat.freq_value - (setting.frequency_offset - FREQUENCY_SHIFT)); + break; + case KM_LINEAR_SCALE: + case KM_SCALE: + user_set_scale(uistat.value); + break; + case KM_REFLEVEL: + user_set_reflevel(uistat.value); + break; + case KM_ATTENUATION: + setting.auto_attenuation = false; + set_attenuation(uistat.value); + break; + case KM_ACTUALPOWER: + set_actual_power(uistat.value); + config_save(); + break; + case KM_IF: + set_IF(uistat.freq_value); +// config_save(); + break; +#ifdef TINYSA4 + case KM_IF2: + set_IF2(uistat.freq_value); +// config_save(); + break; + case KM_R: + set_R(uistat.value); +// config_save(); + break; + case KM_MOD: + set_modulo(uistat.value); + break; + case KM_CP: + ADF4351_CP((int)uistat.value); +// config_save(); + break; +#endif + case KM_SAMPLETIME: + set_step_delay(uistat.value); + break; + case KM_OFFSET_DELAY: + set_offset_delay(uistat.value); + break; + case KM_FAST_SPEEDUP: + set_fast_speedup(uistat.value); + break; + case KM_REPEAT: + set_repeat(uistat.value); + break; + case KM_LOWOUTLEVEL: + set_level(uistat.value - setting.external_gain); + break; + case KM_HIGHOUTLEVEL: + set_level(uistat.value - setting.external_gain); + break; + case KM_DECAY: + set_decay(uistat.value); + break; +#ifdef __QUASI_PEAK__ + case KM_ATTACK: + set_attack(uistat.value); + break; +#endif +#ifdef __ULTRA__ + case KM_ULTRA_START: + config.ultra_start = uistat.freq_value; + reset_settings(setting.mode); +// config_save(); // TODO not now + //ultra_start = config.ultra_start; + break; + case KM_DIRECT_START: + config.direct_start = uistat.freq_value; + config_save(); + break; + case KM_DIRECT_STOP: + config.direct_stop = uistat.freq_value; + config_save(); + break; +#endif +#ifdef TINYSA4 + case KM_EXP_AVER: + setting.exp_aver = uistat.value; + dirty = true; +#endif + case KM_LEVEL: + break; +#ifdef __LIMITS__ + case KM_LIMIT_FREQ: + setting.limits[current_trace][active_limit].frequency = uistat.freq_value - (setting.frequency_offset - FREQUENCY_SHIFT); + dirty = true; + limits_update(); + break; + case KM_LIMIT_LEVEL: + setting.limits[current_trace][active_limit].level = to_dBm(uistat.value); + dirty = true; + limits_update(); + break; +#endif + case KM_NOISE: + set_noise(uistat.value); + break; +#ifdef TINYSA4 + case KM_FREQ_CORR: + set_freq_corr(uistat.value); + break; +#else + case KM_10MHZ: + set_10mhz(uistat.freq_value); + break; +#endif + case KM_EXT_GAIN: + set_external_gain(uistat.value); + break; + case KM_LEVELSWEEP: + setting.modulation = MO_NONE; + set_level_sweep(uistat.value); + break; + case KM_SWEEP_TIME: + set_sweep_time_us(uistat.value*ONE_SECOND_TIME); + update_grid(); + break; + case KM_TRIGGER: + if (setting.trigger == T_AUTO ) + set_trigger(T_NORMAL); + set_trigger_level(to_dBm(uistat.value)); + completed = true; + break; + case KM_GRIDLINES: + set_gridlines(uistat.value); + break; + case KM_MARKER: + set_marker_frequency(active_marker, uistat.freq_value - (setting.frequency_offset - FREQUENCY_SHIFT)); + break; + case KM_MARKER_TIME: + set_marker_time(active_marker, uistat.value); + break; + case KM_MODULATION: + set_modulation_frequency((int)uistat.value); + break; +#ifdef TINYSA4 + case KM_COR_AM: + config.cor_am = -(int)uistat.value; + config_save(); + dirty = true; + break; + case KM_COR_WFM: + config.cor_wfm = -(int)uistat.value; + config_save(); + dirty = true; + break; + case KM_COR_NFM: + config.cor_nfm = -(int)uistat.value; + config_save(); + dirty = true; + break; + case KM_DEVIATION: + set_deviation((int)uistat.freq_value); + break; + case KM_DEPTH: + set_depth((int)uistat.value); + break; +#endif + case KM_VAR: + setting.frequency_var = uistat.freq_value; + break; +#ifdef __NOISE_FIGURE__ + case KM_NF: + config.noise_figure = uistat.value; + config_save(); + dirty = true; + break; +#endif +#ifdef __USE_RTC__ + case KM_RTC_DATE: + case KM_RTC_TIME: + { + int i = 0; + uint32_t dt_buf[2]; + dt_buf[0] = rtc_get_tr_bcd(); // TR should be read first for sync + dt_buf[1] = rtc_get_dr_bcd(); // DR should be read second + // 0 1 2 4 5 6 + // time[] ={sec, min, hr, 0, day, month, year, 0} + uint8_t *time = (uint8_t*)dt_buf; + for (; i < 6 && kp_buf[i]!=0; i++) kp_buf[i]-= '0'; + for (; i < 6 ; i++) kp_buf[i] = 0; + for (i = 0; i < 3; i++) kp_buf[i] = (kp_buf[2*i]<<4) | kp_buf[2*i+1]; // BCD format + if (keypad_mode == KM_RTC_DATE) { + // Month limit 1 - 12 (in BCD) + if (kp_buf[1] < 1) kp_buf[1] = 1; + else if (kp_buf[1] > 0x12) kp_buf[1] = 0x12; + // Day limit (depend from month): + uint8_t day_max = 28 + ((0b11101100000000000010111110111011001100>>(kp_buf[1]<<1))&3); + day_max = ((day_max/10)<<4)|(day_max%10); // to BCD + if (kp_buf[2] < 1) kp_buf[2] = 1; + else if (kp_buf[2] > day_max) kp_buf[2] = day_max; + time[6] = kp_buf[0]; // year + time[5] = kp_buf[1]; // month + time[4] = kp_buf[2]; // day + } + else { + // Hour limit 0 - 23, min limit 0 - 59, sec limit 0 - 59 (in BCD) + if (kp_buf[0] > 0x23) kp_buf[0] = 0x23; + if (kp_buf[1] > 0x59) kp_buf[1] = 0x59; + if (kp_buf[2] > 0x59) kp_buf[2] = 0x59; + time[2] = kp_buf[0]; // hour + time[1] = kp_buf[1]; // min + time[0] = kp_buf[2]; // sec + } + rtc_set_time(dt_buf[1], dt_buf[0]); + } + break; +#endif + + } +} + +void +menu_move_top(void) +{ + while (menu_current_level > 0) + menu_move_back(false); +} + + +// -------------------------- CAL STATUS --------------------------------------------- +const char * const dBText[] = { "1dB/", "2dB/", "5dB/", "10dB/", "20dB/"}; +const int refMHz[] = { 30, 15, 10, 4, 3, 2, 1 }; + +float my_round(float v) +{ + float m = 1; + int sign = 1; + if (v < 0) { + sign = -1; + v = -v; + } + while (v < 100) { + v = v * 10; + m = m / 10; + } + while (v > 1000) { + v = v / 10; + m = m * 10; + } + v = (int)(v+0.5); + v = v * m; + if (sign == -1) { + v = -v; + } + return v; +} +const char * const unit_string[MAX_UNIT_TYPE*2] = { "dBm", "dBmV", "dB"S_MICRO"V", "RAW", "V", "W", "dB", "dB", "dB", "RAW", "V", "W" }; // unit + 6 is delta unit + +//static const float scale_value[]={50000, 20000, 10000, 5000, 2000, 1000, 500, 200, 100, 50, 20,10,5,2,1,0.5,0.2,0.1,0.05,0.02,0.01,0.005,0.002, 0.001,0.0005,0.0002, 0.0001}; +//static const char * const scale_vtext[]= {"50000", "20000", "10000", "5000", "2000", "1000", "500", "200", "100", "50", "20","10","5","2","1","0.5","0.2","0.1","0.05","0.02","0.01", "0.005","0.002","0.001", "0.0005","0.0002","0.0001"}; + +// Quick menu +#define MAX_QUICK_MENU 20 +#define MAX_ITEM_SPACE 2 +static uint16_t quick_menu_y[MAX_QUICK_MENU]; +static menuitem_t *quick_menu[MAX_QUICK_MENU]; +static uint8_t max_quick_menu = 0; +static uint8_t item_space = 0; // + +int invoke_quick_menu(int y) +{ + int i; + for (i = 0; i < max_quick_menu;i++) { + if (y < quick_menu_y[i]) { + if ((uint32_t)quick_menu[i] < KM_NONE) { + ui_mode_keypad((int)quick_menu[i]); + } else { + selection = -1; + menu_current_level = 0; + menu_push_submenu(quick_menu[i]); + } + return TRUE; + } + } + return FALSE; +} +#define YSTEP 8 + +int add_quick_menu(int y, menuitem_t *menu) +{ + y += YSTEP*item_space/2 + YSTEP; + if (max_quick_menu 0.9 && t < 1.1){ + lcd_printf(x, y, "%s%c/",scale_vtext[i],unit_scale_text[setting.unit_scale_index]); + break; + } + i++; + } +#else + lcd_printf(x, y, "%.2F/",setting.scale); +#endif + y = add_quick_menu(y, (menuitem_t *)KM_SCALE); + + // Trigger status + if (is_paused()) { + ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); + ili9341_drawstring("PAUSED", x, y); + y += YSTEP + YSTEP/2 ; + } + if (setting.trigger == T_SINGLE || setting.trigger == T_NORMAL ) { + ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); + ili9341_drawstring("ARMED", x, y); + y += YSTEP + YSTEP/2 ; + } + // AM warning + if (signal_is_AM) { + ili9341_set_foreground(LCD_BRIGHT_COLOR_RED); + ili9341_drawstring("AM", x, y); + y += YSTEP + YSTEP/2 ; + } + quick_menu_y[max_quick_menu] = y; + quick_menu[max_quick_menu++] = (menuitem_t *)NULL; + +// if (setting.mode == M_LOW) { + // Attenuation + ili9341_set_foreground(setting.auto_attenuation ? LCD_FG_COLOR : LCD_BRIGHT_COLOR_GREEN); + lcd_printf(x, y, "Atten:\n%4.2FdB", get_attenuation()); + y = add_quick_menu(y+= YSTEP, (menuitem_t *)menu_atten); +// } + + // Calc + if (setting.average[0]>0) { + ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); + lcd_printf(x, y, "Calc:\n%s", averageText[setting.average[0]]); + y = add_quick_menu(y+= YSTEP, (menuitem_t *)menu_average); + } +#ifdef __SPUR__ // Spur +#ifdef TINYSA3 + if (setting.spur_removal != S_OFF) { +#endif + ili9341_set_foreground(setting.spur_removal == S_ON ? LCD_BRIGHT_COLOR_GREEN : LCD_FG_COLOR); + lcd_printf(x, y, "Spur:\n%s", S_IS_AUTO(setting.spur_removal) ? "AUTO" : (setting.spur_removal == S_OFF ?"OFF" : "ON")); + y = add_quick_menu(y += YSTEP, (menuitem_t *)menu_config); +#ifdef TINYSA3 + } +#endif + if (setting.mirror_masking) { + ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); + ili9341_drawstring("Mask:\nON", x, y); + y = add_quick_menu(y+=YSTEP, (menuitem_t *)menu_stimulus); + } +#endif + + if (setting.subtract[0]) { + ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); + ili9341_drawstring("Norm.", x, y); + y = add_quick_menu(y, (menuitem_t *)menu_display); + } + + // RBW + ili9341_set_foreground(setting.rbw_x10 ? LCD_BRIGHT_COLOR_GREEN : LCD_FG_COLOR); + if (dirty) update_rbw(); + lcd_printf(x, y, "RBW:\n%.1FHz", actual_rbw_x10*100.0); + y = add_quick_menu(y+=YSTEP, (menuitem_t *)menu_rbw); + +#ifdef __VBW__ + // VBW + if (setting.frequency_step > 0) { + int vbw = setting.vbw_x100; + if (vbw != 0) + color = LCD_BRIGHT_COLOR_GREEN; + else { + color = LCD_FG_COLOR; + vbw = 1; + } + ili9341_set_foreground(color); + lcd_printf(x, y, "VBW:\n%.1FHz", actual_rbw_x10*100.0 / vbw); + y = add_quick_menu(y+=YSTEP, (menuitem_t *)menu_vbw); + } +#endif + // Sweep time: SD_NORMAL, SD_PRECISE, SD_FAST, SD_MANUAL + static const char fscan[]={0, 'P', 'F', 'N', 'M'}; + if (dirty) { + calculate_step_delay(); + setting.actual_sweep_time_us = calc_min_sweep_time_us(); + } +#if 0 // Activate for sweep time debugging + lcd_printf(x, y, "%cScan:\n%5.3Fs", fscan[setting.step_delay_mode&7], (float)setting.sweep_time_us/ONE_SECOND_TIME); +#endif + ili9341_set_foreground((setting.step_delay_mode&7) != 0 ? LCD_BRIGHT_COLOR_GREEN : LCD_FG_COLOR); + lcd_printf(x, y, "%cScan:", fscan[setting.step_delay_mode&7]); + ili9341_set_foreground((setting.step_delay || setting.sweep_time_us ) ? LCD_BRIGHT_COLOR_GREEN : LCD_FG_COLOR); + lcd_printf(x, y+YSTEP, "%5.3Fs",(float)setting.actual_sweep_time_us/ONE_SECOND_TIME); + y = add_quick_menu(y+=YSTEP, (menuitem_t *)menu_sweep_speed); + + + #if 0 // Activate for sweep time debugging + y += YSTEP; + update_rbw(); // To ensure the calc_min_sweep time shown takes the latest delay into account + calculate_step_delay(); + uint32_t t = calc_min_sweep_time_us(); + lcd_printf(x, y, "%5.3Fs", (float)t/ONE_SECOND_TIME); + y += YSTEP; + lcd_printf(x, y, "%5.3Fs", (float)setting.additional_step_delay_us/ONE_SECOND_TIME); + y += YSTEP + YSTEP/2 ; +#endif +#ifdef TINYSA4 + if (setting.extra_lna){ + ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); + lcd_printf(x, y, "LNA:ON"); + y = add_quick_menu(y, (menuitem_t *)menu_level); + y += YSTEP; + } + + if (config.ultra_start != ULTRA_AUTO){ + ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); + lcd_printf(x, y, "Ultra:\n%3QHz", ultra_start); + y = add_quick_menu(y += YSTEP, (menuitem_t *)menu_config); + } + + if (setting.disable_correction){ + ili9341_set_foreground(LCD_BRIGHT_COLOR_RED); + lcd_printf(x, y, "Corr:\nOFF"); + y += 2*YSTEP + YSTEP/2; + } + + if (force_signal_path){ + ili9341_set_foreground(LCD_BRIGHT_COLOR_RED); + lcd_printf(x, y, "Path:\n%s", path_text[signal_path]); + y += 2*YSTEP + YSTEP/2; + } + +#endif + // Cal output + if (setting.refer >= 0) { + ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); + lcd_printf(x, y, "Ref:\n%dMHz",reffer_freq[setting.refer]/1000000); + y = add_quick_menu(y+=YSTEP, (menuitem_t *)menu_reffer); + } + + // Offset + if (setting.external_gain != 0.0) { + ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); + lcd_printf(x, y, "Gain:\n%4.1fdB",setting.external_gain); + y = add_quick_menu(y+=YSTEP, (menuitem_t *)KM_EXT_GAIN); + } + + // Repeat + if (setting.repeat != 1) { + ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); + lcd_printf(x, y, "Repeat\n x%d", setting.repeat); + y = add_quick_menu(y+=YSTEP,( menuitem_t *)KM_REPEAT); + } + + // Trigger + if (setting.trigger != T_AUTO) { + if (is_paused() || setting.trigger == T_NORMAL) { + ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); + } else { + ili9341_set_foreground(LCD_BRIGHT_COLOR_RED); + } + ili9341_drawstring("TRIG:", x, y); + + y += YSTEP; + if (rounding) + lcd_printf(x, y, "%6.3f", value(setting.trigger_level)); + else + lcd_printf(x, y, "%6.4F", value(setting.trigger_level)); +// lcd_printf(x, y, "%4f", value(setting.trigger_level)/setting.unit_scale); + y = add_quick_menu(y,(menuitem_t *)menu_trigger); + } +#ifndef TINYSA4 + // Mode + ili9341_set_foreground(level_is_calibrated() ? LCD_BRIGHT_COLOR_GREEN : LCD_BRIGHT_COLOR_RED); + ili9341_drawstring_7x13(MODE_LOW(setting.mode) ? "LOW" : "HIGH", x, y); + y += YSTEP + YSTEP/2 ; +#endif + // Compact status string +// ili9341_set_background(LCD_FG_COLOR); + ili9341_set_foreground(LCD_FG_COLOR); + strncpy(buf," ",BLEN-1); + if (setting.auto_IF) + buf[0] = 'f'; + else + buf[0] = 'F'; + if (S_IS_AUTO(setting.agc)) + buf[1] = 'g'; + else if (S_STATE(setting.agc)) + buf[1] = 'G'; + if (S_IS_AUTO(setting.lna)) + buf[2] = 'n'; + else if (S_STATE(setting.lna)) + buf[2] = 'N'; + if (S_IS_AUTO(setting.below_IF)) + buf[3] = 'b'; + else if (S_STATE(setting.below_IF)) + buf[3] = 'B'; +#ifdef TINYSA4 + if (S_IS_AUTO(setting.spur_removal)) + buf[4] = 's'; + else if (S_STATE(setting.spur_removal)) + buf[4] = 'S'; +#endif + ili9341_drawstring(buf, x, y); + + // Version + y += YSTEP + YSTEP/2 ; +#ifdef TINYSA4 // 'tinySA4_v1.2-[0-9]*-gxxxxxxx' + strncpy(buf,&TINYSA_VERSION[9], BLEN+1); // '1.2-...' +#else // 'tinySA_v1.2-[0-9]*-gxxxxxxx' + strncpy(buf,&TINYSA_VERSION[8], BLEN+1); // '1.2-...' +#endif + if (buf[5]=='-' ) { // '1.2-n-g...' + if (buf[4]=='0') // '1.2-0-g...' + buf[3] = 0; // -> '1.2' + else { + buf[5] = buf[4]; // -> '1.200n' + buf[4] = '0'; + buf[3] = '0'; + } + } else if (buf[6]=='-' ) { // 1.2-nn-g... + buf[3] = '0'; // -> '1.20nn' + } else { // 1.2-345-g... (or 1.2-3456...) + buf[3] = buf[4]; // -> '1.2345' + buf[4] = buf[5]; + buf[5] = buf[6]; + } + buf[6] = 0; + ili9341_drawstring(buf, x, y); + +#ifdef __USE_RTC__ + y += YSTEP + YSTEP/2 ; + uint32_t dr = rtc_get_dr_bin(); // DR read second + lcd_printf(x, y, "20%02d/\n%s/%02d", RTC_DR_YEAR(dr), month[RTC_DR_MONTH(dr)-1], RTC_DR_DAY(dr)); + y += YSTEP*2; + uint32_t tr = rtc_get_tr_bin(); // TR read first + lcd_printf(x, y, "%02d:%02d", RTC_TR_HOUR(dr), RTC_TR_MIN(dr)); +#endif + + + if (y >= BATTERY_START && item_space > 0) { + item_space--; // Reduce item spacing + goto redraw_cal_status; + } + if ((y + (max_quick_menu+1) * YSTEP/2) < BATTERY_START && item_space < MAX_ITEM_SPACE) { + item_space++; // Increase item spacing + goto redraw_cal_status; + } + +// ili9341_set_background(LCD_BG_COLOR); + if (!setting.waterfall) { // Do not draw bottom level if in waterfall mode + // Bottom level + y = area_height + OFFSETY; + if (level_is_calibrated()) + if (setting.auto_reflevel) + color = LCD_FG_COLOR; + else + color = LCD_BRIGHT_COLOR_GREEN; + else + color = LCD_BRIGHT_COLOR_RED; + ili9341_set_foreground(color); + if (rounding) + lcd_printf(x, y, "%4d", (int)(yMax - setting.scale * NGRIDY)); + else + lcd_printf(x, y, "%+4.3F", ((yMax - setting.scale * NGRIDY)/setting.unit_scale)); + y = add_quick_menu(y,(menuitem_t *)menu_average); + } +} + +//---------------------------- #define MENU_STACK_DEPTH_MAX 7 const menuitem_t *menu_stack[MENU_STACK_DEPTH_MAX] = { diff --git a/ui_sa.c b/ui_sa.c deleted file mode 100644 index df3cbb8..0000000 --- a/ui_sa.c +++ /dev/null @@ -1,4463 +0,0 @@ -/* Copyright (c) 2020, Erik Kaashoek erik@kaashoek.com - * All rights reserved. - * - * This 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, or (at your option) - * any later version. - * - * The software 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - - -#define FORM_ICON_WIDTH 16 -#define FORM_ICON_HEIGHT 16 - -static const uint8_t left_icons [] = -{ -#define I_EMPTY (0*16) - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000001), - _BMP16(0b0000000000000001), - _BMP16(0b0000000000000001), - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000001), - _BMP16(0b0000000000000001), - _BMP16(0b0000000000000001), - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000000), - -#define I_HIGH_INPUT (1*16) - // +----------------+ - _BMP16(0b0000000000000000), // | | - _BMP16(0b0000000000000000), // | | - _BMP16(0b0000000001100000), // | ** | - _BMP16(0b0000000000111001), // | *** *| - _BMP16(0b0000111111111111), // | *************| - _BMP16(0b0000000000111001), // | *** *| - _BMP16(0b0000000001100000), // | ** | - _BMP16(0b0000000000000000), // | | - _BMP16(0b0000000000000000), // | | - _BMP16(0b0000000000000000), // | | - _BMP16(0b0000000000000001), // | | - _BMP16(0b0000000000000001), // | | - _BMP16(0b0000000000000001), // | | - _BMP16(0b0000000000000000), // | | - _BMP16(0b0000000000000000), // | | - _BMP16(0b0000000000000000), // | | - // +----------------+ -#define I_LOW_INPUT (2*16) - // +----------------+ - _BMP16(0b0000000000000000), // | | - _BMP16(0b0000000000000000), // | | - _BMP16(0b0000000000000000), // | | - _BMP16(0b0000000000000001), // | | - _BMP16(0b0000000000000001), // | | - _BMP16(0b0000000000000001), // | | - _BMP16(0b0000000000000000), // | | - _BMP16(0b0000000000000000), // | | - _BMP16(0b0000000000000000), // | | - _BMP16(0b0000000001100000), // | ** | - _BMP16(0b0000000000111001), // | **** *| - _BMP16(0b0000111111111111), // | *************| - _BMP16(0b0000000000111001), // | **** *| - _BMP16(0b0000000001100000), // | ** | - _BMP16(0b0000000000000000), // | | - _BMP16(0b0000000000000000), // | | - // +----------------+ -#define I_LOW_OUTPUT (3*16) - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000001), - _BMP16(0b0000000000000001), - _BMP16(0b0000000000000001), - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000000), - _BMP16(0b0000000110000000), - _BMP16(0b0000011100000001), - _BMP16(0b0000111111111111), - _BMP16(0b0000011100000001), - _BMP16(0b0000000110000000), - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000000), - -#define I_HIGH_OUTPUT (4*16) - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000000), - _BMP16(0b0000000110000000), - _BMP16(0b0000011100000001), - _BMP16(0b0000111111111111), - _BMP16(0b0000011100000001), - _BMP16(0b0000000110000000), - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000001), - _BMP16(0b0000000000000001), - _BMP16(0b0000000000000001), - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000000), - -#define I_CONNECT (5*16) - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000000), - _BMP16(0b0000000000110000), - _BMP16(0b0000000000111101), - _BMP16(0b0000001111111111), - _BMP16(0b0000010000111101), - _BMP16(0b0000100000110000), - _BMP16(0b0001000000000000), - _BMP16(0b0001000000000000), - _BMP16(0b0000100000110000), - _BMP16(0b0000010000111101), - _BMP16(0b0000001111111111), - _BMP16(0b0000000000111101), - _BMP16(0b0000000000110000), - _BMP16(0b0000000000000000), - _BMP16(0b0000000000000000), -}; - -const uint8_t right_icons [] = -{ -#define I_SA 0 - // +----------------+ - _BMP16(0b0000000000000000), // | | - _BMP16(0b0111111111111111), // | ***************| - _BMP16(0b0100000000000001), // | * *| - _BMP16(0b1100000000000001), // |** *| - _BMP16(0b1100000000000001), // |** * *| - _BMP16(0b1100000000000001), // |** * *| - _BMP16(0b0100100000000001), // | * * * *| - _BMP16(0b0100100000000001), // | * * * *| - _BMP16(0b0100101010001001), // | * * * * *| - _BMP16(0b0100101010101001), // | * * * * * *| - _BMP16(0b1100101010101001), // |** * * * * * *| - _BMP16(0b1101111111111101), // |** * * * * * *| - _BMP16(0b1100000000000001), // |** *********** *| - _BMP16(0b0100000000000001), // | * *| - _BMP16(0b0111111111111111), // | ***************| - _BMP16(0b0000000000000000), // | | - // +----------------+ - -#define I_GEN 1 - // +----------------+ - _BMP16(0b0000000000000000), // | | - _BMP16(0b0111111111111111), // | ***************| - _BMP16(0b0100000000000001), // | * *| - _BMP16(0b1100000000000001), // |** *| - _BMP16(0b1100111110001101), // |** ***** ** *| - _BMP16(0b1100100010001001), // |** * * * *| - _BMP16(0b0100100010001001), // | * * * * *| - _BMP16(0b0100100010001001), // | * * * * *| - _BMP16(0b0100100010001001), // | * * * * *| - _BMP16(0b0100100010001001), // | * * * * *| - _BMP16(0b1100100010001001), // |** * * * *| - _BMP16(0b1101100011111001), // |** ** ***** *| - _BMP16(0b1100000000000001), // |** *| - _BMP16(0b0100000000000001), // | * *| - _BMP16(0b0111111111111111), // | ***************| - _BMP16(0b0000000000000000), // | | - // +----------------+ -#define I_CONFIG 2 - _BMP16(0b0000000000000000), - _BMP16(0b0111111111111111), - _BMP16(0b0100000000000001), - _BMP16(0b1100000010000001), - _BMP16(0b1100001111000001), - _BMP16(0b1100011110001001), - _BMP16(0b0100011100011101), - _BMP16(0b0100011110111001), - _BMP16(0b0100001111111001), - _BMP16(0b0100011111110001), - _BMP16(0b1100111110000001), - _BMP16(0b1101111100000001), - _BMP16(0b1100111000000001), - _BMP16(0b0100000000000001), - _BMP16(0b0111111111111111), - _BMP16(0b0000000000000000), - -#define I_SINUS 3 - _BMP16(0b0000000000000000), - _BMP16(0b0111111111111111), // 1 - _BMP16(0b0100000000000001), // 2 - _BMP16(0b1100000000000001), // 3 - _BMP16(0b1100000000110001), // 4 - _BMP16(0b1100000001001001), // 5 - _BMP16(0b0100000010000101), // 6 - _BMP16(0b0101000010000101), // 7 - _BMP16(0b0101000010000101), // 8 - _BMP16(0b0101000010000001), // 9 - _BMP16(0b1100100100000001), //10 - _BMP16(0b1100011000000001), //11 - _BMP16(0b1100000000000001), //12 - _BMP16(0b0100000000000001), //13 - _BMP16(0b0111111111111111), //14 - _BMP16(0b0000000000000000), -}; - -#define KP_X(x) (48*(x) + 2 + (LCD_WIDTH-BUTTON_WIDTH-192)) -#define KP_Y(y) (48*(y) + 2) - - -#define KP_PERIOD 10 -#define KP_MINUS 11 -#define KP_X1 12 -#define KP_K 13 -#define KP_M 14 -#define KP_G 15 -#define KP_BS 16 -#define KP_INF 17 -#define KP_DB 18 -#define KP_PLUSMINUS 19 -#define KP_KEYPAD 20 -#define KP_m 21 -#define KP_u 22 -#define KP_n 23 -#define KP_p 24 - -#define KP_0 31 -#define KP_1 32 -#define KP_2 33 -#define KP_5 34 -#define KP_10 35 -#define KP_20 36 -#define KP_50 37 -#define KP_100 38 -#define KP_200 39 -#define KP_500 40 - - -typedef struct { - uint8_t x:4; - uint8_t y:4; - int8_t c; -} keypads_t; - -static const keypads_t *keypads; - -// 7 8 9 G -// 4 5 6 M -// 1 2 3 k -// 0 . < x - -static const keypads_t keypads_freq[] = { - { 1, 3, KP_PERIOD }, - { 0, 3, 0 }, - { 0, 2, 1 }, - { 1, 2, 2 }, - { 2, 2, 3 }, - { 0, 1, 4 }, - { 1, 1, 5 }, - { 2, 1, 6 }, - { 0, 0, 7 }, - { 1, 0, 8 }, - { 2, 0, 9 }, - { 3, 0, KP_G }, - { 3, 1, KP_M }, - { 3, 2, KP_K }, - { 3, 3, KP_X1 }, - { 2, 3, KP_BS }, - { 0, 0, -1 } -}; - -// 7 8 9 -// 4 5 6 -// 1 2 3 -// 0 . < x - -static const keypads_t keypads_positive[] = { - { 1, 3, KP_PERIOD }, - { 0, 3, 0 }, - { 0, 2, 1 }, - { 1, 2, 2 }, - { 2, 2, 3 }, - { 0, 1, 4 }, - { 1, 1, 5 }, - { 2, 1, 6 }, - { 0, 0, 7 }, - { 1, 0, 8 }, - { 2, 0, 9 }, - { 3, 3, KP_X1 }, - { 2, 3, KP_BS }, - { 0, 0, -1 } -}; - -// 100 200 500 n -// 10 20 50 u -// 1 2 5 m -// 0 . < x - -static const keypads_t keypads_pos_unit[] = { - { 1, 3, KP_PERIOD }, - { 0, 3, 0 }, - { 0, 2, 1 }, - { 1, 2, 2 }, - { 2, 2, 5 }, - { 0, 1, KP_10 }, - { 1, 1, KP_20 }, - { 2, 1, KP_50 }, - { 0, 0, KP_100 }, - { 1, 0, KP_200 }, - { 2, 0, KP_500 }, - { 3, 0, KP_n }, - { 3, 1, KP_u }, - { 3, 2, KP_m }, - { 3, 3, KP_X1 }, - { 2, 3, KP_BS }, - { 0, 0, -1 } -}; - -// 7 8 9 m -// 4 5 6 u -// 1 2 3 - -// 0 . < x - -static const keypads_t keypads_plusmin_unit[] = { - { 1, 3, KP_PERIOD }, - { 0, 3, 0 }, - { 0, 2, 1 }, - { 1, 2, 2 }, - { 2, 2, 3 }, - { 0, 1, 4 }, - { 1, 1, 5 }, - { 2, 1, 6 }, - { 0, 0, 7 }, - { 1, 0, 8 }, - { 2, 0, 9 }, - { 3, 0, KP_u}, - { 3, 1, KP_m}, - { 3, 2, KP_MINUS }, - { 3, 3, KP_X1 }, - { 2, 3, KP_BS }, - { 0, 0, -1 } -}; -// 7 8 9 -// 4 5 6 -// 1 2 3 - -// 0 . < x - -static const keypads_t keypads_plusmin[] = { - { 1, 3, KP_PERIOD }, - { 0, 3, 0 }, - { 0, 2, 1 }, - { 1, 2, 2 }, - { 2, 2, 3 }, - { 0, 1, 4 }, - { 1, 1, 5 }, - { 2, 1, 6 }, - { 0, 0, 7 }, - { 1, 0, 8 }, - { 2, 0, 9 }, - { 3, 0, KP_u}, - { 3, 1, KP_m}, - { 3, 2, KP_MINUS }, - { 3, 3, KP_X1 }, - { 2, 3, KP_BS }, - { 0, 0, -1 } -}; - -// 7 8 9 -// 4 5 6 -// 1 2 3 m -// 0 . < x -static const keypads_t keypads_time[] = { - { 1, 3, KP_PERIOD }, - { 0, 3, 0 }, - { 0, 2, 1 }, - { 1, 2, 2 }, - { 2, 2, 3 }, - { 0, 1, 4 }, - { 1, 1, 5 }, - { 2, 1, 6 }, - { 0, 0, 7 }, - { 1, 0, 8 }, - { 2, 0, 9 }, -// { 3, 0, KP_n}, -// { 3, 1, KP_u}, - { 3, 2, KP_m }, - { 3, 3, KP_X1 }, - { 2, 3, KP_BS }, - { 0, 0, -1 } -}; - -enum { - KM_START, KM_STOP, KM_CENTER, KM_SPAN, KM_CW, // These must be first to share common help text - //#5 - KM_REFLEVEL, KM_SCALE, KM_ATTENUATION, KM_ACTUALPOWER, KM_IF, - // #10 - KM_SAMPLETIME, KM_LOWOUTLEVEL, KM_DECAY, KM_NOISE, -#ifdef TINYSA4 - KM_FREQ_CORR, -#else - KM_10MHZ, -#endif - // #15 - KM_REPEAT, KM_EXT_GAIN, KM_TRIGGER, KM_LEVELSWEEP, KM_SWEEP_TIME, - // #20 - KM_OFFSET_DELAY, KM_FAST_SPEEDUP, KM_GRIDLINES, KM_MARKER, KM_MODULATION, - // #25 - KM_HIGHOUTLEVEL, -#ifdef TINYSA4 - KM_COR_AM, KM_COR_WFM, KM_COR_NFM, - KM_DEVIATION, KM_DEPTH, - KM_IF2, - // #30 - KM_R,KM_MOD,KM_CP, -#endif - KM_ATTACK, -#ifdef __ULTRA__ - KM_ULTRA_START, -#endif -#ifdef TINYSA4 - KM_EXP_AVER, -#endif - KM_LEVEL, -#ifdef __LIMITS__ - KM_LIMIT_FREQ, KM_LIMIT_LEVEL, -#endif - KM_MARKER_TIME, - // #35 - KM_VAR, -#ifdef __NOISE_FIGURE__ - KM_NF, -#endif - KM_LINEAR_SCALE, -#ifdef TINYSA4 - KM_DIRECT_START, - KM_DIRECT_STOP, -#ifdef __USE_RTC__ - KM_RTC_DATE, - KM_RTC_TIME, -#endif -#endif - KM_CODE, - KM_NONE // always at enum end -}; - -static const struct { - const keypads_t *keypad_type; - char * name; -} keypads_mode_tbl[KM_NONE] = { -[KM_START] = {keypads_freq , "START"}, // start -[KM_STOP] = {keypads_freq , "STOP"}, // stop -[KM_CENTER] = {keypads_freq , "CENTER"}, // center -[KM_SPAN] = {keypads_freq , "SPAN"}, // span -[KM_CW] = {keypads_freq , "FREQ"}, // cw freq -[KM_REFLEVEL] = {keypads_plusmin_unit, "REF\nLEVEL"}, // reflevel #5 -[KM_SCALE] = {keypads_pos_unit , "SCALE"}, // scale -[KM_ATTENUATION] = {keypads_positive , "ATTENUATE"}, // attenuation -[KM_ACTUALPOWER] = {keypads_plusmin_unit, "ACTUAL\nPOWER"}, // actual power -[KM_IF] = {keypads_freq , "IF"}, // IF -[KM_SAMPLETIME] = {keypads_positive , "SAMPLE\nDELAY"}, // sample delay #10 -[KM_LOWOUTLEVEL] = {keypads_plusmin , "OUTPUT\nLEVEL"}, // KM_LOWOUTLEVEL -[KM_DECAY] = {keypads_positive , "DECAY"}, // KM_DECAY -[KM_NOISE] = {keypads_positive , "NOISE\nLEVEL"}, // KM_NOISE -#ifdef TINYSA4 -[KM_FREQ_CORR] = {keypads_plusmin , "PPB"}, // KM_FREQ_CORR -#else -[KM_10MHZ] = {keypads_freq , "FREQ"}, // KM_10MHz -#endif -[KM_REPEAT] = {keypads_positive , "SAMPLE\nREPEAT"}, // KM_REPEA #15 -[KM_EXT_GAIN] = {keypads_plusmin , "EXT\nGAIN"}, // KM_EXT_GAIN -[KM_TRIGGER] = {keypads_plusmin_unit, "LEVEL"}, // KM_TRIGGER -[KM_LEVELSWEEP] = {keypads_plusmin , "LEVEL\nSWEEP"}, // KM_LEVELSWEEP -[KM_SWEEP_TIME] = {keypads_time , "SWEEP\nSECONDS"}, // KM_SWEEP_TIME -[KM_OFFSET_DELAY] = {keypads_positive , "OFFSET\nDELAY"}, // KM_OFFSET_DELAY #20 -[KM_FAST_SPEEDUP] = {keypads_positive , "FAST\nSPEEDUP"}, // KM_FAST_SPEEDUP -[KM_GRIDLINES] = {keypads_positive , "MINIMUM\nGRIDLINES"}, // KM_GRIDLINES -[KM_MARKER] = {keypads_freq , "MARKER\nFREQ"}, // KM_MARKER -[KM_MODULATION] = {keypads_freq , "MODULATION\nFREQ"}, // KM_MODULATION -[KM_HIGHOUTLEVEL] = {keypads_plusmin , "OUTPUT\nLEVEL"}, // KM_HIGHOUTLEVEL #25 -#ifdef TINYSA4 -[KM_COR_AM] = {keypads_plusmin , "COR\nAM"}, // KM_COR_AM -[KM_COR_WFM] = {keypads_plusmin , "COR\nWFM"}, // KM_COR_WFM -[KM_COR_NFM] = {keypads_plusmin , "COR\nNFM"}, // KM_COR_NFM -[KM_DEVIATION] = {keypads_freq , "DEVIATION"}, // KM_DEVIATION -[KM_DEPTH] = {keypads_positive , "DEPTH%"}, // KM_DEPTH -[KM_IF2] = {keypads_freq , "IF2"}, // KM_IF2 -[KM_R] = {keypads_plusmin , "R"}, // KM_R #30 -[KM_MOD] = {keypads_positive , "MODULO"}, // KM_MOD -[KM_CP] = {keypads_positive , "CP"}, // KM_CP -#endif -[KM_ATTACK] = {keypads_positive , "ATTACK"}, // KM_ATTACK -#ifdef __ULTRA__ -[KM_ULTRA_START] = {keypads_freq , "ULTRA\nSTART"}, // KM_ULTRA_START -#endif -#ifdef TINYSA4 -[KM_EXP_AVER] = {keypads_positive , "EXPONENTIAL\nAVERAGING"}, //KM_EXP_AVER -#endif -[KM_LEVEL] = {keypads_plusmin , "LEVEL"}, // KM_LEVEL -#ifdef __LIMITS__ -[KM_LIMIT_FREQ] = {keypads_freq , "FREQ"}, // KM_LIMIT_FREQ -[KM_LIMIT_LEVEL] = {keypads_plusmin_unit , "LEVEL"}, // KM_LIMIT_LEVEL -#endif -[KM_MARKER_TIME] = {keypads_time , "MARKER\nTIME"}, // KM_MARKER_TIME -[KM_VAR] = {keypads_freq , "JOG\nSTEP"}, // jog step -#ifdef __NOISE_FIGURE__ -[KM_NF] = {keypads_plusmin , "NOISE\nFIGURE"}, // noise figure of tinySA -#endif -[KM_LINEAR_SCALE] = {keypads_plusmin , "SCALE"}, // scale for linear units -#ifdef TINYSA4 -[KM_DIRECT_START] = {keypads_freq , "DIRECT\nSTART"}, // KM_DIRECT_START -[KM_DIRECT_STOP] = {keypads_freq , "DIRECT\nSTOP"}, // KM_DIRECT_STOP -#ifdef __USE_RTC__ -[KM_RTC_DATE] = {keypads_positive , "SET DATE\n YYMMDD"}, // Date -[KM_RTC_TIME] = {keypads_positive , "SET TIME\n HHMMSS"}, // Time -#endif -#endif -[KM_CODE] = {keypads_positive , "CODE"}, // KM_CODE -}; - -#if 0 // Not used -enum { SL_GENLOW_FREQ, SL_GENHIGH_FREQ, SL_GENLOW_LEVEL, SL_GENHIGH_LEVEL }; -ui_slider_t ui_sliders [] = -{ - { KM_CENTER, true, 0, 1000000, 0, 350000000, M_GENLOW}, - { KM_CENTER, true, 0, 1000000, 240000000, 960000000, M_GENHIGH}, - { KM_LOWOUTLEVEL, false,0, 1, -76, -6, M_GENLOW}, - { KM_HIGHOUTLEVEL, false,0, 1, -38, +6, M_GENHIGH}, -}; -#endif - - -// ===[MENU CALLBACKS]========================================================= -const menuitem_t menu_lowoutputmode[]; -const menuitem_t menu_highoutputmode[]; -const menuitem_t menu_mode[]; -static const menuitem_t menu_modulation[]; -static const menuitem_t menu_top[]; -static const menuitem_t menu_trace[]; -static const menuitem_t menu_marker_trace[]; -static const menuitem_t menu_subtract_trace[]; -#ifdef __LIMITS__ -static const menuitem_t menu_limit_modify[]; -static const menuitem_t menu_limit_select[]; -#endif -static const menuitem_t menu_average[]; -static const menuitem_t menu_reffer[]; -static const menuitem_t menu_sweep_points[]; -static const menuitem_t menu_sweep_points_form[]; -static const menuitem_t menu_modulation[]; -static const menuitem_t menu_marker_ref_select[]; -#ifdef __USE_SERIAL_CONSOLE__ -static const menuitem_t menu_connection[]; -#endif -//static const menuitem_t menu_drive_wide[]; -static const menuitem_t menu_config[]; -#ifdef TINYSA4 -static const menuitem_t menu_settings3[]; -static const menuitem_t menu_curve[]; -static const menuitem_t menu_curve_confirm[]; -static const menuitem_t menu_measure_noise_figure[]; -static const menuitem_t menu_calibrate_harmonic[]; -#endif -static const menuitem_t menu_sweep[]; -static const menuitem_t menu_settings[]; -static const menuitem_t menu_settings2[]; -static const menuitem_t menu_lowoutput_settings[]; -extern bool dirty; -char range_text[20]; - -#ifdef TINYSA4 -int input_is_calibrated(void) -{ - if (config.input_is_calibrated) - return true; - drawMessageBox("Error", "First calibrate 100kHz to 5.34GHz input", 2000); - redraw_request|= REDRAW_AREA; - return false; -} - -int output_is_calibrated(void) -{ - if (config.output_is_calibrated) - return true; - drawMessageBox("Error", "First calibrate 30MHz output", 2000); - redraw_request|= REDRAW_AREA; - return false; -} - -static int unlock_internals = 0; - -static UI_FUNCTION_ADV_CALLBACK(menu_internals_acb) -{ - (void)data; - (void)item; - if (b){ - return; - } - if (unlock_internals != 5432) { - kp_help_text = "Internals access code"; - ui_mode_keypad(KM_CODE); - if (uistat.value != 5432) { - return; - } - unlock_internals = 5432; - } - menu_push_submenu(menu_settings2); -} - -#endif - -static UI_FUNCTION_ADV_CALLBACK(menu_sweep_acb) -{ - (void)data; - (void)item; - if (b){ - if (setting.level_sweep != 0 || get_sweep_frequency(ST_SPAN) != 0) { - plot_printf(b->text, sizeof b->text, "SW:%3.2fMHz %+ddB %.3Fs", - get_sweep_frequency(ST_SPAN) / 1000000.0, - (int)setting.level_sweep, - setting.sweep_time_us/(float)ONE_SECOND_TIME); - } - else - plot_printf(b->text, sizeof b->text, "SWEEP: OFF"); - return; - } - menu_push_submenu(menu_sweep); -} - -#ifdef __SWEEP_RESTART__ -static UI_FUNCTION_ADV_CALLBACK(menu_restart_acb){ - (void)item; - (void)data; - if(b){ - if (setting.sweep) { - if (current_index >= 0) { - float current_level = setting.level + ((float)current_index)* setting.level_sweep / (float)sweep_points; - plot_printf(b->text, sizeof b->text, "STOP %5.3QHz %+.1fdBm", getFrequency(current_index), current_level); - } else - plot_printf(b->text, sizeof b->text, "STOP SWEEP"); - } - else - plot_printf(b->text, sizeof b->text, "START SWEEP"); - return; - } - setting.sweep = !setting.sweep; - dirty = true; -} -#endif - -#ifdef TINYSA4 - -float local_actual_level; -int current_curve; -int current_curve_index; - -static UI_FUNCTION_ADV_CALLBACK(menu_curve_acb) - { - (void)item; - int old_m; - if (b){ - plot_printf(b->text, sizeof b->text, "%8.3QHz %+4.1fdB", - config.correction_frequency[current_curve][data], - config.correction_value[current_curve][data]); - return; - } - switch(current_curve) { - case CORRECTION_LOW_OUT: - old_m = setting.mode; - reset_settings(M_GENLOW); - set_level(-35); - set_sweep_frequency(ST_CW, config.correction_frequency[current_curve][data]); - setting.mute = false; - perform(false, 0, config.correction_frequency[current_curve][data], false); - perform(false, 1, config.correction_frequency[current_curve][data], false); - plot_printf(uistat.text, sizeof uistat.text, "Level of %.3QHz output", - config.correction_frequency[current_curve][data]); - kp_help_text = uistat.text; - kp_buf[0]=0; - ui_mode_keypad(KM_LEVEL); - - if (kp_buf[0] != 0) { - float new_offset = (-35.0) - uistat.value + config.correction_value[current_curve][data]; // calculate offset based on difference between measured peak level and known peak level - if (new_offset > -25 && new_offset < 25) { - config.correction_value[current_curve][data] = new_offset; - config_save(); - } - } - reset_settings(old_m); - break; - case CORRECTION_LNA: - reset_settings(M_LOW); - setting.extra_lna = true; - goto common; - case CORRECTION_LOW: - reset_settings(M_LOW); - common: - set_sweep_frequency(ST_SPAN, 1000000); - set_sweep_frequency(ST_CENTER, config.correction_frequency[current_curve][data]); - setting.step_delay_mode = SD_PRECISE; - current_curve_index = data; - menu_push_submenu(menu_curve_confirm); - break; - } -} - -extern float peakLevel; - -UI_FUNCTION_CALLBACK(menu_curve_confirm_cb) -{ - (void)item; - if (data) { - float new_offset = local_actual_level - peakLevel + config.correction_value[current_curve][current_curve_index]; // calculate offset based on difference between measured peak level and known peak level - if (new_offset > -30 && new_offset < 30) { - config.correction_value[current_curve][current_curve_index] = new_offset; - config_save(); - } - } - menu_move_back(false); -} - -float measured_noise_figure; - -UI_FUNCTION_CALLBACK(menu_noise_figure_confirm_cb) -{ - (void)item; - if (data) { - if (measured_noise_figure > 3 && measured_noise_figure < 15) { - config.noise_figure = measured_noise_figure; - config_save(); - nf_gain = 0.00001; // almost zero - set_measurement(M_NF_VALIDATE); // Continue to validate - return; - } - } - menu_move_back(false); -} - -static UI_FUNCTION_CALLBACK(menu_input_curve_prepare_cb) -{ - (void)item; - (void)data; - if (!input_is_calibrated()) - return; - kp_help_text = "Enter actual input level"; - kp_buf[0]=0; - ui_mode_keypad(KM_LEVEL); - if (kp_buf[0] != 0) { - local_actual_level = uistat.value; - current_curve = CORRECTION_LOW; - menu_push_submenu(menu_curve); - } -} - -static UI_FUNCTION_CALLBACK(menu_lna_curve_prepare_cb) -{ - (void)item; - (void)data; - if (!input_is_calibrated()) - return; - kp_help_text = "Enter actual input level"; - kp_buf[0]=0; - ui_mode_keypad(KM_LEVEL); - if (kp_buf[0] != 0) { - local_actual_level = uistat.value; - current_curve = CORRECTION_LNA; - menu_push_submenu(menu_curve); - } -} - -static UI_FUNCTION_CALLBACK(menu_lna_u_curve_prepare_cb) -{ - (void)item; - (void)data; - if (!input_is_calibrated()) - return; - kp_help_text = "Enter actual input level"; - kp_buf[0]=0; - ui_mode_keypad(KM_LEVEL); - if (kp_buf[0] != 0) { - local_actual_level = uistat.value; - current_curve = CORRECTION_LNA_ULTRA; - menu_push_submenu(menu_curve); - } -} - -static UI_FUNCTION_CALLBACK(menu_ultra_curve_prepare_cb) -{ - (void)item; - (void)data; - if (!input_is_calibrated()) - return; - kp_help_text = "Enter actual input level"; - kp_buf[0]=0; - ui_mode_keypad(KM_LEVEL); - if (kp_buf[0] != 0) { - local_actual_level = uistat.value; - current_curve = CORRECTION_LOW_ULTRA; - menu_push_submenu(menu_curve); - } -} - -static UI_FUNCTION_CALLBACK(menu_output_curve_prepare_cb) -{ - (void)item; - (void)data; - if (!output_is_calibrated()) - return; - current_curve = CORRECTION_LOW_OUT; - menu_push_submenu(menu_curve); -} - -#endif - -static UI_FUNCTION_ADV_CALLBACK(menu_output_level_acb) -{ - (void)item; - (void)data; - if (b){ - return; - } - int old_m = setting.mode; - reset_settings(M_GENLOW); -#ifdef TINYSA4 -#define TEST_LEVEL -30 -#else -#define TEST_LEVEL -25 -#endif - set_level(TEST_LEVEL); - set_sweep_frequency(ST_CW, 30000000); - setting.mute = false; - perform(false, 0, 30000000, false); - perform(false, 1, 30000000, false); - kp_help_text = "Enter actual level of 30MHz output"; - kp_buf[0]=0; - ui_mode_keypad(KM_LEVEL); - if (kp_buf[0] != 0) { - float old_offset = config.low_level_output_offset; - if (!config.input_is_calibrated) old_offset = 0; - float new_offset = uistat.value - (TEST_LEVEL) + old_offset; // calculate offset based on difference between measured peak level and known peak level - if (uistat.value == 100) { new_offset = 0; config.input_is_calibrated = false; } - if (new_offset > -15 && new_offset < 15) { - config.output_is_calibrated = true; - config.low_level_output_offset = new_offset; - config_save(); - } - } - reset_settings(old_m); -} - -#ifdef TINYSA4 -static UI_FUNCTION_ADV_CALLBACK(menu_output_level2_acb) -{ - (void)item; - (void)data; - if (b){ - return; - } - if (!output_is_calibrated()) - return; - int old_m = setting.mode; - reset_settings(M_GENLOW); - set_level(-30); - set_sweep_frequency(ST_CW, 1000000000); - setting.mute = false; - perform(false, 0, 1000000000, false); - perform(false, 1, 1000000000, false); - kp_help_text = "Enter actual level of 1GHz output"; - kp_buf[0]=0; - ui_mode_keypad(KM_LEVEL); - if (kp_buf[0] != 0) { - float old_offset = config.direct_level_output_offset; - float new_offset = (-30.0) - uistat.value + old_offset; // calculate offset based on difference between measured peak level and known peak level - if (new_offset > -10 && new_offset < 10) { - config.direct_level_output_offset = new_offset; - config_save(); - } - } - reset_settings(old_m); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_output_level3_acb) -{ - (void)item; - (void)data; - if (b){ - return; - } - if (!output_is_calibrated()) - return; - int old_m = setting.mode; - reset_settings(M_GENLOW); - - force_signal_path = true; - test_path = PATH_LEAKAGE; - test_output_drive = -1; - - set_level(-30); - set_sweep_frequency(ST_CW, 1200000000); - setting.mute = false; - perform(false, 0, 1200000000, false); - perform(false, 1, 1200000000, false); - kp_help_text = "Enter actual level of 1.2GHz output"; - kp_buf[0]=0; - ui_mode_keypad(KM_LEVEL); - if (kp_buf[0] != 0) { - float old_offset = config.adf_level_offset; - float new_offset = (-30.0) - uistat.value + old_offset; // calculate offset based on difference between measured peak level and known peak level - if (new_offset > -10 && new_offset < 10) { - config.adf_level_offset = new_offset; - config_save(); - } - } - force_signal_path = false; - reset_settings(old_m); -} - -#endif - -#ifdef TINYSA4 -static const int item_to_mode[2] = { 0,2 }; -#else -static const int item_to_mode[4] = { 0,1,2,3 }; -#endif -static UI_FUNCTION_ADV_CALLBACK(menu_mode_acb) -{ - (void)data; - item = item_to_mode[item]; - if (b){ - if (item == setting.mode) { - b->param_1.text = "Return"; - b->bg = LCD_MENU_ACTIVE_COLOR; - b->border = BUTTON_BORDER_FALLING | MENU_BUTTON_BORDER; - } - else - b->param_1.text = "Switch"; - return; - } - set_mode(item); -// draw_cal_status(); - switch (item) { - case 0: -// if (setting.mode != M_LOW) -// set_mode(M_LOW); - menu_move_back(true); - break; - case 1: -// if (setting.mode != M_HIGH) -// set_mode(M_HIGH); - menu_move_back(true); - break; - case 2: - menu_push_submenu(menu_lowoutputmode); - break; - case 3: - menu_push_submenu(menu_highoutputmode); - break; - } - redraw_request |= REDRAW_CAL_STATUS; -} - -static UI_FUNCTION_ADV_CALLBACK(menu_load_preset_acb) -{ - (void)item; - if(b){ - setting_t *p = caldata_pointer(data); - if (p) - plot_printf(b->text, sizeof(b->text), "%.6FHz\n%.6FHz", (float)p->frequency0, (float)p->frequency1); - else - plot_printf(b->text, sizeof(b->text), "EMPTY %d", (int)data); - return; - } - if (caldata_recall(data) == -1) { - if (data == 0) - reset_settings(setting.mode); // Restore factory defaults - } - menu_move_back(true); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_store_preset_acb) -{ - (void)item; - if(b){ - b->param_1.u = data; - return; - } - if (data == 100) { - reset_settings(M_LOW); // Restore all defaults in Low mode - set_refer_output(-1); - // setting.mode = -1; - data = 0; - } - caldata_save(data); - menu_move_back(true); -} - -#ifdef __SD_CARD_LOAD__ -UI_FUNCTION_CALLBACK(menu_load_config_cb) -{ - (void)item; - (void)data; - sd_card_load_config("config.ini"); - ui_mode_normal(); -} -#endif - -UI_FUNCTION_CALLBACK(menu_autosettings_cb) -{ - (void)item; - (void)data; - reset_settings(setting.mode); - - markers_reset(); - // set_refer_output(1); - - // SetPowerLevel(100); // Reset -// set_clear_storage(); - dirty = true; - // menu_move_back(true); // stay in input menu - ui_mode_normal(); -// draw_cal_status(); -} - -static UI_FUNCTION_CALLBACK(menu_scale_cb) -{ - (void)item; - (void)data; - kp_help_text = "Enter scale"; - kp_buf[0]=0; - - if (UNIT_IS_LINEAR(setting.unit)) - ui_mode_keypad(KM_LINEAR_SCALE); - else - ui_mode_keypad(KM_SCALE); - ui_mode_normal(); -} - -#ifdef __CALIBRATE__ -static UI_FUNCTION_CALLBACK(menu_calibrate_cb) -{ - (void)data; - (void)item; - switch (data) { - case 1: - sweep_mode = SWEEP_CALIBRATE; -#ifdef TINYSA4 - menu_move_back(false); -#endif - menu_move_back(true); - break; - case 2: - reset_calibration(); - break; -#ifdef TINYSA4 - case 3: - if (!input_is_calibrated()) - return; - sweep_mode = SWEEP_CALIBRATE_HARMONIC; - menu_move_back(false); - menu_move_back(true); - break; -#endif - } -} -#endif - -static UI_FUNCTION_ADV_CALLBACK(menu_scanning_speed_acb) -{ - (void)item; - if(b){ - b->icon = data == setting.step_delay_mode ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - return; - } - set_step_delay(data); -// menu_move_back(false); - ui_mode_normal(); -} - -#define CONFIG_MENUITEM_TOUCH_CAL 0 -#define CONFIG_MENUITEM_TOUCH_TEST 1 -#define CONFIG_MENUITEM_SELFTEST 2 -#define CONFIG_MENUITEM_VERSION 3 -static UI_FUNCTION_CALLBACK(menu_config_cb) -{ - (void)item; - switch (data) { - case CONFIG_MENUITEM_TOUCH_CAL: - touch_cal_exec(); - break; - case CONFIG_MENUITEM_TOUCH_TEST: - touch_draw_test(); - break; - case CONFIG_MENUITEM_SELFTEST: - sweep_mode = 0; // Suspend sweep to save time - menu_move_back(true); - setting.test = 0; - setting.test_argument = 0; - sweep_mode = SWEEP_SELFTEST; - return; - case CONFIG_MENUITEM_VERSION: - show_version(); - break; - } - ui_mode_normal(); - redraw_frame(); - request_to_redraw_grid(); -} -#ifndef TINYSA4 -static UI_FUNCTION_CALLBACK(menu_dfu_cb) -{ - (void)data; - (void)item; - enter_dfu(); -} -#endif - -#ifdef __LISTEN__ -static UI_FUNCTION_ADV_CALLBACK(menu_listen_acb) -{ - (void)data; - (void)item; - if (b){ - b->icon = (sweep_mode & SWEEP_LISTEN) ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - return; - } - if (sweep_mode & SWEEP_LISTEN) { - sweep_mode = SWEEP_ENABLE; - } else { - sweep_mode = SWEEP_LISTEN; - } - ui_mode_normal(); - redraw_frame(); - request_to_redraw_grid(); - -#if 0 - 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 -} -#endif -#ifdef TINYSA4 - - -static UI_FUNCTION_ADV_CALLBACK(menu_lowoutput_settings_acb) -{ - static char mode_string[26]; - (void)item; - if (b){ - if (data == 255) { - plot_printf(mode_string, sizeof mode_string, "%s %s %s %s", - (!force_signal_path ? "" : path_text[test_path]), - (get_sweep_frequency(ST_START) < MINIMUM_DIRECT_FREQ ? "SINUS" : "" ), - (get_sweep_frequency(ST_STOP) >= MINIMUM_DIRECT_FREQ ? "SQUARE WAVE" : ""), - (get_sweep_frequency(ST_STOP) > MAX_LOW_OUTPUT_FREQ && setting.mixer_output ? "MIXER" : "")); - b->param_1.text = mode_string; - return; } - b->icon = data == setting.mixer_output ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - return; - } - switch(data) { - case 255: - menu_push_submenu(menu_lowoutput_settings); - return; - case 0: - setting.mixer_output = false; - dirty = true; - break; - case 1: - setting.mixer_output = true; - dirty = true; - break; - } - menu_move_back(false); -} - -#endif -// const int menu_modulation_value[]={MO_NONE,MO_AM, MO_NFM, MO_WFM, MO_EXTERNAL}; -const char *menu_modulation_text[MO_MAX]= -{ "None", "AM 30%", -#ifdef TINYSA4 - "FM 2.5kHz", - "FM 3kHz", - "FM 5kHz", -#else - "FM 4kHz", -#endif - "FM 75kHz", "External"}; - -static UI_FUNCTION_ADV_CALLBACK(menu_modulation_acb) -{ - (void)item; - if (b){ - plot_printf(b->text, sizeof b->text, "%s", menu_modulation_text[data]); - b->icon = data == setting.modulation ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - return; - } -//Serial.println(item); - if (data) { - set_sweep_frequency(ST_SPAN, 0); // No other scanning allowed when modulation is on!!!!! - set_level_sweep(0); - } - set_modulation(data); -// menu_move_back(false); // Don't move back -} - -static UI_FUNCTION_ADV_CALLBACK(menu_smodulation_acb){ - (void)item; - (void)data; - if(b){ - if (setting.modulation == MO_NONE || setting.modulation == MO_EXTERNAL) - plot_printf(b->text, sizeof b->text, "MOD: %s", menu_modulation_text[setting.modulation]); - else { -#ifdef TINYSA4 - if (setting.modulation == MO_AM) - plot_printf(b->text, sizeof b->text, "MOD: %4dHz AM %d%%", (int)(setting.modulation_frequency), setting.modulation_depth_x100); - else - plot_printf(b->text, sizeof b->text, "MOD: %4dHz FM %4QHz", (int)(setting.modulation_frequency), (freq_t)(setting.modulation_deviation_div100*100)); -#else - plot_printf(b->text, sizeof b->text, "MOD: %4dHz %s", (int)(setting.modulation_frequency), menu_modulation_text[setting.modulation]); -#endif - } - return; - } - menu_push_submenu(menu_modulation); -} - -// 0 1 2 3 4 5 6 7 -const char *menu_reffer_text[]={"OFF","30MHz","15MHz","10MHz","4MHz","3MHz","2MHz","1MHz"}; -static UI_FUNCTION_ADV_CALLBACK(menu_reffer_acb) -{ - (void)item; - if (b){ - b->icon = setting.refer == ((int)data-1) ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - b->param_1.text = menu_reffer_text[data]; - return; - } -//Serial.println(item); - set_refer_output((int)data - 1); - menu_move_back(false); -// ui_mode_normal(); // Stay in menu mode -// draw_cal_status(); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_sreffer_acb){ - (void)item; - (void)data; - if(b){ - b->param_1.text = menu_reffer_text[setting.refer+1]; - return; - } - menu_push_submenu(menu_reffer); -} - -#ifdef TINYSA3 -static UI_FUNCTION_ADV_CALLBACK(menu_lo_drive_acb) -{ - (void)item; - if(b){ - b->param_1.i = drive_dBm[data]; - b->icon = data == setting.lo_drive ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - return; - } -//Serial.println(item); - set_lo_drive(data); - menu_move_back(false); -// ui_mode_normal(); -// draw_cal_status(); -} -#else -static UI_FUNCTION_ADV_CALLBACK(menu_mixer_drive_acb) -{ - (void)item; - if(b){ - b->param_1.i = data; - b->icon = data == setting.lo_drive ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - return; - } -//Serial.println(item); - set_lo_drive(data); - menu_move_back(false); -// ui_mode_normal(); -// draw_cal_status(); -} -#endif - -#if 0 -static UI_FUNCTION_ADV_CALLBACK(menu_sdrive_acb){ - (void)item; - (void)data; - if(b){ -#ifdef TINYSA4 - b->param_1.i = setting.lo_drive; -#else - b->param_1.i = drive_dBm[setting.lo_drive] + (setting.mode==M_GENHIGH ? setting.external_gain : 0); -#endif - return; - } - menu_push_submenu(menu_drive_wide); -} -#endif - -#ifdef __SPUR__ -static UI_FUNCTION_ADV_CALLBACK(menu_spur_acb) -{ - (void)data; - (void)item; - if (b){ - if (setting.mode == M_LOW) { - b->param_1.text = "SPUR\nREMOVAL"; - b->icon = AUTO_ICON(setting.spur_removal); - } else { - b->param_1.text = "MIRROR\nMASKING"; -#ifdef TINYSA4 - b->icon = AUTO_ICON(setting.mirror_masking ? 1 : 0); // mirror_masking does not yet have an auto mode so this is never an auto icon -#else - b->icon = setting.mirror_masking == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; -#endif - } - return; - } - if (setting.mode == M_LOW) { - toggle_spur(); - } else - toggle_mirror_masking(); - // menu_move_back(false); - ui_mode_normal(); -} -#if 0 -#ifdef __HARMONIC__ -static UI_FUNCTION_ADV_CALLBACK(menu_harmonic_spur_acb) -{ - (void)data; - (void)item; - if (b){ - b->icon = AUTO_ICON(setting.spur_removal); - return; - } - toggle_spur(); - ui_mode_normal(); -}#endif -#endif -#endif -#endif - -#ifdef __ULTRA__ -static UI_FUNCTION_ADV_CALLBACK(menu_debug_spur_acb) -{ - (void)data; - (void)item; - if (b){ - b->icon = debug_spur == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; - return; - } - toggle_debug_spur(); - // menu_move_back(); - ui_mode_normal(); -} -#endif - -#ifdef TINYSA4 -static UI_FUNCTION_ADV_CALLBACK(menu_hide_21MHz_acb) -{ - (void)data; - (void)item; - if (b){ - b->icon = config.hide_21MHz == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; - return; - } - config.hide_21MHz = ! config.hide_21MHz; - // menu_move_back(); - ui_mode_normal(); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_progress_bar_acb) -{ - (void)data; - (void)item; - if (b){ - b->icon = progress_bar == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; - return; - } - progress_bar = !progress_bar; - // menu_move_back(); - ui_mode_normal(); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_extra_lna_acb) -{ - (void)data; - (void)item; - if (b){ - b->icon = setting.extra_lna == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; - return; - } - toggle_extra_lna(); - // menu_move_back(false); - ui_mode_normal(); -} -#ifndef __NEW_SWITCHES__ -static UI_FUNCTION_ADV_CALLBACK(menu_adf_out_acb) -{ - (void)data; - (void)item; - if (b){ - b->icon = config.high_out_adf4350 == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; - return; - } - toggle_high_out_adf4350(); - // menu_move_back(false); - ui_mode_normal(); -} -#endif - -#ifdef __WAIT_CTS_WHILE_SLEEPING__ -volatile int sleep = 0; -static UI_FUNCTION_ADV_CALLBACK(menu_sleep_acb) -{ - (void)data; - (void)item; - if (b){ - b->icon = sleep == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; - return; - } - sleep = !sleep; -} -#endif - -static UI_FUNCTION_ADV_CALLBACK(menu_debug_avoid_acb) -{ - (void)data; - (void)item; - if (b){ - b->icon = debug_avoid == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; - return; - } - toggle_debug_avoid(); - // menu_move_back(); - ui_mode_normal(); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_debug_freq_acb) -{ - (void)data; - (void)item; - if (b){ - b->icon = debug_frequencies == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; - return; - } - debug_frequencies = ! debug_frequencies; - // menu_move_back(); - ui_mode_normal(); -} - - -static UI_FUNCTION_ADV_CALLBACK(menu_linear_averaging_acb) -{ - (void)data; - (void)item; - if (b){ - b->icon = linear_averaging == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; - return; - } - linear_averaging = ! linear_averaging; - dirty = true; - // menu_move_back(); - ui_mode_normal(); -} - - -#endif - -#ifdef __ULTRA__ -static UI_FUNCTION_ADV_CALLBACK(menu_ultra_acb) -{ - (void)data; - (void)item; - if (b){ - b->icon = config.ultra == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; - return; - } - if (!config.ultra) { - drawMessageBox("Info", "Visit tinysa.org/ultra for unlock code", 2000); - - kp_help_text = "Ultra unlock code"; - ui_mode_keypad(KM_CODE); - if (uistat.value != 4321) - return; - } - config.ultra = !config.ultra; - config_save(); - reset_settings(M_LOW); - if (config.ultra){ - set_sweep_frequency(ST_START, 0); - set_sweep_frequency(ST_STOP, 3000000000ULL); - } - // menu_move_back(false); - ui_mode_normal(); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_direct_acb) -{ - (void)data; - (void)item; - if (b){ - b->icon = config.direct == 0 ? BUTTON_ICON_NOCHECK : BUTTON_ICON_CHECK; - return; - } - config.direct = !config.direct; - config_save(); - // menu_move_back(false); - ui_mode_normal(); -} - -#endif - -static UI_FUNCTION_CALLBACK(menu_clearconfig_cb) -{ - (void)data; - (void)item; - kp_help_text = "Clear unlock code"; - ui_mode_keypad(KM_CODE); - if (uistat.value != 1234) - return; - clear_all_config_prop_data(); -#ifndef TINYSA4 -#define SCB_AIRCR_VECTKEYSTAT_LSB 16 -#define SCB_AIRCR_VECTKEYSTAT (0xFFFF << SCB_AIRCR_VECTKEYSTAT_LSB) -#define SCB_AIRCR_VECTKEY (0x05FA << SCB_AIRCR_VECTKEYSTAT_LSB) -#define SCB_AIRCR_SYSRESETREQ (1 << 2) - SCB->AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_SYSRESETREQ; - while(true); -#else - rccEnableWWDG(FALSE); - WWDG->CFR = 0x60; - WWDG->CR = 0xff; - /* wait forever */ -#endif - while (1) - ; -} - -float nf_gain; -const char * const averageText[] = { "OFF", "MINH", "MAXH", "MAXD", " AVER4", "A16", "AVER", "QUASI", "TABLE", "DECONV"}; - -static UI_FUNCTION_ADV_CALLBACK(menu_measure_acb) -{ - (void)item; - if (b){ - b->icon = data == setting.measurement ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - return; - } - menu_move_back(false); - markers_reset(); - - if ((data != M_OFF && setting.measurement != M_OFF) || data == M_OFF ) - { - // reset_settings(setting.mode); - if (0) { - no_measurement: - drawMessageBox("Error", "Incorrect input", 2000); - redraw_request|= REDRAW_AREA; - - data = M_OFF; - } - if (setting.measurement == M_LINEARITY) { - TRACE_DISABLE(TRACE_STORED_FLAG); - } - set_average(0,AV_OFF); - set_external_gain(0.0); -#ifdef TINYSA4 - set_extra_lna(false); -#endif - } - switch(data) { - case M_OFF: // Off -// set_measurement(M_OFF); - break; - case M_IMD: // IMD - reset_settings(setting.mode); - for (int i = 1; i< MARKERS_MAX; i++) { - markers[i].mtype = M_DELTA; - } - kp_help_text = "Frequency of fundamental"; - ui_mode_keypad(KM_CENTER); - set_sweep_frequency(ST_START, 0); - set_sweep_frequency(ST_STOP, uistat.value*(MARKERS_MAX+1)); - set_average(0,AV_4); -// set_measurement(M_IMD); - break; - case M_OIP3: // OIP3 - reset_settings(setting.mode); - for (int i = 0; i< 4; i++) { - markers[i].enabled = M_ENABLED; - } - markers[1].mtype = M_TRACKING; - kp_help_text = "Frequency of left signal"; - ui_mode_keypad(KM_CENTER); - freq_t left = uistat.value; - kp_help_text = "Right signal"; - ui_mode_keypad(KM_CENTER); - freq_t right = uistat.value; - set_sweep_frequency(ST_CENTER, (left+right)/2); - freq_t local_span = (right - left)*10; -#ifdef TINYSA4 - if (local_span < 3000) - local_span = 3000; -#else - if (local_span < 30000) - local_span = 30000; -#endif - set_sweep_frequency(ST_SPAN, local_span); - set_average(0,AV_4); -// set_measurement(M_OIP3); - break; - case M_PHASE_NOISE: // Phase noise - reset_settings(setting.mode); - markers[1].enabled = M_ENABLED; - markers[1].mtype = M_DELTA | M_NOISE; - kp_help_text = "Frequency of signal"; - ui_mode_keypad(KM_CENTER); - kp_help_text = "Frequency offset"; - ui_mode_keypad(KM_SPAN); - set_sweep_frequency(ST_SPAN, uistat.value*4); -// set_measurement(M_PHASE_NOISE); - set_average(0,AV_4); - - break; - case M_SNR: // STop band measurement - reset_settings(setting.mode); - kp_help_text = "Frequency of signal"; - ui_mode_keypad(KM_CENTER); - kp_help_text = "Bandwidth"; - ui_mode_keypad(KM_SPAN); - set_sweep_frequency(ST_SPAN, uistat.value*3); -// set_measurement(M_SNR); - set_average(0,AV_4); - - break; - case M_PASS_BAND: // pass band measurement -// reset_settings(setting.mode); - markers[1].enabled = M_ENABLED; - markers[2].enabled = M_ENABLED; -// kp_help_text = "Frequency of signal"; -// ui_mode_keypad(KM_CENTER); -// kp_help_text = "Width of signal"; -// ui_mode_keypad(KM_SPAN); -// set_sweep_frequency(ST_SPAN, uistat.value*2); - set_measurement(M_PASS_BAND); -// SetAverage(4); - - break; -#ifdef __LINEARITY__ - case M_LINEARITY: - TRACE_ENABLE(TRACE_STORED_FLAG); -// set_measurement(M_LINEARITY); - break; -#endif - case M_AM: // AM - reset_settings(setting.mode); - for (int i = 1; i< 3; i++) { - markers[i].enabled = M_ENABLED; -#ifdef TINYSA4 - markers[i].mtype = M_DELTA| M_TRACKING; -#else -// markers[i].mtype = M_DELTA;// | M_TRACKING; -#endif - } -#ifdef TINYSA4 - freq_t span; -#else - freq_t center, span; - markers[0].mtype = M_NORMAL; // M_REFERENCE | M_TRACKING; // Not M_TRACKING!!!! -#endif - kp_help_text = "Frequency of signal"; - ui_mode_keypad(KM_CENTER); -#ifdef TINYSA3 - center = uistat.value; -#endif -#ifdef TINYSA4 - kp_help_text = "Modulation frequency: 500hz .. 10kHz"; -#else - kp_help_text = "Modulation frequency: 3 .. 10kHz"; -#endif - ui_mode_keypad(KM_SPAN); - span = uistat.value; -#ifdef TINYSA4 - if (span < 500 || span > 10000) - goto no_measurement; -#endif -#ifdef TINYSA4 - set_RBW((span * 5 / 50) / 100); -#endif - set_sweep_frequency(ST_SPAN, span * 5); -// update_frequencies(); // To ensure markers are positioned right!!!!!! -// set_measurement(M_AM); -#ifndef TINYSA4 - set_marker_frequency(0, center); - set_marker_frequency(1, center-span); - set_marker_frequency(2, center+span); -#endif - set_average(0,AV_4); - break; - case M_FM: // FM - reset_settings(setting.mode); - for (int i = 1; i< 3; i++) { - markers[i].enabled = M_ENABLED; - } - markers[0].mtype = M_NORMAL; /// Not M_TRACKING !!!! - kp_help_text = "Frequency of signal"; - ui_mode_keypad(KM_CENTER); - set_marker_frequency(0, uistat.value); -#ifdef TINYSA4 - kp_help_text = "Modulation frequency: 500Hz .. 10kHz"; - ui_mode_keypad(KM_SPAN); - if (uistat.value < 500 || uistat.value > 10000) - goto no_measurement; - set_RBW(uistat.value/300); -#else - kp_help_text = "Modulation frequency: 1 .. 2.5kHz"; - ui_mode_keypad(KM_SPAN); - if (uistat.value < 1000 || uistat.value > 2500) - goto no_measurement; - set_RBW(uistat.value/100); -#endif - // actual_rbw_x10 -#ifdef TINYSA4 - kp_help_text = "Frequency deviation: 3 .. 500kHz"; -#define MINIMUM_DEVIATION 1500 -#else - kp_help_text = "Frequency deviation: 500Hz .. 500kHz"; -#define MINIMUM_DEVIATION 12000 -#endif - ui_mode_keypad(KM_SPAN); - if (uistat.value < MINIMUM_DEVIATION) - uistat.value = MINIMUM_DEVIATION; // minimum span - set_sweep_frequency(ST_SPAN, uistat.value*4); -// set_measurement(M_FM); - break; - case M_THD: - set_average(0,AV_4); -// set_measurement(M_THD); - break; -#ifdef __CHANNEL_POWER__ - case M_CP: // channel power - reset_settings(setting.mode); - markers[0].enabled = M_DISABLED; - kp_help_text = "Channel frequency"; - ui_mode_keypad(KM_CENTER); - kp_help_text = "Channel width"; - ui_mode_keypad(KM_SPAN); - set_sweep_frequency(ST_SPAN, uistat.value*3); -// set_measurement(M_CP); - break; -#endif -#ifdef __NOISE_FIGURE__ - case M_NF_TINYSA: - reset_settings(setting.mode); - set_refer_output(-1); - nf_gain = 0; - goto noise_figure; - case M_NF_STORE: - if (measured_noise_figure > 2 && measured_noise_figure < 20) { - config.noise_figure = measured_noise_figure; - config_save(); - data = M_NF_VALIDATE; // Continue to validate - goto validate; - } else { - drawMessageBox("Error", "NF out of range",1000); - data = M_NF_TINYSA; // Continue to measure - } - break; - case M_NF_VALIDATE: -validate: - nf_gain = 0.00001; // almost zero - goto noise_figure; - case M_NF_AMPLIFIER: // noise figure -#if 0 - reset_settings(setting.mode); - set_refer_output(-1); -#endif - kp_help_text = "Amplifier Gain "; - float old_gain = setting.external_gain; - ui_mode_keypad(KM_EXT_GAIN); - nf_gain = setting.external_gain; - setting.external_gain = old_gain; - noise_figure: - markers[0].enabled = M_ENABLED; - markers[0].mtype = M_NOISE | M_AVER; // Not tracking - set_extra_lna(true); - set_attenuation(0); - if (data == M_NF_TINYSA) { - kp_help_text = "Noise center frequency"; - ui_mode_keypad(KM_CENTER); - set_marker_frequency(0, uistat.value); -#if 0 - kp_help_text = "Noise span"; - ui_mode_keypad(KM_SPAN); -#else - set_sweep_frequency(ST_SPAN, 100000); -#endif - set_RBW(1000); // 300kHz - } - -// set_sweep_frequency(ST_SPAN, 0); - set_average(0,AV_100); - if (data == M_NF_TINYSA || data == M_NF_VALIDATE ) { - menu_push_submenu(menu_measure_noise_figure); - goto leave; - } - break; -#endif -#ifdef __FFT_DECONV__ - case M_DECONV: - set_average(0,AV_DECONV); - break; -#endif - } - -// selection = -1; - ui_mode_normal(); - goto leave; // to get rid of warning -leave: - set_measurement(data); -// draw_cal_status(); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_atten_acb) -{ - (void)item; - (void)data; - if(b){ - if (MODE_HIGH(setting.mode)) { - b->param_1.text = "0dB"; - b->icon = (setting.atten_step*30 == data) ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - } - else { - b->param_1.text = "AUTO"; - b->icon = setting.auto_attenuation ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - } - return; - } - if (MODE_HIGH(setting.mode)) { - setting.auto_attenuation = false; - set_attenuation(0); - } else - set_auto_attenuation(); - menu_move_back(true); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_atten_high_acb) -{ - (void)item; - if(b){ - b->icon = (setting.atten_step*30 == data) ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - return; - } - setting.auto_attenuation = false; - set_attenuation(data); - menu_move_back(true); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_reflevel_acb) -{ - (void)item; - (void)data; - if(b){ - b->icon = setting.auto_reflevel ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - return; - } - set_auto_reflevel(true); - menu_move_back(true); -} - -static uint8_t current_trace = TRACE_ACTUAL; - -static UI_FUNCTION_ADV_CALLBACK(menu_average_acb) -{ - (void)item; - if (b){ - b->icon = setting.average[current_trace] == data ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - return; - } - set_average(current_trace,data); - if (data == AV_TABLE) - menu_push_submenu(menu_limit_select); - else { - ui_mode_normal(); - } -// menu_move_back(true); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_trace_acb) -{ - (void)item; - if(b){ - b->param_1.i = data+1; - b->icon = (data == current_trace) ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - b->bg = LCD_TRACE_1_COLOR+data; - return; - } - if (setting.normalized_trace != -1 && data == TRACE_TEMP) { - drawMessageBox("Error", "Disable normalization first", 2000); - redraw_request|= REDRAW_AREA; - } else - current_trace = data; - menu_move_back(false); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_marker_trace_acb) -{ - (void)item; - if(b){ - b->param_1.i = data+1; - b->icon = (data == markers[active_marker].trace) ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - b->bg = LCD_TRACE_1_COLOR+data; - return; - } - markers[active_marker].trace = data; - menu_move_back(false); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_store_trace_acb) -{ - (void)item; - if(b){ - plot_printf(b->text, sizeof(b->text), S_RARROW"TRACE %d", data+1); - b->bg = LCD_TRACE_1_COLOR+data; - if (current_trace == data) - b->fg = LCD_DARK_GREY; - return; - } - store_trace(current_trace,data); - menu_move_back(false); -} - - -static UI_FUNCTION_ADV_CALLBACK(menu_subtract_trace_acb) -{ - (void)item; - if(b){ - if (data) { - plot_printf(b->text, sizeof(b->text), "SUBTRACT\nTRACE %d", data); - b->bg = LCD_TRACE_1_COLOR+data-1; - } - else - plot_printf(b->text, sizeof(b->text), "SUBTRACT\nOFF"); - b->icon = (data == setting.subtract[current_trace]) ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - if (data - 1 == current_trace) - b->fg = LCD_DARK_GREY; - return; - } - subtract_trace(current_trace,data-1); - menu_move_back(false); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_traces_acb) -{ - (void)item; - int count = 0; - if(b){ - if (data == 0) { // Select trace - b->param_1.i = current_trace+1; - b->bg = LCD_TRACE_1_COLOR+current_trace; - } else if (data == 1) { // View - b->icon = IS_TRACE_ENABLE(current_trace) ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - } - else if (data == 2) // freeze - b->icon = setting.stored[current_trace] ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - else if (data == 5) { - if (setting.subtract[current_trace]) { - b->icon = BUTTON_ICON_CHECK; - plot_printf(b->text, sizeof(b->text), "SUBTRACT\nTRACE %d", setting.subtract[current_trace]); - } else { - b->icon = BUTTON_ICON_NOCHECK; - plot_printf(b->text, sizeof(b->text), "SUBTRACT\nOFF"); - } - // b->icon = setting.subtract[current_trace] ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; // icon not needed - } else if (data == 4) { - if (current_trace == TRACES_MAX-1) - b->fg = LCD_DARK_GREY; - else - b->icon = setting.normalized[current_trace] ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - } else if (data == 3) { - b->icon = setting.average[current_trace] != AV_OFF ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - plot_printf(b->text, sizeof(b->text), "CALC\n%s", averageText[setting.average[current_trace]]); - // b->icon = setting.average[current_trace] ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; // icon not needed - } - return; - } - switch(data) { - case 0: - menu_push_submenu(menu_trace); - return; - case 1: - for (int i=0;i 1) { // Always 1 trace enabled - TRACE_DISABLE(1<icon = BUTTON_ICON_CHECK; - if (setting.subtract[0]){ - if (data == 2 && setting.show_stored) - b->icon = BUTTON_ICON_CHECK; - if (data == 3 && !setting.show_stored) - b->icon = BUTTON_ICON_CHECK; - } - return; - } - switch(data) { - case 0: - store_trace(0,2); - break; - case 1: - set_clear_storage(); - break; - case 2: - set_subtract_storage(); - break; - case 3: - toggle_normalize(); - if (setting.subtract[0]) { - kp_help_text = "Ref level"; - ui_mode_keypad(KM_REFLEVEL); -// setting.normalize_level = uistat.value; - } else - set_auto_reflevel(true); - break; -#ifdef TINYSA4 - case 4: - save_to_sd(1+2); // frequencies + actual - break; - case 5: - save_to_sd(1+4); // frequencies + stored - break; -#endif - } - ui_mode_normal(); -// draw_cal_status(); -} -#endif - -static UI_FUNCTION_ADV_CALLBACK(menu_waterfall_acb){ - (void)item; - (void)data; - if (b){ -#ifdef TINYSA4 - if (!(sweep_mode & SWEEP_ENABLE)){ - b->icon = (sweep_mode & SWEEP_ONCE) ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - plot_printf(b->text, sizeof(b->text), "SINGLE\nSWEEP"); - } else { - b->icon = setting.waterfall ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - plot_printf(b->text, sizeof(b->text), "WATER\nFALL"); - } -#else - b->icon = setting.waterfall ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - plot_printf(b->text, sizeof(b->text), "WATER\nFALL"); -#endif - return; - } -#ifdef TINYSA4 - if (is_paused()) { - resume_once(1); - } else -#endif - { - setting.waterfall++; if (setting.waterfall>W_BIG)setting.waterfall = W_OFF; - if (setting.waterfall != W_OFF) - setting.level_meter = false; - set_waterfall(); - ui_mode_normal(); - } -} - -#ifdef __LEVEL_METER__ -static UI_FUNCTION_ADV_CALLBACK(menu_level_meter_acb){ - (void)item; - (void)data; - if (b){ - b->icon = setting.level_meter ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - return; - } - setting.level_meter = !setting.level_meter; - if (setting.level_meter) - setting.waterfall = W_OFF; - set_level_meter(); - ui_mode_normal(); -} -#endif - - -#ifdef __LIMITS__ -uint8_t active_limit = 0; -static UI_FUNCTION_ADV_CALLBACK(menu_limit_select_acb) -{ - (void)item; - if(b){ - int count = 0; - for (int i=0;iicon = (setting.limits[current_trace][data].enabled?BUTTON_ICON_CHECK:BUTTON_ICON_NOCHECK) ; - plot_printf(b->text, sizeof(b->text), "%.6FHz\n%.2F%s", (float)setting.limits[current_trace][data].frequency, value(setting.limits[current_trace][data].level),unit_string[setting.unit]); - return; - } - active_limit = data; - setting.limits[current_trace][active_limit].enabled = true; - dirty = true; - limits_update(); - menu_push_submenu(menu_limit_modify); -} - -#endif - -extern const menuitem_t menu_marker_select[]; - -static UI_FUNCTION_ADV_CALLBACK(menu_marker_modify_acb) -{ - (void)item; - if (active_marker == MARKER_INVALID) return; - if(b){ - uistat.text[0] = 0; - uistat.text[1] = 0; - switch(data) { - case 0: - uistat.text[0] = active_marker+'1'; - break; - case M_DELTA: - uistat.text[0] = markers[active_marker].ref+'1'; - /* fall through */ - case M_NOISE: - case M_TRACKING: - case M_AVER: - b->icon = BUTTON_ICON_NOCHECK; - if (markers[active_marker].mtype & data) - b->icon = BUTTON_ICON_CHECK; - break; - case M_STORED: - uistat.text[0] = markers[active_marker].trace+'1'; - b->bg = LCD_TRACE_1_COLOR+markers[active_marker].trace; - break; - } - b->param_1.text = uistat.text; - return; - } - if (data == M_DELTA && !(markers[active_marker].mtype & M_DELTA)) { // Not yet set - menu_push_submenu(menu_marker_ref_select); - goto set_delta; - return; - } else if (data == M_STORED) { - current_trace = 0; - menu_push_submenu(menu_marker_trace); - return; - } else if (markers[active_marker].mtype & data) - markers[active_marker].mtype &= ~data; - else if (data) { - set_delta: - markers[active_marker].mtype |= data; - } else - menu_push_submenu(menu_marker_select); - markmap_all_markers(); -// redraw_marker(active_marker, TRUE); -// menu_move_back(false); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_marker_ref_select_acb) -{ - (void)item; - if(b){ -// b->icon = markers[data-1].enabled ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - b->icon = (markers[active_marker].ref == data-1 ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP ); - b->param_1.i = data; - return; - } - markers[data-1].enabled = true; -// interpolate_maximum(data-1); // possibly not a maximum - set_marker_index(data-1, markers[data-1].index); - markers[active_marker].ref = data-1; - redraw_marker(active_marker); - menu_move_back(false); -} - -extern const menuitem_t menu_marker_modify[]; -static UI_FUNCTION_ADV_CALLBACK(menu_marker_select_acb) -{ - (void)item; - if(b){ - b->icon = markers[data-1].enabled ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - b->param_1.i = data; - return; - } - markers[data-1].enabled = true; -// interpolate_maximum(data-1); // possibly not a maximum - set_marker_index(data-1, markers[data-1].index); - active_marker_select(data-1); -// menu_push_submenu(menu_marker_modify); - redraw_marker(active_marker); - menu_move_back(false); -} - -static UI_FUNCTION_CALLBACK(menu_marker_delete_cb) -{ - (void)item; - (void)data; - if (active_marker>=0){ - for (int i = 0; iparam_1.text = rbwsel_text[data]; -#else - b->param_1.u = rbwsel_x10[data]/10; -#endif - b->icon = setting.rbw_x10 == rbwsel_x10[data] ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - return; - } - set_RBW(rbwsel_x10[data]); - menu_move_back(true); -} - -#ifdef __VBW__ -static UI_FUNCTION_ADV_CALLBACK(menu_vbw_acb) -{ - (void)item; - if (b){ - b->param_1.f = vbwsel_x100[data] > 0 ? 1.0f/vbwsel_x100[data] : 0; - b->icon = setting.vbw_x100 == vbwsel_x100[data] ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - return; - } - set_VBW(vbwsel_x100[data]); - menu_move_back(true); -} - -#endif - -static UI_FUNCTION_ADV_CALLBACK(menu_unit_acb) -{ - (void)item; - if (b){ - b->icon = data == setting.unit ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - return; - } - set_unit(data); - menu_move_back(true); -} - -#if 0 -enum { - S_20,S_10,S_5,S_2,S_1,S_P5,S_P2,S_P1,S_P05,S_P02,S_P01 -}; -static const float menu_scale_per_value[11]={20,10,5,2,1,0.5,0.2,0.1,0.05,0.02,0.01}; - -static UI_FUNCTION_ADV_CALLBACK(menu_scale_per_acb) -{ - (void)item; - if(b){ - return; - } - set_scale(menu_scale_per_value[data]); - menu_move_back(true); -} -#endif - -const char *mode_text[] = {"PRE","POST","MID"}; - -static UI_FUNCTION_ADV_CALLBACK(menu_trigger_acb) -{ - (void)item; - if(b){ - if (data == T_MODE) { - b->param_1.text = mode_text[setting.trigger_mode - T_PRE]; - } else if (data == T_UP || data == T_DOWN) - b->icon = setting.trigger_direction == data ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - else - b->icon = setting.trigger == data ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - return; - } - if (data == T_MODE) { - setting.trigger_mode += 1; - if (setting.trigger_mode > T_MID) - setting.trigger_mode = T_PRE; - set_trigger(setting.trigger_mode); - } else if (data != T_DONE) { - set_trigger(data); -// menu_move_back(false); - ui_mode_normal(); - } - completed = true; -} - -#if 0 -static void choose_active_trace(void) -{ - int i; - if (trace[uistat.current_trace].enabled) - // do nothing - return; - for (i = 0; i < TRACE_COUNT ; i++) - if (trace[i].enabled) { - uistat.current_trace = i; - return; - } -} -#endif -static void choose_active_marker(void) -{ - int i; - for (i = 0; i < MARKER_COUNT; i++) - if (markers[i].enabled == M_ENABLED) { - active_marker = i; - return; - } - active_marker = MARKER_INVALID; -} -#ifdef TINYSA4 -#define __HARMONIC__ -#endif - -#ifdef __HARMONIC__ -static UI_FUNCTION_ADV_CALLBACK(menu_harmonic_acb) -{ - (void)item; - if(b){ - b->icon = setting.harmonic == data ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - return; - } - set_harmonic(data); -} -#endif - - -static UI_FUNCTION_ADV_CALLBACK(menu_settings_agc_acb){ - (void)item; - (void)data; - if(b){ - b->icon = AUTO_ICON(setting.agc); - return; - } - toggle_AGC(); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_settings_lna_acb){ - (void)item; - (void)data; - if(b){ - if (S_IS_AUTO(setting.lna)) - b->icon = BUTTON_ICON_CHECK_AUTO; - else - b->icon = setting.lna ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - return; - } - toggle_LNA(); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_settings_bpf_acb){ - (void)item; - (void)data; - if(b){ - b->icon = setting.tracking ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - return; - } - toggle_tracking(); -} - -#ifdef __LCD_BRIGHTNESS__ -static UI_FUNCTION_CALLBACK(menu_brightness_cb) -{ - (void)item; - (void)data; - int16_t value = config._brightness; - ili9341_set_foreground(LCD_MENU_TEXT_COLOR); - ili9341_set_background(LCD_MENU_COLOR); - ili9341_fill(LCD_WIDTH/2-80, LCD_HEIGHT/2-20, 160, 40); - ili9341_drawstring_7x13("BRIGHTNESS", LCD_WIDTH/2-35, LCD_HEIGHT/2-13); - ili9341_drawstring_7x13(S_LARROW" USE LEVELER BUTTON "S_RARROW, LCD_WIDTH/2-72, LCD_HEIGHT/2+2); - while (TRUE) { - int status = btn_check(); - if (status & (EVT_UP|EVT_DOWN)) { - do { - if (status & EVT_UP ) value+=5; - if (status & EVT_DOWN) value-=5; - if (value < 0) value = 0; - if (value > 100) value = 100; - lcd_setBrightness(value); - status = btn_wait_release(); - } while (status != 0); - } - if (status == EVT_BUTTON_SINGLE_CLICK) - break; - } - config._brightness = (uint8_t)value; - lcd_setBrightness(value); - redraw_request|= REDRAW_AREA; - ui_mode_normal(); -} -#endif - -static UI_FUNCTION_ADV_CALLBACK(menu_settings_pulse_acb){ - (void)item; - (void)data; - if(b){ - b->icon = setting.pulse ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - return; - } - toggle_pulse(); -} - -#ifdef __DRAW_LINE__ -static UI_FUNCTION_ADV_CALLBACK(menu_settings_draw_line_acb){ - (void)item; - (void)data; - if(b){ - b->icon = setting.draw_line ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - return; - } - toggle_draw_line(); - if (setting.draw_line) { - kp_help_text = "Level"; - ui_mode_keypad(KM_TRIGGER); - set_trigger(T_AUTO); - } -} -#endif -#ifdef __HAM_BAND__ -static UI_FUNCTION_ADV_CALLBACK(menu_settings_ham_bands){ - (void)item; - (void)data; - if(b){ - b->icon = config.hambands ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - return; - } - toggle_hambands(); -} -#endif - -static UI_FUNCTION_ADV_CALLBACK(menu_settings_below_if_acb){ - (void)item; - (void)data; - if(b){ - if (S_IS_AUTO(setting.below_IF)) - b->icon = BUTTON_ICON_CHECK_AUTO; - else - b->icon = setting.below_IF ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - return; - } - toggle_below_IF(); -} - -#if 0 -static UI_FUNCTION_ADV_CALLBACK(menu_settings_ultra_acb){ - (void)item; - (void)data; - if(b){ - if (S_IS_AUTO(setting.ultra)) - b->icon = BUTTON_ICON_CHECK_AUTO; - else - b->icon = setting.ultra ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - return; - } - toggle_ultra(); -} -#endif - -static UI_FUNCTION_ADV_CALLBACK(menu_lo_output_acb){ - (void)item; - (void)data; - if(b){ - b->icon = setting.tracking_output ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - return; - } - toggle_tracking_output(); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_pause_acb) -{ - (void) data; - (void) item; - if (b){ - b->icon = !(sweep_mode & SWEEP_ENABLE) ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - return; - } - toggle_sweep(); -// menu_move_back(true); -// draw_cal_status(); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_flip_acb) -{ - (void) data; - (void) item; - if (b){ - return; - } - config.flip = ! config.flip; - ili9341_flip(config.flip); - config_save(); - redraw_request|= REDRAW_AREA | REDRAW_FREQUENCY | REDRAW_CAL_STATUS; -} - -static UI_FUNCTION_ADV_CALLBACK(menu_shift_acb) -{ - (void) data; - (void) item; - if (b){ - b->icon = setting.frequency_offset != FREQUENCY_SHIFT ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - return; - } - if (setting.frequency_offset != FREQUENCY_SHIFT) { - setting.frequency_offset = FREQUENCY_SHIFT; - } else { - if (FREQ_IS_STARTSTOP()) { - freq_t old_start = get_sweep_frequency(ST_START); - freq_t old_stop = get_sweep_frequency(ST_STOP); - kp_help_text = "Actual start frequency"; - ui_mode_keypad(KM_START); - setting.frequency_offset = uistat.value - old_start + FREQUENCY_SHIFT; - set_sweep_frequency(ST_START, old_start); - set_sweep_frequency(ST_STOP, old_stop); - } else { - freq_t old_center = get_sweep_frequency(ST_CENTER); - freq_t old_span = get_sweep_frequency(ST_SPAN); - kp_help_text = "Actual center frequency"; - ui_mode_keypad(KM_CENTER); - setting.frequency_offset = uistat.value - old_center + FREQUENCY_SHIFT; - set_sweep_frequency(ST_CENTER, old_center); - set_sweep_frequency(ST_SPAN, old_span); - } - } - ui_mode_normal(); -// menu_move_back(true); -// draw_cal_status(); -} - -#ifdef __REMOTE_DESKTOP__ -#if 0 // Not used in UI -static UI_FUNCTION_ADV_CALLBACK(menu_send_display_acb) -{ - (void) data; - (void) item; - if (b){ - b->icon = auto_capture ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; - return; - } - auto_capture = ! auto_capture; - // Update all screen to CPU - if (auto_capture) - redraw_request|=REDRAW_AREA|REDRAW_BATTERY|REDRAW_FREQUENCY|REDRAW_CAL_STATUS; -} -#endif -#endif - -static UI_FUNCTION_ADV_CALLBACK(menu_outputmode_acb) -{ - (void) data; - (void) item; - if(b){ - b->param_1.text = setting.mute ? "OFF" : "ON"; - return; - } - toggle_mute(); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_enter_marker_acb) -{ - (void) data; - (void) item; - if(b){ - b->param_1.text = FREQ_IS_CW() ? "TIME" : "FREQUENCY"; - return; - } - if (FREQ_IS_CW()) - ui_mode_keypad(KM_MARKER_TIME); - else - ui_mode_keypad(KM_MARKER); -} - -#ifdef TINYSA4 -static const uint16_t points_setting[] = {51, 101, 201, 256, 290, 450}; -#else -static const uint16_t points_setting[] = {51, 101, 145, 290}; -#endif -static UI_FUNCTION_ADV_CALLBACK(menu_points_acb){ - (void)item; - if(b){ - b->icon = points_setting[data] == sweep_points ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - b->param_1.i = points_setting[data]; - return; - } - set_sweep_points(points_setting[data]); -} - -#ifdef __USE_SERIAL_CONSOLE__ -static UI_FUNCTION_ADV_CALLBACK(menu_serial_speed_acb) -{ - static const uint32_t usart_speed[] = {19200, 38400, 57600, 115200, 230400, 460800, 921600, 1843200, 2000000, 3000000}; - (void)item; - uint32_t speed = usart_speed[data]; - if (b){ - b->icon = config._serial_speed == speed ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - b->param_1.u = speed; - return; - } - config._serial_speed = speed; - shell_update_speed(); -} - -static UI_FUNCTION_ADV_CALLBACK(menu_connection_acb) -{ - (void)item; - if (b){ - b->icon = (config._mode&_MODE_CONNECTION_MASK) == data ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; - return; - } - config._mode&=~_MODE_CONNECTION_MASK; - config._mode|=data; - config_save(); - shell_reset_console(); -} -#endif -// ===[MENU DEFINITION]========================================================= -// Back button submenu list - -static const menuitem_t menu_back[] = { - { MT_CANCEL, 0, S_LARROW" BACK", NULL }, - { MT_NONE, 0, NULL, NULL } // sentinel -}; - -static const menuitem_t menu_store_preset[] = -{ - { MT_ADV_CALLBACK, 0, "STORE AS\nSTARTUP",menu_store_preset_acb}, - { MT_ADV_CALLBACK |MT_REPEATS, DATA_STARTS_REPEATS(1,4), "STORE %d", menu_store_preset_acb}, - { MT_ADV_CALLBACK, 100,"FACTORY\nDEFAULTS",menu_store_preset_acb}, - { MT_NONE, 0, NULL,menu_back} // next-> menu_back -}; - -static const menuitem_t menu_load_preset[] = -{ - { MT_ADV_CALLBACK, 0, "LOAD\nSTARTUP", menu_load_preset_acb}, - { MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(1,4), MT_CUSTOM_LABEL, menu_load_preset_acb}, - { MT_SUBMENU, 0, "STORE" , menu_store_preset}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; -#ifdef TINYSA4 -static const menuitem_t menu_mixer_drive[] = { - { MT_ADV_CALLBACK, 4, "Auto", menu_mixer_drive_acb}, - { MT_ADV_CALLBACK, 3, "%+ddBm", menu_mixer_drive_acb}, - { MT_ADV_CALLBACK, 2, "%+ddBm", menu_mixer_drive_acb}, - { MT_ADV_CALLBACK, 1, "%+ddBm", menu_mixer_drive_acb}, - { MT_ADV_CALLBACK, 0, "%+ddBm", menu_mixer_drive_acb}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; -#else -static const menuitem_t menu_lo_drive[] = { - { MT_ADV_CALLBACK, 15, "%+ddBm", menu_lo_drive_acb}, - { MT_ADV_CALLBACK, 14, "%+ddBm", menu_lo_drive_acb}, - { MT_ADV_CALLBACK, 13, "%+ddBm", menu_lo_drive_acb}, - { MT_ADV_CALLBACK, 12, "%+ddBm", menu_lo_drive_acb}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; -#endif - -static const menuitem_t menu_modulation[] = { - { MT_FORM | MT_TITLE, 0, "MODULATION",NULL}, - { MT_FORM | MT_ADV_CALLBACK, MO_NONE, MT_CUSTOM_LABEL, menu_modulation_acb}, - { MT_FORM | MT_ADV_CALLBACK | MT_LOW, MO_AM, "AM", menu_modulation_acb}, -#ifdef TINYSA4 - { MT_FORM | MT_ADV_CALLBACK, MO_WFM, "FM", menu_modulation_acb}, - { MT_FORM | MT_KEYPAD, KM_MODULATION, "FREQ: %s", "50Hz..5kHz"}, - { MT_FORM | MT_KEYPAD, KM_DEPTH, "AM DEPTH: %s%%", "0..100"}, - { MT_FORM | MT_KEYPAD, KM_DEVIATION, "FM DEVIATION: %s", "1kHz..300kHz"}, -// { MT_FORM | MT_ADV_CALLBACK, MO_NFM2, MT_CUSTOM_LABEL, menu_modulation_acb}, -// { MT_FORM | MT_ADV_CALLBACK, MO_NFM3, MT_CUSTOM_LABEL, menu_modulation_acb}, -#else - { MT_FORM | MT_ADV_CALLBACK, MO_NFM, MT_CUSTOM_LABEL, menu_modulation_acb}, - { MT_FORM | MT_ADV_CALLBACK, MO_WFM, MT_CUSTOM_LABEL, menu_modulation_acb}, - { MT_FORM | MT_ADV_CALLBACK | MT_LOW, MO_EXTERNAL,MT_CUSTOM_LABEL, menu_modulation_acb}, - { MT_FORM | MT_KEYPAD, KM_MODULATION, "FREQ: %s", "50Hz..5kHz"}, -#endif - { MT_FORM | MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_sweep[] = { - { MT_FORM | MT_KEYPAD, KM_SPAN, "SPAN: %s", VARIANT("0..350MHz", range_text)}, - { MT_FORM | MT_KEYPAD | MT_LOW, KM_LEVELSWEEP,"LEVEL CHANGE: %s", VARIANT("-70..70","-90..90")}, - { MT_FORM | MT_KEYPAD, KM_SWEEP_TIME, "SWEEP TIME: %s", "0..600 seconds"}, - { MT_FORM | MT_SUBMENU, 0, "SWEEP POINTS", menu_sweep_points_form}, - { MT_FORM | MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; -#ifdef TINYSA4 -static const menuitem_t menu_lowoutput_settings[] = { - { MT_FORM | MT_ADV_CALLBACK, 0, "Cleanest signal, max 4.4GHz", menu_lowoutput_settings_acb}, - { MT_FORM | MT_ADV_CALLBACK, 1, "Highest accuracy, max 5.4GHz", menu_lowoutput_settings_acb}, - { MT_FORM | MT_SUBMENU, 255, S_RARROW"Config", menu_config}, - { MT_FORM | MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; -#endif - -char low_level_help_text[12] = "-76..-6"; -char center_text[18] = "FREQ: %s"; - -const menuitem_t menu_lowoutputmode[] = { - { MT_FORM | MT_ADV_CALLBACK, 0, "LOW OUTPUT %s", menu_outputmode_acb}, -// { MT_FORM | MT_ADV_CALLBACK, 0, "MOD: %s", menu_smodulation_acb}, - { MT_FORM | MT_KEYPAD, KM_CENTER, center_text, VARIANT("10kHz..350MHz","10kHz..850MHz")}, - { MT_FORM | MT_KEYPAD, KM_LOWOUTLEVEL, "LEVEL: %s", low_level_help_text}, - { MT_FORM | MT_ADV_CALLBACK, 0, MT_CUSTOM_LABEL, menu_smodulation_acb}, - { MT_FORM | MT_ADV_CALLBACK, 0, MT_CUSTOM_LABEL, menu_sweep_acb}, -#ifdef __SWEEP_RESTART__ - { MT_FORM | MT_ADV_CALLBACK, 0, MT_CUSTOM_LABEL, menu_restart_acb}, -#endif - { MT_FORM | MT_KEYPAD, KM_EXT_GAIN, "EXTERNAL GAIN: %s", "-100..+100"}, -#ifdef TINYSA4 - { MT_FORM | MT_ADV_CALLBACK, 255, "OUTPUT: %s", menu_lowoutput_settings_acb}, -#endif - { MT_FORM | MT_CANCEL, 0, "MODE", NULL }, - { MT_FORM | MT_NONE, 0, NULL, NULL } // sentinel -}; - -const menuitem_t menu_highoutputmode[] = { - { MT_FORM | MT_ADV_CALLBACK, 0, "HIGH OUTPUT %s", menu_outputmode_acb}, - { MT_FORM | MT_KEYPAD, KM_CENTER, center_text, VARIANT("240MHz..959MHz",range_text)}, - { MT_FORM | MT_KEYPAD, KM_HIGHOUTLEVEL, "LEVEL: %s", low_level_help_text /* "-76..-6" */}, - { MT_FORM | MT_ADV_CALLBACK, 0, MT_CUSTOM_LABEL, menu_smodulation_acb}, - { MT_FORM | MT_ADV_CALLBACK, 0, MT_CUSTOM_LABEL, menu_sweep_acb}, -#ifdef __SWEEP_RESTART__ - { MT_FORM | MT_ADV_CALLBACK, 0, MT_CUSTOM_LABEL, menu_restart_acb}, -#endif - { MT_FORM | MT_KEYPAD, KM_EXT_GAIN, "EXTERNAL GAIN: %s", "-100..+100"}, -#ifdef TINYSA4 - { MT_FORM | MT_SUBMENU, 255, S_RARROW" Settings", menu_settings3}, -#endif - { MT_FORM | MT_CANCEL, 0, "MODE", NULL }, - { MT_FORM | MT_NONE, 0, NULL, NULL } // sentinel -}; - -static const menuitem_t menu_average[] = { - { MT_ADV_CALLBACK, AV_OFF, "OFF", menu_average_acb}, - { MT_ADV_CALLBACK, AV_MIN, "MIN\nHOLD", menu_average_acb}, - { MT_ADV_CALLBACK, AV_MAX_HOLD, "MAX\nHOLD", menu_average_acb}, - { MT_ADV_CALLBACK, AV_MAX_DECAY, "MAX\nDECAY", menu_average_acb}, - { MT_ADV_CALLBACK, AV_4, "AVER 4", menu_average_acb}, - { MT_ADV_CALLBACK, AV_16, "AVER 16", menu_average_acb}, -#ifdef TINYSA4 - { MT_ADV_CALLBACK, AV_100, "AVER", menu_average_acb}, -#endif -#ifdef __QUASI_PEAK__ - { MT_ADV_CALLBACK, AV_QUASI, "QUASI\nPEAK", menu_average_acb}, -#endif -#ifdef __LIMITS__ - { MT_ADV_CALLBACK, AV_TABLE, "TABLE"S_RARROW"\nTRACE", menu_average_acb}, -#endif - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_rbw[] = { - { MT_ADV_CALLBACK, 0, " AUTO", menu_rbw_acb}, -#ifdef TINYSA4 - { MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(1,9), "%sHz", menu_rbw_acb}, -#else - { MT_ADV_CALLBACK | MT_REPEATS, DATA_STARTS_REPEATS(1,6), "%4dkHz", menu_rbw_acb}, -#endif - { MT_NONE, 0, NULL, menu_back} // next-> menu_back - -}; - -#ifdef __VBW__ -static const menuitem_t menu_vbw[] = { - { MT_ADV_CALLBACK, 0, " AUTO", menu_vbw_acb}, - { MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(1,5), "%b.2f RBW", menu_vbw_acb}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; -#endif - -static const menuitem_t menu_reffer[] = { - { MT_FORM | MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(0,8), "%s", menu_reffer_acb}, - { MT_FORM | MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_atten[] = { - { MT_ADV_CALLBACK, 0, "%s", menu_atten_acb}, - { MT_KEYPAD | MT_LOW, KM_ATTENUATION, "MANUAL\n\b%s", "0 - 30dB"}, -// { MT_ADV_CALLBACK | MT_HIGH,0, "0dB", menu_atten_high_acb}, - { MT_ADV_CALLBACK | MT_HIGH,30, "22.5 - 40dB", menu_atten_high_acb}, - { MT_FORM | MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_reflevel[] = { - { MT_ADV_CALLBACK,0, "AUTO", menu_reflevel_acb}, - { MT_KEYPAD, KM_REFLEVEL, "MANUAL\n\b%s", NULL}, - { MT_CANCEL, 0, S_LARROW" BACK", NULL }, - { MT_NONE, 0, NULL, NULL } // sentinel -}; - -const menuitem_t menu_marker_search[] = { - { MT_CALLBACK, 4, "PEAK\n SEARCH", menu_marker_search_cb }, - { MT_CALLBACK, 0, "MIN\n" S_LARROW" LEFT", menu_marker_search_cb }, - { MT_CALLBACK, 1, "MIN\n" S_RARROW" RIGHT", menu_marker_search_cb }, - { MT_CALLBACK, 2, "MAX\n" S_LARROW" LEFT", menu_marker_search_cb }, - { MT_CALLBACK, 3, "MAX\n" S_RARROW" RIGHT", menu_marker_search_cb }, - { MT_ADV_CALLBACK, 0, "ENTER\n%s", menu_enter_marker_acb}, - { MT_ADV_CALLBACK, M_TRACKING, "TRACKING",menu_marker_modify_acb }, -#ifdef TINYSA4 - { MT_KEYPAD, KM_NOISE, "PEAK\n\b%s", "2..20 dB"}, -#endif - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -const menuitem_t menu_marker_modify[] = { - { MT_ADV_CALLBACK, 0, "MARKER %s", menu_marker_modify_acb}, - { MT_ADV_CALLBACK, M_DELTA, "DELTA %s", menu_marker_modify_acb}, - { MT_ADV_CALLBACK, M_NOISE, "NOISE", menu_marker_modify_acb}, - { MT_ADV_CALLBACK, M_TRACKING, "TRACKING", menu_marker_modify_acb}, - { MT_ADV_CALLBACK, M_STORED, "TRACE %s", menu_marker_modify_acb}, - { MT_ADV_CALLBACK, M_AVER, "TRACE\nAVERAGE", menu_marker_modify_acb}, - { MT_SUBMENU, 0, "SEARCH", menu_marker_search}, - { MT_CALLBACK, M_DELETE, "DELETE", menu_marker_delete_cb}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -#ifdef __LIMITS__ -static const menuitem_t menu_limit_modify[] = -{ - { MT_KEYPAD, KM_LIMIT_FREQ, "FREQUENCY\n\b%s", "Frequency"}, - { MT_KEYPAD, KM_LIMIT_LEVEL, "LEVEL\n\b%s", "Level"}, - { MT_CALLBACK, 0, "DISABLE", menu_limit_disable_cb}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_limit_select[] = { - { MT_ADV_CALLBACK | MT_REPEATS, DATA_STARTS_REPEATS(0,LIMITS_MAX), MT_CUSTOM_LABEL, menu_limit_select_acb }, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; -#endif - -#if 0 -const menuitem_t menu_marker_sel[] = { - { MT_CALLBACK, 1, "MARKER %d", menu_marker_sel_cb }, - { MT_CALLBACK, 2, "MARKER %d", menu_marker_sel_cb }, - { MT_CALLBACK, 3, "MARKER %d", menu_marker_sel_cb }, - { MT_CALLBACK, 4, "MARKER %d", menu_marker_sel_cb }, -// { MT_CALLBACK, 0, "ALL OFF", menu_marker_sel_cb }, - { MT_CALLBACK, 0, "DELTA", menu_marker_sel_cb }, - { MT_CALLBACK, 0, "NOISE", menu_marker_sel_cb }, - { MT_CALLBACK, 0, "TRACKING", menu_marker_sel_cb }, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; -#endif - -const menuitem_t menu_marker_select[] = { - { MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(1,MARKER_COUNT), "MARKER %d", menu_marker_select_acb }, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_marker_ref_select[] = { - { MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(1,MARKER_COUNT), S_RARROW"MARKER %d", menu_marker_ref_select_acb }, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -const menuitem_t menu_marker_ops[] = { - { MT_CALLBACK, ST_START, S_RARROW" START", menu_marker_op_cb }, - { MT_CALLBACK, ST_STOP, S_RARROW" STOP", menu_marker_op_cb }, - { MT_CALLBACK, ST_CENTER, S_RARROW" CENTER", menu_marker_op_cb }, - { MT_CALLBACK, ST_SPAN, S_RARROW" SPAN", menu_marker_op_cb }, - { MT_CALLBACK, 4, S_RARROW" REF LEVEL",menu_marker_op_cb }, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_marker[] = { -// { MT_SUBMENU, 0, "SELECT\nMARKER", menu_marker_sel}, - { MT_SUBMENU, 0, "MODIFY\nMARKERS", menu_marker_modify}, - { MT_SUBMENU, 0, "MARKER\nOPS", menu_marker_ops}, - { MT_SUBMENU, 0, "SEARCH\nMARKER", menu_marker_search}, - { MT_CALLBACK, 0, "RESET\nMARKERS", menu_markers_reset_cb}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -#ifndef TINYSA4 -static const menuitem_t menu_dfu[] = { - { MT_FORM | MT_CALLBACK, 0, "ENTER DFU", menu_dfu_cb}, - { MT_FORM | MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; -#endif - -#ifdef __HARMONIC__ -static const menuitem_t menu_harmonic[] = -{ - { MT_ADV_CALLBACK, 0, "OFF", menu_harmonic_acb}, - { MT_ADV_CALLBACK, 2, "2", menu_harmonic_acb}, - { MT_ADV_CALLBACK, 3, "3", menu_harmonic_acb}, - { MT_ADV_CALLBACK, 4, "4", menu_harmonic_acb}, - { MT_ADV_CALLBACK, 5, "5", menu_harmonic_acb}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; -#endif - - -static const menuitem_t menu_scanning_speed[] = -{ -// { MT_ADV_CALLBACK, SD_NORMAL, "NORMAL", menu_scanning_speed_acb}, // order must match definition of enum -// { MT_ADV_CALLBACK, SD_PRECISE, PRECISE", menu_scanning_speed_acb}, -// { MT_ADV_CALLBACK | MT_LOW,SD_FAST, "FAST", menu_scanning_speed_acb}, -// { MT_KEYPAD | MT_LOW,KM_FAST_SPEEDUP, "FAST\nSPEEDUP", "2..20"}, - { MT_KEYPAD, KM_SAMPLETIME, "SDELAY\n\b%s", "250..10000, 0=auto"}, // This must be item 4 to match highlighting - { MT_KEYPAD, KM_OFFSET_DELAY, "ODELAY\n\b%s", "250..10000, 0=auto"}, // This must be item 5 to match highlighting - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_sweep_points[] = { -#ifdef TINYSA4 - { MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(0,6), "%3d point", menu_points_acb }, -#else - { MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(0,4), "%3d point", menu_points_acb }, -#endif - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_sweep_points_form[] = { -#ifdef TINYSA4 - { MT_FORM|MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(0,6), "%3d point", menu_points_acb }, -#else - { MT_FORM|MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(0,4), "%3d point", menu_points_acb }, -#endif - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_sweep_speed[] = -{ - { MT_ADV_CALLBACK, SD_NORMAL, "NORMAL", menu_scanning_speed_acb}, // order must match definition of enum - { MT_ADV_CALLBACK, SD_PRECISE, "PRECISE", menu_scanning_speed_acb}, -#ifdef TINYSA4 - { MT_ADV_CALLBACK, SD_FAST, "FAST", menu_scanning_speed_acb}, -#else - { MT_ADV_CALLBACK | MT_LOW,SD_FAST, "FAST", menu_scanning_speed_acb}, -#endif - { MT_ADV_CALLBACK, SD_NOISE_SOURCE, "NOISE\nSOURCE", menu_scanning_speed_acb}, -#ifdef TINYSA4 - { MT_KEYPAD, KM_FAST_SPEEDUP,"SPEEDUP\n\b%s", "2..20, 0=disable"}, -#else - { MT_KEYPAD | MT_LOW,KM_FAST_SPEEDUP,"SPEEDUP\n\b%s", "2..20, 0=disable"}, -#endif - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -#ifdef TINYSA4 -static const menuitem_t menu_curve3[] = { - { MT_FORM | MT_ADV_CALLBACK | MT_REPEATS, DATA_STARTS_REPEATS(14,6), MT_CUSTOM_LABEL, menu_curve_acb }, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_curve2[] = { - { MT_FORM | MT_ADV_CALLBACK | MT_REPEATS, DATA_STARTS_REPEATS(7,7), MT_CUSTOM_LABEL, menu_curve_acb }, - { MT_FORM | MT_SUBMENU, 0, S_RARROW" MORE", menu_curve3}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_curve[] = { - { MT_FORM | MT_ADV_CALLBACK | MT_REPEATS, DATA_STARTS_REPEATS(0,7), MT_CUSTOM_LABEL, menu_curve_acb }, - { MT_FORM | MT_SUBMENU, 0, S_RARROW" MORE", menu_curve2}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_curve_confirm[] = { - { MT_CALLBACK, 1, "OK", menu_curve_confirm_cb }, - { MT_CALLBACK, 0, "CANCEL", menu_curve_confirm_cb }, - { MT_NONE, 0, NULL, NULL } // sentinel -}; - -static const menuitem_t menu_noise_figure_confirm[] = { - { MT_CALLBACK, 1, "STORE\nTINYSA NF", menu_noise_figure_confirm_cb }, - { MT_CALLBACK, 0, "CANCEL", menu_noise_figure_confirm_cb }, - { MT_NONE, 0, NULL, NULL } // sentinel -}; - -#endif - -#ifdef TINYSA4 -static const menuitem_t menu_actual_power2[] = -{ - { MT_ADV_CALLBACK, 0, "30MHz\nLEVEL", menu_output_level_acb}, - { MT_ADV_CALLBACK, 0, "1GHz\nLEVEL", menu_output_level2_acb}, - { MT_ADV_CALLBACK, 0, "1.2GHz\nLEVEL", menu_output_level3_acb}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; -#endif - -static const menuitem_t menu_actual_power[] = -{ - { MT_KEYPAD, KM_ACTUALPOWER, "INPUT\nLEVEL", "Enter actual level under marker"}, -#ifdef TINYSA4 - { MT_SUBMENU, 0, "OUTPUT\nLEVEL", menu_actual_power2}, - { MT_CALLBACK, 0, "INPUT\nCURVE", menu_input_curve_prepare_cb}, - { MT_CALLBACK, 0, "LNA\nCURVE", menu_lna_curve_prepare_cb}, - { MT_CALLBACK, 0, "ULTRA\nCURVE", menu_ultra_curve_prepare_cb}, - { MT_CALLBACK, 0, "LNA_U\nCURVE", menu_lna_u_curve_prepare_cb}, - { MT_CALLBACK, 0, "OUTPUT\nCURVE", menu_output_curve_prepare_cb}, -#else - { MT_ADV_CALLBACK, 0, "OUTPUT\nLEVEL", menu_output_level_acb}, -#endif - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -#ifdef TINYSA4 -static const menuitem_t menu_settings4[]; -#endif - -#ifdef TINYSA4 -static const menuitem_t menu_settings4[] = -{ - { MT_ADV_CALLBACK, 0, "DEBUG\nFREQ", menu_debug_freq_acb}, - { MT_ADV_CALLBACK, 0, "DEBUG\nAVOID", menu_debug_avoid_acb}, - { MT_ADV_CALLBACK, 0, "DEBUG\nSPUR", menu_debug_spur_acb}, - { MT_ADV_CALLBACK, 0, "HIDE\n21MHz", menu_hide_21MHz_acb}, -#if 0 // only used during development - { MT_KEYPAD, KM_COR_AM, "COR\nAM", "Enter AM modulation correction"}, - { MT_KEYPAD, KM_COR_WFM, "COR\nWFM", "Enter WFM modulation correction"}, - { MT_KEYPAD, KM_COR_NFM, "COR\nNFM", "Enter NFM modulation correction"}, -#endif -// { MT_CALLBACK, 0 , "CLEAR\nCONFIG", menu_clearconfig_cb}, -// { MT_SUBMENU, 0, S_RARROW" MORE", menu_settings3}, - { MT_KEYPAD, KM_DIRECT_START, "DSTART\n\b%s", ""}, - { MT_KEYPAD, KM_DIRECT_STOP, "DSTOP\n\b%s", ""}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; -#endif - -static const menuitem_t menu_settings3[] = -{ -#ifdef TINYSA4 -// { MT_KEYPAD, KM_GRIDLINES, "MINIMUM\nGRIDLINES", "Enter minimum horizontal grid divisions"}, -#ifndef __NEW_SWITCHES__ - { MT_ADV_CALLBACK, 0, "ADF OUT", menu_adf_out_acb}, -#endif - { MT_KEYPAD, KM_ULTRA_START,"ULTRASTART\n\b%s", "10G=auto"}, -// { MT_KEYPAD | MT_LOW, KM_IF2, "IF2 FREQ", "Set to zero for no IF2"}, - { MT_KEYPAD, KM_R, "R\n\b%s", "Set R"}, - { MT_KEYPAD, KM_MOD, "MODULO\n\b%s", "Set MODULO"}, - { MT_KEYPAD, KM_CP, "CP", "Set CP"}, -#ifdef __WAIT_CTS_WHILE_SLEEPING__ - { MT_ADV_CALLBACK, 0, "SLEEP\nWAIT", menu_sleep_acb}, -#endif -#ifdef __HARMONIC__ - { MT_SUBMENU ,0, "HARMONIC", menu_harmonic}, -#endif -// { MT_ADV_CALLBACK | MT_LOW, 0, "ULTRA\nMODE", menu_settings_ultra_acb}, -#ifdef __HAM_BAND__ - { MT_ADV_CALLBACK, 0, "HAM\nBANDS", menu_settings_ham_bands}, -#endif - { MT_SUBMENU, 0, S_RARROW" MORE", menu_settings4}, -#else -#ifdef __ULTRA__ - { MT_ADV_CALLBACK, 0, "ENABLE\nULTRA", menu_ultra_acb}, - { MT_KEYPAD, KM_ULTRA_START, "ULTRA\nSTART", "Enter ULTRA mode start freq"}, - { MT_ADV_CALLBACK, 0, "DEBUG\nSPUR", menu_debug_spur_acb}, -#endif -#ifdef __HARMONIC__ - { MT_SUBMENU | MT_HIGH,0, "HARMONIC", menu_harmonic}, -// { MT_ADV_CALLBACK,0, "SPUR\nREMOVAL", menu_harmonic_spur_acb}, -#endif -#ifdef __HAM_BAND__ - { MT_ADV_CALLBACK, 0, "HAM\nBANDS", menu_settings_ham_bands}, -#endif -#endif // TINYSA4 - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_settings2[] = -{ - { MT_ADV_CALLBACK, 0, "AGC", menu_settings_agc_acb}, - { MT_ADV_CALLBACK, 0, "LNA", menu_settings_lna_acb}, - { MT_ADV_CALLBACK | MT_LOW, 0, "BPF", menu_settings_bpf_acb}, - { MT_ADV_CALLBACK | MT_LOW, 0, "BELOW IF", menu_settings_below_if_acb}, - { MT_KEYPAD | MT_LOW, KM_IF, "IF FREQ\n\b%s", "0=auto IF"}, -#ifdef TINYSA4 - #ifdef __QUASI_PEAK__ - { MT_KEYPAD, KM_DECAY, "DECAY\n\b%s", "0..1000000ms or sweeps"}, - { MT_KEYPAD, KM_ATTACK, "ATTACK\n\b%s", "0..100000ms"}, -#endif -#endif - { MT_SUBMENU,0, "SCAN\nSPEED", menu_scanning_speed}, -#ifdef TINYSA4 - { MT_SUBMENU | MT_LOW,0, "MIXER\nDRIVE", menu_mixer_drive}, - { MT_SUBMENU, 0, S_RARROW" MORE", menu_settings3}, -#else - { MT_SUBMENU | MT_LOW,0, "MIXER\nDRIVE", menu_lo_drive}, - { MT_KEYPAD, KM_10MHZ, "CORRECT\nFREQUENCY", "Enter actual l0MHz frequency"}, -#endif - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - - -static const menuitem_t menu_settings[] = -{ -#ifdef TINYSA4 - { MT_ADV_CALLBACK,0, "PROGRESS\nBAR", menu_progress_bar_acb}, - { MT_ADV_CALLBACK, 0, "DIRECT\nMODE", menu_direct_acb}, - { MT_ADV_CALLBACK, 0, "LINEAR\nAVERAGING", menu_linear_averaging_acb}, - { MT_KEYPAD, KM_FREQ_CORR, "FREQ CORR\n\b%s", "Enter ppb correction"}, -// { MT_SUBMENU, 0, "CALIBRATE\nHARMONIC", menu_calibrate_harmonic}, -#endif -#ifdef __NOISE_FIGURE__ - { MT_KEYPAD, KM_NF, "NF\n\b%s", "Enter tinySA noise figure"}, -#endif -#ifdef __SD_CARD_LOAD__ - { MT_CALLBACK, 0 , "LOAD\nCONFIG.INI", menu_load_config_cb}, -// { MT_CALLBACK, 1 , "LOAD\nSETTING.INI", menu_load_config_cb}, -#endif -#ifdef TINYSA4 - { MT_ADV_CALLBACK, 0, "INTERNALS", menu_internals_acb}, -#endif - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -#ifdef __NOISE_FIGURE__ -static const menuitem_t menu_measure_noise_figure[] = -{ - { MT_ADV_CALLBACK, M_NF_TINYSA, "MEASURE\nTINYSA NF",menu_measure_acb}, - { MT_ADV_CALLBACK, M_NF_STORE, "STORE\nTINYSA NF",menu_measure_acb}, - { MT_ADV_CALLBACK, M_NF_VALIDATE, "VALIDATE\nTINYSA NF",menu_measure_acb}, - { MT_ADV_CALLBACK, M_NF_AMPLIFIER, "MEASURE\nAMP NF",menu_measure_acb}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; -#endif - -static const menuitem_t menu_measure2[] = { - { MT_ADV_CALLBACK, M_AM, "AM", menu_measure_acb}, - { MT_ADV_CALLBACK, M_FM, "FM", menu_measure_acb}, - { MT_ADV_CALLBACK, M_THD, "THD", menu_measure_acb}, -#ifdef __CHANNEL_POWER__ - { MT_ADV_CALLBACK, M_CP, "CHANNEL\nPOWER",menu_measure_acb}, -#endif -#ifdef __LINEARITY__ -{ MT_ADV_CALLBACK | MT_LOW, M_LINEARITY, "LINEAR", menu_measure_acb}, -#endif -#ifdef __NOISE_FIGURE__ -{ MT_SUBMENU | MT_LOW, 0, "NOISE\nFIGURE", menu_measure_noise_figure}, -#endif -#ifdef __FFT_DECONV__ - { MT_ADV_CALLBACK, M_DECONV, "DECONV", menu_measure_acb}, -#endif - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_measure[] = { - { MT_ADV_CALLBACK, M_OFF, "OFF", menu_measure_acb}, - { MT_ADV_CALLBACK, M_IMD, "HARMONIC", menu_measure_acb}, - { MT_ADV_CALLBACK, M_OIP3, "OIP3", menu_measure_acb}, - { MT_ADV_CALLBACK, M_PHASE_NOISE,"PHASE\nNOISE", menu_measure_acb}, - { MT_ADV_CALLBACK, M_SNR, "SNR", menu_measure_acb}, - { MT_ADV_CALLBACK, M_PASS_BAND, "-3dB\nWIDTH", menu_measure_acb}, - { MT_SUBMENU, 0, S_RARROW" MORE", menu_measure2}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -#ifdef __CALIBRATE__ -#ifdef TINYSA4 -static const menuitem_t menu_calibrate_harmonic[] = -{ - { MT_FORM | MT_TITLE, 0, "Connect 5.34GHz at -50 to -10dBm", NULL}, -#ifdef TINYSA4 - { MT_FORM | MT_CALLBACK, 3, "CALIBRATE", menu_calibrate_cb}, -#endif - { MT_FORM | MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_calibrate_normal[] = -{ - { MT_FORM | MT_TITLE, 0, "Connect CAL and RF", NULL}, -#ifdef TINYSA4 - { MT_FORM | MT_CALLBACK, 1, "CALIBRATE", menu_calibrate_cb}, -#endif - { MT_FORM | MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_calibrate[] = -{ - { MT_FORM | MT_SUBMENU, 1, "CALIBRATE 100kHz to 5.34GHz", menu_calibrate_normal}, - { MT_FORM | MT_SUBMENU, 1, "CALIBRATE above 5.34GHz", menu_calibrate_harmonic}, - { MT_FORM | MT_CALLBACK, 2, "RESET CALIBRATION", menu_calibrate_cb}, - { MT_FORM | MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -#else -static const menuitem_t menu_calibrate[] = -{ - { MT_FORM | MT_TITLE, 0, "Connect HIGH and LOW", NULL}, - { MT_FORM | MT_CALLBACK, 1, "CALIBRATE", menu_calibrate_cb}, - { MT_FORM | MT_CALLBACK, 2, "RESET CALIBRATION", menu_calibrate_cb}, - { MT_FORM | MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; -#endif - -#endif - -#ifdef __USE_SERIAL_CONSOLE__ -const menuitem_t menu_serial_speed[] = { - { MT_ADV_CALLBACK|MT_REPEATS, DATA_STARTS_REPEATS(0,10), "%u", menu_serial_speed_acb }, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_connection[] = { - { MT_ADV_CALLBACK, _MODE_USB, "USB", menu_connection_acb }, - { MT_ADV_CALLBACK, _MODE_SERIAL, "SERIAL", menu_connection_acb }, - { MT_SUBMENU, 0, "SERIAL\nSPEED", menu_serial_speed }, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; -#endif - -const menuitem_t menu_touch[] = { - { MT_CALLBACK, CONFIG_MENUITEM_TOUCH_CAL, "TOUCH CAL", menu_config_cb}, - { MT_CALLBACK, CONFIG_MENUITEM_TOUCH_TEST, "TOUCH TEST", menu_config_cb}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -#ifdef __USE_RTC__ -const menuitem_t menu_date_time[] = { - { MT_KEYPAD, KM_RTC_TIME, "SET TIME\n\b%s", 0 }, // MUST BE BEFORE DATE - { MT_KEYPAD, KM_RTC_DATE, "SET DATE\n\b%s", 0 }, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; -#endif - -static const menuitem_t menu_config2[] = -{ - { MT_ADV_CALLBACK, 0, "PULSE\nHIGH", menu_settings_pulse_acb}, - { MT_ADV_CALLBACK | MT_LOW, 0,"LO OUTPUT", menu_lo_output_acb}, -#ifdef __ULTRA__ - { MT_ADV_CALLBACK, 0, "ENABLE\nULTRA", menu_ultra_acb}, -#endif - { MT_KEYPAD, KM_GRIDLINES, "MINIMUM\nGRIDLINES", "Enter minimum horizontal grid divisions"}, - { MT_KEYPAD, KM_VAR, "JOG STEP\n\b%s","0 = AUTO"}, - { MT_CALLBACK, 0 , "CLEAR\nCONFIG", menu_clearconfig_cb}, -#ifdef __USE_SERIAL_CONSOLE__ - { MT_SUBMENU, 0, "CONNECTION", menu_connection}, -#endif - { MT_SUBMENU, 0, "LEVEL\nCORRECTION", menu_actual_power}, -#ifdef TINYSA4 - { MT_SUBMENU, 0, "EXPERT\nCONFIG", menu_settings}, -#else - { MT_SUBMENU, 0, "EXPERT\nCONFIG", menu_settings2}, -#endif - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_config[] = { - { MT_SUBMENU, 0, "TOUCH", menu_touch}, - { MT_CALLBACK, CONFIG_MENUITEM_SELFTEST, "SELF TEST", menu_config_cb}, -#ifdef __CALIBRATE__ - { MT_SUBMENU, 0, "LEVEL CAL", menu_calibrate}, -#endif - { MT_CALLBACK, CONFIG_MENUITEM_VERSION, "VERSION", menu_config_cb}, -#ifdef __SPUR__ - { MT_ADV_CALLBACK,0, "%s", menu_spur_acb}, -#endif - { MT_KEYPAD, KM_REPEAT, "SAMPLE REP\n\b%s", "1..100"}, -#ifdef __LCD_BRIGHTNESS__ - { MT_CALLBACK, 0, "BRIGHTNESS", menu_brightness_cb}, -#endif -#ifdef __USE_RTC__ - { MT_SUBMENU, 0, "DATE\nTIME", menu_date_time}, -#endif -#ifndef TINYSA4 - { MT_SUBMENU, 0, S_RARROW" DFU", menu_dfu}, -#endif - { MT_SUBMENU, 0, S_RARROW"MORE", menu_config2}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; -#if 0 -static const menuitem_t menu_storage[] = -{ - { MT_ADV_CALLBACK,0, "TRACE %d", menu_storage_acb}, - { MT_ADV_CALLBACK,1, "%s", menu_storage_acb}, - { MT_ADV_CALLBACK,1, "DISPLAY", menu_storage_acb}, - { MT_ADV_CALLBACK,2, "COPY\nFROM", menu_storage_acb}, - { MT_ADV_CALLBACK,3, "SUBTRACT", menu_storage_acb}, - { MT_ADV_CALLBACK,4, "NORMALIZE", menu_storage_acb}, - { MT_ADV_CALLBACK,5, "WRITE\n"S_RARROW"SD",menu_storage_acb}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; -#endif -static const menuitem_t menu_trace[] = -{ - { MT_ADV_CALLBACK|MT_REPEATS,DATA_STARTS_REPEATS(0,TRACES_MAX), "TRACE %d", menu_trace_acb}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_marker_trace[] = -{ - { MT_ADV_CALLBACK|MT_REPEATS,DATA_STARTS_REPEATS(0,TRACES_MAX), "TRACE %d", menu_marker_trace_acb}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_store_trace[] = -{ - { MT_ADV_CALLBACK|MT_REPEATS,DATA_STARTS_REPEATS(0,TRACES_MAX), MT_CUSTOM_LABEL, menu_store_trace_acb}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_subtract_trace[] = -{ - { MT_ADV_CALLBACK|MT_REPEATS,DATA_STARTS_REPEATS(0,TRACES_MAX+1), MT_CUSTOM_LABEL, menu_subtract_trace_acb}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_traces[] = -{ - { MT_ADV_CALLBACK,0, "TRACE %d", menu_traces_acb}, - { MT_ADV_CALLBACK,1, "ENABLE", menu_traces_acb}, - { MT_ADV_CALLBACK,2, "FREEZE", menu_traces_acb}, - { MT_ADV_CALLBACK,3, MT_CUSTOM_LABEL, menu_traces_acb}, // Calc - { MT_ADV_CALLBACK,4, "NORMALIZE", menu_traces_acb}, - { MT_ADV_CALLBACK,5, MT_CUSTOM_LABEL, menu_traces_acb}, // Trace Math - { MT_SUBMENU, 0, "COPY\n"S_RARROW"TRACE", menu_store_trace}, -#ifdef TINYSA4 - { MT_ADV_CALLBACK,6, "WRITE\n"S_RARROW"SD", menu_traces_acb}, -#endif - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_display[] = { - { MT_ADV_CALLBACK,0, "PAUSE\nSWEEP", menu_pause_acb}, - { MT_ADV_CALLBACK,1, MT_CUSTOM_LABEL, menu_waterfall_acb}, -#ifdef __LEVEL_METER__ - { MT_ADV_CALLBACK,1, "BIG\nNUMBER", menu_level_meter_acb}, -#endif -#ifdef __DRAW_LINE__ - { MT_ADV_CALLBACK,1, "DRAW\nLINE", menu_settings_draw_line_acb}, -#endif - { MT_KEYPAD, KM_SWEEP_TIME, "SWEEP\nTIME", "0..600s, 0=disable"}, // This must be item 3 to match highlighting - { MT_SUBMENU, 0, "SWEEP\nPOINTS", menu_sweep_points}, - { MT_SUBMENU, 0, "SWEEP\nACCURACY", menu_sweep_speed}, - { MT_ADV_CALLBACK,0, "ROTATE\nDISPLAY", menu_flip_acb}, -//#ifdef __REMOTE_DESKTOP__ -// { MT_ADV_CALLBACK,0, "SEND\nDISPLAY", menu_send_display_acb}, -//#endif -// { MT_KEYPAD, KM_SWEEP_TIME, "SWEEP\nTIME", NULL}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_unit[] = -{ - { MT_ADV_CALLBACK,U_DBM, "dBm", menu_unit_acb}, - { MT_ADV_CALLBACK,U_DBMV, "dBmV", menu_unit_acb}, - { MT_ADV_CALLBACK,U_DBUV, "dB"S_MICRO"V", menu_unit_acb}, - { MT_ADV_CALLBACK,U_VOLT, "Volt", menu_unit_acb}, -//{ MT_ADV_CALLBACK,U_UVOLT, S_MICRO"Volt", menu_unit_acb}, - { MT_ADV_CALLBACK,U_WATT, "Watt", menu_unit_acb}, -//{ MT_ADV_CALLBACK,U_UWATT, S_MICRO"Watt", menu_unit_acb}, -#ifdef TINYSA4 - { MT_ADV_CALLBACK,U_RAW, "RAW", menu_unit_acb}, -#endif - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_trigger[] = { - { MT_ADV_CALLBACK, T_AUTO, "AUTO", menu_trigger_acb}, - { MT_ADV_CALLBACK, T_NORMAL, "NORMAL", menu_trigger_acb}, - { MT_ADV_CALLBACK, T_SINGLE, "SINGLE", menu_trigger_acb}, -// { MT_ADV_CALLBACK, T_DONE, "READY", menu_trigger_acb}, - { MT_KEYPAD, KM_TRIGGER, "TRIGGER LEV\n\b%s", NULL}, - { MT_ADV_CALLBACK, T_UP, "UP\nEDGE", menu_trigger_acb}, - { MT_ADV_CALLBACK, T_DOWN, "DOWN\nEDGE", menu_trigger_acb}, - { MT_ADV_CALLBACK, T_MODE, "%s\nTRIGGER", menu_trigger_acb}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_level[] = { - { MT_SUBMENU, 0, "REF LEVEL", menu_reflevel}, -//{ MT_SUBMENU, 0, "SCALE/DIV", menu_scale_per}, - { MT_CALLBACK,0, "SCALE/DIV", menu_scale_cb}, - { MT_SUBMENU, 0, "ATTENUATE", menu_atten}, -// { MT_SUBMENU,0, "CALC", menu_average}, - { MT_SUBMENU, 0, "UNIT", menu_unit}, - { MT_KEYPAD, KM_EXT_GAIN, "EXT GAIN\n\b%s",NULL}, -#ifdef TINYSA4 - { MT_ADV_CALLBACK | MT_LOW ,0,"LNA", menu_extra_lna_acb}, - #endif - { MT_SUBMENU, 0, "TRIGGER", menu_trigger}, -#ifdef __LISTEN__ - { MT_ADV_CALLBACK, 0, "LISTEN", menu_listen_acb}, -#endif - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -static const menuitem_t menu_stimulus[] = { - { MT_KEYPAD, KM_START, "START\n\b%s", NULL}, - { MT_KEYPAD, KM_STOP, "STOP\n\b%s", NULL}, - { MT_KEYPAD, KM_CENTER, "CENTER\n\b%s", NULL}, - { MT_KEYPAD, KM_SPAN, "SPAN\n\b%s", NULL}, - { MT_KEYPAD, KM_CW, "ZERO SPAN", NULL}, - { MT_SUBMENU,0, "RBW", menu_rbw}, -#ifdef __VBW__ - { MT_SUBMENU, 0, "VBW", menu_vbw}, -#endif - { MT_ADV_CALLBACK,0, "SHIFT\nFREQ", menu_shift_acb}, - { MT_NONE, 0, NULL, menu_back} // next-> menu_back -}; - -#ifdef TINYSA4 -const menuitem_t menu_mode[] = { -// { MT_FORM | MT_TITLE, 0, "tinySA MODE", NULL}, - { MT_FORM | MT_ADV_CALLBACK | MT_ICON, I_LOW_INPUT+I_SA, "Spectrum Analyzer", menu_mode_acb}, - { MT_FORM | MT_ADV_CALLBACK | MT_ICON, I_LOW_OUTPUT+I_SINUS, "Signal Generator", menu_mode_acb}, -// { MT_FORM | MT_ADV_CALLBACK | MT_ICON, I_HIGH_OUTPUT+I_GEN, "%s to HIGH out", menu_mode_acb}, - { MT_FORM | MT_ADV_CALLBACK | MT_ICON, I_CONNECT+I_GEN, "Calibration Output: %s", menu_sreffer_acb}, - { MT_FORM | MT_NONE, 0, NULL, NULL } // sentinel -}; -#else -const menuitem_t menu_mode[] = { -// { MT_FORM | MT_TITLE, 0, "tinySA MODE", NULL}, - { MT_FORM | MT_ADV_CALLBACK | MT_ICON, I_LOW_INPUT+I_SA, "%s to LOW in", menu_mode_acb}, - { MT_FORM | MT_ADV_CALLBACK | MT_ICON, I_HIGH_INPUT+I_SA, "%s to HIGH in", menu_mode_acb}, - { MT_FORM | MT_ADV_CALLBACK | MT_ICON, I_LOW_OUTPUT+I_SINUS, "%s to LOW out", menu_mode_acb}, - { MT_FORM | MT_ADV_CALLBACK | MT_ICON, I_HIGH_OUTPUT+I_GEN, "%s to HIGH out", menu_mode_acb}, - { MT_FORM | MT_ADV_CALLBACK | MT_ICON, I_CONNECT+I_GEN, "Cal. output: %s", menu_sreffer_acb}, -// { MT_SUBMENU, 0, "EXPERT\nCONFIG", menu_settings3}, -// { MT_FORM | MT_CANCEL, 0, S_RARROW" BACK", NULL }, - { MT_FORM | MT_NONE, 0, NULL, NULL } // sentinel -}; -#endif - -static const menuitem_t menu_top[] = { - { MT_SUBMENU, 0, "PRESET", menu_load_preset}, - { MT_SUBMENU, 0, "FREQUENCY", menu_stimulus}, - { MT_SUBMENU, 0, "LEVEL", menu_level}, - { MT_SUBMENU, 0, "TRACE", menu_traces}, - { MT_SUBMENU, 0, "DISPLAY", menu_display}, - { MT_SUBMENU, 0, "MARKER", menu_marker}, - { MT_SUBMENU, 0, "MEASURE", menu_measure}, - { MT_SUBMENU, 0, "CONFIG", menu_config}, - { MT_SUBMENU, 0, "MODE", menu_mode}, - { MT_NONE, 0, NULL, NULL } // sentinel, - // MENUITEM_CLOSE, -}; - -// ===[MENU DEFINITION END]====================================================== - -#define ACTIVE_COLOR RGBHEX(0x007FFF) - -static void menu_item_modify_attribute( // To modify menu buttons with keypad modes - const menuitem_t *menu, int item, ui_button_t *button) -{ - if (menu == menu_display) { - if (item == 5) - button->icon = setting.sweep_time_us != 0 ? BUTTON_ICON_CHECK_MANUAL : BUTTON_ICON_CHECK_AUTO; -// } else if (menu == menu_sweep_speed) { -// if (item == 3) -// button->icon = setting.fast_speedup != 0 ? BUTTON_ICON_CHECK_MANUAL : BUTTON_ICON_CHECK_AUTO; - } else if (menu == menu_reflevel) { - if (item == 1) - button->icon = setting.auto_reflevel ? BUTTON_ICON_GROUP: BUTTON_ICON_GROUP_CHECKED; - } else if (menu == menu_atten) { - if (item == 1) - button->icon = setting.auto_attenuation ? BUTTON_ICON_GROUP: BUTTON_ICON_GROUP_CHECKED; - } -} - -static void fetch_numeric_target(uint8_t mode) -{ - switch (mode) { - case KM_START: - uistat.freq_value = get_sweep_frequency(ST_START) + (setting.frequency_offset - FREQUENCY_SHIFT); - plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); - break; - case KM_STOP: - uistat.freq_value = get_sweep_frequency(ST_STOP) + (setting.frequency_offset - FREQUENCY_SHIFT); - plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); - break; - case KM_CENTER: - uistat.freq_value = get_sweep_frequency(ST_CENTER) + (setting.frequency_offset - FREQUENCY_SHIFT); - plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); - break; - case KM_SPAN: - uistat.freq_value = get_sweep_frequency(ST_SPAN); - plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); - break; - case KM_CW: - uistat.freq_value = get_sweep_frequency(ST_CW) + (setting.frequency_offset - FREQUENCY_SHIFT); - plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); - break; - case KM_SCALE: - case KM_LINEAR_SCALE: - uistat.value = setting.scale; - plot_printf(uistat.text, sizeof uistat.text, "%f/", uistat.value); - break; - case KM_REFLEVEL: - uistat.value = setting.reflevel; - plot_printf(uistat.text, sizeof uistat.text, "%.3F", uistat.value); - break; - case KM_ATTENUATION: - uistat.value = get_attenuation(); - plot_printf(uistat.text, sizeof uistat.text, "%ddB", ((int32_t)uistat.value)); - break; - case KM_ACTUALPOWER: - uistat.value = get_level_offset(); - plot_printf(uistat.text, sizeof uistat.text, "%ddB", ((int32_t)uistat.value)); - break; - case KM_IF: - uistat.freq_value = setting.frequency_IF; - if (!setting.auto_IF) - plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); - else - plot_printf(uistat.text, sizeof uistat.text, "AUTO"); - break; -#ifdef TINYSA4 - case KM_IF2: - uistat.freq_value = config.frequency_IF2; - plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); - break; - case KM_R: - uistat.value = setting.R; - if (setting.R) - plot_printf(uistat.text, sizeof uistat.text, "%d", setting.R); - else - plot_printf(uistat.text, sizeof uistat.text, "AUTO"); - break; - case KM_MOD: - if (local_modulo) - plot_printf(uistat.text, sizeof uistat.text, "%d", local_modulo); - else - plot_printf(uistat.text, sizeof uistat.text, "AUTO"); - break; - case KM_CP: - uistat.value = ADF4350_modulo; - plot_printf(uistat.text, sizeof uistat.text, "%d", ADF4350_modulo); - break; -#endif - case KM_SAMPLETIME: - uistat.value = setting.step_delay; - if (uistat.value) - plot_printf(uistat.text, sizeof uistat.text, "%dus", ((int32_t)uistat.value)); - else - plot_printf(uistat.text, sizeof uistat.text, "AUTO"); - break; - case KM_FAST_SPEEDUP: - uistat.value = setting.fast_speedup; - plot_printf(uistat.text, sizeof uistat.text, "%d", ((int32_t)uistat.value)); - break; - case KM_REPEAT: - uistat.value = setting.repeat; - plot_printf(uistat.text, sizeof uistat.text, "%d", ((int32_t)uistat.value)); - break; - case KM_LOWOUTLEVEL: - uistat.value = get_level(); // compensation for dB offset during low output mode - float end_level = ((int32_t)uistat.value)+setting.level_sweep; - if (end_level < level_min()) - end_level = level_min(); - if (end_level > level_max()) - end_level = level_max(); - uistat.value += setting.external_gain; - end_level += setting.external_gain; - if (setting.level_sweep != 0) - plot_printf(uistat.text, sizeof uistat.text, "%.1f to %.1fdBm", uistat.value, end_level); - else -#ifdef TINYSA4 - plot_printf(uistat.text, sizeof uistat.text, "%+.1fdBm %s", uistat.value, (setting.disable_correction?"Uncorrected":"")); -#else - plot_printf(uistat.text, sizeof uistat.text, "%+.1fdBm", uistat.value); -#endif - break; - case KM_HIGHOUTLEVEL: - uistat.value = get_level(); // compensation for dB offset during low output mode - uistat.value += setting.external_gain; - plot_printf(uistat.text, sizeof uistat.text, "%+.1fdBm", uistat.value); - break; - case KM_DECAY: - uistat.value = setting.decay; - plot_printf(uistat.text, sizeof uistat.text, "%d", ((int32_t)uistat.value)); - break; -#ifdef __QUASI_PEAK__ - case KM_ATTACK: - uistat.value = setting.attack; - plot_printf(uistat.text, sizeof uistat.text, "%d", ((int32_t)uistat.value)); - break; -#endif -#ifdef __ULTRA__ - case KM_ULTRA_START: - uistat.freq_value = config.ultra_start; - if (config.ultra_start == ULTRA_AUTO) - plot_printf(uistat.text, sizeof uistat.text, "AUTO"); - else - plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value ); - break; - case KM_DIRECT_START: - uistat.freq_value = config.direct_start; - plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); - break; - case KM_DIRECT_STOP: - uistat.freq_value = config.direct_stop; - plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); - break; -#endif -#ifdef __LIMITS__ - case KM_LIMIT_FREQ: - uistat.freq_value = setting.limits[current_trace][active_limit].frequency; - plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); - break; - case KM_LIMIT_LEVEL: - uistat.value = value(setting.limits[current_trace][active_limit].level); - plot_printf(uistat.text, sizeof uistat.text, "%.1f", uistat.value); - break; -#endif - case KM_NOISE: - uistat.value = setting.noise; - plot_printf(uistat.text, sizeof uistat.text, "%d", ((int32_t)uistat.value)); - break; -#ifdef TINYSA4 - case KM_FREQ_CORR: - if (config.setting_frequency_30mhz >= 3000000000ULL) - uistat.value = (config.setting_frequency_30mhz - 3000000000ULL)/3; - else - uistat.value = - ((int)(3000000000ULL - config.setting_frequency_30mhz))/3; - - plot_printf(uistat.text, sizeof uistat.text, "%d", (int32_t)uistat.value); - break; -#else - case KM_10MHZ: - uistat.freq_value = config.setting_frequency_10mhz; - plot_printf(uistat.text, sizeof uistat.text, "%3.6fMHz", uistat.freq_value); - break; -#endif - case KM_EXT_GAIN: - uistat.value = setting.external_gain; - plot_printf(uistat.text, sizeof uistat.text, "%.1fdB", uistat.value); - break; - case KM_LEVELSWEEP: - uistat.value = setting.level_sweep; - plot_printf(uistat.text, sizeof uistat.text, "%.1fdB", uistat.value); - break; - case KM_SWEEP_TIME: -// if (setting.sweep_time_us < calc_min_sweep_time_us()) -// uistat.value = calc_min_sweep_time_us(); -// else - uistat.value = setting.sweep_time_us; - uistat.value /= (float)ONE_SECOND_TIME; - plot_printf(uistat.text, sizeof uistat.text, "%.3Fs", uistat.value); - break; - case KM_TRIGGER: - uistat.value = value(setting.trigger_level); - char *format; - if (UNIT_IS_LINEAR(setting.unit)) - format = "%.3F%s"; // 5 characters incl u, m, etc... - else - format = "%.1f%s"; - plot_printf(uistat.text, sizeof uistat.text, format, uistat.value,unit_string[setting.unit]); - break; - case KM_MARKER: - if (active_marker >=0) { - uistat.freq_value = markers[active_marker].frequency; - plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); - } - break; - case KM_MODULATION: - if (active_marker >=0) { - uistat.value = setting.modulation_frequency; - plot_printf(uistat.text, sizeof uistat.text, "%7.0fHz", uistat.value); - } - break; -#ifdef TINYSA4 - case KM_DEVIATION: - uistat.freq_value = setting.modulation_deviation_div100 * 100; - plot_printf(uistat.text, sizeof uistat.text, "%.3QHz", uistat.freq_value); - break; - case KM_DEPTH: - uistat.value = setting.modulation_depth_x100; - plot_printf(uistat.text, sizeof uistat.text, "%3d", (int)uistat.value); - break; -#endif - case KM_VAR: - uistat.freq_value = setting.frequency_var; - if ( setting.frequency_var) - plot_printf(uistat.text, sizeof uistat.text, "%.4QHz", setting.frequency_var); - else - plot_printf(uistat.text, sizeof uistat.text, "AUTO"); - - break; -#ifdef __NOISE_FIGURE__ - case KM_NF: - uistat.value = config.noise_figure; - plot_printf(uistat.text, sizeof uistat.text, "%.1fdB", uistat.value); - break; -#endif -#ifdef __USE_RTC__ - case KM_RTC_TIME: - { - uint32_t tr = rtc_get_tr_bin(); // TR read first - plot_printf(uistat.text, sizeof uistat.text, "%02d:%02d:%02d", - RTC_TR_HOUR(dr), - RTC_TR_MIN(dr), - RTC_TR_SEC(dr)); - } - break; - case KM_RTC_DATE: - { - uint32_t dr = rtc_get_dr_bin(); // DR read second - plot_printf(uistat.text, sizeof uistat.text, "20%02d/%02d/%02d", - RTC_DR_YEAR(dr), - RTC_DR_MONTH(dr), - RTC_DR_DAY(dr)); - } - break; -#endif - } -} - -static void -set_numeric_value(void) -{ - switch (keypad_mode) { - case KM_START: - set_sweep_frequency(ST_START, uistat.freq_value - (setting.frequency_offset - FREQUENCY_SHIFT)); - break; - case KM_STOP: - set_sweep_frequency(ST_STOP, (freq_t)(uistat.freq_value - (setting.frequency_offset - FREQUENCY_SHIFT))); - break; - case KM_CENTER: - set_sweep_frequency(ST_CENTER, uistat.freq_value - (setting.frequency_offset - FREQUENCY_SHIFT)); - break; - case KM_SPAN: - setting.modulation = MO_NONE; - set_sweep_frequency(ST_SPAN, uistat.freq_value); - break; - case KM_CW: - set_sweep_frequency(ST_CW, uistat.freq_value - (setting.frequency_offset - FREQUENCY_SHIFT)); - break; - case KM_LINEAR_SCALE: - case KM_SCALE: - user_set_scale(uistat.value); - break; - case KM_REFLEVEL: - user_set_reflevel(uistat.value); - break; - case KM_ATTENUATION: - setting.auto_attenuation = false; - set_attenuation(uistat.value); - break; - case KM_ACTUALPOWER: - set_actual_power(uistat.value); - config_save(); - break; - case KM_IF: - set_IF(uistat.freq_value); -// config_save(); - break; -#ifdef TINYSA4 - case KM_IF2: - set_IF2(uistat.freq_value); -// config_save(); - break; - case KM_R: - set_R(uistat.value); -// config_save(); - break; - case KM_MOD: - set_modulo(uistat.value); - break; - case KM_CP: - ADF4351_CP((int)uistat.value); -// config_save(); - break; -#endif - case KM_SAMPLETIME: - set_step_delay(uistat.value); - break; - case KM_OFFSET_DELAY: - set_offset_delay(uistat.value); - break; - case KM_FAST_SPEEDUP: - set_fast_speedup(uistat.value); - break; - case KM_REPEAT: - set_repeat(uistat.value); - break; - case KM_LOWOUTLEVEL: - set_level(uistat.value - setting.external_gain); - break; - case KM_HIGHOUTLEVEL: - set_level(uistat.value - setting.external_gain); - break; - case KM_DECAY: - set_decay(uistat.value); - break; -#ifdef __QUASI_PEAK__ - case KM_ATTACK: - set_attack(uistat.value); - break; -#endif -#ifdef __ULTRA__ - case KM_ULTRA_START: - config.ultra_start = uistat.freq_value; - reset_settings(setting.mode); -// config_save(); // TODO not now - //ultra_start = config.ultra_start; - break; - case KM_DIRECT_START: - config.direct_start = uistat.freq_value; - config_save(); - break; - case KM_DIRECT_STOP: - config.direct_stop = uistat.freq_value; - config_save(); - break; -#endif -#ifdef TINYSA4 - case KM_EXP_AVER: - setting.exp_aver = uistat.value; - dirty = true; -#endif - case KM_LEVEL: - break; -#ifdef __LIMITS__ - case KM_LIMIT_FREQ: - setting.limits[current_trace][active_limit].frequency = uistat.freq_value - (setting.frequency_offset - FREQUENCY_SHIFT); - dirty = true; - limits_update(); - break; - case KM_LIMIT_LEVEL: - setting.limits[current_trace][active_limit].level = to_dBm(uistat.value); - dirty = true; - limits_update(); - break; -#endif - case KM_NOISE: - set_noise(uistat.value); - break; -#ifdef TINYSA4 - case KM_FREQ_CORR: - set_freq_corr(uistat.value); - break; -#else - case KM_10MHZ: - set_10mhz(uistat.freq_value); - break; -#endif - case KM_EXT_GAIN: - set_external_gain(uistat.value); - break; - case KM_LEVELSWEEP: - setting.modulation = MO_NONE; - set_level_sweep(uistat.value); - break; - case KM_SWEEP_TIME: - set_sweep_time_us(uistat.value*ONE_SECOND_TIME); - update_grid(); - break; - case KM_TRIGGER: - if (setting.trigger == T_AUTO ) - set_trigger(T_NORMAL); - set_trigger_level(to_dBm(uistat.value)); - completed = true; - break; - case KM_GRIDLINES: - set_gridlines(uistat.value); - break; - case KM_MARKER: - set_marker_frequency(active_marker, uistat.freq_value - (setting.frequency_offset - FREQUENCY_SHIFT)); - break; - case KM_MARKER_TIME: - set_marker_time(active_marker, uistat.value); - break; - case KM_MODULATION: - set_modulation_frequency((int)uistat.value); - break; -#ifdef TINYSA4 - case KM_COR_AM: - config.cor_am = -(int)uistat.value; - config_save(); - dirty = true; - break; - case KM_COR_WFM: - config.cor_wfm = -(int)uistat.value; - config_save(); - dirty = true; - break; - case KM_COR_NFM: - config.cor_nfm = -(int)uistat.value; - config_save(); - dirty = true; - break; - case KM_DEVIATION: - set_deviation((int)uistat.freq_value); - break; - case KM_DEPTH: - set_depth((int)uistat.value); - break; -#endif - case KM_VAR: - setting.frequency_var = uistat.freq_value; - break; -#ifdef __NOISE_FIGURE__ - case KM_NF: - config.noise_figure = uistat.value; - config_save(); - dirty = true; - break; -#endif -#ifdef __USE_RTC__ - case KM_RTC_DATE: - case KM_RTC_TIME: - { - int i = 0; - uint32_t dt_buf[2]; - dt_buf[0] = rtc_get_tr_bcd(); // TR should be read first for sync - dt_buf[1] = rtc_get_dr_bcd(); // DR should be read second - // 0 1 2 4 5 6 - // time[] ={sec, min, hr, 0, day, month, year, 0} - uint8_t *time = (uint8_t*)dt_buf; - for (; i < 6 && kp_buf[i]!=0; i++) kp_buf[i]-= '0'; - for (; i < 6 ; i++) kp_buf[i] = 0; - for (i = 0; i < 3; i++) kp_buf[i] = (kp_buf[2*i]<<4) | kp_buf[2*i+1]; // BCD format - if (keypad_mode == KM_RTC_DATE) { - // Month limit 1 - 12 (in BCD) - if (kp_buf[1] < 1) kp_buf[1] = 1; - else if (kp_buf[1] > 0x12) kp_buf[1] = 0x12; - // Day limit (depend from month): - uint8_t day_max = 28 + ((0b11101100000000000010111110111011001100>>(kp_buf[1]<<1))&3); - day_max = ((day_max/10)<<4)|(day_max%10); // to BCD - if (kp_buf[2] < 1) kp_buf[2] = 1; - else if (kp_buf[2] > day_max) kp_buf[2] = day_max; - time[6] = kp_buf[0]; // year - time[5] = kp_buf[1]; // month - time[4] = kp_buf[2]; // day - } - else { - // Hour limit 0 - 23, min limit 0 - 59, sec limit 0 - 59 (in BCD) - if (kp_buf[0] > 0x23) kp_buf[0] = 0x23; - if (kp_buf[1] > 0x59) kp_buf[1] = 0x59; - if (kp_buf[2] > 0x59) kp_buf[2] = 0x59; - time[2] = kp_buf[0]; // hour - time[1] = kp_buf[1]; // min - time[0] = kp_buf[2]; // sec - } - rtc_set_time(dt_buf[1], dt_buf[0]); - } - break; -#endif - - } -} - -void -menu_move_top(void) -{ - while (menu_current_level > 0) - menu_move_back(false); -} - - -// -------------------------- CAL STATUS --------------------------------------------- -const char * const dBText[] = { "1dB/", "2dB/", "5dB/", "10dB/", "20dB/"}; -const int refMHz[] = { 30, 15, 10, 4, 3, 2, 1 }; - -float my_round(float v) -{ - float m = 1; - int sign = 1; - if (v < 0) { - sign = -1; - v = -v; - } - while (v < 100) { - v = v * 10; - m = m / 10; - } - while (v > 1000) { - v = v / 10; - m = m * 10; - } - v = (int)(v+0.5); - v = v * m; - if (sign == -1) { - v = -v; - } - return v; -} -const char * const unit_string[MAX_UNIT_TYPE*2] = { "dBm", "dBmV", "dB"S_MICRO"V", "RAW", "V", "W", "dB", "dB", "dB", "RAW", "V", "W" }; // unit + 6 is delta unit - -static const float scale_value[]={50000, 20000, 10000, 5000, 2000, 1000, 500, 200, 100, 50, 20,10,5,2,1,0.5,0.2,0.1,0.05,0.02,0.01,0.005,0.002, 0.001,0.0005,0.0002, 0.0001}; -static const char * const scale_vtext[]= {"50000", "20000", "10000", "5000", "2000", "1000", "500", "200", "100", "50", "20","10","5","2","1","0.5","0.2","0.1","0.05","0.02","0.01", "0.005","0.002","0.001", "0.0005","0.0002","0.0001"}; - -// Quick menu -#define MAX_QUICK_MENU 20 -#define MAX_ITEM_SPACE 2 -static uint16_t quick_menu_y[MAX_QUICK_MENU]; -static menuitem_t *quick_menu[MAX_QUICK_MENU]; -static uint8_t max_quick_menu = 0; -static uint8_t item_space = 0; // - -int invoke_quick_menu(int y) -{ - int i; - for (i = 0; i < max_quick_menu;i++) { - if (y < quick_menu_y[i]) { - if ((uint32_t)quick_menu[i] < KM_NONE) { - ui_mode_keypad((int)quick_menu[i]); - } else { - selection = -1; - menu_current_level = 0; - menu_push_submenu(quick_menu[i]); - } - return TRUE; - } - } - return FALSE; -} -#define YSTEP 8 - -int add_quick_menu(int y, menuitem_t *menu) -{ - y += YSTEP*item_space/2 + YSTEP; - if (max_quick_menu 0.9 && t < 1.1){ - lcd_printf(x, y, "%s%c/",scale_vtext[i],unit_scale_text[setting.unit_scale_index]); - break; - } - i++; - } -#else - lcd_printf(x, y, "%.2F/",setting.scale); -#endif - y = add_quick_menu(y, (menuitem_t *)KM_SCALE); - - // Trigger status - if (is_paused()) { - ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); - ili9341_drawstring("PAUSED", x, y); - y += YSTEP + YSTEP/2 ; - } - if (setting.trigger == T_SINGLE || setting.trigger == T_NORMAL ) { - ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); - ili9341_drawstring("ARMED", x, y); - y += YSTEP + YSTEP/2 ; - } - // AM warning - if (signal_is_AM) { - ili9341_set_foreground(LCD_BRIGHT_COLOR_RED); - ili9341_drawstring("AM", x, y); - y += YSTEP + YSTEP/2 ; - } - quick_menu_y[max_quick_menu] = y; - quick_menu[max_quick_menu++] = (menuitem_t *)NULL; - -// if (setting.mode == M_LOW) { - // Attenuation - ili9341_set_foreground(setting.auto_attenuation ? LCD_FG_COLOR : LCD_BRIGHT_COLOR_GREEN); - lcd_printf(x, y, "Atten:\n%4.2FdB", get_attenuation()); - y = add_quick_menu(y+= YSTEP, (menuitem_t *)menu_atten); -// } - - // Calc - if (setting.average[0]>0) { - ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); - lcd_printf(x, y, "Calc:\n%s", averageText[setting.average[0]]); - y = add_quick_menu(y+= YSTEP, (menuitem_t *)menu_average); - } -#ifdef __SPUR__ // Spur -#ifdef TINYSA3 - if (setting.spur_removal != S_OFF) { -#endif - ili9341_set_foreground(setting.spur_removal == S_ON ? LCD_BRIGHT_COLOR_GREEN : LCD_FG_COLOR); - lcd_printf(x, y, "Spur:\n%s", S_IS_AUTO(setting.spur_removal) ? "AUTO" : (setting.spur_removal == S_OFF ?"OFF" : "ON")); - y = add_quick_menu(y += YSTEP, (menuitem_t *)menu_config); -#ifdef TINYSA3 - } -#endif - if (setting.mirror_masking) { - ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); - ili9341_drawstring("Mask:\nON", x, y); - y = add_quick_menu(y+=YSTEP, (menuitem_t *)menu_stimulus); - } -#endif - - if (setting.subtract[0]) { - ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); - ili9341_drawstring("Norm.", x, y); - y = add_quick_menu(y, (menuitem_t *)menu_display); - } - - // RBW - ili9341_set_foreground(setting.rbw_x10 ? LCD_BRIGHT_COLOR_GREEN : LCD_FG_COLOR); - if (dirty) update_rbw(); - lcd_printf(x, y, "RBW:\n%.1FHz", actual_rbw_x10*100.0); - y = add_quick_menu(y+=YSTEP, (menuitem_t *)menu_rbw); - -#ifdef __VBW__ - // VBW - if (setting.frequency_step > 0) { - int vbw = setting.vbw_x100; - if (vbw != 0) - color = LCD_BRIGHT_COLOR_GREEN; - else { - color = LCD_FG_COLOR; - vbw = 1; - } - ili9341_set_foreground(color); - lcd_printf(x, y, "VBW:\n%.1FHz", actual_rbw_x10*100.0 / vbw); - y = add_quick_menu(y+=YSTEP, (menuitem_t *)menu_vbw); - } -#endif - // Sweep time: SD_NORMAL, SD_PRECISE, SD_FAST, SD_MANUAL - static const char fscan[]={0, 'P', 'F', 'N', 'M'}; - if (dirty) { - calculate_step_delay(); - setting.actual_sweep_time_us = calc_min_sweep_time_us(); - } -#if 0 // Activate for sweep time debugging - lcd_printf(x, y, "%cScan:\n%5.3Fs", fscan[setting.step_delay_mode&7], (float)setting.sweep_time_us/ONE_SECOND_TIME); -#endif - ili9341_set_foreground((setting.step_delay_mode&7) != 0 ? LCD_BRIGHT_COLOR_GREEN : LCD_FG_COLOR); - lcd_printf(x, y, "%cScan:", fscan[setting.step_delay_mode&7]); - ili9341_set_foreground((setting.step_delay || setting.sweep_time_us ) ? LCD_BRIGHT_COLOR_GREEN : LCD_FG_COLOR); - lcd_printf(x, y+YSTEP, "%5.3Fs",(float)setting.actual_sweep_time_us/ONE_SECOND_TIME); - y = add_quick_menu(y+=YSTEP, (menuitem_t *)menu_sweep_speed); - - - #if 0 // Activate for sweep time debugging - y += YSTEP; - update_rbw(); // To ensure the calc_min_sweep time shown takes the latest delay into account - calculate_step_delay(); - uint32_t t = calc_min_sweep_time_us(); - lcd_printf(x, y, "%5.3Fs", (float)t/ONE_SECOND_TIME); - y += YSTEP; - lcd_printf(x, y, "%5.3Fs", (float)setting.additional_step_delay_us/ONE_SECOND_TIME); - y += YSTEP + YSTEP/2 ; -#endif -#ifdef TINYSA4 - if (setting.extra_lna){ - ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); - lcd_printf(x, y, "LNA:ON"); - y = add_quick_menu(y, (menuitem_t *)menu_level); - y += YSTEP; - } - - if (config.ultra_start != ULTRA_AUTO){ - ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); - lcd_printf(x, y, "Ultra:\n%3QHz", ultra_start); - y = add_quick_menu(y += YSTEP, (menuitem_t *)menu_config); - } - - if (setting.disable_correction){ - ili9341_set_foreground(LCD_BRIGHT_COLOR_RED); - lcd_printf(x, y, "Corr:\nOFF"); - y += 2*YSTEP + YSTEP/2; - } - - if (force_signal_path){ - ili9341_set_foreground(LCD_BRIGHT_COLOR_RED); - lcd_printf(x, y, "Path:\n%s", path_text[signal_path]); - y += 2*YSTEP + YSTEP/2; - } - -#endif - // Cal output - if (setting.refer >= 0) { - ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); - lcd_printf(x, y, "Ref:\n%dMHz",reffer_freq[setting.refer]/1000000); - y = add_quick_menu(y+=YSTEP, (menuitem_t *)menu_reffer); - } - - // Offset - if (setting.external_gain != 0.0) { - ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); - lcd_printf(x, y, "Gain:\n%4.1fdB",setting.external_gain); - y = add_quick_menu(y+=YSTEP, (menuitem_t *)KM_EXT_GAIN); - } - - // Repeat - if (setting.repeat != 1) { - ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); - lcd_printf(x, y, "Repeat\n x%d", setting.repeat); - y = add_quick_menu(y+=YSTEP,( menuitem_t *)KM_REPEAT); - } - - // Trigger - if (setting.trigger != T_AUTO) { - if (is_paused() || setting.trigger == T_NORMAL) { - ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); - } else { - ili9341_set_foreground(LCD_BRIGHT_COLOR_RED); - } - ili9341_drawstring("TRIG:", x, y); - - y += YSTEP; - if (rounding) - lcd_printf(x, y, "%6.3f", value(setting.trigger_level)); - else - lcd_printf(x, y, "%6.4F", value(setting.trigger_level)); -// lcd_printf(x, y, "%4f", value(setting.trigger_level)/setting.unit_scale); - y = add_quick_menu(y,(menuitem_t *)menu_trigger); - } -#ifndef TINYSA4 - // Mode - ili9341_set_foreground(level_is_calibrated() ? LCD_BRIGHT_COLOR_GREEN : LCD_BRIGHT_COLOR_RED); - ili9341_drawstring_7x13(MODE_LOW(setting.mode) ? "LOW" : "HIGH", x, y); - y += YSTEP + YSTEP/2 ; -#endif - // Compact status string -// ili9341_set_background(LCD_FG_COLOR); - ili9341_set_foreground(LCD_FG_COLOR); - strncpy(buf," ",BLEN-1); - if (setting.auto_IF) - buf[0] = 'f'; - else - buf[0] = 'F'; - if (S_IS_AUTO(setting.agc)) - buf[1] = 'g'; - else if (S_STATE(setting.agc)) - buf[1] = 'G'; - if (S_IS_AUTO(setting.lna)) - buf[2] = 'n'; - else if (S_STATE(setting.lna)) - buf[2] = 'N'; - if (S_IS_AUTO(setting.below_IF)) - buf[3] = 'b'; - else if (S_STATE(setting.below_IF)) - buf[3] = 'B'; -#ifdef TINYSA4 - if (S_IS_AUTO(setting.spur_removal)) - buf[4] = 's'; - else if (S_STATE(setting.spur_removal)) - buf[4] = 'S'; -#endif - ili9341_drawstring(buf, x, y); - - // Version - y += YSTEP + YSTEP/2 ; -#ifdef TINYSA4 // 'tinySA4_v1.2-[0-9]*-gxxxxxxx' - strncpy(buf,&TINYSA_VERSION[9], BLEN+1); // '1.2-...' -#else // 'tinySA_v1.2-[0-9]*-gxxxxxxx' - strncpy(buf,&TINYSA_VERSION[8], BLEN+1); // '1.2-...' -#endif - if (buf[5]=='-' ) { // '1.2-n-g...' - if (buf[4]=='0') // '1.2-0-g...' - buf[3] = 0; // -> '1.2' - else { - buf[5] = buf[4]; // -> '1.200n' - buf[4] = '0'; - buf[3] = '0'; - } - } else if (buf[6]=='-' ) { // 1.2-nn-g... - buf[3] = '0'; // -> '1.20nn' - } else { // 1.2-345-g... (or 1.2-3456...) - buf[3] = buf[4]; // -> '1.2345' - buf[4] = buf[5]; - buf[5] = buf[6]; - } - buf[6] = 0; - ili9341_drawstring(buf, x, y); - -#ifdef __USE_RTC__ - y += YSTEP + YSTEP/2 ; - uint32_t dr = rtc_get_dr_bin(); // DR read second - lcd_printf(x, y, "20%02d/\n%s/%02d", RTC_DR_YEAR(dr), month[RTC_DR_MONTH(dr)-1], RTC_DR_DAY(dr)); - y += YSTEP*2; - uint32_t tr = rtc_get_tr_bin(); // TR read first - lcd_printf(x, y, "%02d:%02d", RTC_TR_HOUR(dr), RTC_TR_MIN(dr)); -#endif - - - if (y >= BATTERY_START && item_space > 0) { - item_space--; // Reduce item spacing - goto redraw_cal_status; - } - if ((y + (max_quick_menu+1) * YSTEP/2) < BATTERY_START && item_space < MAX_ITEM_SPACE) { - item_space++; // Increase item spacing - goto redraw_cal_status; - } - -// ili9341_set_background(LCD_BG_COLOR); - if (!setting.waterfall) { // Do not draw bottom level if in waterfall mode - // Bottom level - y = area_height + OFFSETY; - if (level_is_calibrated()) - if (setting.auto_reflevel) - color = LCD_FG_COLOR; - else - color = LCD_BRIGHT_COLOR_GREEN; - else - color = LCD_BRIGHT_COLOR_RED; - ili9341_set_foreground(color); - if (rounding) - lcd_printf(x, y, "%4d", (int)(yMax - setting.scale * NGRIDY)); - else - lcd_printf(x, y, "%+4.3F", ((yMax - setting.scale * NGRIDY)/setting.unit_scale)); - y = add_quick_menu(y,(menuitem_t *)menu_average); - } -} -