3198 lines
85 KiB
C++
3198 lines
85 KiB
C++
/*
|
|
* "ui.cpp"
|
|
*
|
|
* This file implements the touch screen interface for the TinySA.
|
|
*
|
|
* Modifications through Version 2.5:
|
|
*
|
|
* Lots of general cleanup; removed a lot of the menu processing that was left
|
|
* over from the NanoVNA code but not used here including the "marker" and
|
|
* "calibration" stuff. For now some NanoVNA holdovers are left intact as they
|
|
* may be used in the future such as multiple "traces".
|
|
*
|
|
*
|
|
* Modifications in Version 2.6 by WA2FZW:
|
|
*
|
|
* Replaced the use of macros to define the menu items and replaced those with
|
|
* a class/object implementation; much neater!
|
|
*
|
|
*
|
|
* Modifications in Version 2.7 by WA2FZW:
|
|
*
|
|
* Eliminated the "kpf" array which contained the characters used to paint the numbers
|
|
* in the keypad keys and in the numerical input box. The "kpf" array is replaced with
|
|
* the "KP_Font" array, which contains bitmaps for the characters that make for a much
|
|
* better looking display! I also eliminated all the characters leftover from the
|
|
* NanoVNA code that aren't used here.
|
|
*/
|
|
|
|
|
|
#include <SPI.h> // SPI Bus handling library
|
|
#include "simpleSA.h"
|
|
#include "ui.h" // User interface definitions and prototypes
|
|
#include "cmd.h" // Command processing functions
|
|
#include "preferences.h" // Save/recall functions
|
|
#include <TFT_eSPI.h> // Display/Touch Screen header file
|
|
#include "menu.h" // "Menuitem" class definition
|
|
#include "marker.h" // Marker class definition
|
|
#include "si4432.h" // Si4432 class definition
|
|
|
|
|
|
extern Marker marker[MARKER_COUNT]; // Array of markers
|
|
|
|
extern void TouchCalibrate (); // Function is in "tinySA.ino"
|
|
extern char* FormatIPAddress (IPAddress ipAddress ); // Function in "TinySA_wifi.cpp"
|
|
|
|
extern IPAddress ipAddress; // Global in "tinySA.ino"
|
|
extern TFT_eSPI tft; // TFT Screen object
|
|
|
|
//extern void RedrawHisto ();
|
|
extern void menuExit();
|
|
|
|
extern void ClearDisplay ( void );
|
|
extern void DisplayError ( uint8_t severity, const char *l1, const char *l2, const char *l3, const char *l4 );
|
|
extern void SetRX ( int );
|
|
extern void setMode (uint16_t newMode);
|
|
|
|
extern int changedSetting; // Display needs updated
|
|
|
|
extern bool AGC_On; // Flag indicates if Preamp AGC is enabled
|
|
extern uint8_t AGC_Reg; // Fixed value for preampGain if not auto
|
|
|
|
extern Si4432 rcvr; // Si4432 Receiver object
|
|
extern Si4432 xmit; // Si4432 Transmitter object
|
|
#ifdef SI_TG_IF_CS
|
|
extern Si4432 tg_if; // Si4432 Tracking Generator IF
|
|
#endif
|
|
#ifdef SI_TG_LO_CS
|
|
extern Si4432 tg_lo; // Si4432 Tracking Generator LO
|
|
#endif
|
|
|
|
extern int VFO; // Selects transmitter or receiver Si4432
|
|
|
|
|
|
/*
|
|
* This might seem a bit weird, but I've had to do something like this in other projects!
|
|
* Sooner or later I'll figure out ir normal "true" and "false" can be used instead. As
|
|
* these are used in some of the logic that has to do with multiple traces which are not
|
|
* implemented (yet), it's impossible to tell if they can be replaced by the normal
|
|
* indicators.
|
|
*/
|
|
|
|
#define FALSE 0
|
|
#define TRUE -1
|
|
|
|
|
|
/*
|
|
* The "uistat" structure seems to contain information about the current state
|
|
* of the user interface, but I haven't figured out what the elements all mean
|
|
* yet.
|
|
*/
|
|
|
|
typedef struct {
|
|
int8_t digit; // Original comment said "0 to 5", but it gets initialized
|
|
// to '6' below!
|
|
int8_t digit_mode;
|
|
int8_t current_trace; // 0 to 3 ???
|
|
int32_t value; // For editing at numeric input area
|
|
int32_t previous_value;
|
|
} uistat_t;
|
|
|
|
|
|
/*
|
|
* Set the initial user interface status:
|
|
*/
|
|
|
|
uistat_t uistat = {
|
|
6, // digit - See note above
|
|
0, // digit_mode
|
|
0, // current_trace
|
|
0, // value
|
|
0 // previous_value
|
|
};
|
|
|
|
|
|
/*
|
|
* Create the "config" structure; not sure why in here and not in the main program file.
|
|
*/
|
|
|
|
config_t config;
|
|
|
|
|
|
/*
|
|
* Define the trace type structure. This is a NanoVNA holdover and needs to be eliminated,
|
|
* but for now, there are a lot of places where it is used. I'll get to it eventually!
|
|
*/
|
|
|
|
typedef struct
|
|
{
|
|
uint8_t enabled;
|
|
uint8_t type;
|
|
uint8_t channel;
|
|
uint8_t polar;
|
|
float scale;
|
|
float refpos;
|
|
} trace_t;
|
|
|
|
|
|
/*
|
|
* Then create an array of trace types (Note, "TRACE_COUNT" is currently defined as '1'
|
|
* in the "tinySA.h" file.
|
|
*/
|
|
|
|
trace_t trace[TRACE_COUNT];
|
|
|
|
|
|
/*
|
|
* These definitions are related to manipulation of the menu on the touch screen:
|
|
*/
|
|
|
|
#define NO_EVENT 0
|
|
#define EVT_BUTTON_SINGLE_CLICK 0x01
|
|
#define EVT_BUTTON_DOUBLE_CLICK 0x02
|
|
#define EVT_BUTTON_DOWN_LONG 0x04
|
|
#define EVT_UP 0x10
|
|
#define EVT_DOWN 0x20
|
|
#define EVT_REPEAT 0x40
|
|
|
|
|
|
/*
|
|
* Timing for touch screen button events:
|
|
*/
|
|
|
|
#define BUTTON_DOWN_LONG_TICKS 5000 // Original comment said 1 Second?
|
|
#define BUTTON_DOUBLE_TICKS 5000 // 500 mS
|
|
#define BUTTON_REPEAT_TICKS 1000 // 100 mS
|
|
#define BUTTON_DEBOUNCE_TICKS 200 // 20 mS
|
|
|
|
|
|
/*
|
|
* These look like timer values, but they aren't used anywhere; the code compiles
|
|
* fine with them commented out:
|
|
*/
|
|
|
|
static uint16_t last_button = 0;
|
|
static uint32_t last_button_down_ticks;
|
|
static uint32_t last_button_repeat_ticks;
|
|
|
|
static int8_t inhibit_until_release = FALSE;
|
|
|
|
|
|
/*
|
|
* Requested operations:
|
|
*/
|
|
|
|
enum { OP_NONE = 0, OP_TOUCH, OP_FREQCHANGE };
|
|
|
|
uint8_t operation_requested = OP_NONE; // No operations so far
|
|
|
|
|
|
/*
|
|
* These define the things that are entered using the keypad. The numbers are used as an
|
|
* index into the "keypad_mode_label" array which contains the strings that appear at
|
|
* the left of the numerical entry box and the "keypads_mode_tbl" in the "menu_invoke"
|
|
* function.
|
|
*/
|
|
|
|
enum { KM_START, KM_STOP, KM_CENTER, KM_SPAN, KM_FOCUS,
|
|
KM_REFPOS, KM_ATTENUATION, KM_ACTUALPOWER, KM_IFFREQ, KM_PREAMP,
|
|
KM_TUNE, KM_SGFREQ, KM_SGLEVEL, KM_SGLEVCAL, KM_IFSTART, KM_IFSTOP,
|
|
KM_IFSIG, KM_TGOFFSET, KM_TGLO_DRIVE, KM_TGIF_DRIVE, KM_BANDSCOPESTART, KM_BANDSCOPESPAN };
|
|
|
|
|
|
/*
|
|
* These are the strings that appear in the numerical entry box under the keypad.
|
|
*
|
|
* The order of the labels corresponds to the "KM_" list above.
|
|
*
|
|
* WA2FZW - need to change the formatting as on some menus, the numerical entry
|
|
* box covers the "<- BACK" button.
|
|
*/
|
|
|
|
static const char * const keypad_mode_label[] =
|
|
{
|
|
"START", "STOP", "CENTER", "SPAN", "FOCUS",
|
|
"REFPOS", "ATTEN", "POWER", "IF FREQ", "PREAMP",
|
|
"XTAL CAL", "SG FREQ", "dBm", "Max dBm", "IF START", "IF STOP",
|
|
"IF Sig Freq", "TG OFFSET", "TG LO Drive", "TG IF Drive", "START", "SPAN"
|
|
};
|
|
|
|
|
|
uint8_t ui_mode = UI_NORMAL; // User interface in "NORMAL" mode for now
|
|
static uint8_t keypad_mode; // Current keypad mode
|
|
static int8_t selection = 0; // Current menu selection, I think
|
|
|
|
static int8_t last_touch_status = FALSE;
|
|
|
|
static int16_t last_touch_x;
|
|
static int16_t last_touch_y;
|
|
|
|
#define EVT_TOUCH_NONE 0 // Touch screen status condition
|
|
#define EVT_TOUCH_DOWN 1 // definitions
|
|
#define EVT_TOUCH_PRESSED 2
|
|
#define EVT_TOUCH_RELEASED 3
|
|
|
|
#define NUMINPUT_LEN 10 // Length of the mumeric input box
|
|
|
|
#define KP_CONTINUE 0 // Keypad entry status definitions
|
|
#define KP_DONE 1
|
|
#define KP_CANCEL 2
|
|
|
|
static char kp_buf[NUMINPUT_LEN+1]; // Buffer for numerical entry
|
|
static int8_t kp_index = 0; // Index to the above buffer
|
|
|
|
static uint8_t selectedMarker = 0; // Currently selected marker (default is 1st one)
|
|
|
|
static uint16_t bg = BLACK; // Background is normally black
|
|
|
|
|
|
/*
|
|
* The function prototypes are needed here as many of the functions are referenced in
|
|
* setting up the menu structure which is done outside the context of any of the
|
|
* actual program code.
|
|
*/
|
|
|
|
static void ui_mode_normal ( void );
|
|
static void ui_mode_menu ( void );
|
|
static void ui_mode_numeric ( int _keypad_mode );
|
|
static void ui_mode_keypad ( int _keypad_mode );
|
|
static void draw_menu ( void );
|
|
static void leave_ui_mode ( void );
|
|
static void erase_menu_buttons ( void );
|
|
static void ui_process_keypad ( void );
|
|
static void menu_push_submenu ( Menuitem *submenu );
|
|
static void menu_move_back ( void );
|
|
static void menu_mode_cb ( int item ); // M0WID added 3.0d
|
|
static void menu_save_cb ( int item );
|
|
static void menu_refer_cb ( int item );
|
|
static void menu_refer_cb2 ( int item );
|
|
static void menu_trace_cb ( int item ); // WA2FZW - Repurposed in Version 2.6
|
|
static void menu_format2_cb ( int item );
|
|
static void menu_format_cb ( int item );
|
|
static void menu_scale_cb ( int item );
|
|
static void menu_sweep_cb ( int item );
|
|
static void menu_IF_sweep_cb ( int item ); // M0WID added 3.0c
|
|
static void menu_recall_cb ( int item );
|
|
static void menu_version_cb (int item );
|
|
static void menu_generate_cb(int item); // WA2FZW - Added in M0WID's Version 05
|
|
static void menu_Bandscope_cb ( int item ); // M0WID added 3.0f
|
|
|
|
static void menu_tracking_cb(int item); // M0WID - added in 3.0e
|
|
static void menu_tg_offset_cb(int item); // M0WID - added in 3.0e
|
|
static void menu_tgIF_drive_cb(int item); // M0WID - added in 3.0e
|
|
static void menu_tgLO_drive_cb(int item); // M0WID - added in 3.0e
|
|
|
|
static void menu_rbw_cb ( int item );
|
|
static void menu_dBper_cb ( int item );
|
|
static void menu_dBgain_cb (int item ); // M0WID
|
|
static void menu_autosettings_cb ( int item );
|
|
static void menu_average_cb (int item );
|
|
static void menu_spur_cb ( int item );
|
|
static void menu_actualpower_cb ( int item );
|
|
static void menu_storage_cb ( int item );
|
|
static void menu_IF_freq_cb ( int item ); // WA2FZW - Added in Version 2.5
|
|
static void menu_sig_freq_cb ( int item ); // M0WID - Added in Version 3.0a
|
|
static void menu_sig_levCal_cb ( int item ); // M0WID - Added in Version 3.0a
|
|
static void menu_sig_level_cb ( int item ); // M0WID - Added in Version 3.0b
|
|
static void menu_atten_cb ( int item ); // WA2FZW - Added in Version 2.6
|
|
static void menu_touch_cb ( int item ); // WA2FZW - Added in Version 2.6
|
|
static void KeyNumber ( int8_t key, int x, int y ); // WA2FZW - Added in Version 2.7
|
|
|
|
static void menu_tune_cb ( int item ); // WA2FZW - Added in Version 2.7
|
|
static void menu_save_config_cb ( int item ); // WA2FZW - Added in Version 2.7
|
|
static void menu_markers_cb ( int item ); // WA2FZW - Added in Version 2.7
|
|
static void menu_marker_select_cb ( int item ); // WA2FZW - Added in Version 2.9
|
|
static void menu_marker_color_cb ( int item ); // WA2FZW - Added in Version 2.9
|
|
|
|
static void StartMarkerMenu ( void ); // M0WID - push menu stack to start at marker level not root
|
|
static void StartSweepMenu ( void ); // M0WID - push menu stack to start at sweep level not root
|
|
static void StartDisplayMenu ( void ); // M0WID - push menu stack to start at display level not root
|
|
static void StartRBWMenu ( void ); // M0WID - push menu stack to start at rbw level not root
|
|
|
|
/*
|
|
* The "KN_xxx" definitions (for key number) replace the "KP_xxx" definitions
|
|
* previously used to paint the numbers on the keys and in the numerical entry
|
|
* box. I eliminated all the leftovers from the NanoVNA code that aren't used
|
|
* here.
|
|
*/
|
|
|
|
#define KN_PERIOD 10 // '.'
|
|
#define KN_MINUS 11 // '-'
|
|
#define KN_X 12 // 'X' (aka "Enter")
|
|
#define KN_K 13 // 'K' (for "Kilo")
|
|
#define KN_M 14 // 'M' (for "Mega")
|
|
#define KN_BS 15 // Backspace arrow
|
|
|
|
|
|
/*
|
|
* The "KP_Font" array contains the bitmaps for the characters used to paint the keypas
|
|
* keys and the numerical entry box. The array is indexed by the "KN_xxx" definitions
|
|
* above,
|
|
*/
|
|
|
|
uint16_t KP_Font[] = {
|
|
|
|
0x0FF0, 0x3FFC, 0x7FFE, 0x7C3E, 0xF83F, 0xF07F, 0xF07F, // '0' => index = 0
|
|
0xF0FF, 0xF0FF, 0xF1EF, 0xF1EF, 0xF3CF, 0xF3CF, 0xF78F,
|
|
0xF78F, 0xFF0F, 0xFF0F, 0xFE1F, 0x7E3E, 0x7FFE, 0x3FFC,
|
|
0x0FF0,
|
|
|
|
0x00F0, 0x01F0, 0x03F0, 0x07F0, 0x0FF0, 0x0FF0, 0x0EF0, // '1' => index = 1
|
|
0x0CF0, 0x00F0, 0x00F0, 0x00F0, 0x00F0, 0x00F0, 0x00F0,
|
|
0x00F0, 0x00F0, 0x00F0, 0x00F0, 0x00F0, 0x03FC, 0x03FC,
|
|
0x03FC,
|
|
|
|
0x0FF0, 0x3FFC, 0x7FFE, 0x7C3E, 0xF81F, 0xF00F, 0xF00F, // '2' => index = 2
|
|
0x001F, 0x003F, 0x007E, 0x00FC, 0x01F8, 0x03F0, 0x07E0,
|
|
0x0FC0, 0x1F80, 0x3F00, 0x7E00, 0xFC00, 0xFFFF, 0xFFFF,
|
|
0xFFFF,
|
|
|
|
0x0FF0, 0x3FFC, 0x7FFE, 0x7C3E, 0xF81F, 0xF00F, 0xF00F, // '3' => index = 3
|
|
0x001E, 0x003E, 0x01FC, 0x01F8, 0x01FC, 0x007E, 0x001F,
|
|
0x000F, 0xF00F, 0xF00F, 0xF81F, 0x7C3E, 0x7FFE, 0x3FFC,
|
|
0x0FF0,
|
|
|
|
0x01F8, 0x01F8, 0x03F8, 0x03F8, 0x07F8, 0x07F8, 0x0FF8, // '4' => index = 4
|
|
0x0F78, 0x1F78, 0x1E78, 0x3E78, 0x3C78, 0x7C78, 0x7878,
|
|
0xF878, 0xFFFF, 0xFFFF, 0xFFFF, 0x0078, 0x0078, 0x0078,
|
|
0x0078,
|
|
|
|
0xFFFF, 0xFFFF, 0xFFFF, 0xF000, 0xF000, 0xF000, 0xF000, // '5' => index = 5
|
|
0xF7F0, 0xFFFC, 0xFFFE, 0xFC3E, 0xF81F, 0x000F, 0x000F,
|
|
0x000F, 0x000F, 0xF00F, 0xF81F, 0x7C3E, 0x7FFE, 0x3FFC,
|
|
0x0FF0,
|
|
|
|
0x0FF0, 0x3FFC, 0x7FFE, 0x7C3E, 0xF81F, 0xF00F, 0xF000, // '6' => index = 6
|
|
0xF000, 0xF7F0, 0xFFFC, 0xFFFE, 0xFC3E, 0xF81F, 0xF00F,
|
|
0xF00F, 0xF00F, 0xF00F, 0xF81F, 0x7C3E, 0x7FFE, 0x3FFC,
|
|
0x0FF0,
|
|
|
|
0xFFFF, 0xFFFF, 0xFFFF, 0x001F, 0x003E, 0x007C, 0x00F8, // '7' => index = 7
|
|
0x01F0, 0x01E0, 0x03E0, 0x03C0, 0x07C0, 0x0780, 0x0780,
|
|
0x0F80, 0x0F00, 0x0F00, 0x0F00, 0x0F00, 0x0F00, 0x0F00,
|
|
0x0F00,
|
|
|
|
0x07E0, 0x1FF8, 0x3FFC, 0x7C3E, 0x781E, 0x781E, 0x781E, // '8' => index = 8
|
|
0x3C3C, 0x1FF8, 0x0FF0, 0x3FFC, 0x7C3E, 0x781E, 0xF00F,
|
|
0xF00F, 0xF00F, 0xF00F, 0xF81F, 0x7C3E, 0x7FFE, 0x3FFC,
|
|
0x0FF0,
|
|
|
|
0x0FF0, 0x3FFC, 0x7FFE, 0x7C3E, 0xF81F, 0xF00F, 0xF00F, // '9' => index = 9
|
|
0xF00F, 0xF00F, 0xF81F, 0x7C3F, 0x7FFF, 0x3FFF, 0x0FFF,
|
|
0x000F, 0x000F, 0xF00F, 0xF81F, 0x7C3E, 0x7FFE, 0x3FFC,
|
|
0x0FF0,
|
|
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // '.' => index = KN_PERIOD
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
|
0x0000, 0x0000, 0x0000, 0x0380, 0x07C0, 0x07C0, 0x0380,
|
|
0x0000,
|
|
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // '-' => index = KN_MINUS
|
|
0x0000, 0x0000, 0x0000, 0x3FFC, 0x3FFC, 0x3FFC, 0x3FFC,
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
|
0x0000,
|
|
|
|
0x0000, 0x0000, 0xF00F, 0x781E, 0x781E, 0x3C3C, 0x3C3C, // 'X' => index = KN_X
|
|
0x1E78, 0x1E78, 0x0FF0, 0x07E0, 0x0FF0, 0x0FF0, 0x1E78,
|
|
0x1E78, 0x3C3C, 0x3C3C, 0x781E, 0x781E, 0xF00F, 0x0000,
|
|
0x0000,
|
|
|
|
0xF01F, 0xF03E, 0xF07C, 0xF0F8, 0xF1F0, 0xF3E0, 0xF7C2, // 'K' => index = KN_K
|
|
0xFF80, 0xFF00, 0xFE00, 0xFC00, 0xFC00, 0xFE00, 0xFF00,
|
|
0xFFC0, 0xF7E0, 0xF3F0, 0xF1F0, 0xF0F8, 0xF07E, 0xF03F,
|
|
0xF01F,
|
|
|
|
0xF00F, 0xF00F, 0xF81F, 0xF81F, 0xFC3F, 0xFC3F, 0xFE7F, // 'M' => index = KN_M
|
|
0xFE7F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7EF, 0xF7EF,
|
|
0xF3CF, 0xF3CF, 0xF18F, 0xF18F, 0xF00F, 0xF00F, 0xF00F,
|
|
0xF00F,
|
|
|
|
0x0000, 0x0000, 0x0040, 0x00C0, 0x01C0, 0x03C0, 0x07C0, // Backspace arrow => index = KN_BS
|
|
0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x7FFF, 0x3FFF,
|
|
0x1FFF, 0x0FFF, 0x07C0, 0x03C0, 0x01C0, 0x00C0, 0x0040,
|
|
0x0000
|
|
};
|
|
|
|
|
|
/*
|
|
* Define the actual menu item text and associated callback functions for all the menus.
|
|
*
|
|
* Modified in Version 2.6 by WA2FZW:
|
|
*
|
|
* Replaced all the "MENUITEM_xxxx" macros with the "Menuitem" class/object implementation.
|
|
* This not only affects the menu definitions, but how things are handled throughout the
|
|
* module.
|
|
*
|
|
* Note, that while it would be nice to have the main menu at the top of the list followed
|
|
* by any sub-menus, the compiler doesn't like that. The sub-menus have to be defined before
|
|
* they are referenced in a higher level menu. This was also the case with the original
|
|
* macro implementation.
|
|
*/
|
|
|
|
static Menuitem menu_mode[] = // Select mode menu
|
|
{
|
|
Menuitem ( MT_FUNC, "\2SWEEP\0LOW", menu_mode_cb ),
|
|
Menuitem ( MT_FUNC, "\2SIG\0GEN", menu_mode_cb ),
|
|
Menuitem ( MT_FUNC, "\2IF\0SWEEP", menu_mode_cb ),
|
|
Menuitem ( MT_FUNC, "\2BAND\0SCOPE",menu_mode_cb ),
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
|
|
static Menuitem menu_average[] = // Enables averaging and sets value
|
|
{
|
|
Menuitem ( MT_FUNC, "OFF", menu_average_cb ), // No averaging
|
|
Menuitem ( MT_FUNC, "MIN", menu_average_cb ), // Not sure about
|
|
Menuitem ( MT_FUNC, "MAX", menu_average_cb ), // These two
|
|
Menuitem ( MT_FUNC, " 2 ", menu_average_cb ), // Divide by 2
|
|
Menuitem ( MT_FUNC, " 4 ", menu_average_cb ), // By 4
|
|
Menuitem ( MT_FUNC, " 8 ", menu_average_cb ), // By 8
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
static Menuitem menu_storage[] = // Sweep storage options
|
|
{
|
|
Menuitem ( MT_FUNC, "STORE", menu_storage_cb ), // Save current sweep
|
|
Menuitem ( MT_FUNC, "CLEAR", menu_storage_cb ), // Erase saved sweep
|
|
Menuitem ( MT_FUNC, "SUBTRACT", menu_storage_cb ), // Not sure what this does!
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
static Menuitem menu_generate[] = // Frequency generator mode
|
|
{
|
|
// Menuitem ( MT_FUNC, "OFF", menu_generate_cb ),
|
|
Menuitem ( MT_FUNC, "ON", menu_generate_cb ),
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
|
|
static Menuitem menu_tracking[] = // Tracking generator mode
|
|
{
|
|
Menuitem ( MT_FUNC, "OFF", menu_tracking_cb ),
|
|
Menuitem ( MT_FUNC, "ON", menu_tracking_cb ),
|
|
Menuitem ( MT_FUNC, "OFFSET", menu_tg_offset_cb ),
|
|
Menuitem ( MT_FUNC, "\2IF\0DRIVE", menu_tgIF_drive_cb ),
|
|
#ifdef SI_TG_LO_CS
|
|
Menuitem ( MT_FUNC, "\2LO\0DRIVE", menu_tgLO_drive_cb ),
|
|
#endif
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
|
|
static Menuitem menu_spur[] = // Turn spurious suppression on or off
|
|
{
|
|
Menuitem ( MT_FUNC, "OFF", menu_spur_cb ),
|
|
Menuitem ( MT_FUNC, "ON", menu_spur_cb ),
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
static Menuitem menu_rbw[] = // Resolution bandwidth settings
|
|
{
|
|
Menuitem ( MT_FUNC, " AUTO", menu_rbw_cb ), // In auto mode, there are many
|
|
Menuitem ( MT_FUNC, " 3kHz", menu_rbw_cb ), // more available settings that
|
|
Menuitem ( MT_FUNC, " 10kHz", menu_rbw_cb ), // are roughly the sweep range
|
|
Menuitem ( MT_FUNC, " 30kHz", menu_rbw_cb ), // divided by 300.
|
|
Menuitem ( MT_FUNC, "100kHz", menu_rbw_cb ),
|
|
Menuitem ( MT_FUNC, "300kHz", menu_rbw_cb ),
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
static Menuitem menu_dBper[] = // Scale setting menu
|
|
{
|
|
Menuitem ( MT_FUNC, " 1dB/", menu_dBper_cb ),
|
|
Menuitem ( MT_FUNC, " 2dB/", menu_dBper_cb ),
|
|
Menuitem ( MT_FUNC, " 5dB/", menu_dBper_cb ),
|
|
Menuitem ( MT_FUNC, " 10dB/", menu_dBper_cb ),
|
|
Menuitem ( MT_FUNC, " 20dB/", menu_dBper_cb ),
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
/*
|
|
* Menu to set the gain overide register (REG_AGCOR 0x69) in the SI4432 transceiver.
|
|
* See app note AN440 for the full explanation.
|
|
*
|
|
* Modified in Version 2.6 by WA2FZW:
|
|
*
|
|
* The original code had set values in a sub-menu. Now we use the keypad to set
|
|
* any value one likes!. But here are rules! See the documentation for the
|
|
* explanation.
|
|
*/
|
|
|
|
static Menuitem menu_dBgain[] =
|
|
{
|
|
Menuitem ( MT_FUNC, "AGC ON", menu_dBgain_cb ), //0x60
|
|
Menuitem ( MT_FUNC, "\2SET\0VALUE", menu_dBgain_cb ), //Set actual value
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
|
|
static Menuitem menu_save[] = // Setting save options
|
|
{
|
|
Menuitem ( MT_FUNC, "SAVE 0", menu_save_cb ), // This works like the NanoVNA
|
|
Menuitem ( MT_FUNC, "SAVE 1", menu_save_cb ), // where you an save a number of
|
|
Menuitem ( MT_FUNC, "SAVE 2", menu_save_cb ), // different configurations
|
|
Menuitem ( MT_FUNC, "SAVE 3", menu_save_cb ),
|
|
Menuitem ( MT_FUNC, "SAVE 4", menu_save_cb ),
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
static Menuitem menu_recall[] = // For recalling saved configurations
|
|
{
|
|
Menuitem ( MT_FUNC, "RECALL 0", menu_recall_cb ),
|
|
Menuitem ( MT_FUNC, "RECALL 1", menu_recall_cb ),
|
|
Menuitem ( MT_FUNC, "RECALL 2", menu_recall_cb ),
|
|
Menuitem ( MT_FUNC, "RECALL 3", menu_recall_cb ),
|
|
Menuitem ( MT_FUNC, "RECALL 4", menu_recall_cb ),
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
static Menuitem menu_save_recall[] = // Save or recall options
|
|
{
|
|
Menuitem ( MT_MENU, "SAVE", menu_save ), // Show save options
|
|
Menuitem ( MT_MENU, "RECALL", menu_recall ), // Show recall options
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
|
|
int menu_refer_value[] = { -1, 0, 1, 2, 3, 4, 5, 6 }; // Actual values for the register
|
|
|
|
static Menuitem menu_refer2[] = // Part 2 of the reference values
|
|
{
|
|
Menuitem ( MT_FUNC, "3MHz", menu_refer_cb2 ),
|
|
Menuitem ( MT_FUNC, "2MHz", menu_refer_cb2 ),
|
|
Menuitem ( MT_FUNC, "1MHz", menu_refer_cb2 ),
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
static Menuitem menu_refer[] = // GPIO2 reference frequency values
|
|
{
|
|
Menuitem ( MT_FUNC, "OFF", menu_refer_cb ),
|
|
Menuitem ( MT_FUNC, "30MHz", menu_refer_cb ),
|
|
Menuitem ( MT_FUNC, "15MHz", menu_refer_cb ),
|
|
Menuitem ( MT_FUNC, "10MHz", menu_refer_cb ),
|
|
Menuitem ( MT_FUNC, "4MHz", menu_refer_cb ),
|
|
Menuitem ( MT_MENU, " MORE->", menu_refer2 ),
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
static Menuitem menu_traces[] = // Toggle display traces on and off
|
|
{
|
|
Menuitem ( MT_FUNC, "\2dB\0On/Off", menu_trace_cb ),
|
|
Menuitem ( MT_FUNC, "\2GAIN\0On/Off", menu_trace_cb ),
|
|
Menuitem ( MT_MENU, "AVERAGE", menu_average ), // The sub menu allows values to be set
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
static Menuitem menu_select_marker[] =
|
|
{
|
|
Menuitem ( MT_FUNC, "MKR #1", menu_marker_select_cb ),
|
|
Menuitem ( MT_FUNC, "MKR #2", menu_marker_select_cb ),
|
|
Menuitem ( MT_FUNC, "MKR #3", menu_marker_select_cb ),
|
|
Menuitem ( MT_FUNC, "MKR #4", menu_marker_select_cb ),
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
static Menuitem menu_marker_color[] =
|
|
{
|
|
Menuitem ( MT_FUNC, "WHITE", menu_marker_color_cb ),
|
|
Menuitem ( MT_FUNC, "RED", menu_marker_color_cb ),
|
|
Menuitem ( MT_FUNC, "BLUE", menu_marker_color_cb ),
|
|
Menuitem ( MT_FUNC, "GREEN", menu_marker_color_cb ),
|
|
Menuitem ( MT_FUNC, "YELLOW", menu_marker_color_cb ),
|
|
Menuitem ( MT_FUNC, "ORANGE", menu_marker_color_cb ),
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
static Menuitem menu_markers[] =
|
|
{
|
|
Menuitem ( MT_MENU, "\2SELECT\0MARKER", menu_select_marker ),
|
|
Menuitem ( MT_MENU, "\2SELECT\0COLOR", menu_marker_color ),
|
|
Menuitem ( MT_FUNC, "\2ENABLE/\0DISABLE", menu_markers_cb ),
|
|
Menuitem ( MT_FUNC, "\2ENABLE\0ALL", menu_markers_cb ),
|
|
Menuitem ( MT_FUNC, "\2DISABLE\0ALL", menu_markers_cb ),
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
static Menuitem menu_display[] = // Display menu
|
|
{
|
|
Menuitem ( MT_MENU, "TRACES", menu_traces ), // Turn display traces on and off
|
|
Menuitem ( MT_MENU, "\2PREAMP\0GAIN", menu_dBgain ), // Set preamp gain
|
|
Menuitem ( MT_FUNC, "\2REF\0LEVEL", menu_scale_cb ), // Set top line of the grid
|
|
Menuitem ( MT_MENU, "dB/DIV", menu_dBper ), // Menu to set vertical grid scale
|
|
Menuitem ( MT_MENU, "\2SPUR\0REDUCTION", menu_spur ), // Enable or disable spur reduction
|
|
Menuitem ( MT_FUNC, "\2DEFAULT\0SETTINGS",menu_autosettings_cb ),
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
static Menuitem menu_sweep2[] =
|
|
{
|
|
Menuitem ( MT_MENU, "RBW", menu_rbw ), // Set the resolution bandwidth
|
|
Menuitem ( MT_FUNC, "ATTEN", menu_atten_cb ), // Set the attenuation
|
|
Menuitem ( MT_MENU, "MARKERS", menu_markers ), // Marker sub menu
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
static Menuitem menu_sweep[] = // This is the main "SWEEP" menu
|
|
{
|
|
Menuitem ( MT_FUNC, "\2SWEEP\0START", menu_sweep_cb ),
|
|
Menuitem ( MT_FUNC, "\2SWEEP\0STOP", menu_sweep_cb ),
|
|
Menuitem ( MT_FUNC, "\2SWEEP\0CENTER", menu_sweep_cb ),
|
|
Menuitem ( MT_FUNC, "\2SWEEP\0SPAN", menu_sweep_cb ),
|
|
Menuitem ( MT_FUNC, "\2FOCUS\0FREQ", menu_sweep_cb ),
|
|
Menuitem ( MT_MENU, "MORE->", menu_sweep2 ), // Additional options above
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
static Menuitem menu_output[] = // The "OUTPUT" menu
|
|
{
|
|
Menuitem ( MT_MENU, "REFERENCE", menu_refer ), // Select GPIO2 reference frequency
|
|
Menuitem ( MT_FUNC, "GENERATOR", menu_generate_cb ), // Turn generator mode on or off
|
|
#ifdef SI_TG_IF_CS
|
|
Menuitem ( MT_MENU, "TRACKING", menu_tracking ), // Tracking generator control
|
|
#endif
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
static Menuitem menu_touchscreen[] =
|
|
{
|
|
Menuitem ( MT_FUNC, "\2TOUCH\0CAL", menu_touch_cb ), // Calibrate touch screen
|
|
Menuitem ( MT_FUNC, "\2TOUCH\0TEST", menu_touch_cb ), // Test touch screen calibration
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
/*
|
|
* WA2FZW - Still to do - Add items to do the frequency calibrations.
|
|
*/
|
|
|
|
static Menuitem menu_calibrate[] =
|
|
{
|
|
Menuitem ( MT_FUNC, "TX FREQ", menu_tune_cb ),
|
|
Menuitem ( MT_FUNC, "RX FREQ", menu_tune_cb ),
|
|
Menuitem ( MT_FUNC, "\2ACTUAL\0POWER", menu_actualpower_cb ), // Calibrate power setting
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
static Menuitem menu_config[] = // The "CONFIG" menu
|
|
{
|
|
Menuitem ( MT_MENU, "CALIBRATE", menu_calibrate ), // Calibration menu
|
|
Menuitem ( MT_MENU, "\2TOUCH\0SCREEN", menu_touchscreen ), // Calibrate & test the touch screen
|
|
Menuitem ( MT_FUNC, "\2IF\0FREQ", menu_IF_freq_cb ), // Set the IF frequency
|
|
Menuitem ( MT_FUNC, "\2SAVE\0CONFIG", menu_save_config_cb ), // Save "config" structure
|
|
Menuitem ( MT_FUNC, "VERSION", menu_version_cb ), // Display "About" information
|
|
Menuitem ( MT_BACK, "<-BACK" ), // Next level up
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
|
|
static Menuitem menu_sig_gen[] = // The "CONFIG" menu
|
|
{
|
|
Menuitem ( MT_MENU, "MODE", menu_mode ),
|
|
Menuitem ( MT_FUNC, "\2SET\0FREQ", menu_sig_freq_cb ), // Set the output frequency
|
|
Menuitem ( MT_FUNC, "\2SET\0dBm", menu_sig_level_cb ), // Set the output level
|
|
Menuitem ( MT_FUNC, "\2CAL\0dBm", menu_sig_levCal_cb ), // Calibrate the sig gen output level
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
|
|
|
|
static Menuitem menu_IFsweep_top[] = // This is the main "IF_SWEEP" menu
|
|
{
|
|
Menuitem ( MT_MENU, "MODE", menu_mode ),
|
|
Menuitem ( MT_FUNC, "\2SWEEP\0START", menu_IF_sweep_cb ),
|
|
Menuitem ( MT_FUNC, "\2SWEEP\0STOP", menu_IF_sweep_cb ),
|
|
Menuitem ( MT_FUNC, "\2SWEEP\0SIG", menu_IF_sweep_cb ),
|
|
Menuitem ( MT_MENU, "REFERENCE", menu_refer ), // Select GPIO2 reference frequency
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
|
|
static Menuitem menu_Bandscope_top[] = // This is the main "IF_SWEEP" menu
|
|
{
|
|
Menuitem ( MT_MENU, "MODE", menu_mode ),
|
|
Menuitem ( MT_FUNC, "\2SWEEP\0START", menu_Bandscope_cb ),
|
|
Menuitem ( MT_FUNC, "\2SWEEP\0SPAN", menu_Bandscope_cb ),
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
* And last but not least the main menu!
|
|
*/
|
|
|
|
static Menuitem menu_top[] =
|
|
{
|
|
Menuitem ( MT_MENU, "MODE", menu_mode ),
|
|
Menuitem ( MT_MENU, "SWEEP", menu_sweep ),
|
|
Menuitem ( MT_MENU, "DISPLAY", menu_display ),
|
|
Menuitem ( MT_MENU, "STORAGE", menu_storage ),
|
|
Menuitem ( MT_MENU, "OUTPUT", menu_output ),
|
|
Menuitem ( MT_MENU, "\2SAVE/\0RECALL", menu_save_recall ),
|
|
Menuitem ( MT_MENU, "CONFIG", menu_config ),
|
|
Menuitem ( MT_END ) // End marker
|
|
};
|
|
|
|
|
|
static uint8_t menu_current_level = 0; // Current level (MAIN)
|
|
|
|
static Menuitem *menu_stack[MENU_STACK_DEPTH] = // Initialize the stack
|
|
{ menu_top, // Main menu is on top
|
|
NULL, // These get set as we
|
|
NULL, // go along
|
|
NULL
|
|
};
|
|
|
|
|
|
/*
|
|
* Some definitions and more variables associated with the menu handling:
|
|
*/
|
|
|
|
#define OFFSETX 15 // "X" offset (from what?)
|
|
#define OFFSETY 0 // "Y" offset
|
|
|
|
|
|
/*
|
|
* Menu handling functions:
|
|
*/
|
|
|
|
static int touch_check ( void );
|
|
|
|
static void touch_wait_release ( void ) // Wait for touch screen release
|
|
{
|
|
int tstatus;
|
|
|
|
do
|
|
{
|
|
tstatus = touch_check (); // Check the touch screen status
|
|
} while ( tstatus != EVT_TOUCH_RELEASED ); // Loop until released
|
|
}
|
|
|
|
|
|
static int touch_status ( void ) // Get the touch screen status
|
|
{
|
|
return ( tft.getTouchRawZ() > TS_MINIMUM_Z ); // "RawZ" is a measure of touch pressure
|
|
}
|
|
|
|
|
|
#define RAWERR 20 // Deadband error allowed in successive position samples
|
|
|
|
|
|
/*
|
|
* "validTouch" - Added by M0WID in Version 05:
|
|
*
|
|
* Adds a lot of checking to make sure that the user actually intended to touch
|
|
* something as opposed to a shaky-hand touch!
|
|
*
|
|
* WA2FZW - Why use the un-calibrated touch values here and the convert them
|
|
* to calibrated values in "getTouch"?
|
|
*/
|
|
|
|
uint8_t validTouch ( uint16_t *x, uint16_t *y, uint16_t threshold )
|
|
{
|
|
uint16_t x_tmp, y_tmp; // "X" and "Y coordinates
|
|
static uint16_t x_tmp2, y_tmp2; // Second "X" and "Y coordinates
|
|
|
|
|
|
/*
|
|
* Wait until pressure stops increasing to debounce pressure, but only?
|
|
*/
|
|
|
|
uint16_t z1 = 1;
|
|
uint16_t z2 = 0;
|
|
|
|
while ( z1 > z2 )
|
|
{
|
|
z2 = z1; // Old pressure = last pressure
|
|
z1 = tft.getTouchRawZ (); // Read new pressure
|
|
|
|
if ( z1 <= threshold ) // return immediately
|
|
return false;
|
|
}
|
|
|
|
// Serial.print ( "Z = " ); Serial.println ( z1 ); // Debugging
|
|
|
|
if ( z1 <= threshold ) // If pressure less than the specified threshold
|
|
return false; // It's not a valid touch
|
|
|
|
// x_tmp2 = x_tmp; // Save values from last scan
|
|
// y_tmp2 = y_tmp;
|
|
|
|
tft.getTouchRaw ( &x_tmp, &y_tmp ); // Get touch coordinates
|
|
|
|
// Serial.print ( "Sample 1 x,y = " ); // Debugging
|
|
// Serial.print ( x_tmp );
|
|
// Serial.print ( "," );
|
|
// Serial.print ( y_tmp );
|
|
// Serial.print ( "Z = " );
|
|
// Serial.println ( z1 );
|
|
|
|
delayMicroseconds ( 1000 ); // Small delay to the next sample
|
|
|
|
if ( tft.getTouchRawZ() <= threshold ) // Threshold not met?
|
|
return false; // Then not a valid touch
|
|
|
|
delayMicroseconds ( 1000 ); // Small delay to the next sample
|
|
|
|
tft.getTouchRaw ( &x_tmp2, &y_tmp2 ); // Get 2nd set of coordinates
|
|
|
|
// Serial.print ( "Sample 2 x,y = " ); // More debugging
|
|
// Serial.print ( x_tmp2 );
|
|
// Serial.print ( ", " );
|
|
// Serial.println ( y_tmp2 );
|
|
// Serial.print ( "Sample difference = " );
|
|
// Serial.print ( abs ( x_tmp - x_tmp2 ));
|
|
// Serial.print ( "," );
|
|
// Serial.println ( abs (y_tmp - y_tmp2 ));
|
|
|
|
if ( abs ( x_tmp - x_tmp2 ) > RAWERR ) // Error limit exceeded?
|
|
return false; // Then invalid touch
|
|
|
|
if ( abs (y_tmp - y_tmp2 ) > RAWERR ) // Same check for "Y" values
|
|
return false;
|
|
|
|
*x = x_tmp; // Set good
|
|
*y = y_tmp; // Coordinates
|
|
|
|
return true; // And indicate valid touch
|
|
}
|
|
|
|
|
|
/*
|
|
* "getTouch" - Added by M0WID in Version 05:
|
|
*
|
|
* Replaces the TFT_eSPI library function. Returns false if not a valid touch.
|
|
* If it is a valid touch, the calibrated x and y values returned in the
|
|
* arguments.
|
|
*/
|
|
|
|
#define RELEASE_COUNT 10
|
|
#define PRESS_COUNT 3
|
|
|
|
uint8_t getTouch ( uint16_t *x, uint16_t *y )
|
|
{
|
|
uint16_t x_tmp, y_tmp; // Temporary touch coordinates
|
|
static unsigned long pressTime;
|
|
static int lastState;
|
|
static uint16_t threshold = TS_MINIMUM_Z;
|
|
uint8_t n;
|
|
|
|
if ( lastState )
|
|
{
|
|
threshold = 50; // Change threshold limit if valid to provide hysteresis
|
|
n = RELEASE_COUNT; // Need this no of not pressed read results to return not pressed
|
|
}
|
|
|
|
else
|
|
{
|
|
threshold = TS_MINIMUM_Z; // Higher limit to indicate pressed
|
|
n = PRESS_COUNT; // Lower number of counts needed
|
|
}
|
|
|
|
int valid = 0; // Non zero if valid touch seen
|
|
|
|
while ( n-- )
|
|
{
|
|
if ( validTouch ( &x_tmp, &y_tmp, threshold ))
|
|
valid++; // WA2FZW - Removed extra semicolon
|
|
else
|
|
valid--; // M0WID - add check that it is really released
|
|
}
|
|
|
|
// Serial.printf ( "last %i valid %i\n", lastState, valid );
|
|
|
|
if (( lastState && (valid <= -RELEASE_COUNT+1)) || (!lastState && (valid < PRESS_COUNT-1))) // Not a valid touch
|
|
{
|
|
// pressTime = 0; // Time = '0'
|
|
lastState = false;
|
|
return false; // Indicate invalid touch
|
|
}
|
|
|
|
|
|
/*
|
|
* If we get this far touch is valid
|
|
*/
|
|
|
|
// pressTime = millis() + 50; // Debounce?
|
|
|
|
tft.convertRawXY ( &x_tmp, &y_tmp ); // Calibrate the readings
|
|
|
|
if ( x_tmp >= tft.width () || y_tmp >= tft.height ()) // Off the chart?
|
|
{
|
|
lastState = false;
|
|
return false; // Then bad touch
|
|
}
|
|
|
|
*x = x_tmp; // Set return values
|
|
*y = y_tmp;
|
|
lastState = true;
|
|
return true; // Indicate touch is valid
|
|
}
|
|
|
|
|
|
static int touch_check ( void ) // Check for TS touched
|
|
{
|
|
uint16_t x = 0; // Used to store the "X" and
|
|
uint16_t y = 0; // "Y" coordinates
|
|
|
|
int stat = getTouch ( &x, &y ); // Read the touch screen
|
|
|
|
// Serial.printf ( "TouchCheck stat=%i, x=%i, y=%i \n", stat, x, y ); // Debugging
|
|
|
|
if ( stat ) // Valid touch if non-zero
|
|
{
|
|
last_touch_x = x; // Save coordinates for ???
|
|
last_touch_y = y;
|
|
}
|
|
|
|
if ( stat != last_touch_status ) // Did the status change?
|
|
{
|
|
last_touch_status = stat; // Yes make new status old
|
|
|
|
if ( stat ) // If non-zero screen was touched
|
|
return EVT_TOUCH_PRESSED; // Indicate that fact
|
|
else
|
|
return EVT_TOUCH_RELEASED;
|
|
}
|
|
|
|
else // Status didn't change
|
|
{
|
|
if ( stat ) // If non-zero
|
|
return EVT_TOUCH_DOWN; // Must still be touched
|
|
else // If "stat" is zero
|
|
return EVT_TOUCH_NONE; // Nothing happening!
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* "DrawString" - Paint a character in a specified size and color:
|
|
*
|
|
* "t" The character
|
|
* "x & y" Coordinates
|
|
* "tc" Text color
|
|
* "size" Font size
|
|
*
|
|
* Modified in Version 2.2 by WA2FZW:
|
|
*
|
|
* Changed the name from "DrawStringSize" to "DrawString" and eliminated the
|
|
* "DrawString_5x7" function and replaced all calls to that with calls to this one.
|
|
*
|
|
* Eliminated the "bc" (background color) argument, so everything displays with
|
|
* a transparent background.
|
|
*/
|
|
|
|
void DrawString ( const char *t, int x, int y, int tc, int size )
|
|
{
|
|
|
|
//Serial.println ( t ); // Debugging
|
|
|
|
tft.setCursor ( x, y ); // Set location
|
|
tft.setTextColor ( tc ); // Set text color
|
|
tft.setTextSize ( size ); // and font size
|
|
tft.print ( t ); // Paint the character
|
|
}
|
|
|
|
|
|
/*
|
|
* "touch_cal_exec" - Runs the calibration procedure built into the "TFT_eSPI"
|
|
* library.
|
|
*/
|
|
|
|
void touch_cal_exec ( void )
|
|
{
|
|
TouchCalibrate (); // Function is in "tinySA.cpp"
|
|
}
|
|
|
|
|
|
/*
|
|
* "touch_position" returns the calibrated x/y value corrected for screen rotation setting
|
|
* when using the "ESP_eSPI" library.
|
|
*/
|
|
|
|
void touch_position ( int *x, int *y )
|
|
{
|
|
*x = last_touch_x;
|
|
*y = last_touch_y;
|
|
|
|
// Serial.print ( "TP = " );
|
|
// Serial.print ( *x );
|
|
// Serial.print ( ", " );
|
|
// Serial.println ( *y );
|
|
}
|
|
|
|
|
|
/*
|
|
* "touch_draw_test" lets you scribble on the display
|
|
*/
|
|
|
|
void touch_draw_test ( void )
|
|
{
|
|
int status; // Touch screen status
|
|
int x0, y0; // Point '0'
|
|
int x1, y1; // Point '1'
|
|
|
|
tft.fillRect ( 0, 0, 320, 240, 0 ); // Fade to black
|
|
|
|
DrawString ( "TOUCH TEST: DRAG PANEL", OFFSETX, 233, WHITE, 1 );
|
|
|
|
do
|
|
{
|
|
status = touch_check();
|
|
} while ( status != EVT_TOUCH_PRESSED );
|
|
|
|
touch_position ( &x0, &y0 );
|
|
|
|
do
|
|
{
|
|
status = touch_check ();
|
|
touch_position ( &x1, &y1 );
|
|
|
|
tft.drawLine ( x0, y0, x1, y1, WHITE );
|
|
|
|
x0 = x1;
|
|
y0 = y1;
|
|
} while ( status != EVT_TOUCH_RELEASED );
|
|
}
|
|
|
|
|
|
void ShowVersion ( void )
|
|
{
|
|
char ipBuff[60]; // To format IP address
|
|
|
|
ShowSplash (); // Like "Help - About"
|
|
tft.setTextDatum ( TC_DATUM ); // Top center text position datum
|
|
|
|
sprintf ( ipBuff, "IP address %s", FormatIPAddress ( ipAddress ));
|
|
tft.drawString ( ipBuff, 160, 140 );
|
|
tft.setTextDatum ( TL_DATUM ); // Back to default top left
|
|
|
|
while ( true )
|
|
{
|
|
if ( touch_check () == EVT_TOUCH_PRESSED ) // Wait for screen to be touched
|
|
break; // And bail out
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* "ShowSplash" displays a screen like a "Help - About" screen
|
|
*/
|
|
|
|
void ShowSplash ( void )
|
|
{
|
|
ClearDisplay (); // Fade to black!
|
|
|
|
tft.setTextDatum ( TC_DATUM ); // Top center text position datum
|
|
|
|
tft.setTextColor ( MAGENTA );
|
|
|
|
tft.setFreeFont ( &FreeSerifBoldItalic18pt7b ); // Select Free Serif 9 point font
|
|
tft.drawString ( "TinySA for ESP32", 160, 20 );
|
|
tft.setTextColor ( WHITE );
|
|
tft.setFreeFont ( &FreeSansBold9pt7b ); // Select Free Serif 9 point font
|
|
tft.drawString ( "By WA2FZW, M0WID,", 160, 60 );
|
|
tft.drawString ( "VK3PE and G3ZQC", 160, 80 );
|
|
tft.drawString ( "Version 3.0", 160, 100 );
|
|
tft.drawString ( "Original by Erik (PD0EK)", 160, 120 );
|
|
|
|
tft.setTextDatum ( TL_DATUM ); // Back to default top left
|
|
|
|
tft.setCursor ( 0, 120 ); // Position cursor for any more messages
|
|
tft.setFreeFont ( NULL ); // Select default font
|
|
}
|
|
|
|
|
|
void enter_dfu(void) {} // Do nothing function
|
|
|
|
|
|
void request_to_redraw_grid() // Clear the display and update
|
|
{
|
|
ClearDisplay ();
|
|
changedSetting = true;
|
|
menuExit(); // Handle the return from the menu
|
|
// RedrawHisto ();
|
|
}
|
|
|
|
|
|
void draw_frequencies() {} // Do nothing
|
|
|
|
|
|
|
|
/*
|
|
* "menu_mode_cb" - handles the process of setting the operating mode
|
|
*/
|
|
|
|
void menu_mode_cb ( int item )
|
|
{
|
|
switch ( item )
|
|
{
|
|
case 0: // Set Sweep low range
|
|
setMode(SA_LOW_RANGE);
|
|
ui_mode_normal (); // No menu displayed
|
|
break;
|
|
|
|
case 1: // Set Signal Generator
|
|
setMode(SIG_GEN_LOW_RANGE);
|
|
ui_mode_normal (); // No menu displayed
|
|
break;
|
|
|
|
case 2: // Set IF Sweep mode
|
|
setMode(IF_SWEEP);
|
|
ui_mode_normal (); // No menu displayed
|
|
break;
|
|
|
|
case 3: // Set IF Sweep mode
|
|
setMode(BANDSCOPE);
|
|
ui_mode_normal (); // No menu displayed
|
|
break;
|
|
}
|
|
changedSetting = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* "menu_save_config_cb" - Saves the "config" structure (for use after calibration)
|
|
*/
|
|
|
|
void menu_save_config_cb ( int item )
|
|
{
|
|
WriteConfig (); // Simple enough!
|
|
menu_move_back();
|
|
ui_mode_normal();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_tune_cb" - handles the process of calibrating frequencies of the Si4432
|
|
* modules. See the documentation for an explanation of how to perform the calibration.
|
|
*/
|
|
|
|
void menu_tune_cb ( int item )
|
|
{
|
|
switch ( item )
|
|
{
|
|
case 0: // Calibrate TX
|
|
VFO = TX_4432; // Select transmitter module
|
|
break;
|
|
|
|
case 1: // Calibrate RX
|
|
VFO = RX_4432; // Select receiver module
|
|
break;
|
|
}
|
|
|
|
int km = KM_TUNE;
|
|
ui_mode_keypad ( km );
|
|
ui_process_keypad ();
|
|
|
|
}
|
|
|
|
|
|
void menu_marker_color_cb ( int item )
|
|
{
|
|
char colors[6] = { 'W', 'R', 'B', 'G', 'Y', 'O' };
|
|
|
|
UpdateMarker ( selectedMarker, colors[item] );
|
|
draw_menu ();
|
|
menu_move_back();
|
|
}
|
|
|
|
void menu_marker_select_cb ( int item )
|
|
{
|
|
selectedMarker = item;
|
|
draw_menu ();
|
|
menu_move_back();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_markers_cb" - Turn markers on or off
|
|
*/
|
|
|
|
void menu_markers_cb ( int item )
|
|
{
|
|
switch ( item )
|
|
{
|
|
case 0: // Now handled by "menu_marker_select_cb"
|
|
break; // So do othing
|
|
|
|
case 2: // Toggle the currently selected marker
|
|
marker[selectedMarker].Toggle();
|
|
draw_menu ();
|
|
break;
|
|
|
|
case 3: // Turn them all on
|
|
for ( int i = 0; i < MARKER_COUNT; i++ )
|
|
marker[i].Enable();
|
|
ui_mode_normal();
|
|
break;
|
|
|
|
case 4: // Turn them all off
|
|
for ( int i = 0; i < MARKER_COUNT; i++ )
|
|
marker[i].Disable();
|
|
ui_mode_normal();
|
|
break;
|
|
}
|
|
|
|
for ( int i = 0; i < MARKER_COUNT; i++ )
|
|
setting.MkrStatus[i] = marker[i].Status ();
|
|
|
|
WriteSettings ();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_IF_freq_cb" - Handles setting the IF Frequency
|
|
*/
|
|
|
|
void menu_IF_freq_cb ( int item )
|
|
{
|
|
int km = KM_IFFREQ;
|
|
ui_mode_keypad ( km );
|
|
ui_process_keypad ();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_sig_freq_cb" - Handles setting the signal generator Frequency
|
|
*/
|
|
|
|
void menu_sig_freq_cb ( int item )
|
|
{
|
|
int km = KM_SGFREQ;
|
|
tft.fillScreen ( bg );
|
|
ui_mode_keypad ( km );
|
|
ui_process_keypad ();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_sig_level_cb" - Handles setting the signal generator output level
|
|
*/
|
|
|
|
void menu_sig_level_cb ( int item )
|
|
{
|
|
int km = KM_SGLEVEL;
|
|
tft.fillScreen ( bg );
|
|
ui_mode_keypad ( km );
|
|
ui_process_keypad ();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_sig_levCal_cb" - Handles setting the signal generator max level (no attenuation)
|
|
*/
|
|
|
|
void menu_sig_levCal_cb ( int item )
|
|
{
|
|
int km = KM_SGLEVCAL;
|
|
tft.fillScreen ( bg );
|
|
ui_mode_keypad ( km );
|
|
ui_process_keypad ();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_tg_offset_cb" - Handles setting the tracking generator offset from SA IF
|
|
*/
|
|
|
|
void menu_tg_offset_cb ( int item )
|
|
{
|
|
int km = KM_TGOFFSET;
|
|
tft.fillScreen ( bg );
|
|
ui_mode_keypad ( km );
|
|
ui_process_keypad ();
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* "menu_tgIF_drive_cb" - Handles setting the tracking generator IF drive
|
|
*/
|
|
|
|
void menu_tgIF_drive_cb ( int item )
|
|
{
|
|
int km = KM_TGIF_DRIVE;
|
|
tft.fillScreen ( bg );
|
|
ui_mode_keypad ( km );
|
|
ui_process_keypad ();
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* "menu_tgLo_drive_cb" - Handles setting the tracking generator LO drive
|
|
*/
|
|
|
|
void menu_tgLO_drive_cb ( int item )
|
|
{
|
|
int km = KM_TGLO_DRIVE;
|
|
tft.fillScreen ( bg );
|
|
ui_mode_keypad ( km );
|
|
ui_process_keypad ();
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* "menu_generate_cb" - M0WID Version 05; replaces the function "menu_output_cb"
|
|
* from previous versions.
|
|
*/
|
|
|
|
static void menu_generate_cb ( int item )
|
|
{
|
|
SetGenerate ( 1 ); // Item 0 is off, 1 is on
|
|
// selection = item;
|
|
// draw_menu ();
|
|
// menu_move_back();
|
|
ui_mode_normal (); // No menu displayed
|
|
}
|
|
|
|
|
|
/*
|
|
* menu_tracking_cb handles settings for the tracking generator
|
|
*/
|
|
static void menu_tracking_cb (int item )
|
|
{
|
|
switch ( item )
|
|
{
|
|
case 0: // Turn Off
|
|
SetTracking (0);
|
|
ui_mode_normal (); // Back to sweep
|
|
break;
|
|
|
|
case 1: // Turn On
|
|
SetTracking (1);
|
|
ui_mode_normal (); // Back to sweep
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* "menu_autosettings_cb" seems to set all the defaults then clears the menu
|
|
* from the display.
|
|
*
|
|
* Modified in Version 2.5 by WA2FZW:
|
|
*
|
|
* Added definitions in "My_SA.h" to allow the user to customize the "AUTO" settings.
|
|
*/
|
|
|
|
static void menu_autosettings_cb ( int item )
|
|
{
|
|
SetSweepStart ( AUTO_SWEEP_START ); // Scan limits
|
|
SetSweepStop ( AUTO_SWEEP_STOP );
|
|
SetPowerGrid ( AUTO_PWR_GRID );
|
|
SetPreampGain ( AUTO_LNA );
|
|
SetRefLevel ( AUTO_REF_LEVEL );
|
|
SetRefOutput ( AUTO_REF_OUTPUT );
|
|
SetAttenuation ( AUTO_ATTEN );
|
|
// SetPowerLevel ( 100 ); // Removed - Screws up calibration
|
|
SetRBW ( AUTO_RBW ); // Auto mode
|
|
SetRX ( 0 );
|
|
setting.ShowGain = 1; // Gain trace on
|
|
setting.ShowSweep = 1; // Main sweep trace on
|
|
|
|
menu_move_back ();
|
|
ui_mode_normal (); // No menu displayed
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* "menu_touch_cb" is the dispatcher for part of the "TOUCH SCREEN" menu
|
|
*/
|
|
|
|
static void menu_touch_cb ( int item )
|
|
{
|
|
switch ( item )
|
|
{
|
|
case 0: // All these need symbols!
|
|
touch_cal_exec ();
|
|
request_to_redraw_grid ();
|
|
draw_menu ();
|
|
break;
|
|
|
|
case 1:
|
|
touch_draw_test ();
|
|
request_to_redraw_grid ();
|
|
draw_menu ();
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* "menu_version_cb" handles displaying the "About" screen
|
|
*/
|
|
|
|
static void menu_version_cb ( int item )
|
|
{
|
|
ShowVersion ();
|
|
request_to_redraw_grid ();
|
|
draw_menu ();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_save_cb" saves the current "setting" structure in a named location in the
|
|
* flash memory. The "preferences Save" function adds the "item" number to the string
|
|
* "Save" to create the saved name.
|
|
*/
|
|
|
|
static void menu_save_cb ( int item )
|
|
{
|
|
if ( item < 0 || item > 4 ) // Legal "item" number?
|
|
return; // Nope
|
|
|
|
Save ( item );
|
|
menu_move_back();
|
|
ui_mode_normal();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_recall_cb" - Works like "menu_save_cb" in reverse
|
|
*/
|
|
|
|
static void menu_recall_cb ( int item )
|
|
{
|
|
if ( item < 0 || item > 4 ) // Test for illegal "item"
|
|
return;
|
|
|
|
Recall ( item );
|
|
menu_move_back();
|
|
ui_mode_normal();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_refer_cb" - Set reference level from 1st page of the "REFERENCE" menu
|
|
*/
|
|
|
|
static void menu_refer_cb ( int item )
|
|
{
|
|
// Serial.println ( item ); // Debugging
|
|
|
|
SetRefOutput ( menu_refer_value[item] );
|
|
menu_move_back();
|
|
ui_mode_normal();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_refer_cb2" - Set reference output frequency from 2nd page
|
|
* of the "REFERENCE" menu
|
|
*/
|
|
|
|
static void menu_refer_cb2 ( int item )
|
|
{
|
|
// Serial.println ( item ); // Debugging
|
|
|
|
SetRefOutput ( menu_refer_value[item+5] ); // Items 0 - 4 are on page 1
|
|
menu_move_back ();
|
|
ui_mode_normal ();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_spur_cb" - Handles the "Spur Reduction" menu item.
|
|
*/
|
|
|
|
static void menu_spur_cb ( int item )
|
|
{
|
|
SetSpur ( item );
|
|
menu_move_back ();
|
|
ui_mode_normal ();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_storage_cb" - Handles the "STORAGE" menu item.
|
|
*/
|
|
|
|
static void menu_storage_cb ( int item )
|
|
{
|
|
switch ( item )
|
|
{
|
|
case 0: // "STORE"
|
|
SetStorage ();
|
|
break;
|
|
|
|
case 1:
|
|
SetClearStorage (); // "CLEAR"
|
|
break;
|
|
|
|
case 2: // "SUBTRACT" - What does this mean?
|
|
SetSubtractStorage ();
|
|
break;
|
|
}
|
|
|
|
menu_move_back ();
|
|
ui_mode_normal ();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_average_cb" - Handles the "AVERAGE" menu item.
|
|
*/
|
|
|
|
static void menu_average_cb ( int item )
|
|
{
|
|
SetAverage ( item );
|
|
menu_move_back ();
|
|
ui_mode_normal ();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_rbw_cb" - Handles the "RBW" menu item.
|
|
*
|
|
* WA2FZW - Moved the "rbwsel" choices into the function; they were previously
|
|
* defined in global space.
|
|
*/
|
|
|
|
static void menu_rbw_cb ( int item )
|
|
{
|
|
const int rbwsel[] = { 0, 31, 106, 322, 1121, 3355 }; // Resolution bandwidth choices (in KHz * 10)
|
|
|
|
SetRBW ( rbwsel[item] );
|
|
menu_move_back ();
|
|
ui_mode_normal ();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_dBper_cb" - Handles the "SCALE/DIV" menu item
|
|
*/
|
|
|
|
static void menu_dBper_cb ( int item )
|
|
{
|
|
int menu_dBper_value[] = { 1, 2, 5, 10, 20 }; // Scale setting values (dB/division)
|
|
|
|
SetPowerGrid ( menu_dBper_value[item] );
|
|
menu_move_back ();
|
|
ui_mode_normal ();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_dBgain_cb" - Handles the "PREAMP GAIN" menu item.
|
|
*/
|
|
|
|
static void menu_dBgain_cb ( int item )
|
|
{
|
|
if ( item == 0 ) // Turn the AGC on
|
|
{
|
|
SetPreampGain ( 0x60 ); // ACG on value
|
|
menu_move_back ();
|
|
ui_mode_normal ();
|
|
}
|
|
|
|
else // Get value from the keypad
|
|
{
|
|
int km = KM_PREAMP;
|
|
ui_mode_keypad ( km );
|
|
ui_process_keypad ();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* "choose_active_trace" - Holdover from NanoVNA but left in as it might be used
|
|
* in the future in the TinySA.
|
|
*/
|
|
|
|
static void choose_active_trace ( void )
|
|
{
|
|
int i;
|
|
|
|
if ( trace[uistat.current_trace].enabled ) // If true
|
|
return; // Do nothing
|
|
|
|
for ( i = 0; i < TRACE_COUNT ; i++ ) // "TRACE_COUNT" is set to '1' somewhere
|
|
if ( trace[i].enabled ) // Find first "enabled: trace
|
|
{
|
|
uistat.current_trace = i; // Save the index
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Repurposed in Version 2.6 by WA2FZW:
|
|
*
|
|
* Now toggles the main sweep trace or the gain trace on or off.
|
|
*
|
|
*
|
|
* Like so many other of these functions "item" is the position of the item in the
|
|
* menu; this has to be fixed!
|
|
*
|
|
* Here, item '0' is the main sweep trace and item '1' is the gain trace.
|
|
*/
|
|
|
|
static void menu_trace_cb ( int item )
|
|
{
|
|
switch ( item )
|
|
{
|
|
case 0: // Toggle the main sweep
|
|
setting.ShowSweep = !setting.ShowSweep;
|
|
|
|
break;
|
|
|
|
case 1: // Toggle the gain trace
|
|
setting.ShowGain = !setting.ShowGain;
|
|
|
|
break;
|
|
}
|
|
|
|
WriteSettings ();
|
|
menu_move_back ();
|
|
ui_mode_normal ();
|
|
}
|
|
|
|
|
|
static void menu_atten_cb ( int item )
|
|
{
|
|
int km = KM_ATTENUATION;
|
|
ui_mode_keypad ( km );
|
|
ui_process_keypad ();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_scale_cb" - Handles the "REF LEVEL" menu item.
|
|
*/
|
|
|
|
static void menu_scale_cb ( int item )
|
|
{
|
|
int km = KM_REFPOS;
|
|
ui_mode_keypad ( km );
|
|
ui_process_keypad ();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_actualpower_cb" - Handles the "ACTUAL POWER" menu item.
|
|
*/
|
|
|
|
static void menu_actualpower_cb ( int item )
|
|
{
|
|
int km = KM_ACTUALPOWER;
|
|
ui_mode_keypad ( km );
|
|
ui_process_keypad ();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_sweep_cb" - Handles the menu items under the "SCAN" menu.
|
|
*
|
|
* Modified in Version 2.5 by WA2FZW:
|
|
*
|
|
* Eliminated "case 5" which was the handler for "Pause Sweep". That menu
|
|
* choice really didn't do anything, so it was eliminated altogether. I left
|
|
* the switch intact should we wish to add something to the "Scan" menu list.
|
|
*
|
|
*
|
|
* Modified in Version 2.9 by WA2FZW:
|
|
*
|
|
* Totally eliminated the "switch" as all the menu items that set frequencies
|
|
* are handled the same.
|
|
*/
|
|
|
|
static void menu_sweep_cb ( int item )
|
|
{
|
|
ui_mode_keypad ( item );
|
|
ui_process_keypad ();
|
|
}
|
|
|
|
|
|
|
|
static void menu_IF_sweep_cb ( int item )
|
|
{
|
|
ui_mode_keypad ( item + KM_IFSTART - 1 ); // item = 1 -> KM_IFSTART, 2 -> KM_IFSTOP, 3-> KM_IFSIG
|
|
ui_process_keypad ();
|
|
}
|
|
|
|
static void menu_Bandscope_cb ( int item )
|
|
{
|
|
ui_mode_keypad ( item + KM_BANDSCOPESTART - 1 ); // item = 1 -> KM_BANDSCOPESTART, 2 -> KM_BANDSCOPESPAN
|
|
ui_process_keypad ();
|
|
}
|
|
|
|
/*
|
|
* "ensure_selection" - Validates that a menu selection is valid
|
|
*/
|
|
|
|
static void ensure_selection ( void )
|
|
{
|
|
Menuitem *menu = menu_stack[menu_current_level];
|
|
int i;
|
|
|
|
for ( i = 0; menu[i].Type() != MT_END; i++ ) {} // Drops out when the "END" is found
|
|
|
|
if ( selection >= i )
|
|
selection = i - 1;
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_move_back" - Go back to the previous menu level
|
|
*/
|
|
|
|
static void menu_move_back ( void )
|
|
{
|
|
if ( menu_current_level == 0 )
|
|
return;
|
|
|
|
// Serial.print ( "Poplevel=" );
|
|
// Serial.println ( menu_current_level );
|
|
|
|
menu_current_level--;
|
|
ensure_selection (); // Make sure valid
|
|
erase_menu_buttons (); // Erase old buttons
|
|
draw_menu (); // Paint new ones
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_push_submenu" - Paint a new sub-menu
|
|
*/
|
|
|
|
static void menu_push_submenu ( Menuitem *submenu )
|
|
{
|
|
|
|
// Serial.print( "Pushlevel=" );
|
|
// Serial.println ( menu_current_level );
|
|
|
|
if ( menu_current_level < MENU_STACK_DEPTH - 1 )
|
|
menu_current_level++;
|
|
|
|
menu_stack[menu_current_level] = submenu;
|
|
ensure_selection ();
|
|
erase_menu_buttons ();
|
|
draw_menu ();
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_invoke" -
|
|
*/
|
|
|
|
static void menu_invoke ( int item )
|
|
{
|
|
Menuitem *menu = menu_stack[menu_current_level];
|
|
menu = &menu[item];
|
|
|
|
// Serial.print ( "Invoke=" );
|
|
// Serial.print ( item );
|
|
// Serial.print ( ", type=" );
|
|
// Serial.print ( menu->type );
|
|
// Serial.print ( ", label= " );
|
|
// Serial.println ( menu->label );
|
|
|
|
switch ( menu->Type() )
|
|
{
|
|
case MT_END:
|
|
ui_mode_normal (); // Clear menu display
|
|
break;
|
|
|
|
case MT_BACK: // Go up one level
|
|
menu_move_back ();
|
|
break;
|
|
|
|
case MT_FUNC: // Call function to process selection
|
|
{
|
|
menu->Call ( item );
|
|
break;
|
|
}
|
|
|
|
case MT_MENU: // Display a sub-menu
|
|
menu_push_submenu ( menu->GetSubmenu () );
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* All the following stuff has to do with the keypad. The first two definitions
|
|
* are the 'x' and 'y' coordinates of the entire keypad. The "KP_X" and "KP_Y"
|
|
* macros set the 'x' and 'y' pixel coordinates for the key based on its row
|
|
* and column in the keypad; pretty clever!
|
|
*/
|
|
|
|
#define KP_X(x) ( 48 * ( x ) + 2 + ( 320 - 64 - 192 ))
|
|
#define KP_Y(y) ( 48 * ( y ) + 2 )
|
|
|
|
|
|
|
|
typedef struct
|
|
{
|
|
uint16_t x, y; // X and Y coordinates of a key
|
|
int8_t c; // Index to the "kpf" array of characters?
|
|
} keypads_t;
|
|
|
|
static const keypads_t *keypads; // Pointer to array of keypads
|
|
static uint8_t keypads_last_index; // Index into the array
|
|
|
|
|
|
/*
|
|
* There are different keypads for different things.
|
|
*
|
|
* The numbers in the "KP_X(n)" and "KP_Y(n) macro calls are the X and Y positions
|
|
* of the keys the columns (X) are numbered from left to right as 0 to 3 and the
|
|
* rows (Y) are numbered from top to bottom as 0 to 3.
|
|
*
|
|
* WA2FZW - Some space can be saved by creating one generic keypad with the digits
|
|
* and decimal point and then individual supplemental ones for the special keys on
|
|
* eash of the following.
|
|
*
|
|
* The first one is for entering frequencies.
|
|
*/
|
|
|
|
static const keypads_t keypads_freq[] = // Keypad array for frequencies
|
|
{
|
|
{ KP_X(1), KP_Y(3), KN_PERIOD }, // Decimal point
|
|
{ KP_X(0), KP_Y(3), 0 }, // '0' digit
|
|
{ KP_X(0), KP_Y(2), 1 }, // '1' digit
|
|
{ KP_X(1), KP_Y(2), 2 },
|
|
{ KP_X(2), KP_Y(2), 3 },
|
|
{ KP_X(0), KP_Y(1), 4 },
|
|
{ KP_X(1), KP_Y(1), 5 },
|
|
{ KP_X(2), KP_Y(1), 6 },
|
|
{ KP_X(0), KP_Y(0), 7 },
|
|
{ KP_X(1), KP_Y(0), 8 },
|
|
{ KP_X(2), KP_Y(0), 9 },
|
|
{ KP_X(3), KP_Y(1), KN_M }, // Megahertz
|
|
{ KP_X(3), KP_Y(2), KN_K }, // Kilohertz
|
|
{ KP_X(3), KP_Y(3), KN_X }, // Enter
|
|
{ KP_X(2), KP_Y(3), KN_BS }, // Backspace
|
|
{ 0, 0, -1 } // Array end marker
|
|
};
|
|
|
|
|
|
static const keypads_t keypads_signed_freq[] = // Keypad array for signed frequencies
|
|
{
|
|
{ KP_X(1), KP_Y(3), KN_PERIOD }, // Decimal point
|
|
{ KP_X(0), KP_Y(3), 0 }, // '0' digit
|
|
{ KP_X(0), KP_Y(2), 1 }, // '1' digit
|
|
{ KP_X(1), KP_Y(2), 2 },
|
|
{ KP_X(2), KP_Y(2), 3 },
|
|
{ KP_X(0), KP_Y(1), 4 },
|
|
{ KP_X(1), KP_Y(1), 5 },
|
|
{ KP_X(2), KP_Y(1), 6 },
|
|
{ KP_X(0), KP_Y(0), 7 },
|
|
{ KP_X(1), KP_Y(0), 8 },
|
|
{ KP_X(2), KP_Y(0), 9 },
|
|
{ KP_X(3), KP_Y(0), KN_MINUS },
|
|
{ KP_X(3), KP_Y(1), KN_M }, // Megahertz
|
|
{ KP_X(3), KP_Y(2), KN_K }, // Kilohertz
|
|
{ KP_X(3), KP_Y(3), KN_X }, // Enter
|
|
{ KP_X(2), KP_Y(3), KN_BS }, // Backspace
|
|
{ 0, 0, -1 } // Array end marker
|
|
};
|
|
|
|
static const keypads_t keypads_integer[] = // Keypad array for integers (no decimal point)
|
|
{
|
|
{ KP_X(1), KP_Y(3), 0 },
|
|
{ KP_X(1), KP_Y(2), 1 },
|
|
{ KP_X(2), KP_Y(2), 2 },
|
|
{ KP_X(3), KP_Y(2), 3 },
|
|
{ KP_X(1), KP_Y(1), 4 },
|
|
{ KP_X(2), KP_Y(1), 5 },
|
|
{ KP_X(3), KP_Y(1), 6 },
|
|
{ KP_X(1), KP_Y(0), 7 },
|
|
{ KP_X(2), KP_Y(0), 8 },
|
|
{ KP_X(3), KP_Y(0), 9 },
|
|
{ KP_X(3), KP_Y(3), KN_X },
|
|
{ KP_X(2), KP_Y(3), KN_BS },
|
|
{ 0, 0, -1 }
|
|
};
|
|
|
|
static const keypads_t keypads_level[] = // Used for "ACTUAL POWER" input
|
|
{
|
|
{ KP_X(1), KP_Y(3), KN_PERIOD },
|
|
{ KP_X(0), KP_Y(3), 0 },
|
|
{ KP_X(0), KP_Y(2), 1 },
|
|
{ KP_X(1), KP_Y(2), 2 },
|
|
{ KP_X(2), KP_Y(2), 3 },
|
|
{ KP_X(0), KP_Y(1), 4 },
|
|
{ KP_X(1), KP_Y(1), 5 },
|
|
{ KP_X(2), KP_Y(1), 6 },
|
|
{ KP_X(0), KP_Y(0), 7 },
|
|
{ KP_X(1), KP_Y(0), 8 },
|
|
{ KP_X(2), KP_Y(0), 9 },
|
|
{ KP_X(3), KP_Y(2), KN_MINUS },
|
|
{ KP_X(3), KP_Y(3), KN_X },
|
|
{ KP_X(2), KP_Y(3), KN_BS },
|
|
{ 0, 0, -1 }
|
|
};
|
|
|
|
|
|
/*
|
|
* This array is indexed by the enum at the top of the file that defines the values for
|
|
* "KM_START", KM_STOP, etc.
|
|
*/
|
|
|
|
static const keypads_t * const keypads_mode_tbl[] =
|
|
{
|
|
keypads_freq, // KM_START..........Sweep start frequency
|
|
keypads_freq, // KM_STOP...........Sweep stop frequency
|
|
keypads_freq, // KM_CENTER.........Sweep center frequency
|
|
keypads_freq, // KM_SPAN...........Sweep frequency span
|
|
keypads_freq, // KM_FOCUS..........Focus Frequency
|
|
keypads_level, // KM_REFPOS.........Grid reference level (top line)
|
|
keypads_integer, // KM_ATTENUATION....Attenuation
|
|
keypads_level, // KM_ACTUALPOWER....Power level calibration
|
|
keypads_freq, // KM_IFFREQ.........IF frequency
|
|
keypads_integer, // KM_PREAMP.........Preamp gain
|
|
keypads_integer, // KM_TUNE...........Transceiver crystal load
|
|
keypads_freq, // KM_SGFREQ.........Sig Gen frequency
|
|
keypads_level, // KM_SGLEVEL........Sig Gen Power level
|
|
keypads_level, // KM_SGLEVCAL.......Power level calibration
|
|
keypads_freq, // KM_IFSTART........IF Sweep start frequency
|
|
keypads_freq, // KM_IFSTOP.........IF Sweep stop frequency
|
|
keypads_freq, // KM_IFSIG..........IF Sweep signal frequency
|
|
keypads_signed_freq, // KM_TGOFFSET.......Offset Frequency of TG IF compared to SA IF
|
|
keypads_level, // KM_TGLO_DRIVE.....Tracking generator LO drive
|
|
keypads_level, // KM_TGIF_DRIVE.....Tracking generator IF drive
|
|
keypads_freq, // KM_BANDSCOPESTART.IF Sweep start frequency
|
|
keypads_freq // KM_BANDSCOPESPAN..IF Sweep stop frequency
|
|
};
|
|
|
|
|
|
/*
|
|
* "draw_keypad" - Seems pretty self-explanatory!
|
|
*
|
|
* Modified in Version 2.7 by WA2FZW:
|
|
*
|
|
* Instead of simply painting reqular characters from the (no longer existing)
|
|
* "kpf" array, the characters used in the keypad keys and in the number box are
|
|
* now painted using bitmaps in the "KP_Font" array.
|
|
*
|
|
* The "KeyNumber" function replaces the "DrawFont" function to paint the bitmaps.
|
|
*/
|
|
|
|
static void draw_keypad ( void )
|
|
{
|
|
int i = 0;
|
|
|
|
while ( keypads[i].x ) // Non zero "X" location
|
|
{
|
|
uint16_t bg = config.menu_normal_color; // Color when key is not selected
|
|
|
|
if ( i == selection )
|
|
bg = config.menu_active_color; // Color when a key is selected
|
|
|
|
tft.fillRect ( keypads[i].x, keypads[i].y, 44, 44, bg ); // Set background color
|
|
|
|
KeyNumber ( keypads[i].c, keypads[i].x+12, keypads[i].y+10 ); // Paint the character
|
|
|
|
i++; // Next
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
* "KeyNumber" uses the "KP_Font" array to draw a number in a keypad key.
|
|
*/
|
|
|
|
static void KeyNumber ( int8_t key, int x, int y )
|
|
{
|
|
|
|
uint16_t bits; // Holds the bitmap for one line
|
|
|
|
uint16_t* font = &KP_Font[key * 22]; // Calculate pointer to desired bitmap
|
|
|
|
for ( int line = 0; line < 22; line++ ) // Do line by line; top to bottom
|
|
{
|
|
bits = font[line]; // Get the bit pattern for a line
|
|
|
|
for ( int column = 0; column < 16; column++ ) // horizontally left to right
|
|
{
|
|
if ( bits & 0x8000 ) // Is the next pixel turned on?
|
|
tft.drawPixel ( column+x, line+y, BLACK ); // Yes, always black
|
|
|
|
bits <<= 1; // Shift the bitmap byte one place left
|
|
}
|
|
} // Next line
|
|
}
|
|
|
|
/*
|
|
* "draw_numeric_area_frame" - Draws the numerical box uncer the keypad
|
|
*/
|
|
|
|
static void draw_numeric_area_frame ( void )
|
|
{
|
|
tft.fillRect ( 0, 208, 256, 32, WHITE ); // White background
|
|
|
|
DrawString ( keypad_mode_label[keypad_mode], 10, 220, BLACK, 1 );
|
|
tft.setCursor(0,230);
|
|
tft.printf("%i",uistat.previous_value);
|
|
}
|
|
|
|
|
|
/*
|
|
* "draw_numeric_input" - Puts numbers in the numerical entry box
|
|
*
|
|
* Modified in Version 2.7 by WA2FZW:
|
|
*
|
|
* Instead of using characters from the (no longer exists) "kpf" array to write
|
|
* in the numerical input box, the characters are now defined by bitmaps in the
|
|
* "KP_Font" array. The "KeyNumber" replaces the (no longer exists) "DrawFont"
|
|
* function.
|
|
*
|
|
* Also re-did how it decides to add space after every third digit. A leading
|
|
* minus sign no longer counts and if a decimal point is entered, we no longer
|
|
* add the extra space between digits.
|
|
*/
|
|
|
|
static void draw_numeric_input ( const char *buf )
|
|
{
|
|
int i = 0; // Buffer index
|
|
int x = 58; // 'X' coordinate for first character
|
|
int nextX = 20; // Normal character spacing
|
|
bool sawDot = false; // True if decimal entered
|
|
uint8_t digits = 0; // Digit counter
|
|
|
|
for ( i = 0; i < 10 && buf[i]; i++ )
|
|
{
|
|
nextX = 18; // Normal character spacing
|
|
|
|
uint16_t fg = BLACK; // Foreground is black
|
|
uint16_t bg = WHITE; // Background is white
|
|
|
|
int c = buf[i]; // Get a character
|
|
|
|
if ( c == '.' ) // Decimal point?
|
|
{
|
|
c = KN_PERIOD; // Index to '.' in the "KP_Font" array
|
|
sawDot = true; // Decimal seen
|
|
}
|
|
|
|
else if ( c == '-' ) // Minus sign"
|
|
c = KN_MINUS; // Index to '_' in the "KP_Font" array
|
|
|
|
else if ( isDigit ( c )) // Digit?
|
|
c = c - '0'; // Quick & dirty "atoi"
|
|
|
|
else // None of the above
|
|
c = -1;
|
|
|
|
if ( c >= 0 ) // 'c' was found
|
|
{
|
|
KeyNumber ( c, x, 208+4 ); // Paint the character
|
|
// addIx++;
|
|
|
|
if ( c <= 9 ) // Is it a number?
|
|
{
|
|
digits++; // Increment the digit counter
|
|
if ( !sawDot ) // No decimal yet
|
|
if (( digits % 3 ) == 0 ) // Every third digit
|
|
nextX += 6; // Add extra space
|
|
}
|
|
}
|
|
|
|
else
|
|
tft.fillRect ( x, 208+4, 20, 24, bg ); // If not found, erase it
|
|
|
|
x += nextX; // Place for next digit
|
|
|
|
} // End of for loop
|
|
|
|
if ( i < 10 )
|
|
tft.fillRect ( x, 208+4, 20 * ( 10-i ), 24, WHITE ); // Fill something with white
|
|
}
|
|
|
|
|
|
/*
|
|
* "draw_menu_buttons" - Paint the menu buttons
|
|
*/
|
|
|
|
static void draw_menu_buttons ( Menuitem *menu )
|
|
{
|
|
int i = 0;
|
|
|
|
//Serial.println( "----------------------------" ); // Debugging
|
|
|
|
for ( i = 0; i < 7; i++ ) // Maximum number of menu buttons is 7
|
|
{
|
|
if ( menu[i].Type() == MT_END ) // End of the menu
|
|
break; // So no need to look any further
|
|
|
|
int y = 32 * i; // "Y" coordinate in pixels?
|
|
uint16_t bg = config.menu_normal_color; // Background is unselected color
|
|
uint16_t fg = BLACK; // Text is in black
|
|
|
|
if ( ui_mode == UI_MENU && i == selection ) // focus only in MENU mode but not in KEYPAD mode
|
|
bg = config.menu_active_color; // Set background to selected color
|
|
|
|
tft.fillRect ( 320-60, y, 60, 30, bg ); // These hard coded numbers have to go!
|
|
|
|
if ( menu[i].isMultiline ()) // Multi-line label?
|
|
{
|
|
DrawString ( menu[i].Text1(), 320-54, y+6, fg, 1 ); // First line
|
|
DrawString ( menu[i].Text2(), 320-54, y+17, fg, 1 ); // Second line
|
|
}
|
|
|
|
else // Single line label
|
|
DrawString ( menu[i].Text1(), 320-54, y+12, fg, 1 );
|
|
} // End of for loop
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_select_touch" - Wait for a menu button to be pushed
|
|
*/
|
|
|
|
static void menu_select_touch ( int i )
|
|
{
|
|
selection = i;
|
|
|
|
draw_menu (); // Draw the menu buttons
|
|
|
|
// Serial.println ( "Before wait release" ); // Debugging
|
|
|
|
touch_wait_release (); // Wait for a release indication
|
|
|
|
// Serial.println ( "After wait release" );
|
|
|
|
selection = -1; // Don't understand this ???
|
|
|
|
menu_invoke ( i );
|
|
}
|
|
|
|
|
|
/*
|
|
* "menu_apply_touch" - Figure out which button was touched
|
|
*/
|
|
|
|
static void menu_apply_touch ( void )
|
|
{
|
|
int touch_x, touch_y; // Touch coordinates
|
|
Menuitem *menu = menu_stack[menu_current_level];
|
|
int i;
|
|
|
|
touch_position ( &touch_x, &touch_y ); // Get coordinates
|
|
|
|
for ( i = 0; i < 7; i++ ) // Up to 7 buttons
|
|
{
|
|
int y = 32 * i; // "Y" coordinate of button in pixels
|
|
|
|
if ( y-2 < touch_y && touch_y < y+30+2 && 320-60 < touch_x )
|
|
{
|
|
menu_select_touch ( i ); // This is the button that was selected
|
|
return; // We're done!
|
|
}
|
|
} // End of for loop
|
|
|
|
touch_wait_release (); // Wait for button release
|
|
ui_mode_normal (); // No more menu
|
|
}
|
|
|
|
|
|
/*
|
|
* "draw_menu" - Paint the entire menu
|
|
*/
|
|
|
|
static void draw_menu ( void )
|
|
{
|
|
// Serial.println ( "draw menu" ); // Debugging
|
|
draw_menu_buttons ( menu_stack[menu_current_level] ); // Paint the buttons
|
|
}
|
|
|
|
|
|
/*
|
|
* "erase_menu_buttons" - Self explanatory
|
|
*/
|
|
static void erase_menu_buttons ( void )
|
|
{
|
|
|
|
// Serial.println ( "erase buttons" ); // Debugging
|
|
|
|
tft.fillRect ( 320-60, 0, 60, 32*7, bg );
|
|
}
|
|
|
|
|
|
/*
|
|
* "erase_numeric_input" - Erase the numerical input box below the keypad
|
|
*/
|
|
|
|
static void erase_numeric_input ( void )
|
|
{
|
|
tft.fillRect ( 0, 240-32, 320, 32, bg ); // Poof!
|
|
}
|
|
|
|
|
|
/*
|
|
* "request_to_draw_cells_behind_menu" - Do nothing function
|
|
*/
|
|
|
|
void request_to_draw_cells_behind_menu () {}
|
|
|
|
|
|
/*
|
|
* "leave_ui_mode" - Cleanup after using the touch screen.
|
|
*
|
|
* Modified in Version 2.1 by WA2FZW:
|
|
*
|
|
* Eliminated "changedSetting" test and "WriteSettings". Because savings the
|
|
* settings was also being handled in some of the functions that set the members
|
|
* of the "setting" structure, the structure was sometimes being saved twice. It
|
|
* was also being saved when the parameters didn't actually change. This was
|
|
* all fixed in "Cmd.cpp".
|
|
*/
|
|
|
|
static void leave_ui_mode ( void )
|
|
{
|
|
if ( ui_mode == UI_MENU ) // In menu mode?
|
|
{
|
|
erase_menu_buttons (); // Erase the menu area
|
|
request_to_redraw_grid();
|
|
}
|
|
|
|
else if ( ui_mode == UI_NUMERIC ) // Using the keypad?
|
|
erase_numeric_input (); // Erase the number box
|
|
|
|
// Serial.println ( "leave UI" ); // Debugging
|
|
}
|
|
|
|
|
|
/*
|
|
* "fetch_numeric_target" - Gets one of the scan frequency parameters. The
|
|
* "GetSweepStart()" etc functions are in the cmd.cpp file.
|
|
*/
|
|
|
|
static void fetch_numeric_target ( void )
|
|
{
|
|
switch ( keypad_mode )
|
|
{
|
|
case KM_START:
|
|
uistat.value = GetSweepStart ();
|
|
break;
|
|
|
|
case KM_STOP:
|
|
uistat.value = GetSweepStop ();
|
|
break;
|
|
|
|
case KM_CENTER:
|
|
uistat.value = GetSweepCenter ();
|
|
break;
|
|
|
|
case KM_SPAN:
|
|
uistat.value = GetSweepSpan ();
|
|
break;
|
|
|
|
case KM_FOCUS:
|
|
uistat.value = GetSweepCenter ();
|
|
break;
|
|
|
|
case KM_REFPOS:
|
|
// uistat.value = get_trace_refpos ( uistat.current_trace ) * 1000;
|
|
break;
|
|
|
|
case KM_ATTENUATION:
|
|
uistat.value = setting.Attenuate;
|
|
break;
|
|
|
|
case KM_ACTUALPOWER:
|
|
// uistat.value = velocity_factor;
|
|
break;
|
|
|
|
case KM_IFFREQ:
|
|
uistat.value = setting.IF_Freq;
|
|
break;
|
|
|
|
case KM_SGFREQ:
|
|
uistat.value = sigGenSetting.Frequency;
|
|
break;
|
|
|
|
case KM_SGLEVEL:
|
|
uistat.value = sigGenSetting.Power;
|
|
break;
|
|
|
|
case KM_SGLEVCAL:
|
|
uistat.value = sigGenSetting.Calibration;
|
|
break;
|
|
|
|
case KM_PREAMP:
|
|
uistat.value = GetPreampGain ( &AGC_On, &AGC_Reg );
|
|
break;
|
|
|
|
case KM_IFSTART:
|
|
uistat.value = GetIFsweepStart();
|
|
break;
|
|
|
|
case KM_IFSTOP:
|
|
uistat.value = GetIFsweepStop();
|
|
break;
|
|
|
|
case KM_IFSIG:
|
|
uistat.value = GetIFsweepSigFreq();
|
|
break;
|
|
|
|
case KM_TGOFFSET:
|
|
uistat.value = trackGenSetting.Offset;
|
|
break;
|
|
|
|
case KM_TGIF_DRIVE:
|
|
uistat.value = trackGenSetting.IF_Drive;
|
|
break;
|
|
|
|
case KM_TGLO_DRIVE:
|
|
uistat.value = trackGenSetting.LO_Drive;
|
|
break;
|
|
|
|
case KM_BANDSCOPESTART:
|
|
uistat.value = setting.BandscopeStart;
|
|
break;
|
|
|
|
case KM_BANDSCOPESPAN:
|
|
uistat.value = setting.BandscopeSpan;
|
|
break;
|
|
|
|
}
|
|
|
|
uint32_t x = uistat.value;
|
|
int n = 0;
|
|
|
|
for (; x >= 10 && n < 9; n++ )
|
|
x /= 10;
|
|
|
|
uistat.digit = n;
|
|
|
|
uistat.previous_value = uistat.value;
|
|
Serial.printf("uistat previous value %f\n", uistat.previous_value );
|
|
}
|
|
|
|
|
|
/*
|
|
* "draw_numeric_area" - Paints adds the appropriate text to the numeric entry box
|
|
* and requests it to be painted.
|
|
*/
|
|
|
|
static void draw_numeric_area ( void )
|
|
{
|
|
char buf[10];
|
|
snprintf ( buf, sizeof buf, "%9d", uistat.value );
|
|
draw_numeric_input ( buf );
|
|
}
|
|
|
|
|
|
/*
|
|
* "ui_mode_menu" - Sets menu mode and paints the menu
|
|
*/
|
|
|
|
static void ui_mode_menu ( void )
|
|
{
|
|
|
|
if ( ui_mode == UI_MENU ) // If already in menu mode
|
|
return; // Nothing to do here
|
|
|
|
ui_mode = UI_MENU; // Set menu mode
|
|
Serial.println("ui_mode_menu");
|
|
// area_width = AREA_WIDTH_NORMAL - ( 64 - 8 ); // Narrower plotting area
|
|
// area_height = HEIGHT;
|
|
ensure_selection (); // Validate current selection
|
|
draw_menu (); // And paint the menu
|
|
}
|
|
|
|
|
|
/*
|
|
* "ui_mode_numeric" - Puts the UI into numeric mode
|
|
*/
|
|
static void ui_mode_numeric ( int _keypad_mode )
|
|
{
|
|
if ( ui_mode == UI_NUMERIC ) // Already in numeric mode?
|
|
return; // Nothing to do
|
|
|
|
leave_ui_mode (); // Get out of previous mode?
|
|
|
|
keypad_mode = _keypad_mode; // Set numeric mode
|
|
ui_mode = UI_NUMERIC;
|
|
|
|
// area_width = AREA_WIDTH_NORMAL;
|
|
// area_height = 240 - 32; // HEIGHT - 32;
|
|
|
|
draw_numeric_area_frame ();
|
|
fetch_numeric_target ();
|
|
draw_numeric_area ();
|
|
}
|
|
|
|
|
|
/*
|
|
* "ui_mode_keypad" - Puts us in keypad mode
|
|
*/
|
|
|
|
static void ui_mode_keypad ( int _keypad_mode )
|
|
{
|
|
if ( ui_mode == UI_KEYPAD ) // Already here?
|
|
return; // Nuttin to do
|
|
|
|
keypad_mode = _keypad_mode; // Pick the proper keypad format
|
|
keypads = keypads_mode_tbl[_keypad_mode];
|
|
|
|
int i;
|
|
for ( i = 0; keypads[i+1].c >= 0; i++ ) {}
|
|
|
|
keypads_last_index = i; // Fall out of loop when found
|
|
|
|
ui_mode = UI_KEYPAD; // Set keypad mode
|
|
|
|
// area_width = AREA_WIDTH_NORMAL - ( 64 - 8 );
|
|
// area_height = HEIGHT - 32;
|
|
|
|
draw_menu (); // Paint the menu
|
|
draw_keypad (); // Then the keypad
|
|
fetch_numeric_target (); //!!!!!
|
|
draw_numeric_area_frame (); // Then the numeric entry area
|
|
draw_numeric_input (""); // Blanked out?
|
|
}
|
|
|
|
|
|
/*
|
|
* "ui_mode_normal" - Puts the UI into normal mode
|
|
*/
|
|
|
|
static void ui_mode_normal ( void )
|
|
{
|
|
if ( ui_mode == UI_NORMAL ) // Already there?
|
|
return; // Done
|
|
|
|
//**HERE2
|
|
// area_width = AREA_WIDTH_NORMAL;
|
|
// area_height = HEIGHT;
|
|
|
|
menu_current_level = 0;
|
|
|
|
leave_ui_mode();
|
|
ui_mode = UI_NORMAL;
|
|
}
|
|
|
|
|
|
/*
|
|
* "my_atof" - A homebrew ascii to double function; not sure why needed?
|
|
*/
|
|
|
|
double my_atof ( const char *p )
|
|
{
|
|
int neg = FALSE;
|
|
|
|
if ( *p == '-' ) // If first character is a minus sign
|
|
neg = TRUE; // Number is negative
|
|
|
|
if ( *p == '-' || *p == '+' ) // If first character is a plus or minus sign
|
|
p++; // Skip over it
|
|
|
|
double x = atoi ( p ); // ???
|
|
|
|
while ( isdigit ( (int) *p )) // If next character is a digit
|
|
p++; // Bump the pointer
|
|
|
|
if ( *p == '.' ) // If it's a decimal point
|
|
{
|
|
double d = 1.0f; // "d" = '1' in floating point
|
|
p++; // Next character
|
|
|
|
while ( isdigit ( (int) *p )) // As long as we see digits
|
|
{
|
|
d /= 10; // Divide "d" by 10
|
|
x += d * ( *p - '0' ); // Then add in the next digit
|
|
p++; // Next character
|
|
}
|
|
}
|
|
|
|
if ( *p == 'e' || *p == 'E' ) // Not a digit then is it an exponent?
|
|
{
|
|
p++; // Next character
|
|
int exp = atoi ( p ); // Convert exponent to integer
|
|
|
|
while ( exp > 0 ) // If exponent positive
|
|
{
|
|
x *= 10; // Multiply the number by 10
|
|
exp--; // And decrement the exponent
|
|
}
|
|
|
|
while ( exp < 0 ) // If the exponent is negative
|
|
{
|
|
x /= 10; // Divide the number by 10
|
|
exp++; // And increment the exponent
|
|
}
|
|
}
|
|
|
|
if ( neg ) // If the whole answer is negative
|
|
x = -x; // Make the number negative
|
|
return x; // And send it back
|
|
}
|
|
|
|
|
|
/*
|
|
* "keypad_click" -
|
|
*/
|
|
|
|
static int keypad_click ( int key )
|
|
{
|
|
int c = keypads[key].c; // Index to the "KP_Font" array
|
|
char fBuff[20]; // Frequency string
|
|
|
|
if (( c >= KN_X && c <= KN_M )) // 'X', 'K' or 'M' key pressed?
|
|
{
|
|
int32_t scale = 1; // Default "scale"?
|
|
|
|
if ( c >= KN_X && c <= KN_M ) // Redundent test? Why?
|
|
{
|
|
int n = c - KN_X; // 'X' -> 0, 'K' _> 1, 'M' -> 2
|
|
|
|
while ( n-- > 0 ) // Multiplier will be 1K or 1M
|
|
scale *= 1000;
|
|
}
|
|
|
|
|
|
/*
|
|
* When we get here, the numeric input has completed. We convert the number to
|
|
* a "double" and multiply it by the "scale".
|
|
*/
|
|
|
|
if (kp_index ==0) // no entry - treat same as <-
|
|
return KP_CANCEL;
|
|
|
|
double value = my_atof ( kp_buf ) * ( double ) scale;
|
|
|
|
switch ( keypad_mode )
|
|
{
|
|
case KM_START: // Start frequency entered?
|
|
SetSweepStart (( int32_t ) value );
|
|
break;
|
|
|
|
case KM_STOP: // Stop frequency entered?
|
|
SetSweepStop (( int32_t ) value );
|
|
break;
|
|
|
|
case KM_CENTER: // Center frequency entered?
|
|
SetSweepCenter (( int32_t ) value, WIDE );
|
|
break;
|
|
|
|
case KM_SPAN: // Frequency span entered?
|
|
SetSweepSpan (( int32_t ) value );
|
|
break;
|
|
|
|
case KM_FOCUS: // Focus frequency entered?
|
|
SetSweepCenter ((int32_t ) value, NARROW );
|
|
break;
|
|
|
|
case KM_REFPOS: // Reference level
|
|
SetRefLevel (value );
|
|
break;
|
|
|
|
case KM_ATTENUATION: // Attenuator setting
|
|
if ( value > PE4302_MAX ) // Too high?
|
|
{
|
|
DisplayError ( ERR_WARN,
|
|
"Illegal attenuator setting!",
|
|
"Ignored!", NULL, NULL );
|
|
break;
|
|
}
|
|
|
|
SetAttenuation ( value );
|
|
break;
|
|
|
|
case KM_ACTUALPOWER: // Power level
|
|
RequestSetPowerLevel ( value );
|
|
break;
|
|
|
|
case KM_IFFREQ:
|
|
|
|
if ( !SetIFFrequency (( uint32_t ) value )) // Bad frequency?
|
|
{
|
|
strcpy ( fBuff, FormatFrequency (( uint32_t ) value ));
|
|
|
|
DisplayError ( ERR_WARN,
|
|
fBuff,
|
|
"Invalid IF Frequency!",
|
|
"IF Frequency set to:",
|
|
FormatFrequency ( setting.IF_Freq ));
|
|
}
|
|
break;
|
|
|
|
case KM_SGFREQ:
|
|
if ( (value > MAX_SIGLO_FREQ) || (value < MIN_SIGLO_FREQ) )
|
|
{
|
|
strcpy ( fBuff, FormatFrequency (( uint32_t ) value ));
|
|
|
|
DisplayError ( ERR_WARN,
|
|
fBuff,
|
|
"Invalid Frequency!",
|
|
NULL,
|
|
NULL );
|
|
}
|
|
else
|
|
sigGenSetting.Frequency = value;
|
|
break;
|
|
|
|
|
|
case KM_SGLEVEL:
|
|
if ( (value > sigGenSetting.Calibration) || (value < sigGenSetting.Calibration - ATTENUATOR_RANGE) )
|
|
{
|
|
|
|
DisplayError ( ERR_WARN,
|
|
"Invalid Level!",
|
|
NULL, NULL,
|
|
NULL );
|
|
}
|
|
else
|
|
sigGenSetting.Power = value;
|
|
break;
|
|
|
|
|
|
case KM_SGLEVCAL:
|
|
if ( (value > 20) || (value < -30) )
|
|
{
|
|
|
|
DisplayError ( ERR_WARN,
|
|
"Invalid Level!",
|
|
NULL, NULL,
|
|
NULL );
|
|
}
|
|
else
|
|
sigGenSetting.Calibration = value;
|
|
break;
|
|
|
|
|
|
case KM_IFSTART: // IF Start frequency entered?
|
|
SetIFsweepStart (( int32_t ) value );
|
|
break;
|
|
|
|
|
|
case KM_IFSTOP: // IF Stop frequency entered?
|
|
SetIFsweepStop (( int32_t ) value );
|
|
break;
|
|
|
|
case KM_IFSIG: // IF Signal frequency entered?
|
|
SetIFsweepSigFreq (( int32_t ) value );
|
|
break;
|
|
|
|
|
|
case KM_PREAMP:
|
|
if (( value < 5 ) || ( value > 49 )) // Range check
|
|
{
|
|
DisplayError ( ERR_WARN,
|
|
"Illegal preamp gain setting!",
|
|
"Ignored!", NULL, NULL );
|
|
break;
|
|
}
|
|
SetPreampGain ( value );
|
|
break;
|
|
|
|
case KM_TUNE:
|
|
if ( value > 255 ) // Illegal value?
|
|
{
|
|
DisplayError ( ERR_WARN,
|
|
"Illegal calibration factor!",
|
|
"Ignored!", NULL, NULL );
|
|
break; // Done!
|
|
}
|
|
|
|
if ( VFO == TX_4432 ) // Transmitter module selected?
|
|
{
|
|
xmit.Tune ( ( uint8_t ) value ); // Tune it
|
|
config.RX_capacitance = ( uint8_t ) value; // And save it
|
|
}
|
|
|
|
else if ( VFO == RX_4432 ) // Receiver module selected?
|
|
{
|
|
rcvr.Tune ( ( uint8_t ) value ); // Tune it
|
|
config.RX_capacitance = ( uint8_t ) value; // And save it
|
|
}
|
|
#ifdef SI_TG_IF_CS
|
|
else if ( VFO == TGIF_4432 ) // Tracking generator IF module selected?
|
|
{
|
|
tg_if.Tune ( ( uint8_t ) value ); // Tune it
|
|
config.tgIF_capacitance = ( uint8_t ) value; // And save it
|
|
}
|
|
#endif
|
|
#ifdef SI_TG_LO_CS
|
|
else if ( VFO == TGLO_4432 ) // Tracking generator LO module selected?
|
|
{
|
|
tg_lo.Tune ( ( uint8_t ) value ); // Tune it
|
|
config.tgLO_capacitance = ( uint8_t ) value; // And save it
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case KM_TGOFFSET:
|
|
if ( (value > MAX_TG_OFFSET) || (value < MIN_TG_OFFSET) )
|
|
{
|
|
strcpy ( fBuff, FormatSignedFrequency (( int32_t ) value ));
|
|
|
|
DisplayError ( ERR_WARN,
|
|
fBuff,
|
|
"Invalid Frequency!",
|
|
NULL,
|
|
NULL );
|
|
}
|
|
else
|
|
trackGenSetting.Offset = value;
|
|
break;
|
|
|
|
case KM_TGIF_DRIVE:
|
|
if ( (value > MAX_DRIVE) || (value < MIN_DRIVE) )
|
|
{
|
|
DisplayError ( ERR_WARN,
|
|
"Invalid drive level!",
|
|
"(0-7)",
|
|
NULL,
|
|
NULL );
|
|
}
|
|
else
|
|
trackGenSetting.IF_Drive = value;
|
|
break;
|
|
|
|
case KM_TGLO_DRIVE:
|
|
if ( (value > MAX_DRIVE) || (value < MIN_DRIVE) )
|
|
{
|
|
DisplayError ( ERR_WARN,
|
|
"Invalid drive level!",
|
|
"(0-7)",
|
|
NULL,
|
|
NULL );
|
|
}
|
|
else
|
|
trackGenSetting.LO_Drive = value;
|
|
break;
|
|
|
|
|
|
case KM_BANDSCOPESTART: // Bandscope Start frequency entered?
|
|
SetBandscopeStart (( int32_t ) value );
|
|
break;
|
|
|
|
|
|
case KM_BANDSCOPESPAN: // Bandscope span entered?
|
|
SetBandscopeSpan (( int32_t ) value );
|
|
break;
|
|
|
|
|
|
} // End of "switch"
|
|
|
|
return KP_DONE; // Indicate finished with the keypad
|
|
|
|
}
|
|
|
|
else if ( c <= 9 && kp_index < NUMINPUT_LEN )
|
|
kp_buf[kp_index++] = '0' + c;
|
|
|
|
else if ( c == KN_PERIOD && kp_index < NUMINPUT_LEN )
|
|
{
|
|
|
|
/*
|
|
* Check period in former input
|
|
*/
|
|
|
|
int j;
|
|
|
|
for ( j = 0; j < kp_index && kp_buf[j] != '.'; j++ ) {}
|
|
|
|
if ( kp_index == j )
|
|
kp_buf[kp_index++] = '.'; // Append period if there was no period
|
|
|
|
}
|
|
|
|
else if ( c == KN_MINUS )
|
|
{
|
|
if ( kp_index == 0 )
|
|
kp_buf[kp_index++] = '-';
|
|
}
|
|
|
|
else if ( c == KN_BS )
|
|
{
|
|
if ( kp_index == 0 )
|
|
return KP_CANCEL;
|
|
|
|
--kp_index;
|
|
}
|
|
|
|
kp_buf[kp_index] = '\0'; // NULL terminator
|
|
draw_numeric_input ( kp_buf );
|
|
return KP_CONTINUE; // Still more to process
|
|
}
|
|
|
|
|
|
/*
|
|
* "keypad_apply_touch" - Figures out which keypad pad was touched
|
|
*/
|
|
|
|
static int keypad_apply_touch ( void )
|
|
{
|
|
int touch_x, touch_y; // Touch coordinates
|
|
int i = 0;
|
|
|
|
touch_position ( &touch_x, &touch_y ); // Get touch coordinates
|
|
|
|
while ( keypads[i].x )
|
|
{
|
|
if (keypads[i].x-2 < touch_x && touch_x < keypads[i].x+44+2
|
|
&& keypads[i].y-2 < touch_y && touch_y < keypads[i].y+44+2)
|
|
{
|
|
|
|
selection = i; // Set focus
|
|
draw_keypad (); // Repaint with selected pad highlighted
|
|
touch_wait_release (); // Wait for pad released
|
|
selection = -1; // Erase focus
|
|
draw_keypad (); // And repaint again
|
|
return i; // Return selected pad index
|
|
}
|
|
|
|
i++; // Try the next one
|
|
} // End of "while" loop
|
|
|
|
if ( touch_y > 48 * 4 )
|
|
return -2; // Exit keypad mode
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
* "numeric_apply_touch" -
|
|
*/
|
|
|
|
static void numeric_apply_touch ( void )
|
|
{
|
|
int touch_x, touch_y; // Touch coordinates
|
|
touch_position ( &touch_x, &touch_y ); // Get coordinates
|
|
|
|
if ( touch_x < 64 ) // Out of touch area?
|
|
{ // Hard-coded numbers have to go!
|
|
ui_mode_normal ();
|
|
return;
|
|
}
|
|
|
|
if ( touch_x > 64 + 9 * 20 + 8 + 8 ) // Your guess is as good as mine!
|
|
{
|
|
ui_mode_keypad ( keypad_mode );
|
|
ui_process_keypad ();
|
|
return;
|
|
}
|
|
|
|
if ( touch_y > 240 - 40 )
|
|
{
|
|
int n = 9 - ( touch_x - 64 ) / 20;
|
|
uistat.digit = n;
|
|
uistat.digit_mode = TRUE;
|
|
}
|
|
|
|
else
|
|
{
|
|
int step, n;
|
|
|
|
if ( touch_y < 100 )
|
|
step = 1;
|
|
|
|
else
|
|
step = -1;
|
|
|
|
for (n = uistat.digit; n > 0; n-- )
|
|
step *= 10;
|
|
|
|
uistat.value += step;
|
|
}
|
|
|
|
draw_numeric_area ();
|
|
touch_wait_release ();
|
|
uistat.digit_mode = FALSE;
|
|
draw_numeric_area ();
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* "ui_process_keypad" -
|
|
*/
|
|
|
|
static void ui_process_keypad ( void )
|
|
{
|
|
int status;
|
|
|
|
kp_index = 0;
|
|
|
|
while ( TRUE ) // "TRUE = '-1" in this program
|
|
{
|
|
status = touch_check (); // Look for screen touched
|
|
|
|
if ( status == EVT_TOUCH_PRESSED ) // If it was touched
|
|
{
|
|
int key = keypad_apply_touch (); // Process it
|
|
|
|
if ( key >= 0 && keypad_click ( key ))
|
|
break; // Exit loop on done or cancel
|
|
|
|
else if ( key == -2 )
|
|
{
|
|
// xxx; // ???????
|
|
// return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//**HERE3
|
|
|
|
request_to_redraw_grid ();
|
|
ui_mode_normal ();
|
|
// draw_menu ();
|
|
// menu_move_back();
|
|
}
|
|
|
|
|
|
/*
|
|
* "UiProcessTouch" -
|
|
*/
|
|
|
|
void UiProcessTouch ( void )
|
|
{
|
|
int tstatus = touch_check(); // Look for screen touch
|
|
|
|
if ( tstatus == EVT_TOUCH_PRESSED || tstatus == EVT_TOUCH_DOWN )
|
|
{
|
|
// Serial.printf( "process Touch status = %i, UImode = %i \n", tstatus, ui_mode );
|
|
|
|
switch ( ui_mode )
|
|
{
|
|
case UI_NORMAL:
|
|
|
|
// Serial.println( "waiting for release" );
|
|
int touch_x, touch_y; // Touch coordinates
|
|
touch_position ( &touch_x, &touch_y ); // Get coordinates
|
|
Serial.printf("x:%i y:%i\n", touch_x, touch_y);
|
|
touch_wait_release ();
|
|
|
|
|
|
// test to see if the touch is in the marker area
|
|
if ( (touch_y < 10) && (touch_x < 160) )
|
|
{
|
|
marker[0].Toggle(); // marker 1
|
|
return;
|
|
}
|
|
else if ( (touch_y < 10) && (touch_x > 160) )
|
|
{
|
|
marker[2].Toggle(); // marker 3
|
|
return;
|
|
}
|
|
else if ( (touch_y < 20) && (touch_x < 160) )
|
|
{
|
|
marker[1].Toggle(); // marker 2
|
|
return;
|
|
}
|
|
else if ( (touch_y < 20) && (touch_x > 160) )
|
|
{
|
|
marker[3].Toggle(); // marker 4
|
|
return;
|
|
}
|
|
else if ( (touch_y < 40) && (touch_x > 30) )
|
|
StartMarkerMenu();
|
|
else if ( (touch_y > 210) && ( setting.Mode == SA_LOW_RANGE ) )
|
|
StartSweepMenu();
|
|
else if ( (touch_x < 30) && (touch_y < 60) && ( setting.Mode == SA_LOW_RANGE ) )
|
|
StartRBWMenu();
|
|
else if ( (touch_x < 30) && (touch_y > CHAR_HEIGHT * 20 ) && ( touch_y < CHAR_HEIGHT * 22 ) && ( setting.Mode == SA_LOW_RANGE ) )
|
|
{
|
|
SetSpur (!setting.Spur);
|
|
return;
|
|
}
|
|
else if ( (touch_x < 30) && ( setting.Mode == SA_LOW_RANGE ) )
|
|
StartDisplayMenu();
|
|
|
|
selection = -1; // Switch menu mode
|
|
bg = BLACK; // black background
|
|
ui_mode_menu ();
|
|
break;
|
|
|
|
case UI_MENU:
|
|
menu_apply_touch ();
|
|
break;
|
|
|
|
case UI_NUMERIC:
|
|
numeric_apply_touch ();
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* Function to enter menu at certain level and selection
|
|
* HERE
|
|
* static uint8_t menu_current_level = 0; // Current level (MAIN)
|
|
*
|
|
* static Menuitem *menu_stack[MENU_STACK_DEPTH] = // Initialize the stack
|
|
* { menu_top, // Main menu is on top
|
|
* NULL, // These get set as we
|
|
* NULL, // go along
|
|
* NULL
|
|
* };
|
|
*
|
|
* // helpers for setting menus from outside
|
|
* enum { MENU_TOP, MENU_SWEEP, MENU_DISPLAY, MENU_STORAGE, MENU_OUTPUT, MENU_SAVE, MENU_CONFIG }; // Root Menu
|
|
* enum { SWEEP_START, SWEEP_STOP, SWEEP_CENTRE, SWEEP_SPAN, FOCUS }; // Sweep menu - level 1
|
|
* enum { RBW, ATTEN, MARKERS }; // Sweep more menu - level 2
|
|
* enum { TRACES, PREAMP, REF_LEVEL, DB_DIV, SPUR, DEFAULT_SETTINGS }; // Display menu - level 1
|
|
*
|
|
*/
|
|
|
|
void StartSigGenMenu ( void )
|
|
{
|
|
tft.unloadFont();
|
|
selection = -1; // Switch menu mode
|
|
menu_current_level = 0;
|
|
menu_stack[0] = menu_sig_gen;
|
|
bg = SIG_BACKGROUND_COLOR;
|
|
tft.fillRect ( 320-60, 0, 60, 32*ELEMENTS(menu_sig_gen), bg );
|
|
ui_mode_menu ();
|
|
}
|
|
|
|
void StartSigGenFreq ( void )
|
|
{
|
|
tft.unloadFont();
|
|
selection = -1; // Switch menu mode
|
|
// menu_current_level = 0;
|
|
// menu_stack[0] = menu_sig_gen;
|
|
bg = SIG_BACKGROUND_COLOR;
|
|
tft.fillScreen ( bg );
|
|
menu_sig_freq_cb ( 0 );
|
|
}
|
|
|
|
|
|
|
|
static void StartMarkerMenu ( void )
|
|
{
|
|
selection = -1; // Switch menu mode
|
|
menu_current_level = 3;
|
|
menu_stack[1] = menu_sweep;
|
|
menu_stack[2] = menu_sweep2;
|
|
menu_stack[3] = menu_markers;
|
|
}
|
|
|
|
|
|
static void StartSweepMenu ( void )
|
|
{
|
|
selection = -1; // Switch menu mode
|
|
menu_current_level = 1;
|
|
menu_stack[1] = menu_sweep;
|
|
menu_stack[2] = NULL;
|
|
menu_stack[3] = NULL;
|
|
}
|
|
|
|
static void StartDisplayMenu ( void )
|
|
{
|
|
selection = -1; // Switch menu mode
|
|
menu_current_level = 1;
|
|
menu_stack[1] = menu_display;
|
|
menu_stack[2] = NULL;
|
|
menu_stack[3] = NULL;
|
|
}
|
|
|
|
static void StartRBWMenu ( void )
|
|
{
|
|
selection = -1; // Switch menu mode
|
|
menu_current_level = 3;
|
|
menu_stack[1] = menu_sweep;
|
|
menu_stack[2] = menu_sweep2;
|
|
menu_stack[3] = menu_rbw;
|
|
}
|
|
|
|
|
|
/*
|
|
* Resets the menu stack to root level for SA mode
|
|
*/
|
|
void ResetSAMenuStack (void)
|
|
{
|
|
tft.unloadFont();
|
|
selection = -1; // Switch menu mode
|
|
menu_current_level = 0;
|
|
menu_stack[0] = menu_top;
|
|
menu_stack[1] = NULL;
|
|
menu_stack[2] = NULL;
|
|
menu_stack[3] = NULL;
|
|
if (ui_mode != UI_NORMAL)
|
|
ui_mode_normal ();
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Resets the menu stack to root level for IF_SWEEP mode
|
|
*/
|
|
void ResetIFsweepMenuStack (void)
|
|
{
|
|
tft.unloadFont();
|
|
selection = -1; // Switch menu mode
|
|
menu_current_level = 0;
|
|
menu_stack[0] = menu_IFsweep_top;
|
|
menu_stack[1] = NULL;
|
|
menu_stack[2] = NULL;
|
|
menu_stack[3] = NULL;
|
|
if (ui_mode != UI_NORMAL)
|
|
ui_mode_normal ();
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Resets the menu stack to root level for Bandscope mode
|
|
*/
|
|
void ResetBandscopeMenuStack (void)
|
|
{
|
|
tft.unloadFont();
|
|
selection = -1; // Switch menu mode
|
|
menu_current_level = 0;
|
|
menu_stack[0] = menu_Bandscope_top;
|
|
menu_stack[1] = NULL;
|
|
menu_stack[2] = NULL;
|
|
menu_stack[3] = NULL;
|
|
if (ui_mode != UI_NORMAL)
|
|
ui_mode_normal ();
|
|
}
|
|
|
|
|
|
/*
|
|
* "ui_process" -
|
|
*/
|
|
|
|
void ui_process ( void )
|
|
{
|
|
switch ( operation_requested ) // Only one case???
|
|
{
|
|
case OP_TOUCH:
|
|
UiProcessTouch ();
|
|
break;
|
|
}
|
|
|
|
operation_requested = OP_NONE;
|
|
}
|