//=================================================================
// console.cs
//=================================================================
// Thetis is a C# implementation of a Software Defined Radio.
// Copyright (C) 2004-2009  FlexRadio Systems 
// Copyright (C) 2010-2020  Doug Wigley
// Credit is given to Sizenko Alexander of Style-7 (http://www.styleseven.com/) for the Digital-7 font.
//
// This program 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 2
// of the License, or (at your option) any later version.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
// You may contact us via email at: sales@flex-radio.com.
// Paper mail may be sent to: 
//    FlexRadio Systems
//    8900 Marybank Dr.
//    Austin, TX 78750
//    USA
//
//=================================================================
// Modifications to support the Behringer Midi controllers
// by Chris Codella, W2PA, May 2017.  Indicated by //-W2PA comment lines. 
// Modifications for using the new database import function.  W2PA, 29 May 2017
// Support QSK, possible with Protocol-2 firmware v1.7 (Orion-MkI and Orion-MkII), and later.  W2PA, 5 April 2019 
// Modfied heavily - Copyright (C) 2019-2024 Richard Samphire (MW0LGE)
//=================================================================

using Midi2Cat.Data; //-W2PA Necessary for Behringer MIDI changes

namespace Thetis
{
    using RawInput_dll;
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Diagnostics;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Drawing.Text;
    using System.Globalization;
    using System.IO;
    using System.IO.Ports;
    using System.Linq;
    using System.Net;
    using System.Net.Sockets;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Timers;
    using System.Windows.Forms;
    using System.Xml.Linq;
    using System.Collections.Concurrent;

    public partial class Console : Form
    {
        public const bool CHECK_DEV_VERSION = true; // this will check github for dev versions, set to false when performing a release

        public const int MAX_FPS = 360;

        #region Variable Declarations
        // ======================================================
        // Variable Declarations
        // ======================================================
        private frmAbout _frmAbout;

        static private List<PrivateFontCollection> _fontCollections;
        Font LEDLFont = null;
        Font LEDSFont = null;
        Font LEDMFont = null;

        public PSForm psform;
        private DigiMode rx1dm;
        private DigiMode rx2dm;

        public Radio radio;
        public SpecRX specRX;
        public Midi2CatCommands Midi2Cat;
        private System.Timers.Timer n1mm_delay;             // timer for setting delay on focus
        private Thread draw_display_thread;					// draws the main display 
        private Thread multimeter_thread;					// updates the rx1/tx meter data
        private Thread rx2_meter_thread;					// updates the rx2 meter data
        private Thread poll_ptt_thread;						// polls the PTT line on the parallel port
        private Thread poll_cw_thread;
        private Thread poll_pa_pwr_thread;					// polls the FWD and REV power if the PA is installed
        private Thread poll_tx_inhibit_thead;
        private Thread display_volts_amps_thead;            // calculate and display volts and amps for ANAN-8000DLE
        private Thread sql_update_thread;					// polls the RX signal strength
        private Thread rx2_sql_update_thread;				// polls the RX2 signal strength
        private Thread vox_update_thread;					// polls the mic input
        private Thread noise_gate_update_thread;			// polls the mic input during TX
        private Thread _overload_thread;
        public bool _pause_DisplayThread = true;             // MW0LGE_21d initally paused
        private bool calibration_running = false;
        private bool displaydidit = false;
        public Mutex calibration_mutex = new Mutex();

        private Setup m_frmSetupForm;
        private readonly Object m_objSetupFormLocker = new Object();

        private frmBandStack2 m_frmBandStack2;
        private frmFilterManager m_frmFilterManager;

        private CWX m_frmCWXForm;

        public XVTRForm XVTRForm;
        public EQForm EQForm;
        public FilterForm filterRX1Form;
        public FilterForm filterRX2Form;
        public DiversityForm diversityForm;
        // G8NJJ
        public SliderSettingsForm sliderForm;
        public ModeButtonsPopup modePopupForm;
        public FilterButtonsPopup filterPopupForm;
        public BandButtonsPopup bandPopupForm;
        public ModeDependentSettingsForm modeDependentSettingsForm;
        public VFOSettingsPopup VFOSettingsForm;
        public DisplaySettingsForm displaySettingsForm;

        public RAForm raForm;
        public Path_Illustrator path_Illustrator;

        public MemoryForm memoryForm;
        public MemoryList MemoryList { get; private set; }
        public WaveControl WaveForm;

        public SpotControl SpotForm;                       // ke9ns add DX spotter function
        public ScanControl ScanForm;                       // ke9ns add freq Scanner function

        public SwlControl SwlForm;                         // ke9ns add band swl form

        //====================================================================================

        private DXMemList dxmemList; // ke9ns add
        public DXMemList DXMemList // ke9ns add
        {
            get { return dxmemList; }
        }

        //=======================================================================================

        private int rx1_squelch_threshold_scroll = 0;//-160;
        private int rx2_squelch_threshold_scroll = 0;//-160;
        private int rx1_fm_squelch_threshold_scroll = 0;
        private int rx2_fm_squelch_threshold_scroll = 0;
        private int rx1_voice_squelch_threshold_scroll = 0;
        private int rx2_voice_squelch_threshold_scroll = 0;

        private SquelchState rx1_squelch_state = SquelchState.OFF;
        private SquelchState rx1_fm_squelch_state = SquelchState.OFF;
        private SquelchState rx2_squelch_state = SquelchState.OFF;
        private SquelchState rx2_fm_squelch_state = SquelchState.OFF;

        private bool _bands_VHF_selected = false;
        private bool _bands_HF_selected = true;
        private bool _bands_GEN_selected = false;
        private bool _iscollapsed = false;
        private bool _isexpanded = true;

        private RadioButtonTS[] vhf_text;

        private bool was_panadapter = false;				// used to restore panadater when switching to spectrum DSP mode
        private bool was_waterfall = false;					// used to restore waterfall when switching to spectrum DSP mode

        public float[] rx1_preamp_offset;					// offset values for each preamp mode in dB
        public float[] rx2_preamp_offset;					// offset values for each preamp mode in dB
        public float rx1_meter_cal_offset;					// multimeter calibration offset per volume setting in dB
        public float rx2_meter_cal_offset;					// multimeter calibration offset per volume setting in dB
        public float[] rx_meter_cal_offset_by_radio;
        public float[] rx_display_cal_offset_by_radio;

        private struct ztb_data
        {
            public double CentreFrequency;
            public int PanSliderPosition;
            public int ZoomSliderPosition;
            public bool Initalised;
        }

        private ztb_data[][] ztb_data_by_band;

        private int[] rx1_step_attenuator_by_band;
        private int[] rx2_step_attenuator_by_band;
        private int[] tx_step_attenuator_by_band;
        private bool[] diversity_rx1_ref_by_band;
        private bool[] diversity_rx2_ref_by_band;

        private bool meter_data_ready;						// used to synchronize the new DSP data with the multimeter
        private float new_meter_data;						// new data for the multimeter from the DSP
        private float current_meter_data;					// current data for the multimeter
        private int meter_peak_count;						// Counter for peak hold on multimeter
        private int meter_peak_value;						// Value for peak hold on multimeter
        private float[] meter_text_history;					// Array used to output the peak power over a period of time
        private int meter_text_history_index;				// index used with above variable to do peak power
        private float new_swrmeter_data;						// new data for the multimeter from the DSP
        private float current_swrmeter_data;					// current data for the multimeter

        private bool rx2_meter_data_ready;					// used to synchronize the new DSP data with the multimeter
        private float rx2_meter_new_data;					// new data for the multimeter from the DSP
        private float rx2_meter_current_data;				// current data for the multimeter
        private int rx2_meter_peak_count;					// Counter for peak hold on multimeter
        private int rx2_meter_peak_value;					// Value for peak hold on multimeter
        public int pa_fwd_power;							// forward power as read by the ADC on the PA
        public int pa_rev_power;							// reverse power as read by the ADC on the PA
        private bool tuning;								// true when the TUN button is active
        public float[][] rx1_level_table;					// table used to store RX1 Level cal settings
        public float[][] rx2_level_table;					// table used to store RX2 Level cal settings

        public double[] CTCSS_array =  {
            67.0 , 69.3 , 71.9 , 74.4 , 77.0 , 79.7 , 82.5 , 85.4 , 88.5 , 91.5 ,
            94.8 , 97.4 , 100.0, 103.5, 107.2, 110.9, 114.8, 118.8, 123.0, 127.3,
            131.8, 136.5, 141.3, 146.2, 151.4, 156.7, 159.8, 162.2, 165.5, 167.9,
            171.3, 173.8, 177.3, 179.9, 183.5, 186.2, 189.9, 192.8, 199.5, 203.5,
            206.5, 210.7, 218.1, 225.7, 229.1, 233.6, 241.8, 250.3, 254.1};

        public double[] FM_deviation_array = { 5000, 2500 };

        private bool calibrating;							// true if running a calibration routine
        private bool manual_mox;							// True if the MOX button was clicked on (not PTT)		

        private DSPMode vfob_dsp_mode;						// Saves control pointer for last mode used on VFO B 
        private Filter vfob_filter;							// Saves control pointer for last filter used on VFO B
        private int vfo_char_width;							// Used to calibrate mousewheel tuning
        private int vfo_char_space;							// Used to calibrate mousewheel tuning
        private int vfo_small_char_width;					// Used to calibrate mousewheel tuning
        private int vfo_small_char_space;					// Used to calibrate mousewheel tuning
        private int vfo_decimal_width;						// Used to calibrate mousewheel tuning
        private int vfo_decimal_space;						// Used to calibrate mousewheel tuning		
        private int vfo_sub_char_width;						// Used to calibrate mousewheel tuning
        private int vfo_sub_char_space;						// Used to calibrate mousewheel tuning
        private int vfo_sub_decimal_width;					// Used to calibrate mousewheel tuning
        private int vfo_sub_decimal_space;					// Used to calibrate mousewheel tuning	
        private int vfo_pixel_offset;						// Used to calibrate mousewheel tuning
        private int vfoa_hover_digit;						// Digit for hover display
        private int vfo_sub_pixel_offset;
        private int vfoa_sub_hover_digit;					// Digit for VFOA sub hover display
        private int vfob_hover_digit;						// Digit for hover display

        private DSPMode quick_save_mode;					// Quick Save Mode
        private Filter quick_save_filter;					// Quick Save Filter

        private string separator;							// contains the locations specific decimal separator

        private int last_filter_shift;
        private int last_var1_shift;
        private int last_var2_shift;

        private readonly HiPerfTimer break_in_timer;
        public double avg_vox_pwr = 0.0;

        public float alex_fwd = 0;
        public float alex_rev = 0;
        public float drivepwr = 0.0f;
        public float calfwdpower = 0.0f;
        public float alex_swr = 0.0f;
        private float average_drivepwr = 0.0f;
        private float average_revadc = 0.0f;
        private float average_fwdadc = 0.0f;
        private float average_drvadc = 0.0f;

        private static readonly MemoryStream msgrab = new MemoryStream(Properties.Resources.grab);
        private static readonly MemoryStream msgrabbing = new MemoryStream(Properties.Resources.grabbing);
        private static readonly MemoryStream mscross_outlined = new MemoryStream(Properties.Resources.cross_rl);

        readonly NumberFormatInfo nfi = NumberFormatInfo.InvariantInfo;  // so we are region independent in terms of ',' and '.' for floats
        private static Image m_imgTimer_off = (Image)Properties.Resources.ResourceManager.GetObject("timer");
        private static Image m_imgTimer_on = (Image)Properties.Resources.ResourceManager.GetObject("timer_on");

        public bool initializing = true;

        private int h_delta = 0;
        private int v_delta = 0;
        private int previous_delta = 0;

        private Size console_basis_size = new Size(100, 100);
        private Size picdisplay_basis_size = new Size(100, 100);
        private Point gr_filter_basis_location = new Point(100, 100);
        private Point gr_Multimeter_basis_location = new Point(100, 100);
        private Point gr_BandHF_basis_location = new Point(100, 100);
        private Point gr_BandGEN_basis_location = new Point(100, 100);
        private Point gr_BandVHF_basis_location = new Point(100, 100);
        private Point gr_Mode_basis_location = new Point(100, 100);
        private Point gr_RX2Mode_basis_location = new Point(100, 100);
        private Point gr_VFOB_basis_location = new Point(100, 100);
        private Point gr_VFOA_basis_location = new Point(100, 100);
        private Point gr_ModePhone_basis_location = new Point(100, 100);
        private Point gr_ModeCW_basis_location = new Point(100, 100);
        private Point gr_ModeDig_basis_location = new Point(100, 100);
        private Point gr_ModeFM_basis_location = new Point(100, 100);
        private Point gr_VFO_basis_location = new Point(100, 100);
        private Point gr_vfobetween_basis_location = new Point(100, 100);

        //MW0LGE_21k9rc6 new resize implementation
        private Point tb_display_zoom_basis = new Point(100, 100);
        private Point lbl_display_zoom_basis = new Point(100, 100);
        private Size tb_display_zoom_size_basis = new Size(100, 100);
        private Size lbl_display_zoom_size_basis = new Size(100, 100);
        private Point tb_displaypan_basis = new Point(100, 100);
        private Point lbl_displaypan_basis = new Point(100, 100);
        private Size tb_displaypan_size_basis = new Size(100, 100);
        private Size lbl_displaypan_size_basis = new Size(100, 100);

        private Size tb_display_pan_size_basis = new Size(100, 100);
        private Point btn_display_pan_center_basis = new Point(100, 100);
        //

        private Point txt_display_peak_freq_basis = new Point(100, 100);
        private Point txt_display_peak_power_basis = new Point(100, 100);
        private Point txt_display_peak_offset_basis = new Point(100, 100);

        private Size gr_display_size_basis = new Size(100, 100);
        private Point gr_display2_basis = new Point(100, 100);

        private Point gr_dsp_basis = new Point(100, 100);

        private Point gr_multirx_basis = new Point(100, 100);

        private Point gr_display_split_basis = new Point(100, 100);
        private Point gr_options_basis = new Point(100, 100);
        private Point gr_sound_controls_basis = new Point(100, 100);
        private Point chk_squelch_basis = new Point(100, 100);
        private Point ud_squelch_basis = new Point(100, 100);
        private Point pic_sql_basis = new Point(100, 100);
        private Point tb_sql_basis = new Point(100, 100);
        private Point gr_antenna_basis = new Point(100, 100);
        private Point chk_bci_basis = new Point(100, 100);
        private Point button1_basis = new Point(100, 100);

        private Point gr_rx2_meter_basis = new Point(100, 100);
        private Point gr_rx2_filter_basis = new Point(100, 100);
        private Point gr_rx2_display_basis = new Point(100, 100);
        private Point gr_rx2_dsp_basis = new Point(100, 100);

        private Point lbl_rx2_rf_basis = new Point(100, 100);
        private Point ud_rx2_rf_basis = new Point(100, 100);
        private Point tb_rx2_rf_basis = new Point(100, 100);
        private Point gr_rx2_rf_basis = new Point(100, 100);

        private Point chk_rx2_squelch_basis = new Point(100, 100);
        private Point ud_rx2_squelch_basis = new Point(100, 100);
        private Point tb_rx2_squelch_basis = new Point(100, 100);
        private Point pic_rx2_squelch_basis = new Point(100, 100);

        private Point gr_rx2_mixer_basis = new Point(100, 100);
        private Point gr_rx2_enable_basis = new Point(100, 100);
        private Point chk_rx2_enable_basis = new Point(100, 100);
        private Point combo_rx2_preamp_basis = new Point(100, 100);
        private Point lbl_rx2_band_basis = new Point(100, 100);
        private Point combo_rx2_band_basis = new Point(100, 100);

        private Size txt_multi_text_size_basis = new Size(100, 100); // original size of miltimeter text
        private Point gr_multi_meter_menus_basis = new Point(100, 100);  // original pos of multimeter menu group
        private Size gr_multi_meter_menus_size_basis = new Size(100, 100); // original size of multimeter menu

        private Size gr_multi_meter_size_basis = new Size(100, 100);
        private Point pic_multi_meter_digital_basis = new Point(100, 100);
        private Size pic_multi_meter_size_basis = new Size(100, 100);
        private Point pic_rx2meter_basis = new Point(100, 100);
        private Size pic_rx2meter_size_basis = new Size(100, 100);
        private Point lbl_multi_smeter_basis = new Point(100, 100);
        private Size lbl_multi_smeter_size_basis = new Size(100, 100);
        private Point lbl_rx2meter_basis = new Point(100, 100);
        private Size lbl_rx2meter_size_basis = new Size(100, 100);
        private Point txt_multi_text_basis = new Point(100, 100);
        private Point txt_rx2meter_basis = new Point(100, 100);
        private Size txt_rx2meter_size_basis = new Size(100, 100);
        private Point chk_power_basis = new Point(100, 100);
        private Point gr_power_basis = new Point(100, 100);
        private Size gr_options_size_basis = new Size(100, 100);
        private Point chk_mon_basis = new Point(100, 100);
        private Point chk_mut_basis = new Point(100, 100);
        private Point chk_rx2_mut_basis = new Point(100, 100);
        private Point chk_mox_basis = new Point(100, 100);
        private Point chk_tun_basis = new Point(100, 100);
        private Point chk_vox_basis = new Point(100, 100);
        private Point chk_ps2_basis = new Point(100, 100);
        private Point chk_dup_basis = new Point(100, 100);
        private Point chk_ctun_basis = new Point(100, 100);
        private Point chk_x2tr_basis = new Point(100, 100);

        private Point tb_af_basis = new Point(100, 100);
        private Point tb_rf_basis = new Point(100, 100);
        private Point tb_pwr_basis = new Point(100, 100);

        private Point tb_rx1af_basis = new Point(100, 100);
        private Point tb_rx2af_basis = new Point(100, 100);
        private Point gr_display_basis = new Point(100, 100);
        private Point pic_display_basis = new Point(100, 100);
        private Point info_bar_basis = new Point(100, 100);
        private Point pic_waterfall_basis = new Point(100, 100);
        private Point combo_display_mode_basis = new Point(100, 100);
        private Point combo_rx2_display_mode_basis = new Point(100, 100);
        private Point combo_agc_basis = new Point(100, 100);
        private Point combo_preamp_basis = new Point(100, 100);
        private Point combo_rx2agc_basis = new Point(100, 100);
        private Point combo_meter_rxmode_basis = new Point(100, 100);
        private Point combo_rx2meter_mode_basis = new Point(100, 100);
        private Point combo_meter_txmode_basis = new Point(100, 100);
        private Point ud_rx1_step_att_present_data_basis = new Point(100, 100);
        private Point ud_rx2_step_att_present_data_basis = new Point(100, 100);
        private Size gr_BandHF_basis_size = new Size(100, 100);
        private Size gr_BandGEN_basis_size = new Size(100, 100);
        private Size gr_BandVHF_basis_size = new Size(100, 100);
        private Size gr_Mode_basis_size = new Size(100, 100);
        private Size gr_RX2Mode_basis_size = new Size(100, 100);
        private Point rad_band160_basis = new Point(100, 100);
        private Point rad_band80_basis = new Point(100, 100);
        private Point rad_band60_basis = new Point(100, 100);
        private Point rad_band40_basis = new Point(100, 100);
        private Point rad_band30_basis = new Point(100, 100);
        private Point rad_band20_basis = new Point(100, 100);
        private Point rad_band17_basis = new Point(100, 100);
        private Point rad_band15_basis = new Point(100, 100);
        private Point rad_band12_basis = new Point(100, 100);
        private Point rad_band10_basis = new Point(100, 100);
        private Point rad_band6_basis = new Point(100, 100);
        private Point rad_band2_basis = new Point(100, 100);
        private Point rad_bandwwv_basis = new Point(100, 100);
        private Point rad_bandgen_basis = new Point(100, 100);
        private Point rad_bandVHF0_basis = new Point(100, 100);
        private Point rad_bandVHF1_basis = new Point(100, 100);
        private Point rad_bandVHF2_basis = new Point(100, 100);
        private Point rad_bandVHF3_basis = new Point(100, 100);
        private Point rad_bandVHF4_basis = new Point(100, 100);
        private Point rad_bandVHF5_basis = new Point(100, 100);
        private Point rad_bandVHF6_basis = new Point(100, 100);
        private Point rad_bandVHF7_basis = new Point(100, 100);
        private Point rad_bandVHF8_basis = new Point(100, 100);
        private Point rad_bandVHF9_basis = new Point(100, 100);
        private Point rad_bandVHF10_basis = new Point(100, 100);
        private Point rad_bandVHF11_basis = new Point(100, 100);
        private Point rad_bandVHF12_basis = new Point(100, 100);
        private Point rad_bandVHF13_basis = new Point(100, 100);
        private Point btn_bandVHF_basis = new Point(100, 100);
        private Point btn_bandHF_basis = new Point(100, 100);
        private Point rad_bandGEN0_basis = new Point(100, 100);
        private Point rad_bandGEN1_basis = new Point(100, 100);
        private Point rad_bandGEN2_basis = new Point(100, 100);
        private Point rad_bandGEN3_basis = new Point(100, 100);
        private Point rad_bandGEN4_basis = new Point(100, 100);
        private Point rad_bandGEN5_basis = new Point(100, 100);
        private Point rad_bandGEN6_basis = new Point(100, 100);
        private Point rad_bandGEN7_basis = new Point(100, 100);
        private Point rad_bandGEN8_basis = new Point(100, 100);
        private Point rad_bandGEN9_basis = new Point(100, 100);
        private Point rad_bandGEN10_basis = new Point(100, 100);
        private Point rad_bandGEN11_basis = new Point(100, 100);
        private Point rad_bandGEN12_basis = new Point(100, 100);
        private Point rad_bandGEN13_basis = new Point(100, 100);
        private Point btn_bandHF1_basis = new Point(100, 100);
        private Point rad_mode_lsb_basis = new Point(100, 100);
        private Point rad_mode_usb_basis = new Point(100, 100);
        private Point rad_mode_dsb_basis = new Point(100, 100);
        private Point rad_mode_cwl_basis = new Point(100, 100);
        private Point rad_mode_cwu_basis = new Point(100, 100);
        private Point rad_mode_fmn_basis = new Point(100, 100);
        private Point rad_mode_am_basis = new Point(100, 100);
        private Point rad_mode_sam_basis = new Point(100, 100);
        private Point rad_mode_spec_basis = new Point(100, 100);
        private Point rad_mode_digl_basis = new Point(100, 100);
        private Point rad_mode_digu_basis = new Point(100, 100);
        private Point rad_mode_drm_basis = new Point(100, 100);
        private Point rad_RX2mode_lsb_basis = new Point(100, 100);
        private Point rad_RX2mode_usb_basis = new Point(100, 100);
        private Point rad_RX2mode_dsb_basis = new Point(100, 100);
        private Point rad_RX2mode_cwl_basis = new Point(100, 100);
        private Point rad_RX2mode_cwu_basis = new Point(100, 100);
        private Point rad_RX2mode_fmn_basis = new Point(100, 100);
        private Point rad_RX2mode_am_basis = new Point(100, 100);
        private Point rad_RX2mode_sam_basis = new Point(100, 100);
        private Point rad_RX2mode_spec_basis = new Point(100, 100);
        private Point rad_RX2mode_digl_basis = new Point(100, 100);
        private Point rad_RX2mode_digu_basis = new Point(100, 100);
        private Point rad_RX2mode_drm_basis = new Point(100, 100);
        // G8NJJ
        private Point chk_RIT_basis = new Point(100, 100);//G8NJJ added
        private Point chk_XIT_basis = new Point(100, 100);//G8NJJ added
        private Point ud_RIT_basis = new Point(100, 100);//G8NJJ added
        private Point ud_XIT_basis = new Point(100, 100);//G8NJJ added
        private Point btn_RITReset_basis = new Point(100, 100);//G8NJJ added
        private Point btn_XITReset_basis = new Point(100, 100);//G8NJJ added
        private Point lbl_RX1_Mute_VFOA_basis = new Point(100, 100);
        private Point lbl_RX2_Mute_VFOB_basis = new Point(100, 100);
        private Point lbl_RX1_APF_VFOA_basis = new Point(100, 100);
        private Point lbl_RX2_APF_VFOB_basis = new Point(100, 100);
        //
        // G8NJJ: Titlebar strings and button/encoder/menu definitions for Andromeda
        //
        private string TitleBarMultifunction;                   // shows action assigned to multi encoder
        private string TitleBarEncoder;                         // shows most recent encoder value change

        //
        private static System.Timers.Timer _tmrDriveSliderUpdate;
        private static System.Timers.Timer _tmrTuneSliderUpdate;
        // MW0LGE
        private TCPIPcatServer m_tcpCATServer;
        private TCPIPtciServer m_tcpTCIServer;
        private bool m_bDisplayLoopRunning = false;
        private frmNotchPopup m_frmNotchPopup;
        private frmFinder _frmFinder;
        private frmSeqLog m_frmSeqLog;
        private Thread multimeter2_thread_rx1;
        private Thread multimeter2_thread_rx2;
        private bool _onlyOneSetupInstance; // used by setup to ensure only one instance created
        private bool _onlyOneCWXInstance;

        private bool _portAudioInitalising = false;
        private bool _portAudioIssue = false;
        private bool _exitConsoleInDispose = true;

        private bool m_bLogShutdown = false; // bool that is set via command line args to log the shutdown stages

        private frmReleaseNotes _frmReleaseNotes;

        private bool _restart;

        private bool _check_error_log = true;
        private long _error_log_initial_size = -1;

        public CWX CWXForm
        {
            // implemented so that the creation of the form happens in a single place
            get {
                if (m_frmCWXForm == null || m_frmCWXForm.IsDisposed)
                {
                    Debug.Assert(_onlyOneCWXInstance);
                    _onlyOneCWXInstance = false;
                    m_frmCWXForm = new CWX(this);
                    m_frmCWXForm.StopEverything(chkPower.Checked); //[2.10.3]MW0LGE
                }

                return m_frmCWXForm;
            }
            set { }
        }

        // used to delay repaint of all controls, until after they have been moved
        private const int WM_SETREDRAW = 11;
        [DllImport("user32.dll")]
        private static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);
        [DllImport("user32.dll")]
        static extern bool RedrawWindow(IntPtr hWnd, IntPtr lprcUpdate, IntPtr hrgnUpdate, uint flags);
        // ----
        // rawinput grabbing for mousewheel/keyboard
        private RawInput m_objRawinput;
        // ----
        private static System.Timers.Timer autoStartTimer;
        // ----
        #endregion

        #region Constructor and Destructor
        // ======================================================
        // Constructor and Destructor
        // ======================================================
        public Console(string[] args)
        {
            //#error version
            this.Opacity = 0f; // FadeIn below. Note: console form has 0% set in form designer

            Display.specready = false;
            bool bShowReleaseNotes = false;

            //MW0LGE
            // Problems with CultureInfo.
            // MemoryPanel and Spot system changes CultureInfo on their own threads, problem with this is that the culture change is now not limited just in that thread, if they
            // access stuff outside their thread, then the stuff they access has the same culture as the calling thread. VFOA frequency etc gets read incorrectly.
            // I have no idea how this actually managed to work before, unless it has been a recent change/fix to .NET 4.8.
            // I went through the stages of standardising the xml/db saving so to use CultureInfo.InvariantCulture, however the issues caused by Spot and Memory forms
            // just meant it was 100x easier just to force whole application to un-US.
            CultureInfo ci = new CultureInfo("en-US");

            CultureInfo.DefaultThreadCurrentCulture = ci;
            CultureInfo.DefaultThreadCurrentUICulture = ci;
            Thread.CurrentThread.CurrentCulture = ci;
            Thread.CurrentThread.CurrentUICulture = ci;
            //

            if (Common.HasArg(args, "-help"))
            {
                showHelpInfo();

                _exitConsoleInDispose = false;
                Environment.Exit(0);
                return;
            }
            m_bLogShutdown = Common.HasArg(args, "-logshutdown");

            // check versions of DLL/etc
            if (!checkVersions())
            {
                // version incorrect
                DialogResult dr = MessageBox.Show("An incorrect version of a required dll has been found.\n" +
                    "Please resolve the issue otherwise unexpected behaviour may occur.",
                    "Version error",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);

                _exitConsoleInDispose = false;
                Environment.Exit(1);
                return;
            }
            //

            string app_data_path = "";

            foreach (string s in args)
            {
                if (s.StartsWith("-datapath:"))
                {
                    string path = s.Trim().Substring(s.Trim().IndexOf(":") + 1);
                    if (path.EndsWith("\"")) path = path.Substring(0, path.Length - 1);
                    if (!path.EndsWith("\\")) path += "\\";
                    if (Directory.Exists(path))
                        app_data_path = path;
                    else
                    {
                        DialogResult dr = MessageBox.Show("-datapath: command line option found, but the folder specified was not found.\n" +
                            "Would you like to create this folder?  If not, the default folder will be used.\n\n" +
                            "(" + path + ")",
                            "Command Line Option: Create Folder?",
                            MessageBoxButtons.YesNo,
                            MessageBoxIcon.Question, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);

                        if (dr == DialogResult.Yes)
                        {
                            Directory.CreateDirectory(path);
                            app_data_path = path;
                        }
                    }
                }
            }

            if (string.IsNullOrEmpty(app_data_path))
            {
                if (Environment.Is64BitProcess)
                    app_data_path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
                    + "\\OpenHPSDR\\Thetis-x64\\";
                else
                    app_data_path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
                        + "\\OpenHPSDR\\Thetis\\";
            }

#if(DEBUG)
            app_data_path += "Debug\\";
#endif

            AppDataPath = app_data_path;
            //AppDataPath has been set at this point

            if (_check_error_log)
            {
                //store size of ErrorLog.txt at this point, and compare at shutdown. If different display a msg
                _error_log_initial_size = getErrorLogSize();
            }

            if (!Directory.Exists(AppDataPath))
                Directory.CreateDirectory(AppDataPath);

            Splash.ShowSplashScreen(Common.GetVerNum(true, true));							// Start splash screen with version number

            // PA init thread - from G7KLJ changes - done as early as possible
            Splash.SetStatus("Initializing PortAudio");			// Set progress point as early as possible
            _portAudioInitalising = true;
            _portAudioIssue = false;
            Thread portAudioThread = new Thread(new ThreadStart(initialisePortAudio))
            {
                Name = "Initalise PortAudioThread",
                Priority = ThreadPriority.Highest,
                IsBackground = true,
            };
            portAudioThread.SetApartmentState(ApartmentState.STA); // no ASIO deivces without this
            portAudioThread.Start();
            //

            // Instance name - done as early as possible as very slow
            _getInstanceNameComplete = false;
            Thread instanceNameThread = new Thread(new ThreadStart(getInstanceName))
            {
                Name = "getInstanceNameThread",
                Priority = ThreadPriority.Highest,
                IsBackground = true,
            };
            instanceNameThread.Start();
            //

            Splash.SetStatus("Initializing Components");        // Set progress point

            InitializeComponent();								// Windows Forms Generated Code
            InitialiseAndromedaMenus();

            //
            ucQuickRecallPad.console = this;
            Display.console = this;
            //

            GlobalMouseHandler gmh = new GlobalMouseHandler(); // capture mouse up event
            gmh.MouseUp += new MouseMovedEvent(gmh_MouseUp);
            gmh.MouseMove += new MouseEventHandler(gmh_MouseMove); //MW0LGE_21d3
            Application.AddMessageFilter(gmh);

            foreach (PanelTS control in this.Controls.OfType<PanelTS>())
            {
                foreach (TextBoxTS c in control.Controls.OfType<TextBoxTS>())
                {
                    c.GotFocus += new EventHandler(textbox_GotFocus);
                    c.LostFocus += new EventHandler(textbox_LostFocus);
                }
                foreach (ComboBoxTS c in control.Controls.OfType<ComboBoxTS>())
                {
                    c.DropDown += new EventHandler(combo_OpenDropDown);
                    c.DropDownClosed += new EventHandler(combo_CloseDropDown);
                }

            }

            foreach (GroupBoxTS control in this.Controls.OfType<GroupBoxTS>())
            {
                foreach (TextBoxTS c in control.Controls.OfType<TextBoxTS>())
                {
                    c.GotFocus += new EventHandler(textbox_GotFocus);
                    c.LostFocus += new EventHandler(textbox_LostFocus);
                }
                foreach (ComboBoxTS c in control.Controls.OfType<ComboBoxTS>())
                {
                    c.DropDown += new EventHandler(combo_OpenDropDown);
                    c.DropDownClosed += new EventHandler(combo_CloseDropDown);
                }
            }

            // MW0LGE_21k9
            ptbRF.MouseWheel += new MouseEventHandler(MouseWheelAGCRX1);
            ptbRX2RF.MouseWheel += new MouseEventHandler(MouseWheelAGCRX2);
            //

            // for resizing
            GrabConsoleSizeBasis();
            MinimumSize = this.Size;

            Splash.SetStatus("Initializing Database");			// Set progress point

            bool ok = DBMan.LoadDB(args, out string broken_folder);
            if (!ok)
            {
                if (string.IsNullOrEmpty(broken_folder))
                    MessageBox.Show($"There was an issue loading the database.", "Database Issue", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                else
                    MessageBox.Show($"There was an issue loading the database. The database has been moved to [{AppDataPath}DB\\broken\\{broken_folder}].", "Database Issue", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);

                _exitConsoleInDispose = false;
                Environment.Exit(1);
                return;
            }

            Splash.SetStatus("Initializing Hardware");			// Set progress point
            InitCTCSS();

            //TODO !!!!!!!!!!!!!!
            bool RX2Enabled = false;
            if (File.Exists(DB.FileName))
            {
                Dictionary<string, string> d = DB.GetVarsDictionary("State");

                if (d.ContainsKey("chkRX2"))
                    RX2Enabled = bool.Parse(d["chkRX2"]);
                else
                    RX2Enabled = false;
            }
            //END_TODO !!!!!!!!!!!!!!

            Splash.SetStatus("Initializing Radio");				// Set progress point
            radio = new Radio(AppDataPath);					    // Initialize the Radio processor   INIT_SLOW

            specRX = new SpecRX();
            Display.specready = true;

            break_in_timer = new HiPerfTimer();

            Midi2Cat = new Midi2CatCommands(this);

            // resize events are caused by this
            if (RX2Enabled)
            {
                this.MinimumSize = new Size(this.MinimumSize.Width, this.MinimumSize.Height - (panelRX2Filter.Height + 8));
            }
            else
            {
                console_basis_size.Height -= (panelRX2Filter.Height + 8);
                this.MinimumSize = new Size(this.MinimumSize.Width, this.MinimumSize.Height - (panelRX2Filter.Height + 8));
                this.Height -= (panelRX2Filter.Height + 8);
            }
            // end move down

            // initialise expandedSize so that we have something as a minimum to come back to from collapsed state //MW0LGE
            expandedSize = new Size(this.Width, this.Height);

            Init60mChannels();
            LoadLEDFont();

            Splash.SetStatus("Loading Settings");				// Set progress point

            TimeOutTimerManager.Initialise(this);

            InitConsole();                                      // Initialize all forms and main variables  INIT_SLOW

            //[2.10.3.4]MW0LGE shutdown log remove
            removeShutdownLog();

            addDelegates();

            CWFWKeyer = true;

            Common.DoubleBufferAll(this, true);

            // update titlebar
            this.Text = BasicTitleBar;//TitleBar.GetString(); //MW0LGE_21b

            initializing = false;

            //MW0LGE [2.9.0.8]
            //start multimer renderers
            Splash.SetStatus("Setting up meters");
            MeterManager.RunAllRendererDisplays();

            Splash.SetStatus("Setting up DSP");                       // Set progress point

            selectFilters();
            selectModes();

            SyncDSP(); //   INIT_SLOW

            specRX.GetSpecRX(0).Update = true;
            specRX.GetSpecRX(1).Update = true;
            specRX.GetSpecRX(cmaster.inid(1, 0)).Update = true;

            // still waiting PA
            if (_portAudioInitalising && portAudioThread != null && portAudioThread.IsAlive)
            {
                Splash.SetStatus("Waiting for PortAudio");
                bool bOk = portAudioThread.Join(5000);
                if (!bOk) MessageBox.Show("There was an issue initialising PortAudio", "PortAudio", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
            }
            if (_portAudioIssue)
                MessageBox.Show("There was an issue initialising PortAudio", "PortAudio", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);

            //            
            if (!IsSetupFormNull) SetupForm.SetupCMAsio(_portAudioIssue, Common.HasArg(args, "-cmasioconfig"));

            // still waiting cpu
            if (!_getInstanceNameComplete && instanceNameThread != null && instanceNameThread.IsAlive)
            {
                Splash.SetStatus("Waiting for CPU GetInstance");
                bool bOk = instanceNameThread.Join(5000);
                if (!bOk) MessageBox.Show("There was an issue initialising CPU ussage", "CPU Ussage. This will not be available on the status bar.", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
            }
            CpuUsage(); //[2.10.1.0] MW0LGE initial call to setup check marks in status bar as a minimum

            Splash.SetStatus("Processing Finder Info");
            // obtain finder info before splash closes
            //-- setup finder search data
            _frmFinder.ReadXmlFinderFile(AppDataPath); // note: needs to be before frm gather
            _frmFinder.GatherSearchData(this, toolTip1);
            _frmFinder.GatherSearchData(SetupForm, SetupForm.ToolTip);
            _frmFinder.GatherSearchData(EQForm, EQForm.ToolTip);
            _frmFinder.GatherSearchData(BandStack2Form, BandStack2Form.ToolTip);
            _frmFinder.GatherSearchData(psform, null);
            _frmFinder.WriteXmlFinderFile(AppDataPath); // note: this will only happen if not already there

            Splash.SetStatus("Finished");

            Splash.SplashForm.Owner = this;						// So that main form will show/focus when splash disappears //MW0LGE_21d done in show above
            Splash.CloseForm();									// End splash screen            

            Common.FadeIn(this);

            txtVFOAFreq_LostFocus(this, EventArgs.Empty);
            txtVFOBFreq_LostFocus(this, EventArgs.Empty);
            chkSquelch_CheckStateChanged(this, EventArgs.Empty);
            chkRX2Squelch_CheckStateChanged(this, EventArgs.Empty);

            UpdateWaterfallLevelValues();
            updateDisplayGridLevelValues();
            UpdateDiversityValues();

            rx1_meter_cal_offset = rx_meter_cal_offset_by_radio[(int)current_hpsdr_model];
            RX1DisplayCalOffset = rx_display_cal_offset_by_radio[(int)current_hpsdr_model];
            //added rx2 //MW0LGE_22b
            rx2_meter_cal_offset = rx_meter_cal_offset_by_radio[(int)current_hpsdr_model];
            RX2DisplayCalOffset = rx_display_cal_offset_by_radio[(int)current_hpsdr_model];

            //MW0LGE_21d fix isuse where controls that had been
            //clicked and now unselected show as different text colour when disabled
            initControlBackColours(this);

            //MW0LGE_21d instance the spot form
            if (SpotForm == null || SpotForm.IsDisposed) SpotForm = new SpotControl(this);

            //MW0LGE_21d BandStack2
            BandStackFilter bsf = BandStackManager.GetFilter(RX1Band, false);
            if (bsf != null)
            {
                bsf.GenerateFilteredList(true);
                bsf.SelectInitial(); // sets up the filter to obey the mode of operation, be it current, preset or last used

                //change VFOA to entry in the current band filter
                BandStackEntry bse = bsf.Current();
                if (bse != null)
                {
                    ClickTuneDisplay = bse.CTUNEnabled;
                    chkFWCATU.Checked = ClickTuneDisplay;
                    CentreFrequency = bse.CentreFrequency;
                    if (bse.ZoomSlider != ptbDisplayZoom.Value)
                    {
                        ptbDisplayZoom.Value = bse.ZoomSlider;
                        ptbDisplayZoom_Scroll(this, EventArgs.Empty);
                    }

                    if (RX1Filter != bse.Filter)
                        RX1Filter = bse.Filter;

                    if (RX1DSPMode != bse.Mode)
                        RX1DSPMode = bse.Mode;

                    VFOAFreq = bse.Frequency;
                }

                BandStack2Form.InitBandStackFilter(bsf);
                updateStackNumberDisplay(bsf);
            }

            if (!IsSetupFormNull)
            {
                // late start these, to give time for console to resize etc, because
                // external app may ask for rx2 before expand/collapse sizes have been calculated
                SetupForm.StartupTCIServer();
                SetupForm.StartupTCPIPcatServer();
            }

            //resize N1MM //MW0LGE_21k9c
            N1MM.Resize(1);
            if (RX2Enabled) N1MM.Resize(2);
            //

            // go for launch -- display forms, or user controls in thetis
            MeterManager.FinishSetupAndDisplay();

            //[2.10.3.5]MW0LGE setup all status icon items
            addStatusStripToolTipHandlers(); // improves #354
            UpdateStatusBarStatusIcons(StatusBarIconGroup.All);

            //
            handleShowOnStartWindowsForms();
            handleLaunchOnStartUp();
            //

            LegacyItemController.Init(this);
            LegacyItemController.Update();

            //display render thread
#if SNOWFALL
            Display.SetSantaGif(Properties.Resources.santa);
#endif
            m_bResizeDX2Display = true;
            if (draw_display_thread == null || !draw_display_thread.IsAlive)
            {
                draw_display_thread = new Thread(new ThreadStart(RunDisplay))
                {
                    Name = "Run Display Thread",
                    Priority = m_tpDisplayThreadPriority, //MW0LGE now defaulted with m_tpDisplayThreadPriority, and updated by setupform
                    IsBackground = false//true MW0LGE_21b rundisplay now stops nicely, ensuring dx gpu resources are released                    
                };
                draw_display_thread.SetApartmentState(ApartmentState.STA);
                draw_display_thread.Start();
            }
            _pause_DisplayThread = false;

            // test spectrum
            //if (_spectrum_thread == null || !_spectrum_thread.IsAlive)
            //{
            //    _spectrum_thread = new Thread(new ThreadStart(RunSpectrum))
            //    {
            //        Name = "Spectrum Thread",
            //        Priority = ThreadPriority.BelowNormal,
            //        IsBackground = true
            //    };
            //    _spectrum_thread.Start();
            //}
            //

            //release notes
            _frmReleaseNotes = new frmReleaseNotes();
            _frmReleaseNotes.InitPath(Application.StartupPath);
            if (bShowReleaseNotes) ShowReleaseNotes();
            //

            //autostart
            bool bAutoStart = Common.HasArg(args, "-autostart") || m_bAutoPowerOn;
            if (bAutoStart)
            {
                autoStartTimer = new System.Timers.Timer(2000);
                autoStartTimer.Elapsed += OnAutoStartTimerEvent;
                autoStartTimer.AutoReset = false;
                autoStartTimer.Start();
            }
        }
        private void initialisePortAudio()
        {
            System.Int32 result = PA19.PA_Initialize();
            _portAudioIssue = result != 0;

            _portAudioInitalising = false;
            Debug.Print("PA init done");
        }
        public bool IsSetupFormNull
        {
            // MW0LGE used because some aspects of thetis test for null.
            // Doing so on the singleton would instantiate it if null
            get { return m_frmSetupForm == null || m_frmSetupForm.IsDisposed; }
        }
        public Setup SetupForm
        {
            // MW0LGE implement SetupForm as singleton, with some level of thread safety (which is probably not needed)
            get {
                lock (m_objSetupFormLocker)
                {
                    if (IsSetupFormNull)
                    {
                        Debug.Assert(_onlyOneSetupInstance); // this should not happen, ever !  // G7KLJ's idea/implementation
                        _onlyOneSetupInstance = false;
                        Debug.Print("New setup form - should happen only once");
                        m_frmSetupForm = new Setup(this);
                        m_frmSetupForm.AfterConstructor(); // G7KLJ's idea/implementation
                    }
                    return m_frmSetupForm;
                }
            }
        }
        public void ShowReleaseNotes()
        {
            if (_frmReleaseNotes != null)
                _frmReleaseNotes.ShowReleaseNotes();
        }
        public frmBandStack2 BandStack2Form {
            get {
                if (m_frmBandStack2 == null || m_frmBandStack2.IsDisposed)
                {
                    m_frmBandStack2 = new frmBandStack2();
                    m_frmBandStack2.EntrySelectedHandlers += OnEntryClicked;
                    m_frmBandStack2.EntryAddHandlers += OnEntryAdd;
                    m_frmBandStack2.EntryDeleteHandlers += OnEntryDelete;
                    m_frmBandStack2.EntryUpdateHandlers += OnEntryUpdate;
                    m_frmBandStack2.IgnoreDupeHandlers += OnIgnoreDupes;
                    m_frmBandStack2.HideOnSelectHandlers += OnHideOnSelect;
                    m_frmBandStack2.ShowInSpectrumHandlers += OnShowInSpectrum;
                    m_frmBandStack2.InitForm(this); // perform init after all handlers attached
                }
                return m_frmBandStack2;
            }
        }
        public frmFilterManager FilterManagerForm
        {
            get
            {
                if (m_frmFilterManager == null || m_frmFilterManager.IsDisposed)
                {
                    m_frmFilterManager = new frmFilterManager();
                }
                return m_frmFilterManager;
            }
        }

        //MW0LGE
        //helper functions to suspend drawing/painting
        //of controls. This is to help limit flicker during
        //resize of console window
        private void SuspendDrawing(Control control)
        {
            if (initializing) return;
            control.SuspendLayout();
            SendMessage(control.Handle, WM_SETREDRAW, false, 0);
        }
        private void ResumeDrawing(Control control, bool refresh = true)
        {
            if (initializing) return;
            control.ResumeLayout();
            SendMessage(control.Handle, WM_SETREDRAW, true, 0);
            if (refresh) control.Refresh();
        }
        //--
        private void OnAutoStartTimerEvent(Object source, ElapsedEventArgs e)
        {
            // used by autostart command line flags, this event will fire after 2 seconds 
            chkPower.Checked = true;
        }

        private ThreadPriority m_tpDisplayThreadPriority = ThreadPriority.Normal;
        public ThreadPriority DisplayThreadPriority
        {
            get
            {
                return m_tpDisplayThreadPriority;
            }
            set
            {
                m_tpDisplayThreadPriority = value;
                if (draw_display_thread != null)
                {
                    draw_display_thread.Priority = m_tpDisplayThreadPriority;
                }

            }
        }

        void gmh_MouseUp()
        {
            if (!selectByClick)
                ToggleFocusMasterTimer();
        }
        protected override void Dispose(bool disposing)
        {
            shutdownLogStringToPath("Inside Console Dispose()");

            if (_exitConsoleInDispose) // ignore this if the incorrect dlls are found. We wont have used anything
                ExitConsole();

            if (_frmShutDownForm != null)
            {
                shutdownLogStringToPath("Before _frmShutDownForm.Close()");
                _frmShutDownForm.Close(); // last thing to get rid of
                _frmShutDownForm.Dispose();
                shutdownLogStringToPath("After _frmShutDownForm.Dispose()");
            }

            if (_check_error_log)
            {
                shutdownLogStringToPath("Before error log size check");
                //check error log size
                long new_szie = getErrorLogSize();
                if (new_szie != _error_log_initial_size)
                {
                    //log file has changed
                    MessageBox.Show("The ErrorLog.txt has been updated during this sesson.\n\n" +
                    "Please email it to MW0LGE at : [mw0lge@grange-lane.co.uk].\n\n" +
                    "It is located in this folder : [" + AppDataPath + "].",
                    "Error Log Change",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                }
                shutdownLogStringToPath("After error log size check");
            }

            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }

            base.Dispose(disposing);

            shutdownLogStringToPath("Leaving Console Dispose()");
        }

        #endregion

        #region Main
        static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
        {
            Debug.WriteLine(e.Exception.Message);
            Common.LogException(e.Exception);
        }
        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            Debug.WriteLine((e.ExceptionObject as Exception).Message);
            Common.LogException(e.ExceptionObject as Exception);
        }
        public bool Restart
        {
            get { return _restart; }
            set { _restart = value; }
        }
        // ======================================================
        // Main
        // ======================================================
        [STAThread]
        static void Main(string[] args)
        {
            Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

            string app_data_path = "";
            foreach (string s in args)
            {
                if (s.StartsWith("-datapath:"))
                {
                    string path = s.Trim().Substring(s.Trim().IndexOf(":") + 1);
                    if (path.EndsWith("\"")) path = path.Substring(0, path.Length - 1);
                    if (!path.EndsWith("\\")) path += "\\";
#if(DEBUG)
                    path += "Debug\\";
#endif
                    if (Directory.Exists(path))
                        app_data_path = path;
                    else
                    {
                        DialogResult dr = MessageBox.Show("-datapath: command line option found, but the folder specified was not found.\n" +
                            "Would you like to create this folder?  If not, the default folder will be used.\n\n" +
                            "(" + path + ")",
                            "Command Line Option: Create Folder?",
                            MessageBoxButtons.YesNo,
                            MessageBoxIcon.Question, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);

                        if (dr == DialogResult.Yes)
                        {
                            Directory.CreateDirectory(path);
                            app_data_path = path;
                        }
                    }
                }
            }

            if (string.IsNullOrEmpty(app_data_path))
            {
                app_data_path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
                    + "\\OpenHPSDR\\Thetis\\";
                if (Environment.Is64BitProcess)
                    app_data_path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
                    + "\\OpenHPSDR\\Thetis-x64\\";

#if(DEBUG)
                app_data_path += "Debug\\";
#endif
            }

            bool restart = false;
            try
            {
                {
                    // Need to create the directory in %appdata% before we run wisdom
                    if (!Directory.Exists(app_data_path))
                        Directory.CreateDirectory(app_data_path);
                }

                try
                {
                    if (!CheckForOpenProcesses())
                        return;
                }
                catch (Exception)
                {

                }

                Common.SetLogPath(app_data_path); // init the logger MW0LGE

                Win32.TimeBeginPeriod(1); // set timer resolution to 1ms => freq=1000Hz
                Application.EnableVisualStyles();
                Application.DoEvents();

                _theConsole = new Console(args);
                Application.Run(_theConsole);
                restart = _theConsole.Restart && !Common.ShiftKeyDown;
            }
            catch (Exception ex)
            {
                // could not find exception for column not found //MW0LGE_21k9rc6
                if (ex.Message.Contains("does not belong to table", StringComparison.InvariantCultureIgnoreCase))
                {
                    string msg = "The database is incorrectly configured for this version of Thetis.\n\n" +
                        "This is most likely because the database has not yet been updated.\n\n" +
                        "Try holding left CTRL as you start up Thetis,\n" +
                        "and keep it held until you see a message.";
                    MessageBox.Show(msg, "Database Error",
                        MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                }
                else
                {
                    string msg = ex.Message + "\n\n" + ex.StackTrace.ToString();
                    if (ex.InnerException != null) msg += "\n\n" + ex.InnerException.Message;
                    MessageBox.Show(msg, "Fatal Error",
                        MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                }
                Application.Exit();
            }

            if (restart)
            {
                Application.Restart();
                //System.Diagnostics.Process.Start(Application.ExecutablePath);
            }
        }

        #endregion

        #region Misc Routines
        // ======================================================
        // Misc Routines
        // ======================================================

        private bool spec_display = true;
        public bool SpecDisplay
        {
            get { return spec_display; }
            set
            {
                spec_display = value;
                cmaster.SetRunPanadapter(0, value);
            }
        }

        public string TitleBarMultifunctionString
        {
            set
            {
                TitleBarMultifunction = value;
                if (_iscollapsed)
                    this.Text = getTitleWithFWVersion() + TitleBarMultifunction + "    " + TitleBarEncoder;
                else
                    this.Text = getTitleWithFWVersion() + TitleBarMultifunction;
            }
        }

        public string TitleBarEncoderString
        {
            set
            {
                TitleBarEncoder = value;
                if (_iscollapsed)
                    this.Text = getTitleWithFWVersion() + TitleBarMultifunction + "    " + TitleBarEncoder;
            }
        }

        //MW0LGE_21g
        public string VersionWithoutFW
        {
            get
            {
                //[2.10.3.6]MW0LGE changed to use invoke if needed as CATTCPIPserver uses this from another thread
                if (this.InvokeRequired)
                {
                    return (string)this.Invoke(new Func<string>(() => TitleBar.GetString(false)));
                }
                else
                {
                    return TitleBar.GetString(false);
                }
            }
        }

        private string getTitleWithFWVersion()
        {
            string sFW = "";

            if (!IsSetupFormNull)
            {
                sFW = SetupForm.GetFirmwareCodeVersionString();
                if (!string.IsNullOrEmpty(sFW)) sFW = " (" + sFW + ")";
            }

            return TitleBar.GetString().Replace("<FW>", sFW);
        }
        //MW0LGE_21b
        private string m_sCustomTitle = "";
        public string BasicTitleBar {
            get {
                if (_iscollapsed) return this.Text = getTitleWithFWVersion() + TitleBarMultifunction;
                if (!m_sCustomTitle.Equals("")) return getTitleWithFWVersion() + "   --   " + m_sCustomTitle;
                return getTitleWithFWVersion();
            }
            set {

            }
        }
        public string CustomTitle {
            get {
                return m_sCustomTitle;
            }
            set {
                m_sCustomTitle = value;
                this.Text = BasicTitleBar;
            }
        }
        //

        private bool m_bCTUNputsZeroOnMouse = false; //MW0LGE_21k9d
        public bool CTUNputsZeroOnMouse
        {
            get { return m_bCTUNputsZeroOnMouse; }
            set { m_bCTUNputsZeroOnMouse = value; }
        }

        private void onNotchDelete()
        {
            if (SelectedNotch != null)
            {
                removeNotch(SelectedNotch);
            }
        }
        private void onBWChanged(double width)
        {
            if (SelectedNotch != null)
            {
                if (width != SelectedNotch.FWidth) changeNotchBW(SelectedNotch, width);
            }
        }
        private void onActiveChanged(bool active)
        {
            if (SelectedNotch != null)
            {
                if (active != SelectedNotch.Active) changeNotchActive(SelectedNotch, active);
            }
        }
        private void onClearButton()
        {
            toolStripStatusLabel_SeqWarning.Visible = false;
            NetworkIO.clearSnapshots();
        }

        private void InitConsole()
        {
            _frmAbout = new frmAbout(this, CHECK_DEV_VERSION);
            m_frmNotchPopup = new frmNotchPopup();
            m_frmSeqLog = new frmSeqLog();
            _frmFinder = new frmFinder();

            psform = new PSForm(this);

            Audio.console = this;

            chkDSPNB2.Enabled = true;

            vfoa_hover_digit = -1;
            vfob_hover_digit = -1;

            rx_meter_cal_offset_by_radio = new float[(int)HPSDRModel.LAST];
            rx_display_cal_offset_by_radio = new float[(int)HPSDRModel.LAST];
            ResetLevelCalibration(true); // MW0LGE_[2.9.0.6] removed code below, call reset so that code is in one place

            ztb_data_by_band = new ztb_data[2][];// 2 rx
            ztb_data_by_band[0] = new ztb_data[(int)Band.LAST];
            ztb_data_by_band[1] = new ztb_data[(int)Band.LAST];

            rx1_preamp_by_band = new PreampMode[(int)Band.LAST];
            rx2_preamp_by_band = new PreampMode[(int)Band.LAST];

            rx1_step_attenuator_by_band = new int[(int)Band.LAST];
            rx2_step_attenuator_by_band = new int[(int)Band.LAST];
            tx_step_attenuator_by_band = new int[(int)Band.LAST];

            for (int rx = 0; rx < 2; rx++)
            {
                for (int i = 0; i < (int)Band.LAST; i++)
                {
                    ztb_data_by_band[rx][i].Initalised = false;
                }
            }

            for (int i = 0; i < (int)Band.LAST; i++)
            {
                switch ((Band)i)
                {
                    default:
                        rx1_preamp_by_band[i] = PreampMode.HPSDR_ON;
                        rx2_preamp_by_band[i] = PreampMode.HPSDR_ON;
                        setRX1stepAttenuatorForBand((Band)i, 0);
                        setRX2stepAttenuatorForBand((Band)i, 0);
                        break;
                }

                setTXstepAttenuatorForBand((Band)i, 31);
            }

            power_by_band = new int[(int)Band.LAST];
            for (int i = 0; i < (int)Band.LAST; i++) power_by_band[i] = 50;

            limitPower_by_band = new int[(int)Band.LAST];
            for (int i = 0; i < (int)Band.LAST; i++) limitPower_by_band[i] = 100;

            tunePower_by_band = new int[(int)Band.LAST];
            for (int i = 0; i < (int)Band.LAST; i++) tunePower_by_band[i] = 50;

            limitTunePower_by_band = new int[(int)Band.LAST];
            for (int i = 0; i < (int)Band.LAST; i++) limitTunePower_by_band[i] = 100;

            fm_tx_offset_by_band_mhz = new double[(int)Band.LAST];
            for (int i = 0; i < (int)Band.LAST; i++) // setup default FM offsets
            {
                switch ((Band)i)
                {
                    case Band.B6M: fm_tx_offset_by_band_mhz[i] = 1; break; // 1MHz
                    case Band.B10M: fm_tx_offset_by_band_mhz[i] = 0.1; break; // 100kHz
                    default: fm_tx_offset_by_band_mhz[i] = 0.1; break; // 100kHz
                }
            }

            rx1_agcm_by_band = new AGCMode[(int)Band.LAST]; // AGC Mode by band
            rx2_agcm_by_band = new AGCMode[(int)Band.LAST];

            rx1_agct_by_band = new int[(int)Band.LAST];
            rx2_agct_by_band = new int[(int)Band.LAST];
            for (int i = 0; i < (int)Band.LAST; i++)
            {
                rx1_agcm_by_band[i] = AGCMode.MED;
                rx2_agcm_by_band[i] = AGCMode.MED;

                switch ((Band)i)
                {
                    case Band.B160M:
                    case Band.B80M:
                    case Band.B60M:
                        rx1_agct_by_band[i] = 75;
                        rx2_agct_by_band[i] = 75;
                        break;
                    case Band.B40M:
                    case Band.B30M:
                        rx1_agct_by_band[i] = 80;
                        rx2_agct_by_band[i] = 80;
                        break;
                    case Band.B20M:
                    case Band.B17M:
                        rx1_agct_by_band[i] = 85;
                        rx2_agct_by_band[i] = 85;
                        break;
                    case Band.B10M:
                        rx1_agct_by_band[i] = 95;
                        rx2_agct_by_band[i] = 95;
                        break;
                    case Band.B6M:
                        rx1_agct_by_band[i] = 110;
                        rx2_agct_by_band[i] = 110;
                        break;
                    default:
                        rx1_agct_by_band[i] = 90;
                        rx2_agct_by_band[i] = 90;
                        break;
                }
            }

            diversity_rx1_ref_by_band = new bool[(int)Band.LAST];
            diversity_rx2_ref_by_band = new bool[(int)Band.LAST];

            for (int i = 0; i < (int)Band.LAST; i++)
            {
                diversity_rx1_ref_by_band[i] = true;
                diversity_rx2_ref_by_band[i] = false;
            }

            vhf_text = new RadioButtonTS[15];
            vhf_text[0] = radBandVHF0;
            vhf_text[1] = radBandVHF1;
            vhf_text[2] = radBandVHF2;
            vhf_text[3] = radBandVHF3;
            vhf_text[4] = radBandVHF4;
            vhf_text[5] = radBandVHF5;
            vhf_text[6] = radBandVHF6;
            vhf_text[7] = radBandVHF7;
            vhf_text[8] = radBandVHF8;
            vhf_text[9] = radBandVHF9;
            vhf_text[10] = radBandVHF10;
            vhf_text[11] = radBandVHF11;
            vhf_text[12] = radBandVHF12;
            vhf_text[13] = radBandVHF13;

            radBandGEN0.Enabled = true; // ke9ns add turn on all the buttons for GEN SWL
            radBandGEN1.Enabled = true;
            radBandGEN2.Enabled = true;
            radBandGEN3.Enabled = true;
            radBandGEN4.Enabled = true;
            radBandGEN5.Enabled = true;
            radBandGEN6.Enabled = true;
            radBandGEN7.Enabled = true;
            radBandGEN8.Enabled = true;
            radBandGEN9.Enabled = true;
            radBandGEN10.Enabled = true;
            radBandGEN11.Enabled = true;
            radBandGEN12.Enabled = true;
            radBandGEN13.Enabled = true;

            rx1_level_table = new float[(int)Band.LAST][]; // 3 settings per band (display_offset, preamp, multimeter offset)
            for (int i = 0; i < (int)Band.LAST; i++)
            {
                rx1_level_table[i] = new float[3];
                rx1_level_table[i][0] = -37.5f;	// setup defaults;
                rx1_level_table[i][1] = 20.0f;
                rx1_level_table[i][2] = -11.5f;
            }

            rx2_level_table = new float[(int)Band.LAST][]; // 3 settings per band (display_offset, preamp, multimeter offset)
            for (int i = 0; i < (int)Band.LAST; i++)
            {
                rx2_level_table[i] = new float[3];
                rx2_level_table[i][0] = -37.5f;	// setup defaults;
                rx2_level_table[i][1] = -20.0f;
                rx2_level_table[i][2] = -11.5f;
            }

            setupModifyXVTRantennaArray();

            tune_power = 0;
            calibrating = false;

            // get culture specific decimal separator
            separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;

            tune_step_list = new List<TuneStep>
            {
                new TuneStep(1, "1Hz"),//0
                new TuneStep(2, "2Hz"),//1
                new TuneStep(10, "10Hz"),//2
                new TuneStep(25, "25Hz"),//3
                new TuneStep(50, "50Hz"),//4
                new TuneStep(100, "100Hz"),//5
                new TuneStep(250, "250Hz"),//6
                new TuneStep(500, "500Hz"),//7
                new TuneStep(1000, "1kHz"),//8
                new TuneStep(2000, "2kHz"),//9
                new TuneStep(2500, "2.5kHz"),//10
                new TuneStep(5000, "5kHz"),//11
                new TuneStep(6250, "6.25kHz"),//12
                new TuneStep(9000, "9kHz"),//13
                new TuneStep(10000, "10kHz"),//14
                new TuneStep(12500, "12.5kHz"),//15
                new TuneStep(15000, "15kHz"),//16
                new TuneStep(20000, "20kHz"),//17
                new TuneStep(25000, "25kHz"),//18
                new TuneStep(30000, "30kHz"),//19
                new TuneStep(50000, "50kHz"),//20
                new TuneStep(100000, "100kHz"),//21
                new TuneStep(250000, "250kHz"),//22
                new TuneStep(500000, "500kHz"),//23
                new TuneStep(1000000, "1MHz"),//24
                new TuneStep(10000000, "10MHz")//25

            };  // initialize wheel tuning list array

            tune_step_index = 2;

            m_nTuneStepsByMode = new int[(int)DSPMode.LAST]; //MW0LGE_21j
            for (int i = 0; i < (int)DSPMode.LAST; i++)
                m_nTuneStepsByMode[i] = tune_step_index;

            meter_text_history = new float[multimeter_text_peak_samples];

            current_meter_data = -200.0f;
            new_meter_data = -200.0f;

            //MW0LGE_22b fixes start state issue for RX2 meter
            rx2_meter_current_data = -200.0f;
            rx2_meter_new_data = -200.0f;

            rx1_preamp_offset = new float[(int)PreampMode.LAST];
            rx1_preamp_offset[(int)PreampMode.HPSDR_OFF] = 20.0f; //atten inline
            rx1_preamp_offset[(int)PreampMode.HPSDR_ON] = 0.0f; //no atten
            rx1_preamp_offset[(int)PreampMode.HPSDR_MINUS10] = 10.0f;
            rx1_preamp_offset[(int)PreampMode.HPSDR_MINUS20] = 20.0f;
            rx1_preamp_offset[(int)PreampMode.HPSDR_MINUS30] = 30.0f;
            rx1_preamp_offset[(int)PreampMode.HPSDR_MINUS40] = 40.0f;
            rx1_preamp_offset[(int)PreampMode.HPSDR_MINUS50] = 50.0f;
            rx1_preamp_offset[(int)PreampMode.SA_MINUS10] = 10.0f;
            rx1_preamp_offset[(int)PreampMode.SA_MINUS20] = 20.0f; //MW0LGE_21d step atten
            rx1_preamp_offset[(int)PreampMode.SA_MINUS30] = 30.0f;

            rx2_preamp_offset = new float[(int)PreampMode.LAST];
            rx2_preamp_offset[(int)PreampMode.HPSDR_OFF] = 20.0f;
            rx2_preamp_offset[(int)PreampMode.HPSDR_ON] = 0.0f;
            rx2_preamp_offset[(int)PreampMode.HPSDR_MINUS10] = 10.0f;
            rx2_preamp_offset[(int)PreampMode.HPSDR_MINUS20] = 20.0f;  //MW0LGE_21d step atten
            rx2_preamp_offset[(int)PreampMode.HPSDR_MINUS30] = 30.0f;
            rx2_preamp_offset[(int)PreampMode.SA_MINUS10] = 10.0f;  //MW0LGE_21d SA stuff
            rx2_preamp_offset[(int)PreampMode.SA_MINUS20] = 20.0f;
            rx2_preamp_offset[(int)PreampMode.SA_MINUS30] = 30.0f;

            this.ActiveControl = chkPower;		// Power has focus initially

            //MW0LGE_21d Display.Target = picDisplay;
            InitDisplayModes();					// Initialize Display Modes
            InitAGCModes();						// Initialize AGC Modes
            InitMultiMeterModes();              // Initialize MultiMeter Modes

            // MW0LGE_[2.9.0.7] setup the multi meter
            _RX1MeterValues = new Dictionary<Reading, float>();
            _RX2MeterValues = new Dictionary<Reading, float>();

            for (int n = 0; n < (int)Reading.LAST; n++)
            {
                _RX1MeterValues.Add((Reading)n, -200f);
                _RX2MeterValues.Add((Reading)n, -200f);
            }

            MeterManager.Init(this);
            //

            //[2.10.3.1]MW0LGE make sure it is created on this thread, as the following serial
            //devices could cause it to be created on another thread
            m_frmCWXForm = null;
            _onlyOneCWXInstance = true;
            CWX tmp = CWXForm;
            //--

            Siolisten = new SIOListenerII(this);
            Sio2listen = new SIO2ListenerII(this);
            Sio3listen = new SIO3ListenerII(this);
            Sio4listen = new SIO4ListenerII(this);
            AndromedaSiolisten = new SIO5ListenerII(this);
            AriesSiolisten = new SIO6ListenerII(this);
            GanymedeSiolisten = new SIO7ListenerII(this);

            EQForm = new EQForm(this);

            InitFilterPresets();					// Initialize filter values

            SwlForm = new SwlControl(this);         // ke9ns add communicate with swl list controls

            // ***** THIS IS WHERE SETUP FORM IS CREATED
            _onlyOneSetupInstance = true; // make sure that we limit to one instance
            SetupForm.StartPosition = FormStartPosition.Manual; // *********** IMPORTANT   first use of singleton will create Setup form       INIT_SLOW            

            BuildTXProfileCombos(); // MW0LGE_21k9rc4b build them, so that GetState can apply the combobox text

            Common.RestoreForm(EQForm, "EQForm", false);

            XVTRForm = new XVTRForm(this);
            WaveForm = new WaveControl(this) { StartPosition = FormStartPosition.Manual };	// create Wave form

            MemoryList = MemoryList.Restore();
            MemoryList.CheckVersion();
            dxmemList = DXMemList.Restore1(); // ke9ns add for dx spotter
            dxmemList.CheckVersion1(); // ke9ns add

            InitMemoryFrontPanel();
            vfob_dsp_mode = DSPMode.LSB;
            vfob_filter = Filter.F3;
            comboDisplayMode.Text = "Panafall";
            comboRX2DisplayMode.Text = "Panadapter";
            comboMeterRXMode.SelectedIndex = 0;
            comboRX2MeterMode.SelectedIndex = 0;
            comboTuneMode.SelectedIndex = 0;
            quick_save_filter = Filter.F3;
            quick_save_mode = DSPMode.LSB;
            ptbPWR.Value = 100;
            btnDisplayPanCenter_Click(this, EventArgs.Empty);

            comboFMCTCSS.Text = "100.0";

            GetState(); // recall saved state

            UpdateTXProfile(SetupForm.TXProfile); // now update the combos

            Splash.SetStatus("Finalizing settings");

            //MW0LGE_21d BandStack2
            BandStackManager.Extended = Extended;
            BandStackManager.Region = CurrentRegion;

            initializing = false;
            SetupForm.ForceTXProfileUpdate();   // loads previously saved profile
            initializing = true;

            // MW0LGE certain things in setup need objects created in this instance, so we will
            // delay them during init of setup, and now do them here
            SetupForm.PerformDelayedInitalistion();

            chkFullDuplex.Checked = false;
            if (rx1_dsp_mode == DSPMode.FIRST || rx1_dsp_mode == DSPMode.LAST)
                radModeLSB.Checked = true;
            if (rx2_dsp_mode == DSPMode.FIRST || rx2_dsp_mode == DSPMode.LAST)
                radRX2ModeLSB.Checked = true;
            if (rx1_filter == Filter.FIRST || rx1_filter == Filter.LAST ||
               (rx1_filter == Filter.NONE && rx1_dsp_mode != DSPMode.DRM && rx1_dsp_mode != DSPMode.SPEC))
                radFilter3.Checked = true;
            if (rx2_filter == Filter.FIRST || rx2_filter == Filter.LAST ||
               (rx2_filter == Filter.NONE && rx2_dsp_mode != DSPMode.DRM && rx2_dsp_mode != DSPMode.SPEC))
                radRX2Filter3.Checked = true;

            chkVFOATX_CheckedChanged(this, EventArgs.Empty);
            chkVFOBTX_CheckedChanged(this, EventArgs.Empty);

            PAPresent = pa_present;
            SampleRateTX = sample_rate_tx;

            if (comboAGC.SelectedIndex < 0)
                RX1AGCMode = AGCMode.MED;
            if (comboRX2AGC.SelectedIndex < 0)
                comboRX2AGC.Text = "Med";

            ptbPWR_Scroll(this, EventArgs.Empty);
            ptbTune_Scroll(this, EventArgs.Empty); //MW0LGE_22b
            ptbAF_Scroll(this, EventArgs.Empty);
            ptbSquelch_Scroll(this, EventArgs.Empty);
            ptbMic_Scroll(this, EventArgs.Empty);
            ptbCPDR_Scroll(this, EventArgs.Empty);
            ptbVOX_Scroll(this, EventArgs.Empty);
            ptbNoiseGate_Scroll(this, EventArgs.Empty);
            ptbCWSpeed_Scroll(this, EventArgs.Empty);
            ptbCWAPFBandwidth_Scroll(this, EventArgs.Empty);
            ptbCWAPFFreq_Scroll(this, EventArgs.Empty);
            ptbCWAPFGain_Scroll(this, EventArgs.Empty);
            ptbPanMainRX_Scroll(this, EventArgs.Empty);
            ptbPanSubRX_Scroll(this, EventArgs.Empty);
            ptbRX2RF_Scroll(this, EventArgs.Empty);
            ptbRX2Squelch_Scroll(this, EventArgs.Empty);

            initializing = false;
            RX1PreampMode = rx1_preamp_by_band[(int)rx1_band];
            RX1AttenuatorData = getRX1stepAttenuatorForBand(rx1_band);
            RX2PreampMode = rx2_preamp_by_band[(int)rx2_band];
            RX2AttenuatorData = getRX2stepAttenuatorForBand(rx2_band);
            initializing = true;

            ptbDisplayZoom_Scroll(this, EventArgs.Empty);
            ptbRX0Gain_Scroll(this, EventArgs.Empty);
            ptbRX1Gain_Scroll(this, EventArgs.Empty);
            ptbPanMainRX_Scroll(this, EventArgs.Empty);
            ptbPanSubRX_Scroll(this, EventArgs.Empty);
            ptbRX2Pan_Scroll(this, EventArgs.Empty);
            ptbRX2Gain_Scroll(this, EventArgs.Empty);
            ptbRF_Scroll(this, EventArgs.Empty);
            ptbVACRXGain_Scroll(this, EventArgs.Empty);
            ptbVACTXGain_Scroll(this, EventArgs.Empty);

            setupZTBButton(); //MW0LGE_21k9

            //MW0LGE_21k7 mute buttons
            chkMUT_CheckedChanged(this, EventArgs.Empty);
            chkRX2Mute_CheckedChanged(this, EventArgs.Empty);
            //

            chkTNF_CheckedChanged(this, EventArgs.Empty);
            radRX1Show_CheckedChanged(this, EventArgs.Empty);
            radRX2Show_CheckedChanged(this, EventArgs.Empty);
            chkRX2SR_CheckedChanged(this, EventArgs.Empty);

            chkDisplayAVG_CheckedChanged(this, EventArgs.Empty);

            CalcDisplayFreq();
            CalcRX2DisplayFreq();

            tune_step_index--;					// Setup wheel tuning
            ChangeTuneStepUp();

            UpdateRX1DisplayOffsets();
            UpdateRX2DisplayOffsets();
            SetupForm.initCATandPTTprops();   // wjt added -- get console props setup for cat and ptt 

            if (comboMeterTXMode.Items.Count > 0 && comboMeterTXMode.SelectedIndex < 0)
                comboMeterTXMode.SelectedIndex = 0;

            chkMOX.Enabled = false;
            chkTUN.Enabled = false; // MW0LGE_21a
            chk2TONE.Enabled = false; // MW0LGE_21a

            if (!collapsedDisplay)
            {
                //wd5y
                BtnBartoolStripMenuItem.Visible = false;
                TopControlstoolStripMenuItem.Visible = false;
                RXTXGainToolStripMenuItem.Visible = false;
                //wd5y
                modeToolStripMenuItem.Visible = false;
                bandToolStripMenuItem.Visible = false;
                rX2ToolStripMenuItem.Visible = false;
            }

            //MW0LGE duped from above Display.Target = picDisplay;
            update_rx2_display = true;

            if (startdiversity)
                eSCToolStripMenuItem_Click(this, EventArgs.Empty);

            // uncomment for multiple displays
            //cmaster.Getrxa(4).pDisplay.StartDisplay(4);
            //cmaster.Getrxa(5).pDisplay.StartDisplay(5);
            //cmaster.Getrxa(6).pDisplay.StartDisplay(6);

            SetupForm.RestoreNotchesFromDatabase();

            // Prepare for QSK in InitConsole
            qsk_sidetone_volume = SetupForm.TXAF;
            non_qsk_agc = RX1AGCMode;
            non_qsk_agc_hang_thresh = SetupForm.AGCRX1HangThreshold;//SetupForm.AGCHangThreshold; //MW0LGE_21k8
            non_qsk_ATTOnTX = m_bAttontx;
            non_qsk_ATTOnTXVal = SetupForm.ATTOnTX;
            non_qsk_breakin_delay = break_in_delay;
            RX1_band_change = RX1Band;

            setupTuneDriveSlider(); //MW0LGE_22b

            //setup info bar
            SetupInfoBar();
            //

            DumpCap.Initalise(this);
            if (DumpCap.ClearFolderOnRestart) DumpCap.ClearDumpFolder();
            m_frmSeqLog.SetWireSharkPath(DumpCap.WireSharkPath);
            //--

            initialiseRawInput(); // MW0LGE

            return;
        }
        #region InfoBar
        //infobar
        private bool _bInfoBarShowSEQErrors = true;
        public bool InfoBarShowSeqErrors
        {
            get { return _bInfoBarShowSEQErrors; }
            set { _bInfoBarShowSEQErrors = value; }
        }
        public void SetupInfoBarButton(ucInfoBar.ActionTypes action, bool bEnabled)
        {
            infoBar.UpdateButtonState(action, bEnabled);
        }
        private void SetupInfoBar()
        {
            infoBar.LateInit(this);

            if (psform != null)
                infoBar.PSAEnabled = psform.AutoCalEnabled;

            if (!IsSetupFormNull)
            {
                infoBar.UpdateButtonState(ucInfoBar.ActionTypes.Blobs, SetupForm.PeakBlobsEnabled, false);
                infoBar.UpdateButtonState(ucInfoBar.ActionTypes.ActivePeaks, SetupForm.ActivePeakHoldsEnabled, false);
                infoBar.UpdateButtonState(ucInfoBar.ActionTypes.CFC, SetupForm.CFCEnabled, false);
                infoBar.UpdateButtonState(ucInfoBar.ActionTypes.CursorInfo, SetupForm.ShowDisplayMHzCursorInfo, false);
                infoBar.UpdateButtonState(ucInfoBar.ActionTypes.Leveler, SetupForm.TXLevelerOn, false);
                infoBar.UpdateButtonState(ucInfoBar.ActionTypes.CFCeq, SetupForm.CFCPEQEnabled, false);
                infoBar.UpdateButtonState(ucInfoBar.ActionTypes.ShowSpots, SetupForm.ShowTCISpots /*| other spots*/, false);
                infoBar.UpdateButtonState(ucInfoBar.ActionTypes.DisplayFill, SetupForm.DisplayPanFill, true); // <- last one needs to be true
            }

            // tooltips
            infoBar.SetToolTipLeft(1, 1, "RBW - Resolution Bandwidth");
            infoBar.SetToolTipLeft(1, 2, "PB - Passband Bandwidth");

            infoBar.SetToolTipRight(1, 1, "NPSD - Noise Floor Power Spectral Density");
            infoBar.SetToolTipRight(1, 2, "PBNP - Estimated Passband Noise Power");
            infoBar.SetToolTipRight(1, 3, "PBSNR - Estimated Passband SNR");
        }
        public void InfoBarFeedbackLevel(int level, bool bFeedbackLevelOk, bool bCorrectionsBeingApplied, bool bCalibrationAttemptsChanged, Color feedbackColour)
        {
            if (infoBar.InvokeRequired)
                infoBar.Invoke(new Action(() => infoBar.PSInfo(level, bFeedbackLevelOk, bCorrectionsBeingApplied, bCalibrationAttemptsChanged, feedbackColour)));
            else
                infoBar.PSInfo(level, bFeedbackLevelOk, bCorrectionsBeingApplied, bCalibrationAttemptsChanged, feedbackColour);
        }

        public ucUnderOverFlowWarningViewer VAC1UnderOver
        {
            get { return ucVAC1UnderOver; }
        }
        public ucUnderOverFlowWarningViewer VAC2UnderOver
        {
            get { return ucVAC2UnderOver; }
        }
        //endinfobar
        #endregion

        // TCPIPCat
        private int m_nTCPIPCatPort = 13013;
        public int TCPIPCatPort
        {
            get { return m_nTCPIPCatPort; }
            set { m_nTCPIPCatPort = value; }
        }
        private string m_sTCPIPCatAddress = "127.0.0.1";
        public string TCPIPCatIP
        {
            get { return m_sTCPIPCatAddress; }
            set { m_sTCPIPCatAddress = value; }
        }
        public void ShowTCPIPCatLog()
        {
            if (m_tcpCATServer != null) m_tcpCATServer.ShowLog();
        }
        private void OnTCPIIPcatClientConnect()
        {
            if (m_tcpCATServer == null) return;
            if (!IsSetupFormNull)
                SetupForm.TCPIPcatClientsConnectedChange = m_tcpCATServer.ClientsConnected;
        }
        private void OnTCPIIPcatClientDisconnect()
        {
            if (m_tcpCATServer == null) return;
            if (!IsSetupFormNull)
                SetupForm.TCPIPcatClientsConnectedChange = m_tcpCATServer.ClientsConnected;
        }
        private void OnTCPIIPcatClientError(SocketException se)
        {
            Debug.Print("TCPIP CAT Client Error : " + se.Message);
        }
        private void OnTCPIIPcatServerError(SocketException se)
        {
            Debug.Print("TCPIP CAT Server Error : " + se.Message);
        }
        private bool _bTCPIPcatDelegatesAdded = false;
        private void addTCPIPcatDelegates()
        {
            if (_bTCPIPcatDelegatesAdded) return;
            m_tcpCATServer.ClientConnectedHandlers += OnTCPIIPcatClientConnect;
            m_tcpCATServer.ClientDisconnectedHandlers += OnTCPIIPcatClientDisconnect;
            m_tcpCATServer.ClientErrorHandlers += OnTCPIIPcatClientError;
            m_tcpCATServer.ServerErrorHandlers += OnTCPIIPcatServerError;
            _bTCPIPcatDelegatesAdded = true;
        }
        private void removeTCPIPcatDelegates()
        {
            if (_bTCPIPcatDelegatesAdded)
            {
                m_tcpCATServer.ClientConnectedHandlers -= OnTCPIIPcatClientConnect;
                m_tcpCATServer.ClientDisconnectedHandlers -= OnTCPIIPcatClientDisconnect;
                m_tcpCATServer.ClientErrorHandlers -= OnTCPIIPcatClientError;
                m_tcpCATServer.ServerErrorHandlers -= OnTCPIIPcatServerError;
                _bTCPIPcatDelegatesAdded = false;
            }
        }

        private bool m_bTCPIPcatWelcomeMessage = false;
        public bool TCPIPcatWelcomeMessage
        {
            get { return m_bTCPIPcatWelcomeMessage; }
            set
            {
                m_bTCPIPcatWelcomeMessage = value;
                if (m_tcpCATServer != null)
                    m_tcpCATServer.SendWelcome = m_bTCPIPcatWelcomeMessage;
            }
        }
        public void SetupTCPIPCat(bool bOn)
        {
            if (bOn)
            {
                //
                bool bOK = IPAddress.TryParse(m_sTCPIPCatAddress, out IPAddress address);
                if (bOK)
                {
                    if (m_objTCPIPCatParser == null) m_objTCPIPCatParser = new CATParser(this);
                    if (m_tcpCATServer != null) m_tcpCATServer.StopServer();

                    Debug.Print("Starting TCPIP CAT on " + m_sTCPIPCatAddress + ":" + m_nTCPIPCatPort.ToString());
                    m_tcpCATServer = new TCPIPcatServer(address, m_nTCPIPCatPort);

                    addTCPIPcatDelegates();

                    m_tcpCATServer.StartServer(this, m_bTCPIPcatWelcomeMessage);

                    if (!m_tcpCATServer.IsServerRunning)
                    {
                        if (!IsSetupFormNull) SetupForm.DisableTCPIPCatServerDueToError();
                        removeTCPIPcatDelegates();
                        MessageBox.Show("Unable to start the server." + Environment.NewLine + Environment.NewLine + "[ " + m_tcpCATServer.LastError + " ]", "TCPIP CAT Server",
                            MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                    }
                    else
                    {
                        NetworkIO.SetCATPort(m_nTCPIPCatPort);
                    }
                }
                //
            }
            else
            {
                if (m_tcpCATServer != null)
                {
                    m_tcpCATServer.CloseLog();
                    m_tcpCATServer.StopServer();
                    removeTCPIPcatDelegates();
                }
            }
            UpdateStatusBarStatusIcons(StatusBarIconGroup.TCPIPCat);
        }

        //TCI
        private bool _tci_ptt = false;
        public bool TCIPTT
        {
            get { return _tci_ptt; }
            set
            {
                _tci_ptt = value && !disable_ptt; // only use when we allow ptt control
                                                  // Prevents the issue when ptt control is off,
                                                  // a tcippt request comes in and then sits there
                                                  // until sometime later ptt control is turned on
            }
        }
        private int m_nTCIPort = 50001;
        public int TCIport
        {
            get { return m_nTCIPort; }
            set { m_nTCIPort = value; }
        }
        private string m_sTCIAddress = "127.0.0.1";
        public string TCIip
        {
            get { return m_sTCIAddress; }
            set { m_sTCIAddress = value; }
        }
        private bool _bTCIDelegatesAdded = false;
        private void addTCIDelegates()
        {
            if (_bTCIDelegatesAdded) return;
            m_tcpTCIServer.ClientConnectedHandlers += OnTCIClientConnect;
            m_tcpTCIServer.ClientDisconnectedHandlers += OnTCIClientDisconnect;
            m_tcpTCIServer.ClientErrorHandlers += OnTCIClientError;
            m_tcpTCIServer.ServerErrorHandlers += OnTCIServerError;
            _bTCIDelegatesAdded = true;
        }
        private void removeTCIDelegates()
        {
            if (_bTCIDelegatesAdded)
            {
                m_tcpTCIServer.ClientConnectedHandlers -= OnTCIClientConnect;
                m_tcpTCIServer.ClientDisconnectedHandlers -= OnTCIClientDisconnect;
                m_tcpTCIServer.ClientErrorHandlers -= OnTCIClientError;
                m_tcpTCIServer.ServerErrorHandlers -= OnTCIServerError;
                _bTCIDelegatesAdded = false;
            }
        }
        private void OnTCIClientConnect()
        {
            if (m_tcpTCIServer == null) return;
            if (!IsSetupFormNull)
                SetupForm.TCIClientsConnectedChange = m_tcpTCIServer.ClientsConnected;
        }
        private void OnTCIClientDisconnect()
        {
            if (m_tcpTCIServer == null) return;
            if (!IsSetupFormNull)
                SetupForm.TCIClientsConnectedChange = m_tcpTCIServer.ClientsConnected;
        }
        private void OnTCIClientError(SocketException se)
        {
            Debug.Print("TCI Client Error : " + se.Message);
        }
        private void OnTCIServerError(SocketException se)
        {
            Debug.Print("TCI Server Error : " + se.Message);
        }

        private bool m_bTCICWbecomesCWUabove10mhz = false;
        public bool TCICWbecomesCWUabove10mhz
        {
            get { return m_bTCICWbecomesCWUabove10mhz; }
            set
            {
                m_bTCICWbecomesCWUabove10mhz = value;
                if (m_tcpTCIServer != null) m_tcpTCIServer.CWbecomesCWUabove10mhz = m_bTCICWbecomesCWUabove10mhz;
            }
        }
        private bool m_bTCICWLUbecomesCW = false;
        public bool TCICWLUbecomesCW
        {
            get { return m_bTCICWLUbecomesCW; }
            set
            {
                m_bTCICWLUbecomesCW = value;
                if (m_tcpTCIServer != null) m_tcpTCIServer.CWLUbecomesCW = m_bTCICWLUbecomesCW;
            }
        }
        private bool m_bEmulateSunSDR2Pro = false;
        public bool EmulateSunSDR2Pro
        {
            get { return m_bEmulateSunSDR2Pro; }
            set
            {
                m_bEmulateSunSDR2Pro = value;
                if (m_tcpTCIServer != null) m_tcpTCIServer.EmulateSunSDR2Pro = m_bEmulateSunSDR2Pro;
            }
        }
        private bool m_bEmulateExpertSDR3Protocol = false;
        public bool EmulateExpertSDR3Protocol
        {
            get { return m_bEmulateExpertSDR3Protocol; }
            set
            {
                m_bEmulateExpertSDR3Protocol = value;
                if (m_tcpTCIServer != null) m_tcpTCIServer.EmulateExpertSDR3Protocol = m_bEmulateExpertSDR3Protocol;
            }
        }
        private bool m_bTCIuseRX1vfoaForRX2vfoa = false;
        public bool TCIuseRX1vfoaForRX2vfoa
        {
            get { return m_bTCIuseRX1vfoaForRX2vfoa; }
            set
            {
                m_bTCIuseRX1vfoaForRX2vfoa = value;
                if (m_tcpTCIServer != null) m_tcpTCIServer.UseRX1VFOaForRX2VFOa = m_bTCIuseRX1vfoaForRX2vfoa;
            }
        }
        private bool m_bTCIcopyRX2VFObToVFOa = false;
        public bool TCIcopyRX2VFObToVFOa
        {
            get { return m_bTCIcopyRX2VFObToVFOa; }
            set
            {
                m_bTCIcopyRX2VFObToVFOa = value;
                if (m_tcpTCIServer != null) m_tcpTCIServer.CopyRX2VFObToVFOa = m_bTCIcopyRX2VFObToVFOa;
            }
        }
        private bool m_bTCIsendInitialStateOnConnect = true;
        public bool TCIsendInitialStateOnConnect
        {
            get { return m_bTCIsendInitialStateOnConnect; }
            set
            {
                m_bTCIsendInitialStateOnConnect = value;
                if (m_tcpTCIServer != null) m_tcpTCIServer.SendInitialFrequencyStateOnConnect = m_bTCIsendInitialStateOnConnect;
            }
        }
        public void ShowTCILog()
        {
            if (m_tcpTCIServer != null) m_tcpTCIServer.ShowLog();
        }
        public void SetupTCI(bool bOn, int rateLimit)
        {
            if (bOn)
            {
                //
                bool bOK = IPAddress.TryParse(m_sTCIAddress, out IPAddress address);
                if (bOK)
                {
                    if (m_tcpTCIServer != null) m_tcpTCIServer.StopServer();

                    Debug.Print("Starting TCI on " + m_sTCIAddress + ":" + m_nTCIPort.ToString());
                    m_tcpTCIServer = new TCPIPtciServer(address, m_nTCIPort);

                    addTCIDelegates();

                    m_tcpTCIServer.StartServer(this, rateLimit, m_bTCIcopyRX2VFObToVFOa, m_bTCIuseRX1vfoaForRX2vfoa, m_bTCIsendInitialStateOnConnect, m_bTCICWLUbecomesCW, m_bEmulateSunSDR2Pro, m_bEmulateExpertSDR3Protocol);

                    if (!m_tcpTCIServer.IsServerRunning)
                    {
                        if (!IsSetupFormNull) SetupForm.DisableTCIServerDueToError();
                        removeTCIDelegates();
                        MessageBox.Show("Unable to start the server." + Environment.NewLine + Environment.NewLine + "[ " + m_tcpTCIServer.LastError + " ]", "TCI Server",
                            MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                    }
                }
                //
            }
            else
            {
                if (m_tcpTCIServer != null)
                {
                    m_tcpTCIServer.CloseLog();
                    m_tcpTCIServer.StopServer();
                    removeTCIDelegates();
                }
            }
            UpdateStatusBarStatusIcons(StatusBarIconGroup.TCI);
        }
        //

        private void selectFilters()
        {
            //rx1
            for (int i = 1; i < 11; i++)
            {
                string s = "radFilter" + i.ToString();
                if (panelFilter.Controls.ContainsKey(s))
                {
                    RadioButtonTS b = panelFilter.Controls[s] as RadioButtonTS;
                    if (b == null) break;
                    if (b.Checked) radFilter_CheckedChanged(b, EventArgs.Empty);
                }
            }
            for (int i = 1; i < 3; i++)
            {
                string s = "radFilterVar" + i.ToString();
                if (panelFilter.Controls.ContainsKey(s))
                {
                    RadioButtonTS b = panelFilter.Controls[s] as RadioButtonTS;
                    if (b == null) break;
                    if (b.Checked) radFilter_CheckedChanged(b, EventArgs.Empty);
                }
            }
            //rx2
            for (int i = 1; i < 8; i++)
            {
                string s = "radRX2Filter" + i.ToString();
                if (panelRX2Filter.Controls.ContainsKey(s))
                {
                    RadioButtonTS b = panelRX2Filter.Controls[s] as RadioButtonTS;
                    if (b == null) break;
                    if (b.Checked) radFilter_CheckedChanged(b, EventArgs.Empty);
                }
            }
            for (int i = 1; i < 3; i++)
            {
                string s = "radRX2FilterVar" + i.ToString();
                if (panelRX2Filter.Controls.ContainsKey(s))
                {
                    RadioButtonTS b = panelRX2Filter.Controls[s] as RadioButtonTS;
                    if (b == null) break;
                    if (b.Checked) radFilter_CheckedChanged(b, EventArgs.Empty);
                }
            }
        }

        private void selectModes()
        {
            string[] sModes = { "LSB", "USB", "DSB", "CWL", "CWU", "FM", "AM", "SAM", "SPEC", "DIGL", "DIGU", "DRM" };
            // rx1
            for (int i = 0; i < sModes.Length; i++)
            {
                string s = "radMode" + sModes[i];
                if (panelMode.Controls.ContainsKey(s))
                {
                    RadioButtonTS b = panelMode.Controls[s] as RadioButtonTS;
                    if (b == null) break;
                    if (b.Checked) radModeButton_CheckedChanged(b, EventArgs.Empty);
                }
            }
            // rx2
            for (int i = 0; i < sModes.Length; i++)
            {
                string s = "radRX2Mode" + sModes[i];
                if (panelRX2Mode.Controls.ContainsKey(s))
                {
                    RadioButtonTS b = panelRX2Mode.Controls[s] as RadioButtonTS;
                    if (b == null) break;
                    if (b.Checked) radRX2ModeButton_CheckedChanged(b, EventArgs.Empty);
                }
            }
        }
        public void Init60mChannels()
        {
            channels_60m = new List<Channel>();
            switch (CurrentRegion)
            {
                case FRSRegion.UK:
                    channels_60m.Add(new Channel(5.26125, 5500));
                    channels_60m.Add(new Channel(5.2800, 8000));
                    channels_60m.Add(new Channel(5.29025, 3500));
                    channels_60m.Add(new Channel(5.3025, 9000));
                    channels_60m.Add(new Channel(5.3180, 10000));
                    channels_60m.Add(new Channel(5.3355, 5000));
                    channels_60m.Add(new Channel(5.3560, 4000));
                    channels_60m.Add(new Channel(5.36825, 12500));
                    channels_60m.Add(new Channel(5.3800, 4000));
                    channels_60m.Add(new Channel(5.39825, 6500));
                    channels_60m.Add(new Channel(5.4050, 3000));
                    break;
                case FRSRegion.US:
                    channels_60m.Add(new Channel(5.3320, 2800));
                    channels_60m.Add(new Channel(5.3480, 2800));
                    channels_60m.Add(new Channel(5.3585, 2800));
                    channels_60m.Add(new Channel(5.3730, 2800));
                    channels_60m.Add(new Channel(5.4050, 2800));
                    break;
                default:
                    channels_60m.Add(new Channel(5.3320, 2800));
                    channels_60m.Add(new Channel(5.3480, 2800));
                    channels_60m.Add(new Channel(5.3585, 2800));
                    channels_60m.Add(new Channel(5.3730, 2800));
                    channels_60m.Add(new Channel(5.4050, 2800));
                    break;
            }
        }

        private void SyncDSP()
        {
            for (int i = 0; i < 2; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    RadioDSPRX dsp_rx = radio.GetDSPRX(i, j);
                    dsp_rx.Update = true;
                    dsp_rx.Force = true;
                    dsp_rx.BufferSize = dsp_rx.BufferSize;
                    dsp_rx.Force = false;
                }
            }

            for (int i = 0; i < 1; i++)
            {
                RadioDSPTX dsp_tx = radio.GetDSPTX(i);
                dsp_tx.Update = true;
                dsp_tx.Force = true;
                dsp_tx.BufferSize = dsp_tx.BufferSize;
                dsp_tx.Force = false;
            }

            SetupForm.UpdateTXDisplayFFT();

            for (int i = 0; i < 2; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    RadioDSPRX dsp_rx = radio.GetDSPRX(i, j);
                    dsp_rx.Update = false;
                    dsp_rx.Force = true;
                    dsp_rx.Update = true;
                    dsp_rx.Force = false;
                }
            }

            for (int i = 0; i < 1; i++)
            {
                RadioDSPTX dsp_tx = radio.GetDSPTX(i);
                dsp_tx.Update = false;
                dsp_tx.Force = true;
                dsp_tx.Update = true;
                dsp_tx.Force = false;
            }
        }

        public bool Force16bitIQ = false;

        public void ExitConsole()
        {
            shutdownLogStringToPath("Inside ExitConsole()");

            shutdownLogStringToPath("Before Midi2Cat.CloseMidi2Cat()");
            if (Midi2Cat != null) Midi2Cat.CloseMidi2Cat();

            shutdownLogStringToPath("Before N1MM.Stop()");
            N1MM.Stop();

            shutdownLogStringToPath("Before m_frmCWXForm.Close()");
            if (m_frmCWXForm != null)
                m_frmCWXForm.Close();

            shutdownLogStringToPath("Before n1mm_udp_client.Close()");
            if (n1mm_udp_client != null)
                n1mm_udp_client.Close();

            shutdownLogStringToPath("Before SetupForm.Dispose()");
            if (!IsSetupFormNull)		// make sure Setup form is deallocated
                SetupForm.Dispose();

            shutdownLogStringToPath("Before PA19.PA_Terminate()");
            PA19.PA_Terminate();		// terminate audio interface

            shutdownLogStringToPath("Before DB.Exit()");
            DB.Exit();					// close and save database

            shutdownLogStringToPath("Before DBMan.Shutdown()");
            DBMan.Shutdown();

            shutdownLogStringToPath("Before NetworkIO.DestroyRNet()");
            NetworkIO.DestroyRNet();

            shutdownLogStringToPath("Before radio.Shutdown()");
            if (radio != null)
                radio.Shutdown();

            shutdownLogStringToPath("Before Win32.TimeEndPeriod(1)");
            Win32.TimeEndPeriod(1); // return to previous timing precision
            Thread.Sleep(100);

            shutdownLogStringToPath("Leaving ExitConsole()");
        }

        public void SaveState()
        {
            // Automatically saves all control settings to the database in the tab
            // pages on this form of the following types: CheckBox, ComboBox,
            // NumericUpDown, RadioButton, TextBox, and TrackBar (slider)

            if (DB.Merged) return; // prevent saving as we want to ignore everything

            string s;

            if (current_breakin_mode == BreakIn.QSK) QSKEnabled = false; // Just to save the non-qsk settings, but leaving the button alone
            chkPower.Checked = false;		// turn off the power first

            //-------------------------------------------------------------------
            // ke9ns add  create database to store my stuff in

            string file_name2 = AppDataPath + "ke9ns8.dat"; // save data for my mods

            FileStream stream2 = new FileStream(file_name2, FileMode.Create); // open BMP  file
            BinaryWriter writer2 = new BinaryWriter(stream2);

            writer2.Write(Display.GrayScale);                    // color or grayscale watetfall
            writer2.Write(Display.GridOff);                      // save panadapter grid on/off

            writer2.Write(SpotControl.nameB);               // name for dx spotter
            writer2.Write(SpotControl.callB);               // call sign for dx spotter
            writer2.Write(SpotControl.nodeB);               // node  for dx spotter
            writer2.Write(SpotControl.portB);               // port for dx spotter

            writer2.Write(callsign);                             // callsign for waterfall ID
            writer2.Write(lastcallsign);                         // last callsign test for valid waterfall ID

            writer2.Write((byte)noaaON);                          // space weather console display

            writer2.Write("end");


            writer2.Close();    // close  file
            stream2.Close();   // close stream


            List<string> a = new List<string>();

            foreach (Control c in this.Controls)			// For each control
            {
                // if it is a groupbox or panel, check for sub controls
                if (c.GetType() == typeof(GroupBoxTS) || c.GetType() == typeof(PanelTS))
                {
                    foreach (Control c2 in c.Controls)	// for each sub-control
                    {	// check to see if it is a value type we need to save
                        if (c2.Enabled)
                        {
                            if (c2.GetType() == typeof(CheckBoxTS))
                                a.Add(c2.Name + "/" + ((CheckBoxTS)c2).Checked.ToString());
                            else if (c2.GetType() == typeof(ComboBoxTS))
                            {
                                if (((ComboBoxTS)c2).Items.Count > 0)
                                    a.Add(c2.Name + "/" + ((ComboBoxTS)c2).Text);
                            }
                            else if (c2.GetType() == typeof(NumericUpDownTS))
                                a.Add(c2.Name + "/" + ((NumericUpDownTS)c2).Value.ToString());
                            else if (c2.GetType() == typeof(RadioButtonTS))
                                a.Add(c2.Name + "/" + ((RadioButtonTS)c2).Checked.ToString());
                            else if (c2.GetType() == typeof(TextBoxTS))
                            {
                                if (((TextBoxTS)c2).ReadOnly == false)
                                    a.Add(c2.Name + "/" + ((TextBoxTS)c2).Text);
                            }
                            else if (c2.GetType() == typeof(TrackBarTS))
                                a.Add(c2.Name + "/" + ((TrackBarTS)c2).Value.ToString());
                            else if (c2.GetType() == typeof(PrettyTrackBar))
                                a.Add(c2.Name + "/" + ((PrettyTrackBar)c2).Value.ToString());
#if(DEBUG)
                            else if (c2.GetType() == typeof(GroupBox) ||
                                c2.GetType() == typeof(CheckBox) ||
                                c2.GetType() == typeof(ComboBox) ||
                                c2.GetType() == typeof(NumericUpDown) ||
                                c2.GetType() == typeof(RadioButton) ||
                                c2.GetType() == typeof(TextBox) ||
                                c2.GetType() == typeof(TrackBar))
                                Debug.WriteLine(this.Name + " -> " + c2.Name + " needs to be converted to a Thread Safe control.");
#endif
                        }
                        else
                            Debug.Print("Not saving : " + c2.Name);
                    }
                }
                else // it is not a group box
                {	// check to see if it is a value type we need to save
                    if (c.Enabled)
                    {
                        if (c.GetType() == typeof(CheckBoxTS))
                            a.Add(c.Name + "/" + ((CheckBoxTS)c).Checked.ToString());
                        else if (c.GetType() == typeof(ComboBoxTS))
                        {
                            if (((ComboBoxTS)c).SelectedIndex >= 0)
                                a.Add(c.Name + "/" + ((ComboBoxTS)c).Text);
                        }
                        else if (c.GetType() == typeof(NumericUpDownTS))
                            a.Add(c.Name + "/" + ((NumericUpDownTS)c).Value.ToString());
                        else if (c.GetType() == typeof(RadioButtonTS))
                            a.Add(c.Name + "/" + ((RadioButtonTS)c).Checked.ToString());
                        else if (c.GetType() == typeof(TextBoxTS))
                        {
                            if (((TextBoxTS)c).ReadOnly == false)
                                a.Add(c.Name + "/" + ((TextBoxTS)c).Text);
                        }
                        else if (c.GetType() == typeof(TrackBarTS))
                            a.Add(c.Name + "/" + ((TrackBarTS)c).Value.ToString());
                        else if (c.GetType() == typeof(PrettyTrackBar))
                            a.Add(c.Name + "/" + ((PrettyTrackBar)c).Value.ToString());
#if(DEBUG)
                        else if (c.GetType() == typeof(GroupBox) ||
                            c.GetType() == typeof(CheckBox) ||
                            c.GetType() == typeof(ComboBox) ||
                            c.GetType() == typeof(NumericUpDown) ||
                            c.GetType() == typeof(RadioButton) ||
                            c.GetType() == typeof(TextBox) ||
                            c.GetType() == typeof(TrackBar))
                            Debug.WriteLine(this.Name + " -> " + c.Name + " needs to be converted to a Thread Safe control.");
#endif
                    }
                }
            }

            a.Remove("udRX1StepAttData/" + udRX1StepAttData.Value.ToString());
            a.Remove("udRX2StepAttData/" + udRX2StepAttData.Value.ToString());
            a.Remove("udTXStepAttData/" + udTXStepAttData.Value.ToString()); //[2.3.6.10]MW0LGE            

            a.Add("last_radio_protocol/" + Audio.LastRadioProtocol.ToString()); // MW0LGE [2.9.0.8] used incase protocol changes from last time. Used in audio.cs tp reset PS feedback level
            a.Add("last_radio_hardware/" + Audio.LastRadioHardware.ToString()); // as above, but hardware related

            a.Add("chkNR_checkstate/" + chkNR.CheckState.ToString());
            a.Add("chkRX2NR_checkstate/" + chkRX2NR.CheckState.ToString());
            a.Add("chkNB_checkstate/" + chkNB.CheckState.ToString());
            a.Add("chkRX2NB_checkstate/" + chkRX2NB.CheckState.ToString());
            a.Add("chkQSK_checkstate/" + chkQSK.CheckState.ToString());
            a.Add("chkSquelch_checkstate/" + chkSquelch.CheckState.ToString()); //MW0LGE [2.9.0.8]
            a.Add("chkRX2Squelch_checkstate/" + chkRX2Squelch.CheckState.ToString());

            a.Add("rx1_display_cal_offset/" + rx1_display_cal_offset.ToString("f4")); //MW0LGE [2.9.0.7] change to same float precision format as display cal by radio model
            a.Add("rx1_meter_cal_offset/" + rx1_meter_cal_offset);

            a.Add("rx2_display_cal_offset/" + rx2_display_cal_offset.ToString("f4"));
            a.Add("rx2_meter_cal_offset/" + rx2_meter_cal_offset);

            a.Add("txtMemoryQuick/" + txtMemoryQuick.Text);		// save quick memory settings
            a.Add("quick_save_mode/" + (int)quick_save_mode);
            a.Add("quick_save_filter/" + (int)quick_save_filter);

            //Squelch Save
            a.Add("rx1_squelch_state/" + rx1_squelch_state.ToString());
            a.Add("rx1_fm_squelch_state/" + rx1_fm_squelch_state.ToString());
            a.Add("rx1_squelch_threshold_scroll/" + rx1_squelch_threshold_scroll);
            a.Add("rx1_fm_squelch_threshold_scroll/" + rx1_fm_squelch_threshold_scroll);
            a.Add("rx1_voice_squelch_threshold_scroll/" + rx1_voice_squelch_threshold_scroll);
            a.Add("rx2_squelch_state/" + rx2_squelch_state.ToString());
            a.Add("rx2_fm_squelch_state/" + rx2_fm_squelch_state.ToString());
            a.Add("rx2_squelch_threshold_scroll/" + rx2_squelch_threshold_scroll);
            a.Add("rx2_fm_squelch_threshold_scroll/" + rx2_fm_squelch_threshold_scroll);
            a.Add("rx2_voice_squelch_threshold_scroll/" + rx2_voice_squelch_threshold_scroll);

            a.Add("click_tune_display/" + click_tune_display);
            a.Add("VFOAFreq/" + VFOAFreq);
            a.Add("CentreFrequency/" + CentreFrequency);
            a.Add("click_tune_rx2_display/" + click_tune_rx2_display);
            a.Add("VFOBFreq/" + VFOBFreq);

            a.Add("VFOASubFreq/" + m_dVFOASubFreq);  // MW0LGE_21a

            a.Add("CentreRX2Frequency/" + CentreRX2Frequency);
            a.Add("diversity_gain_160m/" + diversity_gain_160m);
            a.Add("diversity_gain_r2_160m/" + diversity_gain_r2_160m);
            a.Add("diversity_phase_160m/" + diversity_phase_160m);
            a.Add("diversity_gain_80m/" + diversity_gain_80m);
            a.Add("diversity_gain_r2_80m/" + diversity_gain_r2_80m);
            a.Add("diversity_phase_80m/" + diversity_phase_80m);
            a.Add("diversity_gain_60m/" + diversity_gain_60m);
            a.Add("diversity_gain_r2_60m/" + diversity_gain_r2_60m);
            a.Add("diversity_phase_60m/" + diversity_phase_60m);
            a.Add("diversity_gain_40m/" + diversity_gain_40m);
            a.Add("diversity_gain_r2_40m/" + diversity_gain_r2_40m);
            a.Add("diversity_phase_40m/" + diversity_phase_40m);
            a.Add("diversity_gain_30m/" + diversity_gain_30m);
            a.Add("diversity_gain_r2_30m/" + diversity_gain_r2_30m);
            a.Add("diversity_phase_30m/" + diversity_phase_30m);
            a.Add("diversity_gain_20m/" + diversity_gain_20m);
            a.Add("diversity_gain_r2_20m/" + diversity_gain_r2_20m);
            a.Add("diversity_phase_20m/" + diversity_phase_20m);
            a.Add("diversity_gain_17m/" + diversity_gain_17m);
            a.Add("diversity_gain_r2_17m/" + diversity_gain_r2_17m);
            a.Add("diversity_phase_17m/" + diversity_phase_17m);
            a.Add("diversity_gain_15m/" + diversity_gain_15m);
            a.Add("diversity_gain_r2_15m/" + diversity_gain_r2_15m);
            a.Add("diversity_phase_15m/" + diversity_phase_15m);
            a.Add("diversity_gain_12m/" + diversity_gain_12m);
            a.Add("diversity_gain_r2_12m/" + diversity_gain_r2_12m);
            a.Add("diversity_phase_12m/" + diversity_phase_12m);
            a.Add("diversity_gain_10m/" + diversity_gain_10m);
            a.Add("diversity_gain_r2_10m/" + diversity_gain_r2_10m);
            a.Add("diversity_phase_10m/" + diversity_phase_10m);
            a.Add("diversity_gain_6m/" + diversity_gain_6m);
            a.Add("diversity_gain_r2_6m/" + diversity_gain_r2_6m);
            a.Add("diversity_phase_6m/" + diversity_phase_6m);
            a.Add("diversity_gain_wwv/" + diversity_gain_wwv);
            a.Add("diversity_gain_r2_wwv/" + diversity_gain_r2_wwv);
            a.Add("diversity_phase_wwv/" + diversity_phase_wwv);
            a.Add("diversity_gain_gen/" + diversity_gain_gen);
            a.Add("diversity_gain_r2_gen/" + diversity_gain_r2_gen);
            a.Add("diversity_phase_gen/" + diversity_phase_gen);
            a.Add("diversity_gain_xvtr/" + diversity_gain_xvtr);
            a.Add("diversity_gain_r2_xvtr/" + diversity_gain_r2_xvtr);
            a.Add("diversity_phase_xvtr/" + diversity_phase_xvtr);
            a.Add("waterfall_high_threshold_160m/" + waterfall_high_threshold_160m);
            a.Add("waterfall_low_threshold_160m/" + waterfall_low_threshold_160m);
            a.Add("waterfall_high_threshold_80m/" + waterfall_high_threshold_80m);
            a.Add("waterfall_low_threshold_80m/" + waterfall_low_threshold_80m);
            a.Add("waterfall_high_threshold_60m/" + waterfall_high_threshold_60m);
            a.Add("waterfall_low_threshold_60m/" + waterfall_low_threshold_60m);
            a.Add("waterfall_high_threshold_40m/" + waterfall_high_threshold_40m);
            a.Add("waterfall_low_threshold_40m/" + waterfall_low_threshold_40m);
            a.Add("waterfall_high_threshold_30m/" + waterfall_high_threshold_30m);
            a.Add("waterfall_low_threshold_30m/" + waterfall_low_threshold_30m);
            a.Add("waterfall_high_threshold_20m/" + waterfall_high_threshold_20m);
            a.Add("waterfall_low_threshold_20m/" + waterfall_low_threshold_20m);
            a.Add("waterfall_high_threshold_17m/" + waterfall_high_threshold_17m);
            a.Add("waterfall_low_threshold_17m/" + waterfall_low_threshold_17m);
            a.Add("waterfall_high_threshold_15m/" + waterfall_high_threshold_15m);
            a.Add("waterfall_low_threshold_15m/" + waterfall_low_threshold_15m);
            a.Add("waterfall_high_threshold_12m/" + waterfall_high_threshold_12m);
            a.Add("waterfall_low_threshold_12m/" + waterfall_low_threshold_12m);
            a.Add("waterfall_high_threshold_10m/" + waterfall_high_threshold_10m);
            a.Add("waterfall_low_threshold_10m/" + waterfall_low_threshold_10m);
            a.Add("waterfall_high_threshold_6m/" + waterfall_high_threshold_6m);
            a.Add("waterfall_low_threshold_6m/" + waterfall_low_threshold_6m);
            a.Add("waterfall_high_threshold_wwv/" + waterfall_high_threshold_wwv);
            a.Add("waterfall_low_threshold_wwv/" + waterfall_low_threshold_wwv);
            a.Add("waterfall_high_threshold_gen/" + waterfall_high_threshold_gen);
            a.Add("waterfall_low_threshold_gen/" + waterfall_low_threshold_gen);
            a.Add("waterfall_high_threshold_xvtr/" + waterfall_high_threshold_xvtr);
            a.Add("waterfall_low_threshold_xvtr/" + waterfall_low_threshold_xvtr);
            a.Add("rx2_waterfall_high_threshold_160m/" + rx2_waterfall_high_threshold_160m);
            a.Add("rx2_waterfall_low_threshold_160m/" + rx2_waterfall_low_threshold_160m);
            a.Add("rx2_waterfall_high_threshold_80m/" + rx2_waterfall_high_threshold_80m);
            a.Add("rx2_waterfall_low_threshold_80m/" + rx2_waterfall_low_threshold_80m);
            a.Add("rx2_waterfall_high_threshold_60m/" + rx2_waterfall_high_threshold_60m);
            a.Add("rx2_waterfall_low_threshold_60m/" + rx2_waterfall_low_threshold_60m);
            a.Add("rx2_waterfall_high_threshold_40m/" + rx2_waterfall_high_threshold_40m);
            a.Add("rx2_waterfall_low_threshold_40m/" + rx2_waterfall_low_threshold_40m);
            a.Add("rx2_waterfall_high_threshold_30m/" + rx2_waterfall_high_threshold_30m);
            a.Add("rx2_waterfall_low_threshold_30m/" + rx2_waterfall_low_threshold_30m);
            a.Add("rx2_waterfall_high_threshold_20m/" + rx2_waterfall_high_threshold_20m);
            a.Add("rx2_waterfall_low_threshold_20m/" + rx2_waterfall_low_threshold_20m);
            a.Add("rx2_waterfall_high_threshold_17m/" + rx2_waterfall_high_threshold_17m);
            a.Add("rx2_waterfall_low_threshold_17m/" + rx2_waterfall_low_threshold_17m);
            a.Add("rx2_waterfall_high_threshold_15m/" + rx2_waterfall_high_threshold_15m);
            a.Add("rx2_waterfall_low_threshold_15m/" + rx2_waterfall_low_threshold_15m);
            a.Add("rx2_waterfall_high_threshold_12m/" + rx2_waterfall_high_threshold_12m);
            a.Add("rx2_waterfall_low_threshold_12m/" + rx2_waterfall_low_threshold_12m);
            a.Add("rx2_waterfall_high_threshold_10m/" + rx2_waterfall_high_threshold_10m);
            a.Add("rx2_waterfall_low_threshold_10m/" + rx2_waterfall_low_threshold_10m);
            a.Add("rx2_waterfall_high_threshold_6m/" + rx2_waterfall_high_threshold_6m);
            a.Add("rx2_waterfall_low_threshold_6m/" + rx2_waterfall_low_threshold_6m);
            a.Add("rx2_waterfall_high_threshold_wwv/" + rx2_waterfall_high_threshold_wwv);
            a.Add("rx2_waterfall_low_threshold_wwv/" + rx2_waterfall_low_threshold_wwv);
            a.Add("rx2_waterfall_high_threshold_gen/" + rx2_waterfall_high_threshold_gen);
            a.Add("rx2_waterfall_low_threshold_gen/" + rx2_waterfall_low_threshold_gen);
            a.Add("rx2_waterfall_high_threshold_xvtr/" + rx2_waterfall_high_threshold_xvtr);
            a.Add("rx2_waterfall_low_threshold_xvtr/" + rx2_waterfall_low_threshold_xvtr);
            a.Add("display_grid_max_160m/" + display_grid_max_160m);
            a.Add("display_grid_min_160m/" + display_grid_min_160m);
            a.Add("display_grid_max_80m/" + display_grid_max_80m);
            a.Add("display_grid_min_80m/" + display_grid_min_80m);
            a.Add("display_grid_max_60m/" + display_grid_max_60m);
            a.Add("display_grid_min_60m/" + display_grid_min_60m);
            a.Add("display_grid_max_40m/" + display_grid_max_40m);
            a.Add("display_grid_min_40m/" + display_grid_min_40m);
            a.Add("display_grid_max_30m/" + display_grid_max_30m);
            a.Add("display_grid_min_30m/" + display_grid_min_30m);
            a.Add("display_grid_max_20m/" + display_grid_max_20m);
            a.Add("display_grid_min_20m/" + display_grid_min_20m);
            a.Add("display_grid_max_17m/" + display_grid_max_17m);
            a.Add("display_grid_min_17m/" + display_grid_min_17m);
            a.Add("display_grid_max_15m/" + display_grid_max_15m);
            a.Add("display_grid_min_15m/" + display_grid_min_15m);
            a.Add("display_grid_max_12m/" + display_grid_max_12m);
            a.Add("display_grid_min_12m/" + display_grid_min_12m);
            a.Add("display_grid_max_10m/" + display_grid_max_10m);
            a.Add("display_grid_min_10m/" + display_grid_min_10m);
            a.Add("display_grid_max_6m/" + display_grid_max_6m);
            a.Add("display_grid_min_6m/" + display_grid_min_6m);
            a.Add("display_grid_max_wwv/" + display_grid_max_wwv);
            a.Add("display_grid_min_wwv/" + display_grid_min_wwv);
            a.Add("display_grid_max_gen/" + display_grid_max_gen);
            a.Add("display_grid_min_gen/" + display_grid_min_gen);
            a.Add("display_grid_max_xvtr/" + display_grid_max_xvtr);
            a.Add("display_grid_min_xvtr/" + display_grid_min_xvtr);
            a.Add("rx2_display_grid_max_160m/" + rx2_display_grid_max_160m);
            a.Add("rx2_display_grid_min_160m/" + rx2_display_grid_min_160m);
            a.Add("rx2_display_grid_max_80m/" + rx2_display_grid_max_80m);
            a.Add("rx2_display_grid_min_80m/" + rx2_display_grid_min_80m);
            a.Add("rx2_display_grid_max_60m/" + rx2_display_grid_max_60m);
            a.Add("rx2_display_grid_min_60m/" + rx2_display_grid_min_60m);
            a.Add("rx2_display_grid_max_40m/" + rx2_display_grid_max_40m);
            a.Add("rx2_display_grid_min_40m/" + rx2_display_grid_min_40m);
            a.Add("rx2_display_grid_max_30m/" + rx2_display_grid_max_30m);
            a.Add("rx2_display_grid_min_30m/" + rx2_display_grid_min_30m);
            a.Add("rx2_display_grid_max_20m/" + rx2_display_grid_max_20m);
            a.Add("rx2_display_grid_min_20m/" + rx2_display_grid_min_20m);
            a.Add("rx2_display_grid_max_17m/" + rx2_display_grid_max_17m);
            a.Add("rx2_display_grid_min_17m/" + rx2_display_grid_min_17m);
            a.Add("rx2_display_grid_max_15m/" + rx2_display_grid_max_15m);
            a.Add("rx2_display_grid_min_15m/" + rx2_display_grid_min_15m);
            a.Add("rx2_display_grid_max_12m/" + rx2_display_grid_max_12m);
            a.Add("rx2_display_grid_min_12m/" + rx2_display_grid_min_12m);
            a.Add("rx2_display_grid_max_10m/" + rx2_display_grid_max_10m);
            a.Add("rx2_display_grid_min_10m/" + rx2_display_grid_min_10m);
            a.Add("rx2_display_grid_max_6m/" + rx2_display_grid_max_6m);
            a.Add("rx2_display_grid_min_6m/" + rx2_display_grid_min_6m);
            a.Add("rx2_display_grid_max_wwv/" + rx2_display_grid_max_wwv);
            a.Add("rx2_display_grid_min_wwv/" + rx2_display_grid_min_wwv);
            a.Add("rx2_display_grid_max_gen/" + rx2_display_grid_max_gen);
            a.Add("rx2_display_grid_min_gen/" + rx2_display_grid_min_gen);
            a.Add("rx2_display_grid_max_xvtr/" + rx2_display_grid_max_xvtr);
            a.Add("rx2_display_grid_min_xvtr/" + rx2_display_grid_min_xvtr);

            for (int m = (int)DSPMode.FIRST + 1; m < (int)DSPMode.LAST; m++)
            {	// save filter settings per mode
                for (Filter f = Filter.FIRST + 1; f < Filter.LAST; f++)
                {
                    a.Add("rx1_filters[" + m.ToString() + "][" + ((int)f).ToString() + "]/" + rx1_filters[m].ToString(f));
                }
                a.Add("last_rx1_filter[" + m.ToString() + "]/" + rx1_filters[m].LastFilter.ToString());
            }

            for (int m = (int)DSPMode.FIRST + 1; m < (int)DSPMode.LAST; m++)
            {	// save filter settings per mode
                for (Filter f = Filter.FIRST + 1; f < Filter.LAST; f++)
                {
                    a.Add("rx2_filters[" + m.ToString() + "][" + ((int)f).ToString() + "]/" + rx2_filters[m].ToString(f));
                }
                a.Add("last_rx2_filter[" + m.ToString() + "]/" + rx2_filters[m].LastFilter.ToString());
            }

            for (int i = 0; i < MNotchDB.Count; i++)
            {
                a.Add("mnotchdb[" + i + "]/" + MNotchDB.NotchFromIndex(i).ToString());
            }

            for (int i = 0; i < (int)Band.LAST; i++)
            {
                s = "rx1_level_table[" + i + "]/";
                for (int j = 0; j < 3; j++)
                    s += rx1_level_table[i][j].ToString("f3") + "|";
                s = s.Substring(0, s.Length - 1);
                a.Add(s);
            }

            for (int i = 0; i < (int)Band.LAST; i++)
            {
                s = "rx2_level_table[" + i + "]/";
                for (int j = 0; j < 3; j++)
                    s += rx2_level_table[i][j].ToString("f3") + "|";
                s = s.Substring(0, s.Length - 1);
                a.Add(s);
            }

            rx1_preamp_by_band[(int)rx1_band] = rx1_preamp_mode;
            s = "rx1_preamp_by_band/";
            for (int i = 0; i < (int)Band.LAST; i++)
                s += ((int)rx1_preamp_by_band[i]).ToString() + "|";
            s = s.Substring(0, s.Length - 1);
            a.Add(s);

            rx2_preamp_by_band[(int)rx2_band] = rx2_preamp_mode;
            s = "rx2_preamp_by_band/";
            for (int i = 0; i < (int)Band.LAST; i++)
                s += ((int)rx2_preamp_by_band[i]).ToString() + "|";
            s = s.Substring(0, s.Length - 1);
            a.Add(s);

            setRX1stepAttenuatorForBand(rx1_band, rx1_attenuator_data);
            s = "rx1_step_attenuator_by_band/";
            for (int i = 0; i < (int)Band.LAST; i++)
                s += getRX1stepAttenuatorForBand((Band)i).ToString() + "|";
            s = s.Substring(0, s.Length - 1);
            a.Add(s);

            setRX2stepAttenuatorForBand(rx2_band, rx2_attenuator_data);
            s = "rx2_step_attenuator_by_band/";
            for (int i = 0; i < (int)Band.LAST; i++)
                s += getRX2stepAttenuatorForBand((Band)i).ToString() + "|";
            s = s.Substring(0, s.Length - 1);
            a.Add(s);

            s = "tx_step_attenuator_by_band/";
            for (int i = 0; i < (int)Band.LAST; i++)
                s += getTXstepAttenuatorForBand((Band)i).ToString() + "|";
            s = s.Substring(0, s.Length - 1);
            a.Add(s);

            s = "power_by_band/";
            for (int i = 0; i < (int)Band.LAST; i++)
                s += power_by_band[i].ToString() + "|";
            s = s.Substring(0, s.Length - 1);
            a.Add(s);

            s = "tunePower_by_band/";
            for (int i = 0; i < (int)Band.LAST; i++)
                s += tunePower_by_band[i].ToString() + "|";
            s = s.Substring(0, s.Length - 1);
            a.Add(s);

            s = "limitPower_by_band/";
            for (int i = 0; i < (int)Band.LAST; i++)
                s += limitPower_by_band[i].ToString() + "|";
            s = s.Substring(0, s.Length - 1);
            a.Add(s);

            s = "limitTunePower_by_band/";
            for (int i = 0; i < (int)Band.LAST; i++)
                s += limitTunePower_by_band[i].ToString() + "|";
            s = s.Substring(0, s.Length - 1);
            a.Add(s);

            s = "fm_tx_offset_by_band_mhz/";
            for (int i = 0; i < (int)Band.LAST; i++)
                s += fm_tx_offset_by_band_mhz[i].ToString("R") + "|";
            s = s.Substring(0, s.Length - 1);
            a.Add(s);

            s = "rx1_agct_by_band/";
            for (int i = 0; i < (int)Band.LAST; i++)
                s += rx1_agct_by_band[i].ToString() + "|";
            s = s.Substring(0, s.Length - 1);
            a.Add(s);

            s = "rx2_agct_by_band/";
            for (int i = 0; i < (int)Band.LAST; i++)
                s += rx2_agct_by_band[i].ToString() + "|";
            s = s.Substring(0, s.Length - 1);
            a.Add(s);

            rx1_agcm_by_band[(int)rx1_band] = RX1AGCMode;
            s = "rx1_agcm_by_band/";
            for (int i = 0; i < (int)Band.LAST; i++)
                s += ((int)rx1_agcm_by_band[i]).ToString() + "|";
            s = s.Substring(0, s.Length - 1);
            a.Add(s);

            rx2_agcm_by_band[(int)rx2_band] = RX2AGCMode;
            s = "rx2_agcm_by_band/";
            for (int i = 0; i < (int)Band.LAST; i++)
                s += ((int)rx2_agcm_by_band[i]).ToString() + "|";
            s = s.Substring(0, s.Length - 1);
            a.Add(s);

            s = "diversity_rx1_ref_by_band/";
            for (int i = 0; i < (int)Band.LAST; i++)
                s += Convert.ToUInt16(diversity_rx1_ref_by_band[i]).ToString() + "|";
            s = s.Substring(0, s.Length - 1);
            a.Add(s);

            //MW0LGE_21k9d
            for (int rx = 0; rx < 2; rx++)
            {
                if (rx == 0)
                    s = "rx1_ztbdata";
                else
                    s = "rx2_ztbdata";

                string s1 = "", s2 = "", s3 = "", s4 = "";
                for (int i = 0; i < (int)Band.LAST; i++)
                {
                    ztb_data ztb = ztb_data_by_band[rx][i];
                    s1 += ztb.CentreFrequency.ToString() + "|";
                    s2 += ztb.PanSliderPosition.ToString() + "|";
                    s3 += ztb.ZoomSliderPosition.ToString() + "|";
                    s4 += ztb.Initalised + "|";
                }
                s1 = s1.Substring(0, s1.Length - 1);
                s2 = s2.Substring(0, s2.Length - 1);
                s3 = s3.Substring(0, s3.Length - 1);
                s4 = s4.Substring(0, s4.Length - 1);
                a.Add(s + "_cf/" + s1);
                a.Add(s + "_ps/" + s2);
                a.Add(s + "_zs/" + s3);
                a.Add(s + "_init/" + s4);
            }
            //

            s = "rx_meter_cal_offset_by_radio/";
            for (int i = 0; i < (int)HPSDRModel.LAST; i++)
                s += (rx_meter_cal_offset_by_radio[i]).ToString("f4") + "|";
            s = s.Substring(0, s.Length - 1);
            a.Add(s);

            s = "rx_display_cal_offset_by_radio/";
            for (int i = 0; i < (int)HPSDRModel.LAST; i++)
                s += (rx_display_cal_offset_by_radio[i]).ToString("f4") + "|";
            s = s.Substring(0, s.Length - 1);
            a.Add(s);

            a.Add("panelBandHF.Visible/" + _bands_HF_selected);
            a.Add("panelBandVHF.Visible/" + _bands_VHF_selected);
            a.Add("panelBandGEN.Visible/" + _bands_GEN_selected);
            a.Add("iscollapsed/" + _iscollapsed);
            a.Add("isexpanded/" + _isexpanded);
            a.Add("diversity/" + diversity2);

            for (int i = (int)PreampMode.FIRST + 1; i < (int)PreampMode.LAST; i++)
                a.Add("rx1_preamp_offset[" + i.ToString() + "]/" + rx1_preamp_offset[i].ToString("f3"));

            a.Add("wheel_tune_index/" + tune_step_index.ToString());		// Save wheel tune value

            //MW0LGE_21j
            s = "wheel_tune_index_by_mode/";
            for (int i = 0; i < (int)DSPMode.LAST; i++)
                s += ((int)m_nTuneStepsByMode[i]).ToString() + "|";
            s = s.Substring(0, s.Length - 1);
            a.Add(s);
            //

            a.Add("infoBar_flip/" + infoBar.CurrentFlip.ToString()); //MW0LGE_21k9rc4 info bar currentflip
            a.Add("infoBar_button1/" + ((int)infoBar.Button1Action).ToString()); //MW0LGE_[2.9.0.6] change to in, to prevent getstate issues if enaum names change
            a.Add("infoBar_button2/" + ((int)infoBar.Button2Action).ToString());
            a.Add("infoBar_splitter_ratio/" + infoBar.SplitterRatio.ToString("f4")); //MW0LGE_21k9c changed format

            a.Add("auto_start_forms/" + getAutoStartData()); //[2.10.3.6]MW0LGE

            a.Add("vfob_dsp_mode/" + ((int)vfob_dsp_mode).ToString());			// Save VFO B values 
            a.Add("vfob_filter/" + ((int)vfob_filter).ToString());

            a.Add("RX1MeterPaddingRatio/" + m_fMeterPadRatio.ToString());

            //MW0LGE_21d drop shadow
            Rectangle r = new Rectangle(this.Left, this.Top, this.Width, this.Height);
            if (this.WindowState == FormWindowState.Maximized)
            {
                Size ds = DropShadowSize;
                r.X += ds.Width / 2;
                r.Y += ds.Height / 2;
                r.Width -= ds.Width;
                r.Height -= ds.Height;
            }

            if (this.WindowState != FormWindowState.Minimized)//[2.10.3.6]MW0LGE prevent garbage being stored if shutdown when minimsed
            {
                a.Add("console_top/" + r.Top.ToString());       // save form positions
                a.Add("console_left/" + r.Left.ToString());
                a.Add("console_width/" + r.Width.ToString());
                a.Add("console_height/" + r.Height.ToString());
            }
            a.Add("console_state/" + ((int)this.WindowState).ToString()); //MW0LGE_21 window state

            if (SetupForm.WindowState != FormWindowState.Minimized)//[2.10.3.6]MW0LGE prevent garbage being stored if shutdown when minimsed
            {
                a.Add("setup_top/" + SetupForm.Top.ToString());
                a.Add("setup_left/" + SetupForm.Left.ToString());
            }

            a.Add("IncludeWindowBorders/" + m_bIncludeWindowBorders);   // used in status bar resize form calcs
            a.Add("PanafallSplitBarPerc/" + Display.PanafallSplitBarPerc.ToString());  // the percentage of displayheight that is used in panafall rx1 only

            //--
            a.Add("DumpCap_WireSharkPath/" + DumpCap.WireSharkPath);
            a.Add("DumpCap_Interface/" + DumpCap.Interface.ToString());
            a.Add("DumpCap_NegativeOnly/" + DumpCap.KillOnNegativeSeqOnly.ToString());
            a.Add("DumpCap_ClearFolderOnRestart/" + DumpCap.ClearFolderOnRestart.ToString());
            //--
            a.Add("SeqLog_ShowWarningOnNegativeOnly/" + m_frmSeqLog.StatusBarWarningOnNegativeOnly);
            //--
            a.Add("CPU_ShowSystem/" + m_bShowSystemCPUUsage);
            //--

            a.Add("saved_rx_only/" + saved_rx_only.ToString());
            a.Add("mon_recall/" + mon_recall.ToString());

            string ver_num = Common.GetVerNum();
            a.Add("Version/" + this.Text);		// save the current version
            a.Add("VersionNumber/" + ver_num);      // Thetis version number in a.b.c format
            // a.Add("RadioType/" + CurrentModel);     // radio model string (ex. FLEX1500)
            a.Add("BandTextID/" + current_region);  // TURF Region
            a.Add("Metis_IP_address/" + NetworkIO.HpSdrHwIpAddress.ToString(nfi));
            a.Add("EthernetHostIPAddress/" + NetworkIO.EthernetHostIPAddress.ToString(nfi));

            a.Add("PruneBackups/" + DBMan.PruneBackups.ToString());

            DB.PurgeNotches();                  // remove old notches from DB
                                                // this is done because we have not stored an upper limit the number of notches
                                                // and if we had 20 in there before, and now only write 3, how do we know?
                                                // as it will still be [0]..[19]

            DB.SaveVars("State", a, true);		// save the values to the DB
        }

        private FormWindowState m_WindowState = FormWindowState.Normal;
        public void GetState()
        {
            // returns if an update is needed - MW0LGE_21a
            // Automatically restores all controls from the database in the
            // tab pages on this form of the following types: CheckBox, ComboBox,
            // NumericUpDown, RadioButton, TextBox, and TrackBar (slider)

            string file_name2 = AppDataPath + "ke9ns8.dat"; // save data for my mods

            bool bNeedUpdate = false; // MW0LGE used to rebuild main form collapsed/expanded, done at the very end
            Point pConsoleLocation = new Point(this.Top, this.Left);
            Size szConsoleSize = new Size(this.Width, this.Height);

            if (!File.Exists(file_name2))
            {
                Debug.WriteLine("Create new database file");
                FileStream stream2 = new FileStream(file_name2, FileMode.Create); // open BMP  file
                BinaryWriter writer2 = new BinaryWriter(stream2);
                writer2.Write(Display.GrayScale);                    // color or grayscale watetfall
                writer2.Write(Display.GridOff);                      // save panadapter grid on/off
                writer2.Write(SpotControl.nameB);               // name for dx spotter
                writer2.Write(SpotControl.callB);               // call sign for dx spotter
                writer2.Write(SpotControl.nodeB);               // node  for dx spotter
                writer2.Write(SpotControl.portB);               // port for dx spotter
                writer2.Write(callsign);                             // callsign for waterfall ID
                writer2.Write(lastcallsign);                         // last callsign test for valid waterfall ID
                writer2.Write((byte)noaaON);                          // space weather console display
                writer2.Write("end");
                writer2.Close();    // close  file
                stream2.Close();   // close stream
                Debug.WriteLine("Create new database file");

            }
            else // yes ke9ns.dat file does exist
            {

                FileStream stream2 = new FileStream(file_name2, FileMode.Open); // open BMP  file
                BinaryReader reader2 = new BinaryReader(stream2);

                Display.GrayScale = reader2.ReadByte();                            // color or grayscale waterfall 

                Display.GridOff = reader2.ReadByte();                              // panadapter grid on / off

                SpotControl.DXNAME = reader2.ReadString();                     // name for dx spotter
                SpotControl.DXCALL = reader2.ReadString();                     // call sign for dx spotter
                SpotControl.DXNODE = reader2.ReadString();                     // node for dx spotter
                SpotControl.DXPORT = reader2.ReadString();                     // port for dx spotter


                callsign = reader2.ReadString();                                   // callsign for waterfall ID
                lastcallsign = reader2.ReadString();                               // last callsign test of waterfall ID valid

                noaaON = reader2.ReadByte();                                // space weather console display
                reader2.Close();    // close  file
                stream2.Close();   // close stream
            }

            //[2.10.2.3]MW0LGE change to dictionary as controls will be unique
            Dictionary<string, Control> ctrls = new Dictionary<string, Control>();

            foreach (Control c in this.Controls)
            {
                // if control is a groupbox or panel, retrieve all subcontrols
                if (c.GetType() == typeof(GroupBoxTS) || c.GetType() == typeof(PanelTS))
                {
                    foreach (Control c2 in c.Controls)
                        ctrls.Add(c2.Name, c2);
                }
                else
                {
                    ctrls.Add(c.Name, c);
                }
            }

            List<string> a = DB.GetVars("State");							// Get the saved list of controls
            a.Sort();

            // MW0LGE_21a
            // this to do list will store any that we want to do after the intial pass
            List<KeyValuePair<string, string>> toDoList = new List<KeyValuePair<string, string>>();

            double dVFOAFreq = 7.1; //MW0LGE_21c
            double dVFOBFreq = 7.1;
            double dRX1_centre_freq = 7.1;
            double dRX2_centre_freq = 7.1;

            foreach (string s in a)				// string is in the format "name,value"
            {
                int start, length, index, filter_mode;

                string[] vals = s.Split('/');
                if (vals.Length > 2)
                {
                    for (int i = 2; i < vals.Length; i++)
                        vals[1] += "/" + vals[i];
                }

                string name = vals[0];
                string val = vals[1];
                string[] list;
                int num = 0;

                switch (name)
                {
                    //ignore section
                    case "udFilterLow":
                    case "udFilterHigh":
                    case "udRX2FilterLow":
                    case "udRX2FilterHigh":
                        //[2.10.3]MW0LGE ignore section, in the case of the filter ud controls, they will be set by the filter being selected
                        break;

                    case "last_radio_protocol":
                        Audio.LastRadioProtocol = (RadioProtocol)Enum.Parse(typeof(RadioProtocol), val);
                        break;
                    case "last_radio_hardware":
                        Audio.LastRadioHardware = (HPSDRHW)Enum.Parse(typeof(HPSDRHW), val);
                        break;
                    case "wheel_tune_index":
                        tune_step_index = Int32.Parse(val);
                        break;
                    case var nam when name.StartsWith("wheel_tune_index_by_mode"):
                        list = val.Split('|');
                        if (list.Length != (int)DSPMode.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)DSPMode.LAST; i++)
                            m_nTuneStepsByMode[i] = int.Parse(list[i]);
                        break;
                    case "txtMemoryQuick":
                        txtMemoryQuick.Text = val;
                        break;
                    case "rx1_display_cal_offset":
                        RX1DisplayCalOffset = float.Parse(val);
                        break;
                    case "rx1_meter_cal_offset":
                        rx1_meter_cal_offset = float.Parse(val);
                        break;
                    case "rx2_display_cal_offset":
                        RX2DisplayCalOffset = float.Parse(val);
                        break;
                    case "rx2_meter_cal_offset":
                        rx2_meter_cal_offset = float.Parse(val);
                        break;
                    case "panelBandHF.Visible": //added by w3sz
                        //_bands_HF_selected = bool.Parse(val); //added by w3sz
                        //panelBandHF.Visible = _bands_HF_selected; //added by w3sz
                        //if (_bands_HF_selected) //added by w3sz
                        //    btnBandHF_Click(btnBandHF, EventArgs.Empty); //added by w3sz
                        {
                            bool selected = bool.Parse(val); //[2.10.3.6]MW0LGE
                            BandHFSelected = selected;
                        }
                        break; //added by w3sz
                    case "panelBandVHF.Visible": //added by w3sz
                        //_bands_VHF_selected = bool.Parse(val); //added by w3sz
                        //panelBandVHF.Visible = _bands_VHF_selected; //added by w3sz
                        //if (_bands_VHF_selected) //added by w3sz
                        //    btnBandVHF_Click(btnBandVHF, EventArgs.Empty); //added by w3sz
                        {
                            bool selected = bool.Parse(val); //[2.10.3.6]MW0LGE
                            BandVHFSelected = selected;
                        }
                        break;  //added by w3sz
                    case "panelBandGEN.Visible":
                        //_bands_GEN_selected = bool.Parse(val);
                        //panelBandGEN.Visible = _bands_GEN_selected;
                        //if (_bands_GEN_selected)
                        //    btnBandGEN_Click(radBandGEN, EventArgs.Empty);
                        {
                            bool selected = bool.Parse(val); //[2.10.3.6]MW0LGE
                            BandGENSelected = selected;
                        }
                        break;  //added by w3sz
                    case "iscollapsed":  //added by w3sz
                        _iscollapsed = bool.Parse(val);    //added by w3sz
                        if (_iscollapsed)   //added by w3sz
                        {
                            bNeedUpdate = true;
                            _iscollapsed = true;
                            _isexpanded = false;
                        }
                        break; //added by w3sz
                    case "isexpanded":  //added by w3sz
                        _isexpanded = bool.Parse(val);    //added by w3sz
                        if (_isexpanded)   //added by w3sz
                        {
                            bNeedUpdate = true;
                            _isexpanded = true;
                            _iscollapsed = false;
                        }
                        break; //added by w3sz
                    case "diversity":
                        startdiversity = bool.Parse(val);
                        break;
                    case "quick_save_mode":
                        quick_save_mode = (DSPMode)(Int32.Parse(val));
                        break;
                    case "quick_save_filter":
                        quick_save_filter = (Filter)(Int32.Parse(val));
                        break;
                    case "vfob_dsp_mode":
                        vfob_dsp_mode = (DSPMode)(Int32.Parse(val));
                        break;
                    case "vfob_filter":
                        vfob_filter = (Filter)(Int32.Parse(val));
                        break;
                    case "RX1MeterPaddingRatio":
                        m_fMeterPadRatio = float.Parse(val);
                        break;
                    case "console_top":
                        num = Int32.Parse(val);
                        bNeedUpdate = true;
                        pConsoleLocation.Y = num;
                        break;
                    case "console_left":
                        num = Int32.Parse(val);
                        bNeedUpdate = true;
                        pConsoleLocation.X = num;
                        break;
                    case "console_width":
                        if (dpi <= 96)
                        {
                            int tmp = int.Parse(val);
                            if (_isexpanded) this.expandedSize.Width = tmp;
                            bNeedUpdate = true;
                            szConsoleSize.Width = tmp;
                        }
                        break;
                    case "console_height":
                        if (dpi <= 96)
                        {
                            int tmp = int.Parse(val);
                            if (_isexpanded) this.expandedSize.Height = tmp;
                            bNeedUpdate = true;
                            szConsoleSize.Height = tmp;
                        }
                        break;
                    case "console_state":
                        m_WindowState = (FormWindowState)int.Parse(val);
                        bNeedUpdate = true;
                        break;
                    case "setup_top":
                        num = Int32.Parse(val);
                        SetupForm.Top = num;
                        break;
                    case "setup_left":
                        num = Int32.Parse(val);
                        SetupForm.Left = num;
                        break;
                    case "IncludeWindowBorders":
                        IncludeWindowBorders = bool.Parse(val); // used for statusbar form resize calcs
                        break;
                    case "PanafallSplitBarPerc":
                        Display.PanafallSplitBarPerc = float.Parse(val); // used for the splitter percentage when rx1 only displayed in panafall mode
                        break;
                    case "DumpCap_WireSharkPath":
                        DumpCap.WireSharkPath = val;
                        break;
                    case "DumpCap_Interface":
                        DumpCap.Interface = int.Parse(val);
                        break;
                    case "DumpCap_NegativeOnly":
                        DumpCap.KillOnNegativeSeqOnly = bool.Parse(val);
                        break;
                    case "DumpCap_ClearFolderOnRestart":
                        DumpCap.ClearFolderOnRestart = bool.Parse(val);
                        break;
                    case "SeqLog_ShowWarningOnNegativeOnly":
                        m_frmSeqLog.StatusBarWarningOnNegativeOnly = bool.Parse(val);
                        break;
                    case "CPU_ShowSystem":
                        m_bShowSystemCPUUsage = bool.Parse(val);
                        break;
                    case "saved_rx_only":
                        saved_rx_only = bool.Parse(val);
                        break;
                    case "mon_recall":
                        mon_recall = bool.Parse(val);
                        break;
                    case "rx1_squelch_state":
                        rx1_squelch_state = (SquelchState)Enum.Parse(typeof(SquelchState), val);
                        break;
                    case "rx1_fm_squelch_state":
                        rx1_fm_squelch_state = (SquelchState)Enum.Parse(typeof(SquelchState), val);
                        break;
                    case "rx1_squelch_threshold_scroll":
                        rx1_squelch_threshold_scroll = int.Parse(val);
                        break;
                    case "rx1_fm_squelch_threshold_scroll":
                        rx1_fm_squelch_threshold_scroll = int.Parse(val);
                        break;
                    case "rx1_voice_squelch_threshold_scroll":
                        rx1_voice_squelch_threshold_scroll = int.Parse(val);
                        break;
                    case "rx2_squelch_state":
                        rx2_squelch_state = (SquelchState)Enum.Parse(typeof(SquelchState), val);
                        break;
                    case "rx2_fm_squelch_state":
                        rx2_fm_squelch_state = (SquelchState)Enum.Parse(typeof(SquelchState), val);
                        break;
                    case "rx2_squelch_threshold_scroll":
                        rx2_squelch_threshold_scroll = int.Parse(val);
                        break;
                    case "rx2_fm_squelch_threshold_scroll":
                        rx2_fm_squelch_threshold_scroll = int.Parse(val);
                        break;
                    case "rx2_voice_squelch_threshold_scroll":
                        rx2_voice_squelch_threshold_scroll = int.Parse(val);
                        break;
                    case "click_tune_display":
                        click_tune_display = bool.Parse(val);
                        break;
                    case "VFOAFreq":
                        dVFOAFreq = double.Parse(val); // MW0LGE_21c need to do this at end, as we used center_freq etc
                        break;
                    case "CentreFrequency":
                        dRX1_centre_freq = double.Parse(val);
                        break;
                    case "click_tune_rx2_display":
                        click_tune_rx2_display = bool.Parse(val);
                        break;
                    case "VFOBFreq":
                        dVFOBFreq = double.Parse(val); // MW0LGE_21c need to do this at end, as we used center_freq etc
                        break;
                    case "VFOASubFreq": // MW0LGE_21a
                        VFOASubFreq = double.Parse(val);
                        saved_vfoa_sub_freq = m_dVFOASubFreq;  // init the save sub freq (i dont like this, TODO)
                        break;
                    case "CentreRX2Frequency":
                        dRX2_centre_freq = double.Parse(val);
                        break;
                    case "diversity_gain_160m":
                        diversity_gain_160m = decimal.Parse(val);
                        break;
                    case "diversity_gain_r2_160m":
                        diversity_gain_r2_160m = decimal.Parse(val);
                        break;
                    case "diversity_phase_160m":
                        diversity_phase_160m = decimal.Parse(val);
                        break;
                    case "diversity_gain_80m":
                        diversity_gain_80m = decimal.Parse(val);
                        break;
                    case "diversity_gain_r2_80m":
                        diversity_gain_r2_80m = decimal.Parse(val);
                        break;
                    case "diversity_phase_80m":
                        diversity_phase_80m = decimal.Parse(val);
                        break;
                    case "diversity_gain_60m":
                        diversity_gain_60m = decimal.Parse(val);
                        break;
                    case "diversity_gain_r2_60m":
                        diversity_gain_r2_60m = decimal.Parse(val);
                        break;
                    case "diversity_phase_60m":
                        diversity_phase_60m = decimal.Parse(val);
                        break;
                    case "diversity_gain_40m":
                        diversity_gain_40m = decimal.Parse(val);
                        break;
                    case "diversity_gain_r2_40m":
                        diversity_gain_r2_40m = decimal.Parse(val);
                        break;
                    case "diversity_phase_40m":
                        diversity_phase_40m = decimal.Parse(val);
                        break;
                    case "diversity_gain_30m":
                        diversity_gain_30m = decimal.Parse(val);
                        break;
                    case "diversity_gain_r2_30m":
                        diversity_gain_r2_30m = decimal.Parse(val);
                        break;
                    case "diversity_phase_30m":
                        diversity_phase_30m = decimal.Parse(val);
                        break;
                    case "diversity_gain_20m":
                        diversity_gain_20m = decimal.Parse(val);
                        break;
                    case "diversity_gain_r2_20m":
                        diversity_gain_r2_20m = decimal.Parse(val);
                        break;
                    case "diversity_phase_20m":
                        diversity_phase_20m = decimal.Parse(val);
                        break;
                    case "diversity_gain_17m":
                        diversity_gain_17m = decimal.Parse(val);
                        break;
                    case "diversity_gain_r2_17m":
                        diversity_gain_r2_17m = decimal.Parse(val);
                        break;
                    case "diversity_phase_17m":
                        diversity_phase_17m = decimal.Parse(val);
                        break;
                    case "diversity_gain_15m":
                        diversity_gain_15m = decimal.Parse(val);
                        break;
                    case "diversity_gain_r2_15m":
                        diversity_gain_r2_15m = decimal.Parse(val);
                        break;
                    case "diversity_phase_15m":
                        diversity_phase_15m = decimal.Parse(val);
                        break;
                    case "diversity_gain_12m":
                        diversity_gain_12m = decimal.Parse(val);
                        break;
                    case "diversity_gain_r2_12m":
                        diversity_gain_r2_12m = decimal.Parse(val);
                        break;
                    case "diversity_phase_12m":
                        diversity_phase_12m = decimal.Parse(val);
                        break;
                    case "diversity_gain_10m":
                        diversity_gain_10m = decimal.Parse(val);
                        break;
                    case "diversity_gain_r2_10m":
                        diversity_gain_r2_10m = decimal.Parse(val);
                        break;
                    case "diversity_phase_10m":
                        diversity_phase_10m = decimal.Parse(val);
                        break;
                    case "diversity_gain_6m":
                        diversity_gain_6m = decimal.Parse(val);
                        break;
                    case "diversity_gain_r2_6m":
                        diversity_gain_r2_6m = decimal.Parse(val);
                        break;
                    case "diversity_phase_6m":
                        diversity_phase_6m = decimal.Parse(val);
                        break;
                    case "diversity_gain_wwv":
                        diversity_gain_wwv = decimal.Parse(val);
                        break;
                    case "diversity_gain_r2_wwv":
                        diversity_gain_r2_wwv = decimal.Parse(val);
                        break;
                    case "diversity_phase_wwv":
                        diversity_phase_wwv = decimal.Parse(val);
                        break;
                    case "diversity_gain_gen":
                        diversity_gain_gen = decimal.Parse(val);
                        break;
                    case "diversity_gain_r2_gen":
                        diversity_gain_r2_gen = decimal.Parse(val);
                        break;
                    case "diversity_phase_gen":
                        diversity_phase_gen = decimal.Parse(val);
                        break;
                    case "diversity_gain_xvtr":
                        diversity_gain_xvtr = decimal.Parse(val);
                        break;
                    case "diversity_gain_r2_xvtr":
                        diversity_gain_r2_xvtr = decimal.Parse(val);
                        break;
                    case "diversity_phase_xvtr":
                        diversity_phase_xvtr = decimal.Parse(val);
                        break;
                    case "waterfall_high_threshold_160m":
                        waterfall_high_threshold_160m = float.Parse(val);
                        break;
                    case "waterfall_low_threshold_160m":
                        waterfall_low_threshold_160m = float.Parse(val);
                        break;
                    case "waterfall_high_threshold_80m":
                        waterfall_high_threshold_80m = float.Parse(val);
                        break;
                    case "waterfall_low_threshold_80m":
                        waterfall_low_threshold_80m = float.Parse(val);
                        break;
                    case "waterfall_high_threshold_60m":
                        waterfall_high_threshold_60m = float.Parse(val);
                        break;
                    case "waterfall_low_threshold_60m":
                        waterfall_low_threshold_60m = float.Parse(val);
                        break;
                    case "waterfall_high_threshold_40m":
                        waterfall_high_threshold_40m = float.Parse(val);
                        break;
                    case "waterfall_low_threshold_40m":
                        waterfall_low_threshold_40m = float.Parse(val);
                        break;
                    case "waterfall_high_threshold_30m":
                        waterfall_high_threshold_30m = float.Parse(val);
                        break;
                    case "waterfall_low_threshold_30m":
                        waterfall_low_threshold_30m = float.Parse(val);
                        break;
                    case "waterfall_high_threshold_20m":
                        waterfall_high_threshold_20m = float.Parse(val);
                        break;
                    case "waterfall_low_threshold_20m":
                        waterfall_low_threshold_20m = float.Parse(val);
                        break;
                    case "waterfall_high_threshold_17m":
                        waterfall_high_threshold_17m = float.Parse(val);
                        break;
                    case "waterfall_low_threshold_17m":
                        waterfall_low_threshold_17m = float.Parse(val);
                        break;
                    case "waterfall_high_threshold_15m":
                        waterfall_high_threshold_15m = float.Parse(val);
                        break;
                    case "waterfall_low_threshold_15m":
                        waterfall_low_threshold_15m = float.Parse(val);
                        break;
                    case "waterfall_high_threshold_12m":
                        waterfall_high_threshold_12m = float.Parse(val);
                        break;
                    case "waterfall_low_threshold_12m":
                        waterfall_low_threshold_12m = float.Parse(val);
                        break;
                    case "waterfall_high_threshold_10m":
                        waterfall_high_threshold_10m = float.Parse(val);
                        break;
                    case "waterfall_low_threshold_10m":
                        waterfall_low_threshold_10m = float.Parse(val);
                        break;
                    case "waterfall_high_threshold_6m":
                        waterfall_high_threshold_6m = float.Parse(val);
                        break;
                    case "waterfall_low_threshold_6m":
                        waterfall_low_threshold_6m = float.Parse(val);
                        break;
                    case "waterfall_high_threshold_wwv":
                        waterfall_high_threshold_wwv = float.Parse(val);
                        break;
                    case "waterfall_low_threshold_wwv":
                        waterfall_low_threshold_wwv = float.Parse(val);
                        break;
                    case "waterfall_high_threshold_gen":
                        waterfall_high_threshold_gen = float.Parse(val);
                        break;
                    case "waterfall_low_threshold_gen":
                        waterfall_low_threshold_gen = float.Parse(val);
                        break;
                    case "waterfall_high_threshold_xvtr":
                        waterfall_high_threshold_xvtr = float.Parse(val);
                        break;
                    case "waterfall_low_threshold_xvtr":
                        waterfall_low_threshold_xvtr = float.Parse(val);
                        break;
                    case "rx2_waterfall_high_threshold_160m":
                        rx2_waterfall_high_threshold_160m = float.Parse(val);
                        break;
                    case "rx2_waterfall_low_threshold_160m":
                        rx2_waterfall_low_threshold_160m = float.Parse(val);
                        break;
                    case "rx2_waterfall_high_threshold_80m":
                        rx2_waterfall_high_threshold_80m = float.Parse(val);
                        break;
                    case "rx2_waterfall_low_threshold_80m":
                        rx2_waterfall_low_threshold_80m = float.Parse(val);
                        break;
                    case "rx2_waterfall_high_threshold_60m":
                        rx2_waterfall_high_threshold_60m = float.Parse(val);
                        break;
                    case "rx2_waterfall_low_threshold_60m":
                        rx2_waterfall_low_threshold_60m = float.Parse(val);
                        break;
                    case "rx2_waterfall_high_threshold_40m":
                        rx2_waterfall_high_threshold_40m = float.Parse(val);
                        break;
                    case "rx2_waterfall_low_threshold_40m":
                        rx2_waterfall_low_threshold_40m = float.Parse(val);
                        break;
                    case "rx2_waterfall_high_threshold_30m":
                        rx2_waterfall_high_threshold_30m = float.Parse(val);
                        break;
                    case "rx2_waterfall_low_threshold_30m":
                        rx2_waterfall_low_threshold_30m = float.Parse(val);
                        break;
                    case "rx2_waterfall_high_threshold_20m":
                        rx2_waterfall_high_threshold_20m = float.Parse(val);
                        break;
                    case "rx2_waterfall_low_threshold_20m":
                        rx2_waterfall_low_threshold_20m = float.Parse(val);
                        break;
                    case "rx2_waterfall_high_threshold_17m":
                        rx2_waterfall_high_threshold_17m = float.Parse(val);
                        break;
                    case "rx2_waterfall_low_threshold_17m":
                        rx2_waterfall_low_threshold_17m = float.Parse(val);
                        break;
                    case "rx2_waterfall_high_threshold_15m":
                        rx2_waterfall_high_threshold_15m = float.Parse(val);
                        break;
                    case "rx2_waterfall_low_threshold_15m":
                        rx2_waterfall_low_threshold_15m = float.Parse(val);
                        break;
                    case "rx2_waterfall_high_threshold_12m":
                        rx2_waterfall_high_threshold_12m = float.Parse(val);
                        break;
                    case "rx2_waterfall_low_threshold_12m":
                        rx2_waterfall_low_threshold_12m = float.Parse(val);
                        break;
                    case "rx2_waterfall_high_threshold_10m":
                        rx2_waterfall_high_threshold_10m = float.Parse(val);
                        break;
                    case "rx2_waterfall_low_threshold_10m":
                        rx2_waterfall_low_threshold_10m = float.Parse(val);
                        break;
                    case "rx2_waterfall_high_threshold_6m":
                        rx2_waterfall_high_threshold_6m = float.Parse(val);
                        break;
                    case "rx2_waterfall_low_threshold_6m":
                        rx2_waterfall_low_threshold_6m = float.Parse(val);
                        break;
                    case "rx2_waterfall_high_threshold_wwv":
                        rx2_waterfall_high_threshold_wwv = float.Parse(val);
                        break;
                    case "rx2_waterfall_low_threshold_wwv":
                        rx2_waterfall_low_threshold_wwv = float.Parse(val);
                        break;
                    case "rx2_waterfall_high_threshold_gen":
                        rx2_waterfall_high_threshold_gen = float.Parse(val);
                        break;
                    case "rx2_waterfall_low_threshold_gen":
                        rx2_waterfall_low_threshold_gen = float.Parse(val);
                        break;
                    case "rx2_waterfall_high_threshold_xvtr":
                        rx2_waterfall_high_threshold_xvtr = float.Parse(val);
                        break;
                    case "rx2_waterfall_low_threshold_xvtr":
                        rx2_waterfall_low_threshold_xvtr = float.Parse(val);
                        break;
                    case "display_grid_max_160m":
                        display_grid_max_160m = float.Parse(val);
                        break;
                    case "display_grid_min_160m":
                        display_grid_min_160m = float.Parse(val);
                        break;
                    case "display_grid_max_80m":
                        display_grid_max_80m = float.Parse(val);
                        break;
                    case "display_grid_min_80m":
                        display_grid_min_80m = float.Parse(val);
                        break;
                    case "display_grid_max_60m":
                        display_grid_max_60m = float.Parse(val);
                        break;
                    case "display_grid_min_60m":
                        display_grid_min_60m = float.Parse(val);
                        break;
                    case "display_grid_max_40m":
                        display_grid_max_40m = float.Parse(val);
                        break;
                    case "display_grid_min_40m":
                        display_grid_min_40m = float.Parse(val);
                        break;
                    case "display_grid_max_30m":
                        display_grid_max_30m = float.Parse(val);
                        break;
                    case "display_grid_min_30m":
                        display_grid_min_30m = float.Parse(val);
                        break;
                    case "display_grid_max_20m":
                        display_grid_max_20m = float.Parse(val);
                        break;
                    case "display_grid_min_20m":
                        display_grid_min_20m = float.Parse(val);
                        break;
                    case "display_grid_max_17m":
                        display_grid_max_17m = float.Parse(val);
                        break;
                    case "display_grid_min_17m":
                        display_grid_min_17m = float.Parse(val);
                        break;
                    case "display_grid_max_15m":
                        display_grid_max_15m = float.Parse(val);
                        break;
                    case "display_grid_min_15m":
                        display_grid_min_15m = float.Parse(val);
                        break;
                    case "display_grid_max_12m":
                        display_grid_max_12m = float.Parse(val);
                        break;
                    case "display_grid_min_12m":
                        display_grid_min_12m = float.Parse(val);
                        break;
                    case "display_grid_max_10m":
                        display_grid_max_10m = float.Parse(val);
                        break;
                    case "display_grid_min_10m":
                        display_grid_min_10m = float.Parse(val);
                        break;
                    case "display_grid_max_6m":
                        display_grid_max_6m = float.Parse(val);
                        break;
                    case "display_grid_min_6m":
                        display_grid_min_6m = float.Parse(val);
                        break;
                    case "display_grid_max_wwv":
                        display_grid_max_wwv = float.Parse(val);
                        break;
                    case "display_grid_min_wwv":
                        display_grid_min_wwv = float.Parse(val);
                        break;
                    case "display_grid_max_gen":
                        display_grid_max_gen = float.Parse(val);
                        break;
                    case "display_grid_min_gen":
                        display_grid_min_gen = float.Parse(val);
                        break;
                    case "display_grid_max_xvtr":
                        display_grid_max_xvtr = float.Parse(val);
                        break;
                    case "display_grid_min_xvtr":
                        display_grid_min_xvtr = float.Parse(val);
                        break;
                    case "rx2_display_grid_max_160m":
                        rx2_display_grid_max_160m = float.Parse(val);
                        break;
                    case "rx2_display_grid_min_160m":
                        rx2_display_grid_min_160m = float.Parse(val);
                        break;
                    case "rx2_display_grid_max_80m":
                        rx2_display_grid_max_80m = float.Parse(val);
                        break;
                    case "rx2_display_grid_min_80m":
                        rx2_display_grid_min_80m = float.Parse(val);
                        break;
                    case "rx2_display_grid_max_60m":
                        rx2_display_grid_max_60m = float.Parse(val);
                        break;
                    case "rx2_display_grid_min_60m":
                        rx2_display_grid_min_60m = float.Parse(val);
                        break;
                    case "rx2_display_grid_max_40m":
                        rx2_display_grid_max_40m = float.Parse(val);
                        break;
                    case "rx2_display_grid_min_40m":
                        rx2_display_grid_min_40m = float.Parse(val);
                        break;
                    case "rx2_display_grid_max_30m":
                        rx2_display_grid_max_30m = float.Parse(val);
                        break;
                    case "rx2_display_grid_min_30m":
                        rx2_display_grid_min_30m = float.Parse(val);
                        break;
                    case "rx2_display_grid_max_20m":
                        rx2_display_grid_max_20m = float.Parse(val);
                        break;
                    case "rx2_display_grid_min_20m":
                        rx2_display_grid_min_20m = float.Parse(val);
                        break;
                    case "rx2_display_grid_max_17m":
                        rx2_display_grid_max_17m = float.Parse(val);
                        break;
                    case "rx2_display_grid_min_17m":
                        rx2_display_grid_min_17m = float.Parse(val);
                        break;
                    case "rx2_display_grid_max_15m":
                        rx2_display_grid_max_15m = float.Parse(val);
                        break;
                    case "rx2_display_grid_min_15m":
                        rx2_display_grid_min_15m = float.Parse(val);
                        break;
                    case "rx2_display_grid_max_12m":
                        rx2_display_grid_max_12m = float.Parse(val);
                        break;
                    case "rx2_display_grid_min_12m":
                        rx2_display_grid_min_12m = float.Parse(val);
                        break;
                    case "rx2_display_grid_max_10m":
                        rx2_display_grid_max_10m = float.Parse(val);
                        break;
                    case "rx2_display_grid_min_10m":
                        rx2_display_grid_min_10m = float.Parse(val);
                        break;
                    case "rx2_display_grid_max_6m":
                        rx2_display_grid_max_6m = float.Parse(val);
                        break;
                    case "rx2_display_grid_min_6m":
                        rx2_display_grid_min_6m = float.Parse(val);
                        break;
                    case "rx2_display_grid_max_wwv":
                        rx2_display_grid_max_wwv = float.Parse(val);
                        break;
                    case "rx2_display_grid_min_wwv":
                        rx2_display_grid_min_wwv = float.Parse(val);
                        break;
                    case "rx2_display_grid_max_gen":
                        rx2_display_grid_max_gen = float.Parse(val);
                        break;
                    case "rx2_display_grid_min_gen":
                        rx2_display_grid_min_gen = float.Parse(val);
                        break;
                    case "rx2_display_grid_max_xvtr":
                        rx2_display_grid_max_xvtr = float.Parse(val);
                        break;
                    case "rx2_display_grid_min_xvtr":
                        rx2_display_grid_min_xvtr = float.Parse(val);
                        break;
                    case "Metis_IP_address":
                        NetworkIO.HpSdrHwIpAddress = val;
                        break;
                    case "EthernetHostIPAddress":
                        NetworkIO.EthernetHostIPAddress = val;
                        break;
                    case "infoBar_flip": //MW0LGE_21k9rc4
                        infoBar.CurrentFlip = int.Parse(val);
                        break;
                    case "infoBar_button1":
                        {
                            bool bOk = Enum.TryParse<ucInfoBar.ActionTypes>(val, out ucInfoBar.ActionTypes action);
                            if (bOk)
                                infoBar.Button1Action = action;
                            else
                                infoBar.Button1Action = ucInfoBar.ActionTypes.Blobs;
                        }
                        break;
                    case "infoBar_button2":
                        {
                            bool bOk = Enum.TryParse<ucInfoBar.ActionTypes>(val, out ucInfoBar.ActionTypes action);
                            if (bOk)
                                infoBar.Button2Action = action;
                            else
                                infoBar.Button2Action = ucInfoBar.ActionTypes.ActivePeaks;
                        }
                        break;
                    case "infoBar_splitter_ratio":
                        infoBar.SplitterRatio = float.Parse(val);
                        break;
                    case "auto_start_forms":
                        setAutoStartData(val); //[2.10.3.6]MW0LGE
                        break;
                    case var nam when name.StartsWith("rx1_filters["):
                        start = name.IndexOf("[") + 1;
                        length = name.IndexOf("]") - start;
                        index = Int32.Parse(name.Substring(start, length));

                        start = name.LastIndexOf("[") + 1;
                        length = name.LastIndexOf("]") - start;
                        filter_mode = Int32.Parse(name.Substring(start, length));

                        length = val.IndexOf(":");
                        string n = val.Substring(0, length);

                        if (!val.Contains("|"))
                            val = val.Replace(",", "|");

                        start = val.IndexOf(":") + 2;
                        length = val.IndexOf("|") - start;
                        int low = Int32.Parse(val.Substring(start, length));
                        start = val.IndexOf("|") + 1;
                        int high = Int32.Parse(val.Substring(start));
                        rx1_filters[index].SetFilter((Filter)filter_mode, low, high, n);
                        break;

                    case var nam when name.StartsWith("rx2_filters["):
                        start = name.IndexOf("[") + 1;
                        length = name.IndexOf("]") - start;
                        index = Int32.Parse(name.Substring(start, length));

                        start = name.LastIndexOf("[") + 1;
                        length = name.LastIndexOf("]") - start;
                        filter_mode = Int32.Parse(name.Substring(start, length));

                        length = val.IndexOf(":");
                        n = val.Substring(0, length);

                        if (!val.Contains("|"))
                            val = val.Replace(",", "|");

                        start = val.IndexOf(":") + 2;
                        length = val.IndexOf("|") - start;
                        low = Int32.Parse(val.Substring(start, length));

                        start = val.IndexOf("|") + 1;
                        high = Int32.Parse(val.Substring(start));

                        rx2_filters[index].SetFilter((Filter)filter_mode, low, high, n);
                        break;

                    case var nam when name.StartsWith("mnotchdb"):
                        MNotchDB.Add(MNotch.Parse(val));
                        break;

                    case var nam when name.StartsWith("last_rx1_filter["):
                        start = name.IndexOf("[") + 1;
                        length = name.IndexOf("]") - start;
                        index = Int32.Parse(name.Substring(start, length));
                        rx1_filters[index].LastFilter = (Filter)Enum.Parse(typeof(Filter), val);
                        break;

                    case var nam when name.StartsWith("last_rx2_filter["):
                        start = name.IndexOf("[") + 1;
                        length = name.IndexOf("]") - start;
                        index = Int32.Parse(name.Substring(start, length));
                        rx2_filters[index].LastFilter = (Filter)Enum.Parse(typeof(Filter), val);
                        break;

                    case var nam when name.StartsWith("rx1_preamp_offset["):
                        start = name.IndexOf("[") + 1;
                        length = name.IndexOf("]") - start;
                        index = Int32.Parse(name.Substring(start, length));
                        rx1_preamp_offset[index] = (float)Math.Round(float.Parse(val), 3);
                        break;

                    case var nam when name.StartsWith("diversity_rx1_ref_by_band"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                            diversity_rx1_ref_by_band[i] = Convert.ToBoolean(int.Parse(list[i]));
                        break;

                    // MW0LGE_21k9d - store/recall ZTB
                    case var nam when name.StartsWith("rx1_ztbdata_cf"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                            ztb_data_by_band[0][i].CentreFrequency = double.Parse(list[i]);
                        break;
                    case var nam when name.StartsWith("rx2_ztbdata_cf"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                            ztb_data_by_band[1][i].CentreFrequency = double.Parse(list[i]);
                        break;
                    case var nam when name.StartsWith("rx1_ztbdata_ps"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                            ztb_data_by_band[0][i].PanSliderPosition = int.Parse(list[i]);
                        break;
                    case var nam when name.StartsWith("rx2_ztbdata_ps"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                            ztb_data_by_band[1][i].PanSliderPosition = int.Parse(list[i]);
                        break;
                    case var nam when name.StartsWith("rx1_ztbdata_zs"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                            ztb_data_by_band[0][i].ZoomSliderPosition = int.Parse(list[i]);
                        break;
                    case var nam when name.StartsWith("rx2_ztbdata_zs"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                            ztb_data_by_band[1][i].ZoomSliderPosition = int.Parse(list[i]);
                        break;
                    case var nam when name.StartsWith("rx1_ztbdata_init"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                            ztb_data_by_band[0][i].Initalised = bool.Parse(list[i]);
                        break;
                    case var nam when name.StartsWith("rx2_ztbdata_init"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                            ztb_data_by_band[1][i].Initalised = bool.Parse(list[i]);
                        break;
                    //

                    case var nam when name.StartsWith("rx1_level_table"):
                        start = name.IndexOf("[") + 1;
                        length = name.IndexOf("]") - start;
                        index = int.Parse(name.Substring(start, length));

                        list = val.Split('|');
                        for (int i = 0; i < 3; i++)
                            rx1_level_table[index][i] = (float)Math.Round(float.Parse(list[i]), 3);
                        break;

                    case var nam when name.StartsWith("rx2_level_table"):
                        start = name.IndexOf("[") + 1;
                        length = name.IndexOf("]") - start;
                        index = int.Parse(name.Substring(start, length));

                        list = val.Split('|');
                        for (int i = 0; i < 3; i++)
                            rx2_level_table[index][i] = (float)Math.Round(float.Parse(list[i]), 3);
                        break;

                    case var nam when name.StartsWith("rx1_preamp_by_band"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                            rx1_preamp_by_band[i] = (PreampMode)(int.Parse(list[i]));
                        break;


                    case var nam when name.StartsWith("rx2_preamp_by_band"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                            rx2_preamp_by_band[i] = (PreampMode)(int.Parse(list[i]));
                        break;


                    case var nam when name.StartsWith("rx1_step_attenuator_by_band"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                            setRX1stepAttenuatorForBand((Band)i, int.Parse(list[i]));
                        break;

                    case var nam when name.StartsWith("rx2_step_attenuator_by_band"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                            setRX2stepAttenuatorForBand((Band)i, int.Parse(list[i]));
                        break;

                    case var nam when name.StartsWith("tx_step_attenuator_by_band"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                            setTXstepAttenuatorForBand((Band)i, int.Parse(list[i]));
                        break;

                    case var nam when name.StartsWith("power_by_band"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                        {
                            power_by_band[i] = int.Parse(list[i]);
                        }
                        break;

                    case var nam when name.StartsWith("tunePower_by_band"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                        {
                            tunePower_by_band[i] = int.Parse(list[i]);
                        }
                        break;

                    case var nam when name.StartsWith("limitPower_by_band"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                        {
                            limitPower_by_band[i] = int.Parse(list[i]);
                        }
                        break;

                    case var nam when name.StartsWith("limitTunePower_by_band"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                        {
                            limitTunePower_by_band[i] = int.Parse(list[i]);
                        }
                        break;

                    case var nam when name.StartsWith("fm_tx_offset_by_band_mhz"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                            fm_tx_offset_by_band_mhz[i] = double.Parse(list[i]);
                        break;

                    case var nam when name.StartsWith("rx1_agct_by_band"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                            rx1_agct_by_band[i] = int.Parse(list[i]);
                        break;

                    case var nam when name.StartsWith("rx2_agct_by_band"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                            rx2_agct_by_band[i] = int.Parse(list[i]);
                        break;

                    case var nam when name.StartsWith("rx1_agcm_by_band"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                            rx1_agcm_by_band[i] = (AGCMode)(int.Parse(list[i]));
                        break;

                    case var nam when name.StartsWith("rx2_agcm_by_band"):
                        list = val.Split('|');
                        if (list.Length != (int)Band.LAST) continue; //[2.10.3.5]MW0LGE
                        for (int i = 0; i < (int)Band.LAST; i++)
                            rx2_agcm_by_band[i] = (AGCMode)(int.Parse(list[i]));
                        break;

                    case var nam when name.StartsWith("rx_meter_cal_offset_by_radio"):
                        list = val.Split('|');
                        int numVals = list.Length;
                        if (numVals == (int)HPSDRModel.LAST)  //-W2PA  The number of rig types in the imported DB matches the number in this version
                        {
                            for (int i = 0; i < (int)HPSDRModel.LAST; i++)
                            {
                                rx_meter_cal_offset_by_radio[i] = float.Parse(list[i]);
                            }
                        }  //-W2PA  else the number has changed so don't import, leave the defaults alone
                         ;
                        break;

                    case var nam when name.StartsWith("rx_display_cal_offset_by_radio"):
                        list = val.Split('|');
                        numVals = list.Length;
                        if (numVals == (int)HPSDRModel.LAST)  //-W2PA  The number of rig types in the imported DB matches the number in this version
                        {
                            for (int i = 0; i < (int)HPSDRModel.LAST; i++)
                            {
                                rx_display_cal_offset_by_radio[i] = float.Parse(list[i]);
                            }
                        }  //-W2PA  else the number has changed so don't import, leave the defaults alone
                            ;
                        break;
                    default:
                        // add to the ToDoList
                        toDoList.Add(new KeyValuePair<string, string>(name, val));
                        break;
                }
            }

            // MW0LGE_21a
            // I have moved all this  out of the loop up above, so settings etc are read in
            // before click/change/scroll events actually start happening, otherwise the events will be
            // running on nonsensical data.
            foreach (KeyValuePair<string, string> kvp in toDoList)             // string is in the format "name,value"
            {
                string name = kvp.Key;
                string val = kvp.Value;

                switch (name)
                {
                    case "chkNR_checkstate":
                        chkNR.CheckState = (CheckState)(Enum.Parse(typeof(CheckState), val));
                        break;
                    case "chkRX2NR_checkstate":
                        chkRX2NR.CheckState = (CheckState)(Enum.Parse(typeof(CheckState), val));
                        break;
                    case "chkNB_checkstate":
                        chkNB.CheckState = (CheckState)(Enum.Parse(typeof(CheckState), val));
                        break;
                    case "chkRX2NB_checkstate":
                        chkRX2NB.CheckState = (CheckState)(Enum.Parse(typeof(CheckState), val));
                        break;
                    case "chkQSK_checkstate":
                        chkQSK.CheckState = (CheckState)(Enum.Parse(typeof(CheckState), val));
                        break;

                    case "chkSquelch_checkstate":
                        chkSquelch.CheckState = (CheckState)(Enum.Parse(typeof(CheckState), val));
                        break;
                    case "chkRX2Squelch_checkstate":
                        chkRX2Squelch.CheckState = (CheckState)(Enum.Parse(typeof(CheckState), val));
                        break;

                    case var nam when name.StartsWith("chk"):
                        if (ctrls.ContainsKey(name)) ((CheckBoxTS)ctrls[name]).Checked = bool.Parse(val);
                        break;

                    case var nam when name.StartsWith("combo"):
                        if (ctrls.ContainsKey(name)) ((ComboBoxTS)ctrls[name]).Text = val;
                        break;

                    case var nam when name.StartsWith("ud"):
                        if (ctrls.ContainsKey(name))
                        {
                            NumericUpDownTS c = (NumericUpDownTS)ctrls[name];
                            decimal dnum = decimal.Parse(val);
                            if (dnum > c.Maximum) dnum = c.Maximum;
                            else if (dnum < c.Minimum) dnum = c.Minimum;
                            c.Value = dnum;
                        }
                        break;

                    case var nam when name.StartsWith("rad"):
                        if (ctrls.ContainsKey(name))
                        {
                            RadioButtonTS c = (RadioButtonTS)ctrls[name];
                            if (!val.ToLower().Equals("true") && !val.ToLower().Equals("false")) val = "True";
                            c.Checked = bool.Parse(val);
                        }
                        break;

                    case var nam when name.StartsWith("txt"):
                        if (ctrls.ContainsKey(name)) ((TextBoxTS)ctrls[name]).Text = val;
                        break;

                    case var nam when name.StartsWith("tb"):
                        if (ctrls.ContainsKey(name))
                        {
                            TrackBarTS c = (TrackBarTS)ctrls[name];
                            int num = int.Parse(val);
                            if (num > c.Maximum) num = c.Maximum;
                            if (num < c.Minimum) num = c.Minimum;
                            c.Value = num;
                        }
                        break;

                    case var nam when name.StartsWith("ptb"):
                        if (ctrls.ContainsKey(name)) ((PrettyTrackBar)ctrls[name]).Value = Int32.Parse(val);
                        break;
                }
            }

            //MW0LGE_21c
            //all this is down here now, so that we have the correct centers
            //also, VFOA/B freq assignments do not update the centre frequency anymore
            //if in the initiasation state
            if (click_tune_display)
            {
                CentreFrequency = dRX1_centre_freq;
            }
            else
            {
                CentreFrequency = dVFOAFreq;
            }
            if (click_tune_rx2_display)
            {
                CentreRX2Frequency = dRX2_centre_freq;
            }
            else
            {
                CentreRX2Frequency = dVFOBFreq;
            }
            VFOAFreq = dVFOAFreq;
            VFOBFreq = dVFOBFreq;

            if (bNeedUpdate)
            {
                this.Size = szConsoleSize;
                this.Location = pConsoleLocation;

                if (_iscollapsed)
                {
                    this.CollapseDisplay(false);
                }
                else
                {
                    initializing = false;
                    this.ExpandDisplay(false);
                    initializing = true;
                }

                Common.ForceFormOnScreen(this);
                Common.ForceFormOnScreen(SetupForm);

                //MW0LGE_21d restore window state
                switch (m_WindowState)
                {
                    case FormWindowState.Minimized:
                        this.WindowState = FormWindowState.Normal;
                        break;
                    case FormWindowState.Maximized:
                        this.WindowState = FormWindowState.Maximized;
                        break;
                    default:
                        this.WindowState = FormWindowState.Normal;
                        break;
                }
            }

            return;
        }

        public FilterPreset[] rx1_filters = new FilterPreset[(int)DSPMode.LAST];
        public FilterPreset[] rx2_filters = new FilterPreset[(int)DSPMode.LAST];

        private void InitFilterPresets()
        {
            InitFilterPresets(rx1_filters);
            InitFilterPresets(rx2_filters);
        }

        private void InitFilterPresets(FilterPreset[] preset)
        {
            // used to initialize all the filter variables

            for (int m = (int)DSPMode.FIRST + 1; m < (int)DSPMode.LAST; m++)
            {
                preset[m] = new FilterPreset();
                for (Filter f = Filter.F1; f != Filter.LAST; f++)
                {
                    switch (m)
                    {
                        case (int)DSPMode.LSB:
                            switch (f)
                            {
                                case Filter.F1:
                                    preset[m].SetFilter(f, -5100, -100, "5.0k");
                                    break;
                                case Filter.F2:
                                    preset[m].SetFilter(f, -4500, -100, "4.4k");
                                    break;
                                case Filter.F3:
                                    preset[m].SetFilter(f, -3900, -100, "3.8k");
                                    break;
                                case Filter.F4:
                                    preset[m].SetFilter(f, -3400, -100, "3.3k");
                                    break;
                                case Filter.F5:
                                    preset[m].SetFilter(f, -3000, -100, "2.9k");
                                    break;
                                case Filter.F6:
                                    preset[m].SetFilter(f, -2800, -100, "2.7k");
                                    break;
                                case Filter.F7:
                                    preset[m].SetFilter(f, -2500, -100, "2.4k");
                                    break;
                                case Filter.F8:
                                    preset[m].SetFilter(f, -2200, -100, "2.1k");
                                    break;
                                case Filter.F9:
                                    preset[m].SetFilter(f, -1900, -100, "1.8k");
                                    break;
                                case Filter.F10:
                                    preset[m].SetFilter(f, -1100, -100, "1.0k");
                                    break;
                                case Filter.VAR1:
                                    preset[m].SetFilter(f, -2800, -100, "Var 1");
                                    break;
                                case Filter.VAR2:
                                    preset[m].SetFilter(f, -2800, -100, "Var 2");
                                    break;
                            }
                            preset[m].LastFilter = Filter.F5;
                            break;
                        case (int)DSPMode.USB:
                            switch (f)
                            {
                                case Filter.F1:
                                    preset[m].SetFilter(f, 100, 5100, "5.0k");
                                    break;
                                case Filter.F2:
                                    preset[m].SetFilter(f, 100, 4500, "4.4k");
                                    break;
                                case Filter.F3:
                                    preset[m].SetFilter(f, 100, 3900, "3.8k");
                                    break;
                                case Filter.F4:
                                    preset[m].SetFilter(f, 100, 3400, "3.3k");
                                    break;
                                case Filter.F5:
                                    preset[m].SetFilter(f, 100, 3000, "2.9k");
                                    break;
                                case Filter.F6:
                                    preset[m].SetFilter(f, 100, 2800, "2.7k");
                                    break;
                                case Filter.F7:
                                    preset[m].SetFilter(f, 100, 2500, "2.4k");
                                    break;
                                case Filter.F8:
                                    preset[m].SetFilter(f, 100, 2200, "2.1k");
                                    break;
                                case Filter.F9:
                                    preset[m].SetFilter(f, 100, 1900, "1.8k");
                                    break;
                                case Filter.F10:
                                    preset[m].SetFilter(f, 100, 1100, "1.0k");
                                    break;
                                case Filter.VAR1:
                                    preset[m].SetFilter(f, 100, 2800, "Var 1");
                                    break;
                                case Filter.VAR2:
                                    preset[m].SetFilter(f, 100, 2800, "Var 2");
                                    break;
                            }
                            preset[m].LastFilter = Filter.F5;
                            break;
                        case (int)DSPMode.DIGL:
                            switch (f)
                            {
                                case Filter.F1:
                                    preset[m].SetFilter(f, -digl_click_tune_offset - 1500, -digl_click_tune_offset + 1500, "3.0k");
                                    break;
                                case Filter.F2:
                                    preset[m].SetFilter(f, -digl_click_tune_offset - 1250, -digl_click_tune_offset + 1250, "2.5k");
                                    break;
                                case Filter.F3:
                                    preset[m].SetFilter(f, -digl_click_tune_offset - 1000, -digl_click_tune_offset + 1000, "2.0k");
                                    break;
                                case Filter.F4:
                                    preset[m].SetFilter(f, -digl_click_tune_offset - 750, -digl_click_tune_offset + 750, "1.5k");
                                    break;
                                case Filter.F5:
                                    preset[m].SetFilter(f, -digl_click_tune_offset - 500, -digl_click_tune_offset + 500, "1.0k");
                                    break;
                                case Filter.F6:
                                    preset[m].SetFilter(f, -digl_click_tune_offset - 400, -digl_click_tune_offset + 400, "800");
                                    break;
                                case Filter.F7:
                                    preset[m].SetFilter(f, -digl_click_tune_offset - 300, -digl_click_tune_offset + 300, "600");
                                    break;
                                case Filter.F8:
                                    preset[m].SetFilter(f, -digl_click_tune_offset - 150, -digl_click_tune_offset + 150, "300");
                                    break;
                                case Filter.F9:
                                    preset[m].SetFilter(f, -digl_click_tune_offset - 75, -digl_click_tune_offset + 75, "150");
                                    break;
                                case Filter.F10:
                                    preset[m].SetFilter(f, -digl_click_tune_offset - 38, -digl_click_tune_offset + 38, "75");
                                    break;
                                case Filter.VAR1:
                                    preset[m].SetFilter(f, -digl_click_tune_offset - 400, -digl_click_tune_offset + 400, "Var 1");
                                    break;
                                case Filter.VAR2:
                                    preset[m].SetFilter(f, -digl_click_tune_offset - 400, -digl_click_tune_offset + 400, "Var 2");
                                    break;
                            }
                            preset[m].LastFilter = Filter.F5;
                            break;
                        case (int)DSPMode.DIGU:
                            switch (f)
                            {
                                case Filter.F1:
                                    preset[m].SetFilter(f, digu_click_tune_offset - 1500, digu_click_tune_offset + 1500, "3.0k");
                                    break;
                                case Filter.F2:
                                    preset[m].SetFilter(f, digu_click_tune_offset - 1250, digu_click_tune_offset + 1250, "2.5k");
                                    break;
                                case Filter.F3:
                                    preset[m].SetFilter(f, digu_click_tune_offset - 1000, digu_click_tune_offset + 1000, "2.0k");
                                    break;
                                case Filter.F4:
                                    preset[m].SetFilter(f, digu_click_tune_offset - 750, digu_click_tune_offset + 750, "1.5k");
                                    break;
                                case Filter.F5:
                                    preset[m].SetFilter(f, digu_click_tune_offset - 500, digu_click_tune_offset + 500, "1.0k");
                                    break;
                                case Filter.F6:
                                    preset[m].SetFilter(f, digu_click_tune_offset - 400, digu_click_tune_offset + 400, "800");
                                    break;
                                case Filter.F7:
                                    preset[m].SetFilter(f, digu_click_tune_offset - 300, digu_click_tune_offset + 300, "600");
                                    break;
                                case Filter.F8:
                                    preset[m].SetFilter(f, digu_click_tune_offset - 150, digu_click_tune_offset + 150, "300");
                                    break;
                                case Filter.F9:
                                    preset[m].SetFilter(f, digu_click_tune_offset - 75, digu_click_tune_offset + 75, "150");
                                    break;
                                case Filter.F10:
                                    preset[m].SetFilter(f, digu_click_tune_offset - 38, digu_click_tune_offset + 38, "75");
                                    break;
                                case Filter.VAR1:
                                    preset[m].SetFilter(f, digu_click_tune_offset - 400, digu_click_tune_offset + 400, "Var 1");
                                    break;
                                case Filter.VAR2:
                                    preset[m].SetFilter(f, digu_click_tune_offset - 400, digu_click_tune_offset + 400, "Var 2");
                                    break;
                            }
                            preset[m].LastFilter = Filter.F5;
                            break;
                        case (int)DSPMode.CWL:
                            switch (f)
                            {
                                case Filter.F1:
                                    preset[m].SetFilter(f, -cw_pitch - 500, -cw_pitch + 500, "1.0k");
                                    break;
                                case Filter.F2:
                                    preset[m].SetFilter(f, -cw_pitch - 400, -cw_pitch + 400, "800");
                                    break;
                                case Filter.F3:
                                    preset[m].SetFilter(f, -cw_pitch - 300, -cw_pitch + 300, "600");
                                    break;
                                case Filter.F4:
                                    preset[m].SetFilter(f, -cw_pitch - 250, -cw_pitch + 250, "500");
                                    break;
                                case Filter.F5:
                                    preset[m].SetFilter(f, -cw_pitch - 200, -cw_pitch + 200, "400");
                                    break;
                                case Filter.F6:
                                    preset[m].SetFilter(f, -cw_pitch - 125, -cw_pitch + 125, "250");
                                    break;
                                case Filter.F7:
                                    preset[m].SetFilter(f, -cw_pitch - 75, -cw_pitch + 75, "150");
                                    break;
                                case Filter.F8:
                                    preset[m].SetFilter(f, -cw_pitch - 50, -cw_pitch + 50, "100");
                                    break;
                                case Filter.F9:
                                    preset[m].SetFilter(f, -cw_pitch - 25, -cw_pitch + 25, "50");
                                    break;
                                case Filter.F10:
                                    preset[m].SetFilter(f, -cw_pitch - 13, -cw_pitch + 13, "25");
                                    break;
                                case Filter.VAR1:
                                    preset[m].SetFilter(f, -cw_pitch - 250, -cw_pitch + 250, "Var 1");
                                    break;
                                case Filter.VAR2:
                                    preset[m].SetFilter(f, -cw_pitch - 250, -cw_pitch + 250, "Var 2");
                                    break;
                            }
                            preset[m].LastFilter = Filter.F5;
                            break;
                        case (int)DSPMode.CWU:
                            switch (f)
                            {
                                case Filter.F1:
                                    preset[m].SetFilter(f, cw_pitch - 500, cw_pitch + 500, "1.0k");
                                    break;
                                case Filter.F2:
                                    preset[m].SetFilter(f, cw_pitch - 400, cw_pitch + 400, "800");
                                    break;
                                case Filter.F3:
                                    preset[m].SetFilter(f, cw_pitch - 300, cw_pitch + 300, "600");
                                    break;
                                case Filter.F4:
                                    preset[m].SetFilter(f, cw_pitch - 250, cw_pitch + 250, "500");
                                    break;
                                case Filter.F5:
                                    preset[m].SetFilter(f, cw_pitch - 200, cw_pitch + 200, "400");
                                    break;
                                case Filter.F6:
                                    preset[m].SetFilter(f, cw_pitch - 125, cw_pitch + 125, "250");
                                    break;
                                case Filter.F7:
                                    preset[m].SetFilter(f, cw_pitch - 75, cw_pitch + 75, "150");
                                    break;
                                case Filter.F8:
                                    preset[m].SetFilter(f, cw_pitch - 50, cw_pitch + 50, "100");
                                    break;
                                case Filter.F9:
                                    preset[m].SetFilter(f, cw_pitch - 25, cw_pitch + 25, "50");
                                    break;
                                case Filter.F10:
                                    preset[m].SetFilter(f, cw_pitch - 13, cw_pitch + 13, "25");
                                    break;
                                case Filter.VAR1:
                                    preset[m].SetFilter(f, cw_pitch - 250, cw_pitch + 250, "Var 1");
                                    break;
                                case Filter.VAR2:
                                    preset[m].SetFilter(f, cw_pitch - 250, cw_pitch + 250, "Var 2");
                                    break;
                            }
                            preset[m].LastFilter = Filter.F5;
                            break;
                        case (int)DSPMode.AM:
                            switch (f)
                            {
                                case Filter.F1:
                                    preset[m].SetFilter(f, -10000, 10000, "20k");
                                    break;
                                case Filter.F2:
                                    preset[m].SetFilter(f, -9000, 9000, "18k");
                                    break;
                                case Filter.F3:
                                    preset[m].SetFilter(f, -8000, 8000, "16k");
                                    break;
                                case Filter.F4:
                                    preset[m].SetFilter(f, -6000, 6000, "12k");
                                    break;
                                case Filter.F5:
                                    preset[m].SetFilter(f, -5000, 5000, "10k");
                                    break;
                                case Filter.F6:
                                    preset[m].SetFilter(f, -4500, 4500, "9.0k");
                                    break;
                                case Filter.F7:
                                    preset[m].SetFilter(f, -4000, 4000, "8.0k");
                                    break;
                                case Filter.F8:
                                    preset[m].SetFilter(f, -3500, 3500, "7.0k");
                                    break;
                                case Filter.F9:
                                    preset[m].SetFilter(f, -3000, 3000, "6.0k");
                                    break;
                                case Filter.F10:
                                    preset[m].SetFilter(f, -2500, 2500, "5.0k");
                                    break;
                                case Filter.VAR1:
                                    preset[m].SetFilter(f, -3000, 3000, "Var 1");
                                    break;
                                case Filter.VAR2:
                                    preset[m].SetFilter(f, -3000, 3000, "Var 2");
                                    break;
                            }
                            preset[m].LastFilter = Filter.F5;
                            break;
                        case (int)DSPMode.SAM:
                            switch (f)
                            {
                                case Filter.F1:
                                    preset[m].SetFilter(f, -10000, 10000, "20k");
                                    break;
                                case Filter.F2:
                                    preset[m].SetFilter(f, -9000, 9000, "18k");
                                    break;
                                case Filter.F3:
                                    preset[m].SetFilter(f, -8000, 8000, "16k");
                                    break;
                                case Filter.F4:
                                    preset[m].SetFilter(f, -6000, 6000, "12k");
                                    break;
                                case Filter.F5:
                                    preset[m].SetFilter(f, -5000, 5000, "10k");
                                    break;
                                case Filter.F6:
                                    preset[m].SetFilter(f, -4500, 4500, "9.0k");
                                    break;
                                case Filter.F7:
                                    preset[m].SetFilter(f, -4000, 4000, "8.0k");
                                    break;
                                case Filter.F8:
                                    preset[m].SetFilter(f, -3500, 3500, "7.0k");
                                    break;
                                case Filter.F9:
                                    preset[m].SetFilter(f, -3000, 3000, "6.0k");
                                    break;
                                case Filter.F10:
                                    preset[m].SetFilter(f, -2500, 2500, "5.0k");
                                    break;
                                case Filter.VAR1:
                                    preset[m].SetFilter(f, -3000, 3000, "Var 1");
                                    break;
                                case Filter.VAR2:
                                    preset[m].SetFilter(f, -3000, 3000, "Var 2");
                                    break;
                            }
                            preset[m].LastFilter = Filter.F5;
                            break;
                        case (int)DSPMode.DSB:
                            switch (f)
                            {
                                case Filter.F1:
                                    preset[m].SetFilter(f, -8000, 8000, "16k");
                                    break;
                                case Filter.F2:
                                    preset[m].SetFilter(f, -6000, 6000, "12k");
                                    break;
                                case Filter.F3:
                                    preset[m].SetFilter(f, -5000, 5000, "10k");
                                    break;
                                case Filter.F4:
                                    preset[m].SetFilter(f, -4000, 4000, "8.0k");
                                    break;
                                case Filter.F5:
                                    preset[m].SetFilter(f, -3300, 3300, "6.6k");
                                    break;
                                case Filter.F6:
                                    preset[m].SetFilter(f, -2600, 2600, "5.2k");
                                    break;
                                case Filter.F7:
                                    preset[m].SetFilter(f, -2000, 2000, "4.0k");
                                    break;
                                case Filter.F8:
                                    preset[m].SetFilter(f, -1550, 1550, "3.1k");
                                    break;
                                case Filter.F9:
                                    preset[m].SetFilter(f, -1450, 1450, "2.9k");
                                    break;
                                case Filter.F10:
                                    preset[m].SetFilter(f, -1200, 1200, "2.4k");
                                    break;
                                case Filter.VAR1:
                                    preset[m].SetFilter(f, -3300, 3300, "Var 1");
                                    break;
                                case Filter.VAR2:
                                    preset[m].SetFilter(f, -3300, 3300, "Var 2");
                                    break;
                            }
                            preset[m].LastFilter = Filter.F5;
                            break;
                        default:
                            preset[m].LastFilter = Filter.NONE;
                            break;
                    }
                }
            }
        }

        private void InitDisplayModes()
        {
            // populate the display mode list
            for (DisplayMode dm = DisplayMode.FIRST + 1; dm < DisplayMode.LAST; dm++)
            {
                string s = dm.ToString().ToLower();
                s = s.Substring(0, 1).ToUpper() + s.Substring(1, s.Length - 1);
                comboDisplayMode.Items.Add(s);
            }
        }

        private void InitAGCModes()
        {
            // populate the AGC mode list
            for (AGCMode agc = AGCMode.FIRST + 1; agc < AGCMode.LAST; agc++)
            {
                string s = agc.ToString().ToLower();
                s = s.Substring(0, 1).ToUpper() + s.Substring(1, s.Length - 1);
                comboAGC.Items.Add(s);
            }

            for (AGCMode agc = AGCMode.FIRST + 1; agc < AGCMode.LAST; agc++)
            {
                string s = agc.ToString().ToLower();
                s = s.Substring(0, 1).ToUpper() + s.Substring(1, s.Length - 1);
                comboRX2AGC.Items.Add(s);
            }
        }

        private void InitMultiMeterModes()
        {
            comboMeterRXMode.Items.Add("Signal");
            comboMeterRXMode.Items.Add("Sig Avg");
            comboMeterRXMode.Items.Add("ADC L");
            comboMeterRXMode.Items.Add("ADC R");
            comboMeterRXMode.Items.Add("ADC2 L");
            comboMeterRXMode.Items.Add("ADC2 R");
            comboMeterRXMode.Items.Add("Off");

            comboRX2MeterMode.Items.Add("Signal");
            comboRX2MeterMode.Items.Add("Sig Avg");
            comboRX2MeterMode.Items.Add("ADC L");
            comboRX2MeterMode.Items.Add("ADC R");
            comboRX2MeterMode.Items.Add("ADC2 L");
            comboRX2MeterMode.Items.Add("ADC2 R");
            comboRX2MeterMode.Items.Add("Off");

            comboMeterTXMode.Items.Add("Fwd Pwr");
            comboMeterTXMode.Items.Add("Mic");
            comboMeterTXMode.Items.Add("EQ");
            comboMeterTXMode.Items.Add("Leveler");
            comboMeterTXMode.Items.Add("Lev Gain");
            comboMeterTXMode.Items.Add("CFC");
            comboMeterTXMode.Items.Add("CFC Comp");
            comboMeterTXMode.Items.Add("COMP");
            comboMeterTXMode.Items.Add("ALC");
            comboMeterTXMode.Items.Add("ALC Comp");
            comboMeterTXMode.Items.Add("ALC Group"); //MW0LGE
            comboMeterTXMode.Items.Add("Off");
        }

        private void DisableAllFilters()
        {
            foreach (Control c in panelFilter.Controls)
            {
                if (c.GetType() == typeof(RadioButtonTS))
                {
                    c.Enabled = false;
                }
            }
            filterToolStripMenuItem.Enabled = false;
        }

        private void DisableAllRX2Filters()
        {
            foreach (Control c in panelRX2Filter.Controls)
            {
                if (c.GetType() == typeof(RadioButtonTS))
                {
                    c.Enabled = false;
                }
            }
        }

        private void EnableAllFilters()
        {
            foreach (Control c in panelFilter.Controls)
            {
                if (c.GetType() == typeof(RadioButtonTS))
                {
                    c.Enabled = true;

                    if (c.BackColor == vfo_text_dark_color)
                    {
                        c.BackColor = button_selected_color;
                    }
                }
            }
            filterToolStripMenuItem.Enabled = true;
        }

        private void EnableAllRX2Filters()
        {
            foreach (Control c in panelRX2Filter.Controls)
            {
                if (c.GetType() == typeof(RadioButtonTS))
                {
                    c.Enabled = true;

                    if (c.BackColor == vfo_text_dark_color)
                    {
                        c.BackColor = button_selected_color;
                    }
                }
            }
        }

        private void DisableAllBands()
        {
            foreach (Control c in panelBandHF.Controls)
            {
                c.Enabled = false;

                if (c is RadioButtonTS b)
                {
                    if (b.BackColor == button_selected_color)
                    {
                        b.BackColor = vfo_text_dark_color;
                    }
                }
            }

            foreach (Control c in panelBandVHF.Controls)
            {
                c.Enabled = false;

                if (c is RadioButtonTS b)
                {
                    if (b.BackColor == button_selected_color)
                    {
                        b.BackColor = vfo_text_dark_color;
                    }
                }
            }

            foreach (Control c in panelBandGEN.Controls)
            {
                c.Enabled = false;

                if (c is RadioButtonTS b)
                {
                    if (b.BackColor == button_selected_color)
                    {
                        b.BackColor = vfo_text_dark_color;
                    }
                }
            }

        }


        private void EnableAllBands()
        {
            foreach (Control c in panelBandHF.Controls)
            {
                if (c is RadioButtonTS b)
                {
                    b.Enabled = c != radBand2 || XVTRPresent;

                    if (b.BackColor == vfo_text_dark_color)
                        b.BackColor = button_selected_color;
                }
                else c.Enabled = true;
            }

            foreach (Control c in panelBandVHF.Controls)
            {
                if (c is RadioButtonTS b)
                {
                    if (b.Name == "panelBandHF")
                        b.Enabled = true;
                    else
                    {
                        int index = Int32.Parse(b.Name.Substring(10));
                        if (XVTRForm.GetEnabled(index))
                            b.Enabled = true;
                    }

                    if (b.BackColor == vfo_text_dark_color)
                        b.BackColor = button_selected_color;
                }
                else c.Enabled = true;
            }

            foreach (Control c in panelBandGEN.Controls) // ke9ns add
            {
                if (c is RadioButtonTS b)
                {
                    b.Enabled = true;

                    if (b.BackColor == vfo_text_dark_color) b.BackColor = button_selected_color;
                }
                else
                {
                    c.Enabled = true;
                }
            }

        }

        private void DisableAllModes()
        {
            foreach (RadioButtonTS r in panelMode.Controls)
            {
                r.Enabled = false;
                if (r.BackColor == button_selected_color)
                    r.BackColor = vfo_text_dark_color;
            }
        }

        private void EnableAllModes()
        {
            foreach (RadioButtonTS r in panelMode.Controls)
            {
                if (!string.IsNullOrEmpty(r.Text))
                    r.Enabled = true;
                if (r.BackColor == vfo_text_dark_color)
                    r.BackColor = button_selected_color;
            }
        }

        private void GetVFOCharWidth()
        {
            // This function calculates the pixel width of the VFO display.
            // This information is used for mouse wheel hover tuning.

            Graphics g = txtVFOAFreq.CreateGraphics();

            SizeF size = g.MeasureString("0", txtVFOAFreq.Font, 1000, StringFormat.GenericTypographic);
            vfo_char_width = (int)Math.Round(size.Width - 2.0f, 0);	// subtract 2 since measure string includes 1 pixel border on each side
            float float_char_width = size.Width - 2.0f;

            size = g.MeasureString("00", txtVFOAFreq.Font, 1000, StringFormat.GenericTypographic);
            vfo_char_space = (int)Math.Round(size.Width - 2.0f - 2 * float_char_width, 0);

            size = g.MeasureString(separator, txtVFOAFreq.Font, 1000, StringFormat.GenericTypographic);
            vfo_decimal_width = (int)(size.Width - 2.0f);

            size = g.MeasureString("0" + separator + "0", txtVFOAFreq.Font, 1000, StringFormat.GenericTypographic);
            vfo_decimal_space = (int)Math.Round(size.Width - 2.0f - 2 * float_char_width, 0);

            size = g.MeasureString("1234.678901", txtVFOAFreq.Font, 1000, StringFormat.GenericTypographic);
            vfo_pixel_offset = (int)Math.Round(size.Width - 2.0f, 0);

            size = g.MeasureString("0", txtVFOALSD.Font, 1000, StringFormat.GenericTypographic);
            vfo_small_char_width = (int)Math.Round(size.Width - 2.0f, 0);
            float_char_width = size.Width - 2.0f;

            size = g.MeasureString("00", txtVFOALSD.Font, 1000, StringFormat.GenericTypographic);
            vfo_small_char_space = (int)Math.Round(size.Width - 2.0f - 2 * float_char_width, 0);

            g.Dispose();
        }

        private void GetVFOSubCharWidth()
        {
            // This function calculates the pixel width of the VFO display.
            // This information is used for mouse wheel hover tuning.

            Graphics g = txtVFOABand.CreateGraphics();

            SizeF size = g.MeasureString("0", txtVFOABand.Font, 1000, StringFormat.GenericTypographic);
            vfo_sub_char_width = (int)Math.Round(size.Width - 2.0f, 0);	// subtract 2 since measure string includes 1 pixel border on each side
            float float_char_width = size.Width - 2.0f;

            size = g.MeasureString("00", txtVFOABand.Font, 1000, StringFormat.GenericTypographic);
            vfo_sub_char_space = (int)Math.Round(size.Width - 2.0f - 2 * float_char_width, 0);

            size = g.MeasureString(separator, txtVFOABand.Font, 1000, StringFormat.GenericTypographic);
            vfo_sub_decimal_width = (int)(size.Width - 2.0f);

            size = g.MeasureString("0" + separator + "0", txtVFOABand.Font, 1000, StringFormat.GenericTypographic);
            vfo_sub_decimal_space = (int)Math.Round(size.Width - 2.0f - 2 * float_char_width, 0);

            size = g.MeasureString("1234.678901", txtVFOABand.Font, 1000, StringFormat.GenericTypographic);
            vfo_sub_pixel_offset = (int)Math.Round(size.Width - 2.0f, 0);

            g.Dispose();
        }

        private bool m_bSetBandRunning = false; // so we know if any events raised are caused by SetBand
        public void SetBand(string mode, string filter, double freq, bool CTUN, int ZoomFactor, double CenterFreq)
        {
            //MW0LGE_21d
            Band oldBand = RX1Band;
            DSPMode oldMode = RX1DSPMode;
            Filter oldFilter = RX1Filter;
            double oldFreq = VFOAFreq;
            double oldCentreFreq = CentreFrequency;
            bool oldCtun = ClickTuneDisplay;
            int oldZoomSlider = ptbDisplayZoom.Value;
            m_bSetBandRunning = true;
            //

            // These are needed for managing QSK when band changes also trigger mode changes.
            RX1_band_change = BandByFreq(freq, tx_xvtr_index, current_region);
            qsk_band_changing = true;

            // Set mode, filter, and frequency according to passed parameters

            RX1DSPMode = (DSPMode)Enum.Parse(typeof(DSPMode), mode, true);

            //[2.10.3.6]MW0LGE moved after mode
            if (rx1_dsp_mode != DSPMode.DRM &&
                rx1_dsp_mode != DSPMode.SPEC)
            {
                RX1Filter = (Filter)Enum.Parse(typeof(Filter), filter, true);
            }

            ClickTuneDisplay = false;                               // Set CTUN off to restore center frequency - G3OQD
            chkFWCATU.Checked = ClickTuneDisplay;

            ptbDisplayZoom.Value = ZoomFactor;
            ptbDisplayZoom_Scroll(this, EventArgs.Empty);

            //MW0LGE_21c
            //it repositions everything at centre frequency by setting the CF and then setting VFOA to that CF
            //Lower down VFAFreq is then assigned to the required frequency
            if (CTUN)
            {
                CentreFrequency = CenterFreq;                      // Restore centre frequency if CTUN enabled - G3OQD
                VFOAFreq = CentreFrequency;
            }

            //[2.10.3.6]MW0LGE moved after mode
            //if (rx1_dsp_mode != DSPMode.DRM &&
            //    rx1_dsp_mode != DSPMode.SPEC)
            //{
            //    RX1Filter = (Filter)Enum.Parse(typeof(Filter), filter, true);
            //}

            ClickTuneDisplay = CTUN;
            chkFWCATU.Checked = ClickTuneDisplay;
            VFOAFreq = freq;                                       // Restore actual receive frequency after CTUN status restored - G3OQD         

            // Continuation of QSK-related band/mode-change management - see also QSKEnabled()
            qsk_band_changing = false;
            if (RX1_band_change != oldBand) // actual band change, not just rotating the stack
            {
                if (CurrentBreakInMode == BreakIn.QSK && !QSKEnabled) // We're changing from QSK off to on due to a mode change
                {
                    QSKEnabled = true; // complete the postponed change started in SetRX1Mode() via QSKEnabled()                  
                }
                else if (!(CurrentBreakInMode == BreakIn.QSK) && QSKEnabled) // We're changing from QSK on to off due to a mode change
                {
                    rx1_agcm_by_band[(int)oldBand] = non_qsk_agc;  // was set on the old band where it was on                     
                    non_qsk_agc = rx1_agcm_by_band[(int)RX1_band_change];
                    QSKEnabled = false;  // complete the postponed change started in SetRX1Mode() via QSKEnabled() 
                }
                else if (CurrentBreakInMode == BreakIn.QSK && QSKEnabled) // CW mode to CW mode with QSK on 
                {
                    rx1_agcm_by_band[(int)oldBand] = non_qsk_agc;  // was set on the old band where it was on
                    non_qsk_agc = rx1_agcm_by_band[(int)RX1_band_change];
                    RX1AGCMode = AGCMode.CUSTOM;
                    // don't need to turn QSK on - it's already on
                }
                else if (!(CurrentBreakInMode == BreakIn.QSK) && !QSKEnabled) // Either CW to CW or non-CW to non-CW, with QSK off
                {
                    RX1AGCMode = rx1_agcm_by_band[(int)RX1_band_change];
                }
            }
            else // just rotating the stack without changing bands
            {
                if (CurrentBreakInMode == BreakIn.QSK && !QSKEnabled) // We're changing from QSK off to on due to a mode change
                {
                    QSKEnabled = true; // complete the postponed change started in SetRX1Mode() via QSKEnabled()                  
                }
                else if (!(CurrentBreakInMode == BreakIn.QSK) && QSKEnabled) // We're changing from QSK on to off due to a mode change
                {
                    QSKEnabled = false;  // complete the postponed change started in SetRX1Mode() via QSKEnabled() 
                }
                else if (CurrentBreakInMode == BreakIn.QSK && QSKEnabled) // CW mode to CW mode with QSK on 
                {
                    ; // don't need to turn QSK on - it's already on
                }
                if (RX1DSPMode != DSPMode.CWL && RX1DSPMode != DSPMode.CWU && !QSKEnabled)
                {
                    RX1AGCMode = non_qsk_agc;
                }
            }

            //MW0LGE_21d3 setting the background of buttons, much like the mode buttons, but was totally forgotten here
            RadioButtonTS r = getButtonForBand(oldBand);
            r.BackColor = SystemColors.Control;
            r = getButtonForBand(RX1Band);
            r.BackColor = button_selected_color;
            //

            m_bSetBandRunning = false;

            //MW0LGE_21d
            if (oldBand != RX1Band ||
                oldFreq != VFOAFreq // or if the freq changes
                )
                SetBandChangeHanders?.Invoke(1, oldBand, RX1Band, oldMode, RX1DSPMode, oldFilter, RX1Filter, oldFreq, VFOAFreq,
                    oldCentreFreq, CentreFrequency, oldCtun, ClickTuneDisplay, oldZoomSlider, ptbDisplayZoom.Value);
        }

        private RadioButtonTS getButtonForBand(Band b)
        {
            RadioButtonTS r;

            switch (b)
            {
                case Band.GEN:
                    r = radBandGEN;
                    break;
                case Band.B160M:
                    r = radBand160;
                    break;
                case Band.B80M:
                    r = radBand80;
                    break;
                case Band.B60M:
                    r = radBand60;
                    break;
                case Band.B40M:
                    r = radBand40;
                    break;
                case Band.B30M:
                    r = radBand30;
                    break;
                case Band.B20M:
                    r = radBand20;
                    break;
                case Band.B17M:
                    r = radBand17;
                    break;
                case Band.B15M:
                    r = radBand15;
                    break;
                case Band.B12M:
                    r = radBand12;
                    break;
                case Band.B10M:
                    r = radBand10;
                    break;
                case Band.B6M:
                    r = radBand6;
                    break;
                case Band.B2M:
                    r = radBand2;
                    break;
                case Band.WWV:
                    r = radBandWWV;
                    break;
                case Band.BLMF:
                    r = radBandGEN0;
                    break;
                case Band.B120M:
                    r = radBandGEN1;
                    break;
                case Band.B90M:
                    r = radBandGEN2;
                    break;
                case Band.B61M:
                    r = radBandGEN3;
                    break;
                case Band.B49M:
                    r = radBandGEN4;
                    break;
                case Band.B41M:
                    r = radBandGEN5;
                    break;
                case Band.B31M:
                    r = radBandGEN6;
                    break;
                case Band.B25M:
                    r = radBandGEN7;
                    break;
                case Band.B22M:
                    r = radBandGEN8;
                    break;
                case Band.B19M:
                    r = radBandGEN9;
                    break;
                case Band.B16M:
                    r = radBandGEN10;
                    break;
                case Band.B14M:
                    r = radBandGEN11;
                    break;
                case Band.B13M:
                    r = radBandGEN12;
                    break;
                case Band.B11M:
                    r = radBandGEN13;
                    break;
                case Band.VHF0:
                    r = radBandVHF0;
                    break;
                case Band.VHF1:
                    r = radBandVHF1;
                    break;
                case Band.VHF2:
                    r = radBandVHF2;
                    break;
                case Band.VHF3:
                    r = radBandVHF3;
                    break;
                case Band.VHF4:
                    r = radBandVHF4;
                    break;
                case Band.VHF5:
                    r = radBandVHF5;
                    break;
                case Band.VHF6:
                    r = radBandVHF6;
                    break;
                case Band.VHF7:
                    r = radBandVHF7;
                    break;
                case Band.VHF8:
                    r = radBandVHF8;
                    break;
                case Band.VHF9:
                    r = radBandVHF9;
                    break;
                case Band.VHF10:
                    r = radBandVHF10;
                    break;
                case Band.VHF11:
                    r = radBandVHF11;
                    break;
                case Band.VHF12:
                    r = radBandVHF12;
                    break;
                case Band.VHF13:
                    r = radBandVHF13;
                    break;
                default:
                    r = radBandGEN;
                    break;
            }

            return r;
        }

        public int last_MHZ = 0; // ke9ns 
        public DSPMode last_MODE = DSPMode.LAST;

        private void ChangeTuneStepUp()
        {
            //MW0LGE_21j
            TuneStepIndex = (tune_step_index + 1) % tune_step_list.Count;
        }

        private void ChangeTuneStepDown()
        {
            //MW0LGE_21j
            TuneStepIndex = (tune_step_index - 1 + tune_step_list.Count) % tune_step_list.Count;
        }

        private void UpdateBandButtonColors()
        {
            SetRX1BandButton(rx1_band);
        }

        private void DeselectHF()
        {
            radBand160.Checked = false;
            radBand80.Checked = false;
            radBand60.Checked = false;
            radBand40.Checked = false;
            radBand30.Checked = false;
            radBand20.Checked = false;
            radBand17.Checked = false;
            radBand15.Checked = false;
            radBand12.Checked = false;
            radBand10.Checked = false;
            radBand6.Checked = false;
            radBandWWV.Checked = false;
            radBandGEN.Checked = false;
            radBand2.Checked = false;
        }

        //===================================================
        private void DeselectGEN()  // ke9ns add
        {
            radBandGEN0.Checked = false;
            radBandGEN1.Checked = false;
            radBandGEN2.Checked = false;
            radBandGEN3.Checked = false;
            radBandGEN4.Checked = false;
            radBandGEN5.Checked = false;
            radBandGEN6.Checked = false;
            radBandGEN7.Checked = false;
            radBandGEN8.Checked = false;
            radBandGEN9.Checked = false;
            radBandGEN10.Checked = false;
            radBandGEN11.Checked = false;
            radBandGEN12.Checked = false;
            radBandGEN13.Checked = false;

        }

        private void DeselectVHF()
        {
            radBandVHF0.Checked = false;
            radBandVHF1.Checked = false;
            radBandVHF2.Checked = false;
            radBandVHF3.Checked = false;
            radBandVHF4.Checked = false;
            radBandVHF5.Checked = false;
            radBandVHF6.Checked = false;
            radBandVHF7.Checked = false;
            radBandVHF8.Checked = false;
            radBandVHF9.Checked = false;
            radBandVHF10.Checked = false;
            radBandVHF11.Checked = false;
            radBandVHF12.Checked = false;
            radBandVHF13.Checked = false;
        }

        private void SetRX1BandButton(Band b)
        {
            // MW0LGE lots of changes in this function for BandStack2

            SpotControl.VFOLOW = 0;   // ke9ns add default values (used in spot.cs for mapping dx spots)
            SpotControl.VFOHIGH = 1;  // ke9ns add default values

            switch (b)
            {
                case Band.B160M:
                    SpotControl.VFOLOW = 1800000; // ke9ns add
                    SpotControl.VFOHIGH = 2000000;// ke9ns add
                    radBand160.Checked = true;
                    DeselectVHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.B80M:
                    SpotControl.VFOLOW = 3500000;
                    SpotControl.VFOHIGH = 4000000;
                    radBand80.Checked = true;
                    DeselectVHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.B60M:
                    SpotControl.VFOLOW = 5000000;
                    SpotControl.VFOHIGH = 6000000;
                    radBand60.Checked = true;
                    DeselectVHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.B40M:
                    SpotControl.VFOLOW = 7000000;
                    SpotControl.VFOHIGH = 7300000;
                    radBand40.Checked = true;
                    DeselectVHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.B30M:
                    SpotControl.VFOLOW = 10100000;
                    SpotControl.VFOHIGH = 10150000;
                    radBand30.Checked = true;
                    DeselectVHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.B20M:
                    SpotControl.VFOLOW = 14000000;
                    SpotControl.VFOHIGH = 14350000;
                    radBand20.Checked = true;
                    DeselectVHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.B17M:
                    SpotControl.VFOLOW = 18000000; // 18.068
                    SpotControl.VFOHIGH = 18200000; // 18.168
                    radBand17.Checked = true;
                    DeselectVHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.B15M:
                    SpotControl.VFOLOW = 21000000; // 
                    SpotControl.VFOHIGH = 21450000; // 
                    radBand15.Checked = true;
                    DeselectVHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.B12M:
                    SpotControl.VFOLOW = 24800000; // 24.89
                    SpotControl.VFOHIGH = 25000000; // 24.99
                    radBand12.Checked = true;
                    DeselectVHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.B10M:
                    SpotControl.VFOLOW = 28000000; // 
                    SpotControl.VFOHIGH = 30000000; // 
                    radBand10.Checked = true;
                    DeselectVHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.B6M:
                    SpotControl.VFOLOW = 50000000; // 
                    SpotControl.VFOHIGH = 54000000; //
                    radBand6.Checked = true;
                    DeselectVHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.B2M:
                    radBand2.Checked = true;
                    DeselectVHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.WWV:
                    radBandWWV.Checked = true;
                    DeselectVHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.GEN:
                    //   Debug.WriteLine("gen pushed");
                    radBandGEN.Checked = true;
                    DeselectVHF();
                    DeselectHF(); // ke9ns add
                    break;


                case Band.VHF0:
                    radBandVHF0.Checked = true;
                    DeselectHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.VHF1:
                    radBandVHF1.Checked = true;
                    DeselectHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.VHF2:
                    radBandVHF2.Checked = true;
                    DeselectHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.VHF3:
                    radBandVHF3.Checked = true;
                    DeselectHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.VHF4:
                    radBandVHF4.Checked = true;
                    DeselectHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.VHF5:
                    radBandVHF5.Checked = true;
                    DeselectHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.VHF6:
                    radBandVHF6.Checked = true;
                    DeselectHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.VHF7:
                    radBandVHF7.Checked = true;
                    DeselectHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.VHF8:
                    radBandVHF8.Checked = true;
                    DeselectHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.VHF9:
                    radBandVHF9.Checked = true;
                    DeselectHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.VHF10:
                    radBandVHF10.Checked = true;
                    DeselectHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.VHF11:
                    radBandVHF11.Checked = true;
                    DeselectHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.VHF12:
                    radBandVHF12.Checked = true;
                    DeselectHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.VHF13:
                    radBandVHF13.Checked = true;
                    DeselectHF();
                    DeselectGEN(); // ke9ns add
                    break;
                case Band.BLMF:
                    radBandGEN0.Checked = true;
                    DeselectHF();
                    DeselectVHF(); // ke9ns add
                    break;
                case Band.B120M:
                    radBandGEN1.Checked = true;
                    DeselectHF();
                    DeselectVHF(); // ke9ns add
                    break;
                case Band.B90M:
                    radBandGEN2.Checked = true;
                    DeselectHF();
                    DeselectVHF(); // ke9ns add
                    break;
                case Band.B61M:
                    radBandGEN3.Checked = true;
                    DeselectHF();
                    DeselectVHF(); // ke9ns add
                    break;
                case Band.B49M:
                    radBandGEN4.Checked = true;
                    DeselectHF();
                    DeselectVHF(); // ke9ns add
                    break;
                case Band.B41M:
                    radBandGEN5.Checked = true;
                    DeselectHF();
                    DeselectVHF(); // ke9ns add
                    break;
                case Band.B31M:
                    radBandGEN6.Checked = true;
                    DeselectHF();
                    DeselectVHF(); // ke9ns add
                    break;
                case Band.B25M:
                    radBandGEN7.Checked = true;
                    DeselectHF();
                    DeselectVHF(); // ke9ns add
                    break;
                case Band.B22M:
                    radBandGEN8.Checked = true;
                    DeselectHF();
                    DeselectVHF(); // ke9ns add
                    break;
                case Band.B19M:
                    radBandGEN9.Checked = true;
                    DeselectHF();
                    DeselectVHF(); // ke9ns add
                    break;
                case Band.B16M:
                    radBandGEN10.Checked = true;
                    DeselectHF();
                    DeselectVHF(); // ke9ns add
                    break;
                case Band.B14M:
                    radBandGEN11.Checked = true;
                    DeselectHF();
                    DeselectVHF(); // ke9ns add
                    break;
                case Band.B13M:
                    radBandGEN12.Checked = true;
                    DeselectHF();
                    DeselectVHF(); // ke9ns add
                    break;
                case Band.B11M:
                    radBandGEN13.Checked = true;
                    DeselectHF();
                    DeselectVHF(); // ke9ns add
                    break;

            }
        }
        public Band RX1BandForVFOB()
        {
            // used by multimeter
            if (XVTRForm != null)
            {
                double t_freq = XVTRForm.TranslateFreq(VFOBFreq);
                if (VFOBFreq == t_freq)
                {
                    // no transverter as xvtr_index might not be changed in time when calling this RX1BandForVFOB()
                    return BandByFreq(VFOBFreq, -1, current_region);
                }
                else
                {
                    return BandByFreq(VFOBFreq, rx1_xvtr_index, current_region);
                }
            }
            else
            {
                return BandByFreq(VFOBFreq, rx1_xvtr_index, current_region);
            }
        }
        public Band GetTransverterTranslatedRXBand(double freq)
        {
            if (XVTRForm == null) return 0;

            double t_freq = XVTRForm.TranslateFreq(freq);
            return BandByFreq(t_freq, -1, current_region);
        }
        public Band GetTransverterTranslatedTXBand()
        {
            if (XVTRForm == null) return 0;

            double t_freq = XVTRForm.TranslateFreq(TXFreq);
            return BandByFreq(t_freq, -1, current_region);
        }
        private Band BandByFreq(double freq, int xvtr_index, FRSRegion region)
        {
            if (xvtr_index >= 0) return (Band)(Band.VHF0 + xvtr_index);
            if (!BandStackManager.Ready) return Band.GEN;

            List<BandFrequencyData> bands = BandStackManager.GetBandFrequencyDataForFrequency(freq, extended, region);

            // use the first always as it will be same as old code
            BandFrequencyData bfd = bands.First<BandFrequencyData>();
            return bfd.band;
        }

        // Used to detect when a band change is in progress
        // by comparing with RX1Band at any point
        private Band RX1_band_change = Band.FIRST; //MW0LGE_21d

        private void SetRX1Band(Band b)
        {
            //[2.10.3.6]MW0LGE no band change on TX fix
            if (MOX && (VFOATX || (!rx2_enabled && VFOBTX))) return;

            if (disable_split_on_bandchange)
            {
                if (RX1Band != b && !tuning)
                {
                    if (chkVFOSplit.Checked)
                        chkVFOSplit.Checked = false;
                }
            }

            Band old_band = rx1_band;
            RX1Band = b;

            if (old_band != b)
            {
                UpdateBandButtonColors();
                UpdateWaterfallLevelValues();
                updateDisplayGridLevelValues();
                UpdateDiversityValues();
            }

            if (rx1_xvtr_index >= 0)
            {
                setBandPanelVisible(false, false, true);
            }
            else
            {
                setBandPanelVisible(BandGENSelected, BandHFSelected, false);
            }
        }

        private void SetRX2Band(Band b)
        {
            Band old_band = rx2_band;
            RX2Band = b;
            if (old_band != b)
            {
                UpdateBandButtonColors();
                UpdateWaterfallLevelValues();
                updateDisplayGridLevelValues();
            }
        }

        private void SetTXBand(Band b, bool bIngoreBandChange = false)
        {
            //[2.10.3.6]MW0LGE no band change on TX fix
            if (MOX) return;

            if (disable_split_on_bandchange && !bIngoreBandChange) //[2.10.3.6]MW0LGE might need to ignore this is we are using extended and band is moved to a hamband
            {
                if (TXBand != b && !tuning)
                {
                    if (chkVFOSplit.Checked)
                        chkVFOSplit.Checked = false;
                }
            }

            Band old_band = tx_band;
            TXBand = b;
            if (old_band != b)
                UpdateBandButtonColors();
        }

        private float GainByBand(Band b, int nDriveValue)
        {
            if (IsSetupFormNull) return 1000;

            return SetupForm.GetPAGain(b, nDriveValue);
        }

        public void CheckSelectedButtonColor()
        {
            // used when changing the background color of selected buttons
            foreach (Control c in this.Controls)
            {
                if (c.GetType() == typeof(GroupBoxTS))
                {
                    foreach (Control c2 in ((GroupBoxTS)c).Controls)
                    {
                        if (c2.GetType() == typeof(RadioButtonTS))
                        {
                            RadioButtonTS r = (RadioButtonTS)c2;
                            if (r.Checked && r.BackColor != SystemColors.Control)
                            {
                                c2.BackColor = button_selected_color;
                            }
                        }
                        else if (c2.GetType() == typeof(CheckBoxTS))
                        {
                            CheckBoxTS chk = (CheckBoxTS)c2;
                            if (chk.Checked && chk.BackColor != SystemColors.Control)
                            {
                                c2.BackColor = button_selected_color;
                            }
                        }
                        else if (c2.GetType() == typeof(NumericUpDownTS))
                        {
                            NumericUpDownTS ud = (NumericUpDownTS)c2;
                            if (ud.BackColor != SystemColors.Window)
                            {
                                c2.BackColor = button_selected_color;
                            }
                        }
                        else if (c2.GetType() == typeof(ButtonTS))
                        {
                            ButtonTS b = (ButtonTS)c2;
                            if (b.BackColor != SystemColors.Control)
                            {
                                c2.BackColor = button_selected_color;
                            }
                        }
                    }
                }
                else if (c.GetType() == typeof(RadioButtonTS))
                {
                    RadioButtonTS r = (RadioButtonTS)c;
                    if (r.Checked && r.BackColor != SystemColors.Control)
                        c.BackColor = button_selected_color;
                }
                else if (c.GetType() == typeof(CheckBoxTS))
                {
                    CheckBoxTS chk = (CheckBoxTS)c;
                    if (chk.Checked && chk.BackColor != SystemColors.Control)
                        c.BackColor = button_selected_color;
                }
                else if (c.GetType() == typeof(NumericUpDownTS))
                {
                    NumericUpDownTS ud = (NumericUpDownTS)c;
                    if (ud.BackColor != SystemColors.Window)
                        c.BackColor = button_selected_color;
                }
                else if (c.GetType() == typeof(ButtonTS))
                {
                    ButtonTS b = (ButtonTS)c;
                    if (b.BackColor != SystemColors.Control)
                        c.BackColor = button_selected_color;
                }
            }
        }

        private double PABandOffset(Band b)
        {
            //[2.10.3.5]MW0LGE TOREMOVE
            double num = 0;
            switch (b)
            {
                case Band.B160M:
                    // num = SetupForm.PAADC160;
                    break;
                case Band.B80M:
                    // num = SetupForm.PAADC80;
                    break;
                case Band.B60M:
                    // num = SetupForm.PAADC60;
                    break;
                case Band.B40M:
                    // num = SetupForm.PAADC40;
                    break;
                case Band.B30M:
                    // num = SetupForm.PAADC30;
                    break;
                case Band.B20M:
                    //  num = SetupForm.PAADC20;
                    break;
                case Band.B17M:
                    // num = SetupForm.PAADC17;
                    break;
                case Band.B15M:
                    // num = SetupForm.PAADC15;
                    break;
                case Band.B12M:
                    // num = SetupForm.PAADC12;
                    break;
                case Band.B10M:
                    //  num = SetupForm.PAADC10;
                    break;
            }

            if (num == 0) return 0;
            //return 100000 / Math.Pow(num, 2);
            return (double)108 / num;
        }

        private double SWR(int adc_fwd, int adc_rev)
        {
            if (adc_fwd == 0 && adc_rev == 0)
                return 1.0;
            else if (adc_rev > adc_fwd)
                return 50.0;

            double Ef = ScaledVoltage(adc_fwd);
            double Er = ScaledVoltage(adc_rev);

            double swr = (Ef + Er) / (Ef - Er);

            return swr;
        }

        //[2.10.3.5]MW0LGE TOREMOVE
#if false
        public double ALEXSWR(double g_fwd, double g_rev)
        {
            double rho = Math.Sqrt(g_rev / g_fwd);
            double swr = (1.0 + rho) / (1.0 - rho); ;

            if (!alexpresent || g_fwd < 0.5)
            {
                JanusAudio.SetSWRProtect(1.0f);
                HighSWR = false;
                return 1.0; // swr;
            }

            if (!swrprotection)
            {
                // double rho = Math.Sqrt(g_rev / g_fwd);
                // swr = (1.0 + rho) / (1.0 - rho);
                JanusAudio.SetSWRProtect(1.0f);
                if (swr > 2.2) HighSWR = true;
                else HighSWR = false;
                return swr;
            }

            if (chkTUN.Checked && disable_swr_on_tune && (alexpresent || apollopresent))
            {
                if (g_fwd <= 10.0)
                {
                    //  double rho = Math.Sqrt(g_rev / g_fwd);
                    //  swr = (1.0 + rho) / (1.0 - rho);
                    JanusAudio.SetSWRProtect(1.0f);
                    HighSWR = false;
                    return swr;
                }
            }

            //  if (g_rev > g_fwd)
            //  {
            //    HighSWR = true;
            //   swr = 5.0;
            //   if (current_display_engine == DisplayEngine.GDI_PLUS)
            //      picDisplay.Invalidate();

            //  }
            //  else
            // {
            //     double rho = Math.Sqrt(g_rev / g_fwd);
            //     swr = (1.0 + rho) / (1.0 - rho);
            //  }

            if (swr > 2.2)
            {
                JanusAudio.SetSWRProtect(0.5f);
                HighSWR = true;
                if (swr > 3) JanusAudio.SetSWRProtect(0.25f);
                if (current_display_engine == DisplayEngine.GDI_PLUS)
                    picDisplay.Invalidate();
            }
            else
            {
                JanusAudio.SetSWRProtect(1.0f);
                HighSWR = false;
                if (current_display_engine == DisplayEngine.GDI_PLUS)
                    picDisplay.Invalidate();
            }
            return swr;
        }
#endif

        //public double FWCSWR(int adc_fwd, int adc_rev)
        //{
        //    double f = FWCPAPower(adc_fwd);
        //    double r = FWCPAPower(adc_rev) * swr_table[(int)tx_band];
        //    //Debug.WriteLine("FWCSWR: fwd:"+adc_fwd+" rev:"+adc_rev+" f:"+f.ToString("f2")+" r:"+r.ToString("f2"));

        //    if ((adc_fwd == 0 && adc_rev == 0) || (f < 1.0 && r < 1.0)) return 1.0;
        //    if (adc_rev > adc_fwd) return 50.0;

        //    double sqrt_r_over_f = Math.Sqrt(r / f);
        //    return (1.0 + sqrt_r_over_f) / (1.0 - sqrt_r_over_f);
        //}

        private double ScaledVoltage(int adc)
        {
            double v_det = adc * 0.062963;			// scale factor in V/bit including pot ratio
            double v_out = v_det * 10.39853;		// scale factor in V/V for bridge output to detector voltage
            return v_out * PABandOffset(tx_band);
            //double v_det = adc * 0.0304;
            //			double v_out = 0;
            //			if(v_det >= 1.6)
            //				v_out = (-0.241259304*v_det+12.07915098)*v_det*PABandOffset(CurrentBand);
            //			else if(v_det > 0.35)
            //				v_out = (1/Math.Pow(v_det, 2)+11.3025111)*v_det*PABandOffset(CurrentBand);
            //return v_out;
        }

        private double ADCtodBm(int adc_data)
        {
            if (adc_data == 0)
                return 0;

            double mult = 100000 / Math.Pow(225 / PABandOffset(tx_band), 2);
            return 10 * Math.Log10(mult * Math.Pow(adc_data, 2));
        }

        private double PAPower(int adc)
        {
            double v_out = ScaledVoltage(adc);
            double pow = Math.Pow(v_out, 2) / 50;
            pow = Math.Max(pow, 0.0);
            return pow;
        }

        private double WattsTodBm(double watts)
        {
            return 10 * Math.Log10(watts / 0.001);
        }

        private double dBmToWatts(double dBm)
        {
            return Math.Pow(10, dBm / 10) * 0.001;
        }

        /*public float CalibratedPAPower()
        {
            float watts = alex_fwd; // computeAlexFwdPower();
           //******************************************************************
           // Begin with both numbers in each line equal to the comment value.
           // For each power level from 10W to maximum, adjust power such that
           // the P*SDR meter just achieves the value in the comment. 
           // Record the actual power output as indicated by an external 
           // calibrated meter.  Use the recorded values as the FIRST numbers
           // in the respective lines of the table.
           //******************************************************************
            float[] table = new float[15] {   1.0f,                       //   0W 
                                             SetupForm.PA10W  /  10.0f,   //  10W 
                                             SetupForm.PA20W  /  20.0f,   //  20W 
                                             SetupForm.PA30W  /  30.0f,   //  30W 
                                             SetupForm.PA40W  /  40.0f,   //  40W 
                                             SetupForm.PA50W  /  50.0f,   //  50W 
                                             SetupForm.PA60W  /  60.0f,   //  60W 
                                             SetupForm.PA70W  /  70.0f,   //  70W
                                             SetupForm.PA80W  /  80.0f,   //  80W 
                                             SetupForm.PA90W  /  90.0f,   //  90W
                                             SetupForm.PA100W / 100.0f,   // 100W
                                             SetupForm.PA110W / 110.0f,   // 110W
                                             SetupForm.PA120W / 120.0f,   // 120W 
                                             SetupForm.PA130W / 130.0f,   // 130W
                                             SetupForm.PA140W / 140.0f }; // 140W
            int idx = (int)(0.1f * watts);
            float frac = 0.1f * watts - idx;
            watts *= (1.0f - frac) * table[idx] + frac * table[idx + 1];
            return watts;
        }*/

        public float CalibratedPAPower()
        {
            float watts = alex_fwd;
            //********************************************************************
            // Begin with all spinners set equal to their labelled value.
            // For each spinner, from minimum to maximum, adjust the output power
            // such that your CALIBRATED EXTERNAL METER is equal to the spinner
            // value.  Record the values appearing in the Thetis 'Fwd Pwr' meter.
            // After completing measurements for all spinners, enter your
            // recorded values into the respective spinners.  DO NOT USE
            // POWER EXCEEDING THE RATING OF YOUR RADIO!
            //********************************************************************
            const int entries = 11;                                 // number of table entries
            float interval = 10.0f;                                 // interval (watts) between labels
            float[] PAsets = new float[entries] { 0.0f,
                                                  SetupForm.PA10W,
                                                  SetupForm.PA20W,
                                                  SetupForm.PA30W,
                                                  SetupForm.PA40W,
                                                  SetupForm.PA50W,
                                                  SetupForm.PA60W,
                                                  SetupForm.PA70W,
                                                  SetupForm.PA80W,
                                                  SetupForm.PA90W,
                                                  SetupForm.PA100W };

            switch (CurrentHPSDRModel)
            {
                //case HPSDRModel.ANAN100:
                case HPSDRModel.ANAN100D:
                    interval = 10.0f;
                    float[] ANAN100DCal = new float[entries] {   0.0f,      // predetermined calibration factors
                                                                11.0f,
                                                                24.0f,
                                                                35.0f,
                                                                46.0f,
                                                                57.0f,
                                                                67.0f,
                                                                81.0f,
                                                                90.0f,
                                                               103.0f,
                                                               114.0f };
                    watts = PowerKernel(watts, interval, entries, ANAN100DCal);
                    break;
                case HPSDRModel.ANAN7000D:
                case HPSDRModel.ANAN_G2:                // G8NJJ
                case HPSDRModel.ANAN_G2_1K:             // G8NJJ
                    interval = 10.0f;
                    break;
                case HPSDRModel.ANAN8000D:
                    interval = 20.0f;
                    break;
                case HPSDRModel.ANAN10:
                case HPSDRModel.ANAN10E:
                    interval = 1.0f;
                    break;
                default:
                    interval = 10.0f;
                    break;
            }
            return PowerKernel(watts, interval, entries, PAsets);
        }

        private float PowerKernel(float watts, float interval, int entries, float[] table)
        {
            int idx = 0;
            if (watts > table[entries - 1])
                idx = entries - 2;
            else
            {
                while (watts > table[idx]) idx++;
                if (idx > 0) idx--;
            }
            float frac = (watts - table[idx]) / (table[idx + 1] - table[idx]);
            return interval * ((1.0f - frac) * (float)idx + frac * (float)(idx + 1));
        }

        //public double FWCPAPower(int adc) // adc in, watts out
        //{
        //    if (adc < 2) return 0.0;
        //    double[] table = { 1.0, 2.0, 5.0, 10.0, 20.0, 90.0 };

        //    double watts = 0.0;
        //    double volts = (double)adc / 4096 * 2.5;
        //    double v2 = Math.Pow(volts, 2);

        //    int high_index = 0;
        //    for (int i = 0; i < 6; i++)
        //    {
        //        if (volts < pa_bridge_table[(int)tx_band][i])
        //        {
        //            high_index = i;
        //            break;
        //        }
        //        if (i == 5) high_index = 6;
        //    }

        //    if (high_index != 6)
        //    {
        //        double v_low = 0.0, v_high = 0.0;
        //        double p_low = 0.0, p_high = 0.0;

        //        if (high_index != 0) v_low = pa_bridge_table[(int)tx_band][high_index - 1];
        //        v_high = pa_bridge_table[(int)tx_band][high_index];
        //        if (high_index != 0) p_low = table[high_index - 1];
        //        p_high = table[high_index];
        //        Debug.Assert(v_low <= volts && v_high >= volts);

        //        double v_low_2 = Math.Pow(v_low, 2.0);
        //        double v_high_2 = Math.Pow(v_high, 2.0);

        //        watts = p_low + (p_high - p_low) * ((v2 - v_low_2) / (v_high_2 - v_low_2));
        //    }
        //    else
        //    {
        //        double v_low_2 = Math.Pow(pa_bridge_table[(int)tx_band][4], 2.0);
        //        double v_high_2 = Math.Pow(pa_bridge_table[(int)tx_band][5], 2.0);

        //        if (v_low_2 != v_high_2)
        //        {
        //            double a = 70.0 / (v_high_2 - v_low_2);
        //            double b = 90.0 / (a * v_high_2);

        //            watts = a * v2 + b;
        //        }
        //    }

        //    return watts;
        //}

        private static bool CheckForOpenProcesses()
        {
            // find all open Thetis processes
            Process[] p = Process.GetProcessesByName("Thetis");
            if (p.Length > 1)
            {
                int tries = 0;
                while (tries < 10 && p.Length > 1)
                {
                    Thread.Sleep(100);
                    tries++;

                    p = Process.GetProcessesByName("Thetis");
                }
            }

            if (p.Length > 1)
            {
                DialogResult dr = MessageBox.Show("There are other Thetis instances running.\n" +
                    "Are you sure you want to continue?",
                    "Continue?",
                    MessageBoxButtons.YesNo,
                    MessageBoxIcon.Question, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                if (dr == DialogResult.No)
                {
                    return false;
                }
            }
            return true;
        }

        //public int VersionTextToInt(string version)	// takes a version string like "1.0.6" 
        //{											// and converts it to an int like 010006.
        //    string[] nums = version.Split('.');
        //    if (nums.Length < 3 || nums.Length > 4) return -1;

        //    int num1 = Int32.Parse(nums[0]);
        //    int num2 = Int32.Parse(nums[1]);
        //    int num3 = Int32.Parse(nums[2]);
        //    int num4 = 0;
        //    if (nums.Length == 4) num4 = Int32.Parse(nums[3]);

        //    return num1 * 1000000 + num2 * 10000 + num3 * 100 + num4;
        //}

        public bool CheckValidTXFreq(FRSRegion r, double f, DSPMode mode, bool bIgnoreFilter = false)
        {
            if (extended || tx_xvtr_index > -1)
                return true;

            bool retval = false;

            //MW0LGE_21d filter outside band, ignore option
            int filterLow = bIgnoreFilter ? 0 : Display.TXFilterLow;
            int filterHigh = bIgnoreFilter ? 0 : Display.TXFilterHigh;

            switch (mode)
            {
                case DSPMode.LSB:
                case DSPMode.DIGL:
                case DSPMode.USB:
                case DSPMode.DIGU:
                case DSPMode.DSB:
                case DSPMode.AM:
                case DSPMode.SAM:
                case DSPMode.FM:
                    retval = (CheckValidTXFreq_Private(r, f + filterLow * 1e-6) &&
                        CheckValidTXFreq_Private(r, f + filterHigh * 1e-6));
                    break;
                case DSPMode.CWL:
                case DSPMode.CWU:
                    retval = CheckValidTXFreq_Private(r, f);
                    break;
                case DSPMode.DRM:
                    retval = (CheckValidTXFreq_Private(r, f - 0.012 + filterLow * 1e-6) &&
                        CheckValidTXFreq_Private(r, f - 0.012 + filterHigh * 1e-6));
                    break;
            }

            return retval;
        }

        private bool CheckValidTXFreq_Private(FRSRegion r, double f)
        {
            if (extended || tx_xvtr_index > -1)
                return true;

            f = Math.Round(f, 6);

            //MW0LGE_21f
            return BandStackManager.IsOKToTX(f, extended, r);
        }

        public void SetAlexHPF(double freq)
        {
            if ((CurrentHPSDRHardware == HPSDRHW.OrionMKII) || (CurrentHPSDRHardware == HPSDRHW.Saturn)) SetBPF1(freq);     //G8NJJ
            else
            {
                if (alexpresent && !initializing)
                {
                    if (_mox && disable_hpf_on_tx)
                    {
                        NetworkIO.SetAlexHPFBits(0x20);
                        SetupForm.radDHPFTXled.Checked = true;
                        return;
                    }

                    if (alex_hpf_bypass)
                    {
                        NetworkIO.SetAlexHPFBits(0x20); // Bypass HPF
                        SetupForm.radBPHPFled.Checked = true;
                        return;
                    }

                    if ((decimal)freq >= SetupForm.udAlex1_5HPFStart.Value && // 1.5 MHz HPF
                         (decimal)freq <= SetupForm.udAlex1_5HPFEnd.Value)
                    {
                        if (alex1_5bphpf_bypass)
                        {
                            NetworkIO.SetAlexHPFBits(0x20); // Bypass HPF
                            SetupForm.radBPHPFled.Checked = true;
                        }
                        else
                        {
                            NetworkIO.SetAlexHPFBits(0x10);
                            SetupForm.rad1_5HPFled.Checked = true;
                        }
                    }

                    else if ((decimal)freq >= SetupForm.udAlex6_5HPFStart.Value && // 6.5 MHz HPF
                             (decimal)freq <= SetupForm.udAlex6_5HPFEnd.Value)
                    {
                        if (alex6_5bphpf_bypass)
                        {
                            NetworkIO.SetAlexHPFBits(0x20); // Bypass HPF
                            SetupForm.radBPHPFled.Checked = true;
                        }
                        else
                        {
                            NetworkIO.SetAlexHPFBits(0x08);
                            SetupForm.rad6_5HPFled.Checked = true;
                        }
                    }

                    else if ((decimal)freq >= SetupForm.udAlex9_5HPFStart.Value && // 9.5 MHz HPF
                             (decimal)freq <= SetupForm.udAlex9_5HPFEnd.Value)
                    {
                        if (alex9_5bphpf_bypass)
                        {
                            NetworkIO.SetAlexHPFBits(0x20); // Bypass HPF
                            SetupForm.radBPHPFled.Checked = true;
                        }
                        else
                        {
                            NetworkIO.SetAlexHPFBits(0x04);
                            SetupForm.rad9_5HPFled.Checked = true;
                        }
                    }

                    else if ((decimal)freq >= SetupForm.udAlex13HPFStart.Value && // 13 MHz HPF
                             (decimal)freq <= SetupForm.udAlex13HPFEnd.Value)
                    {
                        if (alex13bphpf_bypass)
                        {
                            NetworkIO.SetAlexHPFBits(0x20); // Bypass HPF
                            SetupForm.radBPHPFled.Checked = true;
                        }
                        else
                        {
                            NetworkIO.SetAlexHPFBits(0x01);
                            SetupForm.rad13HPFled.Checked = true;
                        }
                    }

                    else if ((decimal)freq >= SetupForm.udAlex20HPFStart.Value && // 20 MHz HPF
                             (decimal)freq <= SetupForm.udAlex20HPFEnd.Value)
                    {
                        if (alex20bphpf_bypass)
                        {
                            NetworkIO.SetAlexHPFBits(0x20); // Bypass HPF
                            SetupForm.radBPHPFled.Checked = true;
                        }
                        else
                        {
                            NetworkIO.SetAlexHPFBits(0x02);
                            SetupForm.rad20HPFled.Checked = true;
                        }
                    }

                    else if ((decimal)freq >= SetupForm.udAlex6BPFStart.Value && // 6m BPF/LNA
                             (decimal)freq <= SetupForm.udAlex6BPFEnd.Value)
                    {
                        if (alex6bphpf_bypass || disable_6m_lna_on_rx || (_mox && disable_6m_lna_on_tx))
                        {
                            NetworkIO.SetAlexHPFBits(0x20); // Bypass HPF
                            SetupForm.radBPHPFled.Checked = true;
                        }
                        else
                        {
                            NetworkIO.SetAlexHPFBits(0x40);
                            SetupForm.rad6BPFled.Checked = true;
                        }
                    }
                    else
                    {
                        NetworkIO.SetAlexHPFBits(0x20); // Bypass HPF
                        SetupForm.radBPHPFled.Checked = true;
                    }
                }
            }
        }

        public void SetBPF1(double freq)
        {
            if (alexpresent && !initializing)
            {
                if (_mox && (disable_hpf_on_tx || (disable_hpf_on_ps && PureSignalEnabled)))
                {
                    NetworkIO.SetAlexHPFBits(0x20);
                    SetupForm.BPF1BPTXled = disable_hpf_on_tx;
                    SetupForm.radBPF1BPPSled.Checked = disable_hpf_on_ps && PureSignalEnabled;
                    return;
                }

                if (alex_hpf_bypass)
                {
                    NetworkIO.SetAlexHPFBits(0x20); // Bypass HPF
                    SetupForm.BPBPF1led = true;
                    return;
                }

                if (freq >= SetupForm.BPF1_1_5Start && // 1.5 MHz HPF
                     freq <= SetupForm.BPF1_1_5End)
                {
                    if (bpf1_1_5bp_bypass)
                    {
                        NetworkIO.SetAlexHPFBits(0x20); // Bypass HPF
                        SetupForm.BPBPF1led = true;
                    }
                    else
                    {
                        NetworkIO.SetAlexHPFBits(0x10);
                        SetupForm.BPF1_1_5led = true;
                    }
                }

                else if (freq >= SetupForm.BPF1_6_5Start && // 6.5 MHz HPF
                         freq <= SetupForm.BPF1_6_5End)
                {
                    if (bpf1_6_5bp_bypass)
                    {
                        NetworkIO.SetAlexHPFBits(0x20); // Bypass HPF
                        SetupForm.BPBPF1led = true;
                    }
                    else
                    {
                        NetworkIO.SetAlexHPFBits(0x08);
                        SetupForm.BPF1_6_5led = true;
                    }
                }

                else if (freq >= SetupForm.BPF1_9_5Start && // 9.5 MHz HPF
                         freq <= SetupForm.BPF1_9_5End)
                {
                    if (bpf1_9_5bp_bypass)
                    {
                        NetworkIO.SetAlexHPFBits(0x20); // Bypass HPF
                        SetupForm.BPBPF1led = true;
                    }
                    else
                    {
                        NetworkIO.SetAlexHPFBits(0x04);
                        SetupForm.BPF1_9_5led = true;
                    }
                }

                else if (freq >= SetupForm.BPF1_13Start && // 13 MHz HPF
                         freq <= SetupForm.BPF1_13End)
                {
                    if (bpf1_13bp_bypass)
                    {
                        NetworkIO.SetAlexHPFBits(0x20); // Bypass HPF
                        SetupForm.BPBPF1led = true;
                    }
                    else
                    {
                        NetworkIO.SetAlexHPFBits(0x01);
                        SetupForm.BPF1_13led = true;
                    }
                }

                else if (freq >= SetupForm.BPF1_20Start && // 20 MHz HPF
                         freq <= SetupForm.BPF1_20End)
                {
                    if (bpf1_20bp_bypass)
                    {
                        NetworkIO.SetAlexHPFBits(0x20); // Bypass HPF
                        SetupForm.BPBPF1led = true;
                    }
                    else
                    {
                        NetworkIO.SetAlexHPFBits(0x02);
                        SetupForm.BPF1_20led = true;
                    }
                }

                else if (freq >= SetupForm.BPF1_6Start && // 6m BPF/LNA
                         freq <= SetupForm.BPF1_6End)
                {
                    if (bpf1_6bp_bypass || disable_6m_lna_on_rx || (_mox && disable_6m_lna_on_tx))
                    {
                        NetworkIO.SetAlexHPFBits(0x20); // Bypass HPF
                        SetupForm.BPBPF1led = true;
                    }
                    else
                    {
                        NetworkIO.SetAlexHPFBits(0x40);
                        SetupForm.BPF1_6led = true;
                    }
                }
                else
                {
                    NetworkIO.SetAlexHPFBits(0x20); // Bypass HPF
                    SetupForm.BPBPF1led = true;
                }
            }
        }

        public void SetAlex2HPF(double freq)
        {
            if (alexpresent && !initializing)
            {
                if (alex2_hpf_bypass)
                {
                    NetworkIO.SetAlex2HPFBits(0x20); // Bypass HPF
                    SetupForm.radAlex2BPHPFled.Checked = true;
                    return;
                }

                if ((decimal)freq >= SetupForm.udAlex21_5HPFStart.Value && // 1.5 MHz HPF
                     (decimal)freq <= SetupForm.udAlex21_5HPFEnd.Value)
                {
                    if (alex21_5bphpf_bypass)
                    {
                        NetworkIO.SetAlex2HPFBits(0x20); // Bypass HPF
                        SetupForm.radAlex2BPHPFled.Checked = true;
                    }
                    else
                    {
                        NetworkIO.SetAlex2HPFBits(0x10);
                        SetupForm.radAlex21_5HPFled.Checked = true;
                    }
                }

                else if ((decimal)freq >= SetupForm.udAlex26_5HPFStart.Value && // 6.5 MHz HPF
                         (decimal)freq <= SetupForm.udAlex26_5HPFEnd.Value)
                {
                    if (alex26_5bphpf_bypass)
                    {
                        NetworkIO.SetAlex2HPFBits(0x20); // Bypass HPF
                        SetupForm.radAlex2BPHPFled.Checked = true;
                    }
                    else
                    {
                        NetworkIO.SetAlex2HPFBits(0x08);
                        SetupForm.radAlex26_5HPFled.Checked = true;
                    }
                }

                else if ((decimal)freq >= SetupForm.udAlex29_5HPFStart.Value && // 9.5 MHz HPF
                         (decimal)freq <= SetupForm.udAlex29_5HPFEnd.Value)
                {
                    if (alex29_5bphpf_bypass)
                    {
                        NetworkIO.SetAlex2HPFBits(0x20); // Bypass HPF
                        SetupForm.radAlex2BPHPFled.Checked = true;
                    }
                    else
                    {
                        NetworkIO.SetAlex2HPFBits(0x04);
                        SetupForm.radAlex29_5HPFled.Checked = true;
                    }
                }

                else if ((decimal)freq >= SetupForm.udAlex213HPFStart.Value && // 13 MHz HPF
                         (decimal)freq <= SetupForm.udAlex213HPFEnd.Value)
                {
                    if (alex213bphpf_bypass)
                    {
                        NetworkIO.SetAlex2HPFBits(0x20); // Bypass HPF
                        SetupForm.radAlex2BPHPFled.Checked = true;
                    }
                    else
                    {
                        NetworkIO.SetAlex2HPFBits(0x01);
                        SetupForm.radAlex213HPFled.Checked = true;
                    }
                }

                else if ((decimal)freq >= SetupForm.udAlex220HPFStart.Value && // 20 MHz HPF
                         (decimal)freq <= SetupForm.udAlex220HPFEnd.Value)
                {
                    if (alex220bphpf_bypass)
                    {
                        NetworkIO.SetAlex2HPFBits(0x20); // Bypass HPF
                        SetupForm.radAlex2BPHPFled.Checked = true;
                    }
                    else
                    {
                        NetworkIO.SetAlex2HPFBits(0x02);
                        SetupForm.radAlex220HPFled.Checked = true;
                    }
                }

                else if ((decimal)freq >= SetupForm.udAlex26BPFStart.Value && // 6m BPF/LNA
                         (decimal)freq <= SetupForm.udAlex26BPFEnd.Value)
                {
                    if (alex26bphpf_bypass)
                    {
                        NetworkIO.SetAlex2HPFBits(0x20); // Bypass HPF
                        SetupForm.radAlex2BPHPFled.Checked = true;
                    }
                    else
                    {
                        NetworkIO.SetAlex2HPFBits(0x40);
                        SetupForm.radAlex26BPFled.Checked = true;
                    }
                }
                else
                {
                    NetworkIO.SetAlex2HPFBits(0x20); // Bypass HPF
                    SetupForm.radAlex2BPHPFled.Checked = true;
                }
            }
        }

        public void SetAlexLPF(double freq, bool freqIsTX)
        {
            //Debug.Print("lpf : " + freq.ToString() + " -- freq is tx : " + freqIsTX.ToString());
            if (!_mox && lpf_bypass)
            {
                NetworkIO.SetAlexLPFBits(0x10, false, _mox); // 6m LPF
                SetupForm.rad6LPFled.Checked = true;
                return;
            }

            if (alexpresent && !initializing)
            {
                if ((decimal)freq >= SetupForm.udAlex20mLPFStart.Value && // 30/20m LPF
                          (decimal)freq <= SetupForm.udAlex20mLPFEnd.Value)
                {
                    NetworkIO.SetAlexLPFBits(0x01, freqIsTX, _mox);
                    SetupForm.rad20LPFled.Checked = true;
                }

                else if ((decimal)freq >= SetupForm.udAlex40mLPFStart.Value && // 60/40m LPF
                        (decimal)freq <= SetupForm.udAlex40mLPFEnd.Value)
                {
                    NetworkIO.SetAlexLPFBits(0x02, freqIsTX, _mox);
                    SetupForm.rad40LPFled.Checked = true;
                }

                else if ((decimal)freq >= SetupForm.udAlex80mLPFStart.Value && // 80m LPF
                         (decimal)freq <= SetupForm.udAlex80mLPFEnd.Value)
                {
                    NetworkIO.SetAlexLPFBits(0x04, freqIsTX, _mox);
                    SetupForm.rad80LPFled.Checked = true;
                }

                else if ((decimal)freq >= SetupForm.udAlex160mLPFStart.Value && // 160m LPF
                     (decimal)freq <= SetupForm.udAlex160mLPFEnd.Value)
                {
                    NetworkIO.SetAlexLPFBits(0x08, freqIsTX, _mox);
                    SetupForm.rad160LPFled.Checked = true;
                }

                else if ((decimal)freq >= SetupForm.udAlex6mLPFStart.Value && // 6m LPF
                        (decimal)freq <= SetupForm.udAlex6mLPFEnd.Value)
                {
                    NetworkIO.SetAlexLPFBits(0x10, freqIsTX, _mox);
                    SetupForm.rad6LPFled.Checked = true;
                }

                else if ((decimal)freq >= SetupForm.udAlex10mLPFStart.Value && // 12/10m LPF
                         (decimal)freq <= SetupForm.udAlex10mLPFEnd.Value)
                {
                    NetworkIO.SetAlexLPFBits(0x20, freqIsTX, _mox);
                    SetupForm.rad10LPFled.Checked = true;
                }

                else if ((decimal)freq >= SetupForm.udAlex15mLPFStart.Value && // 17/15 LPF
                          (decimal)freq <= SetupForm.udAlex15mLPFEnd.Value)
                {
                    NetworkIO.SetAlexLPFBits(0x40, freqIsTX, _mox);
                    SetupForm.rad15LPFled.Checked = true;
                }

                else
                {
                    NetworkIO.SetAlexLPFBits(0x10, freqIsTX, _mox); // 6m LPF
                    SetupForm.rad6LPFled.Checked = true;
                }
            }
        }

        public void SetAlex2LPF(double freq)
        {
            if (alexpresent && !initializing)
            {
                if ((decimal)freq >= SetupForm.udAlex220mLPFStart.Value && // 30/20m LPF
                          (decimal)freq <= SetupForm.udAlex220mLPFEnd.Value)
                {
                    NetworkIO.SetAlex2LPFBits(0x01);
                    SetupForm.radAlex220LPFled.Checked = true;
                }

                else if ((decimal)freq >= SetupForm.udAlex240mLPFStart.Value && // 60/40m LPF
                        (decimal)freq <= SetupForm.udAlex240mLPFEnd.Value)
                {
                    NetworkIO.SetAlex2LPFBits(0x02);
                    SetupForm.radAlex240LPFled.Checked = true;
                }

                else if ((decimal)freq >= SetupForm.udAlex280mLPFStart.Value && // 80m LPF
                         (decimal)freq <= SetupForm.udAlex280mLPFEnd.Value)
                {
                    NetworkIO.SetAlex2LPFBits(0x04);
                    SetupForm.radAlex280LPFled.Checked = true;
                }

                else if ((decimal)freq >= SetupForm.udAlex2160mLPFStart.Value && // 160m LPF
                     (decimal)freq <= SetupForm.udAlex2160mLPFEnd.Value)
                {
                    NetworkIO.SetAlex2LPFBits(0x08);
                    SetupForm.radAlex2160LPFled.Checked = true;
                }

                else if ((decimal)freq >= SetupForm.udAlex26mLPFStart.Value && // 6m LPF
                        (decimal)freq <= SetupForm.udAlex26mLPFEnd.Value)
                {
                    NetworkIO.SetAlex2LPFBits(0x10);
                    SetupForm.radAlex26LPFled.Checked = true;
                }

                else if ((decimal)freq >= SetupForm.udAlex210mLPFStart.Value && // 12/10m LPF
                         (decimal)freq <= SetupForm.udAlex210mLPFEnd.Value)
                {
                    NetworkIO.SetAlex2LPFBits(0x20);
                    SetupForm.radAlex210LPFled.Checked = true;
                }

                else if ((decimal)freq >= SetupForm.udAlex215mLPFStart.Value && // 17/15 LPF
                          (decimal)freq <= SetupForm.udAlex215mLPFEnd.Value)
                {
                    NetworkIO.SetAlex2LPFBits(0x40);
                    SetupForm.radAlex215LPFled.Checked = true;
                }

                else
                {
                    NetworkIO.SetAlex2LPFBits(0x10); // 6m LPF
                    SetupForm.radAlex26LPFled.Checked = true;
                }
            }
        }

        public void SelectRX1VarFilter(bool update = true)
        {
            if (rx1_filter == Filter.VAR1) return;
            if (rx1_filter == Filter.VAR2) return;

            // save current filter bounds, reset to var, set filter bounds 
            int high = (int)udFilterHigh.Value;
            int low = (int)udFilterLow.Value;
            radFilterVar1.Checked = true;
            if (update) UpdateRX1Filters(low, high);
        }

        public void SelectRX2VarFilter(bool update = true)
        {
            if (rx2_filter == Filter.VAR1) return;
            if (rx2_filter == Filter.VAR2) return;

            // save current filter bounds, reset to var, set filter bounds 
            int high = (int)udRX2FilterHigh.Value;
            int low = (int)udRX2FilterLow.Value;
            radRX2FilterVar1.Checked = true;
            if (update) UpdateRX2Filters(low, high);
        }

        public void UpdateRXADCCtrlP1()
        {
            NetworkIO.SetADC_cntrl_P1(rx_adc_ctrl_P1);
        }

        // Added 06/24/05 BT for CAT commands
        public void CATMemoryQS()
        {
            btnMemoryQuickSave_Click(this.btnMemoryQuickSave, EventArgs.Empty);
        }

        // Added 06/25/05 BT for CAT commands
        public void CATMemoryQR()
        {
            btnMemoryQuickRestore_Click(this.btnMemoryQuickRestore, EventArgs.Empty);
        }

        // BT 06/30/05 Added for CAT commands
        public int CATBandGroup
        {
            get
            {
                if (BandHFSelected)
                    return 0;
                else
                    return 1;
            }
            set
            {
                if (value == 0)
                    btnBandHF_Click(btnBandHF, EventArgs.Empty);
                else if (value == 1)
                    btnBandVHF_Click(btnBandVHF, EventArgs.Empty);
            }
        }

        // G8NJJ like CATBandGroup but covering SWL too
        // use the enum variables, because all 3 forms can be hidden when display collapsed
        public int BandGroup
        {
            get
            {
                if (_bands_GEN_selected)
                    return 2;
                else if (_bands_VHF_selected)
                    return 1;
                else
                    return 0;
            }
            set
            {
                if (value == 0)
                    btnBandHF_Click(btnBandHF, EventArgs.Empty);
                else if (value == 1)
                    btnBandVHF_Click(btnBandVHF, EventArgs.Empty);
                else if (value == 2)
                    btnBandGEN_Click(radBandGEN, EventArgs.Empty);
            }
        }

        //BT 06/17/05 added for CAT commands
        public void SetCATBand(Band pBand)
        {
            Band b = pBand;
            switch (b)
            {
                case Band.B160M:
                    radBand160_Click(this, EventArgs.Empty);
                    break;
                case Band.B80M:
                    radBand80_Click(this, EventArgs.Empty);
                    break;
                case Band.B60M:
                    radBand60_Click(this, EventArgs.Empty);
                    break;
                case Band.B40M:
                    radBand40_Click(this, EventArgs.Empty);
                    break;
                case Band.B30M:
                    radBand30_Click(this, EventArgs.Empty);
                    break;
                case Band.B20M:
                    radBand20_Click(this, EventArgs.Empty);
                    break;
                case Band.B17M:
                    radBand17_Click(this, EventArgs.Empty);
                    break;
                case Band.B15M:
                    radBand15_Click(this, EventArgs.Empty);
                    break;
                case Band.B12M:
                    radBand12_Click(this, EventArgs.Empty);
                    break;
                case Band.B10M:
                    radBand10_Click(this, EventArgs.Empty);
                    break;
                case Band.B6M:
                    radBand6_Click(this, EventArgs.Empty);
                    break;
                case Band.B2M:
                    radBand2_Click(this, EventArgs.Empty);
                    break;
                case Band.GEN:
                    radBandGEN_Click(this, EventArgs.Empty);
                    break;
                case Band.WWV:
                    radBandWWV_Click(this, EventArgs.Empty);
                    break;
                case Band.VHF0:
                    radBandVHF0.PerformClick();
                    break;
                case Band.VHF1:
                    radBandVHF1.PerformClick();
                    break;
                case Band.VHF2:
                    radBandVHF2.PerformClick();
                    break;
                case Band.VHF3:
                    radBandVHF3.PerformClick();
                    break;
                case Band.VHF4:
                    radBandVHF4.PerformClick();
                    break;
                case Band.VHF5:
                    radBandVHF5.PerformClick();
                    break;
                case Band.VHF6:
                    radBandVHF6.PerformClick();
                    break;
                case Band.VHF7:
                    radBandVHF7.PerformClick();
                    break;
                case Band.VHF8:
                    radBandVHF8.PerformClick();
                    break;
                case Band.VHF9:
                    radBandVHF9.PerformClick();
                    break;
                case Band.VHF10:
                    radBandVHF10.PerformClick();
                    break;
                case Band.VHF11:
                    radBandVHF11.PerformClick();
                    break;
                case Band.VHF12:
                    radBandVHF12.PerformClick();
                    break;
                case Band.VHF13:
                    radBandVHF13.PerformClick();
                    break;
                default:
                    radBandGEN_Click(this, EventArgs.Empty);
                    break;
            }
            repopulateForms();
        }


        public void SetVHFText(int index, string text)
        {
            string old_text = vhf_text[index].Text;
            vhf_text[index].Text = text;
            if (old_text != text) VHFDetailsChangedHandlers?.Invoke(index, vhf_text[index].Enabled, vhf_text[index].Enabled, old_text, vhf_text[index].Text);
        }

        public void SetVHFEnabled(int index, bool b)
        {
            bool old_state = vhf_text[index].Enabled;
            vhf_text[index].Enabled = b;
            if (old_state != b) VHFDetailsChangedHandlers?.Invoke(index, old_state, b, vhf_text[index].Text, vhf_text[index].Text);
        }

        // G8NJJ added to allow labelling of buttons in popup form
        public string GetVHFText(int index)
        {
            return vhf_text[index].Text;
        }
        public bool GetVHFEnabled(int index)
        {
            return vhf_text[index].Enabled;
        }

        private bool m_bLimitFiltersToSidebands = false;    //MW0LGE_21k9
        public bool LimitFiltersToSideBands
        {
            get { return m_bLimitFiltersToSidebands; }
            set { m_bLimitFiltersToSidebands = value; }
        }
        private int m_nLowOutRX1;  // bit of a work around instead of having to add ref to UpdateRX1Filters //MW0LGE_21k9d
        private int m_nHighOutRX1;
        private int m_nLowOutRX2;
        private int m_nHighOutRX2;
        public void UpdateRX1Filters(int low, int high)
        {
            int oldLow, oldHigh;
            if (rx1_filter == Filter.FIRST || rx1_filter == Filter.LAST || rx1_dsp_mode == DSPMode.FIRST || rx1_dsp_mode == DSPMode.LAST)
            {
                oldLow = 0;
                oldHigh = 0;
            }
            else
            {
                oldLow = rx1_filters[(int)rx1_dsp_mode].GetLow(rx1_filter);
                oldHigh = rx1_filters[(int)rx1_dsp_mode].GetHigh(rx1_filter);
            }

            switch (rx1_dsp_mode)
            {
                case DSPMode.LSB:
                case DSPMode.DIGL:
                case DSPMode.CWL:
                    if (low > high - 10) low = high - 10;
                    break;
                case DSPMode.USB:
                case DSPMode.DIGU:
                case DSPMode.CWU:
                    if (high < low + 10) high = low + 10;
                    break;
                case DSPMode.AM:
                case DSPMode.SAM:
                case DSPMode.DSB:
                case DSPMode.SPEC: //MW0LGE_21k9
                    if (high < low + 10)
                    {
                        if (Math.Abs(high) < Math.Abs(low))
                            high = low + 10;
                        else
                            low = high - 10;
                    }
                    break;
                case DSPMode.FM:
                    int halfBw = (int)(radio.GetDSPTX(0).TXFMDeviation + radio.GetDSPRX(0, 0).RXFMHighCut);  //[2.10.3.4]MW0LGE
                    int bw = ((halfBw * 2) / 1000);
                    low = -halfBw;
                    high = halfBw;
                    lblFilterLabel.Text = bw.ToString() + "k";
                    break;
            }

            //MW0LGE_21k9
            limitFilterToSidebands(ref low, ref high, 1);

            if (rx1_dsp_mode != DSPMode.FM) //[2.10.3.4]MW0LGE bypass for FM
            {
                if (low < -max_filter_width)
                    low = -max_filter_width;
                if (high > max_filter_width)
                    high = max_filter_width;
                if (high < -max_filter_width)
                    high = -max_filter_width;
                if (low > max_filter_width)
                    low = max_filter_width;
            }

            // send the settings to the DSP
            if (low == high) return;

            {
                radio.GetDSPRX(0, 0).SetRXFilter(low, high);
                radio.GetDSPRX(0, 1).SetRXFilter(low, high);
            }

            // send the setting to the display
            Display.RX1FilterLow = low;
            Display.RX1FilterHigh = high;

            // update var filter controls
            udFilterLow.Value = low;
            udFilterHigh.Value = high;

            // update Filter Shift
            ptbFilterShift_Update(low, high);

            // update Filter Width
            ptbFilterWidth_Update(low, high);

            // Update Display data if not in panadapter mode
            if (!radio.GetDSPRX(0, 0).SpectrumPreFilter)
                UpdateRXDisplayVars(low, high);

            // set XIT step rate
            if ((high - low) > 250)
            {
                udXIT.Increment = 10;
                udRIT.Increment = 10;
            }
            else
            {
                udXIT.Increment = 5;
                udRIT.Increment = 5;
            }

            if (filterRX1Form != null && !filterRX1Form.IsDisposed)
            {
                if (filterRX1Form.DSPMode == rx1_dsp_mode)
                    filterRX1Form.CurrentFilter = rx1_filter;
            }

            if (oldLow != low || oldHigh != high) FilterEdgesChangedHandlers?.Invoke(1, rx1_filter, RX1Band, low, high, rx1_filters[(int)rx1_dsp_mode].GetName(rx1_filter)); //MW0LGE [2.9.0.7]

            m_nLowOutRX1 = low;
            m_nHighOutRX1 = high;
        }

        public void UpdateRX2Filters(int low, int high)
        {
            int oldLow, oldHigh;
            if (rx2_filter == Filter.FIRST || rx2_filter == Filter.LAST || rx2_dsp_mode == DSPMode.FIRST || rx2_dsp_mode == DSPMode.LAST)
            {
                oldLow = 0;
                oldHigh = 0;
            }
            else
            {
                oldLow = rx2_filters[(int)rx2_dsp_mode].GetLow(rx2_filter);
                oldHigh = rx2_filters[(int)rx2_dsp_mode].GetHigh(rx2_filter);
            }

            switch (rx2_dsp_mode)
            {
                case DSPMode.LSB:
                case DSPMode.DIGL:
                case DSPMode.CWL:
                    if (low > high - 10) low = high - 10;
                    break;
                case DSPMode.USB:
                case DSPMode.DIGU:
                case DSPMode.CWU:
                    if (high < low + 10) high = low + 10;
                    break;
                case DSPMode.AM:
                case DSPMode.SAM:
                case DSPMode.DSB:
                case DSPMode.SPEC: //MW0LGE_21k9
                    if (high < low + 10)
                    {
                        if (Math.Abs(high) < Math.Abs(low))
                            high = low + 10;
                        else
                            low = high - 10;
                    }
                    break;
                case DSPMode.FM:
                    int halfBw = (int)(radio.GetDSPTX(0).TXFMDeviation + radio.GetDSPRX(1, 0).RXFMHighCut);  //[2.10.3.4]MW0LGE
                    low = -halfBw;
                    high = halfBw;
                    break;
            }

            //MW0LGE_21k9
            limitFilterToSidebands(ref low, ref high, 2);

            if (rx1_dsp_mode != DSPMode.FM) //[2.10.3.4]MW0LGE bypass for FM
            {
                if (low < -max_filter_width)
                    low = -max_filter_width;
                if (high > max_filter_width)
                    high = max_filter_width;
                if (high < -max_filter_width)
                    high = -max_filter_width;
                if (low > max_filter_width)
                    low = max_filter_width;
            }

            // send the settings to the DSP
            if (low == high) return;

            // send the settings to the DSP
            radio.GetDSPRX(1, 0).SetRXFilter(low, high);
            radio.GetDSPRX(1, 1).SetRXFilter(low, high);

            // send the setting to the display
            Display.RX2FilterLow = low;
            Display.RX2FilterHigh = high;

            // update var filter controls
            udRX2FilterLow.Value = low;
            udRX2FilterHigh.Value = high;

            if (filterRX2Form != null && !filterRX2Form.IsDisposed)
            {
                if (filterRX2Form.DSPMode == rx2_dsp_mode)
                    filterRX2Form.CurrentFilter = rx2_filter;
            }

            if (oldLow != low || oldHigh != high) FilterEdgesChangedHandlers?.Invoke(2, rx2_filter, RX2Band, low, high, rx1_filters[(int)rx2_dsp_mode].GetName(rx2_filter)); //MW0LGE [2.9.0.7]

            m_nLowOutRX2 = low;
            m_nHighOutRX2 = high;
        }

        public void UpdateRX1FilterNames(Filter f, string old_name, string new_name)
        {
            switch (f)
            {
                case Filter.F1:
                    radFilter1.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.F1);
                    break;
                case Filter.F2:
                    radFilter2.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.F2);
                    break;
                case Filter.F3:
                    radFilter3.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.F3);
                    break;
                case Filter.F4:
                    radFilter4.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.F4);
                    break;
                case Filter.F5:
                    radFilter5.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.F5);
                    break;
                case Filter.F6:
                    radFilter6.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.F6);
                    break;
                case Filter.F7:
                    radFilter7.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.F7);
                    break;
                case Filter.F8:
                    radFilter8.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.F8);
                    break;
                case Filter.F9:
                    radFilter9.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.F9);
                    break;
                case Filter.F10:
                    radFilter10.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.F10);
                    break;
                case Filter.VAR1:
                    radFilterVar1.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.VAR1);
                    break;
                case Filter.VAR2:
                    radFilterVar2.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.VAR2);
                    break;
            }

            if (f == rx1_filter)
                panelFilter.Text = "Filter - " + rx1_filters[(int)rx1_dsp_mode].GetName(f);

            //if (old_name != new_name) FilterNameChangedHandlers?.Invoke(1, f, old_name, new_name);
            if (old_name != new_name) FilterChangedHandlers?.Invoke(1, f, f, RX1Band, rx1_filters[(int)rx1_dsp_mode].GetLow(f), rx1_filters[(int)rx1_dsp_mode].GetHigh(f), rx1_filters[(int)rx1_dsp_mode].GetName(f));
        }

        public void UpdateRX1FilterPresetLow(int val)
        {
            UpdateRX1Filters(val, (int)udFilterHigh.Value);
        }

        public void UpdateRX1FilterPresetHigh(int val)
        {
            UpdateRX1Filters((int)udFilterLow.Value, val);
        }

        public void UpdateRX2FilterNames(Filter f, string old_name, string new_name)
        {
            switch (f)
            {
                case Filter.F1:
                    radRX2Filter1.Text = rx2_filters[(int)rx2_dsp_mode].GetName(Filter.F1);
                    break;
                case Filter.F2:
                    radRX2Filter2.Text = rx2_filters[(int)rx2_dsp_mode].GetName(Filter.F2);
                    break;
                case Filter.F3:
                    radRX2Filter3.Text = rx2_filters[(int)rx2_dsp_mode].GetName(Filter.F3);
                    break;
                case Filter.F4:
                    radRX2Filter4.Text = rx2_filters[(int)rx2_dsp_mode].GetName(Filter.F4);
                    break;
                case Filter.F5:
                    radRX2Filter5.Text = rx2_filters[(int)rx2_dsp_mode].GetName(Filter.F5);
                    break;
                case Filter.F6:
                    radRX2Filter6.Text = rx2_filters[(int)rx2_dsp_mode].GetName(Filter.F6);
                    break;
                case Filter.F7:
                    radRX2Filter7.Text = rx2_filters[(int)rx2_dsp_mode].GetName(Filter.F7);
                    break;
                case Filter.VAR1:
                    radRX2FilterVar1.Text = rx2_filters[(int)rx2_dsp_mode].GetName(Filter.VAR1);
                    break;
                case Filter.VAR2:
                    radRX2FilterVar2.Text = rx2_filters[(int)rx2_dsp_mode].GetName(Filter.VAR2);
                    break;
            }

            if (f == rx2_filter)
                panelRX2Filter.Text = "RX2 Filter - " + rx2_filters[(int)rx2_dsp_mode].GetName(f);

            //if (old_name != new_name) FilterNameChangedHandlers?.Invoke(2, f, old_name, new_name);
            if (old_name != new_name) FilterChangedHandlers?.Invoke(2, f, f, RX2Band, rx2_filters[(int)rx2_dsp_mode].GetLow(f), rx2_filters[(int)rx2_dsp_mode].GetHigh(f), rx2_filters[(int)rx2_dsp_mode].GetName(f));
        }

        public void UpdateRX2FilterPresetLow(int val)
        {
            UpdateRX2Filters(val, (int)udRX2FilterHigh.Value);
        }

        public void UpdateRX2FilterPresetHigh(int val)
        {
            UpdateRX2Filters((int)udRX2FilterLow.Value, val);
        }

        public void UpdateVFOAFreq(string freq)
        {	// only do this routine if there are six digits after the decimal point.
            m_dVFOAFreq = freqFromString(freq); //MW0LGE 
            txtVFOAFreq.Text = freq;
            txtVFOAMSD.Text = freq;

            string temp = freq;
            int index = temp.IndexOf(separator) + 4;
            txtVFOALSD.Text = temp.Remove(0, index);
        }

        private bool sioPut(object sio_listener, string msg)
        {
            //MW0LGE [2.10.3.6_dev4]
            //had to implement like this due to non oo implementation of sio listeners
            if (sio_listener == null) { return false; }

            bool ret = false;
            try
            {
                switch (sio_listener)
                {
                    case SIOListenerII siol:
                        if (siol.SIO != null)
                        {
                            if (siol.SIO.IsOpen)
                            {
                                siol.SIO.put(msg);
                                ret = true;
                            }
                        }
                        break;
                    case SIO2ListenerII siol2:
                        if (siol2.SIO2 != null)
                        {
                            if (siol2.SIO2.IsOpen)
                            {
                                siol2.SIO2.put(msg);
                                ret = true;
                            }
                        }
                        break;
                    case SIO3ListenerII siol3:
                        if (siol3.SIO3 != null)
                        {
                            if (siol3.SIO3.IsOpen)
                            {
                                siol3.SIO3.put(msg);
                                ret = true;
                            }
                        }
                        break;
                    case SIO4ListenerII siol4:
                        if (siol4.SIO4 != null)
                        {
                            if (siol4.SIO4.IsOpen)
                            {
                                siol4.SIO4.put(msg);
                                ret = true;
                            }
                        }
                        break;
                }
            }
            catch { }

            return ret;
        }
        private void BroadcastFreqChange(string vfo, double freq)
        {
            if (IsSetupFormNull) return;

            Dictionary<string, bool> ken = SetupForm.KenwoodAISettings;

            string cmd = "F" + vfo + freq.ToString("f6").Replace(separator, "").PadLeft(11, '0') + ";"; //MW0LGE_22a

            if (ken["port1"]) sioPut(Siolisten, cmd);
            if (ken["port2"]) sioPut(Sio2listen, cmd);
            if (ken["port3"]) sioPut(Sio3listen, cmd);
            if (ken["port4"]) sioPut(Sio4listen, cmd);

            //if (Siolisten != null && Siolisten.SIO != null)
            //{
            //    try
            //    {
            //        if (Siolisten.SIO.IsOpen) Siolisten.SIO.put(cmd);
            //    }
            //    catch { }
            //}

            if (m_tcpCATServer != null && ken["tcp"])
                m_tcpCATServer.SendToClients(cmd);
        }

        public void UpdateVFOBFreq(string freq)
        {	// only do this routine if there are six digits after the decimal point.
            m_dVFOBFreq = freqFromString(freq);
            txtVFOBFreq.Text = freq;
            txtVFOBMSD.Text = freq;

            string temp = freq;
            int index = temp.IndexOf(separator) + 4;
            txtVFOBLSD.Text = temp.Remove(0, index);
        }

        public void CalcDisplayFreq()
        {
            if (Display.CurrentDisplayMode != DisplayMode.PANADAPTER &&
                Display.CurrentDisplayMode != DisplayMode.WATERFALL &&
                Display.CurrentDisplayMode != DisplayMode.PANAFALL &&
                Display.CurrentDisplayMode != DisplayMode.PANASCOPE)
                return;

            if (!initializing)
                specRX.GetSpecRX(0).initAnalyzer();
        }

        public void CalcRX2DisplayFreq()
        {
            if (Display.CurrentDisplayModeBottom != DisplayMode.PANADAPTER &&
                Display.CurrentDisplayModeBottom != DisplayMode.WATERFALL &&
                Display.CurrentDisplayMode != DisplayMode.PANAFALL)
                return;

            if (!initializing)
                specRX.GetSpecRX(1).initAnalyzer();
        }

        public void CalcTXDisplayFreq()
        {
            if (!initializing)
                specRX.GetSpecRX(cmaster.inid(1, 0)).initAnalyzer();
        }

        public void UpdateRXSpectrumDisplayVars()
        {
            UpdateRXDisplayVars((int)udFilterLow.Value, (int)udFilterHigh.Value);
        }

        public void UpdateTXSpectrumDisplayVars()
        {
            UpdateTXDisplayVars(radio.GetDSPTX(0).TXFilterLow, radio.GetDSPTX(0).TXFilterHigh);
        }

        private void UpdateRXDisplayVars(int l, int h)
        {
            if (Display.CurrentDisplayMode != DisplayMode.SPECTRUM &&
               Display.CurrentDisplayMode != DisplayMode.HISTOGRAM &&
               Display.CurrentDisplayMode != DisplayMode.SPECTRASCOPE)
                return;
            int low = 0, high = 0;
            const int extra = 1000;
            const int little_extra = 500;
            int spec_blocksize = radio.GetDSPRX(0, 0).BufferSize;

            switch (rx1_dsp_mode)
            {
                case DSPMode.LSB:
                    low = l - extra;
                    high = 0;
                    break;
                case DSPMode.CWL:
                case DSPMode.DIGL:
                    low = l - little_extra;
                    high = 0;
                    break;
                case DSPMode.USB:
                    low = 0;
                    high = h + extra;
                    break;
                case DSPMode.CWU:
                case DSPMode.DIGU:
                    low = 0;
                    high = h + little_extra;
                    break;
                default:
                    low = l - extra;
                    high = h + extra;
                    break;
            }

            Display.RXSpectrumDisplayLow = low;
            Display.RXSpectrumDisplayHigh = high;
            specRX.GetSpecRX(0).CalcSpectrum(low, high, spec_blocksize, 48000);
        }

        private void UpdateTXDisplayVars(int l, int h)
        {
            if (Display.CurrentDisplayMode != DisplayMode.SPECTRUM &&
                Display.CurrentDisplayMode != DisplayMode.HISTOGRAM &&
                Display.CurrentDisplayMode != DisplayMode.SPECTRASCOPE)
                return;

            int low = 0, high = 0;
            int spec_blocksize = radio.GetDSPTX(0).BufferSize;
            if (l < 0 && h <= 0)
            {
                high = 0;
                if (l >= -910)
                    low = -1000;
                else
                    low = (int)(l * 1.1);
            }
            else if (l >= 0 && h > 0)
            {
                low = 0;
                if (h <= 910)
                    high = 1000;
                else
                    high = (int)(h * 1.1);
            }
            else if (l < 0 && h > 0)
            {
                int max_edge = Math.Max(-l, h);
                low = (int)(max_edge * -1.1);
                high = (int)(max_edge * 1.1);
            }

            Display.TXSpectrumDisplayLow = low;
            Display.TXSpectrumDisplayHigh = high;
            specRX.GetSpecRX(cmaster.inid(1, 0)).CalcSpectrum(low, high, spec_blocksize, 96000);
        }

        public void SetTXFilters(DSPMode mode, int low, int high)
        {
            int l = 0, h = 0;
            switch (mode)
            {
                case DSPMode.LSB:
                case DSPMode.CWL:
                case DSPMode.DIGL:
                    l = -high;
                    h = -low;
                    break;
                case DSPMode.USB:
                case DSPMode.CWU:
                case DSPMode.DIGU:
                    l = low;
                    h = high;
                    break;
                case DSPMode.DSB:
                    l = -high;
                    h = high;
                    break;
                case DSPMode.AM:
                case DSPMode.SAM:
                    l = -high;
                    h = high;
                    break;
                case DSPMode.FM:
                    int halfBw = (int)(radio.GetDSPTX(0).TXFMDeviation + radio.GetDSPTX(0).TXFMHighCut); //[2.10.3.4]MW0LGE
                    l = -halfBw;
                    h = halfBw;
                    break;
                case DSPMode.DRM:
                    l = 7000;
                    h = 17000;
                    break;
            }

            switch (Display.CurrentDisplayMode)
            {
                case DisplayMode.PANADAPTER:
                case DisplayMode.WATERFALL:
                case DisplayMode.PANAFALL:
                case DisplayMode.PANASCOPE:
                    break;
                default:
                    UpdateTXDisplayVars(l, h);
                    break;
            }

            radio.GetDSPTX(0).SetTXFilter(l, h);
            if (mode == DSPMode.FM)
            {
                radio.GetDSPTX(0).Force = true;
                radio.GetDSPTX(0).TXFMLowCut = radio.GetDSPTX(0).TXFMLowCut;
                radio.GetDSPTX(0).TXFMHighCut = radio.GetDSPTX(0).TXFMHighCut;
                radio.GetDSPTX(0).Force = false;
            }

            Display.TXFilterLow = l;
            Display.TXFilterHigh = h;
        }

        public void BuildTXProfileCombos()
        {
            comboTXProfile.Items.Clear();
            comboDigTXProfile.Items.Clear();
            comboFMTXProfile.Items.Clear();
            comboAMTXProfile.Items.Clear();

            string[] s = SetupForm.GetTXProfileStrings();
            comboTXProfile.Items.AddRange(s);
            comboDigTXProfile.Items.AddRange(s);
            comboFMTXProfile.Items.AddRange(s);
            comboAMTXProfile.Items.AddRange(s);
        }

        public void UpdateTXProfile(string name)
        {
            if (IsSetupFormNull) return;

            string oldTXProfile = comboTXProfile.Text;
            string oldDigTXProfile = comboDigTXProfile.Text;
            string oldFMTXProfile = comboFMTXProfile.Text;
            string oldAMTXProfile = comboAMTXProfile.Text;

            BuildTXProfileCombos();

            switch (rx1_dsp_mode)
            {
                case DSPMode.DIGL:
                case DSPMode.DIGU:
                    comboDigTXProfile.Text = name;
                    comboTXProfile.Text = oldTXProfile;
                    comboFMTXProfile.Text = oldFMTXProfile;
                    comboAMTXProfile.Text = oldAMTXProfile;
                    break;
                case DSPMode.FM:
                    comboFMTXProfile.Text = name;
                    comboDigTXProfile.Text = oldDigTXProfile;
                    comboTXProfile.Text = oldTXProfile;
                    comboAMTXProfile.Text = oldAMTXProfile;
                    break;
                case DSPMode.AM:
                case DSPMode.SAM:
                    comboAMTXProfile.Text = name;
                    comboDigTXProfile.Text = oldDigTXProfile;
                    comboTXProfile.Text = oldTXProfile;
                    comboFMTXProfile.Text = oldFMTXProfile;
                    break;
                default:
                    comboTXProfile.Text = name;
                    comboDigTXProfile.Text = oldDigTXProfile;
                    comboFMTXProfile.Text = oldFMTXProfile;
                    comboAMTXProfile.Text = oldAMTXProfile;
                    break;
            }

            if (string.IsNullOrEmpty(comboTXProfile.Text)) comboTXProfile.Text = "Default";
            if (string.IsNullOrEmpty(comboDigTXProfile.Text)) comboDigTXProfile.Text = "Default";
            if (string.IsNullOrEmpty(comboFMTXProfile.Text)) comboFMTXProfile.Text = "Default";
            if (string.IsNullOrEmpty(comboAMTXProfile.Text)) comboAMTXProfile.Text = "Default";
        }
        // Diversity operation is on RX1; therefore, the 'rx1_rate' will be used as the diversity rate;
        public void UpdateDDCs(bool rx2_enabled)
        {
            if (initializing) return;
            int DDCEnable = 0;
            int DDC0 = 1, DDC1 = 2, DDC2 = 4, DDC3 = 8;
            int SyncEnable = 0;
            int[] Rate = new int[8];
            int i;
            int rx1_rate = SampleRateRX1;
            int rx2_rate = SampleRateRX2;
            int ps_rate = cmaster.PSrate;
            int P1_DDCConfig = 0;
            int P1_diversity = 0;
            int P1_rxcount = 0;
            int nddc = 0;
            int cntrl1 = 0;
            int cntrl2 = 0;
            if (diversity2)
                P1_diversity = 1;

            switch (current_hpsdr_model)
            {
                case HPSDRModel.ANAN100D:
                case HPSDRModel.ANAN200D:
                case HPSDRModel.ORIONMKII:
                case HPSDRModel.ANAN7000D:
                case HPSDRModel.ANAN8000D:
                case HPSDRModel.ANAN_G2:
                case HPSDRModel.ANAN_G2_1K:
                    P1_rxcount = 5;                     // RX5 used for puresignal feedback
                    nddc = 5;
                    if (!_mox)
                    {
                        if (diversity2)
                        {
                            P1_DDCConfig =
                            DDCEnable = DDC0;
                            SyncEnable = DDC1;
                            Rate[0] = rx1_rate;
                            Rate[1] = rx1_rate;
                            cntrl1 = rx_adc_ctrl1 & 0xff;
                            cntrl2 = rx_adc_ctrl2 & 0x3f;
                        }
                        else
                        {
                            P1_DDCConfig = 1;
                            DDCEnable = DDC2;
                            SyncEnable = 0;
                            Rate[2] = rx1_rate;
                            cntrl1 = rx_adc_ctrl1 & 0xff;
                            cntrl2 = rx_adc_ctrl2 & 0x3f;
                        }
                    }
                    else
                    {
                        if (!diversity2 && !psform.PSEnabled)
                        {
                            P1_DDCConfig = 1;
                            DDCEnable = DDC2;
                            SyncEnable = 0;
                            Rate[2] = rx1_rate;
                            cntrl1 = rx_adc_ctrl1 & 0xff;
                            cntrl2 = rx_adc_ctrl2 & 0x3f;
                        }
                        else if (!diversity2 && psform.PSEnabled)
                        {
                            P1_DDCConfig = 3;
                            DDCEnable = DDC0 + DDC2;
                            SyncEnable = DDC1;
                            Rate[0] = ps_rate;
                            Rate[1] = ps_rate;
                            Rate[2] = rx1_rate;
                            cntrl1 = (rx_adc_ctrl1 & 0xf3) | 0x08;
                            cntrl2 = rx_adc_ctrl2 & 0x3f;
                        }
                        else if (diversity2 && psform.PSEnabled)
                        {
                            P1_DDCConfig = 3;
                            DDCEnable = DDC0 + DDC2;
                            SyncEnable = DDC1;
                            Rate[0] = ps_rate;
                            Rate[1] = ps_rate;
                            Rate[2] = rx1_rate;
                            cntrl1 = (rx_adc_ctrl1 & 0xf3) | 0x08;
                            cntrl2 = rx_adc_ctrl2 & 0x3f;
                        }
                        else
                        {// diversity2 && !psform.PSEnabled
                            P1_DDCConfig = 2;
                            DDCEnable = DDC0;
                            SyncEnable = DDC1;
                            Rate[0] = rx1_rate;
                            Rate[1] = rx1_rate;
                            cntrl1 = rx_adc_ctrl1 & 0xff;
                            cntrl2 = rx_adc_ctrl2 & 0x3f;
                        }
                    }

                    if (rx2_enabled)
                    {
                        DDCEnable += DDC3;
                        Rate[3] = rx2_rate;
                    }
                    break;
                case HPSDRModel.HERMES:
                case HPSDRModel.ANAN10:
                case HPSDRModel.ANAN100:
                    P1_rxcount = 4;                     // RX4 used for puresignal feedback
                    nddc = 4;
                    if (!_mox)
                    {
                        if (!diversity2)
                        {
                            P1_DDCConfig = 4;
                            DDCEnable = DDC0;
                            SyncEnable = 0;
                            Rate[0] = rx1_rate;
                            cntrl1 = 0;
                            cntrl2 = 0;

                            if (rx2_enabled)
                            {
                                DDCEnable += DDC1;
                                Rate[1] = rx2_rate;
                            }
                        }
                        else
                        {
                            P1_DDCConfig = 5;
                            DDCEnable = DDC0;
                            SyncEnable = DDC1;
                            Rate[0] = rx1_rate;
                            Rate[1] = rx1_rate;
                            cntrl1 = 0;
                            cntrl2 = 0;
                        }
                    }
                    else
                    {
                        if (!diversity2 && !psform.PSEnabled)
                        {
                            P1_DDCConfig = 4;
                            DDCEnable = DDC0;
                            SyncEnable = 0;
                            Rate[0] = rx1_rate;
                            cntrl1 = 0;
                            cntrl2 = 0;

                            if (rx2_enabled)
                            {
                                DDCEnable += DDC1;
                                Rate[1] = rx2_rate;
                            }
                        }
                        else if (diversity2 && !psform.PSEnabled)
                        {
                            P1_DDCConfig = 5;
                            DDCEnable = DDC0;
                            SyncEnable = DDC1;
                            Rate[0] = rx1_rate;
                            Rate[1] = rx1_rate;
                            cntrl1 = 0;
                            cntrl2 = 0;
                        }
                        else // transmitting and PS is ON
                        {
                            P1_DDCConfig = 6;
                            DDCEnable = DDC0;
                            SyncEnable = DDC1;
                            Rate[0] = ps_rate;
                            Rate[1] = ps_rate;
                            cntrl1 = 4;
                            cntrl2 = 0;
                        }
                    }
                    break;

                case HPSDRModel.ANAN10E:
                case HPSDRModel.ANAN100B:
                    P1_rxcount = 2;                     // RX2 used for puresignal feedback
                    nddc = 2;
                    if (!_mox)
                    {
                        if (!diversity2)
                        {
                            P1_DDCConfig = 4;
                            DDCEnable = DDC0;
                            SyncEnable = 0;
                            Rate[0] = rx1_rate;
                            cntrl1 = 0;
                            cntrl2 = 0;

                            if (rx2_enabled)
                            {
                                DDCEnable += DDC1;
                                Rate[1] = rx2_rate;
                            }
                        }
                        else
                        {
                            P1_DDCConfig = 5;
                            DDCEnable = DDC0;
                            SyncEnable = DDC1;
                            Rate[0] = rx1_rate;
                            Rate[1] = rx1_rate;
                            cntrl1 = 0;
                            cntrl2 = 0;
                        }
                    }
                    else
                    {
                        if (!diversity2 && !psform.PSEnabled)
                        {
                            P1_DDCConfig = 4;
                            DDCEnable = DDC0;
                            SyncEnable = 0;
                            Rate[0] = rx1_rate;
                            cntrl1 = 0;
                            cntrl2 = 0;

                            if (rx2_enabled)
                            {
                                DDCEnable += DDC1;
                                Rate[1] = rx2_rate;
                            }
                        }
                        else if (diversity2 && !psform.PSEnabled)
                        {
                            P1_DDCConfig = 5;
                            DDCEnable = DDC0;
                            SyncEnable = DDC1;
                            Rate[0] = rx1_rate;
                            Rate[1] = rx1_rate;
                            cntrl1 = 0;
                            cntrl2 = 0;
                        }
                        else // transmitting and PS is ON
                        {
                            P1_DDCConfig = 5;
                            DDCEnable = DDC0;
                            SyncEnable = DDC1;
                            Rate[0] = ps_rate;
                            Rate[1] = ps_rate;
                            cntrl1 = 4;
                            cntrl2 = 0;
                        }
                    }
                    break;

                case HPSDRModel.HPSDR:
                    break;
            }

            NetworkIO.EnableRxs(DDCEnable);
            NetworkIO.EnableRxSync(0, SyncEnable);
            for (i = 0; i < 4; i++)
                NetworkIO.SetDDCRate(i, Rate[i]);
            NetworkIO.SetADC_cntrl1(cntrl1);
            NetworkIO.SetADC_cntrl2(cntrl2);
            NetworkIO.CmdRx();
            NetworkIO.Protocol1DDCConfig(P1_DDCConfig, P1_diversity, P1_rxcount, nddc);

            //MW0LGE_21e
            if (!IsSetupFormNull) SetupForm.UpdateDDCTab();
        }

        public void GetDDC(out int DDCrx1, out int DDCrx2, out int DDCsync1, out int DDCsync2, out int DDCpsrx, out int DDCpstx)
        {
            //https://docs.google.com/spreadsheets/d/1DbOAXuhHRE1hMBwz8PyxL5FblW5BoiAUzksPaGM0NXY

            int rx1 = -1, rx2 = -1, sync1 = -1, sync2 = -1, psrx = -1, pstx = -1;

            int nME = MOX ? 1 : 0; // [0]
            int nDE = diversityForm != null && Diversity2 ? 1 : 0; // [1]
            int nPSE = psform.PSEnabled ? 1 : 0; // [2]

            int tot = nME + (nDE << 1) + (nPSE << 2);

            if (NetworkIO.CurrentRadioProtocol == RadioProtocol.ETH) // P2
            {
                switch (CurrentHPSDRHardware)
                {
                    case HPSDRHW.Angelia: // ANAN-100D
                    case HPSDRHW.Orion: // ANAN-200D
                    case HPSDRHW.OrionMKII: // ANAN-7000DLE 7000DLEMkII ANAN-8000DLE OrionMkII
                    case HPSDRHW.Saturn:        // ANAN-G2, G21K    (G8NJJ)
                        switch (tot)
                        {
                            case 0: // off[2] off[1] off[0]
                                rx1 = 2;
                                rx2 = 3;
                                break;
                            case 1: // off off on
                                rx1 = 2;
                                rx2 = 3;
                                break;
                            case 2: // off on off
                                sync1 = 0;
                                sync2 = 1;
                                rx2 = 3;
                                break;
                            case 3: // off on on
                                sync1 = 0;
                                sync2 = 1;
                                rx2 = 3;
                                break;
                            case 4: // on off off
                                rx1 = 2;
                                rx2 = 3;
                                break;
                            case 5: // on off on
                                rx1 = 2;
                                rx2 = 3;
                                break;
                            case 6: // on on off
                                sync1 = 0;
                                sync2 = 1;
                                rx2 = 3;
                                break;
                            case 7: // on on on
                                rx1 = 2;
                                rx2 = 3;
                                break;
                        }
                        break;
                    //case HPSDRHW.Atlas: /// ???
                    case HPSDRHW.Hermes: // ANAN-10 ANAN-100 Heremes
                    case HPSDRHW.HermesII: // ANAN-10E ANAN-100B HeremesII
                        switch (tot)
                        {
                            case 0: // off off off
                                rx1 = 0;
                                rx2 = 1;
                                break;
                            case 1: // off off on
                                rx1 = 0;   //MW0LGE_22b missed out
                                rx2 = 1;
                                break;
                            case 2: // off on off
                                sync1 = 0;
                                sync2 = 1;
                                break;
                            case 3: // off on on
                                sync1 = 0;
                                sync2 = 1;
                                break;
                            case 4: // on off off
                                rx1 = 0;
                                rx2 = 1;
                                break;
                            case 5: // on off on
                                break;
                            case 6: // on on off
                                sync1 = 0;
                                sync2 = 1;
                                break;
                            case 7: // on on on
                                break;
                        }
                        break;
                }
            }
            else if (NetworkIO.CurrentRadioProtocol == RadioProtocol.USB) // P1
            {
                switch (CurrentHPSDRHardware)
                {
                    case HPSDRHW.Angelia: // ANAN-100D (all 5 adc)
                    case HPSDRHW.Orion: // ANAN-200D
                    case HPSDRHW.OrionMKII: // ANAN-7000DLE 7000DLEMkII ANAN-8000DLE OrionMkII
                                            // (note Saturn would only be used with P2, so not added here)
                        switch (tot)
                        {
                            case 0: // off off off
                                rx1 = 0;
                                rx2 = 2;
                                break;
                            case 1: // off off on
                                rx1 = 0;
                                rx2 = 2;
                                break;
                            case 2: // off on off
                                //rx1 = 0;
                                sync1 = 0;
                                sync2 = 1;
                                rx2 = 2;
                                break;
                            case 3: // off on on
                                //rx1 = 0;
                                sync1 = 0;
                                sync2 = 1;
                                rx2 = 2;
                                break;
                            case 4: // on off off
                                rx1 = 0;
                                rx2 = 2;
                                break;
                            case 5: // on off on
                                rx1 = 0;
                                rx2 = 2;
                                psrx = 3;
                                pstx = 4;
                                break;
                            case 6: // on on off
                                //rx1 = 0;
                                sync1 = 0;
                                sync2 = 1;
                                rx2 = 2;
                                break;
                            case 7: // on on on
                                //rx1 = 0;
                                sync1 = 0;
                                sync2 = 1;
                                rx2 = 2;
                                psrx = 3;
                                pstx = 4;
                                break;
                        }
                        break;
                    //                    case HPSDRHW.Atlas: /// ???
                    case HPSDRHW.Hermes: // ANAN-10 ANAN-100 Heremes (4 adc)
                        switch (tot)
                        {
                            case 0: // off off off
                                rx1 = 0;
                                rx2 = 1;
                                break;
                            case 1: // off off on
                                rx1 = 0;
                                rx2 = 1;
                                break;
                            case 2: // off on off
                                rx1 = 0;
                                rx2 = 1;
                                break;
                            case 3: // off on on
                                rx1 = 0;
                                rx2 = 1;
                                break;
                            case 4: // on off off
                                rx1 = 0;
                                rx2 = 1;
                                break;
                            case 5: // on off on
                                rx1 = 0;
                                rx2 = 1;
                                psrx = 2;
                                pstx = 3;
                                break;
                            case 6: // on on off
                                rx1 = 0;
                                rx2 = 1;
                                break;
                            case 7: // on on on
                                rx1 = 0;
                                rx2 = 1;
                                psrx = 2;
                                pstx = 3;
                                break;
                        }
                        break;
                    case HPSDRHW.HermesII: // ANAN-10E ANAN-100B HeremesII (2 adc)
                        switch (tot)
                        {
                            case 0: // off off off
                                rx1 = 0;
                                rx2 = 1;
                                break;
                            case 1: // off off on
                                rx1 = 0;
                                rx2 = 1;
                                break;
                            case 2: // off on off
                                rx1 = 0;
                                rx2 = 1;
                                break;
                            case 3: // off on on
                                rx1 = 0;
                                rx2 = 1;
                                break;
                            case 4: // on off off
                                rx1 = 0;
                                rx2 = 1;
                                break;
                            case 5: // on off on
                                psrx = 0;
                                pstx = 1;
                                break;
                            case 6: // on on off
                                rx1 = 0;
                                rx2 = 1;
                                break;
                            case 7: // on on on
                                psrx = 0;
                                pstx = 1;
                                break;
                        }
                        break;
                }
            }

            if (diversityForm != null && Diversity2)
            {
                // check if we are using RX1+RX2, RX1 or RX2
                switch (diversityForm.EXTDIVOutput)
                {
                    case 0: //rx1
                    case 2: //rx1+rx2
                        if (sync1 != -1) rx1 = sync1;
                        break;
                    case 1: //rx2
                        if (sync2 != -1) rx1 = sync2;
                        break;
                }
            }

            if (!MOX && rx1 == -1 && psrx != -1) rx1 = psrx;
            if (MOX && rx1 == -1 && pstx != -1) rx1 = pstx;

            if (rx2 == -1) rx2 = rx1;

            DDCrx1 = rx1;
            DDCrx2 = rx2;
            DDCsync1 = sync1;
            DDCsync2 = sync2;
            DDCpsrx = psrx;
            DDCpstx = pstx;
        }

        public void UpdateDiversityMenuItem()
        {
            bool bDivOn = diversityForm != null && Diversity2;
            if (bDivOn)
                eSCToolStripMenuItem.ForeColor = Color.LimeGreen;
            else
                eSCToolStripMenuItem.ForeColor = SystemColors.ControlLightLight;
        }
        private void UpdateDiversityValues()
        {
            if (!initializing && diversityForm != null)
            {
                diversityForm.DiversityRXRef = diversity_rx1_ref_by_band[(int)rx1_band];

                switch (RX1Band)
                {
                    case Band.B160M:
                        diversityForm.DiversityGain = DiversityGain160m;
                        diversityForm.DiversityR2Gain = DiversityR2Gain160m;
                        diversityForm.DiversityPhase = DiversityPhase160m;
                        break;
                    case Band.B80M:
                        diversityForm.DiversityGain = DiversityGain80m;
                        diversityForm.DiversityR2Gain = DiversityR2Gain80m;
                        diversityForm.DiversityPhase = DiversityPhase80m;
                        break;
                    case Band.B60M:
                        diversityForm.DiversityGain = DiversityGain60m;
                        diversityForm.DiversityR2Gain = DiversityR2Gain60m;
                        diversityForm.DiversityPhase = DiversityPhase60m;
                        break;
                    case Band.B40M:
                        diversityForm.DiversityGain = DiversityGain40m;
                        diversityForm.DiversityR2Gain = DiversityR2Gain40m;
                        diversityForm.DiversityPhase = DiversityPhase40m;
                        break;
                    case Band.B30M:
                        diversityForm.DiversityGain = DiversityGain30m;
                        diversityForm.DiversityR2Gain = DiversityR2Gain30m;
                        diversityForm.DiversityPhase = DiversityPhase30m;
                        break;
                    case Band.B20M:
                        diversityForm.DiversityGain = DiversityGain20m;
                        diversityForm.DiversityR2Gain = DiversityR2Gain20m;
                        diversityForm.DiversityPhase = DiversityPhase20m;
                        break;
                    case Band.B17M:
                        diversityForm.DiversityGain = DiversityGain17m;
                        diversityForm.DiversityR2Gain = DiversityR2Gain17m;
                        diversityForm.DiversityPhase = DiversityPhase17m;
                        break;
                    case Band.B15M:
                        diversityForm.DiversityGain = DiversityGain15m;
                        diversityForm.DiversityR2Gain = DiversityR2Gain15m;
                        diversityForm.DiversityPhase = DiversityPhase15m;
                        break;
                    case Band.B12M:
                        diversityForm.DiversityGain = DiversityGain12m;
                        diversityForm.DiversityR2Gain = DiversityR2Gain12m;
                        diversityForm.DiversityPhase = DiversityPhase12m;
                        break;
                    case Band.B10M:
                        diversityForm.DiversityGain = DiversityGain10m;
                        diversityForm.DiversityR2Gain = DiversityR2Gain10m;
                        diversityForm.DiversityPhase = DiversityPhase10m;
                        break;
                    case Band.B6M:
                        diversityForm.DiversityGain = DiversityGain6m;
                        diversityForm.DiversityR2Gain = DiversityR2Gain6m;
                        diversityForm.DiversityPhase = DiversityPhase6m;
                        break;
                    case Band.WWV:
                        diversityForm.DiversityGain = DiversityGainWWV;
                        diversityForm.DiversityR2Gain = DiversityR2GainWWV;
                        diversityForm.DiversityPhase = DiversityPhaseWWV;
                        break;
                    case Band.GEN:
                        diversityForm.DiversityGain = DiversityGainGEN;
                        diversityForm.DiversityR2Gain = DiversityR2GainGEN;
                        diversityForm.DiversityPhase = DiversityPhaseGEN;
                        break;
                    default:
                        diversityForm.DiversityGain = DiversityGainXVTR;
                        diversityForm.DiversityR2Gain = DiversityR2GainXVTR;
                        diversityForm.DiversityPhase = DiversityPhaseXVTR;
                        break;
                }
            }
        }

        public void UpdateWaterfallLevelValues()
        {
            if (!initializing)
            {
                UpdateBandButtonColors(); // ke9ns add to update the regBOX bandstack values on screen

                switch (RX1Band)
                {
                    case Band.B160M:
                        SetupForm.WaterfallLowThreshold = WaterfallLowThreshold160m;
                        SetupForm.WaterfallHighThreshold = WaterfallHighThreshold160m;
                        Display.WaterfallLowThreshold = WaterfallLowThreshold160m;
                        Display.WaterfallHighThreshold = WaterfallHighThreshold160m;
                        break;
                    case Band.B80M:
                        SetupForm.WaterfallLowThreshold = WaterfallLowThreshold80m;
                        SetupForm.WaterfallHighThreshold = WaterfallHighThreshold80m;
                        Display.WaterfallLowThreshold = WaterfallLowThreshold80m;
                        Display.WaterfallHighThreshold = WaterfallHighThreshold80m;
                        break;
                    case Band.B60M:
                        SetupForm.WaterfallLowThreshold = WaterfallLowThreshold60m;
                        SetupForm.WaterfallHighThreshold = WaterfallHighThreshold60m;
                        Display.WaterfallLowThreshold = WaterfallLowThreshold60m;
                        Display.WaterfallHighThreshold = WaterfallHighThreshold60m;
                        break;
                    case Band.B40M:
                        SetupForm.WaterfallLowThreshold = WaterfallLowThreshold40m;
                        SetupForm.WaterfallHighThreshold = WaterfallHighThreshold40m;
                        Display.WaterfallLowThreshold = WaterfallLowThreshold40m;
                        Display.WaterfallHighThreshold = WaterfallHighThreshold40m;
                        break;
                    case Band.B30M:
                        SetupForm.WaterfallLowThreshold = WaterfallLowThreshold30m;
                        SetupForm.WaterfallHighThreshold = WaterfallHighThreshold30m;
                        Display.WaterfallLowThreshold = WaterfallLowThreshold30m;
                        Display.WaterfallHighThreshold = WaterfallHighThreshold30m;
                        break;
                    case Band.B20M:
                        SetupForm.WaterfallLowThreshold = WaterfallLowThreshold20m;
                        SetupForm.WaterfallHighThreshold = WaterfallHighThreshold20m;
                        Display.WaterfallLowThreshold = WaterfallLowThreshold20m;
                        Display.WaterfallHighThreshold = WaterfallHighThreshold20m;
                        break;
                    case Band.B17M:
                        SetupForm.WaterfallLowThreshold = WaterfallLowThreshold17m;
                        SetupForm.WaterfallHighThreshold = WaterfallHighThreshold17m;
                        Display.WaterfallLowThreshold = WaterfallLowThreshold17m;
                        Display.WaterfallHighThreshold = WaterfallHighThreshold17m;
                        break;
                    case Band.B15M:
                        SetupForm.WaterfallLowThreshold = WaterfallLowThreshold15m;
                        SetupForm.WaterfallHighThreshold = WaterfallHighThreshold15m;
                        Display.WaterfallLowThreshold = WaterfallLowThreshold15m;
                        Display.WaterfallHighThreshold = WaterfallHighThreshold15m;
                        break;
                    case Band.B12M:
                        SetupForm.WaterfallLowThreshold = WaterfallLowThreshold12m;
                        SetupForm.WaterfallHighThreshold = WaterfallHighThreshold12m;
                        Display.WaterfallLowThreshold = WaterfallLowThreshold12m;
                        Display.WaterfallHighThreshold = WaterfallHighThreshold12m;
                        break;
                    case Band.B10M:
                        SetupForm.WaterfallLowThreshold = WaterfallLowThreshold10m;
                        SetupForm.WaterfallHighThreshold = WaterfallHighThreshold10m;
                        Display.WaterfallLowThreshold = WaterfallLowThreshold10m;
                        Display.WaterfallHighThreshold = WaterfallHighThreshold10m;
                        break;
                    case Band.B6M:
                        SetupForm.WaterfallLowThreshold = WaterfallLowThreshold6m;
                        SetupForm.WaterfallHighThreshold = WaterfallHighThreshold6m;
                        Display.WaterfallLowThreshold = WaterfallLowThreshold6m;
                        Display.WaterfallHighThreshold = WaterfallHighThreshold6m;
                        break;
                    case Band.WWV:
                        SetupForm.WaterfallLowThreshold = WaterfallLowThresholdWWV;
                        SetupForm.WaterfallHighThreshold = WaterfallHighThresholdWWV;
                        Display.WaterfallLowThreshold = WaterfallLowThresholdWWV;
                        Display.WaterfallHighThreshold = WaterfallHighThresholdWWV;
                        break;
                    case Band.GEN:
                        SetupForm.WaterfallLowThreshold = WaterfallLowThresholdGEN;
                        SetupForm.WaterfallHighThreshold = WaterfallHighThresholdGEN;
                        Display.WaterfallLowThreshold = WaterfallLowThresholdGEN;
                        Display.WaterfallHighThreshold = WaterfallHighThresholdGEN;
                        break;
                    default:
                        SetupForm.WaterfallLowThreshold = WaterfallLowThresholdXVTR;
                        SetupForm.WaterfallHighThreshold = WaterfallHighThresholdXVTR;
                        Display.WaterfallLowThreshold = WaterfallLowThresholdXVTR;
                        Display.WaterfallHighThreshold = WaterfallHighThresholdXVTR;
                        break;
                }

                switch (RX2Band)
                {
                    case Band.B160M:
                        SetupForm.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold160m;
                        SetupForm.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold160m;
                        Display.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold160m;
                        Display.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold160m;
                        break;
                    case Band.B80M:
                        SetupForm.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold80m;
                        SetupForm.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold80m;
                        Display.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold80m;
                        Display.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold80m;
                        break;
                    case Band.B60M:
                        SetupForm.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold60m;
                        SetupForm.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold60m;
                        Display.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold60m;
                        Display.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold60m;
                        break;
                    case Band.B40M:
                        SetupForm.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold40m;
                        SetupForm.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold40m;
                        Display.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold40m;
                        Display.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold40m;
                        break;
                    case Band.B30M:
                        SetupForm.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold30m;
                        SetupForm.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold30m;
                        Display.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold30m;
                        Display.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold30m;
                        break;
                    case Band.B20M:
                        SetupForm.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold20m;
                        SetupForm.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold20m;
                        Display.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold20m;
                        Display.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold20m;
                        break;
                    case Band.B17M:
                        SetupForm.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold17m;
                        SetupForm.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold17m;
                        Display.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold17m;
                        Display.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold17m;
                        break;
                    case Band.B15M:
                        SetupForm.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold15m;
                        SetupForm.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold15m;
                        Display.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold15m;
                        Display.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold15m;
                        break;
                    case Band.B12M:
                        SetupForm.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold12m;
                        SetupForm.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold12m;
                        Display.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold12m;
                        Display.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold12m;
                        break;
                    case Band.B10M:
                        SetupForm.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold10m;
                        SetupForm.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold10m;
                        Display.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold10m;
                        Display.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold10m;
                        break;
                    case Band.B6M:
                        SetupForm.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold6m;
                        SetupForm.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold6m;
                        Display.RX2WaterfallLowThreshold = RX2WaterfallLowThreshold6m;
                        Display.RX2WaterfallHighThreshold = RX2WaterfallHighThreshold6m;
                        break;
                    case Band.WWV:
                        SetupForm.RX2WaterfallLowThreshold = RX2WaterfallLowThresholdWWV;
                        SetupForm.RX2WaterfallHighThreshold = RX2WaterfallHighThresholdWWV;
                        Display.RX2WaterfallLowThreshold = RX2WaterfallLowThresholdWWV;
                        Display.RX2WaterfallHighThreshold = RX2WaterfallHighThresholdWWV;
                        break;
                    case Band.GEN:
                        SetupForm.RX2WaterfallLowThreshold = RX2WaterfallLowThresholdGEN;
                        SetupForm.RX2WaterfallHighThreshold = RX2WaterfallHighThresholdGEN;
                        Display.RX2WaterfallLowThreshold = RX2WaterfallLowThresholdGEN;
                        Display.RX2WaterfallHighThreshold = RX2WaterfallHighThresholdGEN;
                        break;
                    default:
                        SetupForm.RX2WaterfallLowThreshold = RX2WaterfallLowThresholdXVTR;
                        SetupForm.RX2WaterfallHighThreshold = RX2WaterfallHighThresholdXVTR;
                        Display.RX2WaterfallLowThreshold = RX2WaterfallLowThresholdXVTR;
                        Display.RX2WaterfallHighThreshold = RX2WaterfallHighThresholdXVTR;
                        break;
                }

                SetupForm.UpdateWaterfallBandInfo();

                //MW0LGE override... XVTR? TODO
                setWaterfallGainsIfLinkedToSpectrum(1);
                setWaterfallGainsIfLinkedToSpectrum(2);
            }
        }
        private void updateDisplayGridLevelValues()
        {
            UpdateDisplayGridLevelMinValues(false); // false because we do the updates after setting max below
            UpdateDisplayGridLevelMaxValues(true);
        }
        private void setWaterfallGainsIfLinkedToSpectrum(int rx)
        {
            if (IsSetupFormNull) return;

            if (m_bWaterfallUseRX1SpectrumMinMax && rx == 1)
            {
                Display.WaterfallLowThreshold = SetupForm.DisplayGridMin;
                Display.WaterfallHighThreshold = SetupForm.DisplayGridMax;
            }
            else if (m_bWaterfallUseRX2SpectrumMinMax && rx == 2)
            {
                Display.RX2WaterfallLowThreshold = SetupForm.RX2DisplayGridMin;
                Display.RX2WaterfallHighThreshold = SetupForm.RX2DisplayGridMax;
            }
        }

        public void UpdateDisplayGridLevelMinValues(bool bDoBandInfoAndWaterFallSync)
        {
            if (!initializing)
            {
                switch (RX1Band)
                {
                    case Band.B160M:
                        SetupForm.DisplayGridMin = DisplayGridMin160m;
                        Display.SpectrumGridMin = (int)DisplayGridMin160m;
                        break;
                    case Band.B80M:
                        SetupForm.DisplayGridMin = DisplayGridMin80m;
                        Display.SpectrumGridMin = (int)DisplayGridMin80m;
                        break;
                    case Band.B60M:
                        SetupForm.DisplayGridMin = DisplayGridMin60m;
                        Display.SpectrumGridMin = (int)DisplayGridMin60m;
                        break;
                    case Band.B40M:
                        SetupForm.DisplayGridMin = DisplayGridMin40m;
                        Display.SpectrumGridMin = (int)DisplayGridMin40m;
                        break;
                    case Band.B30M:
                        SetupForm.DisplayGridMin = DisplayGridMin30m;
                        Display.SpectrumGridMin = (int)DisplayGridMin30m;
                        break;
                    case Band.B20M:
                        SetupForm.DisplayGridMin = DisplayGridMin20m;
                        Display.SpectrumGridMin = (int)DisplayGridMin20m;
                        break;
                    case Band.B17M:
                        SetupForm.DisplayGridMin = DisplayGridMin17m;
                        Display.SpectrumGridMin = (int)DisplayGridMin17m;
                        break;
                    case Band.B15M:
                        SetupForm.DisplayGridMin = DisplayGridMin15m;
                        Display.SpectrumGridMin = (int)DisplayGridMin15m;
                        break;
                    case Band.B12M:
                        SetupForm.DisplayGridMin = DisplayGridMin12m;
                        Display.SpectrumGridMin = (int)DisplayGridMin12m;
                        break;
                    case Band.B10M:
                        SetupForm.DisplayGridMin = DisplayGridMin10m;
                        Display.SpectrumGridMin = (int)DisplayGridMin10m;
                        break;
                    case Band.B6M:
                        SetupForm.DisplayGridMin = DisplayGridMin6m;
                        Display.SpectrumGridMin = (int)DisplayGridMin6m;
                        break;
                    case Band.WWV:
                        SetupForm.DisplayGridMin = DisplayGridMinWWV;
                        Display.SpectrumGridMin = (int)DisplayGridMinWWV;
                        break;
                    case Band.GEN:
                        SetupForm.DisplayGridMin = DisplayGridMinGEN;
                        Display.SpectrumGridMin = (int)DisplayGridMinGEN;
                        break;
                    default:
                        SetupForm.DisplayGridMin = DisplayGridMinXVTR;
                        Display.SpectrumGridMin = (int)DisplayGridMinXVTR;
                        break;
                }

                switch (RX2Band)
                {
                    case Band.B160M:
                        SetupForm.RX2DisplayGridMin = RX2DisplayGridMin160m;
                        Display.RX2SpectrumGridMin = (int)RX2DisplayGridMin160m;
                        break;
                    case Band.B80M:
                        SetupForm.RX2DisplayGridMin = RX2DisplayGridMin80m;
                        Display.RX2SpectrumGridMin = (int)RX2DisplayGridMin80m;
                        break;
                    case Band.B60M:
                        SetupForm.RX2DisplayGridMin = RX2DisplayGridMin60m;
                        Display.RX2SpectrumGridMin = (int)RX2DisplayGridMin60m;
                        break;
                    case Band.B40M:
                        SetupForm.RX2DisplayGridMin = RX2DisplayGridMin40m;
                        Display.RX2SpectrumGridMin = (int)RX2DisplayGridMin40m;
                        break;
                    case Band.B30M:
                        SetupForm.RX2DisplayGridMin = RX2DisplayGridMin30m;
                        Display.RX2SpectrumGridMin = (int)RX2DisplayGridMin30m;
                        break;
                    case Band.B20M:
                        SetupForm.RX2DisplayGridMin = RX2DisplayGridMin20m;
                        Display.RX2SpectrumGridMin = (int)RX2DisplayGridMin20m;
                        break;
                    case Band.B17M:
                        SetupForm.RX2DisplayGridMin = RX2DisplayGridMin17m;
                        Display.RX2SpectrumGridMin = (int)RX2DisplayGridMin17m;
                        break;
                    case Band.B15M:
                        SetupForm.RX2DisplayGridMin = RX2DisplayGridMin15m;
                        Display.RX2SpectrumGridMin = (int)RX2DisplayGridMin15m;
                        break;
                    case Band.B12M:
                        SetupForm.RX2DisplayGridMin = RX2DisplayGridMin12m;
                        Display.RX2SpectrumGridMin = (int)RX2DisplayGridMin12m;
                        break;
                    case Band.B10M:
                        SetupForm.RX2DisplayGridMin = RX2DisplayGridMin10m;
                        Display.RX2SpectrumGridMin = (int)RX2DisplayGridMin10m;
                        break;
                    case Band.B6M:
                        SetupForm.RX2DisplayGridMin = RX2DisplayGridMin6m;
                        Display.RX2SpectrumGridMin = (int)RX2DisplayGridMin6m;
                        break;
                    case Band.WWV:
                        SetupForm.RX2DisplayGridMin = RX2DisplayGridMinWWV;
                        Display.RX2SpectrumGridMin = (int)RX2DisplayGridMinWWV;
                        break;
                    case Band.GEN:
                        SetupForm.RX2DisplayGridMin = RX2DisplayGridMinGEN;
                        Display.RX2SpectrumGridMin = (int)RX2DisplayGridMinGEN;
                        break;
                    default:
                        SetupForm.RX2DisplayGridMin = RX2DisplayGridMinXVTR;
                        Display.RX2SpectrumGridMin = (int)RX2DisplayGridMinXVTR;
                        break;
                }

                if (bDoBandInfoAndWaterFallSync)
                {
                    SetupForm.UpdateDisplayGridBandInfo();

                    //MW0LGE override... XVTR? TODO
                    setWaterfallGainsIfLinkedToSpectrum(1);
                    setWaterfallGainsIfLinkedToSpectrum(2);
                }
            }
        }
        public void UpdateDisplayGridLevelMaxValues(bool bDoBandInfoAndWaterFallSync)
        {
            if (!initializing)
            {
                switch (RX1Band)
                {
                    case Band.B160M:
                        SetupForm.DisplayGridMax = DisplayGridMax160m;
                        Display.SpectrumGridMax = (int)DisplayGridMax160m;
                        break;
                    case Band.B80M:
                        SetupForm.DisplayGridMax = DisplayGridMax80m;
                        Display.SpectrumGridMax = (int)DisplayGridMax80m;
                        break;
                    case Band.B60M:
                        SetupForm.DisplayGridMax = DisplayGridMax60m;
                        Display.SpectrumGridMax = (int)DisplayGridMax60m;
                        break;
                    case Band.B40M:
                        SetupForm.DisplayGridMax = DisplayGridMax40m;
                        Display.SpectrumGridMax = (int)DisplayGridMax40m;
                        break;
                    case Band.B30M:
                        SetupForm.DisplayGridMax = DisplayGridMax30m;
                        Display.SpectrumGridMax = (int)DisplayGridMax30m;
                        break;
                    case Band.B20M:
                        SetupForm.DisplayGridMax = DisplayGridMax20m;
                        Display.SpectrumGridMax = (int)DisplayGridMax20m;
                        break;
                    case Band.B17M:
                        SetupForm.DisplayGridMax = DisplayGridMax17m;
                        Display.SpectrumGridMax = (int)DisplayGridMax17m;
                        break;
                    case Band.B15M:
                        SetupForm.DisplayGridMax = DisplayGridMax15m;
                        Display.SpectrumGridMax = (int)DisplayGridMax15m;
                        break;
                    case Band.B12M:
                        SetupForm.DisplayGridMax = DisplayGridMax12m;
                        Display.SpectrumGridMax = (int)DisplayGridMax12m;
                        break;
                    case Band.B10M:
                        SetupForm.DisplayGridMax = DisplayGridMax10m;
                        Display.SpectrumGridMax = (int)DisplayGridMax10m;
                        break;
                    case Band.B6M:
                        SetupForm.DisplayGridMax = DisplayGridMax6m;
                        Display.SpectrumGridMax = (int)DisplayGridMax6m;
                        break;
                    case Band.WWV:
                        SetupForm.DisplayGridMax = DisplayGridMaxWWV;
                        Display.SpectrumGridMax = (int)DisplayGridMaxWWV;
                        break;
                    case Band.GEN:
                        SetupForm.DisplayGridMax = DisplayGridMaxGEN;
                        Display.SpectrumGridMax = (int)DisplayGridMaxGEN;
                        break;
                    default:
                        SetupForm.DisplayGridMax = DisplayGridMaxXVTR;
                        Display.SpectrumGridMax = (int)DisplayGridMaxXVTR;
                        break;
                }

                switch (RX2Band)
                {
                    case Band.B160M:
                        SetupForm.RX2DisplayGridMax = RX2DisplayGridMax160m;
                        Display.RX2SpectrumGridMax = (int)RX2DisplayGridMax160m;
                        break;
                    case Band.B80M:
                        SetupForm.RX2DisplayGridMax = RX2DisplayGridMax80m;
                        Display.RX2SpectrumGridMax = (int)RX2DisplayGridMax80m;
                        break;
                    case Band.B60M:
                        SetupForm.RX2DisplayGridMax = RX2DisplayGridMax60m;
                        Display.RX2SpectrumGridMax = (int)RX2DisplayGridMax60m;
                        break;
                    case Band.B40M:
                        SetupForm.RX2DisplayGridMax = RX2DisplayGridMax40m;
                        Display.RX2SpectrumGridMax = (int)RX2DisplayGridMax40m;
                        break;
                    case Band.B30M:
                        SetupForm.RX2DisplayGridMax = RX2DisplayGridMax30m;
                        Display.RX2SpectrumGridMax = (int)RX2DisplayGridMax30m;
                        break;
                    case Band.B20M:
                        SetupForm.RX2DisplayGridMax = RX2DisplayGridMax20m;
                        Display.RX2SpectrumGridMax = (int)RX2DisplayGridMax20m;
                        break;
                    case Band.B17M:
                        SetupForm.RX2DisplayGridMax = RX2DisplayGridMax17m;
                        Display.RX2SpectrumGridMax = (int)RX2DisplayGridMax17m;
                        break;
                    case Band.B15M:
                        SetupForm.RX2DisplayGridMax = RX2DisplayGridMax15m;
                        Display.RX2SpectrumGridMax = (int)RX2DisplayGridMax15m;
                        break;
                    case Band.B12M:
                        SetupForm.RX2DisplayGridMax = RX2DisplayGridMax12m;
                        Display.RX2SpectrumGridMax = (int)RX2DisplayGridMax12m;
                        break;
                    case Band.B10M:
                        SetupForm.RX2DisplayGridMax = RX2DisplayGridMax10m;
                        Display.RX2SpectrumGridMax = (int)RX2DisplayGridMax10m;
                        break;
                    case Band.B6M:
                        SetupForm.RX2DisplayGridMax = RX2DisplayGridMax6m;
                        Display.RX2SpectrumGridMax = (int)RX2DisplayGridMax6m;
                        break;
                    case Band.WWV:
                        SetupForm.RX2DisplayGridMax = RX2DisplayGridMaxWWV;
                        Display.RX2SpectrumGridMax = (int)RX2DisplayGridMaxWWV;
                        break;
                    case Band.GEN:
                        SetupForm.RX2DisplayGridMax = RX2DisplayGridMaxGEN;
                        Display.RX2SpectrumGridMax = (int)RX2DisplayGridMaxGEN;
                        break;
                    default:
                        SetupForm.RX2DisplayGridMax = RX2DisplayGridMaxXVTR;
                        Display.RX2SpectrumGridMax = (int)RX2DisplayGridMaxXVTR;
                        break;
                }

                if (bDoBandInfoAndWaterFallSync)
                {
                    SetupForm.UpdateDisplayGridBandInfo();

                    //MW0LGE override... XVTR? TODO
                    setWaterfallGainsIfLinkedToSpectrum(1);
                    setWaterfallGainsIfLinkedToSpectrum(2);
                }
            }
        }

        public bool RX1IsIn60m()
        {
            double freq = VFOAFreq;
            return (freq >= 5.1 && freq <= 5.5);
        }

        public bool RX1IsOn60mChannel(Channel c)
        {
            double freq = VFOAFreq - ModeFreqOffset(rx1_dsp_mode);
            freq = Math.Round(freq, 6); // in mhz

            return (c.Freq == freq);
        }
        public bool RX1IsIn60mChannel(Channel c)
        {
            double freq = VFOAFreq;
            freq = Math.Round(freq, 6); // in mhz

            return (freq >= c.Low) && (freq <= c.High);
        }

        public bool RX1IsIn60mChannel()
        {
            foreach (Channel c in Channels60m)
            {
                if (RX1IsIn60mChannel(c)) return true;
            }

            return false; // nothing matched, return false
        }
        public bool RX1IsOn60mChannel()
        {
            foreach (Channel c in Channels60m)
            {
                if (RX1IsOn60mChannel(c)) return true;
            }

            return false; // nothing matched, return false
        }

        public bool RX2IsIn60m()
        {
            double freq = VFOBFreq;
            return (freq >= 5.1 && freq <= 5.5);
        }

        public bool RX2IsOn60mChannel(Channel c)
        {
            double freq = VFOBFreq - ModeFreqOffset(rx2_dsp_mode);
            freq = Math.Round(freq, 6); // in mhz

            return (c.Freq == freq);
        }
        public bool RX2IsIn60mChannel(Channel c)
        {
            double freq = VFOBFreq;
            freq = Math.Round(freq, 6);

            return (freq >= c.Low) && (freq <= c.High);
        }
        public bool RX2IsOn60mChannel()
        {
            foreach (Channel c in Channels60m)
            {
                if (RX2IsOn60mChannel(c)) return true;
            }

            return false; // nothing matched, return false
        }
        public bool RX2IsIn60mChannel()
        {
            foreach (Channel c in Channels60m)
            {
                if (RX2IsIn60mChannel(c)) return true;
            }

            return false; // nothing matched, return false
        }

        private double ModeFreqOffset(DSPMode mode)
        {
            switch (mode)
            {
                case DSPMode.LSB:
                case DSPMode.DIGL:
                    return (1500 * 1e-6);
                case DSPMode.USB:
                case DSPMode.DRM:
                case DSPMode.DIGU:
                    return (-1500 * 1e-6);
                case DSPMode.DSB:
                case DSPMode.CWL:
                case DSPMode.CWU:
                case DSPMode.FM:
                case DSPMode.AM:
                case DSPMode.SAM:
                    return 0;
                default: return 0;
            }
        }

        public string CATGetXVTRBandNames()
        {
            string names = "";
            for (int n = 0; n < 14; n++)
            {
                if (XVTRForm.GetEnabled(n) == true)
                    names += vhf_text[n].Text.ToString().PadLeft(5, ' ');
                else
                    names += "     ";
            }
            return names;
        }

        public string GetFilterPresets(int mode_ndx)
        {
            string mode_info = "";
            for (Filter f = Filter.F1; f < Filter.NONE; f++)
            {

                mode_info += rx1_filters[mode_ndx].GetName(f).PadLeft(5, ' ');
                mode_info += rx1_filters[mode_ndx].GetHigh(f).ToString().PadLeft(5, ' ');
                mode_info += rx1_filters[mode_ndx].GetLow(f).ToString().PadLeft(5, ' ');
            }
            return mode_info;
        }

        public int CurrentTuneStepHz
        {
            get { return tune_step_list[tune_step_index].StepHz; }
        }

        public double CurrentTuneStepMHz
        {
            get { return tune_step_list[tune_step_index].StepHz * 1e-6; }
        }

        //============================================================================ 
        //============================================================================ 
        // ke9ns add CALLSIGN menu field allow WaveForm to get text from here
        //============================================================================ 
        //============================================================================ 
        public static string callsign = "CallSign";

        public string Callsign            // wave.cs gets call sign from here
        {
            get { return callsign; }
            set
            {
                // Callsign = setupForm.txtGenCustomTitle.Text;
                callsign = value;

            } // set
        } // tx id

        public static string lastcallsign = " hhh ";

        public string LastCall            // wave.cs gets call sign from here
        {
            get { return lastcallsign; }
            set
            {
                lastcallsign = value;

            } // set
        } // tx id

        private static byte callsignfocus = 0; // ke9ns used to keep focus on text entry and not flex keyboard shortcuts

        private void radBandGEN0_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.BLMF);
        } // MF or AM band in USA

        private void radBandGEN1_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B120M);
        } // 120m

        private void radBandGEN2_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B90M);
        } // 90m

        private void radBandGEN3_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B61M);
        } // 60m

        private void radBandGEN4_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B49M);
        } // 49m

        private void radBandGEN5_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B41M);
        } // 41m

        private void radBandGEN6_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B31M);
        } //31m

        private void radBandGEN7_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B25M);
        } // 25m

        private void radBandGEN8_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B22M);
        } // 22m

        private void radBandGEN9_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B19M);
        } // 19m

        private void radBandGEN10_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B16M);
        } //16m

        private void radBandGEN11_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B14M);
        } // 14m

        private void radBandGEN12_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B13M);
        } // 13m 

        private void radBandGEN13_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B11M);
        } // 11m

        //==========================================================================
        // ke9ns add RIGHT CLICK to add bandstack to list
        private void radBand160_MouseDown(object sender, MouseEventArgs e)
        {
        } //  radBand160_MouseDown

        private void radBand80_MouseDown(object sender, MouseEventArgs e)
        {
        }//  radBand80_MouseDown

        private void radBand60_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBand40_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBand30_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBand20_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBand17_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBand15_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBand12_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBand10_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBand6_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandGEN0_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandGEN1_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandGEN2_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandGEN3_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandGEN4_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandGEN5_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandGEN6_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandGEN7_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandGEN8_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandGEN9_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandGEN10_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandGEN11_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandGEN12_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandGEN13_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandVHF0_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandVHF1_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandVHF2_MouseDown(object sender, MouseEventArgs e)
        {
        }


        private void radBandVHF3_MouseDown(object sender, MouseEventArgs e)
        {
        }


        private void radBandVHF4_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandVHF5_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandVHF6_MouseDown(object sender, MouseEventArgs e)
        {
        }


        private void radBandVHF7_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandVHF8_MouseDown(object sender, MouseEventArgs e)
        {
        }


        private void radBandVHF9_MouseDown(object sender, MouseEventArgs e)
        {
        }


        private void radBandVHF10_MouseDown(object sender, MouseEventArgs e)
        {
        }


        private void radBandVHF11_MouseDown(object sender, MouseEventArgs e)
        {
        }

        private void radBandVHF12_MouseDown(object sender, MouseEventArgs e)
        {
        }


        private void radBandVHF13_MouseDown(object sender, MouseEventArgs e)
        {
        }

        //====================================================================================================
        // ke9ns
        public bool SWLFORM
        {
            get
            {
                return false;
            }
            set
            {
                if (SwlForm == null || SwlForm.IsDisposed) SwlForm = new SwlControl(this); // ke9ns add communicate with swl list controls

                SwlForm.Show();
                SwlForm.Focus();
                SwlForm.WindowState = FormWindowState.Normal; // ke9ns add
            }
        }

        //====================================================================================================
        //====================================================================================================
        // ke9ns add Thread routine
        private void spotterMenu_Click(object sender, EventArgs e)
        {
            if (SpotForm == null || SpotForm.IsDisposed) SpotForm = new SpotControl(this);

            if (SpotForm.InvokeRequired)
            {
                SpotForm.Invoke(new MethodInvoker(() =>
                {
                    SpotForm.Show();
                    SpotForm.Focus();
                }));
            }
            else
            {
                SpotForm.Show();
                SpotForm.Focus();
            }
        }

        #endregion

        #region Test and Calibration Routines

        public static bool FreqCalibrationRunning = false;
        unsafe public bool CalibrateFreq(float freq)
        {
            if (!chkPower.Checked)
            {
                MessageBox.Show("Power must be on in order to calibrate Frequency.", "Power Is Off",
                    MessageBoxButtons.OK, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                return false;
            }

            //MW0LGE_[2.9.0.6] turn off min grid
            bool bOldMinGridFollowNF = GridMinFollowsNFRX1;
            GridMinFollowsNFRX1 = false;

            calibration_running = true;

            SetupForm.HPSDRFreqCorrectFactorViaAutoCalibration = 1.0;         // TURN-OFF CORRECTION

            string vfo_freq_text = txtVFOAFreq.Text;		// save current frequency
            bool rit_on = chkRIT.Checked;					// save current RIT state
            chkRIT.Checked = false;							// set RIT to Off
            int rit_value = (int)udRIT.Value;				// save current RIT value
            udRIT.Value = 0;								// set RIT Value to 0
            VFOAFreq = freq;								// set frequency to passed value

            Thread.Sleep(1000);                             // wait for changes to take effect

            int ss = 0;
            int fft_size = specRX.GetSpecRX(0).FFTSize;     // get fft_size
            double[,] buf = new double[fft_size, 2];        // buffer for complex spectrum data
            double[] sum = new double[fft_size];            // buffer for "averaged" spectrum data

            _spectrum_mutex.WaitOne();
            for (int i = 0; i < 10; i++)                    // average 10 spectra to reduce noise
            {
                fixed (double* ptr = &buf[0, 0])
                    SpecHPSDRDLL.SnapSpectrum(0, ss, 0, ptr);          // get a spectrum
                for (int j = 0; j < fft_size; j++)
                    sum[j] += buf[j, 0] * buf[j, 0] + buf[j, 1] * buf[j, 1];    // compute magnitude and add to "average"
                Thread.Sleep(50);                                               // wait a little for noise to change
            }
            _spectrum_mutex.ReleaseMutex();

            const double cal_range = 2500.0;                                    // look +/- this much from current freq to find the calibration signal
            double bin_width = (double)(sample_rate_rx1) / (double)fft_size;
            int offset = (int)(cal_range / bin_width);
            double max = double.MinValue;
            int max_index = 0;
            for (int i = fft_size / 2 - offset; i <= fft_size / 2 + offset; i++)// find the bin with the largest signal
            {
                if (sum[i] > max)
                {
                    max = sum[i];
                    max_index = i;
                }
            }

            // Calculate the frequency difference between the known signal and the measured signal
            double diff = bin_width * (fft_size / 2 - max_index);
            double correct_factor = 1.0d - ((diff / (double)(freq * 1e6)));

            SetupForm.HPSDRFreqCorrectFactorViaAutoCalibration = correct_factor;  //TURN-ON CORRECTION

            SetupForm.RXOnly = rx_only;				    	// restore RX Only setting
            chkRIT.Checked = rit_on;						// restore RIT state
            RITValue = rit_value;							// restore RIT value
            VFOAFreq = float.Parse(vfo_freq_text);			// restore frequency
            calibration_running = false;

            GridMinFollowsNFRX1 = bOldMinGridFollowNF;

            return true;
        }

        unsafe public bool CalibrateLevel(float level, float freq, Progress progress, bool suppress_errors)
        {
            // Calibration routine called by Setup Form.
            bool ret_val = false;
            calibration_running = true;
            if (!chkPower.Checked)
            {
                if (!suppress_errors)
                {
                    MessageBox.Show("Power must be on in order to calibrate RX Level.", "Power Is Off",
                        MessageBoxButtons.OK, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                }
                calibration_running = false;
                return false;
            }

            //MW0LGE_[2.9.0.6] turn off min grid
            bool bOldMinGridFollowNF = GridMinFollowsNFRX1;
            bool bOldMinGridFollowNFrx2 = GridMinFollowsNFRX2;
            GridMinFollowsNFRX1 = false;
            GridMinFollowsNFRX2 = false;

            int ss = 0;
            int fft_size = specRX.GetSpecRX(0).FFTSize;     // get fft_size
            double[,] buf = new double[fft_size, 2];        // buffer for complex spectrum data
            double[] sum = new double[fft_size];            // buffer for "averaged" spectrum data

            int iterations = 20;                            // number of samples to average

            //~~~~~

            double vfoa = VFOAFreq;								// save current VFOA

            bool ctun_on = chkFWCATU.Checked;
            chkFWCATU.Checked = false;

            bool rit_on = chkRIT.Checked;						// save current RIT On
            chkRIT.Checked = false;								// turn RIT off
            int rit_val = (int)udRIT.Value;						// save current RIT value

            string display = comboDisplayMode.Text;
            comboDisplayMode.Text = "Panadapter";

            int dsp_buf_size = SetupForm.DSPPhoneRXBuffer;		// save current DSP buffer size
            SetupForm.DSPPhoneRXBuffer = 16384;					// set DSP Buffer Size to 16384

            DSPMode dsp_mode = rx1_dsp_mode;				// save current DSP demod mode
            RX1DSPMode = DSPMode.AM;						// set mode to CWU

            VFOAFreq = freq;									// set VFOA frequency

            bool step_attnRX1 = SetupForm.RX1EnableAtt;
            bool step_attnRX2 = SetupForm.RX2EnableAtt; //MW0LGE_[2.9.0.6]
            SetupForm.RX1EnableAtt = false;
            SetupForm.RX2EnableAtt = false; //MW0LGE_[2.9.0.6]
            PreampMode preampRX1 = RX1PreampMode;				// save current preamp mode
            PreampMode preampRX2 = RX2PreampMode;				// save current preamp mode
            RX1PreampMode = PreampMode.HPSDR_ON;			// set to high
            RX2PreampMode = PreampMode.HPSDR_ON;        //MW0LGE_[2.9.0.6]

            MeterRXMode rx_meter = CurrentMeterRXMode;			// save current RX Meter mode
            CurrentMeterRXMode = MeterRXMode.OFF;				// turn RX Meter off

            float old_multimeter_cal = rx1_meter_cal_offset;
            float old_display_cal = rx1_display_cal_offset;
            float old_multimeter_cal_rx2 = rx2_meter_cal_offset; //MW0LGE_[2.9.0.6]
            float old_display_cal_rx2 = rx2_display_cal_offset; //MW0LGE_[2.9.0.6]

            int progress_divisor;
            if (alexpresent)
            {
                progress_divisor = 390;
            }
            else
            {
                progress_divisor = 120;
            }

            comboPreamp.Enabled = false;
            comboDisplayMode.Enabled = false;
            comboMeterRXMode.Enabled = false;

            progress.SetPercent(0.0f);
            int counter = 0;
            Thread.Sleep(2000);
            btnZeroBeat_Click(this, EventArgs.Empty);

            double cal_range = 20000.0;        // look +/- this much from current freq to find the calibration signal

            double bin_width = (double)(sample_rate_rx1) / (double)fft_size;
            int offset = (int)(cal_range / bin_width);
            double maxsumsq = double.MinValue;
            double avgmag = 0;

            _spectrum_mutex.WaitOne();
            for (int i = 0; i < iterations; i++)
            {
                fixed (double* ptr = &buf[0, 0])
                    SpecHPSDRDLL.SnapSpectrum(0, ss, 0, ptr);                   // get a spectrum

                for (int j = fft_size / 2 - offset; j <= fft_size / 2 + offset; j++)

                    sum[j] += 10.0 * Math.Log10(buf[j, 0] * buf[j, 0] + buf[j, 1] * buf[j, 1]);     // compute dB level for each bin and add to previous for averaging
                Thread.Sleep(20);                                               // wait a little for noise to change
            }
            _spectrum_mutex.ReleaseMutex();

            for (int i = fft_size / 2 - offset; i <= fft_size / 2 + offset; i++)// find the max value in any bin
            {
                sum[i] /= iterations; // convert the sum to the average value for the bin
                avgmag += sum[i];
                if (sum[i] > maxsumsq)
                    maxsumsq = sum[i];
            }

            avgmag /= offset * 2.0;

            if ((maxsumsq - avgmag) < 30.0) // compare the max bin with the average bin value
            {
                MessageBox.Show("Peak is less than 30dB from the noise floor.  " +
                    "Please use a larger signal for frequency calibration.",
                    "Calibration Error - Weak Signal",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                ret_val = false;
                goto end;
            }
            //clean variables for next use
            maxsumsq = 0.0;
            Array.Clear(sum, 0, fft_size);

            rx1_meter_cal_offset = 0.0f;
            rx1_display_cal_offset = 0.0f;
            //MW0LGE_[2.9.0.6]
            rx2_meter_cal_offset = 0.0f;
            rx2_display_cal_offset = 0.0f;
            //
            float num = 0.0f, num2 = 0.0f, avg2 = 0.0f;
            float avg = 0.0f;
            // get the value of the signal strength meter
            Thread.Sleep(1000);
            for (int i = 0; i < 50; i++)
            {
                num += WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.AVG_SIGNAL_STRENGTH);
                Thread.Sleep(50);
                if (!progress.Visible)
                    goto end;
                else progress.SetPercent((float)((float)++counter / progress_divisor));
            }
            avg = num / 50.0f;


            RX1PreampMode = PreampMode.HPSDR_OFF;
            Thread.Sleep(100);

            // get the value of the signal strength meter
            num2 = 0.0f;
            Thread.Sleep(1000);
            for (int i = 0; i < 50; i++)
            {
                num2 += WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.AVG_SIGNAL_STRENGTH);
                Thread.Sleep(50);
                if (!progress.Visible)
                    goto end;
                else progress.SetPercent((float)((float)++counter / progress_divisor));
            }
            avg2 = num2 / 50.0f;

            float off_offset = avg2 - avg;

            rx1_preamp_offset[(int)PreampMode.HPSDR_OFF] = -off_offset;
            rx1_preamp_offset[(int)PreampMode.HPSDR_ON] = 0.0f;
            rx2_preamp_offset[(int)PreampMode.HPSDR_OFF] = -off_offset;
            rx2_preamp_offset[(int)PreampMode.HPSDR_ON] = 0.0f;

            if (alexpresent &&
                current_hpsdr_model != HPSDRModel.ANAN10 &&
                current_hpsdr_model != HPSDRModel.ANAN10E &&
                current_hpsdr_model != HPSDRModel.ANAN7000D &&
                current_hpsdr_model != HPSDRModel.ANAN8000D &&
                current_hpsdr_model != HPSDRModel.ORIONMKII &&
                current_hpsdr_model != HPSDRModel.ANAN_G2 &&
                current_hpsdr_model != HPSDRModel.ANAN_G2_1K)
            {
                RX1PreampMode = PreampMode.HPSDR_MINUS10; //-10dB
                Thread.Sleep(100);

                // get the value of the signal strength meter
                num2 = 0.0f;
                Thread.Sleep(1000);
                for (int i = 0; i < 50; i++)
                {
                    num2 += WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.AVG_SIGNAL_STRENGTH);
                    Thread.Sleep(50);
                    if (!progress.Visible)
                        goto end;
                    else progress.SetPercent((float)((float)++counter / progress_divisor));
                }
                avg2 = num2 / 50.0f;

                float minus10_offset = avg2 - avg;
                rx1_preamp_offset[(int)PreampMode.HPSDR_MINUS10] = -minus10_offset;


                RX1PreampMode = PreampMode.HPSDR_MINUS20; //-20dB
                Thread.Sleep(100);

                // get the value of the signal strength meter
                num2 = 0.0f;
                Thread.Sleep(1000);
                for (int i = 0; i < 50; i++)
                {
                    num2 += WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.AVG_SIGNAL_STRENGTH);
                    Thread.Sleep(50);
                    if (!progress.Visible)
                        goto end;
                    else progress.SetPercent((float)((float)++counter / progress_divisor));
                }
                avg2 = num2 / 50.0f;

                float minus20_offset = avg2 - avg;
                rx1_preamp_offset[(int)PreampMode.HPSDR_MINUS20] = -minus20_offset;


                RX1PreampMode = PreampMode.HPSDR_MINUS30; //-30dB
                Thread.Sleep(100);

                // get the value of the signal strength meter
                num2 = 0.0f; avg2 = 0.0f;
                Thread.Sleep(1000);
                for (int i = 0; i < 50; i++)
                {
                    num2 += WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.AVG_SIGNAL_STRENGTH);
                    Thread.Sleep(50);
                    if (!progress.Visible)
                        goto end;
                    else progress.SetPercent((float)((float)++counter / progress_divisor));
                }
                avg2 = num2 / 50.0f;

                float minus30_offset = avg2 - avg;
                rx1_preamp_offset[(int)PreampMode.HPSDR_MINUS30] = -minus30_offset;

                RX1PreampMode = PreampMode.HPSDR_MINUS40; //-40dB

                Thread.Sleep(100);

                // get the value of the signal strength meter
                num2 = 0.0f;
                Thread.Sleep(1000);
                for (int i = 0; i < 50; i++)
                {
                    num2 += WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.AVG_SIGNAL_STRENGTH);
                    Thread.Sleep(50);
                    if (!progress.Visible)
                        goto end;
                    else progress.SetPercent((float)((float)++counter / progress_divisor));
                }
                avg2 = num2 / 50.0f;

                float minus40_offset = avg2 - avg;
                rx1_preamp_offset[(int)PreampMode.HPSDR_MINUS40] = -minus40_offset;

                RX1PreampMode = PreampMode.HPSDR_MINUS50;

                Thread.Sleep(100);

                // get the value of the signal strength meter
                num2 = 0.0f;
                Thread.Sleep(1000);
                for (int i = 0; i < 50; i++)
                {
                    num2 += WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.AVG_SIGNAL_STRENGTH);
                    Thread.Sleep(50);
                    if (!progress.Visible)
                        goto end;
                    else progress.SetPercent((float)((float)++counter / progress_divisor));
                }
                avg2 = num2 / 50.0f;

                float minus50_offset = avg2 - avg;
                rx1_preamp_offset[(int)PreampMode.HPSDR_MINUS50] = -minus50_offset;

                System.Console.WriteLine("minus10_offset: " + minus10_offset);
                System.Console.WriteLine("minus20_offset: " + minus20_offset);
                System.Console.WriteLine("minus30_offset: " + minus30_offset);
                System.Console.WriteLine("minus40_offset: " + minus40_offset);
                System.Console.WriteLine("minus50_offset: " + minus50_offset);
            }
            System.Console.WriteLine("off_offset: " + off_offset);
            System.Console.WriteLine("Counter @ end: " + counter);

            RX1PreampMode = PreampMode.HPSDR_ON;
            Thread.Sleep(5000);

            cal_range = 2500.0;                         // look +/- this much from current freq to find the calibration signal
            offset = (int)(cal_range / bin_width);

            _spectrum_mutex.WaitOne();
            for (int i = 0; i < iterations; i++)            // average 10 spectra to reduce noise
            {
                fixed (double* ptr = &buf[0, 0])
                    SpecHPSDRDLL.SnapSpectrum(0, ss, 0, ptr);                   // get a spectrum
                for (int j = fft_size / 2 - offset; j <= fft_size / 2 + offset; j++)
                    sum[j] += buf[j, 0] * buf[j, 0] + buf[j, 1] * buf[j, 1];    // compute magnitude^2 and add to sum
                Thread.Sleep(20);                                               // wait a little for noise to change
            }
            _spectrum_mutex.ReleaseMutex();

            for (int i = fft_size / 2 - offset; i <= fft_size / 2 + offset; i++)// find the max value in any bin
            {
                if (sum[i] > maxsumsq)
                    maxsumsq = sum[i];
            }

            avg2 = 10.0f * (float)Math.Log10(maxsumsq / iterations / Math.Pow(fft_size, 2));

            // calculate the difference between the current value and the correct multimeter value
            float diff = level - (avg + rx1_meter_cal_offset + rx1_preamp_offset[(int)rx1_preamp_mode]);
            float diffRX2 = level - (avg + rx2_meter_cal_offset + rx2_preamp_offset[(int)rx2_preamp_mode]); // MW0LGE_[2.9.0.6]
            rx1_meter_cal_offset += diff;
            rx2_meter_cal_offset += diffRX2; //rx1_meter_cal_offset;

            rx_meter_cal_offset_by_radio[(int)current_hpsdr_model] = rx1_meter_cal_offset;  // MW0LGE_[2.9.0.7] re-instated

            // calculate the difference between the current value and the correct spectrum value
            diff = level - (avg2 + rx1_display_cal_offset + rx1_preamp_offset[(int)rx1_preamp_mode]);
            diffRX2 = level - (avg2 + rx2_display_cal_offset + rx2_preamp_offset[(int)rx2_preamp_mode]); // MW0LGE_[2.9.0.6]
            /*     for (int i = 0; i < (int)Band.LAST; i++)
                 {
                     rx1_level_table[i][0] = (float)Math.Round(diff, 3);
                     //rx1_level_table[i][1] = rx1_preamp_offset[(int)rx1_preamp_mode];
                     rx1_level_table[i][2] = (float)Math.Round(rx1_meter_cal_offset, 3);

                     if (!rx2_preamp_present)
                     {
                         rx2_level_table[i][0] = (float)Math.Round(diff, 3);
                         //rx1_level_table[i][1] = rx1_preamp_offset[(int)rx1_preamp_mode];
                         rx2_level_table[i][2] = (float)Math.Round(rx1_meter_cal_offset, 3);
                     }
                 } */

            RX1DisplayCalOffset += diff;
            RX2DisplayCalOffset += diffRX2; // MW0LGE_[2.9.0.6]
            rx_display_cal_offset_by_radio[(int)current_hpsdr_model] = RX1DisplayCalOffset;

            //   if (!rx2_preamp_present)
            //     RX2DisplayCalOffset = RX1DisplayCalOffset;

            ret_val = true;

        end:
            if (!progress.Visible) progress.Text = "";
            progress.Hide();
            //  EnableAllFilters();
            //  EnableAllModes();
            //  VFOLock = false;
            comboPreamp.Enabled = true;
            comboDisplayMode.Enabled = true;
            comboMeterRXMode.Enabled = true;

            if (ret_val == false)
            {
                rx1_meter_cal_offset = old_multimeter_cal;
                rx1_display_cal_offset = old_display_cal;
                rx2_meter_cal_offset = old_multimeter_cal_rx2; //MW0LGE_[2.9.0.6]
                rx2_display_cal_offset = old_display_cal_rx2;
            }

            comboDisplayMode.Text = display;
            chkRIT.Checked = rit_on;							// restore RIT on
            udRIT.Value = rit_val;								// restore RIT value

            chkFWCATU.Checked = ctun_on;

            RX1PreampMode = preampRX1;					        	// restore preamp value
            RX2PreampMode = preampRX2;					        	// restore preamp value MW0LGE_[2.9.0.6]
            SetupForm.RX1EnableAtt = step_attnRX1;
            SetupForm.RX2EnableAtt = step_attnRX2;   //MW0LGE_[2.9.0.6] 

            RX1DSPMode = dsp_mode;						    	// restore DSP mode

            SetupForm.DSPPhoneRXBuffer = dsp_buf_size;		    // restore DSP Buffer Size
            VFOAFreq = vfoa;									// restore vfo frequency

            CurrentMeterRXMode = rx_meter;						// restore RX Meter mode

            calibration_running = false;

            GridMinFollowsNFRX1 = bOldMinGridFollowNF; //MW0LGE_[2.9.0.6]
            GridMinFollowsNFRX2 = bOldMinGridFollowNFrx2;

            if (ret_val) //MW0LGE_[2.9.0.6]
            {
                UpdateRX1DisplayOffsets();
                UpdateRX2DisplayOffsets();
            }
            return ret_val;
        }

        public bool CalibrateRX2Level(float level, float freq, Progress progress, bool suppress_errors)
        {
            // Calibration routine called by Setup Form.
            bool ret_val = false;
            calibration_running = true;
            if (!chkPower.Checked)
            {
                if (!suppress_errors)
                {
                    MessageBox.Show("Power must be on in order to calibrate RX2 Level.", "Power Is Off",
                        MessageBoxButtons.OK, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                }
                calibration_running = false;
                return false;
            }

            float[] a = new float[Display.BUFFER_SIZE];

            bool rit_on = chkRIT.Checked;						// save current RIT On
            chkRIT.Checked = false;								// turn RIT off
            int rit_val = (int)udRIT.Value;						// save current RIT value

            double vfoa = VFOAFreq;                             // save current VFOA

            bool ctun_on = chkX2TR.Checked;
            chkX2TR.Checked = false;

            string display = comboDisplayMode.Text;
            comboDisplayMode.Text = "Spectrum";

            int dsp_buf_size = SetupForm.DSPPhoneRXBuffer;		// save current DSP buffer size
            SetupForm.DSPPhoneRXBuffer = 4096;					// set DSP Buffer Size to 2048

            Filter filter = RX1Filter;						// save current filter

            DSPMode dsp_mode = rx1_dsp_mode;				// save current DSP demod mode
            DSPMode dsp2_mode = rx2_dsp_mode;				// save current DSP demod mode

            RX1DSPMode = DSPMode.DSB;						// set mode to DSB
            RX2DSPMode = DSPMode.DSB;						// set mode to DSB

            VFOAFreq = freq;									// set VFOA frequency
            VFOBFreq = freq;

            bool duplex = full_duplex;
            FullDuplex = true;

            bool rx2 = rx2_enabled;
            RX2Enabled = true;

            Filter rx1_filter = RX1Filter;					// save current AM filter
            UpdateRX1Filters(-500, 500);

            Filter rx2_filter = RX2Filter;
            UpdateRX2Filters(-500, 500);

            bool rx2_preamp = chkRX2Preamp.Checked;					// save current preamp mode
            chkRX2Preamp.Checked = false;							// turn preamp off
            Thread.Sleep(50);

            RX2PreampMode = PreampMode.HPSDR_ON;		    	// set to high

            MeterRXMode rx_meter = CurrentMeterRXMode;			// save current RX Meter mode
            CurrentMeterRXMode = MeterRXMode.OFF;				// turn RX Meter off

            MeterRXMode rx2_meter = RX2MeterMode;
            RX2MeterMode = MeterRXMode.OFF;

            bool display_avg = chkDisplayAVG.Checked;			// save current average state
            chkDisplayAVG.Checked = false;
            chkDisplayAVG.Checked = true;						// set average state to off

            float old_multimeter_cal = rx2_meter_cal_offset;
            float old_display_cal = rx2_display_cal_offset;

            chkRX1Preamp.Enabled = false;
            chkRX2Preamp.Enabled = false;
            comboDisplayMode.Enabled = false;
            comboMeterRXMode.Enabled = false;
            comboRX2MeterMode.Enabled = false;
            int progress_divisor;

            //  if (alexpresent)
            //  {
            //      progress_divisor = 390;
            //  }
            //  else
            //  {
            progress_divisor = 120;
            //  }

            progress.SetPercent(0.0f);
            int counter = 0;

            Thread.Sleep(2000);
            btnZeroBeat_Click(this, EventArgs.Empty);
            RX1Filter = Filter.F6;
            chkDisplayAVG.Checked = false;

            Thread.Sleep(200);

            DisableAllFilters();
            DisableAllModes();
            VFOLock = CheckState.Indeterminate;

            calibration_mutex.WaitOne();

            calibration_mutex.ReleaseMutex();

            float max = float.MinValue;
            float avg = 0;

            for (int i = 0; i < 4095; i++)						// find the maximum signal
            {
                avg += a[i];
                if (a[i] > max)
                {
                    max = a[i];
                }
            }
            avg -= max;
            avg /= 4095;

            if (max < (avg + 30))
            {
                if (!suppress_errors)
                {
                    MessageBox.Show("Peak is less than 30dB from the noise floor.  " +
                        "Please use a larger signal for frequency calibration.",
                        "Calibration Error - Weak Signal",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                }
                ret_val = false;
                goto end2;
            }

            rx2_meter_cal_offset = 0.0f;
            RX2DisplayCalOffset = 0.0f;
            float num = 0.0f; float num2 = 0.0f; float avg2 = 0.0f;
            avg = 0.0f;
            // get the value of the signal strength meter
            for (int i = 0; i < 50; i++)
            {
                num += WDSP.CalculateRXMeter(2, 0, WDSP.MeterType.SIGNAL_STRENGTH);
                Thread.Sleep(50);
                if (!progress.Visible)
                    goto end2;
                else progress.SetPercent((float)((float)++counter / 120));
            }
            avg = num / 50.0f;


            RX2PreampMode = PreampMode.HPSDR_OFF;
            Thread.Sleep(200);

            // get the value of the signal strength meter
            num2 = 0.0f;
            Thread.Sleep(1000);
            for (int i = 0; i < 50; i++)
            {
                num2 += WDSP.CalculateRXMeter(2, 0, WDSP.MeterType.SIGNAL_STRENGTH);
                Thread.Sleep(50);
                if (!progress.Visible)
                    goto end2;
                else progress.SetPercent((float)((float)++counter / progress_divisor));
            }
            avg2 = num2 / 50.0f;

            float off_offset = avg2 - avg;

            rx2_preamp_offset[(int)PreampMode.HPSDR_OFF] = -off_offset;
            rx2_preamp_offset[(int)PreampMode.HPSDR_ON] = 0.0f;
            RX2PreampMode = PreampMode.HPSDR_ON;
            Thread.Sleep(200);

            num2 = 0.0f;
            for (int i = 0; i < 20; i++)
            {
                calibration_mutex.WaitOne();

                calibration_mutex.ReleaseMutex();

                max = float.MinValue;						// find the max spectrum value
                for (int j = 0; j < Display.BUFFER_SIZE; j++)
                    if (a[j] > max) max = a[j];

                num2 += max;

                Thread.Sleep(100);

                if (!progress.Visible)
                    goto end2;
                else progress.SetPercent((float)((float)++counter / 120));
            }
            avg2 = num2 / 20.0f;

            // calculate the difference between the current value and the correct multimeter value
            float diff = level - (avg + rx2_meter_cal_offset + rx2_preamp_offset[(int)rx2_preamp_mode]);
            rx2_meter_cal_offset += diff;

            // calculate the difference between the current value and the correct spectrum value
            diff = level - (avg2 + rx2_display_cal_offset + rx2_preamp_offset[(int)rx2_preamp_mode]);
            RX2DisplayCalOffset = diff;

            ret_val = true;

        end2:
            if (!progress.Visible) progress.Text = "";
            progress.Hide();
            EnableAllFilters();
            EnableAllModes();
            VFOLock = CheckState.Unchecked;
            chkRX1Preamp.Enabled = true;
            chkRX2Preamp.Enabled = true;
            comboDisplayMode.Enabled = true;
            comboMeterRXMode.Enabled = true;
            comboRX2MeterMode.Enabled = true;

            if (ret_val == false)
            {
                rx2_meter_cal_offset = old_multimeter_cal;
                rx2_display_cal_offset = old_display_cal;
            }

            RX2Enabled = rx2;
            comboDisplayMode.Text = display;
            chkRIT.Checked = rit_on;							// restore RIT on
            udRIT.Value = rit_val;								// restore RIT value		

            chkX2TR.Checked = ctun_on;

            DisplayAVG = display_avg;							// restore AVG value
            chkRX2Preamp.Checked = rx2_preamp;
            RX1Filter = rx1_filter;							// restore AM filter
            RX1DSPMode = dsp_mode;							// restore DSP mode*
            RX2Filter = rx2_filter;							// restore AM filter
            RX2DSPMode = dsp2_mode;							// restore DSP mode
            RX1Filter = filter;								// restore filter
            if (dsp_buf_size != 4096)
                chkPower.Checked = false;						// go to standby
            SetupForm.DSPPhoneRXBuffer = dsp_buf_size;				// restore DSP Buffer Size
            VFOAFreq = vfoa;									// restore vfo frequency
            if (dsp_buf_size != 4096)
            {
                Thread.Sleep(100);
                chkPower.Checked = true;
            }
            CurrentMeterRXMode = rx_meter;						// restore RX Meter mode
            RX2MeterMode = rx2_meter;

            calibration_running = false;
            return ret_val;
        }

        public bool CalibratePAGain(Progress progress, bool[] run, int target_watts) // calibrate PA Gain values
        {
            bool ret_val = false;

            if (!chkPower.Checked)
            {
                MessageBox.Show("START must be active in order to calibrate PA Gain.", "START is not presently active",
                    MessageBoxButtons.OK, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                return false;
            }

            calibrating = true;

            DSPMode dsp_mode = rx1_dsp_mode;			// save current wdsp mode
            RX1DSPMode = DSPMode.USB;					// set wdsp mode to CWL

            double vfo_freq = VFOAFreq;						// save current frequency

            int pwr = ptbPWR.Value;						// save current pwr level

            bool tx_eq = chkTXEQ.Checked;
            chkTXEQ.Checked = false;

            bool dx = chkDX.Checked;
            chkDX.Checked = false;

            bool cpdr = chkCPDR.Checked;
            chkCPDR.Checked = false;

            DisableAllFilters();
            DisableAllModes();
            VFOLock = CheckState.Checked;
            comboPreamp.Enabled = false;
            comboDisplayMode.Enabled = false;

            int on_time = 2500;
            int off_time = 2500;

            progress.SetPercent(0.0f);

            float[] band_freqs = { 1.85f, 3.75f, 5.3715f, 7.15f, 10.125f, 14.175f, 18.1f, 21.300f, 24.9f, 28.4f, 50.4f };
            Band[] bands = { Band.B160M, Band.B80M, Band.B60M, Band.B40M, Band.B30M, Band.B20M, Band.B17M, Band.B15M, Band.B12M, Band.B10M, Band.B6M }; //MW0LGE_22b
            int[] max_pwr = { 100, 100, 100, 100, 100, 100, 100, 100, 75, 75, 75 };

            //MW0LGE_22b
            for (int n = (int)Band.B160M; n <= (int)Band.B6M; n++)
            {
                Band b = (Band)n;
                int ndx = n - (int)Band.B160M;

                if (run[ndx]) SetupForm.SetBypassGain(b, 49.0f);
            }

            for (int i = 0; i < band_freqs.Length; i++)
            {
                if (run[i])
                {
                    int error_count = 0;
                    VFOLock = CheckState.Unchecked;
                    VFOAFreq = band_freqs[i];				// set frequency
                    VFOLock = CheckState.Checked;
                    ptbPWR.Value = Math.Min(target_watts, max_pwr[i]);
                    int target = ptbPWR.Value;

                    bool good_result = false;
                    while (good_result == false)
                    {
                        Audio.SourceScale = 1.0;
                        Audio.TXInputSignal = Audio.SignalSource.SINE;
                        tuning = true;
                        chkMOX.Checked = true;

                        for (int j = 0; j < on_time / 100; j++)
                        {
                            Thread.Sleep(100);
                            if (!progress.Visible)
                                goto end;
                        }

                        double watts = 0.0;

                        watts = alex_fwd;

                        chkMOX.Checked = false;
                        tuning = false;

                        Audio.TXInputSignal = Audio.SignalSource.RADIO;

                        if (!progress.Visible)
                            goto end;

                        if (Math.Abs(watts - target) > 2)
                        {
                            // convert to dBm
                            float diff_dBm = (float)Math.Round((WattsTodBm(watts) - WattsTodBm((double)target)), 3);

                            //MW0LGE_22b
                            float g = SetupForm.GetBypassGain(bands[i]);
                            if (g + diff_dBm < 38.8)
                            {
                                if (++error_count > 6)
                                    goto error;

                                float newG = (float)Math.Max(38.8, g - 2.0);
                                SetupForm.SetBypassGain(bands[i], g);
                            }
                            else
                                SetupForm.SetBypassGain(bands[i], g + diff_dBm);

                        }
                        else good_result = true;
                        for (int j = 0; j < off_time / 100; j++)
                        {
                            Thread.Sleep(100);
                            if (!progress.Visible)
                                goto end;
                        }
                    }
                }
                progress.SetPercent((float)((float)(i + 1) / 10));
            }

            ret_val = true;

        end:
            if (!progress.Visible) progress.Text = "";
            progress.Hide();

            EnableAllFilters();
            EnableAllModes();
            VFOLock = CheckState.Unchecked;
            comboPreamp.Enabled = true;
            comboDisplayMode.Enabled = true;

            chkTXEQ.Checked = tx_eq;
            chkDX.Checked = dx;
            chkCPDR.Checked = cpdr;

            chkMOX.Checked = false;
            tuning = false;

            Audio.TXInputSignal = Audio.SignalSource.RADIO;
            Audio.TXOutputSignal = Audio.SignalSource.RADIO;

            RX1DSPMode = dsp_mode;							// restore wdsp mode
            VFOAFreq = vfo_freq;								// restore frequency
            txtVFOAFreq_LostFocus(this, EventArgs.Empty);
            PWR = pwr;									// restore pwr level

            calibrating = false;

            return ret_val;

        error:
            MessageBox.Show("Calculated gain is invalid.  Please double check connections and try again.\n"/* +
                "If this problem persists, contact support@flex-radio.com for support."*/,
                "Invalid Gain Found",
                MessageBoxButtons.OK,
                MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
            goto end;
        }

        public bool CalibratePAGain2(Progress progress, bool[] run, bool suppress_warnings)
        {
            return true;
        }

        public bool LowPowerPASweep(Progress progress, int power) // calibrate PA Gain values
        {
            bool ret_val = false;

            if (!chkPower.Checked)
            {
                MessageBox.Show("Power must be on in order to run PA Sweep.", "Power Is Off",
                    MessageBoxButtons.OK, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                return false;
            }

            calibrating = true;

            DSPMode dsp_mode = RX1DSPMode;				// save current DSP Mode
            RX1DSPMode = DSPMode.USB;					// set DSP Mode to USB

            double vfo_freq = VFOAFreq;						// save current frequency

            int pwr = PWR;						// save current pwr level
            PWR = power;						// set pwr level to 100W

            progress.SetPercent(0.0f);

            float[] band_freqs = { 1.9f, 3.75f, 5.3715f, 7.15f, 10.125f, 14.175f, 18.1f, 21.225f, 24.9f, 28.85f };

            for (int i = 0; i < band_freqs.Length; i++)
            {
                VFOAFreq = band_freqs[i];				// set frequency
                Audio.TXInputSignal = Audio.SignalSource.SINE;
                Audio.SourceScale = 1.0;
                chkMOX.Checked = true;
                for (int j = 0; j < 30; j++)
                {
                    Thread.Sleep(100);
                    if (!progress.Visible)
                        goto end;
                }
                chkMOX.Checked = false;
                Audio.TXInputSignal = Audio.SignalSource.RADIO;

                if (!progress.Visible)
                    goto end;

                for (int j = 0; j < 40; j++)
                {
                    Thread.Sleep(100);
                    if (!progress.Visible)
                        goto end;
                }
                if (!progress.Visible)
                    goto end;

                progress.SetPercent((float)((float)(i + 1) / 10));
            }

            ret_val = true;

        end:
            progress.Hide();
            chkMOX.Checked = false;
            Audio.TXInputSignal = Audio.SignalSource.RADIO;
            RX1DSPMode = dsp_mode;							// restore wdsp mode
            VFOAFreq = vfo_freq;								// restore frequency
            txtVFOAFreq_LostFocus(this, EventArgs.Empty);
            PWR = pwr;									// restore pwr level

            calibrating = false;

            return ret_val;
        }

        #endregion

        #region Properties
        // ======================================================
        // Properties
        // ======================================================

        private IntPtr n1mm_handle = IntPtr.Zero;
        public IntPtr N1MMHandle
        {
            get { return n1mm_handle; }
            set { n1mm_handle = value; }
        }

        IntPtr myHandle = IntPtr.Zero;
        bool selectByClick = false;
        private FocusMasterMode focus_master_mode = FocusMasterMode.None;
        public FocusMasterMode FocusMasterMode
        {
            get { return focus_master_mode; }
            set
            {
                focus_master_mode = value;
                n1mm_handle = IntPtr.Zero;

                if (value != FocusMasterMode.None)
                {
                    if (n1mm_delay == null)
                    {
                        n1mm_delay = new System.Timers.Timer(focus_master_delay);
                        n1mm_delay.Elapsed += new ElapsedEventHandler(n1mm_delay_Elapsed);
                        n1mm_delay.AutoReset = false;
                        n1mm_delay.Enabled = false;
                    }
                    else n1mm_delay.Enabled = false;
                }
                else
                {
                    if (n1mm_delay != null)
                        n1mm_delay.Enabled = false;
                }

                switch (value)
                {
                    case FocusMasterMode.Logger:
                        Thread n1mm_focus_thread = new Thread(new ThreadStart(PollN1MMPacket))
                        {
                            Name = "N1MM Packet Thread",
                            IsBackground = true,
                            Priority = ThreadPriority.BelowNormal
                        };
                        n1mm_focus_thread.Start();
                        break;
                    case FocusMasterMode.Click:
                        myHandle = Win32.GetForegroundWindow();
                        selectByClick = true;
                        SetFocusMaster(false);
                        SetFocusMaster(true);
                        break;
                    case FocusMasterMode.Title:
                        break;
                    case FocusMasterMode.None:
                        SetFocusMaster(false);
                        break;
                }
            }
        }

        private int focus_master_delay = 2000;
        public int FocusMasterDelay
        {
            get { return focus_master_delay; }
            set
            {
                focus_master_delay = value;
                if (n1mm_delay != null)
                {
                    n1mm_delay.Interval = focus_master_delay;
                }
            }
        }

        private int focus_master_udp_port = 12060;
        public int FocusMasterUDPPort
        {
            get { return focus_master_udp_port; }
            set { focus_master_udp_port = value; }
        }

        private string focus_master_win_title = "";
        public string FocusMasterWinTitle
        {
            get { return focus_master_win_title; }
            set { focus_master_win_title = value; }
        }

        private bool enable_led_font = false;
        public bool EnableLEDFont
        {
            get { return enable_led_font; }
            set
            {
                enable_led_font = value;
                if (value)
                {
                    txtVFOAFreq.Font = LEDLFont;
                    txtVFOBFreq.Font = LEDLFont;
                    txtVFOAMSD.Font = LEDLFont;
                    txtVFOBMSD.Font = LEDLFont;
                    txtVFOALSD.Font = LEDSFont;
                    txtVFOBLSD.Font = LEDSFont;
                    txtMultiText.Font = LEDMFont;
                    txtRX2Meter.Font = LEDMFont;
                }
                else
                {
                    txtVFOAFreq.Font = new Font(FontFamily.GenericSansSerif, 20.25F, FontStyle.Regular);
                    txtVFOBFreq.Font = new Font(FontFamily.GenericSansSerif, 20.25F, FontStyle.Regular);
                    txtVFOAMSD.Font = new Font(FontFamily.GenericSansSerif, 20.25F, FontStyle.Regular);
                    txtVFOBMSD.Font = new Font(FontFamily.GenericSansSerif, 20.25F, FontStyle.Regular);
                    txtVFOALSD.Font = new Font(FontFamily.GenericSansSerif, 15.75F, FontStyle.Regular);
                    txtVFOBLSD.Font = new Font(FontFamily.GenericSansSerif, 15.75F, FontStyle.Regular);
                    txtMultiText.Font = new Font(FontFamily.GenericSansSerif, 18F, FontStyle.Regular);
                    txtRX2Meter.Font = new Font(FontFamily.GenericSansSerif, 18F, FontStyle.Regular);
                }
            }

        }

        public Color TxAttenuationBackgroundColour
        {
            set { udTXStepAttData.BackColor = value; }
        }
        private int tx_attenuator_data = 31;
        private bool _updatingTxAtt = false;
        public int TxAttenData
        {
            get { return tx_attenuator_data; }
            set
            {
                if (_updatingTxAtt) return;
                _updatingTxAtt = true;
                tx_attenuator_data = value;
                if (!initializing)
                {
                    setTXstepAttenuatorForBand(tx_band, tx_attenuator_data); //[2.10.3.6]MW0LGE att_fixes #399
                    if (m_bAttontx)
                    {
                        int txatt = getTXstepAttenuatorForBand(tx_band);
                        NetworkIO.SetTxAttenData(txatt); //[2.10.3.6]MW0LGE att_fixes
                        Display.TXAttenuatorOffset = txatt; //[2.10.3.6]MW0LGE att_fixes
                    }
                    else
                    {
                        NetworkIO.SetTxAttenData(0);
                        Display.TXAttenuatorOffset = 0;
                    }

                    //if (m_bAttontx && _mox) //[2.10.3.6]MW0LGE att_fixes
                    //udRX1StepAttData.Value = value; //[2.10.3.6]MW0LGE att_fixes
                    udTXStepAttData.Value = value;
                }
                _updatingTxAtt = false;
            }
        }

        private bool amp_protect = false;
        public bool AmpProtect
        {
            get { return amp_protect; }
            set { amp_protect = value; }
        }

        public bool ManualMox
        {
            get { return manual_mox; }
            set { manual_mox = value; }
        }

        private string apf_btn = "APF";
        public string APFbtn
        {
            get
            {
                return apf_btn;
            }
            set
            {
                apf_btn = value;
                chkCWAPFEnabled.Text = value;
            }
        }

        private string rx1_apf_label = "";
        public string RX1APFlabel
        {
            get
            {
                return rx1_apf_label;
            }
            set
            {
                rx1_apf_label = value;
                lblRX1APF.Text = value;
            }
        }

        private string rx2_apf_label = "";
        public string RX2APFlabel
        {
            get
            {
                return rx2_apf_label;
            }
            set
            {
                rx2_apf_label = value;
                lblRX2APF.Text = value;
            }
        }

        private bool cw_fw_keyer = true;
        public bool CWFWKeyer
        {
            get { return cw_fw_keyer; }
            set
            {
                cw_fw_keyer = value;
                udCWBreakInDelay_ValueChanged(this, EventArgs.Empty);
                NetworkIO.EnableCWKeyer(Convert.ToInt32(value));

                if (!initializing)
                    txtVFOAFreq_LostFocus(this, EventArgs.Empty);
            }
        }

        private bool startdiversity = false;
        private bool diversity2 = false;
        unsafe public bool Diversity2
        {
            get { return diversity2; }
            set
            {
                diversity2 = value;
                AndromedaIndicatorCheck(EIndicatorActions.eINDiversityEnabled, false, diversity2);
                if (diversity2)
                {
                    txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                    UpdateAAudioMixerStates();
                    UpdateDDCs(rx2_enabled);
                    if (RX1StepAttPresent) udRX1StepAttData_ValueChanged(this, EventArgs.Empty);
                    else comboPreamp_SelectedIndexChanged(this, EventArgs.Empty);
                    WDSP.SetEXTDIVRun(0, 1);
                    cmaster.LoadRouterControlBit((void*)0, 0, 1, 1);
                }
                else
                {
                    UpdateDDCs(rx2_enabled);
                    if (RX2StepAttPresent) udRX2StepAttData_ValueChanged(this, EventArgs.Empty);
                    else comboRX2Preamp_SelectedIndexChanged(this, EventArgs.Empty);
                    WDSP.SetEXTDIVRun(0, 0);
                    cmaster.LoadRouterControlBit((void*)0, 0, 1, 0);
                    UpdateAAudioMixerStates();
                }

                UpdateDiversityMenuItem(); //MW0LGE_22b
            }
        }

        // MW0LGE_21d changed to set/getter so can bse used in event delgate system to track changes
        private double m_dCentreFrequency = 0.0;
        public double CentreFrequency
        {
            get
            {
                return Math.Round(m_dCentreFrequency, 6); //MW0LGE_21k8
            }
            set
            {
                double dOld = m_dCentreFrequency;
                m_dCentreFrequency = value;
                if (dOld != m_dCentreFrequency) CentreFrequencyHandlers?.Invoke(1, Math.Round(dOld, 6), Math.Round(m_dCentreFrequency, 6), RX1Band, radio.GetDSPRX(0, 0).RXOsc); //MW0LGE_21d //MW0LGE_21k9d roundings
            }
        }

        private double m_dCentreRX2Frequency = 0.0;
        public double CentreRX2Frequency
        {
            get
            {
                return Math.Round(m_dCentreRX2Frequency, 6); //MW0LGE_21k8
            }
            set {
                double dOld = m_dCentreRX2Frequency;
                m_dCentreRX2Frequency = value;
                if (dOld != m_dCentreRX2Frequency) CentreFrequencyHandlers?.Invoke(2, Math.Round(dOld, 6), Math.Round(m_dCentreRX2Frequency, 6), RX2Band, radio.GetDSPRX(1, 0).RXOsc); //MW0LGE_21d //MW0LGE_21k9d roundings
            }
        }

        private bool update_centerfreq = false;
        public bool UpdateCenterFreq
        {
            get { return update_centerfreq; }
            set
            {
                update_centerfreq = value;
            }
        }

        private bool update_rx2_centerfreq = false;
        public bool UpdateRX2CenterFreq
        {
            get { return update_rx2_centerfreq; }
            set
            {
                update_rx2_centerfreq = value;
            }
        }

        public bool CTuneDisplay
        {
            get { return chkFWCATU.Checked; }
            set
            {
                chkFWCATU.Checked = value;
                if (value == true)
                    lblCtunLabel.BackColor = System.Drawing.Color.Blue;
                else
                    lblCtunLabel.BackColor = System.Drawing.Color.Transparent;

            }
        }

        public bool CTuneRX2Display
        {
            get { return chkX2TR.Checked; }
            set
            {
                chkX2TR.Checked = value;
                if (value == true)
                    lblRX2CtunLabel.BackColor = System.Drawing.Color.Blue;
                else
                    lblRX2CtunLabel.BackColor = System.Drawing.Color.Transparent;
            }
        }

        private bool click_tune_display = false;
        public bool ClickTuneDisplay
        {
            get { return click_tune_display; }
            set
            {
                bool bOld = click_tune_display;
                click_tune_display = value;
                if (bOld != click_tune_display) CTUNChangedHandlers?.Invoke(1, bOld, click_tune_display, RX1Band); //MW0LGE_21d
            }
        }

        private bool click_tune_rx2_display = false;
        public bool ClickTuneRX2Display
        {
            get { return click_tune_rx2_display; }
            set
            {
                bool bOld = click_tune_rx2_display;
                click_tune_rx2_display = value;
                if (bOld != click_tune_rx2_display) CTUNChangedHandlers?.Invoke(2, bOld, click_tune_rx2_display, RX2Band); //MW0LGE_21d
            }
        }

        private bool vhf_tr_relay = false;
        public bool VHFTRRelay
        {
            get { return vhf_tr_relay; }
            set
            {
                vhf_tr_relay = value;
            }
        }

        private bool hf_tr_relay = false;
        public bool HFTRRelay
        {
            get { return hf_tr_relay; }
            set
            {
                hf_tr_relay = value;
                if (!initializing)
                    txtVFOAFreq_LostFocus(this, EventArgs.Empty);
            }
        }

        private bool bpf2_gnd = true;
        public bool BPF2Gnd
        {
            get { return bpf2_gnd; }
            set
            {
                bpf2_gnd = value;
            }
        }

        private bool enable_xvtr_hf = false;
        public bool EnableXVTRHF
        {
            get { return enable_xvtr_hf; }
            set
            {
                enable_xvtr_hf = value;
                if (!initializing)
                {
                    txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                    txtVFOBFreq_LostFocus(this, EventArgs.Empty);
                }
            }
        }

        public bool ANAN8000DLEDisplayVoltsAmps { get; set; }

        private bool rx1_step_att_present = false;
        public bool RX1StepAttPresent
        {
            get { return rx1_step_att_present; }
            set
            {
                rx1_step_att_present = value;
                if (rx1_step_att_present)
                {
                    udRX1StepAttData.Value = getRX1stepAttenuatorForBand(rx1_band); //MW0LGE [2.10.3.6] added
                    udRX1StepAttData_ValueChanged(this, EventArgs.Empty);
                }
                else
                {
                    comboPreamp_SelectedIndexChanged(this, EventArgs.Empty);

                    if (alexpresent)
                        NetworkIO.SetAlexAtten(alex_atten); // normal up alex attenuator setting
                }

                updateAttNudsCombos();

                if (!_mox)
                {
                    update_preamp = true;
                    UpdatePreamps();
                }
                UpdateRX1DisplayOffsets();
            }
        }

        private bool _setFromOtherAttenuator = false; // used to prevent other attenuator from re-setting the caller
        private int rx1_attenuator_data = 0;
        private int _sa_rx1_last_adjust = 0;
        public int RX1AttenuatorData
        {
            get { return rx1_attenuator_data; }
            set
            {
                int oldData = rx1_attenuator_data;
                rx1_attenuator_data = value;
                if (initializing) return;
                
                if (alexpresent &&
                    current_hpsdr_model != HPSDRModel.ANAN10 &&
                    current_hpsdr_model != HPSDRModel.ANAN10E &&
                    current_hpsdr_model != HPSDRModel.ANAN7000D &&
                    current_hpsdr_model != HPSDRModel.ANAN8000D &&
                    current_hpsdr_model != HPSDRModel.ORIONMKII &&
                    current_hpsdr_model != HPSDRModel.ANAN_G2 &&
                    current_hpsdr_model != HPSDRModel.ANAN_G2_1K)
                    udRX1StepAttData.Maximum = (decimal)61;
                else udRX1StepAttData.Maximum = (decimal)31;

                //MW0LGE_22b step atten
                int nRX1DDCinUse = -1, nRX2DDCinUse = -1, sync1 = -1, sync2 = -1, psrx = -1, pstx = -1;
                GetDDC(out nRX1DDCinUse, out nRX2DDCinUse, out sync1, out sync2, out psrx, out pstx);

                int nRX1ADCinUse = GetADCInUse(nRX1DDCinUse); // (rx1)
                int nRX2ADCinUse = GetADCInUse(nRX2DDCinUse); // (rx2)

                if (rx1_step_att_present)
                {
                    if (alexpresent &&
                        current_hpsdr_model != HPSDRModel.ANAN10 &&
                        current_hpsdr_model != HPSDRModel.ANAN10E &&
                        current_hpsdr_model != HPSDRModel.ANAN7000D &&
                        current_hpsdr_model != HPSDRModel.ANAN8000D &&
                        current_hpsdr_model != HPSDRModel.ORIONMKII &&
                        current_hpsdr_model != HPSDRModel.ANAN_G2 &&
                        current_hpsdr_model != HPSDRModel.ANAN_G2_1K)
                    {
                        if (rx1_attenuator_data <= 31)
                        {
                            NetworkIO.SetAlexAtten(0); // 0dB Alex Attenuator
                            if (nRX1ADCinUse == 0) NetworkIO.SetADC1StepAttenData(rx1_attenuator_data);
                            else if (nRX1ADCinUse == 1) NetworkIO.SetADC2StepAttenData(rx1_attenuator_data);
                            else if (nRX1ADCinUse == 2) NetworkIO.SetADC3StepAttenData(rx1_attenuator_data);
                        }
                        else
                        {
                            NetworkIO.SetAlexAtten(3); // -30dB Alex Attenuator
                            if (nRX1ADCinUse == 0) NetworkIO.SetADC1StepAttenData(rx1_attenuator_data + 2);
                            else if (nRX1ADCinUse == 1) NetworkIO.SetADC2StepAttenData(rx1_attenuator_data + 2);
                            else if (nRX1ADCinUse == 2) NetworkIO.SetADC3StepAttenData(rx1_attenuator_data + 2);
                        }
                    }
                    else
                    {
                        NetworkIO.SetAlexAtten(0);
                        if (nRX1ADCinUse == 0) NetworkIO.SetADC1StepAttenData(rx1_attenuator_data);
                        else if (nRX1ADCinUse == 1) NetworkIO.SetADC2StepAttenData(rx1_attenuator_data);
                        else if (nRX1ADCinUse == 2) NetworkIO.SetADC3StepAttenData(rx1_attenuator_data);
                    }
                }

                if (!_mox)
                    setRX1stepAttenuatorForBand(rx1_band, rx1_attenuator_data);

                udRX1StepAttData.Value = rx1_attenuator_data;
                lblAttenLabel.Text = rx1_attenuator_data.ToString() + " dB";

                if (!_mox)
                {
                    if (!_setFromOtherAttenuator)
                    {
                        bool bRX1RX2diversity = m_bDiversityAttLinkForRX1andRX2 && (diversityForm != null && Diversity2 && diversityForm.EXTDIVOutput == 2); // if using diversity, and both rx's are linked, then we need to attenuate both
                        if (((nRX1ADCinUse == nRX2ADCinUse) || bRX1RX2diversity) && RX2AttenuatorData != rx1_attenuator_data)
                        {
                            _setFromOtherAttenuator = true;
                            if (SetupForm.RX2EnableAtt != SetupForm.RX1EnableAtt) SetupForm.RX2EnableAtt = SetupForm.RX1EnableAtt;
                            RX2AttenuatorData = rx1_attenuator_data;
                            _setFromOtherAttenuator = false;
                        }
                    }

                    update_preamp = true;
                    UpdatePreamps();
                }

                UpdateRX1DisplayOffsets();

                if (oldData != rx1_attenuator_data) AttenuatorDataChangedHandlers?.Invoke(1, oldData, rx1_attenuator_data);
            }
        }

        private bool m_bDiversityAttLinkForRX1andRX2 = false;
        public bool DiversityAttLink //[2.10.3.4]MW0LGE used by diversity form
        {
            get { return m_bDiversityAttLinkForRX1andRX2; }
            set { m_bDiversityAttLinkForRX1andRX2 = value; }
        }

        private bool rx2_step_att_present = false;
        public bool RX2StepAttPresent
        {
            get { return rx2_step_att_present; }
            set
            {
                rx2_step_att_present = value;
                if (rx2_preamp_present)
                {
                    if (rx2_step_att_present)
                    {
                        udRX2StepAttData.Value = getRX2stepAttenuatorForBand(rx2_band);
                        udRX2StepAttData_ValueChanged(this, EventArgs.Empty);
                    }
                    else
                    {
                        comboRX2Preamp_SelectedIndexChanged(this, EventArgs.Empty);
                    }
                }

                updateAttNudsCombos();

                if (!_mox)
                {
                    //update_preamp_mode = false;
                    update_preamp = true;
                    UpdatePreamps();
                }
                UpdateRX2DisplayOffsets();
            }
        }

        private bool RX1RX2usingSameADC
        {
            get
            {
                int nRX1DDCinUse = -1, nRX2DDCinUse = -1, sync1 = -1, sync2 = -1, psrx = -1, pstx = -1;
                GetDDC(out nRX1DDCinUse, out nRX2DDCinUse, out sync1, out sync2, out psrx, out pstx);

                int nRX1ADCinUse = GetADCInUse(nRX1DDCinUse); // (rx1)
                int nRX2ADCinUse = GetADCInUse(nRX2DDCinUse); // (rx2)

                return nRX1ADCinUse == nRX2ADCinUse;
            }
        }
        private int rx2_attenuator_data = 0;
        public int RX2AttenuatorData
        {
            get { return rx2_attenuator_data; }
            set
            {
                int oldData = rx2_attenuator_data;
                rx2_attenuator_data = value;
                if (initializing) return;

                if (alexpresent &&
                    current_hpsdr_model != HPSDRModel.ANAN10 &&
                    current_hpsdr_model != HPSDRModel.ANAN10E &&
                    current_hpsdr_model != HPSDRModel.ANAN7000D &&
                    current_hpsdr_model != HPSDRModel.ANAN8000D &&
                    current_hpsdr_model != HPSDRModel.ORIONMKII &&
                    current_hpsdr_model != HPSDRModel.ANAN_G2 &&
                    current_hpsdr_model != HPSDRModel.ANAN_G2_1K)
                    udRX2StepAttData.Maximum = (decimal)61; //MW0LGE_[2.9.0.7]  changed to udRX2
                else udRX2StepAttData.Maximum = (decimal)31;

                //MW0LGE_22b step atten
                int nRX1DDCinUse = -1, nRX2DDCinUse = -1, sync1 = -1, sync2 = -1, psrx = -1, pstx = -1;
                GetDDC(out nRX1DDCinUse, out nRX2DDCinUse, out sync1, out sync2, out psrx, out pstx);

                int nRX1ADCinUse = GetADCInUse(nRX1DDCinUse); // (rx1)
                int nRX2ADCinUse = GetADCInUse(nRX2DDCinUse); // (rx2)

                if (rx2_step_att_present)
                {
                    if (alexpresent &&
                        current_hpsdr_model != HPSDRModel.ANAN10 &&
                        current_hpsdr_model != HPSDRModel.ANAN10E &&
                        current_hpsdr_model != HPSDRModel.ANAN7000D &&
                        current_hpsdr_model != HPSDRModel.ANAN8000D &&
                        current_hpsdr_model != HPSDRModel.ORIONMKII &&
                        current_hpsdr_model != HPSDRModel.ANAN_G2 &&
                        current_hpsdr_model != HPSDRModel.ANAN_G2_1K)
                    {
                        if (rx2_attenuator_data <= 31)
                        {
                            if (nRX2ADCinUse == 0) NetworkIO.SetADC1StepAttenData(rx2_attenuator_data);
                            else if (nRX2ADCinUse == 1) NetworkIO.SetADC2StepAttenData(rx2_attenuator_data);
                            else if (nRX2ADCinUse == 2) NetworkIO.SetADC3StepAttenData(rx2_attenuator_data);
                        }
                        else
                        {
                            if (nRX2ADCinUse == 0) NetworkIO.SetADC1StepAttenData(rx2_attenuator_data + 2);
                            else if (nRX2ADCinUse == 1) NetworkIO.SetADC2StepAttenData(rx2_attenuator_data + 2);
                            else if (nRX2ADCinUse == 2) NetworkIO.SetADC3StepAttenData(rx2_attenuator_data + 2);
                        }
                    }
                    else
                    {
                        if (nRX2ADCinUse == 0) NetworkIO.SetADC1StepAttenData(rx2_attenuator_data);
                        else if (nRX2ADCinUse == 1) NetworkIO.SetADC2StepAttenData(rx2_attenuator_data);
                        else if (nRX2ADCinUse == 2) NetworkIO.SetADC3StepAttenData(rx2_attenuator_data);
                    }
                }

                if (!_mox)
                    setRX2stepAttenuatorForBand(rx2_band, rx2_attenuator_data);

                udRX2StepAttData.Value = rx2_attenuator_data;
                lblRX2AttenLabel.Text = rx2_attenuator_data.ToString() + " dB";

                if (!_mox)
                {
                    if (!_setFromOtherAttenuator)
                    {
                        bool bRX1RX2diversity = m_bDiversityAttLinkForRX1andRX2 && (diversityForm != null && Diversity2 && diversityForm.EXTDIVOutput == 2); // if using diversity, and both rx's are linked, then we need to attenuate both //MW0LGE_[2.9.0.6]
                        if (((nRX1ADCinUse == nRX2ADCinUse) || bRX1RX2diversity) && RX1AttenuatorData != rx2_attenuator_data)
                        {
                            _setFromOtherAttenuator = true;
                            if (SetupForm.RX1EnableAtt != SetupForm.RX2EnableAtt) SetupForm.RX1EnableAtt = SetupForm.RX2EnableAtt;
                            RX1AttenuatorData = rx2_attenuator_data;
                            _setFromOtherAttenuator = false;
                        }
                    }

                    update_preamp = true;
                    UpdatePreamps();
                }

                UpdateRX2DisplayOffsets();

                if (oldData != rx2_attenuator_data) AttenuatorDataChangedHandlers?.Invoke(2, oldData, rx2_attenuator_data);
            }
        }

        private int[] m_nTuneStepsByMode; //MW0LGE_21j

        private List<TuneStep> tune_step_list;				// A list of available tuning steps
        public List<TuneStep> TuneStepList
        {
            get { return tune_step_list; }
        }

        private int tune_step_index;						// An index into the above array
        public int TuneStepIndex
        {
            get { return tune_step_index; }
            set
            {
                if (value < 0 || value > tune_step_list.Count - 1)
                    return;

                int old_index = tune_step_index;

                tune_step_index = value;

                // store the step index against mode. This is recovered on mode change event MW0LGE_21j
                if (m_nLastRXThatHadModeChange == 1)
                    if (isDSPModeValid(RX1DSPMode)) m_nTuneStepsByMode[(int)RX1DSPMode] = tune_step_index;

                txtWheelTune.Text = tune_step_list[tune_step_index].Name;
                lblStepValue.Text = txtWheelTune.Text;

                if (old_index != tune_step_index)
                {
                    TuneStepIndexChangedHandlers?.Invoke(1, old_index, tune_step_index);
                    TuneStepIndexChangedHandlers?.Invoke(2, old_index, tune_step_index);
                }
            }
        }
        public int TuneStepLookup(string s)
        {
            for (int i = 0; i < tune_step_list.Count; i++)
            {
                if (tune_step_list[i].Name == s)
                    return i;
            }

            return -1;
        }
        private bool isDSPModeValid(DSPMode mode)
        {
            return (int)mode > (int)DSPMode.FIRST && (int)mode < (int)DSPMode.LAST;
        }
        private int m_nLastRXThatHadModeChange = 0;
        private void updateStepIndexForMode(int rx, DSPMode mode)
        {
            if (!isDSPModeValid(mode) || rx == 2) return;
            if (!TuneStepPerModeRX1) return;

            m_nLastRXThatHadModeChange = rx;

            TuneStepIndex = m_nTuneStepsByMode[(int)mode];
        }
        private bool m_bTuneStepPerModeRX1 = false;
        public bool TuneStepPerModeRX1
        {
            get
            {
                return m_bTuneStepPerModeRX1;
            }
            set
            {
                m_bTuneStepPerModeRX1 = value;
                updateStepIndexForMode(1, RX1DSPMode);
            }
        }
        /// <summary>
        /// The transmit frequency in MHz
        /// </summary>
        private double _old_tx_freq = -1f;
        private Band _old_tx_band = Band.FIRST;
        public double TXFreq
        {
            get
            {
                double tx_freq = 0.0;

                if (!rx2_enabled)
                {
                    if (!chkVFOBTX.Checked)
                        tx_freq = VFOAFreq;
                    else
                        tx_freq = VFOBFreq;
                }
                else
                {
                    if (chkVFOBTX.Checked)
                        tx_freq = VFOBFreq;
                    else if (chkVFOSplit.Checked)
                        tx_freq = VFOASubFreq;
                    else if (chkVFOATX.Checked)
                        tx_freq = VFOAFreq;
                }

                return tx_freq;
            }

            set
            {
                if (!rx2_enabled)
                {
                    if (!chkVFOBTX.Checked)
                        VFOAFreq = value;
                    else
                        VFOBFreq = value;
                }
                else
                {
                    if (chkVFOBTX.Checked)
                        VFOBFreq = value;
                    else if (chkVFOSplit.Checked)
                        VFOASubFreq = value;
                    else if (chkVFOATX.Checked)
                        VFOAFreq = value;
                }
            }
        }

        private bool swap_vfo_ab_tx = false;
        public bool SwapVFOA_BTX
        {
            get { return swap_vfo_ab_tx; }
            set
            {
                if (value)
                {
                    chkVFOBTX.Checked = true;
                }
                else
                {
                    chkVFOATX.Checked = true;
                }
                swap_vfo_ab_tx = value;
            }
        }

        private bool[] _masterAFLink = { false, false, false, false };
        public void SetAFLinks(int source, bool state)
        {
            if (source < 0 || source > 3) return;

            _masterAFLink[source] = state;

            int value = 0;

            switch (source)
            {
                case 0:
                    value = AF;//master
                    break;
                case 1:
                    value = RX0Gain;//rx1
                    break;
                case 2:
                    value = RX1Gain;//rx1sub
                    break;
                case 3:
                    value = RX2Gain;//rx2
                    break;
            }
            setLinkedAF(source, value);
        }
        public bool IsMasterAFLinked(int rx)
        {
            if (rx < 0 || rx > 3) return false;

            return _masterAFLink[rx];
        }
        private bool _settingLinked = false;
        private void setLinkedAF(int source, int value)
        {
            if (!IsSetupFormNull && SetupForm.LinkAFSlidersOnlyIfCtrlHeld && !Common.CtrlKeyDown) return;
            if (source < 0 || source > 3) return;

            if (_settingLinked) return;
            _settingLinked = true;

            if (!_mox)
            {
                if (_masterAFLink[source])
                {
                    if (_masterAFLink[0]) AF = value; //master
                    if (_masterAFLink[1]) RX0Gain = value; //rx1
                    if (_masterAFLink[2]) RX1Gain = value; //rx1sub
                    if (_masterAFLink[3]) RX2Gain = value; //rx2
                }
            }

            _settingLinked = false;
        }
        public int RX0Gain
        {
            get
            {
                if (ptbRX0Gain != null) return ptbRX0Gain.Value;
                else return -1;
            }
            set
            {
                if (ptbRX0Gain != null) ptbRX0Gain.Value = value;
                ptbRX0Gain_Scroll(this, EventArgs.Empty);
                if (sliderForm != null)
                    sliderForm.RX1Gain = value;
            }
        }

        public int PanMainRX
        {
            get
            {
                if (ptbPanMainRX != null) return ptbPanMainRX.Value;
                else return -1;
            }
            set
            {
                if (ptbPanMainRX != null) ptbPanMainRX.Value = value;
                ptbPanMainRX_Scroll(this, EventArgs.Empty);
            }
        }

        public int RX1Gain
        {
            get
            {
                if (ptbRX1Gain != null) return ptbRX1Gain.Value;
                else return -1;
            }
            set
            {
                if (ptbRX1Gain != null) ptbRX1Gain.Value = value;
                ptbRX1Gain_Scroll(this, EventArgs.Empty);
            }
        }

        public int PanSubRX
        {
            get
            {
                if (ptbPanSubRX != null) return ptbPanSubRX.Value;
                else return -1;
            }
            set
            {
                if (ptbPanSubRX != null) ptbPanSubRX.Value = value;
                ptbPanSubRX_Scroll(this, EventArgs.Empty);
            }
        }

        public int RX2Gain
        {
            get
            {
                if (ptbRX2Gain != null) return ptbRX2Gain.Value;
                else return -1;
            }
            set
            {
                if (ptbRX2Gain != null) ptbRX2Gain.Value = value;
                ptbRX2Gain_Scroll(this, EventArgs.Empty);
            }
        }

        public int RX2Pan
        {
            get
            {
                if (ptbRX2Pan != null) return ptbRX2Pan.Value;
                else return -1;
            }
            set
            {
                if (ptbRX2Pan != null) ptbRX2Pan.Value = value;
                ptbRX2Pan_Scroll(this, EventArgs.Empty);
            }
        }

        public decimal CATDiversityGain
        {
            get
            {
                if (diversityForm != null)
                    return diversityForm.CATDiversityGain;
                else
                    return 0.0m;
            }
            set
            {
                if (diversityForm != null)
                    diversityForm.CATDiversityGain = value;
            }
        }

        public decimal CATDiversityRX1Gain
        {
            get
            {
                if (diversityForm != null)
                    return diversityForm.DiversityGain;
                else
                    return 0.0m;
            }
            set
            {
                if (diversityForm != null)
                    diversityForm.DiversityGain = value;
            }
        }

        public decimal CATDiversityRX2Gain
        {
            get
            {
                if (diversityForm != null)
                    return diversityForm.DiversityR2Gain;
                else
                    return 0.0m;
            }
            set
            {
                if (diversityForm != null)
                    diversityForm.DiversityR2Gain = value;
            }
        }

        public decimal CATDiversityPhase
        {
            get
            {
                if (diversityForm != null)
                    return diversityForm.DiversityPhase;
                else
                    return 0.0m;
            }
            set
            {
                if (diversityForm != null)
                    diversityForm.DiversityPhase = value;
            }
        }

        public bool CATDiversityEnable
        {
            get
            {
                if (diversityForm != null)
                    return diversityForm.DiversityEnabled;
                else
                    return false;
            }
            set
            {
                if (diversityForm != null)
                    if (value)
                        diversityForm.DiversityEnabled = true;
                    else
                        diversityForm.DiversityEnabled = false;
            }
        }

        public bool CATDiversityRXRefSource             // added G8NJJ
        {
            get
            {
                if (diversityForm != null)
                    return diversityForm.DiversityRXRef;
                else
                    return false;
            }
            set
            {
                if (diversityForm != null)
                    if (value)
                        diversityForm.DiversityRXRef = true;
                    else
                        diversityForm.DiversityRXRef = false;
            }
        }

        public int CATDiversityRXSource             // added G8NJJ
        {
            get
            {
                if (diversityForm != null)
                    return diversityForm.DiversityRXSource;
                else
                    return 0;
            }
            set
            {
                if (diversityForm != null)
                    diversityForm.DiversityRXSource = value;
            }
        }

        public bool CATDiversityForm
        {
            get
            {
                if (diversityForm == null || diversityForm.IsDisposed)
                    return false;
                else
                    return true;
            }
            set
            {
                if (value)
                {
                    if (current_hpsdr_model != HPSDRModel.ANAN100D &&
                        current_hpsdr_model != HPSDRModel.ANAN200D &&
                        current_hpsdr_model != HPSDRModel.ORIONMKII &&
                        current_hpsdr_model != HPSDRModel.ANAN7000D &&
                        current_hpsdr_model != HPSDRModel.ANAN8000D &&
                        current_hpsdr_model != HPSDRModel.ANAN_G2 &&
                        current_hpsdr_model != HPSDRModel.ANAN_G2_1K) return;
                    if (diversityForm == null || diversityForm.IsDisposed)
                        diversityForm = new DiversityForm(this);
                    diversityForm.Focus();
                    this.Invoke(new MethodInvoker(diversityForm.Show));
                }
                else
                    if (diversityForm != null)
                    this.Invoke(new MethodInvoker(diversityForm.Close));
            }
        }

        public bool CATCWXForm
        {
            get
            {
                if (m_frmCWXForm == null || m_frmCWXForm.IsDisposed)
                    return false;
                else
                    return true;
            }
            set
            {
                if (value)
                {
                    cWXToolStripMenuItem_Click(this, EventArgs.Empty);
                }
                else
                {
                    if (m_frmCWXForm != null) m_frmCWXForm.Close();
                }
            }
        }

        public bool VFOATX
        {
            get { return chkVFOATX.Checked; }
            set { chkVFOATX.Checked = value; }
        }

        public bool VFOBTX
        {
            get { return chkVFOBTX.Checked; }
            set { chkVFOBTX.Checked = value; }
        }

        private bool vac2_on_split = true;
        public bool VAC2onSplit
        {
            get { return vac2_on_split; }
            set
            {
                if (vac2_on_split != value)
                {
                    vac2_on_split = value;

                    // so that update to SetTXVAC occurs if needed MW0LGE_21k9d
                    chkVFOBTX_CheckedChanged(this, EventArgs.Empty);
                }
            }

        }

        //private string _db_file_name = "";
        //public string DBFileName
        //{
        //    get { return _db_file_name; }
        //    set
        //    {
        //        if (initializing) // ignore changes here after init is complete per design
        //        {
        //            _db_file_name = value;
        //            DB.FileName = value;
        //        }
        //    }
        //}

        private string _app_data_path = "";
        public string AppDataPath
        {
            get { return _app_data_path; }
            set
            {
                _app_data_path = value;

                // set paths of other components
                DBMan.AppDataPath = value;
                Skin.AppDataPath = value;
                MemoryList.AppDataPath = value;
                DXMemList.AppDataPath = value;
            }
        }

        private bool wheel_tunes_vfob = false;
        public bool WheelTunesVFOB
        {
            get { return wheel_tunes_vfob; }
            set { wheel_tunes_vfob = value; }
        }

        private bool disable_ui_mox_changes = true;
        public bool DisableUIMOXChanges
        {
            get { return disable_ui_mox_changes; }
            set { disable_ui_mox_changes = value; }
        }

        private float rx1_xvtr_gain_offset;						// gain offset as entered on the xvtr form
        public float RX1XVTRGainOffset
        {
            get { return rx1_xvtr_gain_offset; }
            set
            {
                rx1_xvtr_gain_offset = value;
                UpdateRX1DisplayOffsets();
            }
        }

        private float rx2_xvtr_gain_offset;						// gain offset as entered on the xvtr form
        public float RX2XVTRGainOffset
        {
            get { return rx2_xvtr_gain_offset; }
            set
            {
                rx2_xvtr_gain_offset = value;
                UpdateRX2DisplayOffsets();
            }
        }

        private float rx_6m_gain_offset = 13;
        public float RX6mGainOffset
        {
            get { return rx_6m_gain_offset; }
            set
            {
                rx_6m_gain_offset = value;
                if (!IsSetupFormNull)
                    txtVFOAFreq_LostFocus(this, EventArgs.Empty);
            }
        }

        private float rx_6m_gain_offset_rx2 = 13;
        public float RX6mGainOffsetRx2
        {
            get { return rx_6m_gain_offset_rx2; }
            set
            {
                rx_6m_gain_offset_rx2 = value;
                if (!IsSetupFormNull)
                    txtVFOBFreq_LostFocus(this, EventArgs.Empty);
            }
        }

        private float rx1_6m_gain_offset = 0;
        public float RX16mGainOffset
        {
            get { return rx1_6m_gain_offset; }
            set
            {
                rx1_6m_gain_offset = value;
                UpdateRX1DisplayOffsets();
            }
        }

        private float rx2_6m_gain_offset = 0;
        public float RX26mGainOffset
        {
            get { return rx2_6m_gain_offset; }
            set
            {
                rx2_6m_gain_offset = value;
                UpdateRX2DisplayOffsets();
            }
        }

        private bool enable_6m_preamp = false;
        public bool Enable6mPreamp
        {
            get { return enable_6m_preamp; }
            set
            {
                enable_6m_preamp = value;
            }
        }

        private bool meter_detail = false;
        public bool MeterDetail
        {
            get { return meter_detail; }
            set { meter_detail = value; }
        }

        private MeterTXMode tune_meter_tx_mode = MeterTXMode.FORWARD_POWER;
        public MeterTXMode TuneTXMeterMode
        {
            get { return tune_meter_tx_mode; }
            set
            {
                tune_meter_tx_mode = value;
                if (chkTUN.Checked)
                {
                    CurrentMeterTXMode = value;
                    comboMeterTXMode_SelectedIndexChanged(this, EventArgs.Empty);
                }
            }
        }

        public bool NB
        {
            get { return chkNB.Checked; }
            set { chkNB.Checked = value; }
        }

        public bool NB2
        {
            get { return chkDSPNB2.Checked; }
            set { chkDSPNB2.Checked = value; }
        }

        public bool QuickPlay
        {
            get { return ckQuickPlay.Checked; }
            set
            {
                ckQuickPlay.Checked = value;
                UpdateButtonBarButtons();
            }
        }
        public bool QuickRec // DH1KLM
        {
            get { return ckQuickRec.Checked; }
            set
            {
                ckQuickRec.Checked = value;
                UpdateButtonBarButtons();
            }
        }

        public void HighlightTXProfileSaveItems(bool bHighlight)
        {
            Common.HightlightControl(chkDX, bHighlight);
            Common.HightlightControl(chkCPDR, bHighlight);
            Common.HightlightControl(ptbCPDR, bHighlight);
            Common.HightlightControl(ptbMic, bHighlight);
            Common.HightlightControl(ptbFMMic, bHighlight);
            Common.HightlightControl(chkShowTXFilter, bHighlight);
            Common.HightlightControl(chkFWCATUBypass, bHighlight);
            Common.HightlightControl(chkMicMute, bHighlight);
            Common.HightlightControl(udTXFilterLow, bHighlight);
            Common.HightlightControl(udTXFilterHigh, bHighlight);
            Common.HightlightControl(chkVOX, bHighlight);
            Common.HightlightControl(ptbVOX, bHighlight);
            Common.HightlightControl(chkNoiseGate, bHighlight);

            // set via EQ form, consequently included in tx profile
            Common.HightlightControl(chkTXEQ, bHighlight);
            Common.HightlightControl(chkRXEQ, bHighlight);

            //vac buttons
            Common.HightlightControl(chkVAC1, bHighlight);
            Common.HightlightControl(chkVAC2, bHighlight);
        }
        public bool DX
        {
            get { return chkDX.Checked; }
            set { chkDX.Checked = value; }
        }

        public bool CFCEnabled
        {
            get
            {
                return SetupForm.CFCEnabled;
            }
            set
            {
                SetupForm.CFCEnabled = value;
            }
        }

        public bool PhaseRotEnabled
        {
            get
            {
                return SetupForm.PhaseRotEnabled;
            }
            set
            {
                SetupForm.PhaseRotEnabled = value;
            }
        }

        private bool peak_tx_meter = true; // as opposed to avg
        public bool PeakTXMeter
        {
            get { return peak_tx_meter; }
            set { peak_tx_meter = value; }
        }

        private bool _allow_vac_bypass = true;
        public bool AllowVACBypass
        {
            get { return _allow_vac_bypass; }
            set { _allow_vac_bypass = value; }
        }

        private bool allow_space_bypass = false;
        public bool AllowSPACEBypass
        {
            get { return allow_space_bypass; }
            set { allow_space_bypass = value; }
        }

        private bool allow_mox_bypass = false;
        public bool AllowMOXBypass
        {
            get { return allow_mox_bypass; }
            set { allow_mox_bypass = value; }
        }

        private bool _allow_micvox_bypass = false;
        public bool AllowMICVOXBypass
        {
            get { return _allow_micvox_bypass; }
            set { _allow_micvox_bypass = value; }
        }

        public float NewMeterData
        {
            get { return new_meter_data; }
        }

        public float Rx2MeterData
        {
            get { return rx2_meter_new_data; }
        }

        private bool _all_mode_mic_ptt = false;
        public bool AllModeMicPTT
        {
            get { return _all_mode_mic_ptt; }
            set { _all_mode_mic_ptt = value; }
        }

        //private int last_rx1_xvtr_index = -1;			// index of last xvtr in use
        //public int LastRX1XVTRIndex
        //{
        //    get { return last_rx1_xvtr_index; }
        //    set { last_rx1_xvtr_index = value; }
        //}

        //private int last_rx2_xvtr_index = -1;			// index of last xvtr in use
        //public int LastRX2XVTRIndex
        //{
        //    get { return last_rx2_xvtr_index; }
        //    set { last_rx2_xvtr_index = value; }
        //}

        private int rx1_xvtr_index = -1;				// index of current xvtr in use
        public int RX1XVTRIndex
        {
            get { return rx1_xvtr_index; }
            set
            {
                rx1_xvtr_index = value;
                if (value >= 0)
                {
                    lblRX1MuteVFOA.SendToBack();
                    lblRX1APF.SendToBack();
                }
                else
                {
                    lblRX1MuteVFOA.BringToFront();
                    lblRX1APF.BringToFront();
                }

            }
        }
        private int rx2_xvtr_index = -1;				// index of current xvtr in use
        public int RX2XVTRIndex
        {
            get { return rx2_xvtr_index; }
            set
            {
                rx2_xvtr_index = value;
                if (value >= 0)
                {
                    lblRX2MuteVFOB.SendToBack();
                    lblRX2APF.SendToBack();
                }
                else
                {
                    lblRX2MuteVFOB.BringToFront();
                    lblRX2APF.BringToFront();
                }
            }
        }

        private int tx_xvtr_index = -1;				// index of current xvtr in use
        public int TXXVTRIndex
        {
            get { return tx_xvtr_index; }
            set
            {
                int oldValue = tx_xvtr_index;

                tx_xvtr_index = value;

                if (oldValue != tx_xvtr_index) TransverterIndexChangedHandlers?.Invoke(oldValue, tx_xvtr_index); //MW0LGE_[2.9.0.7]
            }
        }

        private int last_tx_xvtr_index = -1;		    // index of last xvtr in use
        public int LastTXXVTRIndex
        {
            get { return last_tx_xvtr_index; }
            set { last_tx_xvtr_index = value; }
        }

        private float rx1_path_offset = 0.0f;
        public float RX1PathOffset
        {
            get { return rx1_path_offset; }
        }

        private float rx2_path_offset = 0.0f;
        public float RX2PathOffset
        {
            get { return rx2_path_offset; }
        }

        private PreampMode[] rx1_preamp_by_band;
        public void SetRX1Preamp(Band b, PreampMode mode)
        {
            rx1_preamp_by_band[(int)b] = mode;
        }

        public PreampMode GetPreamp(Band b)
        {
            return rx1_preamp_by_band[(int)b];
        }

        private PreampMode[] rx2_preamp_by_band;


        private double[] fm_tx_offset_by_band_mhz;

        private int[] power_by_band;
        private int[] tunePower_by_band;
        private int[] limitPower_by_band;
        private int[] limitTunePower_by_band;
        public void SetPower(Band b, int pwr)
        {
            power_by_band[(int)b] = pwr;
            if (tx_band == b) PWR = pwr;
        }

        public int GetPower(Band b)
        {
            return power_by_band[(int)b];
        }

        private AGCMode[] rx1_agcm_by_band;
        private AGCMode[] rx2_agcm_by_band;

        private int[] rx1_agct_by_band;
        private int[] rx2_agct_by_band;

        private bool mouse_tune_step = false;
        public bool MouseTuneStep
        {
            get { return mouse_tune_step; }
            set { mouse_tune_step = value; }
        }

        public bool WheelReverse { get; set; }

        private bool new_power_cal = false;
        public bool NewPowerCal
        {
            get { return new_power_cal; }
            set { new_power_cal = value; }
        }

        public bool ShowCWTXFreq
        {
            get { return chkShowTXCWFreq.Checked; }
            set { chkShowTXCWFreq.Checked = value; }
        }

        public bool ShowTXFilter
        {
            get { return chkShowTXFilter.Checked; }
            set { chkShowTXFilter.Checked = value; }
        }

        private bool zero_beat_rit = false;
        public bool ZeroBeatRIT
        {
            get { return zero_beat_rit; }
            set { zero_beat_rit = value; }
        }

        private bool ritxit_sync = false;
        public bool RITXITSync
        {
            get { return ritxit_sync; }
            set { ritxit_sync = value; }
        }


        //=========================================================
        // ke9ns add for display to check if Beacon needs an freq avg signal strength reading
        public bool BeaconSigAvg
        {
            get
            {
                if (SpotForm != null)
                {
                    if ((SpotForm.beacon5 > 0) || (SpotForm.beacon11 > 0) || (SpotForm.WTime == true)) return true;  // if Fast or Slow Beacon scanning is enabled or WWV checking
                    else return false;
                }
                else return false;

            }


        } //  public bool BeaconSigAvg



        //=============================
        // ke9ns add  scheduler calls this to set audio to POST and 48k SR for small file size recordings
        public bool RECPOST
        {
            set
            {

                if (value == true)
                {
                    WaveForm.RECPLAY = true;                 // this sets recording to POST (not IQ pre) 
                    WaveForm.RECPLAY2 = true;                // and reduces .wav to 48000 SR to save file size

                    WaveForm.checkBoxRecord.Checked = true; // start recording

                }
                else
                {
                    //  WaveForm.RECPLAY3 = true;                // and restores .wav to original SR size
                    WaveForm.checkBoxRecord.Checked = value; // start recording

                }


            }

        }

        public bool RECPOST1
        {
            set
            {
                WaveForm.RECPLAY3 = true;                // and restores .wav to original SR size
            }

        }
        // ke9ns add when schedule recording comes up, turn WAVE RED
        public bool REC1
        {
            set
            {
                if (value == false)
                {
                    waveToolStripMenuItem.ForeColor = SystemColors.ControlLightLight;
                    waveToolStripMenuItem.Text = "Wave";

                }
                else
                {
                    waveToolStripMenuItem.ForeColor = Color.Red;
                    waveToolStripMenuItem.Text = "Record";


                }
            }

        } // REC1

        // ke9ns add when schedule comes up, turn Memory RED
        public bool SCHED1
        {
            set
            {
                if (value == false)
                {

                    memoryToolStripMenuItem.ForeColor = SystemColors.ControlLightLight;
                    memoryToolStripMenuItem.Text = "Memory";
                }
                else
                {

                    memoryToolStripMenuItem.ForeColor = Color.Red;
                    memoryToolStripMenuItem.Text = "Mem Sched";
                }
            }

        } // REC1

        private void UpdateRX1DisplayOffsets()
        {
            if (initializing) return;

            if (rx1_step_att_present)
            {
                Display.RX1PreampOffset = rx1_attenuator_data;
                if (current_hpsdr_model != HPSDRModel.ANAN100D &&
                    current_hpsdr_model != HPSDRModel.ANAN200D &&
                    current_hpsdr_model != HPSDRModel.ORIONMKII &&
                    current_hpsdr_model != HPSDRModel.ANAN7000D &&
                    current_hpsdr_model != HPSDRModel.ANAN8000D &&
                    current_hpsdr_model != HPSDRModel.ANAN_G2 &&
                    current_hpsdr_model != HPSDRModel.ANAN_G2_1K &&
                    !rx2_preamp_present || _mox)
                    Display.RX2PreampOffset = rx1_attenuator_data;
            }
            else
            {
                Display.RX1PreampOffset = rx1_preamp_offset[(int)rx1_preamp_mode];

                if (current_hpsdr_model != HPSDRModel.ANAN100D &&
                    current_hpsdr_model != HPSDRModel.ANAN200D &&
                    current_hpsdr_model != HPSDRModel.ORIONMKII &&
                    current_hpsdr_model != HPSDRModel.ANAN7000D &&
                    current_hpsdr_model != HPSDRModel.ANAN8000D &&
                    current_hpsdr_model != HPSDRModel.ANAN_G2 &&
                    current_hpsdr_model != HPSDRModel.ANAN_G2_1K &&
                    !rx2_preamp_present)
                    Display.RX2PreampOffset = rx1_preamp_offset[(int)rx1_preamp_mode];
            }

            Display.RX1DisplayCalOffset = rx1_display_cal_offset + rx1_xvtr_gain_offset + rx1_6m_gain_offset;
        }

        private void UpdateRX2DisplayOffsets()
        {
            if (initializing) return;

            if (rx2_step_att_present)
            {
                Display.RX2PreampOffset = rx2_attenuator_data;

                if (current_hpsdr_model != HPSDRModel.ANAN100D &&
                    current_hpsdr_model != HPSDRModel.ANAN200D &&
                    current_hpsdr_model != HPSDRModel.ORIONMKII &&
                    current_hpsdr_model != HPSDRModel.ANAN7000D &&
                    current_hpsdr_model != HPSDRModel.ANAN8000D &&
                    current_hpsdr_model != HPSDRModel.ANAN_G2 &&
                    current_hpsdr_model != HPSDRModel.ANAN_G2_1K &&
                    !rx2_preamp_present)
                    Display.RX2PreampOffset = rx1_attenuator_data;
            }
            else
            {
                Display.RX2PreampOffset = rx2_preamp_offset[(int)rx2_preamp_mode];

                if (current_hpsdr_model != HPSDRModel.ANAN100D &&
                    current_hpsdr_model != HPSDRModel.ANAN200D &&
                    current_hpsdr_model != HPSDRModel.ORIONMKII &&
                    current_hpsdr_model != HPSDRModel.ANAN7000D &&
                    current_hpsdr_model != HPSDRModel.ANAN8000D &&
                    current_hpsdr_model != HPSDRModel.ANAN_G2 &&
                    current_hpsdr_model != HPSDRModel.ANAN_G2_1K &&
                    !rx2_preamp_present)
                    Display.RX2PreampOffset = rx1_preamp_offset[(int)rx1_preamp_mode];
            }

            Display.RX2DisplayCalOffset = rx2_display_cal_offset + rx2_xvtr_gain_offset + rx2_6m_gain_offset; //MW0LGE_21k5
        }


        private bool click_tune_drag = false;
        public bool ClickTuneDrag
        {
            get { return click_tune_drag; }
            set { click_tune_drag = value; }
        }

        private bool snap_to_click_tuning = false;
        public bool SnapToClickTuning
        {
            get { return snap_to_click_tuning; }
            set { snap_to_click_tuning = value; }
        }

        private bool click_tune_filter = false;
        public bool ClickTuneFilter
        {
            get { return click_tune_filter; }
            set { click_tune_filter = value; }
        }

        private bool xvtr_tune_power = false;
        public bool XVTRTunePower
        {
            get { return xvtr_tune_power; }
            set { xvtr_tune_power = value; }
        }

        public bool DisableToolTips
        {
            set
            {
                if (toolTip1 != null) toolTip1.Active = !value;
            }
        }

        public bool X2TR
        {
            get
            {
                if (chkX2TR != null) return chkX2TR.Checked;
                else return false;
            }
            set
            {
                if (chkX2TR != null) chkX2TR.Checked = value;
            }
        }

        public string TXProfile
        {
            get
            {
                if (comboTXProfile != null) return comboTXProfile.Text;
                else return "";
            }
            set
            {
                switch (rx1_dsp_mode)
                {
                    case DSPMode.DIGL:
                    case DSPMode.DIGU:
                        if (comboDigTXProfile != null) comboDigTXProfile.Text = value;
                        break;
                    case DSPMode.FM:
                        if (comboFMTXProfile != null) comboFMTXProfile.Text = value;
                        break;
                    case DSPMode.AM:
                    case DSPMode.SAM:
                        if (comboAMTXProfile != null) comboAMTXProfile.Text = value;
                        break;
                    default:
                        if (comboTXProfile != null) comboTXProfile.Text = value;
                        break;
                }
            }
        }

        private string vac_sample_rate = "48000";
        public string VACSampleRate
        {
            get
            {
                return vac_sample_rate;
            }
            set
            {
                vac_sample_rate = value;
                if (comboVACSampleRate != null && !(chkVAC2.Checked && chkVFOBTX.Checked))
                    comboVACSampleRate.Text = value;
            }
        }

        private string vac2_sample_rate = "48000";
        public string VAC2SampleRate
        {
            get
            {
                return vac2_sample_rate;
            }
            set
            {
                vac2_sample_rate = value;
                if (comboVACSampleRate != null && (chkVAC2.Checked && chkVFOBTX.Checked))
                    comboVACSampleRate.Text = value;
            }
        }

        private bool vac_stereo;
        public bool VACStereo
        {
            get
            {
                return vac_stereo;
            }
            set
            {
                vac_stereo = value;
                if (chkVACStereo != null && !(chkVAC2.Checked && chkVFOBTX.Checked))
                    chkVACStereo.Checked = value;
            }
        }

        private bool vac2_stereo;
        public bool VAC2Stereo
        {
            get
            {
                return vac2_stereo;
            }
            set
            {
                vac2_stereo = value;
                if (chkVACStereo != null && (chkVAC2.Checked && chkVFOBTX.Checked))
                    chkVACStereo.Checked = value;
            }
        }

        public bool CWIambic
        {
            get
            {
                if (chkCWIambic != null) return chkCWIambic.Checked;
                else return false;
            }

            set
            {
                if (chkCWIambic != null) chkCWIambic.Checked = value;
            }
        }

        private MultiMeterDisplayMode current_meter_display_mode = MultiMeterDisplayMode.Edge;
        public MultiMeterDisplayMode CurrentMeterDisplayMode
        {
            get { return current_meter_display_mode; }
            set
            {
                switch (current_meter_display_mode)
                {
                    case MultiMeterDisplayMode.Edge:
                        switch (value)
                        {
                            case MultiMeterDisplayMode.Edge:
                                break;
                            default:
                                picMultiMeterDigital.BackColor = meter_background_color;
                                picRX2Meter.BackColor = meter_background_color;
                                break;
                        }
                        break;
                    default:
                        switch (value)
                        {
                            case MultiMeterDisplayMode.Edge:
                                picMultiMeterDigital.BackColor = edge_meter_background_color;
                                picRX2Meter.BackColor = edge_meter_background_color;
                                break;
                        }
                        break;
                }
                current_meter_display_mode = value;

                picMultiMeterDigital.Invalidate();
            }
        }

        public bool VFOSync
        {
            get { return chkVFOSync.Checked; }
            set
            {
                chkVFOSync.Checked = value;
                if (value == true)
                    lblVFOSyncLabel.BackColor = System.Drawing.Color.Blue;
                else
                    lblVFOSyncLabel.BackColor = System.Drawing.Color.Transparent;
            }
        }

        private Color vfo_background_color = Color.Black;
        public Color VFOBackgroundColor
        {
            get { return vfo_background_color; }
            set
            {
                vfo_background_color = value;

                txtVFOAFreq.BackColor = value;
                txtVFOAMSD.BackColor = value;
                txtVFOALSD.BackColor = value;
                txtVFOBFreq.BackColor = value;
                txtVFOBMSD.BackColor = value;
                txtVFOBLSD.BackColor = value;
                panelVFOAHover.BackColor = value;
                panelVFOBHover.BackColor = value;
                lblFilterLabel.BackColor = value;
                lblModeLabel.BackColor = value;
                lblModeBigLabel.BackColor = value;
                lblRX2ModeBigLabel.BackColor = value; //[2.10.1.0]MW0LGE ty WD5Y

                //MW0LGE_21d
                lblRX1MuteVFOA.BackColor = value;
                lblRX2MuteVFOB.BackColor = value;
                lblRX2ModeLabel.BackColor = value;
                lblRX1APF.BackColor = value;
                lblRX2APF.BackColor = value;
                //MW0LGE_21f
                lblRX2FilterLabel.BackColor = value;
            }
        }

        private Color meter_digital_text_color = Color.Yellow;
        public Color MeterDigitalTextColor
        {
            get { return meter_digital_text_color; }
            set
            {
                meter_digital_text_color = value;
                txtMultiText.ForeColor = value;
                txtRX2Meter.ForeColor = value;
            }
        }

        private Color meter_digital_background_color = Color.Black;
        public Color MeterDigitalBackgroundColor
        {
            get { return meter_digital_background_color; }
            set
            {
                meter_digital_background_color = value;
                txtMultiText.BackColor = value;
                txtRX2Meter.BackColor = value;
            }
        }

        private Color band_background_color = Color.Black;
        public Color BandBackgroundColor
        {
            get { return band_background_color; }
            set
            {
                band_background_color = value;
                txtVFOABand.BackColor = value;
                txtVFOBBand.BackColor = value;
            }
        }

        private Color edge_meter_background_color = Color.Black;
        private Pen edge_meter_background_pen = new Pen(Color.Black);
        public Color EdgeMeterBackgroundColor
        {
            get { return edge_meter_background_color; }
            set
            {
                edge_meter_background_color = value;
                edge_meter_background_pen.Color = edge_meter_background_color;
                if (current_meter_display_mode == MultiMeterDisplayMode.Edge)
                {
                    picMultiMeterDigital.BackColor = value;
                    picMultiMeterDigital.Invalidate();
                    picRX2Meter.BackColor = value;
                    if (chkRX2.Checked)
                        picRX2Meter.Invalidate();
                }
            }
        }
        private SolidBrush low_brush = new SolidBrush(Color.White);
        private Color edge_low_color = Color.White;
        public Color EdgeLowColor
        {
            get { return edge_low_color; }
            set
            {
                edge_low_color = value;
                low_brush.Color = edge_low_color;
                if (current_meter_display_mode == MultiMeterDisplayMode.Edge)
                {
                    picMultiMeterDigital.Invalidate();
                    if (chkRX2.Checked)
                        picRX2Meter.Invalidate();
                }
            }
        }
        private SolidBrush high_brush = new SolidBrush(Color.Red);
        private Color edge_high_color = Color.Red;
        public Color EdgeHighColor
        {
            get { return edge_high_color; }
            set
            {
                edge_high_color = value;
                high_brush.Color = edge_high_color;
                if (current_meter_display_mode == MultiMeterDisplayMode.Edge)
                {
                    picMultiMeterDigital.Invalidate();
                    if (chkRX2.Checked)
                        picRX2Meter.Invalidate();
                }
            }
        }


        private Pen line_pen = new Pen(Color.Yellow);
        private Pen line_dark_pen = new Pen(Color.Yellow);
        private Color edge_avg_color = Color.Yellow;
        public Color EdgeAVGColor
        {
            get { return edge_avg_color; }
            set
            {
                edge_avg_color = value;
                line_pen.Color = edge_avg_color;
                if (current_meter_display_mode == MultiMeterDisplayMode.Edge)
                    picMultiMeterDigital.Invalidate();
            }
        }

        private Pen meter_background_pen = new Pen(Color.Black);
        private Color meter_background_color = Color.Black;
        public Color MeterBackgroundColor
        {
            get { return meter_background_color; }
            set
            {
                meter_background_color = value;
                meter_background_pen.Color = meter_background_color;
                if (current_meter_display_mode == MultiMeterDisplayMode.Original)
                {
                    picMultiMeterDigital.BackColor = value;
                    picMultiMeterDigital.Invalidate();
                }
            }
        }

        private Color peak_background_color = Color.Black;
        public Color PeakBackgroundColor
        {
            get { return peak_background_color; }
            set
            {
                peak_background_color = value;
                infoBar.BackColor = peak_background_color;
            }
        }

        private bool small_lsd = true;
        public bool SmallLSD
        {
            get { return small_lsd; }
            set
            {
                small_lsd = value;
                txtVFOALSD.Visible = value;
                txtVFOAMSD.Visible = value;
                txtVFOBLSD.Visible = value;
                txtVFOBMSD.Visible = value;
            }
        }

        private Color small_vfo_color = Color.OrangeRed;
        public Color SmallVFOColor
        {
            get { return small_vfo_color; }
            set
            {
                small_vfo_color = value;
                if (small_lsd && chkPower.Checked)
                {
                    txtVFOALSD.ForeColor = small_vfo_color;
                    if (chkVFOSplit.Checked)
                        txtVFOBLSD.ForeColor = small_vfo_color;
                }
            }
        }

        //============================================================
        // ke9ns add
        private Color ring_vfo_color = Color.DarkGreen;
        public Color RingVFOColor
        {
            get { return ring_vfo_color; }
            set
            {
                ring_vfo_color = value;
                grpVFOA.Invalidate();
                grpVFOB.Invalidate();
                grpMultimeter.Invalidate();
                grpRX2Meter.Invalidate();

            }

        } //RingVFOColor

        private Color info_buttons_color = Color.DarkOrange;
        public Color InfoButtonsColor
        {
            get { return info_buttons_color; }
            set
            {
                info_buttons_color = value;

                lblModeLabel.ForeColor = value;
                lblModeBigLabel.ForeColor = value;
                lblRX2ModeBigLabel.ForeColor = value;//[2.10.1.0]MW0LGE ty WD5Y
                lblFilterLabel.ForeColor = value;
                lblAttenLabel.ForeColor = value;
                lblAGCLabel.ForeColor = value;
                lblNRLabel.ForeColor = value;
                lblNBLabel.ForeColor = value;
                lblSNBLabel.ForeColor = value;
                lblANFLabel.ForeColor = value;
                //MW0LGE_21f
                lblRX1MuteVFOA.ForeColor = value;
                lblRX2MuteVFOB.ForeColor = value;
                lblRX2ModeLabel.ForeColor = value;
                lblRX2FilterLabel.ForeColor = value;
                //MW0LGE_22b
                lblRX2AttenLabel.ForeColor = value;
            }
        }

        private int default_low_cut = 150;
        public int DefaultLowCut
        {
            get { return default_low_cut; }
            set
            {
                for (DSPMode m = DSPMode.FIRST + 1; m < DSPMode.LAST; m++)
                {
                    for (Filter f = Filter.FIRST + 1; f < Filter.LAST; f++)
                    {
                        int low = rx1_filters[(int)m].GetLow(f);
                        int high = rx1_filters[(int)m].GetHigh(f);

                        switch (m)
                        {
                            case DSPMode.USB:
                                if (low == default_low_cut)
                                    rx1_filters[(int)m].SetLow(f, value);
                                break;
                            case DSPMode.LSB:
                                if (high == -default_low_cut)
                                    rx1_filters[(int)m].SetHigh(f, -value);
                                break;
                        }
                    }
                }
                default_low_cut = value;
                RX1Filter = rx1_filter;
            }
        }

        private int default_rx2_low_cut = 150;
        public int DefaultRX2LowCut
        {
            get { return default_rx2_low_cut; }
            set
            {
                for (DSPMode m = DSPMode.FIRST + 1; m < DSPMode.LAST; m++)
                {
                    for (Filter f = Filter.FIRST + 1; f < Filter.LAST; f++)
                    {
                        int low = rx2_filters[(int)m].GetLow(f);
                        int high = rx2_filters[(int)m].GetHigh(f);

                        switch (m)
                        {
                            case DSPMode.USB:
                                if (low == default_rx2_low_cut)
                                    rx2_filters[(int)m].SetLow(f, value);
                                break;
                            case DSPMode.LSB:
                                if (high == -default_rx2_low_cut)
                                    rx2_filters[(int)m].SetHigh(f, -value);
                                break;
                        }
                    }
                }
                default_rx2_low_cut = value;
                RX2Filter = rx2_filter;
            }
        }

        //[2.10.3.6]MW0LGE who codes this junk. check for null, but dont bother looking in ptbCPDR_Scroll to see if it is done
        //commenting as a dupe of existing code
        //public int CPDRVal
        //{
        //    get
        //    {
        //        if (ptbCPDR != null) return ptbCPDR.Value;
        //        else return -1;
        //    }
        //    set
        //    {
        //        if (ptbCPDR != null) ptbCPDR.Value = value;
        //        ptbCPDR_Scroll(this, EventArgs.Empty);
        //    }
        //}

        public int NoiseGate
        {
            get
            {
                if (ptbNoiseGate != null) return ptbNoiseGate.Value;
                else return -1;
            }
            set
            {
                if (ptbNoiseGate != null)
                {
                    if (value > ptbNoiseGate.Maximum) value = ptbNoiseGate.Maximum;
                    ptbNoiseGate.Value = value;
                    ptbNoiseGate_Scroll(this, EventArgs.Empty);
                }
            }
        }

        public int VOXSens
        {
            get
            {
                if (ptbVOX != null) return ptbVOX.Value;
                else return -1;
            }
            set
            {
                if (ptbVOX != null)
                {
                    ptbVOX.Value = value;
                    ptbVOX_Scroll(this, EventArgs.Empty);
                }
            }
        }
        // added G8NJJ to allow scaling of VOX gain CAT command to Thetis range which is typ -80 to 0, not 0 to 1000
        public int VOXSensExtent
        {
            get
            {
                if (ptbVOX != null) return (ptbVOX.Maximum - ptbVOX.Minimum);
                else return -1;
            }
        }
        public int VOXSensMin
        {
            get
            {
                if (ptbVOX != null) return ptbVOX.Minimum;
                else return -1;
            }
        }

        public bool NoiseGateEnabled
        {
            get
            {
                if (chkNoiseGate != null) return chkNoiseGate.Checked;
                else return false;
            }
            set
            {
                if (chkNoiseGate != null) chkNoiseGate.Checked = value;
            }
        }

        private int vac_rx_gain;
        public int VACRXGain
        {
            get
            {
                return vac_rx_gain;
            }
            set
            {
                vac_rx_gain = value;
                if (ptbVACRXGain != null && !(chkVAC2.Checked || chkVFOBTX.Checked))
                {
                    ptbVACRXGain.Value = value;
                    ptbVACRXGain_Scroll(this, EventArgs.Empty);
                }
            }
        }

        private int vac2_rx_gain;
        public int VAC2RXGain
        {
            get
            {
                return vac2_rx_gain;
            }
            set
            {
                vac2_rx_gain = value;
                if (ptbVACRXGain != null && (chkVAC2.Checked && chkVFOBTX.Checked))
                {
                    ptbVACRXGain.Value = value;
                    ptbVACRXGain_Scroll(this, EventArgs.Empty);
                }
            }
        }

        private int vac_tx_gain;
        public int VACTXGain
        {
            get
            {
                return vac_tx_gain;
            }
            set
            {
                vac_tx_gain = value;
                if (ptbVACTXGain != null && !(chkVAC2.Checked || chkVFOBTX.Checked))
                {
                    ptbVACTXGain.Value = value;
                    ptbVACTXGain_Scroll(this, EventArgs.Empty);
                }
            }
        }

        private int vac2_tx_gain;
        public int VAC2TXGain
        {
            get
            {
                return vac2_tx_gain;
            }
            set
            {
                vac2_tx_gain = value;
                if (ptbVACTXGain != null && (chkVAC2.Checked && chkVFOBTX.Checked))
                {
                    ptbVACTXGain.Value = value;
                    ptbVACTXGain_Scroll(this, EventArgs.Empty);
                }
            }
        }

        // These class vars save non-QSK settings so they don't have to be made persistent separately from how they're normally handled, 
        // and so that going in/out of QSK mode doesn't modify a user's normal settings when not in a CW mode.
        private int qsk_sidetone_volume = 50;
        private AGCMode non_qsk_agc = AGCMode.MED;
        private int non_qsk_agc_hang_thresh = 1;
        private bool non_qsk_ATTOnTX = false;
        private int non_qsk_ATTOnTXVal = 0;
        private double non_qsk_breakin_delay = 100;
        private bool qsk_in_CW = false;
        private bool qsk_band_changing = false;

        private bool qsk_enabled = false;
        public bool QSKEnabled  // QSK - a.k.a. full-break-in - Possible with Protocol-2 v1.7 or later  -W2PA
        {
            get
            {
                return qsk_enabled;
            }
            set
            {
                if (IsSetupFormNull || qsk_band_changing) return;  // Postpone until band change is completed, else things get messy.  See SetBand()
                if (qsk_enabled == value) return;

                qsk_enabled = value;

                if (qsk_enabled)
                {
                    // Save non-QSK settings
                    non_qsk_agc = RX1AGCMode;
                    non_qsk_agc_hang_thresh = SetupForm.AGCRX1HangThreshold;//SetupForm.AGCHangThreshold; //MW0LGE_21k8
                    non_qsk_ATTOnTX = ATTOnTX;
                    non_qsk_ATTOnTXVal = SetupForm.ATTOnTX;
                    non_qsk_breakin_delay = break_in_delay;

                    // Apply QSK settings.      
                    RX1AGCMode = AGCMode.CUSTOM;  // Use AGC Custom mode for optimal QSK settings                   

                    if (SetupForm.AGCRX1HangThreshold < 70) SetupForm.AGCRX1HangThreshold = 100;

                    ATTOnTX = true;         // Enable attenuation on transmit via the setting
                    SetupForm.ATTOnTX = 31; // W2PA_21a                 
                    BreakInDelay = 0;       // Set break-in delay to zero in case it's something else                    
                }
                else // Disable
                {
                    // Retrieve saved non-QSK settings
                    RX1AGCMode = non_qsk_agc;

                    SetupForm.AGCRX1HangThreshold = non_qsk_agc_hang_thresh;

                    ATTOnTX = non_qsk_ATTOnTX;
                    SetupForm.ATTOnTX = non_qsk_ATTOnTXVal;
                    BreakInDelay = non_qsk_breakin_delay;
                }

                setCWSideToneVolume();
            }
        }
        private void setCWSideToneVolume()
        {
            //[2.10.3.6]MW0LGE changed to one location as code was everywhere previously
            if (cw_sidetone)
            {
                if (qsk_enabled)
                {
                    NetworkIO.SetCWSidetoneVolume((int)(qsk_sidetone_volume * 1.27));
                }
                else
                {
                    if (current_breakin_mode == BreakIn.Manual)
                    {
                        NetworkIO.SetCWSidetoneVolume((int)(txaf * 0.73));
                    }
                    else
                    {
                        NetworkIO.SetCWSidetoneVolume((int)(txaf * 1.27));
                    }
                }
            }
            else
            {
                NetworkIO.SetCWSidetoneVolume(0);
            }
        }
        public CheckState BreakInEnabledState
        {
            get
            {
                return chkQSK.CheckState;
            }
            set
            {
                chkQSK.CheckState = value;
            }
        }

        private bool non_CW_mode_breakin_disabled = false;
        public bool NonCWModeBreakInDisabled
        // Disable break-in temporarily. Used with QSK-enabled firmware (version 1.7 or later).
        // Necessary so that hitting the key won't transmit when in a non-CW mode.
        {
            get
            {
                return non_CW_mode_breakin_disabled;
            }
            set
            {
                if (value)  // disable it if enabled
                {
                    if (BreakInEnabledState != CheckState.Unchecked)
                    {
                        non_CW_mode_breakin_disabled = true;    // take note of disabling so it can be undone
                    }
                    else non_CW_mode_breakin_disabled = false;  // don't need to disable, was already disabled
                }
                else  // re-enable it if it had been disabled
                if (non_CW_mode_breakin_disabled)
                {
                    non_CW_mode_breakin_disabled = false;
                }
            }
        }


        public bool APFEnabled
        {
            get
            {
                if (chkCWAPFEnabled != null) return chkCWAPFEnabled.Checked;
                else return false;
            }
            set
            {
                if (chkCWAPFEnabled != null) chkCWAPFEnabled.Checked = value;
            }
        }

        public bool VOXEnable
        {
            get
            {
                if (chkVOX != null) return chkVOX.Checked;
                else return false;
            }
            set
            {
                if (chkVOX != null) chkVOX.Checked = value;
            }
        }

        public int RF
        {
            get
            {
                if (ptbRF != null) return ptbRF.Value;
                else return -1;
            }
            set
            {
                if (ptbRF != null)
                {
                    ptbRF.Value = value;
                    ptbRF_Scroll(this, EventArgs.Empty);
                }
            }
        }

        public int RX2RF
        {
            get
            {
                if (ptbRX2RF != null) return ptbRX2RF.Value;
                else return -1;
            }
            set
            {
                if (ptbRX2RF != null)
                {
                    ptbRX2RF.Value = value;
                    ptbRX2RF_Scroll(this, EventArgs.Empty);
                }
            }
        }

        private bool enable_kb_shortcuts = false;
        public bool EnableKBShortcuts
        {
            get { return enable_kb_shortcuts; }
            set
            {
                enable_kb_shortcuts = value;
            }
        }

        private bool save_filter_changes = true;
        public bool SaveFilterChanges
        {
            get { return save_filter_changes; }
            set { save_filter_changes = value; }
        }

        private int max_filter_shift = 9999;
        public int MaxFilterShift
        {
            get { return max_filter_shift; }
            set
            {
                max_filter_shift = value;
                UpdateRX1Filters(radio.GetDSPRX(0, 0).RXFilterLow, radio.GetDSPRX(0, 0).RXFilterHigh);
            }
        }

        private int max_filter_width = 9999;
        public int MaxFilterWidth
        {
            get { return max_filter_width; }
            set
            {
                max_filter_width = value;
                UpdateRX1Filters(radio.GetDSPRX(0, 0).RXFilterLow, radio.GetDSPRX(0, 0).RXFilterHigh);
            }
        }

        private bool line_in = false;
        public bool LineIn
        {
            get { return line_in; }
            set
            {
                line_in = value;
                ptbMic_Scroll(this, EventArgs.Empty);
                SetMicGain();
            }
        }

        private double line_in_boost = 0.0;
        public double LineInBoost
        {
            get { return line_in_boost; }
            set
            {
                line_in_boost = value;
                ptbMic_Scroll(this, EventArgs.Empty);
                SetMicGain();
            }
        }

        private bool mic_boost = true;
        public bool MicBoost
        {
            get { return mic_boost; }
            set
            {
                mic_boost = value;
                ptbMic_Scroll(this, EventArgs.Empty);
                SetMicGain();
            }
        }

        private bool mic_xlr = true;
        public bool MicXlr
        {
            get { return mic_xlr; }
            set
            {
                mic_xlr = value;
                ptbMic_Scroll(this, EventArgs.Empty);
                SetMicXlr();
            }
        }

        private bool always_on_top = false;
        public bool AlwaysOnTop
        {
            get { return always_on_top; }
            set
            {
                always_on_top = value;
                if (value)
                {
                    Win32.SetWindowPos(this.Handle.ToInt32(),
                        -1, this.Left, this.Top, this.Width, this.Height, 0);
                }
                else
                {
                    Win32.SetWindowPos(this.Handle.ToInt32(),
                        -2, this.Left, this.Top, this.Width, this.Height, 0);
                }
            }
        }

        private bool quick_qsy = false;
        public bool QuickQSY
        {
            get { return quick_qsy; }
            set { quick_qsy = value; }
        }

        private ColorSheme color_palette = ColorSheme.enhanced;
        public ColorSheme color_sheme
        {
            get { return color_palette; }

            set
            {
                Display.ColorSheme = value;
                color_palette = value;
            }
        }

        private ColorSheme rx2_color_palette = ColorSheme.enhanced;
        public ColorSheme rx2_color_sheme
        {
            get { return rx2_color_palette; }

            set
            {
                Display.RX2ColorSheme = value;
                rx2_color_palette = value;
            }
        }

        public SIOListenerII Siolisten { get; set; } = null;
        public SIO2ListenerII Sio2listen { get; set; } = null;
        public SIO3ListenerII Sio3listen { get; set; } = null;
        public SIO4ListenerII Sio4listen { get; set; } = null;
        public SIO5ListenerII AndromedaSiolisten { get; set; } = null;
        public SIO6ListenerII AriesSiolisten { get; set; } = null;
        public SIO7ListenerII GanymedeSiolisten { get; set; } = null;

        public bool HideTuneStep
        {
            get { return txtWheelTune.Visible; }
            set
            {
                if (!IsSetupFormNull)
                    txtWheelTune.Visible = value;
            }
        }

        // G8NJJ: return the set of strings in the combo box
        public ComboBox.ObjectCollection DisplayModeItems
        {
            get { return comboDisplayMode.Items; }
        }


        public string DisplayModeText
        {
            get { return comboDisplayMode.Text; }
            set
            {
                comboDisplayMode.Text = value;
                UpdateButtonBarButtons();
            }
        }


        // G8NJJ: return the set of strings in the combo box
        public ComboBox.ObjectCollection DisplayRX2ModeItems
        {
            get { return comboRX2DisplayMode.Items; }
        }

        // added G8NJJ
        public string DisplayRX2ModeText
        {
            get { return comboRX2DisplayMode.Text; }
            set
            {
                comboRX2DisplayMode.Text = value;
                UpdateButtonBarButtons();
            }
        }

        private float multimeter_avg_mult_old = 1 - (float)1 / 10;
        private float multimeter_avg_mult_new = (float)1 / 10;
        private int multimeter_avg_num_blocks = 10;
        public int MultiMeterAvgBlocks
        {
            get { return multimeter_avg_num_blocks; }
            set
            {
                multimeter_avg_num_blocks = value;
                multimeter_avg_mult_old = 1 - (float)1 / multimeter_avg_num_blocks;
                multimeter_avg_mult_new = (float)1 / multimeter_avg_num_blocks;
            }
        }

        private bool vac_auto_enable = false;
        public bool VACAutoEnable
        {
            get { return vac_auto_enable; }
            set
            {
                vac_auto_enable = value;
                if (IsSetupFormNull) return;
                if (vac_auto_enable)
                {
                    switch (rx1_dsp_mode)
                    {
                        case DSPMode.DIGL:
                        case DSPMode.DIGU:
                        case DSPMode.DRM:
                            SetupForm.VACEnable = true;
                            break;
                        default:
                            SetupForm.VACEnable = false;
                            break;
                    }
                }
                else SetupForm.VACEnable = false;
            }
        }

        private bool vac2_auto_enable = false;
        public bool VAC2AutoEnable
        {
            get { return vac2_auto_enable; }
            set
            {
                vac2_auto_enable = value;
                if (IsSetupFormNull) return;
                if (vac2_auto_enable)
                {
                    DSPMode dsp_mode = rx1_dsp_mode;
                    if (vac2_rx2) dsp_mode = rx2_dsp_mode;

                    switch (dsp_mode)
                    {
                        case DSPMode.DIGL:
                        case DSPMode.DIGU:
                        case DSPMode.DRM:
                            SetupForm.VAC2Enable = true;
                            break;
                        default:
                            SetupForm.VAC2Enable = false;
                            break;
                    }
                }
                else SetupForm.VAC2Enable = false;
            }
        }

        private bool vac2_rx2 = true;
        public bool VAC2RX2
        {
            get { return vac2_rx2; }
            set
            {
                vac2_rx2 = value;
                if (IsSetupFormNull) return;
                if (vac2_auto_enable)
                {
                    DSPMode dsp_mode = rx1_dsp_mode;
                    if (vac2_rx2) dsp_mode = rx2_dsp_mode;

                    switch (dsp_mode)
                    {
                        case DSPMode.DIGL:
                        case DSPMode.DIGU:
                        case DSPMode.DRM:
                            SetupForm.VAC2Enable = true;
                            break;
                        default:
                            SetupForm.VAC2Enable = false;
                            break;
                    }
                }
            }
        }

        private float rx1_display_cal_offset;					// display calibration offset per volume setting in dB
        public float RX1DisplayCalOffset
        {
            get { return rx1_display_cal_offset; }
            set
            {
                rx1_display_cal_offset = value;
            }
        }

        private float rx2_display_cal_offset;					// display calibration offset per volume setting in dB
        public float RX2DisplayCalOffset
        {
            get { return rx2_display_cal_offset; }
            set
            {
                rx2_display_cal_offset = value;
            }
        }

        private int display_cursor_x;						// x-coord of the cursor when over the display
        public int DisplayCursorX
        {
            get { return display_cursor_x; }
            set
            {
                display_cursor_x = value;
                Display.DisplayCursorX = value;
            }
        }

        private int display_cursor_y;						// y-coord of the cursor when over the display
        public int DisplayCursorY
        {
            get { return display_cursor_y; }
            set
            {
                display_cursor_y = value;
                Display.DisplayCursorY = value;
            }
        }

        private ClickTuneMode current_click_tune_mode = ClickTuneMode.Off;
        public ClickTuneMode CurrentClickTuneMode
        {
            get { return current_click_tune_mode; }
            set
            {
                current_click_tune_mode = value;
                Display.CurrentClickTuneMode = value;
            }
        }

        private double freq_center = 0.0;
        public double Freq_Center
        {
            get { return freq_center; }
            set { freq_center = value; }
        }

        //MW0LGE_21k9
        public void SetupDisplayEngine(bool resizeN1MM = true)
        {
            _pause_DisplayThread = true;

            Display.Target = picDisplay;

            if (resizeN1MM)
            {
                //MW0LGE_21d N1MM
                N1MM.Resize(1);
                if (RX2Enabled) N1MM.Resize(2);
            }

            //MW0LGE_21h
            updateBandstackOverlay(1);

            //these two calls are neeed because when decimation is changed, WDSP needs to be
            //forced to re-do things like spectrum, histogram
            comboDisplayMode_SelectedIndexChanged(this, EventArgs.Empty);
            if (rx2_enabled) comboRX2DisplayMode_SelectedIndexChanged(this, EventArgs.Empty);

            _pause_DisplayThread = false;
        }

        private bool diversity_rx_ref;
        public bool DiversityRXRef
        {
            get
            {
                return diversity_rx1_ref_by_band[(int)rx1_band];
            }
            set
            {
                if (!initializing)
                {
                    diversity_rx_ref = value;
                    diversity_rx1_ref_by_band[(int)rx1_band] = value;
                }
            }
        }

        //[2.10,3.5]MW0LGE the following is an insane implementation, has no one ever heard of arrays?
        private decimal diversity_gain_160m = 1.0M;
        public decimal DiversityGain160m
        {
            get { return diversity_gain_160m; }
            set { diversity_gain_160m = value; }
        }

        private decimal diversity_gain_80m = 1.0M;
        public decimal DiversityGain80m
        {
            get { return diversity_gain_80m; }
            set { diversity_gain_80m = value; }
        }

        private decimal diversity_gain_60m = 1.0M;
        public decimal DiversityGain60m
        {
            get { return diversity_gain_60m; }
            set { diversity_gain_60m = value; }
        }

        private decimal diversity_gain_40m = 1.0M;
        public decimal DiversityGain40m
        {
            get { return diversity_gain_40m; }
            set { diversity_gain_40m = value; }
        }

        private decimal diversity_gain_30m = 1.0M;
        public decimal DiversityGain30m
        {
            get { return diversity_gain_30m; }
            set { diversity_gain_30m = value; }
        }

        private decimal diversity_gain_20m = 1.0M;
        public decimal DiversityGain20m
        {
            get { return diversity_gain_20m; }
            set { diversity_gain_20m = value; }
        }

        private decimal diversity_gain_17m = 1.0M;
        public decimal DiversityGain17m
        {
            get { return diversity_gain_17m; }
            set { diversity_gain_17m = value; }
        }

        private decimal diversity_gain_15m = 1.0M;
        public decimal DiversityGain15m
        {
            get { return diversity_gain_15m; }
            set { diversity_gain_15m = value; }
        }

        private decimal diversity_gain_12m = 1.0M;
        public decimal DiversityGain12m
        {
            get { return diversity_gain_12m; }
            set { diversity_gain_12m = value; }
        }

        private decimal diversity_gain_10m = 1.0M;
        public decimal DiversityGain10m
        {
            get { return diversity_gain_10m; }
            set { diversity_gain_10m = value; }
        }

        private decimal diversity_gain_6m = 1.0M;
        public decimal DiversityGain6m
        {
            get { return diversity_gain_6m; }
            set { diversity_gain_6m = value; }
        }

        private decimal diversity_gain_wwv = 1.0M;
        public decimal DiversityGainWWV
        {
            get { return diversity_gain_wwv; }
            set { diversity_gain_wwv = value; }
        }

        private decimal diversity_gain_gen = 1.0M;
        public decimal DiversityGainGEN
        {
            get { return diversity_gain_gen; }
            set { diversity_gain_gen = value; }
        }

        private decimal diversity_gain_xvtr = 1.0M;
        public decimal DiversityGainXVTR
        {
            get { return diversity_gain_xvtr; }
            set { diversity_gain_xvtr = value; }
        }

        private decimal diversity_gain_r2_160m = 1.0M;
        public decimal DiversityR2Gain160m
        {
            get { return diversity_gain_r2_160m; }
            set { diversity_gain_r2_160m = value; }
        }

        private decimal diversity_gain_r2_80m = 1.0M;
        public decimal DiversityR2Gain80m
        {
            get { return diversity_gain_r2_80m; }
            set { diversity_gain_r2_80m = value; }
        }

        private decimal diversity_gain_r2_60m = 1.0M;
        public decimal DiversityR2Gain60m
        {
            get { return diversity_gain_r2_60m; }
            set { diversity_gain_r2_60m = value; }
        }

        private decimal diversity_gain_r2_40m = 1.0M;
        public decimal DiversityR2Gain40m
        {
            get { return diversity_gain_r2_40m; }
            set { diversity_gain_r2_40m = value; }
        }

        private decimal diversity_gain_r2_30m = 1.0M;
        public decimal DiversityR2Gain30m
        {
            get { return diversity_gain_r2_30m; }
            set { diversity_gain_r2_30m = value; }
        }

        private decimal diversity_gain_r2_20m = 1.0M;
        public decimal DiversityR2Gain20m
        {
            get { return diversity_gain_r2_20m; }
            set { diversity_gain_r2_20m = value; }
        }

        private decimal diversity_gain_r2_17m = 1.0M;
        public decimal DiversityR2Gain17m
        {
            get { return diversity_gain_r2_17m; }
            set { diversity_gain_r2_17m = value; }
        }

        private decimal diversity_gain_r2_15m = 1.0M;
        public decimal DiversityR2Gain15m
        {
            get { return diversity_gain_r2_15m; }
            set { diversity_gain_r2_15m = value; }
        }

        private decimal diversity_gain_r2_12m = 1.0M;
        public decimal DiversityR2Gain12m
        {
            get { return diversity_gain_r2_12m; }
            set { diversity_gain_r2_12m = value; }
        }

        private decimal diversity_gain_r2_10m = 1.0M;
        public decimal DiversityR2Gain10m
        {
            get { return diversity_gain_r2_10m; }
            set { diversity_gain_r2_10m = value; }
        }

        private decimal diversity_gain_r2_6m = 1.0M;
        public decimal DiversityR2Gain6m
        {
            get { return diversity_gain_r2_6m; }
            set { diversity_gain_r2_6m = value; }
        }

        private decimal diversity_gain_r2_wwv = 1.0M;
        public decimal DiversityR2GainWWV
        {
            get { return diversity_gain_r2_wwv; }
            set { diversity_gain_r2_wwv = value; }
        }

        private decimal diversity_gain_r2_gen = 1.0M;
        public decimal DiversityR2GainGEN
        {
            get { return diversity_gain_r2_gen; }
            set { diversity_gain_r2_gen = value; }
        }

        private decimal diversity_gain_r2_xvtr = 1.0M;
        public decimal DiversityR2GainXVTR
        {
            get { return diversity_gain_r2_xvtr; }
            set { diversity_gain_r2_xvtr = value; }
        }

        private decimal diversity_phase_160m = 0.0M;
        public decimal DiversityPhase160m
        {
            get { return diversity_phase_160m; }
            set { diversity_phase_160m = value; }
        }

        private decimal diversity_phase_80m = 0.0M;
        public decimal DiversityPhase80m
        {
            get { return diversity_phase_80m; }
            set { diversity_phase_80m = value; }
        }

        private decimal diversity_phase_60m = 0.0M;
        public decimal DiversityPhase60m
        {
            get { return diversity_phase_60m; }
            set { diversity_phase_60m = value; }
        }

        private decimal diversity_phase_40m = 0.0M;
        public decimal DiversityPhase40m
        {
            get { return diversity_phase_40m; }
            set { diversity_phase_40m = value; }
        }

        private decimal diversity_phase_30m = 0.0M;
        public decimal DiversityPhase30m
        {
            get { return diversity_phase_30m; }
            set { diversity_phase_30m = value; }
        }

        private decimal diversity_phase_20m = 0.0M;
        public decimal DiversityPhase20m
        {
            get { return diversity_phase_20m; }
            set { diversity_phase_20m = value; }
        }

        private decimal diversity_phase_17m = 0.0M;
        public decimal DiversityPhase17m
        {
            get { return diversity_phase_17m; }
            set { diversity_phase_17m = value; }
        }

        private decimal diversity_phase_15m = 0.0M;
        public decimal DiversityPhase15m
        {
            get { return diversity_phase_15m; }
            set { diversity_phase_15m = value; }
        }

        private decimal diversity_phase_12m = 0.0M;
        public decimal DiversityPhase12m
        {
            get { return diversity_phase_12m; }
            set { diversity_phase_12m = value; }
        }

        private decimal diversity_phase_10m = 0.0M;
        public decimal DiversityPhase10m
        {
            get { return diversity_phase_10m; }
            set { diversity_phase_10m = value; }
        }

        private decimal diversity_phase_6m = 0.0M;
        public decimal DiversityPhase6m
        {
            get { return diversity_phase_6m; }
            set { diversity_phase_6m = value; }
        }

        private decimal diversity_phase_wwv = 0.0M;
        public decimal DiversityPhaseWWV
        {
            get { return diversity_phase_wwv; }
            set { diversity_phase_wwv = value; }
        }

        private decimal diversity_phase_gen = 0.0M;
        public decimal DiversityPhaseGEN
        {
            get { return diversity_phase_gen; }
            set { diversity_phase_gen = value; }
        }

        private decimal diversity_phase_xvtr = 0.0M;
        public decimal DiversityPhaseXVTR
        {
            get { return diversity_phase_xvtr; }
            set { diversity_phase_xvtr = value; }
        }

        private float waterfall_high_threshold_160m = -80.0F;
        public float WaterfallHighThreshold160m
        {
            get { return waterfall_high_threshold_160m; }
            set { waterfall_high_threshold_160m = value; }
        }

        private float waterfall_low_threshold_160m = -120.0F;
        public float WaterfallLowThreshold160m
        {
            get { return waterfall_low_threshold_160m; }
            set { waterfall_low_threshold_160m = value; }
        }

        private float waterfall_high_threshold_80m = -80.0F;
        public float WaterfallHighThreshold80m
        {
            get { return waterfall_high_threshold_80m; }
            set { waterfall_high_threshold_80m = value; }
        }

        private float waterfall_low_threshold_80m = -120.0F;
        public float WaterfallLowThreshold80m
        {
            get { return waterfall_low_threshold_80m; }
            set { waterfall_low_threshold_80m = value; }
        }

        private float waterfall_high_threshold_60m = -80.0F;
        public float WaterfallHighThreshold60m
        {
            get { return waterfall_high_threshold_60m; }
            set { waterfall_high_threshold_60m = value; }
        }

        private float waterfall_low_threshold_60m = -120.0F;
        public float WaterfallLowThreshold60m
        {
            get { return waterfall_low_threshold_60m; }
            set { waterfall_low_threshold_60m = value; }
        }

        private float waterfall_high_threshold_40m = -80.0F;
        public float WaterfallHighThreshold40m
        {
            get { return waterfall_high_threshold_40m; }
            set { waterfall_high_threshold_40m = value; }
        }

        private float waterfall_low_threshold_40m = -120.0F;
        public float WaterfallLowThreshold40m
        {
            get { return waterfall_low_threshold_40m; }
            set { waterfall_low_threshold_40m = value; }
        }

        private float waterfall_high_threshold_30m = -80.0F;
        public float WaterfallHighThreshold30m
        {
            get { return waterfall_high_threshold_30m; }
            set { waterfall_high_threshold_30m = value; }
        }

        private float waterfall_low_threshold_30m = -130.0F;
        public float WaterfallLowThreshold30m
        {
            get { return waterfall_low_threshold_30m; }
            set { waterfall_low_threshold_30m = value; }
        }

        private float waterfall_high_threshold_20m = -80.0F;
        public float WaterfallHighThreshold20m
        {
            get { return waterfall_high_threshold_20m; }
            set { waterfall_high_threshold_20m = value; }
        }

        private float waterfall_low_threshold_20m = -130.0F;
        public float WaterfallLowThreshold20m
        {
            get { return waterfall_low_threshold_20m; }
            set { waterfall_low_threshold_20m = value; }
        }

        private float waterfall_high_threshold_17m = -80.0F;
        public float WaterfallHighThreshold17m
        {
            get { return waterfall_high_threshold_17m; }
            set { waterfall_high_threshold_17m = value; }
        }

        private float waterfall_low_threshold_17m = -130.0F;
        public float WaterfallLowThreshold17m
        {
            get { return waterfall_low_threshold_17m; }
            set { waterfall_low_threshold_17m = value; }
        }

        private float waterfall_high_threshold_15m = -80.0F;
        public float WaterfallHighThreshold15m
        {
            get { return waterfall_high_threshold_15m; }
            set { waterfall_high_threshold_15m = value; }
        }

        private float waterfall_low_threshold_15m = -130.0F;
        public float WaterfallLowThreshold15m
        {
            get { return waterfall_low_threshold_15m; }
            set { waterfall_low_threshold_15m = value; }
        }

        private float waterfall_high_threshold_12m = -80.0F;
        public float WaterfallHighThreshold12m
        {
            get { return waterfall_high_threshold_12m; }
            set { waterfall_high_threshold_12m = value; }
        }

        private float waterfall_low_threshold_12m = -140.0F;
        public float WaterfallLowThreshold12m
        {
            get { return waterfall_low_threshold_12m; }
            set { waterfall_low_threshold_12m = value; }
        }

        private float waterfall_high_threshold_10m = -80.0F;
        public float WaterfallHighThreshold10m
        {
            get { return waterfall_high_threshold_10m; }
            set { waterfall_high_threshold_10m = value; }
        }

        private float waterfall_low_threshold_10m = -140.0F;
        public float WaterfallLowThreshold10m
        {
            get { return waterfall_low_threshold_10m; }
            set { waterfall_low_threshold_10m = value; }
        }

        private float waterfall_high_threshold_6m = -80.0F;
        public float WaterfallHighThreshold6m
        {
            get { return waterfall_high_threshold_6m; }
            set { waterfall_high_threshold_6m = value; }
        }

        private float waterfall_low_threshold_6m = -140.0F;
        public float WaterfallLowThreshold6m
        {
            get { return waterfall_low_threshold_6m; }
            set { waterfall_low_threshold_6m = value; }
        }

        private float waterfall_high_threshold_wwv = -80.0F;
        public float WaterfallHighThresholdWWV
        {
            get { return waterfall_high_threshold_wwv; }
            set { waterfall_high_threshold_wwv = value; }
        }

        private float waterfall_low_threshold_wwv = -130.0F;
        public float WaterfallLowThresholdWWV
        {
            get { return waterfall_low_threshold_wwv; }
            set { waterfall_low_threshold_wwv = value; }
        }

        private float waterfall_high_threshold_gen = -80.0F;
        public float WaterfallHighThresholdGEN
        {
            get { return waterfall_high_threshold_gen; }
            set { waterfall_high_threshold_gen = value; }
        }

        private float waterfall_low_threshold_gen = -130.0F;
        public float WaterfallLowThresholdGEN
        {
            get { return waterfall_low_threshold_gen; }
            set { waterfall_low_threshold_gen = value; }
        }

        private float waterfall_high_threshold_xvtr = -80.0F;
        public float WaterfallHighThresholdXVTR
        {
            get { return waterfall_high_threshold_xvtr; }
            set { waterfall_high_threshold_xvtr = value; }
        }

        private float waterfall_low_threshold_xvtr = -140.0F;
        public float WaterfallLowThresholdXVTR
        {
            get { return waterfall_low_threshold_xvtr; }
            set { waterfall_low_threshold_xvtr = value; }
        }

        private float rx2_waterfall_high_threshold_160m = -80.0F;
        public float RX2WaterfallHighThreshold160m
        {
            get { return rx2_waterfall_high_threshold_160m; }
            set { rx2_waterfall_high_threshold_160m = value; }
        }

        private float rx2_waterfall_low_threshold_160m = -120.0F;
        public float RX2WaterfallLowThreshold160m
        {
            get { return rx2_waterfall_low_threshold_160m; }
            set { rx2_waterfall_low_threshold_160m = value; }
        }

        private float rx2_waterfall_high_threshold_80m = -80.0F;
        public float RX2WaterfallHighThreshold80m
        {
            get { return rx2_waterfall_high_threshold_80m; }
            set { rx2_waterfall_high_threshold_80m = value; }
        }

        private float rx2_waterfall_low_threshold_80m = -120.0F;
        public float RX2WaterfallLowThreshold80m
        {
            get { return rx2_waterfall_low_threshold_80m; }
            set { rx2_waterfall_low_threshold_80m = value; }
        }

        private float rx2_waterfall_high_threshold_60m = -80.0F;
        public float RX2WaterfallHighThreshold60m
        {
            get { return rx2_waterfall_high_threshold_60m; }
            set { rx2_waterfall_high_threshold_60m = value; }
        }

        private float rx2_waterfall_low_threshold_60m = -120.0F;
        public float RX2WaterfallLowThreshold60m
        {
            get { return rx2_waterfall_low_threshold_60m; }
            set { rx2_waterfall_low_threshold_60m = value; }
        }

        private float rx2_waterfall_high_threshold_40m = -80.0F;
        public float RX2WaterfallHighThreshold40m
        {
            get { return rx2_waterfall_high_threshold_40m; }
            set { rx2_waterfall_high_threshold_40m = value; }
        }

        private float rx2_waterfall_low_threshold_40m = -120.0F;
        public float RX2WaterfallLowThreshold40m
        {
            get { return rx2_waterfall_low_threshold_40m; }
            set { rx2_waterfall_low_threshold_40m = value; }
        }

        private float rx2_waterfall_high_threshold_30m = -80.0F;
        public float RX2WaterfallHighThreshold30m
        {
            get { return rx2_waterfall_high_threshold_30m; }
            set { rx2_waterfall_high_threshold_30m = value; }
        }

        private float rx2_waterfall_low_threshold_30m = -130.0F;
        public float RX2WaterfallLowThreshold30m
        {
            get { return rx2_waterfall_low_threshold_30m; }
            set { rx2_waterfall_low_threshold_30m = value; }
        }

        private float rx2_waterfall_high_threshold_20m = -80.0F;
        public float RX2WaterfallHighThreshold20m
        {
            get { return rx2_waterfall_high_threshold_20m; }
            set { rx2_waterfall_high_threshold_20m = value; }
        }

        private float rx2_waterfall_low_threshold_20m = -130.0F;
        public float RX2WaterfallLowThreshold20m
        {
            get { return rx2_waterfall_low_threshold_20m; }
            set { rx2_waterfall_low_threshold_20m = value; }
        }

        private float rx2_waterfall_high_threshold_17m = -80.0F;
        public float RX2WaterfallHighThreshold17m
        {
            get { return rx2_waterfall_high_threshold_17m; }
            set { rx2_waterfall_high_threshold_17m = value; }
        }

        private float rx2_waterfall_low_threshold_17m = -130.0F;
        public float RX2WaterfallLowThreshold17m
        {
            get { return rx2_waterfall_low_threshold_17m; }
            set { rx2_waterfall_low_threshold_17m = value; }
        }

        private float rx2_waterfall_high_threshold_15m = -80.0F;
        public float RX2WaterfallHighThreshold15m
        {
            get { return rx2_waterfall_high_threshold_15m; }
            set { rx2_waterfall_high_threshold_15m = value; }
        }

        private float rx2_waterfall_low_threshold_15m = -130.0F;
        public float RX2WaterfallLowThreshold15m
        {
            get { return rx2_waterfall_low_threshold_15m; }
            set { rx2_waterfall_low_threshold_15m = value; }
        }

        private float rx2_waterfall_high_threshold_12m = -80.0F;
        public float RX2WaterfallHighThreshold12m
        {
            get { return rx2_waterfall_high_threshold_12m; }
            set { rx2_waterfall_high_threshold_12m = value; }
        }

        private float rx2_waterfall_low_threshold_12m = -140.0F;
        public float RX2WaterfallLowThreshold12m
        {
            get { return rx2_waterfall_low_threshold_12m; }
            set { rx2_waterfall_low_threshold_12m = value; }
        }

        private float rx2_waterfall_high_threshold_10m = -80.0F;
        public float RX2WaterfallHighThreshold10m
        {
            get { return rx2_waterfall_high_threshold_10m; }
            set { rx2_waterfall_high_threshold_10m = value; }
        }

        private float rx2_waterfall_low_threshold_10m = -140.0F;
        public float RX2WaterfallLowThreshold10m
        {
            get { return rx2_waterfall_low_threshold_10m; }
            set { rx2_waterfall_low_threshold_10m = value; }
        }

        private float rx2_waterfall_high_threshold_6m = -80.0F;
        public float RX2WaterfallHighThreshold6m
        {
            get { return rx2_waterfall_high_threshold_6m; }
            set { rx2_waterfall_high_threshold_6m = value; }
        }

        private float rx2_waterfall_low_threshold_6m = -140.0F;
        public float RX2WaterfallLowThreshold6m
        {
            get { return rx2_waterfall_low_threshold_6m; }
            set { rx2_waterfall_low_threshold_6m = value; }
        }

        private float rx2_waterfall_high_threshold_wwv = -80.0F;
        public float RX2WaterfallHighThresholdWWV
        {
            get { return rx2_waterfall_high_threshold_wwv; }
            set { rx2_waterfall_high_threshold_wwv = value; }
        }

        private float rx2_waterfall_low_threshold_wwv = -130.0F;
        public float RX2WaterfallLowThresholdWWV
        {
            get { return rx2_waterfall_low_threshold_wwv; }
            set { rx2_waterfall_low_threshold_wwv = value; }
        }

        private float rx2_waterfall_high_threshold_gen = -80.0F;
        public float RX2WaterfallHighThresholdGEN
        {
            get { return rx2_waterfall_high_threshold_gen; }
            set { rx2_waterfall_high_threshold_gen = value; }
        }

        private float rx2_waterfall_low_threshold_gen = -130.0F;
        public float RX2WaterfallLowThresholdGEN
        {
            get { return rx2_waterfall_low_threshold_gen; }
            set { rx2_waterfall_low_threshold_gen = value; }
        }

        private float rx2_waterfall_high_threshold_xvtr = -80.0F;
        public float RX2WaterfallHighThresholdXVTR
        {
            get { return rx2_waterfall_high_threshold_xvtr; }
            set { rx2_waterfall_high_threshold_xvtr = value; }
        }

        private float rx2_waterfall_low_threshold_xvtr = -140.0F;
        public float RX2WaterfallLowThresholdXVTR
        {
            get { return rx2_waterfall_low_threshold_xvtr; }
            set { rx2_waterfall_low_threshold_xvtr = value; }
        }

        //grid levels
        private float display_grid_max_160m = -40.0F;
        public float DisplayGridMax160m
        {
            get { return display_grid_max_160m; }
            set { display_grid_max_160m = value; }
        }

        private float display_grid_min_160m = -140.0F;
        public float DisplayGridMin160m
        {
            get { return display_grid_min_160m; }
            set { display_grid_min_160m = value; }
        }

        private float display_grid_max_80m = -40.0F;
        public float DisplayGridMax80m
        {
            get { return display_grid_max_80m; }
            set { display_grid_max_80m = value; }
        }

        private float display_grid_min_80m = -140.0F;
        public float DisplayGridMin80m
        {
            get { return display_grid_min_80m; }
            set { display_grid_min_80m = value; }
        }

        private float display_grid_max_60m = -40.0F;
        public float DisplayGridMax60m
        {
            get { return display_grid_max_60m; }
            set { display_grid_max_60m = value; }
        }

        private float display_grid_min_60m = -140.0F;
        public float DisplayGridMin60m
        {
            get { return display_grid_min_60m; }
            set { display_grid_min_60m = value; }
        }

        private float display_grid_max_40m = -40.0F;
        public float DisplayGridMax40m
        {
            get { return display_grid_max_40m; }
            set { display_grid_max_40m = value; }
        }

        private float display_grid_min_40m = -140.0F;
        public float DisplayGridMin40m
        {
            get { return display_grid_min_40m; }
            set { display_grid_min_40m = value; }
        }

        private float display_grid_max_30m = -40.0F;
        public float DisplayGridMax30m
        {
            get { return display_grid_max_30m; }
            set { display_grid_max_30m = value; }
        }

        private float display_grid_min_30m = -140.0F;
        public float DisplayGridMin30m
        {
            get { return display_grid_min_30m; }
            set { display_grid_min_30m = value; }
        }

        private float display_grid_max_20m = -40.0F;
        public float DisplayGridMax20m
        {
            get { return display_grid_max_20m; }
            set { display_grid_max_20m = value; }
        }

        private float display_grid_min_20m = -140.0F;
        public float DisplayGridMin20m
        {
            get { return display_grid_min_20m; }
            set { display_grid_min_20m = value; }
        }

        private float display_grid_max_17m = -40.0F;
        public float DisplayGridMax17m
        {
            get { return display_grid_max_17m; }
            set { display_grid_max_17m = value; }
        }

        private float display_grid_min_17m = -140.0F;
        public float DisplayGridMin17m
        {
            get { return display_grid_min_17m; }
            set { display_grid_min_17m = value; }
        }

        private float display_grid_max_15m = -40.0F;
        public float DisplayGridMax15m
        {
            get { return display_grid_max_15m; }
            set { display_grid_max_15m = value; }
        }

        private float display_grid_min_15m = -140.0F;
        public float DisplayGridMin15m
        {
            get { return display_grid_min_15m; }
            set { display_grid_min_15m = value; }
        }

        private float display_grid_max_12m = -40.0F;
        public float DisplayGridMax12m
        {
            get { return display_grid_max_12m; }
            set { display_grid_max_12m = value; }
        }

        private float display_grid_min_12m = -140.0F;
        public float DisplayGridMin12m
        {
            get { return display_grid_min_12m; }
            set { display_grid_min_12m = value; }
        }

        private float display_grid_max_10m = -40.0F;
        public float DisplayGridMax10m
        {
            get { return display_grid_max_10m; }
            set { display_grid_max_10m = value; }
        }

        private float display_grid_min_10m = -140.0F;
        public float DisplayGridMin10m
        {
            get { return display_grid_min_10m; }
            set { display_grid_min_10m = value; }
        }

        private float display_grid_max_6m = -40.0F;
        public float DisplayGridMax6m
        {
            get { return display_grid_max_6m; }
            set { display_grid_max_6m = value; }
        }

        private float display_grid_min_6m = -140.0F;
        public float DisplayGridMin6m
        {
            get { return display_grid_min_6m; }
            set { display_grid_min_6m = value; }
        }

        private float display_grid_max_wwv = -40.0F;
        public float DisplayGridMaxWWV
        {
            get { return display_grid_max_wwv; }
            set { display_grid_max_wwv = value; }
        }

        private float display_grid_min_wwv = -140.0F;
        public float DisplayGridMinWWV
        {
            get { return display_grid_min_wwv; }
            set { display_grid_min_wwv = value; }
        }

        private float display_grid_max_gen = -40.0F;
        public float DisplayGridMaxGEN
        {
            get { return display_grid_max_gen; }
            set { display_grid_max_gen = value; }
        }

        private float display_grid_min_gen = -140.0F;
        public float DisplayGridMinGEN
        {
            get { return display_grid_min_gen; }
            set { display_grid_min_gen = value; }
        }

        private float display_grid_max_xvtr = -40.0F;
        public float DisplayGridMaxXVTR
        {
            get { return display_grid_max_xvtr; }
            set { display_grid_max_xvtr = value; }
        }

        private float display_grid_min_xvtr = -140.0F;
        public float DisplayGridMinXVTR
        {
            get { return display_grid_min_xvtr; }
            set { display_grid_min_xvtr = value; }
        }

        // rx2 grid levels
        private float rx2_display_grid_max_160m = -40.0F;
        public float RX2DisplayGridMax160m
        {
            get { return rx2_display_grid_max_160m; }
            set { rx2_display_grid_max_160m = value; }
        }

        private float rx2_display_grid_min_160m = -140.0F;
        public float RX2DisplayGridMin160m
        {
            get { return rx2_display_grid_min_160m; }
            set { rx2_display_grid_min_160m = value; }
        }

        private float rx2_display_grid_max_80m = -40.0F;
        public float RX2DisplayGridMax80m
        {
            get { return rx2_display_grid_max_80m; }
            set { rx2_display_grid_max_80m = value; }
        }

        private float rx2_display_grid_min_80m = -140.0F;
        public float RX2DisplayGridMin80m
        {
            get { return rx2_display_grid_min_80m; }
            set { rx2_display_grid_min_80m = value; }
        }

        private float rx2_display_grid_max_60m = -40.0F;
        public float RX2DisplayGridMax60m
        {
            get { return rx2_display_grid_max_60m; }
            set { rx2_display_grid_max_60m = value; }
        }

        private float rx2_display_grid_min_60m = -140.0F;
        public float RX2DisplayGridMin60m
        {
            get { return rx2_display_grid_min_60m; }
            set { rx2_display_grid_min_60m = value; }
        }

        private float rx2_display_grid_max_40m = -40.0F;
        public float RX2DisplayGridMax40m
        {
            get { return rx2_display_grid_max_40m; }
            set { rx2_display_grid_max_40m = value; }
        }

        private float rx2_display_grid_min_40m = -140.0F;
        public float RX2DisplayGridMin40m
        {
            get { return rx2_display_grid_min_40m; }
            set { rx2_display_grid_min_40m = value; }
        }

        private float rx2_display_grid_max_30m = -40.0F;
        public float RX2DisplayGridMax30m
        {
            get { return rx2_display_grid_max_30m; }
            set { rx2_display_grid_max_30m = value; }
        }

        private float rx2_display_grid_min_30m = -140.0F;
        public float RX2DisplayGridMin30m
        {
            get { return rx2_display_grid_min_30m; }
            set { rx2_display_grid_min_30m = value; }
        }

        private float rx2_display_grid_max_20m = -40.0F;
        public float RX2DisplayGridMax20m
        {
            get { return rx2_display_grid_max_20m; }
            set { rx2_display_grid_max_20m = value; }
        }

        private float rx2_display_grid_min_20m = -140.0F;
        public float RX2DisplayGridMin20m
        {
            get { return rx2_display_grid_min_20m; }
            set { rx2_display_grid_min_20m = value; }
        }

        private float rx2_display_grid_max_17m = -40.0F;
        public float RX2DisplayGridMax17m
        {
            get { return rx2_display_grid_max_17m; }
            set { rx2_display_grid_max_17m = value; }
        }

        private float rx2_display_grid_min_17m = -140.0F;
        public float RX2DisplayGridMin17m
        {
            get { return rx2_display_grid_min_17m; }
            set { rx2_display_grid_min_17m = value; }
        }

        private float rx2_display_grid_max_15m = -40.0F;
        public float RX2DisplayGridMax15m
        {
            get { return rx2_display_grid_max_15m; }
            set { rx2_display_grid_max_15m = value; }
        }

        private float rx2_display_grid_min_15m = -140.0F;
        public float RX2DisplayGridMin15m
        {
            get { return rx2_display_grid_min_15m; }
            set { rx2_display_grid_min_15m = value; }
        }

        private float rx2_display_grid_max_12m = -40.0F;
        public float RX2DisplayGridMax12m
        {
            get { return rx2_display_grid_max_12m; }
            set { rx2_display_grid_max_12m = value; }
        }

        private float rx2_display_grid_min_12m = -140.0F;
        public float RX2DisplayGridMin12m
        {
            get { return rx2_display_grid_min_12m; }
            set { rx2_display_grid_min_12m = value; }
        }

        private float rx2_display_grid_max_10m = -40.0F;
        public float RX2DisplayGridMax10m
        {
            get { return rx2_display_grid_max_10m; }
            set { rx2_display_grid_max_10m = value; }
        }

        private float rx2_display_grid_min_10m = -140.0F;
        public float RX2DisplayGridMin10m
        {
            get { return rx2_display_grid_min_10m; }
            set { rx2_display_grid_min_10m = value; }
        }

        private float rx2_display_grid_max_6m = -40.0F;
        public float RX2DisplayGridMax6m
        {
            get { return rx2_display_grid_max_6m; }
            set { rx2_display_grid_max_6m = value; }
        }

        private float rx2_display_grid_min_6m = -140.0F;
        public float RX2DisplayGridMin6m
        {
            get { return rx2_display_grid_min_6m; }
            set { rx2_display_grid_min_6m = value; }
        }

        private float rx2_display_grid_max_wwv = -40.0F;
        public float RX2DisplayGridMaxWWV
        {
            get { return rx2_display_grid_max_wwv; }
            set { rx2_display_grid_max_wwv = value; }
        }

        private float rx2_display_grid_min_wwv = -140.0F;
        public float RX2DisplayGridMinWWV
        {
            get { return rx2_display_grid_min_wwv; }
            set { rx2_display_grid_min_wwv = value; }
        }

        private float rx2_display_grid_max_gen = -40.0F;
        public float RX2DisplayGridMaxGEN
        {
            get { return rx2_display_grid_max_gen; }
            set { rx2_display_grid_max_gen = value; }
        }

        private float rx2_display_grid_min_gen = -140.0F;
        public float RX2DisplayGridMinGEN
        {
            get { return rx2_display_grid_min_gen; }
            set { rx2_display_grid_min_gen = value; }
        }

        private float rx2_display_grid_max_xvtr = -40.0F;
        public float RX2DisplayGridMaxXVTR
        {
            get { return rx2_display_grid_max_xvtr; }
            set { rx2_display_grid_max_xvtr = value; }
        }

        private float rx2_display_grid_min_xvtr = -140.0F;
        public float RX2DisplayGridMinXVTR
        {
            get { return rx2_display_grid_min_xvtr; }
            set { rx2_display_grid_min_xvtr = value; }
        }
        //end of insane implementation

        private int digu_click_tune_offset = 1500;
        public int DIGUClickTuneOffset
        {
            get { return digu_click_tune_offset; }
            set
            {
                digu_click_tune_offset = value;
                Filter filter1 = RX1Filter;     // save RX1 filter
                Filter filter2 = RX2Filter;     // save RX2 filter
                //reset preset filter's center frequency - W4TME

                for (Filter f = Filter.F1; f < Filter.LAST; f++)
                {
                    int low = rx1_filters[(int)DSPMode.DIGU].GetLow(f);
                    int high = rx1_filters[(int)DSPMode.DIGU].GetHigh(f);
                    string name = rx1_filters[(int)DSPMode.DIGU].GetName(f);

                    int bw = high - low;
                    low = digu_click_tune_offset - bw / 2;
                    high = digu_click_tune_offset + bw / 2;
                    rx1_filters[(int)DSPMode.DIGU].SetFilter(f, low, high, name);
                    rx2_filters[(int)DSPMode.DIGU].SetFilter(f, low, high, name);
                }
                RX1Filter = filter1;            // restore RX1 filter
                RX2Filter = filter2;            // restore RX2 filter                     
            }
        }

        private int digl_click_tune_offset = 2210;
        public int DIGLClickTuneOffset
        {
            get { return digl_click_tune_offset; }
            set
            {
                digl_click_tune_offset = value;
                Filter filter1 = RX1Filter;     // save RX1 filter
                Filter filter2 = RX2Filter;     // save RX2 filter
                //reset preset filter's center frequency - W4TME

                for (Filter f = Filter.F1; f < Filter.LAST; f++)
                {
                    int low = rx1_filters[(int)DSPMode.DIGL].GetLow(f);
                    int high = rx1_filters[(int)DSPMode.DIGL].GetHigh(f);
                    string name = rx1_filters[(int)DSPMode.DIGL].GetName(f);

                    int bw = high - low;
                    low = -digl_click_tune_offset - bw / 2;
                    high = -digl_click_tune_offset + bw / 2;
                    rx1_filters[(int)DSPMode.DIGL].SetFilter(f, low, high, name);
                    rx2_filters[(int)DSPMode.DIGL].SetFilter(f, low, high, name);
                }
                RX1Filter = filter1;        // restore RX1 filter
                RX2Filter = filter2;        // restore RX2 filter          
            }
        }

        private double vox_hang_time = 250.0;
        public double VOXHangTime
        {
            get { return vox_hang_time; }
            set
            {
                vox_hang_time = value;
                if (!IsSetupFormNull) SetupForm.VOXHangTime = (int)value;
            }
        }

        private bool vox_active = false;
        public bool VOXActive
        {
            get { return vox_active; }
            set { vox_active = value; }
        }

        private bool save_txprofile_on_exit = true;
        public bool SaveTXProfileOnExit
        {
            get { return save_txprofile_on_exit; }
            set { save_txprofile_on_exit = value; }
        }

        private BreakIn current_breakin_mode = BreakIn.Semi;
        public BreakIn CurrentBreakInMode
        {
            get { return current_breakin_mode; }
            set
            {
                current_breakin_mode = value;
                switch (value)
                {
                    case BreakIn.QSK:
                        QSKEnabled = true;
                        NetworkIO.SetCWBreakIn(1);
                        chkQSK.Text = "QSK";
                        break;
                    case BreakIn.Manual: // manual PTT
                        QSKEnabled = false;
                        NetworkIO.SetCWBreakIn(0);
                        chkQSK.Text = "OFF";

                        break;
                    case BreakIn.Semi:
                        QSKEnabled = false;
                        NetworkIO.SetCWBreakIn(1);
                        chkQSK.Text = "SEMI";
                        break;
                }
                TXAF = txaf;
            }
        }

        private HPSDRModel current_hpsdr_model = HPSDRModel.HERMES;
        public HPSDRModel CurrentHPSDRModel
        {
            get { return current_hpsdr_model; }
            set
            {
                HPSDRModel saved_hpsdr_model = current_hpsdr_model;
                current_hpsdr_model = value;

                Display.CurrentHPSDRModel = value;
                chkFullDuplex.Visible = false;
                NetworkIO.fwVersionsChecked = false;

                switch (current_hpsdr_model)
                {
                    case HPSDRModel.HERMES:
                        chkDX.Checked = false;
                        chkDX.Visible = false;
                        rx2_preamp_present = false;
                        NetworkIO.SetRxADC(1);
                        NetworkIO.SetMKIIBPF(0);
                        cmaster.SetADCSupply(0, 33);
                        NetworkIO.LRAudioSwap(1);
                        CurrentHPSDRHardware = HPSDRHW.Hermes;
                        break;
                    case HPSDRModel.ANAN10:
                        chkDX.Checked = false;
                        chkDX.Visible = false;
                        rx2_preamp_present = false;
                        NetworkIO.SetRxADC(1);
                        NetworkIO.SetMKIIBPF(0);
                        cmaster.SetADCSupply(0, 33);
                        NetworkIO.LRAudioSwap(1);
                        CurrentHPSDRHardware = HPSDRHW.Hermes;
                        break;
                    case HPSDRModel.ANAN10E:
                        chkDX.Checked = false;
                        chkDX.Visible = false;
                        rx2_preamp_present = false;
                        NetworkIO.SetRxADC(1);
                        NetworkIO.SetMKIIBPF(0);
                        cmaster.SetADCSupply(0, 33);
                        NetworkIO.LRAudioSwap(1);
                        CurrentHPSDRHardware = HPSDRHW.HermesII;
                        break;
                    case HPSDRModel.ANAN100:
                        chkDX.Checked = false;
                        chkDX.Visible = false;
                        rx2_preamp_present = false;
                        NetworkIO.SetRxADC(1);
                        NetworkIO.SetMKIIBPF(0);
                        cmaster.SetADCSupply(0, 33);
                        NetworkIO.LRAudioSwap(1);
                        CurrentHPSDRHardware = HPSDRHW.Hermes;
                        break;
                    case HPSDRModel.ANAN100B:
                        chkDX.Checked = false;
                        chkDX.Visible = false;
                        rx2_preamp_present = false;
                        NetworkIO.SetRxADC(1);
                        NetworkIO.SetMKIIBPF(0);
                        cmaster.SetADCSupply(0, 33);
                        NetworkIO.LRAudioSwap(1);
                        CurrentHPSDRHardware = HPSDRHW.HermesII;
                        break;
                    case HPSDRModel.ANAN100D:
                        //chkDX.Visible = true; //[2.10.3.6]MW0LGE stereo diversity set as invisible until re-implemented
                        chkDX.Visible = false;
                        rx2_preamp_present = true;
                        NetworkIO.SetRxADC(2);
                        NetworkIO.SetMKIIBPF(0);
                        cmaster.SetADCSupply(0, 33);
                        NetworkIO.LRAudioSwap(0);
                        CurrentHPSDRHardware = HPSDRHW.Angelia;
                        break;
                    case HPSDRModel.ANAN200D:
                        //chkDX.Visible = true; //[2.10.3.6]MW0LGE stereo diversity set as invisible until re-implemented
                        chkDX.Visible = false;
                        rx2_preamp_present = true;
                        NetworkIO.SetRxADC(2);
                        NetworkIO.SetMKIIBPF(0);
                        cmaster.SetADCSupply(0, 50);
                        NetworkIO.LRAudioSwap(0);
                        CurrentHPSDRHardware = HPSDRHW.Orion;
                        break;
                    case HPSDRModel.ORIONMKII:
                        //chkDX.Visible = true; //[2.10.3.6]MW0LGE stereo diversity set as invisible until re-implemented
                        chkDX.Visible = false;
                        rx2_preamp_present = true;
                        NetworkIO.SetRxADC(2);
                        NetworkIO.SetMKIIBPF(1);
                        cmaster.SetADCSupply(0, 50);
                        NetworkIO.LRAudioSwap(0);
                        CurrentHPSDRHardware = HPSDRHW.OrionMKII;
                        break;
                    case HPSDRModel.ANAN7000D:
                        //chkDX.Visible = true; //[2.10.3.6]MW0LGE stereo diversity set as invisible until re-implemented
                        chkDX.Visible = false;
                        rx2_preamp_present = true;
                        NetworkIO.SetRxADC(2);
                        NetworkIO.SetMKIIBPF(1);
                        cmaster.SetADCSupply(0, 50);
                        NetworkIO.LRAudioSwap(0);
                        CurrentHPSDRHardware = HPSDRHW.OrionMKII;
                        break;
                    case HPSDRModel.ANAN8000D:
                        //chkDX.Visible = true; //[2.10.3.6]MW0LGE stereo diversity set as invisible until re-implemented
                        chkDX.Visible = false;
                        rx2_preamp_present = true;
                        NetworkIO.SetRxADC(2);
                        NetworkIO.SetMKIIBPF(1);
                        cmaster.SetADCSupply(0, 50);
                        NetworkIO.LRAudioSwap(0);
                        CurrentHPSDRHardware = HPSDRHW.OrionMKII;
                        break;
                    case HPSDRModel.ANAN_G2:
                        //chkDX.Visible = true; //[2.10.3.6]MW0LGE stereo diversity set as invisible until re-implemented
                        chkDX.Visible = false;
                        rx2_preamp_present = true;
                        NetworkIO.SetRxADC(2);
                        NetworkIO.SetMKIIBPF(1);
                        cmaster.SetADCSupply(0, 50);
                        NetworkIO.LRAudioSwap(0);
                        CurrentHPSDRHardware = HPSDRHW.Saturn;
                        AmpSens = 66.23f;                                // current reading sensitivity
                        AmpVoff = 0.0f;                                  // current sensor voltage offset
                        break;
                    case HPSDRModel.ANAN_G2_1K:             // G8NJJ: likely to need further changes for PA
                        //chkDX.Visible = true; //[2.10.3.6]MW0LGE stereo diversity set as invisible until re-implemented
                        chkDX.Visible = false;
                        rx2_preamp_present = true;
                        NetworkIO.SetRxADC(2);
                        NetworkIO.SetMKIIBPF(1);
                        cmaster.SetADCSupply(0, 50);
                        NetworkIO.LRAudioSwap(0);
                        CurrentHPSDRHardware = HPSDRHW.Saturn;
                        AmpSens = 66.23f;                                // current reading sensitivity
                        AmpVoff = 0.0f;                                  // current sensor voltage offset
                        break;

                }

                switch (current_hpsdr_model)
                {
                    case HPSDRModel.HPSDR:
                        break;
                    case HPSDRModel.HERMES:
                    case HPSDRModel.ANAN10:
                    case HPSDRModel.ANAN10E:
                    case HPSDRModel.ANAN100:
                    case HPSDRModel.ANAN100B:
                    case HPSDRModel.ANAN100D:
                    case HPSDRModel.ANAN200D:
                    case HPSDRModel.ORIONMKII:
                    case HPSDRModel.ANAN7000D:
                    case HPSDRModel.ANAN8000D:
                    case HPSDRModel.ANAN_G2:
                    case HPSDRModel.ANAN_G2_1K:
                        if (!comboMeterTXMode.Items.Contains("Ref Pwr"))
                            comboMeterTXMode.Items.Insert(1, "Ref Pwr");
                        if (!comboMeterTXMode.Items.Contains("SWR"))
                            comboMeterTXMode.Items.Insert(2, "SWR");
                        if (!comboMeterTXMode.Items.Contains("Fwd SWR"))
                            comboMeterTXMode.Items.Insert(3, "Fwd SWR");
                        break;
                }

                SetComboPreampForHPSDR();
                UpdateDDCs(rx2_enabled);

                if (!initializing)
                {
                    rx1_meter_cal_offset = rx_meter_cal_offset_by_radio[(int)current_hpsdr_model];
                    RX1DisplayCalOffset = rx_display_cal_offset_by_radio[(int)current_hpsdr_model];
                    rx2_meter_cal_offset = rx_meter_cal_offset_by_radio[(int)current_hpsdr_model];
                    RX2DisplayCalOffset = rx_display_cal_offset_by_radio[(int)current_hpsdr_model];
                }

                if (!IsSetupFormNull && saved_hpsdr_model != current_hpsdr_model)
                    txtVFOAFreq_LostFocus(this, EventArgs.Empty);

                cmaster.CMSetTXOutputLevelRun();

                if (saved_hpsdr_model != current_hpsdr_model) CurrentModelChangedHandlers?.Invoke(saved_hpsdr_model, current_hpsdr_model); //MW0LGE_[2.9.0.7]
            }
        }

        public HPSDRHW CurrentHPSDRHardware { get; set; } = HPSDRHW.Atlas;

        private int alex_preamp_offset = 0;
        public int AlexPreampOffset
        {
            get { return alex_preamp_offset; }
            set
            {
                alex_preamp_offset = value;
                Display.AlexPreampOffset = alex_preamp_offset;
            }
        }

        private double saved_vfoa_freq = 7.1;
        private double saved_vfoa_sub_freq = 7.1;
        private double saved_vfob_freq = 7.1;

        private bool m_bHotSwitchOCTXPins = false;
        public bool AllowHotSwitchingForOCTXPins
        {
            get { return m_bHotSwitchOCTXPins; }
            set {
                m_bHotSwitchOCTXPins = value;
                updateOCTXPins(_mox);
            }
        }
        private void updateOCTXPins(bool tx)
        {
            if (!IsSetupFormNull) SetupForm.UpdateForHotSwitch(tx);
        }

        private bool penny_ext_ctrl_enabled = true;
        public bool PennyExtCtrlEnabled
        {
            get { return penny_ext_ctrl_enabled; }
            set
            {
                penny_ext_ctrl_enabled = value;

                if (!initializing)
                {
                    Band lo_band = BandByFreq(XVTRForm.TranslateFreq(VFOAFreq), rx1_xvtr_index, current_region);
                    Band lo_bandb = BandByFreq(XVTRForm.TranslateFreq(VFOBFreq), rx2_xvtr_index, current_region);
                    int bits = Penny.getPenny().ExtCtrlEnable(lo_band, lo_bandb, _mox, value, tuning, SetupForm.TestIMD, chkExternalPA.Checked); // MW0LGE_21j
                    if (!IsSetupFormNull) SetupForm.UpdateOCLedStrip(_mox, bits);
                }
            }
        }

        private bool alex_ant_ctrl_enabled = true;
        public bool AlexAntCtrlEnabled
        {
            get { return alex_ant_ctrl_enabled; }
            set
            {
                alex_ant_ctrl_enabled = value;

                UpdateTRXAnt();
                if (rx1_xvtr_index >= 0)
                {
                    Band lo_band = BandByFreq(XVTRForm.TranslateFreq(VFOAFreq), rx1_xvtr_index, current_region);
                    Alex.getAlex().UpdateAlexAntSelection(lo_band, _mox, alex_ant_ctrl_enabled, true);
                }
                else
                {
                    Alex.getAlex().UpdateAlexAntSelection(RX1Band, _mox, alex_ant_ctrl_enabled, false);
                }
                UpdateTRXAnt();

                // QSK not allowed if rx and tx not on same antenna
                if ((RX1DSPMode == DSPMode.CWL || RX1DSPMode == DSPMode.CWU) &&
                     (BreakInEnabledState == CheckState.Indeterminate)) chkQSK_CheckStateChanged(this, EventArgs.Empty);
            }
        }

        private void UpdateTRXAnt()
        {
            if (chkRxAnt.Checked)
            {
                if (!Alex.trx_ant_different && !initializing)
                {
                    chkRxAnt.Checked = false;
                    return;
                }
                Alex.TRxAnt = true;
                chkRxAnt.Text = "Tx Ant";
                chkRxAnt.ForeColor = Color.Yellow;
            }
            else
            {
                Alex.TRxAnt = false;
                chkRxAnt.Text = "Rx Ant";
                if (Alex.trx_ant_different) chkRxAnt.ForeColor = Color.SpringGreen;
                else chkRxAnt.ForeColor = SystemColors.ControlLightLight;
            }

        }

        private bool rx_out_override = false;
        public bool RxOutOverride
        {
            get { return rx_out_override; }
            set
            {
                rx_out_override = value;
                Alex.rx_out_override = value;
                AlexAntCtrlEnabled = alex_ant_ctrl_enabled;
            }
        }

        private bool cw_sidetone = true;
        public bool CWSidetone
        {
            get { return cw_sidetone; }
            set
            {
                cw_sidetone = value;
                if (chkCWSidetone != null) chkCWSidetone.Checked = value;

                DSPMode tx_mode = rx1_dsp_mode;
                if (chkVFOBTX.Checked && chkRX2.Checked) tx_mode = rx2_dsp_mode;

                if (tx_mode == DSPMode.CWL || tx_mode == DSPMode.CWU)
                    chkMON.Checked = value;

                setCWSideToneVolume();
            }
        }

        private PTTMode _current_ptt_mode = PTTMode.NONE;
        public PTTMode CurrentPTTMode
        {
            get { return _current_ptt_mode; }
            set { _current_ptt_mode = value; }
        }

        private bool rx2_preamp_present = false;
        public bool RX2PreampPresent
        {
            get { return rx2_preamp_present; }
            set
            {
                rx2_preamp_present = value;
                if (rx2_preamp_present)
                {
                    if (current_hpsdr_model == HPSDRModel.HPSDR)
                    {
                        RX2StepAttPresent = false;
                    }
                    else
                    {
                        rx2_step_att_present = true;
                        comboRX2Preamp.Show();
                        udRX2StepAttData.Show();
                        lblRX2Preamp.Visible = true;
                    }

                }
                else
                {
                    comboRX2Preamp.Hide();
                    udRX2StepAttData.Hide();
                    lblRX2Preamp.Visible = false;
                }
            }
        }

        private int rx_adc_ctrl1 = 4;
        public int RXADCCtrl1
        {
            get { return rx_adc_ctrl1; }
            set
            {
                rx_adc_ctrl1 = value;
                UpdateDDCs(rx2_enabled);
            }
        }

        public int GetADCInUse(int ddc)
        {
            if (ddc < 0 || ddc > 7) return -1;

            int adcControl = 0;
            if (NetworkIO.CurrentRadioProtocol == RadioProtocol.ETH)
            {
                adcControl = ddc < 4 ? RXADCCtrl1 : RXADCCtrl2;
                if (ddc >= 4) ddc -= 4; // ddc4 becomes the ddc0 point in rxdacctrl2
            }
            else if (NetworkIO.CurrentRadioProtocol == RadioProtocol.USB)
            {
                // protocol 1 assigned ADCs for each DDC
                // RXADCCtrl_P1 is a 14 bit int, 2 bits per DDC 66554433221100
                adcControl = RXADCCtrl_P1;
            }
            else return -1;

            int mask = 3 << (ddc * 2);
            int tmp = adcControl & mask;
            tmp = tmp >> (ddc * 2);

            return tmp;
        }

        private int rx_adc_ctrl2 = 0;
        public int RXADCCtrl2
        {
            get { return rx_adc_ctrl2; }
            set
            {
                rx_adc_ctrl2 = value;
                UpdateDDCs(rx2_enabled);
            }
        }

        // set protocol 1 assigned ADCs for each DDC
        private int rx_adc_ctrl_P1 = 4;                 // 14 bit int, 2 bits per DDC 66554433221100
        public int RXADCCtrl_P1
        {
            get { return rx_adc_ctrl_P1; }
            set
            {
                rx_adc_ctrl_P1 = value;
                UpdateRXADCCtrlP1();
            }
        }

        public CheckState VFOLock { get; set; } = CheckState.Unchecked;

        private bool vfoA_lock = false;
        public bool VFOALock
        {
            get { return vfoA_lock; }
            set
            {
                bool old_state = vfoA_lock;
                //bool enabled = true;
                vfoA_lock = value;                
                //switch (vfoA_lock)
                //{
                //    case false:
                //        txtVFOAFreq.Enabled = true;
                //        break;
                //    case true:
                //        enabled = false;
                //        txtVFOAFreq.Enabled = false;
                //        break;
                //}
                //[2.3.10.6]MW0LGE whoever did the commented code above needs to step away from the computer, how about if else????
                bool enabled = !vfoA_lock;
                txtVFOAFreq.Enabled = enabled;
                if (vfoA_lock) chkVFOSync.Checked = false;

                if (vfoA_lock)
                {
                    DisableAllBands();
                    DisableAllModes();
                }
                else
                {
                    EnableAllBands();
                    EnableAllModes();
                }

                btnVFOBtoA.Enabled = enabled;
                btnVFOSwap.Enabled = enabled;

                btnMemoryQuickRestore.Enabled = enabled;

                if (vfoA_lock)
                    lblLockLabel.BackColor = System.Drawing.Color.Blue;
                else
                    lblLockLabel.BackColor = System.Drawing.Color.Transparent;
                lblLockLabel.Invalidate();

                AndromedaIndicatorCheck(EIndicatorActions.eINVFOLock, true, vfoA_lock);

                chkVFOLock.Checked = vfoA_lock;

                if (vfoA_lock != old_state)
                {
                    VfoALockChangedHandlers?.Invoke(1, old_state, vfoA_lock);
                    old_state = vfoA_lock;
                }
            }
        }

        private bool vfoB_lock = false;
        public bool VFOBLock
        {
            get { return vfoB_lock; }
            set
            {
                bool old_state = vfoB_lock;
                //bool enabled = true;
                vfoB_lock = value;
                //switch (vfoB_lock)
                //{
                //    case false:
                //        txtVFOBFreq.Enabled = true;
                //        break;
                //    case true:
                //        enabled = false;
                //        txtVFOBFreq.Enabled = false;
                //        chkVFOSync.Checked = false;
                //        break;
                //}
                //[2.3.10.6]MW0LGE whoever did the commented code above needs to step away from the computer, how about if else????
                bool enabled = !vfoB_lock;
                txtVFOBFreq.Enabled = enabled;
                if (vfoB_lock) chkVFOSync.Checked = false;

                comboRX2Band.Enabled = enabled;
                btnVFOAtoB.Enabled = enabled;
                chkVFOSync.Enabled = enabled;


                radRX2ModeLSB.Enabled = enabled;
                radRX2ModeUSB.Enabled = enabled;
                radRX2ModeDSB.Enabled = enabled;
                radRX2ModeCWL.Enabled = enabled;
                radRX2ModeCWU.Enabled = enabled;
                radRX2ModeFMN.Enabled = enabled;
                radRX2ModeAM.Enabled = enabled;
                radRX2ModeSAM.Enabled = enabled;
                radRX2ModeSPEC.Enabled = enabled;
                radRX2ModeDIGL.Enabled = enabled;
                radRX2ModeDIGU.Enabled = enabled;
                radRX2ModeDRM.Enabled = enabled;

                if (vfoB_lock)
                    lblRX2LockLabel.BackColor = System.Drawing.Color.Blue;
                else
                    lblRX2LockLabel.BackColor = System.Drawing.Color.Transparent;

                AndromedaIndicatorCheck(EIndicatorActions.eINVFOLock, false, vfoB_lock); // <- this use of false is totally wrong, because if RX2 is in use, then lock B is RX2.
                                                                                         // I just cba to fix it, as this sort of thing keeps being done. -LGE

                chkVFOBLock.Checked = vfoB_lock;

                if (vfoB_lock != old_state)
                {
                    VfoBLockChangedHandlers?.Invoke(RX2Enabled ? 2 : 1, old_state, vfoB_lock);
                    old_state = vfoB_lock;
                }
            }
        }

        private double wave_freq = 0.0;
        private bool wave_playback = false;
        public bool WavePlayback
        {
            get { return wave_playback; }
            set
            {
                wave_playback = value;
                if (wave_playback)
                {
                    wave_freq = (VFOAFreq * 1e6) % sample_rate_rx1;
                }
                else
                {
                    txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                }
            }
        }

        private bool saved_rx_only = false;
        private bool rx_only = false;
        public bool RXOnly
        {
            get { return rx_only; }
            set
            {
                rx_only = value;
                if (rx1_dsp_mode != DSPMode.SPEC &&
                    rx1_dsp_mode != DSPMode.DRM &&
                    chkPower.Checked)
                    chkMOX.Enabled = !rx_only;
                chkTUN.Enabled = !rx_only;
                chk2TONE.Enabled = !rx_only; // MW0LGE_21a
                chkVOX.Enabled = !rx_only;
                if (rx_only && chkMOX.Checked)
                    chkMOX.Checked = false;

                if (!IsSetupFormNull)
                {
                    if (SetupForm.RXOnly != rx_only)
                        SetupForm.RXOnly = rx_only;
                }
            }
        }

        private bool _useTxInhibit = false;
        private bool _reverseTxInhibit = false;
        public bool UseTxInhibit { get { return _useTxInhibit; } set { _useTxInhibit = value; } }
        public bool ReverseTxInhibit { get { return _reverseTxInhibit; } set { _reverseTxInhibit = value; } }

        private bool _tx_inhibit = false;
        public bool TXInhibit
        {
            get { return _tx_inhibit; }
            set
            {
                _tx_inhibit = value;
                if (rx1_dsp_mode != DSPMode.SPEC &&
                    rx1_dsp_mode != DSPMode.DRM &&
                    chkPower.Checked)
                    chkMOX.Enabled = !_tx_inhibit;

                chkTUN.Enabled = !_tx_inhibit;
                chk2TONE.Enabled = !_tx_inhibit; //MW0LGE_21a
                chkVOX.Enabled = !_tx_inhibit;

                if ((rx1_dsp_mode == DSPMode.CWL ||
                    rx1_dsp_mode == DSPMode.CWU) &&
                    chkPower.Checked)
                    chkMOX.Enabled = !_tx_inhibit;

                if (_tx_inhibit && chkMOX.Checked)
                    chkMOX.Checked = false;

                toolStripStatusLabel_TXInhibit.Visible = _tx_inhibit;
            }
        }

        private FRSRegion current_region = FRSRegion.FIRST;
        public FRSRegion CurrentRegion
        {
            get { return current_region; }
            set {
                current_region = value;

                //MW0LGE_21d bandstack initalising
                BandStackManager.Region = current_region;
                BandStackFilter bsf = BandStackManager.GetFilter(RX1Band, false);
                if (bsf != null)
                {
                    BandStack2Form.InitBandStackFilter(bsf);
                    updateStackNumberDisplay(bsf);

                    updateBandstackOverlay(1); //MW0LGE_21h
                }
            }
        }


        private static bool display_duplex = false;
        public static bool DisplayDuplex
        {
            get { return display_duplex; }
            set { display_duplex = value; }
        }

        double rx1_dds_freq_mhz;
        private void UpdateRX1DDSFreq()
        {
            if (initializing) return;
            SetAlexHPF(fwc_dds_freq);
            UpdateAlexTXFilter();
            UpdateAlexRXFilter();

            switch (CurrentHPSDRModel)
            {
                case HPSDRModel.HERMES:
                case HPSDRModel.ANAN10:
                case HPSDRModel.ANAN10E:
                case HPSDRModel.ANAN100:
                case HPSDRModel.ANAN100B:
                    NetworkIO.VFOfreq(0, rx1_dds_freq_mhz, 0);
                    break;
                default:
                    NetworkIO.VFOfreq(0, rx1_dds_freq_mhz, 0);
                    NetworkIO.VFOfreq(1, rx1_dds_freq_mhz, 0);
                    NetworkIO.VFOfreq(2, rx1_dds_freq_mhz, 0);
                    break;
            }

        }

        double rx2_dds_freq_mhz;
        private void UpdateRX2DDSFreq()
        {
            if (initializing) return;
            UpdateAlexTXFilter();
            UpdateAlexRXFilter();

            if (current_hpsdr_model == HPSDRModel.ORIONMKII ||
                current_hpsdr_model == HPSDRModel.ANAN7000D ||
                current_hpsdr_model == HPSDRModel.ANAN8000D ||
                current_hpsdr_model == HPSDRModel.ANAN_G2 ||
                current_hpsdr_model == HPSDRModel.ANAN_G2_1K)
            {
                SetAlex2HPF(rx2_dds_freq_mhz);
            }

            switch (CurrentHPSDRModel)
            {
                case HPSDRModel.HERMES:
                case HPSDRModel.ANAN10:
                case HPSDRModel.ANAN10E:
                case HPSDRModel.ANAN100:
                case HPSDRModel.ANAN100B:
                    NetworkIO.VFOfreq(1, rx2_dds_freq_mhz, 0);
                    break;
                default:
                    NetworkIO.VFOfreq(3, rx2_dds_freq_mhz, 0);
                    break;
            }

        }

        double tx_dds_freq_mhz = 14;
        private void UpdateTXDDSFreq()
        {
            if (initializing) return;
            SetAlexLPF(tx_dds_freq_mhz, true);
            if (_mox)
                SetAlexHPF(fwc_dds_freq);
            NetworkIO.VFOfreq(0, tx_dds_freq_mhz, 1);
        }

        private void UpdateAlexTXFilter()
        {
            if (!_mox)
            {
                if (!rx2_preamp_present && chkRX2.Checked)
                {
                    if (rx1_dds_freq_mhz > rx2_dds_freq_mhz) SetAlexLPF(rx1_dds_freq_mhz, false);
                    else SetAlexLPF(rx2_dds_freq_mhz, false);
                }
                else SetAlexLPF(rx1_dds_freq_mhz, false);
            }
        }

        private void UpdateAlexRXFilter()
        {
            if (!_mox)
            {
                if (!rx2_preamp_present && chkRX2.Checked)
                {
                    if (rx1_dds_freq_mhz < rx2_dds_freq_mhz) SetAlexHPF(rx1_dds_freq_mhz);
                    else SetAlexHPF(rx2_dds_freq_mhz);
                }
            }
        }

        private double fwc_dds_freq = 14;
        public double FWCDDSFreq
        {
            get { return fwc_dds_freq; }
            set
            {
                fwc_dds_freq = value;

                double f = fwc_dds_freq + vfo_offset;
                rx1_dds_freq_mhz = f;
                UpdateRX1DDSFreq();
            }
        }

        private double rx2_dds_freq = 14;
        public double RX2DDSFreq
        {
            get { return rx2_dds_freq; }
            set
            {
                rx2_dds_freq = value;

                double f = rx2_dds_freq + rx2_vfo_offset;
                rx2_dds_freq_mhz = f;
                UpdateRX2DDSFreq();
            }
        }

        private double dds_freq = 14;
        public double DDSFreq
        {
            get { return dds_freq; }
            set
            {
                dds_freq = value;
            }
        }

        private double min_freq = 0.0;
        public double MinFreq
        {
            get { return min_freq; }
            set
            {
                min_freq = value;
                if (VFOAFreq < min_freq)
                    VFOAFreq = min_freq;
            }
        }

        private double max_freq = 61.44;
        public double MaxFreq
        {
            get { return max_freq; }
            set
            {
                max_freq = value;

                if (IsSetupFormNull) return;
                if (VFOAFreq > max_freq && rx1_xvtr_index < 0)
                    VFOAFreq = max_freq;
            }
        }

        private double vfo_offset = 0.0;
        public double VFOOffset
        {
            get { return vfo_offset; }
            set { vfo_offset = value; }
        }

        private double rx2_vfo_offset = 0.0;
        public double RX2VFOOffset
        {
            get { return rx2_vfo_offset; }
            set { rx2_vfo_offset = value; }
        }

        private bool if_shift = false;
        public bool IFShift
        {
            get { return if_shift; }
            set { if_shift = value; }
        }

        private bool extended = false;
        public bool Extended
        {
            get { return extended; }
            set { extended = value;

                //MW0LGE_21d bandstack initalising
                BandStackManager.Extended = value;
                BandStackFilter bsf = BandStackManager.GetFilter(RX1Band, false);
                if (bsf != null)
                {
                    BandStack2Form.InitBandStackFilter(bsf);
                    updateStackNumberDisplay(bsf);

                    updateBandstackOverlay(1); //MW0LGE_21h
                }
            }
        }

        //MW0LGE
        private bool m_bWaterfallUseRX1SpectrumMinMax = false;
        public bool WaterfallUseRX1SpectrumMinMax {
            get { return m_bWaterfallUseRX1SpectrumMinMax; }
            set {
                m_bWaterfallUseRX1SpectrumMinMax = value;

                //MW0LGE override, and dont update any setupform/band settings
                Display.SpectrumBasedThresholdsRX1 = m_bWaterfallUseRX1SpectrumMinMax;

                setWaterfallGainsIfLinkedToSpectrum(1);
            }
        }
        private bool m_bWaterfallUseRX2SpectrumMinMax = false;
        public bool WaterfallUseRX2SpectrumMinMax {
            get { return m_bWaterfallUseRX2SpectrumMinMax; }
            set {
                m_bWaterfallUseRX2SpectrumMinMax = value;

                //MW0LGE override, and dont update any setupform/band settings
                Display.SpectrumBasedThresholdsRX2 = m_bWaterfallUseRX2SpectrumMinMax;

                setWaterfallGainsIfLinkedToSpectrum(2);
            }
        }

        private readonly Object m_objTCILocker = new Object();
        public Console ThreadSafeTCIAccessor
        {
            get
            {
                lock (m_objTCILocker)
                {
                    return this;
                }
            }
        }

        private CATParser m_objTCPIPCatParser = null;
        private readonly Object m_objCatParseLocker = new Object();
        public string ThreadSafeCatParse(string msg)
        {
            if (this.IsDisposed) return "";

            if (this.InvokeRequired)
                return (string)this.Invoke(new Func<string>(() => safeCat(msg)));
            else
                return safeCat(msg);
        }
        private string safeCat(string msg)
        {
            string sRet;
            if (m_objTCPIPCatParser == null) return "";

            lock (m_objCatParseLocker)
            {
                sRet = m_objTCPIPCatParser.Get(msg);
                return sRet;
            }
        }

        public bool _bSendLimitedPowerLevels = false;
        public bool SendLimitedPowerLevels
        {
            get { return _bSendLimitedPowerLevels; }
            set { _bSendLimitedPowerLevels = value; }
        }
        //-

        private int latch_delay = 0;
        public int LatchDelay
        {
            get { return latch_delay; }
            set { latch_delay = value; }
        }

        public bool CPDR
        {
            get { return chkCPDR.Checked; }
            set
            {
                if (IsSetupFormNull)
                    return;

                chkCPDR.Checked = value;
            }
        }
        public int CPDRMin
        {
            get { return ptbCPDR != null ? ptbCPDR.Minimum : 0; }
        }
        public int CPDRMax
        {
            get { return ptbCPDR != null ? ptbCPDR.Maximum : 0; }
        }
        public int CPDRLevel
        {
            get
            {
                if (ptbCPDR == null) return -1;
                return ptbCPDR.Value;
            }
            set
            {
                if (ptbCPDR == null) return;
                ptbCPDR.Value = value;
                ptbCPDR_Scroll(this, EventArgs.Empty);
            }
        }

        public int Mic
        {
            get { return ptbMic.Value; }
            set
            {
                if (IsSetupFormNull)
                    return;

                //[2.10.3.6]MW0LGE fix #417
                value = Math.Max(mic_gain_min, value);
                value = Math.Min(mic_gain_max, value);
                ptbMic.Minimum = mic_gain_min;
                ptbMic.Maximum = mic_gain_max;
                //

                ptbMic.Value = value;
                ptbMic_Scroll(this, EventArgs.Empty);
            }
        }

        public int FMMic  // W4TME
        {
            get { return ptbFMMic.Value; }
            set
            {
                if (IsSetupFormNull)
                    return;

                //[2.10.3.6]MW0LGE fix #417
                value = Math.Max(mic_gain_min, value);
                value = Math.Min(mic_gain_max, value);
                ptbFMMic.Minimum = mic_gain_min;
                ptbFMMic.Maximum = mic_gain_max;
                //

                ptbFMMic.Value = value;
                ptbFMMic_Scroll(this, EventArgs.Empty);
            }
        }

        #region CAT Properties

        // props for cat control 

        public double CATVFOA
        {
            get { return saved_vfoa_freq; }
        }

        public double CATVFOB
        {
            get { return saved_vfob_freq; }
        }

        //-W2PA Added three new functions to make CAT functions match behavior of equivalent console functions.
        //   i.e. not just copy frequency alone
        public void CATVFOAtoB()
        {
            btnVFOAtoB_Click(this, EventArgs.Empty);
        }
        public void CATVFOBtoA()
        {
            btnVFOBtoA_Click(this, EventArgs.Empty);
        }
        public void CATVFOABSwap()
        {
            btnVFOSwap_Click(this, EventArgs.Empty);
        }

        public int CATTXProfileCount
        {
            get
            {
                return comboTXProfile.Items.Count;
            }
        }

        public int CATTXProfile
        {
            get
            {
                switch (rx1_dsp_mode)
                {
                    case DSPMode.DIGL:
                    case DSPMode.DIGU:
                        return comboDigTXProfile.SelectedIndex;
                    case DSPMode.FM:
                        return comboFMTXProfile.SelectedIndex;
                    case DSPMode.AM:
                        return comboAMTXProfile.SelectedIndex;
                    default:
                        return comboTXProfile.SelectedIndex;
                }
            }
            set
            {
                switch (rx1_dsp_mode)
                {
                    case DSPMode.DIGL:
                    case DSPMode.DIGU:
                        comboDigTXProfile.SelectedIndex = value;
                        break;
                    case DSPMode.FM:
                        comboFMTXProfile.SelectedIndex = value;
                        break;
                    case DSPMode.AM:
                        comboAMTXProfile.SelectedIndex = value;
                        break;
                    default:
                        comboTXProfile.SelectedIndex = value;
                        break;
                }
            }
        }

        public string CATPanSwap
        {
            get
            {
                if (chkPanSwap.Checked)
                    return "1";
                else
                    return "0";
            }
            set
            {
                if (value == "1")
                    chkPanSwap.Checked = true;
                else
                    chkPanSwap.Checked = false;
            }
        }

        public string CATPhoneDX
        {
            get
            {
                if (chkDX.Checked)
                    return "1";
                else
                    return "0";
            }
            set
            {
                if (value == "1")
                    chkDX.Checked = true;
                else
                    chkDX.Checked = false;
            }
        }

        public string CATMultRX
        {
            get
            {
                if (chkEnableMultiRX.Checked)
                    return "1";
                else
                    return "0";
            }
            set
            {
                if (value == "1")
                    chkEnableMultiRX.Checked = true;
                else
                    chkEnableMultiRX.Checked = false;
            }

        }

        public string CATRXEQ
        {
            get
            {
                if (chkRXEQ.Checked)
                    return "1";
                else
                    return "0";
            }
            set
            {
                if (value == "1")
                    chkRXEQ.Checked = true;
                else
                    chkRXEQ.Checked = false;
            }
        }

        public string CATTXEQ
        {
            get
            {
                if (chkTXEQ.Checked)
                    return "1";
                else
                    return "0";
            }
            set
            {
                if (value == "1")
                    chkTXEQ.Checked = true;
                else
                    chkTXEQ.Checked = false;
            }
        }

        public string CATDispPeak
        {
            get
            {
                if (chkDisplayPeak.Checked)
                    return "1";
                else
                    return "0";
            }
            set
            {
                if (value == "1")
                    chkDisplayPeak.Checked = true;
                else
                    chkDisplayPeak.Checked = false;
            }

        }

        public string CATRX2DispPeak
        {
            get
            {
                if (chkRX2DisplayPeak.Checked)
                    return "1";
                else
                    return "0";
            }
            set
            {
                if (value == "1")
                    chkRX2DisplayPeak.Checked = true;
                else
                    chkRX2DisplayPeak.Checked = false;
            }

        }

        public string CATDispCenter
        {
            set
            {
                btnDisplayPanCenter.PerformClick();
            }
        }

        public string CATDispZoom
        {
            set
            {
                switch (value)
                {
                    case "0":
                        radDisplayZoom05.PerformClick();
                        break;
                    case "1":
                        radDisplayZoom1x.PerformClick();
                        break;
                    case "2":
                        radDisplayZoom2x.PerformClick();
                        break;
                    case "3":
                        radDisplayZoom4x.PerformClick();
                        break;
                    default:
                        radDisplayZoom1x.PerformClick();
                        break;
                }
            }

            get
            {
                if (radDisplayZoom05.Checked)
                    return "0";
                else if (radDisplayZoom1x.Checked)
                    return "1";
                else if (radDisplayZoom2x.Checked)
                    return "2";
                else if (radDisplayZoom4x.Checked)
                    return "3";
                else
                    return "4";
            }
        }

        public string CATZB
        {
            set
            {
                btnZeroBeat_Click(this, EventArgs.Empty);
            }
        }

        public void CATTuneStepUp()
        {
            ChangeTuneStepUp();
        }

        public void CATTuneStepDown()
        {
            ChangeTuneStepDown();
        }

        //-W2PA This specifies the number of MIDI messages that cause a single tune step increment
        // It is useful when using coarse increments, such as 100kHz, and wanting more wheel rotation for each one
        // so that tuning isn't so critical. Midi2Cat support functions follow.
        private int midi_messages_per_tune_step = 1;
        public int MidiMessagesPerTuneStep
        {
            get
            {
                return midi_messages_per_tune_step;
            }
            set
            {
                if ((value <= max_midi_messages_per_tune_step) && (value > 0))
                    midi_messages_per_tune_step = value;
            }
        }

        private int max_midi_messages_per_tune_step = 64;  // Upper limit 
        public int MaxMIDIMessagesPerTuneStep
        {
            get
            {
                return max_midi_messages_per_tune_step;
            }
            set
            {
                if (value <= 64 && value > 1)
                {
                    max_midi_messages_per_tune_step = value;
                }
            }
        }

        private int min_midi_messages_per_tune_step = 1;  // Lower limit 
        public int MinMIDIMessagesPerTuneStep
        {
            get
            {
                return min_midi_messages_per_tune_step;
            }
            set
            {
                if (value <= 9 && value > 0)
                {
                    min_midi_messages_per_tune_step = value;
                }
            }
        }

        public void CATMidiMessagesPerTuneStepUp()
        {
            int oldM = MidiMessagesPerTuneStep;
            MidiMessagesPerTuneStep = oldM * 2;
        }
        public void CATMidiMessagesPerTuneStepDown()
        {
            int oldM = MidiMessagesPerTuneStep;
            MidiMessagesPerTuneStep = oldM / 2;
        }
        public void CATMidiMessagesPerTuneStepToggle()
        {
            if (midi_messages_per_tune_step == min_midi_messages_per_tune_step)
                midi_messages_per_tune_step = max_midi_messages_per_tune_step;
            else
                midi_messages_per_tune_step = min_midi_messages_per_tune_step;
        }

        private int cat_bci_reject = 0;
        public int CATBCIReject
        {
            get
            {
                cat_bci_reject = 0;
                return cat_bci_reject;
            }
            set
            {

            }
        }

        private int cat_apf_status = 0;
        public int CATAPF
        {
            get { return cat_apf_status; }
            set
            {
                if (value == 0)
                    chkCWAPFEnabled.CheckState = CheckState.Unchecked;
                else if (value == 1)
                    chkCWAPFEnabled.CheckState = CheckState.Checked;
            }
        }

        private int cat_TTT_status = 0;
        public int CATTTTest
        {
            get
            {
                cat_TTT_status = Convert.ToInt32(SetupForm.TTgenrun);
                return cat_TTT_status;
            }
            set
            {
                if (value == 0)
                {
                    SetupForm.TTgenrun = false;
                    cat_TTT_status = 0;
                }
                else if (value == 1)
                {
                    SetupForm.TTgenrun = true;
                    cat_TTT_status = 1;
                }

            }
        }

        public void CATSingleCal()
        {
            psform.SingleCalrun();
        }

        private int cat_breakin_status = 0;
        public int CATBreakIn
        {
            get
            {
                if (chkQSK.Checked)
                    return 1;
                else
                    return 0;
            }
            set
            {
                if (value == 0)
                    chkQSK.CheckState = CheckState.Unchecked; // manual break-in
                else if (value == 1)
                    chkQSK.CheckState = CheckState.Checked; // semi break-in
            }
        }

        private int cat_qsk_breakin_status = 0;
        public int CATQSKBreakIn
        {
            get {
                if (chkQSK.CheckState == CheckState.Indeterminate)
                    return 1;
                else
                    return 0;
            }
            set
            {
                if (value == 0)
                    chkQSK.CheckState = CheckState.Checked; // semi break-in
                else if (value == 1)
                    chkQSK.CheckState = CheckState.Indeterminate; // qsk break-in
            }
        }

        private int cat_nr_status = 0;
        public int CATNR
        {
            get { return cat_nr_status; }
            set
            {
                if (value == 0)
                    chkNR.CheckState = CheckState.Unchecked;
                else if (value == 1)
                    chkNR.CheckState = CheckState.Checked;
            }
        }

        private int cat_nr2_status = 0;
        public int CATNR2
        {
            get { return cat_nr2_status; }
            set
            {
                if (value == 0)
                    chkNR.CheckState = CheckState.Unchecked;
                else if (value == 1)
                    chkNR.CheckState = CheckState.Indeterminate;
            }
        }

        private int cat_rx2_nr_status = 0;
        public int CATRX2NR
        {
            get { return cat_rx2_nr_status; }
            set
            {
                if (value == 0)
                    chkRX2NR.CheckState = CheckState.Unchecked;
                else if (value == 1)
                    chkRX2NR.CheckState = CheckState.Checked;
            }
        }

        private int cat_rx2_nr2_status = 0;
        public int CATRX2NR2
        {
            get { return cat_rx2_nr2_status; }
            set
            {
                if (value == 0)
                    chkRX2NR.CheckState = CheckState.Unchecked;
                else if (value == 1)
                    chkRX2NR.CheckState = CheckState.Indeterminate;
            }
        }


        private int cat_anf_status = 0;
        public int CATANF
        {
            get { return cat_anf_status; }
            set
            {
                if (value == 0)
                    chkANF.Checked = false;
                else if (value == 1)
                    chkANF.Checked = true;
            }
        }


        private int catrx2_anf_status = 0;
        public int CATRX2ANF
        {
            get { return catrx2_anf_status; }
            set
            {
                if (value == 0)
                    chkRX2ANF.Checked = false;
                else if (value == 1)
                    chkRX2ANF.Checked = true;
            }
        }



        private int cat_nb1_status = 0;
        public int CATNB1
        {
            get { return cat_nb1_status; }
            set
            {
                if (value == 0)
                    chkNB.CheckState = CheckState.Unchecked;
                else if (value == 1)
                    chkNB.CheckState = CheckState.Checked;
            }
        }


        private int cat_nb2_status = 0;
        public int CATNB2
        {
            get { return cat_nb2_status; }
            set
            {
                if (value == 0)
                    chkNB.CheckState = CheckState.Unchecked;
                else if (value == 1)
                    chkNB.CheckState = CheckState.Indeterminate;
            }
        }

        private int cat_rx2nb1_status = 0;
        public int CATRX2NB1
        {
            get
            {
                return cat_rx2nb1_status;

            }
            set
            {
                if (value == 0)
                    chkRX2NB.CheckState = CheckState.Unchecked;
                else if (value == 1)
                    chkRX2NB.CheckState = CheckState.Checked;
            }
        }

        private int cat_snb_status = 0;
        public int CATSNB
        {
            get { return cat_snb_status; }
            set
            {
                if (value == 0)
                    chkDSPNB2.Checked = false;
                else if (value == 1)
                    chkDSPNB2.Checked = true;
            }
        }

        private int cat_rx2snb_status = 0;
        public int CATRX2SNB
        {
            get
            {
                return cat_rx2snb_status;

            }
            set
            {
                if (value == 0)
                    chkRX2NB2.Checked = false;
                else if (value == 1)
                    chkRX2NB2.Checked = true;
            }
        }

        public int CATRX1RX2RadioButton
        {
            get
            {
                if (show_rx2)
                    return 1;
                else
                    return 0;

            }
            set
            {
                if (value == 0)                     // RX1
                    radRX1Show.Checked = true;
                else if (value == 1)                // RX2
                    radRX2Show.Checked = true;
            }
        }

        public void CATRX2BandUpDown(int direction)
        {
            comboRX2Band.Focus();

            string next = "", previous = "";
            switch (comboRX2Band.Text)
            {
                case "160m": next = "80m"; previous = "GEN"; break;
                case "80m": next = "60m"; previous = "160m"; break;
                case "60m": next = "40m"; previous = "80m"; break;
                case "40m": next = "30m"; previous = "60m"; break;
                case "30m": next = "20m"; previous = "40m"; break;
                case "20m": next = "17m"; previous = "30m"; break;
                case "17m": next = "15m"; previous = "20m"; break;
                case "15m": next = "12m"; previous = "15m"; break;
                case "12m": next = "10m"; previous = "15m"; break;
                case "10m": next = "6m"; previous = "12m"; break;
                case "6m": next = "WWV"/*"2m"*/; previous = "10m"; break;
                //case "2m": next = "WWV"; previous = "6m"; break; //MW0LGE remove 2m and this //MW0LGE21_h
                case "GEN": next = "160m"; previous = "VHF13"; break;
                case "WWV": next = "VHF0"; previous = "6m"; break;
                case "VHF0"/*"VU 2m"*/: next = "VHF1"; previous = "WWV"; break;  // remove these VU 2m/70cm MW0LGE_21h
                case "VHF1"/*"VU 70cm"*/: next = "VHF2"; previous = "VHF0"; break;
                case "VHF2": next = "VHF3"; previous = "VHF1"; break;
                case "VHF3": next = "VHF4"; previous = "VHF2"; break;
                case "VHF4": next = "VHF5"; previous = "VHF3"; break;
                case "VHF5": next = "VHF6"; previous = "VHF4"; break;
                case "VHF6": next = "VHF7"; previous = "VHF5"; break;
                case "VHF7": next = "VHF8"; previous = "VHF6"; break;
                case "VHF8": next = "VHF9"; previous = "VHF7"; break;
                case "VHF9": next = "VHF10"; previous = "VHF8"; break;
                case "VHF10": next = "VHF11"; previous = "VHF9"; break;
                case "VHF11": next = "VHF12"; previous = "VHF10"; break;
                case "VHF12": next = "VHF13"; previous = "VHF11"; break;
                case "VHF13": next = "GEN"; previous = "VHF12"; break;
            }


            if (next.StartsWith("VHF"))                                 //see if the next vhf entry is enabled
            {
                int next_ndx = Convert.ToInt32(next.Substring(3));
                if (!XVTRForm.GetEnabled(next_ndx))
                    next = "GEN";                                       //if not, go back to GEN
            }

            if (previous.StartsWith("VHF"))
            {
                int previous_ndx = Convert.ToInt32(previous.Substring(3));
                if (previous_ndx != 0)
                {
                    if (previous_ndx > 0)
                    {
                        for (int n = previous_ndx - 1; n >= 0; n--)     //find the last enabled VHF entry
                        {
                            if (XVTRForm.GetEnabled(n))
                            {
                                previous = "VHF" + n.ToString();
                                break;
                            }
                            else
                                previous = "WWV";                       //or default to the value just below the VHF selections
                        }
                    }
                    else
                        previous = "WWV";
                }
            }


            string new_band;
            if (direction == 1)
                new_band = next;
            else
                new_band = previous;


            BandStackFilter bsf = BandStackManager.GetFilter(BandStackManager.StringToBand(new_band));
            if (bsf != null)
            {
                BandStackEntry bse = bsf.First();

                //MW0LGE_21h
                if (bse == null)
                {
                    bse = bsf.LastVisited.Copy(); // in case of nothing in the filter (ie deleted everything, or no entries)
                    // at least set it to the band we want
                    bse.Band = BandStackManager.StringToBand(new_band);
                }

                if (bse != null)
                {
                    RX2DSPMode = bse.Mode;
                    RX2Filter = bse.Filter;
                    VFOBFreq = bse.Frequency;
                }
            }

            btnHidden.Focus();
        }

        private int cat_rx2nb2_status = 0;
        public int CATRX2NB2
        {
            get
            {
                return cat_rx2nb2_status;
            }
            set
            {
                if (value == 0)
                    chkRX2NB.CheckState = CheckState.Unchecked;             // edited 30/3/2018 G8NJJ to access the NB control not SNB
                else if (value == 1)
                    chkRX2NB.CheckState = CheckState.Indeterminate;         // edited 30/3/2018 G8NJJ to access the NB control not SNB
            }
        }

        private int cat_cmpd_status = 0;
        public int CATCmpd
        {
            get { return cat_cmpd_status; }
            set
            {
                if (value == 0)
                    chkCPDR.Checked = false;
                else if (value == 1)
                    chkCPDR.Checked = true;
            }
        }

        private int cat_mic_status = 0;
        public int CATMIC
        {
            get
            {
                cat_mic_status = ptbMic.Value;
                return cat_mic_status;
            }
            set
            {
                //value = Math.Max(-96, value);
                //value = Math.Min(70, value);

                //[2.10.3.6]MW0LGE fix #417
                value = Math.Max(mic_gain_min, value);
                value = Math.Min(mic_gain_max, value);
                ptbMic.Minimum = mic_gain_min;
                ptbMic.Maximum = mic_gain_max;
                //

                ptbMic.Value = value;
                ptbMic_Scroll(this, EventArgs.Empty);
                if (sliderForm != null)
                    sliderForm.MicGain = value;
            }
        }

        private int cat_filter_width = 0;
        public int CATFilterWidth
        {
            get
            {
                cat_filter_width = ptbFilterWidth.Value;
                return cat_filter_width;
            }
            set
            {
                value = Math.Max(1, value);
                value = Math.Min(10000, value);
                ptbFilterWidth.Value = value;
                ptbFilterWidth_Scroll(this.ptbFilterWidth, EventArgs.Empty);	// added
            }
        }

        public int CATFilterShift
        {
            get
            {
                return ptbFilterShift.Value;
            }
            set
            {
                value = Math.Max(-1000, value);
                value = Math.Min(1000, value);
                ptbFilterShift.Value = value;
                ptbFilterShift_Scroll(this.ptbFilterShift, EventArgs.Empty);
            }
        }

        public int CATFilterShiftReset
        {
            set
            {
                if (value == 1)
                    btnFilterShiftReset.PerformClick();
            }
        }

        private int cat_bin_status = 0;
        public int CATBIN
        {
            get
            {
                if (chkBIN.Checked)
                    cat_bin_status = 1;
                else
                    cat_bin_status = 0;

                return cat_bin_status;
            }
            set
            {
                if (value == 1)
                    chkBIN.Checked = true;
                else if (value == 0)
                    chkBIN.Checked = false;
            }
        }

        public PreampMode CATPreamp
        {
            set { RX1PreampMode = value; }
            get { return RX1PreampMode; }
        }

        public int CATCWSpeed
        {
            get
            {
                return ptbCWSpeed.Value;
            }
            set
            {
                value = Math.Max(1, value);
                value = Math.Min(60, value);
                ptbCWSpeed.Value = value;
                ptbCWSpeed_Scroll(this, EventArgs.Empty);
            }
        }

        private int cat_display_avg_status = 0;
        public int CATDisplayAvg
        {
            get
            {
                if (chkDisplayAVG.Checked)
                    cat_display_avg_status = 1;
                else
                    cat_display_avg_status = 0;

                return cat_display_avg_status;
            }
            set
            {
                if (value == 1)
                    chkDisplayAVG.Checked = true;
                else
                    chkDisplayAVG.Checked = false;
            }
        }

        private int cat_rx2display_avg_status = 0;
        public int CATRX2DisplayAvg
        {
            get
            {
                if (chkRX2DisplayAVG.Checked)
                    cat_rx2display_avg_status = 1;
                else
                    cat_rx2display_avg_status = 0;

                return cat_rx2display_avg_status;
            }
            set
            {
                if (value == 1)
                    chkRX2DisplayAVG.Checked = true;
                else
                    chkRX2DisplayAVG.Checked = false;
            }
        }

        public int CATSquelch
        {
            get
            {
                int nRet = 0;
                switch (chkSquelch.CheckState)
                {
                    case CheckState.Unchecked:
                        nRet = 0;
                        break;
                    case CheckState.Checked: //sql
                        nRet = 1;
                        break;
                    case CheckState.Indeterminate: //vsql
                        nRet = 2;
                        break;
                }
                return nRet;
            }
            set
            {
                switch (value)
                {
                    case 0: // unchecked
                        chkSquelch.CheckState = CheckState.Unchecked;
                        break;
                    case 1: // checked sql
                        chkSquelch.CheckState = CheckState.Checked;
                        break;
                    case 2: // intermediate vsql
                        chkSquelch.CheckState = CheckState.Indeterminate;
                        break;
                }
            }
        }

        public int CATSquelch2 //[2.10.3.5]MW0LGE change to an int, same as CATSquelch, why implement it differenly in the first place? boggles my mind
        {
            //[2.10.3.5]MW0LGE tri state for vsql
            get
            {
                int nRet = 0;
                switch (chkRX2Squelch.CheckState)
                {
                    case CheckState.Unchecked:
                        nRet = 0;
                        break;
                    case CheckState.Checked: //sql
                        nRet = 1;
                        break;
                    case CheckState.Indeterminate: //vsql
                        nRet = 2;
                        break;
                }
                return nRet;
            }
            set
            {
                switch (value)
                {
                    case 0: // unchecked
                        chkRX2Squelch.CheckState = CheckState.Unchecked;
                        break;
                    case 1: // checked sql
                        chkRX2Squelch.CheckState = CheckState.Checked;
                        break;
                    case 2: // intermediate vsql
                        chkRX2Squelch.CheckState = CheckState.Indeterminate;
                        break;
                }
            }
        }

        public string CATQMSValue
        {
            get { return this.txtMemoryQuick.Text; }
        }

        private Parity cat_parity;
        public Parity CATParity
        {
            set { cat_parity = value; }
            get { return cat_parity; }
        }

        private Parity cat2_parity;
        public Parity CAT2Parity
        {
            set { cat2_parity = value; }
            get { return cat2_parity; }
        }

        private Parity cat3_parity;
        public Parity CAT3Parity
        {
            set { cat3_parity = value; }
            get { return cat3_parity; }
        }

        private Parity cat4_parity;
        public Parity CAT4Parity
        {
            set { cat4_parity = value; }
            get { return cat4_parity; }
        }

        private StopBits cat_stop_bits;
        public StopBits CATStopBits
        {
            set { cat_stop_bits = value; }
            get { return cat_stop_bits; }
        }

        private StopBits cat2_stop_bits;
        public StopBits CAT2StopBits
        {
            set { cat2_stop_bits = value; }
            get { return cat2_stop_bits; }
        }

        private StopBits cat3_stop_bits;
        public StopBits CAT3StopBits
        {
            set { cat3_stop_bits = value; }
            get { return cat3_stop_bits; }
        }

        private StopBits cat4_stop_bits;
        public StopBits CAT4StopBits
        {
            set { cat4_stop_bits = value; }
            get { return cat4_stop_bits; }
        }

        private int cat_data_bits;
        public int CATDataBits
        {
            set { cat_data_bits = value; }
            get { return cat_data_bits; }
        }

        private int cat2_data_bits;
        public int CAT2DataBits
        {
            set { cat2_data_bits = value; }
            get { return cat2_data_bits; }
        }

        private int cat3_data_bits;
        public int CAT3DataBits
        {
            set { cat3_data_bits = value; }
            get { return cat3_data_bits; }
        }

        private int cat4_data_bits;
        public int CAT4DataBits
        {
            set { cat4_data_bits = value; }
            get { return cat4_data_bits; }
        }

        private int cat_baud_rate;
        public int CATBaudRate
        {
            set { cat_baud_rate = value; }
            get { return cat_baud_rate; }
        }

        private int cat2_baud_rate;
        public int CAT2BaudRate
        {
            set { cat2_baud_rate = value; }
            get { return cat2_baud_rate; }
        }

        private int cat3_baud_rate;
        public int CAT3BaudRate
        {
            set { cat3_baud_rate = value; }
            get { return cat3_baud_rate; }
        }

        private int cat4_baud_rate;
        public int CAT4BaudRate
        {
            set { cat4_baud_rate = value; }
            get { return cat_baud_rate; }
        }

        private bool cat_enabled;
        public bool CATEnabled
        {
            set
            {
                try
                {
                    cat_enabled = value;
                    if (Siolisten != null)  // if we've got a listener tell them about state change 
                    {
                        if (cat_enabled)
                        {
                            Siolisten.enableCAT();
                        }
                        else
                        {
                            Siolisten.disableCAT();
                        }
                    }
                }
                catch (Exception)
                {
                    MessageBox.Show("Error enabling CAT on COM" + cat_port + ".\n" +
                        "Please check CAT settings and try again.",
                        "CAT Error",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                    if (!IsSetupFormNull) SetupForm.CATEnabled = false;
                }
            }
            get { return cat_enabled; }
        }

        // property set when An Andromeda panel is connected via a serial CAT port.
        // NOT used for G2 panel accessed via TCP/IP
        private bool andromeda_cat_enabled;
        public bool AndromedaCATEnabled
        {
            set
            {
                try
                {
                    andromeda_cat_enabled = value;
                    if (value) NetworkIO.ATU_Tune(1); // set default state for J16 pin 10 to high when Andromeda is enabled
                    else NetworkIO.ATU_Tune(0);
                    if (AndromedaSiolisten != null)  // if we've got a listener tell them about state change
                    {
                        if (andromeda_cat_enabled)
                        {
                            AndromedaSiolisten.enableCAT5();
                            InitialiseAndromedaIndicators(true);           // initialise the panel LEDs
                            toolStripStatusLabelAndromedaMulti.Visible = true;
                        }
                        else
                        {
                            AndromedaSiolisten.disableCAT5();
                        }
                    }
                }
                catch (Exception)
                {
                    MessageBox.Show("Error enabling Andromeda on COM" + cat_port + ".\n" +
                        "Please check settings and try again.",
                        "Andromeda CAT Error",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                    if (!IsSetupFormNull)
                    {
                        if (!andromeda_g2_enabled)
                            SetupForm.AndromedaCATEnabled = false;
                    }
                }
            }
            get { return andromeda_cat_enabled; }
        }


        private bool aries_cat_enabled; // ATU
        public bool AriesCATEnabled
        {
            set
            {
                try
                {
                    aries_cat_enabled = value;
                    if (AriesSiolisten != null)  // if we've got a listener tell them about state change
                    {
                        if (aries_cat_enabled)
                        {
                            AriesSiolisten.enableCAT6();
                            InitialiseAries();

                        }
                        else
                        {
                            AriesSiolisten.disableCAT6();
                        }
                    }
                }
                catch (Exception)
                {
                    MessageBox.Show("Error enabling Aries on COM" + cat_port + ".\n" +
                        "Please check settings and try again.",
                        "Aries CAT Error",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                    if (!IsSetupFormNull) SetupForm.AriesCATEnabled = false;
                }
            }
            get { return aries_cat_enabled; }
        }

        private bool ganymede_cat_enabled; // amplifier
        public bool GanymedeCATEnabled
        {
            set
            {
                try
                {
                    ganymede_cat_enabled = value;
                    if (GanymedeSiolisten != null)  // if we've got a listener tell them about state change
                    {
                        if (ganymede_cat_enabled)
                        {
                            GanymedeSiolisten.enableCAT7();
                            MakeGanymedeVersionRequestMsg();
                            MakeGanymedeStatusRequestMsg();
                        }
                        else
                        {
                            GanymedeSiolisten.disableCAT7();
                        }
                    }
                }
                catch (Exception)
                {
                    MessageBox.Show("Error enabling Ganymede on COM" + cat_port + ".\n" +
                        "Please check settings and try again.",
                        "Ganymede CAT Error",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                    if (!IsSetupFormNull) SetupForm.GanymedeCATEnabled = false;
                }
            }
            get { return ganymede_cat_enabled; }
        }

        private bool cat2_enabled;
        public bool CAT2Enabled
        {
            set
            {
                try
                {
                    cat2_enabled = value;
                    if (Sio2listen != null)  // if we've got a listener tell them about state change 
                    {
                        if (cat2_enabled)
                        {
                            Sio2listen.enableCAT2();
                        }
                        else
                        {
                            Sio2listen.disableCAT2();
                        }
                    }
                }
                catch (Exception)
                {
                    MessageBox.Show("Error enabling CAT2 on COM" + cat_port + ".\n" +
                        "Please check CAT2 settings and try again.",
                        "CAT2 Error",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                    if (!IsSetupFormNull) SetupForm.CAT2Enabled = false;
                }
            }
            get { return cat2_enabled; }
        }

        private bool cat3_enabled;
        public bool CAT3Enabled
        {
            set
            {
                try
                {
                    cat3_enabled = value;
                    if (Sio3listen != null)  // if we've got a listener tell them about state change 
                    {
                        if (cat3_enabled)
                        {
                            Sio3listen.enableCAT3();
                        }
                        else
                        {
                            Sio3listen.disableCAT3();
                        }
                    }
                }
                catch (Exception)
                {
                    MessageBox.Show("Error enabling CAT3 on COM" + cat_port + ".\n" +
                        "Please check CAT3 settings and try again.",
                        "CAT3 Error",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                    if (!IsSetupFormNull) SetupForm.CAT3Enabled = false;
                }
            }
            get { return cat3_enabled; }
        }

        private bool cat4_enabled;
        public bool CAT4Enabled
        {
            set
            {
                try
                {
                    cat4_enabled = value;
                    if (Sio4listen != null)  // if we've got a listener tell them about state change 
                    {
                        if (cat4_enabled)
                        {
                            Sio4listen.enableCAT4();
                        }
                        else
                        {
                            Sio4listen.disableCAT4();
                        }
                    }
                }
                catch (Exception)
                {
                    MessageBox.Show("Error enabling CAT4 on COM" + cat_port + ".\n" +
                        "Please check CAT4 settings and try again.",
                        "CAT4 Error",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                    if (!IsSetupFormNull) SetupForm.CAT4Enabled = false;
                }
            }
            get { return cat4_enabled; }
        }

        private int cat_rig_type;
        public int CATRigType
        {
            get { return cat_rig_type; }
            set { cat_rig_type = value; }
        }

        private int cat_port;
        public int CATPort
        {
            get { return cat_port; }
            set { cat_port = value; }
        }

        private int cat2_port;
        public int CAT2Port
        {
            get { return cat2_port; }
            set { cat2_port = value; }
        }

        private int cat3_port;
        public int CAT3Port
        {
            get { return cat3_port; }
            set { cat3_port = value; }
        }

        private int cat4_port;
        public int CAT4Port
        {
            get { return cat4_port; }
            set { cat4_port = value; }
        }

        private int andromeda_cat_port;
        public int AndromedaCATPort
        {
            get { return andromeda_cat_port; }
            set { andromeda_cat_port = value; }
        }

        private int aries_cat_port;
        public int AriesCATPort
        {
            get { return aries_cat_port; }
            set { aries_cat_port = value; }
        }
        private int ganymede_cat_port;
        public int GanymedeCATPort
        {
            get { return ganymede_cat_port; }
            set { ganymede_cat_port = value; }
        }

        private bool cat_ptt_rts = false;
        public bool CATPTTRTS
        {
            get { return cat_ptt_rts; }
            set { cat_ptt_rts = value; }
        }

        private bool cat_ptt_dtr;
        public bool CATPTTDTR
        {
            get { return cat_ptt_dtr; }
            set { cat_ptt_dtr = value; }
        }

        public SerialPortPTT serialPTT = null;
        private bool ptt_bit_bang_enabled;
        public bool PTTBitBangEnabled
        {
            get { return ptt_bit_bang_enabled; }
            set
            {
                ptt_bit_bang_enabled = value;
                if (serialPTT != null)  // kill current serial PTT if we have one 
                {
                    serialPTT.Destroy();
                    serialPTT = null;
                }
                if (ptt_bit_bang_enabled)
                {
                    // wjt -- don't really like popping a msg box in here ...   nasty when we do a remoted 
                    // setup ... will let that wait for the great console refactoring 
                    try
                    {
                        serialPTT = new SerialPortPTT(cat_ptt_bit_bang_port, cat_ptt_rts, cat_ptt_dtr);
                        serialPTT.Init();
                    }
                    catch (Exception ex)
                    {
                        ptt_bit_bang_enabled = false;
                        if (!IsSetupFormNull)
                        {
                            SetupForm.copyCATPropsToDialogVars(); // need to make sure the props on the setup page get reset 
                        }
                        MessageBox.Show("Could not initialize PTT Bit Bang control.  Exception was:\n\n " + ex.Message +
                            "\n\nPTT Bit Bang control has been disabled.", "Error Initializing PTT control",
                            MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);

                    }
                }
            }
        }

        private int cat_ptt_bit_bang_port;
        public int CATPTTBitBangPort
        {
            get { return cat_ptt_bit_bang_port; }
            set { cat_ptt_bit_bang_port = value; }
        }


        #endregion

        private int tune_power;								// power setting to use when TUN button is pressed
        public int TunePower
        {
            get { return tune_power; }
            set
            {
                tune_power = value;
                if (!IsSetupFormNull)
                    SetupForm.FixedTunePower = tune_power;

                if (chkTUN.Checked)
                    PWR = tune_power;
            }
        }
        private int twotone_tune_power; //MW0LGE_22b
        public int TwoToneTunePower
        {
            get { return twotone_tune_power; }
            set
            {
                twotone_tune_power = value;
                if (!IsSetupFormNull)
                    SetupForm.TwoTonePower = twotone_tune_power;

                if (chk2TONE.Checked)
                    PWR = twotone_tune_power;
            }
        }

        private int previous_pwr = 50;
        public int PreviousPWR
        {
            get { return previous_pwr; }
            set { previous_pwr = value; }
        }

        #region CAT Properties
        private Band rx1_band;
        public Band RX1Band
        {
            get { return rx1_band; }
            set
            {
                //[2.10.3.6]MW0LGE no band change on TX fix
                if (MOX && (VFOATX || (!rx2_enabled && VFOBTX))) return;

                Band old_band = rx1_band;
                rx1_band = value;

                Band lo_band = Band.FIRST;
                if (rx1_xvtr_index >= 0)
                    // Fix Penny O/C VHF control Vk4xv
                    lo_band = BandByFreq(XVTRForm.TranslateFreq(VFOAFreq), rx1_xvtr_index, current_region);

                if (!initializing && rx1_preamp_mode > PreampMode.FIRST)
                {
                    rx1_preamp_by_band[(int)old_band] = rx1_preamp_mode;
                    setRX1stepAttenuatorForBand(old_band, rx1_attenuator_data);
                }

                if (rx1_band != old_band || initializing)
                {
                    // save values for old band
                    rx1_agcm_by_band[(int)old_band] = (AGCMode)comboAGC.SelectedIndex;
                    rx1_agct_by_band[(int)old_band] = ptbRF.Value;
                    SetupForm.ATTOnTX = getTXstepAttenuatorForBand(tx_band); //[2.10.3.6]MW0LGE att_fixes
                    RX1PreampMode = rx1_preamp_by_band[(int)rx1_band];
                    RX1AttenuatorData = getRX1stepAttenuatorForBand(rx1_band);
                    //[2.10.3.6]MW0LGE this tmp is needed because RX1AGCMode causes an update to the setup form
                    //with the current max value for AGC (depending on agcmode) if the agcmode selected index changes
                    //which in turn sets RF again
                    int tmp = rx1_agct_by_band[(int)rx1_band];
                    RX1AGCMode = rx1_agcm_by_band[(int)rx1_band];
                    RF = tmp;

                    //================================================================================           
                    // ke9ns ADD for use by scanner so it knows which band button your on currently
                    // MW0LGE_21a moved all to scancontrol where it should be.
                    if (ScanForm != null) ScanForm.BandChanged(rx1_band);
                    //============================================================== ke9ns end

                }
                DisplayAriesRXAntenna();

                //MW0LGE_21b
                if (old_band != rx1_band)
                {
                    BandChangeHandlers?.Invoke(1, old_band, rx1_band);
                }
                else
                {
                    BandNoChangeHandlers?.Invoke(1, rx1_band);
                }
            }
        }

        private string BandToString(Band b)
        {
            string ret = "GEN";
            switch (b)
            {
                case Band.GEN: ret = "GEN"; break;
                case Band.B160M: ret = "160m"; break;
                case Band.B80M: ret = "80m"; break;
                case Band.B60M: ret = "60m"; break;
                case Band.B40M: ret = "40m"; break;
                case Band.B30M: ret = "30m"; break;
                case Band.B20M: ret = "20m"; break;
                case Band.B17M: ret = "17m"; break;
                case Band.B15M: ret = "15m"; break;
                case Band.B12M: ret = "12m"; break;
                case Band.B10M: ret = "10m"; break;
                case Band.B6M: ret = "6m"; break;
                case Band.B2M: ret = "2m"; break;
                case Band.WWV: ret = "WWV"; break;
                case Band.BLMF: ret = "LMF"; break;  // ke9ns add
                case Band.B120M: ret = "120m"; break;
                case Band.B90M: ret = "90m"; break;
                case Band.B61M: ret = "61m"; break;
                case Band.B49M: ret = "49m"; break;
                case Band.B41M: ret = "41m"; break;
                case Band.B31M: ret = "31m"; break;
                case Band.B25M: ret = "25m"; break;
                case Band.B22M: ret = "22m"; break;
                case Band.B19M: ret = "19m"; break;
                case Band.B16M: ret = "16m"; break;
                case Band.B14M: ret = "14m"; break;
                case Band.B13M: ret = "13m"; break;
                case Band.B11M: ret = "11m"; break;
                case Band.VHF0: ret = "VHF0"; break; //"VU 2m"; break; //MW0LGE_21h get rid of these VU 2m and 70cms
                case Band.VHF1: ret = "VHF1"; break; //"VU 70cm"; break;
                case Band.VHF2: ret = "VHF2"; break;
                case Band.VHF3: ret = "VHF3"; break;
                case Band.VHF4: ret = "VHF4"; break;
                case Band.VHF5: ret = "VHF5"; break;
                case Band.VHF6: ret = "VHF6"; break;
                case Band.VHF7: ret = "VHF7"; break;
                case Band.VHF8: ret = "VHF8"; break;
                case Band.VHF9: ret = "VHF9"; break;
                case Band.VHF10: ret = "VHF10"; break;
                case Band.VHF11: ret = "VHF11"; break;
                case Band.VHF12: ret = "VHF12"; break;
                case Band.VHF13: ret = "VHF13"; break;
                default: ret = "GEN"; break;
            }

            return ret;
        }

        private Band StringToBand(string s)
        {
            Band b = Band.GEN;
            switch (s)
            {
                case "GEN": b = Band.GEN; break;
                case "160m": b = Band.B160M; break;
                case "80m": b = Band.B80M; break;
                case "60m": b = Band.B60M; break;
                case "40m": b = Band.B40M; break;
                case "20m": b = Band.B20M; break;
                case "17m": b = Band.B17M; break;
                case "15m": b = Band.B15M; break;
                case "12m": b = Band.B12M; break;
                case "10m": b = Band.B10M; break;
                case "6m": b = Band.B6M; break;
                case "2m": b = Band.B2M; break;
                case "WWV": b = Band.WWV; break;
                case "LMF": b = Band.BLMF; break; // ke9ns add
                case "120m": b = Band.B120M; break;
                case "90m": b = Band.B90M; break;
                case "61m": b = Band.B61M; break;
                case "49m": b = Band.B49M; break;
                case "41m": b = Band.B41M; break;
                case "31m": b = Band.B31M; break;
                case "25m": b = Band.B25M; break;
                case "22m": b = Band.B22M; break;
                case "19m": b = Band.B19M; break;
                case "16m": b = Band.B16M; break;
                case "14m": b = Band.B14M; break;
                case "13m": b = Band.B13M; break;
                case "11m": b = Band.B11M; break;

                case "VHF0"/*"VU 2m"*/: b = Band.VHF0; break;// remove these VU 2m/70cm MW0LGE_21h
                case "VHF1"/*"VU 70cm"*/: b = Band.VHF1; break;
                case "VHF2": b = Band.VHF2; break;
                case "VHF3": b = Band.VHF3; break;
                case "VHF4": b = Band.VHF4; break;
                case "VHF5": b = Band.VHF5; break;
                case "VHF6": b = Band.VHF6; break;
                case "VHF7": b = Band.VHF7; break;
                case "VHF8": b = Band.VHF8; break;
                case "VHF9": b = Band.VHF9; break;
                case "VHF10": b = Band.VHF10; break;
                case "VHF11": b = Band.VHF11; break;
                case "VHF12": b = Band.VHF12; break;
                case "VHF13": b = Band.VHF13; break;
            }

            return b;
        }

        private Band rx2_band;
        public Band RX2Band
        {
            get { return rx2_band; }
            set
            {
                //[2.10.3.6]MW0LGE no band change on TX fix
                if (MOX && VFOBTX) return;

                Band old_band = rx2_band;
                rx2_band = value;

                //MW0LGE
                // not all bands are in the drop down, and consequently solution above caused
                // all sorts of issues when for example dragging RX2 outside HAM bands
                string sBand = BandToString(rx2_band);
                if (comboRX2Band.Items.Contains(sBand))
                {
                    comboRX2Band.Text = sBand;
                }

                Band lo_band = Band.FIRST;
                if (rx2_xvtr_index >= 0)
                    lo_band = BandByFreq(XVTRForm.TranslateFreq(VFOBFreq), rx2_xvtr_index, current_region);//MW0LGE use rx2_xvtr_index
                                                                                                           //MW0LGE this was changed in RX1Band but not here

                if (!initializing && rx2_preamp_mode > PreampMode.FIRST)
                {
                    rx2_preamp_by_band[(int)old_band] = rx2_preamp_mode;
                    setRX2stepAttenuatorForBand(old_band, rx2_attenuator_data);
                }

                if (rx2_band != old_band || initializing)
                {
                    // save values for old band
                    rx2_agcm_by_band[(int)old_band] = (AGCMode)comboRX2AGC.SelectedIndex;
                    rx2_agct_by_band[(int)old_band] = ptbRX2RF.Value;

                    RX2PreampMode = rx2_preamp_by_band[(int)rx2_band];
                    RX2AttenuatorData = getRX2stepAttenuatorForBand(rx2_band);
                    int tmp = rx2_agct_by_band[(int)rx2_band]; //[2.10.3.6]MW0LGE see comment in RX1Band
                    RX2AGCMode = rx2_agcm_by_band[(int)rx2_band];
                    RX2RF = tmp;

                    repopulateForms();

                    //MW0LGE_21b
                    if (old_band != rx2_band)
                    {
                        BandChangeHandlers?.Invoke(2, old_band, rx2_band);
                    }
                    else
                    {
                        BandNoChangeHandlers?.Invoke(2, rx2_band);
                    }
                }
            }
        }

        private Band tx_band;
        public Band TXBand
        {
            get { return tx_band; }
            set
            {
                //[2.10.3.6]MW0LGE no band change on TX fix
                if (MOX) return;

                Band old_band = tx_band;
                if (initializing) old_band = value; // we cant use tx_band, because it is unset (GEN), unless we save it out it is irrelevant MW0LGE

                tx_band = value;

                Band lo_band = Band.FIRST;
                if (tx_xvtr_index >= 0)
                    // Fix Penny O/C VHF control Vk4xv
                    lo_band = BandByFreq(XVTRForm.TranslateFreq(VFOAFreq), rx1_xvtr_index, current_region);

                if (tx_band != old_band || initializing)
                {
                    // save values for old band
                    int old_pwr = ptbPWR.Value;
                    if (initializing) old_pwr = power_by_band[(int)old_band]; // we cant use what is set on the trackbar if we are
                                                                              // initialisting, becase it is irrelevent, old_band will = value at this point MW0LGE

                    power_by_band[(int)old_band] = old_pwr;

                    ptbPWR.LimitValue = limitPower_by_band[(int)value];
                    ptbTune.LimitValue = limitTunePower_by_band[(int)value]; //MW0LGE_22b

                    PWR = power_by_band[(int)value];
                    TunePWR = tunePower_by_band[(int)value]; //MW0LGE_22b

                    // save FM TX Offset
                    if (!initializing)
                    {
                        fm_tx_offset_by_band_mhz[(int)old_band] = fm_tx_offset_mhz;
                    }
                    FMTXOffsetMHz = fm_tx_offset_by_band_mhz[(int)value]; //MW0LGE_21k9
                }

                if (old_band != Band.B60M && !initializing)
                {
                    SetupForm.TXFilterHighSave = tx_filter_high;
                    SetupForm.TXFilterLowSave = tx_filter_low;
                }

                if (tx_band == Band.B60M)
                {
                    if (tx_filter_high > 2900)
                        SetupForm.TXFilterHigh = 2900;
                    if (tx_filter_low < 100)
                        SetupForm.TXFilterLow = 100;
                }

                if (tx_band != old_band || initializing)
                {
                    if (old_band == Band.B60M)
                    {
                        if (tx_filter_high != SetupForm.TXFilterHighSave)
                            SetupForm.TXFilterHigh = SetupForm.TXFilterHighSave;
                        if (tx_filter_low != SetupForm.TXFilterLowSave)
                            SetupForm.TXFilterLow = SetupForm.TXFilterLowSave;
                    }
                }
                DisplayAriesTXAntenna();

                if (tx_band != old_band) TXBandChangeHandlers?.Invoke(old_band, tx_band, TXFreq); //MW0LGE_22b
            }
        }

        // Added 06/24/05 BT for CAT commands
        public bool CATVFOLock
        {
            get { return chkVFOLock.Checked; }
            set
            {
                //[2.10.3.5]MW0LGE has to be a joke, just dupe code why not
                VFOALock = value;

                //chkVFOLock.Checked = value;
                //if (value == true)
                //    lblLockLabel.BackColor = System.Drawing.Color.Blue;
                //else
                //    lblLockLabel.BackColor = System.Drawing.Color.Transparent;
            }
        }

        public bool CATVFOBLock
        {
            get { return chkVFOBLock.Checked; }
            set
            {
                //[2.10.3.5]MW0LGE has to be a joke, just dupe code why not
                VFOBLock = value;

                //chkVFOBLock.Checked = value;
                //if (value == true)
                //    lblRX2LockLabel.BackColor = System.Drawing.Color.Blue;
                //else
                //    lblRX2LockLabel.BackColor = System.Drawing.Color.Transparent;
            }
        }

        // Added 07/30/05 BT for cat commands next 8 functions
        public string CATReadSigStrength()
        {
            float num = 0f;
            float rx1PreampOffset = 0.0f;

            if (rx1_step_att_present) rx1PreampOffset = (float)rx1_attenuator_data;
            else rx1PreampOffset = rx1_preamp_offset[(int)rx1_preamp_mode];

            num = WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.SIGNAL_STRENGTH);
            num = num +
                rx1_meter_cal_offset +
                rx1PreampOffset +
                rx1_xvtr_gain_offset;
            return num.ToString("f1") + " dBm";
        }

        public string CATReadAvgStrength()
        {
            float num = 0f;
            num = WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.AVG_SIGNAL_STRENGTH);
            num = num +
                rx1_meter_cal_offset +
                rx1_preamp_offset[(int)rx1_preamp_mode] +
                rx1_path_offset +
                rx1_xvtr_gain_offset;
            return num.ToString("f1") + " dBm";
        }

        public string CATReadADC_L()
        {
            float num = 0f;
            num = WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.ADC_REAL);
            return num.ToString("f1") + " dBFS";
        }

        public string CATReadADC_R()
        {
            float num = 0f;
            num = WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.ADC_IMAG);
            return num.ToString("f1") + " dBFS";
        }

        public string CATReadALC()
        {
            float num = 0f;

            if (Audio.CurrentAudioState1 == Audio.AudioState.DTTSP)
            {
                num = (float)Math.Max(-20.0, -WDSP.CalculateTXMeter(0, WDSP.MeterType.ALC));
                return num.ToString("f1") + " dB";
            }
            else return "0" + separator + "0 dB";
        }

        public string CATReadFwdPwr()
        {
            double power = 0.0;

            if (alexpresent)
            {
                power = calfwdpower;

                return power.ToString("f0") + " W";
            }
            else
            {
                return "0" + separator + "00 W";
            }
        }

        public string CATReadPeakPwr()
        {
            float num = 0f;
            if (alexpresent)
            {
                if (Audio.CurrentAudioState1 == Audio.AudioState.DTTSP)
                {
                    num = (float)Math.Max(0.0, WDSP.CalculateTXMeter(0, WDSP.MeterType.ALC));
                    num *= (float)ptbPWR.Value;

                    meter_text_history[meter_text_history_index] = num;
                    meter_text_history_index = (meter_text_history_index + 1) % multimeter_text_peak_samples;
                    float max = float.MinValue;
                    for (int i = 0; i < multimeter_text_peak_samples; i++)
                    {
                        if (meter_text_history[i] > max)
                            max = meter_text_history[i];
                    }
                    num = max;

                    return num.ToString("f0") + " W";
                }
                else return "0 W";
            }
            else
            {
                if (Audio.CurrentAudioState1 == Audio.AudioState.DTTSP)
                {
                    num = (float)Math.Max(0.0, WDSP.CalculateTXMeter(0, WDSP.MeterType.ALC));
                    num *= (float)((float)ptbPWR.Value * 0.01);
                    return num.ToString("f2") + " W";
                }
                else return "0" + separator + "00 W";
            }
        }

        public string CATReadRevPwr()
        {
            double power = 0.0;
            power = alex_rev;
            return power.ToString("f0") + " W";
        }

        public string CATReadSWR()
        {
            double swr = 1.0;
            swr = alex_swr;
            return swr.ToString("f1") + " : 1";
        }

        //*************end of 8 functions.

        //=======================================================================================
        // ke9ns add
        public int ReadAvgStrength(uint sub)
        {
            float num = 0f;
            num = WDSP.CalculateRXMeter(0, sub, WDSP.MeterType.AVG_SIGNAL_STRENGTH);
            num = num +
                rx1_meter_cal_offset +
                rx1_preamp_offset[(int)rx1_preamp_mode] +
                rx1_path_offset +
                rx1_xvtr_gain_offset;
            return (int)num;
        }

        //=======================================================================================
        // ke9ns add
        public int ReadStrength(uint sub)
        {
            float num = 0f;
            num = WDSP.CalculateRXMeter(0, sub, WDSP.MeterType.SIGNAL_STRENGTH);
            num = num +
                rx1_meter_cal_offset +
                rx1_preamp_offset[(int)rx1_preamp_mode] +
                rx1_path_offset +
                rx1_xvtr_gain_offset;
            return (int)num;

        }

        public int WWVTone = 0;                             // Magnetude of the Tone received in audio.cs routine
        public bool WWVReady = false;                       // let you know when a new magnetude is updated
        private bool kw_auto_information = false;
        public bool KWAutoInformation
        {
            get { return kw_auto_information; }
            set { kw_auto_information = value; }
        }

        #endregion

        private DSPMode rx1_dsp_mode = DSPMode.FIRST;
        public DSPMode RX1DSPMode
        {
            get { return rx1_dsp_mode; }
            set
            {
                //[2.10.3.6]MW0LGE no mode change on TX fix
                if (MOX && (VFOATX || (!rx2_enabled && VFOBTX))) return;

                RadioButtonTS r = null;
                switch (value)
                {
                    case DSPMode.LSB:
                        r = radModeLSB;
                        break;
                    case DSPMode.USB:
                        r = radModeUSB;
                        break;
                    case DSPMode.DSB:
                        r = radModeDSB;
                        break;
                    case DSPMode.CWL:
                        r = radModeCWL;
                        break;
                    case DSPMode.CWU:
                        r = radModeCWU;
                        break;
                    case DSPMode.FM:
                        r = radModeFMN;
                        break;
                    case DSPMode.AM:
                        r = radModeAM;
                        break;
                    case DSPMode.SAM:
                        r = radModeSAM;
                        break;
                    case DSPMode.SPEC:
                        r = radModeSPEC;
                        break;
                    case DSPMode.DIGL:
                        r = radModeDIGL;
                        break;
                    case DSPMode.DIGU:
                        r = radModeDIGU;
                        break;
                    case DSPMode.DRM:
                        r = radModeDRM;
                        break;
                }
                r.Checked = true;

                if (modePopupForm != null) modePopupForm.RepopulateForm();
                if (filterPopupForm != null) filterPopupForm.RepopulateForm();
            }
        }

        private DSPMode rx2_dsp_mode = DSPMode.FIRST;
        public DSPMode RX2DSPMode
        {
            get { return rx2_dsp_mode; }
            set
            {
                //[2.10.3.6]MW0LGE no mode change on TX fix
                if (MOX && VFOBTX && rx2_enabled) return;

                RadioButtonTS r = null;
                switch (value)
                {
                    case DSPMode.LSB:
                        r = radRX2ModeLSB;
                        break;
                    case DSPMode.USB:
                        r = radRX2ModeUSB;
                        break;
                    case DSPMode.DSB:
                        r = radRX2ModeDSB;
                        break;
                    case DSPMode.CWL:
                        r = radRX2ModeCWL;
                        break;
                    case DSPMode.CWU:
                        r = radRX2ModeCWU;
                        break;
                    case DSPMode.FM:
                        r = radRX2ModeFMN;
                        break;
                    case DSPMode.AM:
                        r = radRX2ModeAM;
                        break;
                    case DSPMode.SAM:
                        r = radRX2ModeSAM;
                        break;
                    case DSPMode.DIGL:
                        r = radRX2ModeDIGL;
                        break;
                    case DSPMode.DIGU:
                        r = radRX2ModeDIGU;
                        break;
                    case DSPMode.DRM:
                        r = radRX2ModeDRM;
                        break;
                }

                r.Checked = true;
                if (modePopupForm != null) modePopupForm.RepopulateForm();
                if (filterPopupForm != null) filterPopupForm.RepopulateForm();
            }
        }

        private Filter rx1_filter = Filter.FIRST;
        public Filter RX1Filter
        {
            get { return rx1_filter; }
            set
            {
                RadioButtonTS r = null;
                switch (value)
                {
                    case Filter.F1:
                        r = radFilter1;
                        break;
                    case Filter.F2:
                        r = radFilter2;
                        break;
                    case Filter.F3:
                        r = radFilter3;
                        break;
                    case Filter.F4:
                        r = radFilter4;
                        break;
                    case Filter.F5:
                        r = radFilter5;
                        break;
                    case Filter.F6:
                        r = radFilter6;
                        break;
                    case Filter.F7:
                        r = radFilter7;
                        break;
                    case Filter.F8:
                        r = radFilter8;
                        break;
                    case Filter.F9:
                        r = radFilter9;
                        break;
                    case Filter.F10:
                        r = radFilter10;
                        break;
                    case Filter.VAR1:
                        r = radFilterVar1;
                        break;
                    case Filter.VAR2:
                        r = radFilterVar2;
                        break;
                    case Filter.NONE:
                        SetRX1Filter(Filter.NONE);
                        break;
                }

                if (r != null)
                {
                    if (r.Checked)
                    {
                        r.Checked = false;
                    }

                    r.Checked = true;
                }

                // commented as changed order in CATCommands.cs should no longer require this
                if (filterPopupForm != null) filterPopupForm.RepopulateForm();
            }
        }

        private Filter rx2_filter = Filter.FIRST;
        public Filter RX2Filter
        {
            get { return rx2_filter; }
            set
            {
                RadioButtonTS r = null;
                switch (value)
                {
                    case Filter.F1:
                        r = radRX2Filter1;
                        break;
                    case Filter.F2:
                        r = radRX2Filter2;
                        break;
                    case Filter.F3:
                        r = radRX2Filter3;
                        break;
                    case Filter.F4:
                        r = radRX2Filter4;
                        break;
                    case Filter.F5:
                        r = radRX2Filter5;
                        break;
                    case Filter.F6:
                        r = radRX2Filter6;
                        break;
                    case Filter.F7:
                        r = radRX2Filter7;
                        break;
                    case Filter.VAR1:
                        r = radRX2FilterVar1;
                        break;
                    case Filter.VAR2:
                        r = radRX2FilterVar2;
                        break;
                    case Filter.NONE:
                        SetRX2Filter(Filter.NONE);
                        break;
                }

                if (r != null)
                {
                    if (r.Checked)
                    {
                        r.Checked = false;
                    }

                    r.Checked = true;
                }

                // commented as changed order in CATCommands.cs should no longer require this
                if (filterPopupForm != null) filterPopupForm.RepopulateForm();
            }
        }

        public String CurrentMeterRXModeText
        {
            get { return comboMeterRXMode.Text; }
            set
            {
                comboMeterRXMode.Text = value;
                UpdateButtonBarButtons();
            }
        }

        private MeterRXMode current_meter_rx_mode = MeterRXMode.SIGNAL_STRENGTH;
        public MeterRXMode CurrentMeterRXMode
        {
            get { return current_meter_rx_mode; }
            set
            {
                string text = "";
                switch (value)
                {
                    case MeterRXMode.SIGNAL_STRENGTH:
                        text = "Signal";
                        break;
                    case MeterRXMode.SIGNAL_AVERAGE:
                        text = "Sig Avg";
                        break;
                    case MeterRXMode.ADC_L:
                        text = "ADC L";
                        break;
                    case MeterRXMode.ADC_R:
                        text = "ADC R";
                        break;
                    case MeterRXMode.ADC2_L:
                        text = "ADC2 L";
                        break;
                    case MeterRXMode.ADC2_R:
                        text = "ADC2 R";
                        break;
                    case MeterRXMode.OFF:
                        text = "Off";
                        break;
                }

                if (string.IsNullOrEmpty(text)) return;

                comboMeterRXMode.Text = text;
            }
        }

        public ComboBox.ObjectCollection MeterRXModeItems
        {
            get { return comboMeterRXMode.Items; }
        }

        public String RX2MeterModeText
        {
            get { return comboRX2MeterMode.Text; }
            set
            {
                comboRX2MeterMode.Text = value;
                UpdateButtonBarButtons();
            }
        }


        private MeterRXMode rx2_meter_mode = MeterRXMode.SIGNAL_STRENGTH;
        public MeterRXMode RX2MeterMode
        {
            get { return rx2_meter_mode; }
            set
            {
                string text = "";
                switch (value)
                {
                    case MeterRXMode.SIGNAL_STRENGTH:
                        text = "Signal";
                        break;
                    case MeterRXMode.SIGNAL_AVERAGE:
                        text = "Sig Avg";
                        break;
                    case MeterRXMode.ADC_L:
                        text = "ADC L";
                        break;
                    case MeterRXMode.ADC_R:
                        text = "ADC R";
                        break;
                    case MeterRXMode.ADC2_L:
                        text = "ADC2 L";
                        break;
                    case MeterRXMode.ADC2_R:
                        text = "ADC2 R";
                        break;
                    case MeterRXMode.OFF:
                        text = "Off";
                        break;
                }

                if (string.IsNullOrEmpty(text)) return;

                comboRX2MeterMode.Text = text;
            }
        }

        public ComboBox.ObjectCollection RX2MeterModeItems
        {
            get { return comboRX2MeterMode.Items; }
        }

        public String CurrentMeterTXModeText
        {
            get { return comboMeterTXMode.Text; }
            set
            {
                comboMeterTXMode.Text = value;
                UpdateButtonBarButtons();
            }
        }

        private MeterTXMode current_meter_tx_mode = MeterTXMode.FORWARD_POWER;
        public MeterTXMode CurrentMeterTXMode
        {
            get { return current_meter_tx_mode; }
            set
            {
                string text = "";
                switch (value)
                {
                    case MeterTXMode.FORWARD_POWER:
                        text = "Fwd Pwr";
                        break;
                    case MeterTXMode.REVERSE_POWER:
                        text = "Ref Pwr";
                        break;
                    case MeterTXMode.SWR_POWER:
                        text = "Fwd SWR";
                        break;
                    case MeterTXMode.MIC:
                        text = "Mic";
                        break;
                    case MeterTXMode.EQ:
                        text = "EQ";
                        break;
                    case MeterTXMode.LEVELER:
                        text = "Leveler";
                        break;
                    case MeterTXMode.LVL_G:
                        text = "Lev Gain";
                        break;
                    case MeterTXMode.CFC_PK:
                        text = "CFC";
                        break;
                    case MeterTXMode.CFC_G:
                        text = "CFC Comp";
                        break;
                    case MeterTXMode.COMP:
                        text = "COMP";
                        break;
                    case MeterTXMode.ALC:
                        text = "ALC";
                        break;
                    case MeterTXMode.ALC_G:
                        text = "ALC Comp";
                        break;
                    case MeterTXMode.ALC_GROUP:
                        text = "ALC Group";
                        break;
                    case MeterTXMode.SWR:
                        text = "SWR";
                        break;
                    case MeterTXMode.OFF:
                        text = "Off";
                        break;
                }
                if (string.IsNullOrEmpty(text)) return;

                comboMeterTXMode.Text = text;
            }
        }

        public ComboBox.ObjectCollection MeterTXModeItems
        {
            get { return comboMeterTXMode.Items; }
        }
        public int GetDSPcwPitchShiftToZero(int rx)
        {
            // rx 1 or 2
            int nPitch = 0;
            switch (rx)
            {
                case 1:
                    {
                        if (RX1DSPMode == DSPMode.CWL)
                        {
                            nPitch = CWPitch;
                        }
                        else if (RX1DSPMode == DSPMode.CWU)
                        {
                            nPitch = -CWPitch;
                        }
                    }
                    break;
                case 2:
                    if (RX2DSPMode == DSPMode.CWL)
                    {
                        nPitch = CWPitch;
                    }
                    else if (RX2DSPMode == DSPMode.CWU)
                    {
                        nPitch = -CWPitch;
                    }
                    break;
            }
            return nPitch;
        }

        private int cw_pitch = 600;
        public int CWPitch
        {
            get { return cw_pitch; }
            set
            {
                int diff = cw_pitch - value;
                cw_pitch = value;
                if (cw_pitch <= 0) cw_pitch = 0;  //-W2PA
                udCWPitch.Value = cw_pitch;
                Display.CWPitch = cw_pitch;
                NetworkIO.SetCWSidetoneFreq(cw_pitch);

                //-W2PA June 2017
                //      This centers the passband of the CW filters on the pitch frequency, but if CWPitch setter is called by mode buttons,  
                //      it prevents filter setting from persisting when the mode changes or band changes, since band changes trigger mode changes.
                //      This happened because of a line:  CWPitch = cw_pitch;  in SetRX1Mode and SetRX2Mode.  
                //      Those are now commented out. This should only be called by the CW Pitch control in the UI and Setup, or by a CAT command.
                for (Filter f = Filter.F1; f < Filter.LAST; f++)
                {
                    // Adjust CWL filters
                    int low = rx1_filters[(int)DSPMode.CWL].GetLow(f);
                    int high = rx1_filters[(int)DSPMode.CWL].GetHigh(f);
                    string name = rx1_filters[(int)DSPMode.CWL].GetName(f);

                    int bw = high - low;
                    low = -cw_pitch - bw / 2;
                    high = -cw_pitch + bw / 2;

                    if (high > 0) // stop shifting the passband when it hits the image limit, while allowing pitch to continue to decrease
                    {
                        low -= high;  // slide the passband down to put its edge at zero
                        high = 0;
                    }

                    rx1_filters[(int)DSPMode.CWL].SetFilter(f, low, high, name);
                    rx2_filters[(int)DSPMode.CWL].SetFilter(f, low, high, name); // n6vl

                    // Adjust CWU filters
                    low = rx1_filters[(int)DSPMode.CWU].GetLow(f);
                    high = rx1_filters[(int)DSPMode.CWU].GetHigh(f);
                    name = rx1_filters[(int)DSPMode.CWU].GetName(f);

                    bw = high - low;
                    low = cw_pitch - bw / 2;
                    high = cw_pitch + bw / 2;

                    if (low < 0) // stop adjusting the passband when it hits the image limit, while allowing pitch to continue to decrease
                    {
                        high -= low;  // slide the passband up to put its edge at zero
                        low = 0;
                    }

                    rx1_filters[(int)DSPMode.CWU].SetFilter(f, low, high, name);
                    rx2_filters[(int)DSPMode.CWU].SetFilter(f, low, high, name);
                }

                switch (rx1_dsp_mode)
                {
                    case DSPMode.CWL:
                        diff = -diff;
                        if (_mox)
                        {
                            VFOAFreq += (double)diff / 1e6;
                            if (chkVFOSplit.Checked) VFOBFreq += (double)diff / 1e6;
                        }
                        else
                        {
                            txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                            txtVFOBFreq_LostFocus(this, EventArgs.Empty);
                        }
                        RX1Filter = rx1_filter;
                        RX2Filter = rx2_filter;
                        break;
                    case DSPMode.CWU:
                        if (_mox)
                        {
                            VFOAFreq += (double)diff / 1e6;
                            if (chkVFOSplit.Checked) VFOBFreq += (double)diff / 1e6;
                        }
                        else
                        {
                            txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                            txtVFOBFreq_LostFocus(this, EventArgs.Empty);
                        }
                        RX1Filter = rx1_filter;
                        RX2Filter = rx2_filter;
                        break;
                }
                if (!IsSetupFormNull)
                {
                    if (SetupForm.RX1APFControls)
                        SetupForm.RX1APFFreq = ptbCWAPFFreq.Value;
                    if (SetupForm.RX1subAPFControls)
                        SetupForm.RX1subAPFFreq = ptbCWAPFFreq.Value;
                    if (SetupForm.RX2APFControls)
                        SetupForm.RX2APFFreq = ptbCWAPFFreq.Value;
                }
            }
        }

        static double freqFromString(string s)
        {
            if (double.TryParse(s, out double f))
            {
                return f;
            }
            return 0;
            //try
            //{
            //    return Double.Parse(s);
            //}
            //catch
            //{
            //    return 0;
            //}
        }

        private double m_dVFOAFreq = 0;
        public double VFOAFreq
        {
            get
            {
                return Math.Round(m_dVFOAFreq, 6);  // MW0LGE_21d so many lost focus calls fixed because of this, rounded to 6
            }
            set
            {
                if (vfoA_lock || IsSetupFormNull) return; //[2.10.3.5]MW0LGE removed the state check
                if (!this.InvokeRequired)
                {
                    VFOAUpdate(value);
                }
                else
                {
                    VFOUpdateDel del = new VFOUpdateDel(VFOAUpdate);
                    Invoke(del, new object[] { value });
                }
            }
        }

        //
        private delegate void VFOUpdateDel(double freq);
        private void VFOAUpdate(double freq)
        {
            m_dVFOAFreq = Math.Round(freq, 6); // MW0LGE_21d rounded to 6
            txtVFOAFreq.Text = freq.ToString("f6");
            txtVFOAFreq_LostFocus(this, EventArgs.Empty);
        }
        private void VFOBUpdate(double freq)
        {
            m_dVFOBFreq = Math.Round(freq, 6); // MW0LGE_21d rounded to 6
            txtVFOBFreq.Text = freq.ToString("f6");
            txtVFOBFreq_LostFocus(this, EventArgs.Empty);
        }
        private void VFOASubUpdate(double freq)
        {
            double dOldVFOASubFreq = VFOASubFreq; // can return -999

            m_dVFOASubFreq = Math.Round(freq, 6);// MW0LGE_21d rounded to 6
            txtVFOABand.Text = freq.ToString("f6");
            txtVFOABand_LostFocus(this, EventArgs.Empty);

            //MW0LGE [2.9.0.7] also in UpdateVFOASub
            if (dOldVFOASubFreq != VFOASubFreq)
            {
                Band ob = BandByFreq(XVTRForm.TranslateFreq(dOldVFOASubFreq), rx1_xvtr_index, current_region);
                Band nb = BandByFreq(XVTRForm.TranslateFreq(VFOASubFreq), rx1_xvtr_index, current_region);

                VFOASubFrequencyChangeHandlers?.Invoke(ob, nb, RX1DSPMode, RX1Filter, dOldVFOASubFreq, VFOASubFreq,
                    CentreFrequency, ClickTuneDisplay, ptbDisplayZoom.Value, radio.GetDSPRX(0, 1).RXOsc, 1);
            }
        }
        public bool VFOASubInUse
        {
            get { return rx2_enabled && (chkEnableMultiRX.Checked || chkVFOSplit.Checked); }
        }
        private double m_dVFOASubFreq = 0;
        public double VFOASubFreq //rx2
        {
            get
            {
                if (!VFOASubInUse) return -999.999; // [2.10.1.0] MW0LGE changed as MeterManager makes use of this
                return Math.Round(m_dVFOASubFreq, 6); // MW0LGE_21d rounded to 6
            }

            set
            {
                if (vfoA_lock || IsSetupFormNull) return; //[2.10.3.6]MW0LGE removed the state check
                if (!this.InvokeRequired)
                {
                    VFOASubUpdate(value);
                }
                else
                {
                    VFOUpdateDel del = new VFOUpdateDel(VFOASubUpdate);
                    Invoke(del, new object[] { value });
                }
            }
        }

        private double m_dVFOBFreq = 0;
        public double VFOBFreq
        {
            get
            {
                return Math.Round(m_dVFOBFreq, 6); // MW0LGE_21d rounded to 6
            }
            set
            {
                if (vfoB_lock || IsSetupFormNull) return; //[2.10.3.5]MW0LGE removed state check
                value = Math.Max(0, value);
                if (!this.InvokeRequired)
                {
                    VFOBUpdate(value);
                }
                else
                {
                    VFOUpdateDel del = new VFOUpdateDel(VFOBUpdate);
                    Invoke(del, new object[] { value });
                }
            }
        }

        public int PWRConstrained
        {
            get { return ptbPWR.ConstrainedValue; }
        }
        public int TunePWRConstrained
        {
            get { return ptbTune.ConstrainedValue; }
        }
        public int PWR
        {
            get { return ptbPWR.Value; }
            set
            {
                value = Math.Max(0, value);			// lower bound
                value = Math.Min(100, value);		// upper bound

                ptbPWR.Value = value;
                ptbPWR_Scroll(this, EventArgs.Empty);
            }
        }
        public int TunePWR  //MW0LGE_22b
        {
            get { return ptbTune.Value; }
            set
            {
                value = Math.Max(0, value);			// lower bound
                value = Math.Min(100, value);		// upper bound

                ptbTune.Value = value;
                ptbTune_Scroll(this, EventArgs.Empty);
            }
        }

        private bool pa_values = false;
        public bool PAValues
        {
            get { return pa_values; }
            set { pa_values = value; }
        }

        public int AF
        {
            get { return ptbAF.Value; }
            set
            {
                value = Math.Max(0, value);			// lower bound
                value = Math.Min(100, value);		// upper bound

                ptbAF.Value = value;
                ptbAF_Scroll(this, EventArgs.Empty);
            }
        }

        private int rxaf = 50;
        public int RXAF
        {
            get { return rxaf; }
            set { rxaf = value; }
        }

        private bool m_bIgnoreAFChangeForMonitor = false;
        public bool IgnoreAFChangeForMonitor
        {
            get { return m_bIgnoreAFChangeForMonitor; }
            set { m_bIgnoreAFChangeForMonitor = value; }
        }
        private int txaf = 50;
        public int TXAF
        {
            get { return txaf; }
            set
            {
                int oldMONVolume = txaf;

                txaf = value;
                qsk_sidetone_volume = value;

                if (!IsSetupFormNull) SetupForm.TXAF = txaf;

                if (MOX || Audio.MOX) ptbAF.Value = txaf;

                setCWSideToneVolume();

                if (txaf != oldMONVolume)
                    MONVolumeChangedHandlers?.Invoke(oldMONVolume, txaf);
            }
        }

        public bool DisplayAVG
        {
            get { return chkDisplayAVG.Checked; }
            set { chkDisplayAVG.Checked = value; }
        }

        private double break_in_delay = 300;
        public double BreakInDelay
        {
            get { return break_in_delay; }
            set
            {
                break_in_delay = value;
                udCWBreakInDelay.Value = (int)value;
                if (BreakInEnabledState != CheckState.Unchecked) NetworkIO.SetCWHangTime((int)value + key_up_delay);
                else NetworkIO.SetCWHangTime(0);
            }
        }

        private int apf_freq = 0;
        public int APFFreq
        {
            get { return apf_freq; }
            set
            {
                apf_freq = value;
                ptbCWAPFFreq.Value = value;
                lblCWAPFTune.Text = "Tune:  " + ptbCWAPFFreq.Value.ToString();
            }
        }

        private int apf_bandwidth = 150;
        public int APFBandwidth
        {
            get { return apf_bandwidth; }
            set
            {
                apf_bandwidth = value;
                ptbCWAPFBandwidth.Value = value;
                lblCWAPFBandwidth.Text = "Bandwidth:  " + ptbCWAPFBandwidth.Value.ToString();
            }
        }

        private int apf_gain = 0;
        public int APFGain
        {
            get { return apf_gain; }
            set
            {
                if (ptbCWAPFGain != null)
                {
                    apf_gain = value;
                    ptbCWAPFGain.Value = value;
                    double gain_value = Math.Round(ptbCWAPFGain.Value / 10.0, 0);
                    lblCWAPFGain.Text = "Gain:  " + gain_value.ToString();
                }
            }
        }

        private bool _cat_ptt = false;
        public bool CATPTT
        {
            get { return _cat_ptt; }
            set { _cat_ptt = value; }
        }

        private bool reverse_paddles = false;
        public bool ReversePaddles
        {
            get { return reverse_paddles; }
            set
            {
                reverse_paddles = value;
                NetworkIO.ReversePaddles(Convert.ToInt32(value));
            }
        }

        private bool cw_auto_mode_switch = false;
        public bool CWAutoModeSwitch
        {
            get { return cw_auto_mode_switch; }
            set
            {
                cw_auto_mode_switch = value;
            }
        }

        // Sets or reads the PS-A button
        public bool PSA
        {
            get { return chkFWCATUBypass.Checked; }
            set { chkFWCATUBypass.Checked = value; }
        }

        public bool MOX
        {
            get { return chkMOX.Checked; }
            set { chkMOX.Checked = value; }
        }

        public bool MOXEnabled
        {
            get { return chkMOX.Enabled; }
            set { chkMOX.Enabled = value; }
        }

        public bool MON
        {
            get { return chkMON.Checked; }
            set { chkMON.Checked = value; }
        }

        public bool MUT
        {
            get { return chkMUT.Checked; }
            set { chkMUT.Checked = value; }
        }

        public bool MUT2
        {
            get { return chkRX2Mute.Checked; }
            set { chkRX2Mute.Checked = value; }
        }

        public bool TUN
        {
            get { return chkTUN.Checked; }
            set
            {
                chkTUN.Checked = value;
            }
        }

        public int RX1FilterLow
        {
            get { return (int)udFilterLow.Value; }
            set { udFilterLow.Value = value; }
        }

        public int RX1FilterHigh
        {
            get { return (int)udFilterHigh.Value; }
            set { udFilterHigh.Value = value; }
        }

        public int RX2FilterLow
        {
            get { return (int)udRX2FilterLow.Value; }
            set { udRX2FilterLow.Value = value; }
        }

        public int RX2FilterHigh
        {
            get { return (int)udRX2FilterHigh.Value; }
            set { udRX2FilterHigh.Value = value; }
        }

        public int FilterShiftValue
        {
            get { return ptbFilterShift.Value; }
            set { ptbFilterShift.Value = value; }
        }

        private static List<Channel> channels_60m;
        public static List<Channel> Channels60m
        {
            get
            {
                return channels_60m;
            }
        }

        private bool pennylanepresent = true;
        public bool PennyLanePresent
        {
            get { return pennylanepresent; }
            set
            {
                pennylanepresent = true;
                cmaster.CMSetTXOutputLevelRun();
            }
        }

        public bool PennyPresent = false;
        public bool MercuryPresent = false;

        private bool disable_6m_lna_on_rx = false;
        public bool Disable6mLNAonRX
        {
            get { return disable_6m_lna_on_rx; }
            set
            {
                disable_6m_lna_on_rx = value;
                double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                double freq2 = VFOBFreq;// Double.Parse(txtVFOBFreq.Text);
                SetAlexHPF(freq);
                if (current_hpsdr_model == HPSDRModel.ANAN7000D || current_hpsdr_model == HPSDRModel.ANAN8000D ||
                    current_hpsdr_model == HPSDRModel.ANAN_G2 || current_hpsdr_model == HPSDRModel.ANAN_G2_1K)
                {
                    SetAlex2HPF(freq2);
                    txtVFOBFreq_LostFocus(this, EventArgs.Empty);
                }

                txtVFOAFreq_LostFocus(this, EventArgs.Empty);
            }
        }

        private bool disable_6m_lna_on_tx = true;
        public bool Disable6mLNAonTX
        {
            get { return disable_6m_lna_on_tx; }
            set
            {
                disable_6m_lna_on_tx = value;
                double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                SetAlexHPF(freq);
            }
        }

        private bool disable_hpf_on_tx = false;
        public bool DisableHPFonTX
        {
            get { return disable_hpf_on_tx; }
            set
            {
                disable_hpf_on_tx = value;
                double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                SetAlexHPF(freq);
            }
        }
        private bool disable_hpf_on_ps = false;
        public bool DisableHPFonPS
        {
            get { return disable_hpf_on_ps; }
            set
            {
                disable_hpf_on_ps = value;
                double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                SetAlexHPF(freq);
            }
        }
        private bool lpf_bypass = false;
        public bool LPFBypass
        {
            get { return lpf_bypass; }
            set
            {
                lpf_bypass = value;
                if (chkPower.Checked)
                {
                    double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                    if (_mox) freq = tx_dds_freq_mhz;
                    SetAlexLPF(freq, _mox);
                    if (!initializing)
                        txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                }
            }
        }

        private bool alex_hpf_bypass = false;
        public bool AlexHPFBypass
        {
            get { return alex_hpf_bypass; }
            set
            {
                alex_hpf_bypass = value;
                double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                SetAlexHPF(freq);
                if (!initializing)
                    txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                BPF1ToolStripMenuItem.Checked = value;
            }
        }

        private bool alex2_hpf_bypass = false;
        public bool Alex2HPFBypass
        {
            get { return alex2_hpf_bypass; }
            set
            {
                alex2_hpf_bypass = value;
                double freq = VFOBFreq;// Double.Parse(txtVFOBFreq.Text); //[2.10.3.6]freq changes.
                SetAlex2HPF(freq);
                if (!initializing)
                    txtVFOBFreq_LostFocus(this, EventArgs.Empty);
                BPF2ToolStripMenuItem.Checked = value;
            }
        }

        private bool alex1_5bphpf_bypass = false;
        public bool Alex1_5BPHPFBypass
        {
            get { return alex1_5bphpf_bypass; }
            set
            {
                alex1_5bphpf_bypass = value;
                double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                SetAlexHPF(freq);
            }
        }

        private bool bpf1_1_5bp_bypass = false;
        public bool BPF1_1_5BPBypass
        {
            get { return bpf1_1_5bp_bypass; }
            set
            {
                bpf1_1_5bp_bypass = value;
                double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                SetAlexHPF(freq);
            }
        }

        private bool alex21_5bphpf_bypass = false;
        public bool Alex21_5BPHPFBypass
        {
            get { return alex21_5bphpf_bypass; }
            set
            {
                alex21_5bphpf_bypass = value;
                double freq = VFOBFreq;// Double.Parse(txtVFOBFreq.Text); //[2.10.3.6]freq changes.
                SetAlex2HPF(freq);
            }
        }

        private bool alex6_5bphpf_bypass = false;
        public bool Alex6_5BPHPFBypass
        {
            get { return alex6_5bphpf_bypass; }
            set
            {
                alex6_5bphpf_bypass = value;
                double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                SetAlexHPF(freq);
            }
        }

        private bool bpf1_6_5bp_bypass = false;
        public bool BPF1_6_5BPBypass
        {
            get { return bpf1_6_5bp_bypass; }
            set
            {
                bpf1_6_5bp_bypass = value;
                double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                SetAlexHPF(freq);
            }
        }

        private bool alex26_5bphpf_bypass = false;
        public bool Alex26_5BPHPFBypass
        {
            get { return alex26_5bphpf_bypass; }
            set
            {
                alex26_5bphpf_bypass = value;
                double freq = VFOBFreq;// Double.Parse(txtVFOBFreq.Text); //[2.10.3.6]freq changes.
                SetAlex2HPF(freq);
            }
        }

        private bool alex9_5bphpf_bypass = false;
        public bool Alex9_5BPHPFBypass
        {
            get { return alex9_5bphpf_bypass; }
            set
            {
                alex9_5bphpf_bypass = value;
                double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                SetAlexHPF(freq);
            }
        }

        private bool bpf1_9_5bp_bypass = false;
        public bool BPF1_9_5BPBypass
        {
            get { return bpf1_9_5bp_bypass; }
            set
            {
                bpf1_9_5bp_bypass = value;
                double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                SetAlexHPF(freq);
            }
        }

        private bool alex29_5bphpf_bypass = false;
        public bool Alex29_5BPHPFBypass
        {
            get { return alex29_5bphpf_bypass; }
            set
            {
                alex29_5bphpf_bypass = value;
                double freq = VFOBFreq;// Double.Parse(txtVFOBFreq.Text); //[2.10.3.6]freq changes.
                SetAlex2HPF(freq);
            }
        }

        private bool alex13bphpf_bypass = false;
        public bool Alex13BPHPFBypass
        {
            get { return alex13bphpf_bypass; }
            set
            {
                alex13bphpf_bypass = value;
                double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                SetAlexHPF(freq);
            }
        }

        private bool bpf1_13bp_bypass = false;
        public bool BPF1_13BPBypass
        {
            get { return bpf1_13bp_bypass; }
            set
            {
                bpf1_13bp_bypass = value;
                double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                SetAlexHPF(freq);
            }
        }

        private bool alex213bphpf_bypass = false;
        public bool Alex213BPHPFBypass
        {
            get { return alex213bphpf_bypass; }
            set
            {
                alex213bphpf_bypass = value;
                double freq = VFOBFreq;// Double.Parse(txtVFOBFreq.Text); //[2.10.3.6]freq changes.
                SetAlex2HPF(freq);
            }
        }

        private bool alex20bphpf_bypass = false;
        public bool Alex20BPHPFBypass
        {
            get { return alex20bphpf_bypass; }
            set
            {
                alex20bphpf_bypass = value;
                double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                SetAlexHPF(freq);
            }
        }

        private bool bpf1_20bp_bypass = false;
        public bool BPF1_20BPBypass
        {
            get { return bpf1_20bp_bypass; }
            set
            {
                bpf1_20bp_bypass = value;
                double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                SetAlexHPF(freq);
            }
        }

        private bool alex220bphpf_bypass = false;
        public bool Alex220BPHPFBypass
        {
            get { return alex220bphpf_bypass; }
            set
            {
                alex220bphpf_bypass = value;
                double freq = VFOBFreq;// Double.Parse(txtVFOBFreq.Text); //[2.10.3.6]freq changes.
                SetAlex2HPF(freq);
            }
        }

        private bool alex6bphpf_bypass = false;
        public bool Alex6BPHPFBypass
        {
            get { return alex6bphpf_bypass; }
            set
            {
                alex6bphpf_bypass = value;
                double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                SetAlexHPF(freq);
                txtVFOAFreq_LostFocus(this, EventArgs.Empty);
            }
        }

        private bool bpf1_6bp_bypass = false;
        public bool BPF1_6BPBypass
        {
            get { return bpf1_6bp_bypass; }
            set
            {
                bpf1_6bp_bypass = value;
                double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                SetAlexHPF(freq);
            }
        }

        private bool alex26bphpf_bypass = false;
        public bool Alex26BPHPFBypass
        {
            get { return alex26bphpf_bypass; }
            set
            {
                alex26bphpf_bypass = value;
                double freq = VFOBFreq;// Double.Parse(txtVFOBFreq.Text); //[2.10.3.6]freq changes.
                SetAlex2HPF(freq);
            }
        }

        private bool swrprotection = true;
        public bool SWRProtection
        {
            get { return swrprotection; }
            set
            {
                swrprotection = value;
            }
        }

        private bool disable_swr_on_tune = true;
        public bool DisableSWRonTune
        {
            get { return disable_swr_on_tune; }
            set
            {
                disable_swr_on_tune = value;
            }
        }

        private bool m_bAttontx = true;
        public bool ATTOnTX
        {
            get { return m_bAttontx; }
            set
            {
                if (!value && _auto_attTX_when_not_in_ps) return; // ignore in this case
                m_bAttontx = value;
                updateAttNudsCombos();

                if (PowerOn)
                {
                    if (m_bAttontx)
                    {
                        int txatt = getTXstepAttenuatorForBand(tx_band);
                        NetworkIO.SetTxAttenData(txatt); //[2.10.3.6]MW0LGE att_fixes
                        Display.TXAttenuatorOffset = txatt; //[2.10.3.6]MW0LGE att_fixes
                    }
                    else
                    {
                        NetworkIO.SetTxAttenData(0);
                        Display.TXAttenuatorOffset = 0;
                    }
                }

            }
        }

        private bool apollopresent = false;
        public bool ApolloPresent
        {
            get { return apollopresent; }
            set
            {
                bool oldValue = apollopresent;

                apollopresent = value;
                if (apollopresent)
                {
                    if (!comboMeterTXMode.Items.Contains("Ref Pwr"))
                        comboMeterTXMode.Items.Insert(1, "Ref Pwr");
                }
                else
                {
                    if (!initializing)
                    {
                        if (comboMeterTXMode.Items.Contains("Ref Pwr"))
                            comboMeterTXMode.Items.Remove("Ref Pwr");
                    }
                }

                if (oldValue != apollopresent) ApolloPresentChangedHandlers?.Invoke(oldValue, apollopresent); //MW0LGE_[2.9.0.7]
            }
        }

        private bool apollo_tuner_enabled = false;
        public bool ApolloTunerEnabled {
            get { return apollo_tuner_enabled; }
            set {
                apollo_tuner_enabled = value;
                if (apollo_tuner_enabled) NetworkIO.EnableApolloTuner(1);
                else NetworkIO.EnableApolloTuner(0);
            }
        }

        private bool alexpresent = true;
        public bool AlexPresent {
            get { return alexpresent; }
            set {
                bool oldValue = alexpresent;

                alexpresent = value;

                if (alexpresent)
                {
                    if (!comboMeterTXMode.Items.Contains("Ref Pwr"))
                        comboMeterTXMode.Items.Insert(1, "Ref Pwr");

                    if (!comboMeterTXMode.Items.Contains("SWR"))
                        comboMeterTXMode.Items.Insert(2, "SWR");

                    if (comboMeterTXMode.SelectedIndex < 0)
                        comboMeterTXMode.SelectedIndex = 0;

                    SetAlexHPF(fwc_dds_freq);
                    SetAlexLPF(tx_dds_freq_mhz, true);
                    SetAlex2HPF(rx2_dds_freq_mhz);
                }
                else
                {
                    string cur_txt = comboMeterTXMode.Text;

                    if (!initializing)
                    {
                        if (comboMeterTXMode.Items.Contains("Ref Pwr"))
                            comboMeterTXMode.Items.Remove("Ref Pwr");
                        if (comboMeterTXMode.Items.Contains("SWR"))
                            comboMeterTXMode.Items.Remove("SWR");
                    }

                    comboMeterTXMode.Text = cur_txt;
                    if (comboMeterTXMode.SelectedIndex < 0 &&
                        comboMeterTXMode.Items.Count > 0)
                        comboMeterTXMode.SelectedIndex = 0;
                }

                if (oldValue != alexpresent) AlexPresentChangedHandlers?.Invoke(oldValue, alexpresent); //MW0LGE_[2.9.0.7]
            }
        }

        private string hpsdr_network_ip_addr;
        public string HPSDRNetworkIPAddr
        {
            get { return hpsdr_network_ip_addr; }
            set
            {
                hpsdr_network_ip_addr = value;
            }
        }

        private int mic_gain_min = -40;
        public int MicGainMin
        {
            get { return mic_gain_min; }
            set
            {
                mic_gain_min = value;
                ptbMic_Scroll(this, EventArgs.Empty);
            }
        }

        private int mic_gain_max = 10;
        public int MicGainMax
        {
            get { return mic_gain_max; }
            set
            {
                mic_gain_max = value;
                ptbMic_Scroll(this, EventArgs.Empty);
            }
        }

        private int alex_atten;
        private PreampMode rx1_preamp_mode = PreampMode.HPSDR_OFF;
        public PreampMode RX1PreampMode
        {
            get { return rx1_preamp_mode; }
            set
            {
                PreampMode oldMode = rx1_preamp_mode;
                rx1_preamp_mode = value;
                if (initializing) return;

                if (!alexpresent && ((rx1_preamp_mode == PreampMode.HPSDR_MINUS10) ||
                                    (rx1_preamp_mode == PreampMode.HPSDR_MINUS20) ||
                                    (rx1_preamp_mode == PreampMode.HPSDR_MINUS30) ||
                                    (rx1_preamp_mode == PreampMode.HPSDR_MINUS40) ||
                                    (rx1_preamp_mode == PreampMode.HPSDR_MINUS50)))
                {
                    rx1_preamp_mode = PreampMode.HPSDR_OFF;
                }

                alex_atten = 0;
                int merc_preamp = 0;
                int rx1_att_value = 0;
                switch (rx1_preamp_mode)
                {
                    case PreampMode.HPSDR_ON:  //0dB
                        rx1_att_value = 0;
                        merc_preamp = 1; //no attn
                        alex_atten = 0;
                        break;
                    case PreampMode.HPSDR_OFF: //-20dB
                        rx1_att_value = 20;
                        merc_preamp = 0; //attn inline
                        alex_atten = 0;
                        break;
                    case PreampMode.HPSDR_MINUS10:
                        rx1_att_value = 0;
                        merc_preamp = 1;
                        alex_atten = 1;
                        break;
                    case PreampMode.HPSDR_MINUS20:
                        rx1_att_value = 0;
                        merc_preamp = 1;
                        alex_atten = 2;
                        break;
                    case PreampMode.HPSDR_MINUS30:
                        rx1_att_value = 0;
                        merc_preamp = 1;
                        alex_atten = 3;
                        break;
                    case PreampMode.HPSDR_MINUS40:
                        rx1_att_value = 20;
                        merc_preamp = 0;
                        alex_atten = 2;
                        break;
                    case PreampMode.HPSDR_MINUS50:
                        rx1_att_value = 20;
                        merc_preamp = 0;
                        alex_atten = 3;
                        break;
                    case PreampMode.SA_MINUS10:
                        rx1_att_value = 10;
                        merc_preamp = 0;
                        alex_atten = 0;
                        break;
                    case PreampMode.SA_MINUS20:
                        rx1_att_value = 20;
                        merc_preamp = 0;
                        alex_atten = 0;
                        break;
                    case PreampMode.SA_MINUS30:
                        rx1_att_value = 30;
                        merc_preamp = 0;
                        alex_atten = 0;
                        break;
                }

                //MW0LGE_22b
                int nRX1DDCinUse = -1, nRX2DDCinUse = -1, sync1 = -1, sync2 = -1, psrx = -1, pstx = -1;
                GetDDC(out nRX1DDCinUse, out nRX2DDCinUse, out sync1, out sync2, out psrx, out pstx);

                int nRX1ADCinUse = GetADCInUse(nRX1DDCinUse); // (rx1)
                int nRX2ADCinUse = GetADCInUse(nRX2DDCinUse); // (rx2)

                if (current_hpsdr_model != HPSDRModel.HPSDR)
                {
                    if (!rx1_step_att_present)
                    {
                        if (nRX1ADCinUse == 0) NetworkIO.SetADC1StepAttenData(rx1_att_value);
                        else if (nRX1ADCinUse == 1) NetworkIO.SetADC2StepAttenData(rx1_att_value);
                        else if (nRX1ADCinUse == 2) NetworkIO.SetADC3StepAttenData(rx1_att_value);
                    }
                }
                else
                {
                    NetworkIO.SetRX1Preamp(merc_preamp);
                }

                if (rx1_step_att_present)
                {
                    if (alexpresent &&
                        current_hpsdr_model != HPSDRModel.ANAN10 &&
                        current_hpsdr_model != HPSDRModel.ANAN10E &&
                        current_hpsdr_model != HPSDRModel.ANAN7000D &&
                        current_hpsdr_model != HPSDRModel.ANAN8000D &&
                        current_hpsdr_model != HPSDRModel.ORIONMKII &&
                        current_hpsdr_model != HPSDRModel.ANAN_G2 &&
                        current_hpsdr_model != HPSDRModel.ANAN_G2_1K)
                    {
                        if (rx1_attenuator_data <= 31)
                        {
                            NetworkIO.SetAlexAtten(0); // 0dB Alex Attenuator
                        }
                        else
                        {
                            NetworkIO.SetAlexAtten(3); // -30dB Alex Attenuator
                        }
                    }
                    else
                    {
                        NetworkIO.SetAlexAtten(0);
                    }
                }
                else
                {
                    NetworkIO.SetAlexAtten(alex_atten);
                }
                //

                rx1_preamp_by_band[(int)rx1_band] = rx1_preamp_mode;

                switch (rx1_preamp_mode)
                {
                    case PreampMode.HPSDR_ON:
                        comboPreamp.Text = "0dB";
                        break;

                    case PreampMode.HPSDR_OFF:
                        comboPreamp.Text = "-20dB";
                        break;

                    case PreampMode.HPSDR_MINUS10:
                        comboPreamp.Text = "-10db";
                        break;

                    case PreampMode.HPSDR_MINUS20:
                        comboPreamp.Text = "-20db";
                        break;

                    case PreampMode.HPSDR_MINUS30:
                        comboPreamp.Text = "-30db";
                        break;

                    case PreampMode.HPSDR_MINUS40:
                        comboPreamp.Text = "-40db"; //MW0LGE_22b lower
                        break;

                    case PreampMode.HPSDR_MINUS50:
                        comboPreamp.Text = "-50db"; //MW0LGE_22b lower
                        break;
                    case PreampMode.SA_MINUS10:
                        comboPreamp.Text = "-10dB";
                        break;
                    case PreampMode.SA_MINUS20:
                        comboPreamp.Text = "-20dB";
                        break;
                    case PreampMode.SA_MINUS30:
                        comboPreamp.Text = "-30dB";
                        break;
                }

                if (!_mox && !_setFromOtherAttenuator)
                {
                    bool bRX1RX2diversity = m_bDiversityAttLinkForRX1andRX2 && (diversityForm != null && Diversity2 && diversityForm.EXTDIVOutput == 2); // if using diversity, and both rx's are linked, then we need to attenuate both
                    if (((nRX1ADCinUse == nRX2ADCinUse) || bRX1RX2diversity) && RX2PreampMode != rx1_preamp_mode)
                    {
                        _setFromOtherAttenuator = true;
                        if (SetupForm.RX2EnableAtt != SetupForm.RX1EnableAtt) SetupForm.RX2EnableAtt = SetupForm.RX1EnableAtt;
                        RX2PreampMode = rx1_preamp_mode;
                        _setFromOtherAttenuator = false;
                    }
                }

                if (chkSquelch.Checked)
                    ptbSquelch_Scroll(this, EventArgs.Empty);

                if (!_mox)
                {
                    update_preamp = true;
                    UpdatePreamps();
                }
                UpdateRX1DisplayOffsets(); //MW0LGE_22b

                if (oldMode != rx1_preamp_mode) PreampModeChangedHandlers?.Invoke(1, oldMode, rx1_preamp_mode);
            }
        }

        private PreampMode rx2_preamp_mode = PreampMode.HPSDR_OFF;
        public PreampMode RX2PreampMode
        {
            get { return rx2_preamp_mode; }
            set
            {
                PreampMode oldMode = rx2_preamp_mode;
                rx2_preamp_mode = value;
                if (initializing) return;

                int rx2_preamp = 0;
                int rx2_att_value = 0;

                //MW0LGE_22b
                switch (rx2_preamp_mode)
                {
                    case PreampMode.HPSDR_ON:  //0dB
                        rx2_att_value = 0;
                        rx2_preamp = 1; //no attn
                        comboRX2Preamp.Text = "0dB";
                        break;
                    case PreampMode.HPSDR_OFF: //-20dB
                        rx2_att_value = 20;
                        rx2_preamp = 0; //attn inline
                        comboRX2Preamp.Text = "-20dB";
                        break;
                    case PreampMode.HPSDR_MINUS10:
                        rx2_att_value = 10;
                        rx2_preamp = 1;
                        comboRX2Preamp.Text = "-10db"; //MW0LGE_22b lower
                        break;
                    case PreampMode.HPSDR_MINUS20:
                        rx2_att_value = 20;
                        rx2_preamp = 1;
                        comboRX2Preamp.Text = "-20db";  //MW0LGE_22b lower
                        break;
                    case PreampMode.HPSDR_MINUS30:
                        rx2_att_value = 30;
                        rx2_preamp = 1;
                        comboRX2Preamp.Text = "-30db";  //MW0LGE_22b lower
                        break;
                    case PreampMode.SA_MINUS10:
                        rx2_att_value = 10;
                        rx2_preamp = 0;
                        comboRX2Preamp.Text = "-10dB";
                        break;
                    case PreampMode.SA_MINUS20:
                        rx2_att_value = 20;
                        rx2_preamp = 0;
                        comboRX2Preamp.Text = "-20dB";
                        break;
                    case PreampMode.SA_MINUS30:
                        rx2_att_value = 30;
                        rx2_preamp = 0;
                        comboRX2Preamp.Text = "-30dB";
                        break;
                }

                //MW0LGE_22b
                int nRX1DDCinUse = -1, nRX2DDCinUse = -1, sync1 = -1, sync2 = -1, psrx = -1, pstx = -1;
                GetDDC(out nRX1DDCinUse, out nRX2DDCinUse, out sync1, out sync2, out psrx, out pstx);

                int nRX1ADCinUse = GetADCInUse(nRX1DDCinUse); // (rx1)
                int nRX2ADCinUse = GetADCInUse(nRX2DDCinUse); // (rx2)

                if (!rx2_step_att_present && (current_hpsdr_model == HPSDRModel.ANAN100D ||  //MW0LGE_22b we dont want to do this if we are using SA
                    current_hpsdr_model == HPSDRModel.ANAN200D ||
                    current_hpsdr_model == HPSDRModel.ORIONMKII ||
                    current_hpsdr_model == HPSDRModel.ANAN7000D ||
                    current_hpsdr_model == HPSDRModel.ANAN8000D ||
                    current_hpsdr_model == HPSDRModel.ANAN_G2 ||
                    current_hpsdr_model == HPSDRModel.ANAN_G2_1K))
                {
                    if (nRX2ADCinUse == 0) NetworkIO.SetADC1StepAttenData(rx2_att_value);
                    else if (nRX2ADCinUse == 1) NetworkIO.SetADC2StepAttenData(rx2_att_value);
                    else if (nRX2ADCinUse == 2) NetworkIO.SetADC3StepAttenData(rx2_att_value);
                }

                if (current_hpsdr_model == HPSDRModel.HPSDR)
                    NetworkIO.SetRX2Preamp(rx2_preamp);

                rx2_preamp_by_band[(int)rx2_band] = rx2_preamp_mode;

                if (!_mox && !_setFromOtherAttenuator)
                {
                    bool bRX1RX2diversity = m_bDiversityAttLinkForRX1andRX2 && (diversityForm != null && Diversity2 && diversityForm.EXTDIVOutput == 2); // if using diversity, and both rx's are linked, then we need to attenuate both
                    if (((nRX1ADCinUse == nRX2ADCinUse) || bRX1RX2diversity) && RX1PreampMode != rx2_preamp_mode)
                    {
                        _setFromOtherAttenuator = true;
                        if (SetupForm.RX1EnableAtt != SetupForm.RX2EnableAtt) SetupForm.RX1EnableAtt = SetupForm.RX2EnableAtt;
                        RX1PreampMode = rx2_preamp_mode;
                        _setFromOtherAttenuator = false;
                    }
                }

                UpdateRX2DisplayOffsets();

                if (chkRX2Squelch.Checked)
                    ptbRX2Squelch_Scroll(this, EventArgs.Empty);

                if (oldMode != rx2_preamp_mode) PreampModeChangedHandlers?.Invoke(2, oldMode, rx2_preamp_mode);
            }
        }

        public int Squelch
        {
            get
            {
                // [2.9.3.5]MW0LGE reverted back
                return ptbSquelch.Value;
            }
            set
            {
                // [2.9.3.5]MW0LGE reverted back to -160 to 0
                _bIgnoreSqlUpdate = true;
                ptbSquelch.Value = value;
                _bIgnoreSqlUpdate = false;
                ptbSquelch_Scroll(this, EventArgs.Empty);
            }
        }

        public int Squelch2
        {
            get
            {
                // [2.9.3.5]MW0LGE reverted back to -160 to 0
                return ptbRX2Squelch.Value;
            }
            set
            {
                // [2.9.3.5]MW0LGE reverted back to -160 to 0
                _bIgnoreSqlUpdate = true;
                ptbRX2Squelch.Value = value;
                _bIgnoreSqlUpdate = false;
                ptbRX2Squelch_Scroll(this, EventArgs.Empty);
            }
        }

        public int Zoom
        {
            get { return ptbDisplayZoom.Value; }
            set
            {
                ptbDisplayZoom.Value = value;
                ptbDisplayZoom_Scroll(this, EventArgs.Empty);
            }
        }

        public int Pan
        {
            get { return ptbDisplayPan.Value; }
            set
            {
                ptbDisplayPan.Value = value;
                ptbDisplayPan_Scroll(this, EventArgs.Empty);
            }
        }
        private AGCMode m_RX1agcMode = AGCMode.FIRST;
        public AGCMode RX1AGCMode
        {
            get { return m_RX1agcMode; }
            set
            {
                m_RX1agcMode = value;
                comboAGC.SelectedIndex = (int)value;
                lblAGCLabel.Text = "AGC: " + comboAGC.Text;
            }
        }
        private AGCMode m_RX2agcMode = AGCMode.FIRST;
        public AGCMode RX2AGCMode
        {
            get
            {
                return m_RX2agcMode;
            }
            set
            {
                m_RX2agcMode = value;
                comboRX2AGC.SelectedIndex = (int)value;
                lblRX2AGCLabel.Text = "AGC: " + comboRX2AGC.Text;
            }
        }

        public bool VFOSplit
        {
            get { return chkVFOSplit.Checked; }
            set
            {
                chkVFOSplit.Checked = value;
                if (value == true)
                    lblVFOSplit.BackColor = System.Drawing.Color.Blue;
                else
                    lblVFOSplit.BackColor = System.Drawing.Color.Transparent;
            }
        }
        public bool RITOn
        {
            get { return chkRIT.Checked; }
            set
            {
                chkRIT.Checked = value;
                if (value == true)
                    lblRITLabel.BackColor = System.Drawing.Color.Blue;
                else
                    lblRITLabel.BackColor = System.Drawing.Color.Transparent;
            }
        }

        public int RITValue
        {
            get { return (int)udRIT.Value; }
            set
            {
                udRIT.Value = value;
                lblRITValue.Text = value.ToString();
            }
        }

        public bool XITOn
        {
            get { return chkXIT.Checked; }
            set
            {
                chkXIT.Checked = value;
                if (value == true)
                    lblXITLabel.BackColor = System.Drawing.Color.Blue;
                else
                    lblXITLabel.BackColor = System.Drawing.Color.Transparent;
            }
        }

        public int XITValue
        {
            get { return (int)udXIT.Value; }
            set
            {
                udXIT.Value = value;
                lblXITValue.Text = value.ToString();
            }
        }

        private int fm_tx_bw = 6000;
        public int FMtxBW
        {
            get { return fm_tx_bw; }
            set { fm_tx_bw = value; }
        }

        private int mox_delay = 10;
        public int MoxDelay
        {
            get { return mox_delay; }
            set
            {
                mox_delay = value;
            }
        }

        private int space_mox_delay = 0;
        public int SpaceMoxDelay {
            get { return space_mox_delay; }
            set {
                space_mox_delay = value;
            }
        }

        private int key_up_delay = 10;
        public int KeyUpDelay
        {
            get { return key_up_delay; }
            set
            {
                key_up_delay = value;
            }
        }

        private int rf_delay = 30;
        public int RFDelay
        {
            get { return rf_delay; }
            set { rf_delay = value; }
        }

        private int ptt_out_delay = 20;
        public int PTTOutDelay
        {
            get { return ptt_out_delay; }
            set { ptt_out_delay = value; }
        }

        private int tx_filter_high = 3100;
        public int TXFilterHigh
        {
            get { return tx_filter_high; }
            set
            {
                tx_filter_high = value;
                udTXFilterHigh.Value = value;
                SetTXFilters(rx1_dsp_mode, tx_filter_low, tx_filter_high);
            }
        }

        private int tx_filter_low = 200;
        public int TXFilterLow
        {
            get { return tx_filter_low; }
            set
            {
                tx_filter_low = value;
                udTXFilterLow.Value = value;
                SetTXFilters(rx1_dsp_mode, tx_filter_low, tx_filter_high);
            }
        }

        private delegate void SetTimerDel(System.Windows.Forms.Timer t, bool enable);
        private void SetTimer(System.Windows.Forms.Timer t, bool enable)
        {
            t.Enabled = enable;
        }

        private bool high_swr = false;
        public bool HighSWR
        {
            get { return high_swr; }
            set
            {
                high_swr = value;
                Display.HighSWR = value;
            }
        }

        private bool disable_ptt = false;
        public bool DisablePTT
        {
            get { return disable_ptt; }
            set { disable_ptt = value; }
        }

        private bool mic_ptt_disabled = false;
        public bool MicPTTDisabled
        {
            get { return mic_ptt_disabled; }
            set
            {
                mic_ptt_disabled = value;
                NetworkIO.SetMicPTT(Convert.ToInt32(value));
            }
        }

        public bool PowerOn
        {
            get { return chkPower.Checked; }
            set { chkPower.Checked = value; }
        }

        public bool PowerEnabled
        {
            get { return chkPower.Enabled; }
            set { chkPower.Enabled = value; }
        }

        private bool vac_sound_card_stereo = false;
        public bool VACSoundCardStereo
        {
            get { return vac_sound_card_stereo; }
            set
            {
                vac_sound_card_stereo = value;
                Audio.VACStereo = value;
            }
        }

        private bool vac2_sound_card_stereo = false;
        public bool VAC2SoundCardStereo
        {
            get { return vac2_sound_card_stereo; }
            set
            {
                vac2_sound_card_stereo = value;
                Audio.VAC2Stereo = value;
            }
        }

        private bool vac_enabled = false;
        public bool VACEnabled
        {
            get { return vac_enabled; }
            set
            {
                vac_enabled = value;
                Audio.VACEnabled = value;
                if (chkVAC1 != null) chkVAC1.Checked = value;
            }
        }

        private bool vac2_enabled = false;
        public bool VAC2Enabled
        {
            get { return vac2_enabled; }
            set
            {
                vac2_enabled = value;
                Audio.VAC2Enabled = value;
                if (chkVAC2 != null) chkVAC2.Checked = value;
                chkVFOBTX_CheckedChanged(this, EventArgs.Empty);
            }
        }

        private int audio_driver_index2 = 0;
        public int AudioDriverIndex2
        {
            get { return audio_driver_index2; }
            set { audio_driver_index2 = value; }
        }

        private int audio_driver_index3 = 0;
        public int AudioDriverIndex3
        {
            get { return audio_driver_index3; }
            set { audio_driver_index3 = value; }
        }

        private int audio_input_index2 = 0;
        public int AudioInputIndex2
        {
            get { return audio_input_index2; }
            set { audio_input_index2 = value; }
        }

        private int audio_input_index3 = 0;
        public int AudioInputIndex3
        {
            get { return audio_input_index3; }
            set { audio_input_index3 = value; }
        }

        private int audio_output_index2 = 0;
        public int AudioOutputIndex2
        {
            get { return audio_output_index2; }
            set { audio_output_index2 = value; }
        }

        private int audio_output_index3 = 0;
        public int AudioOutputIndex3
        {
            get { return audio_output_index3; }
            set { audio_output_index3 = value; }
        }

        private int sample_rate_rx1 = 0; //[2.10.2.3]MW0LGE change to 0 so that comboAudioSampleRate1_SelectedIndexChanged will do its thing is system is shutdown with 48000 selected
        private int m_nOldSampleRateRX1 = 0;
        public int SampleRateRX1
        {
            get { return sample_rate_rx1; }
            set
            {
                m_nOldSampleRateRX1 = sample_rate_rx1;

                sample_rate_rx1 = value;
                RadioDSP.SampleRate = value;
                Audio.SampleRate1 = value;
                Display.SampleRateRX1 = value;
                switch (rx1_dsp_mode)
                {
                    case DSPMode.SPEC:
                        SetRX1Mode(DSPMode.SPEC);
                        break;
                }

                switch (Display.CurrentDisplayMode)
                {
                    case DisplayMode.PANADAPTER:
                    case DisplayMode.WATERFALL:
                    case DisplayMode.PANAFALL:
                    case DisplayMode.PANASCOPE:
                        CalcDisplayFreq();
                        btnDisplayPanCenter.PerformClick();
                        break;
                    case DisplayMode.SPECTRUM:
                    case DisplayMode.HISTOGRAM:
                        UpdateRXSpectrumDisplayVars();
                        break;
                }

                if (m_nOldSampleRateRX1 != sample_rate_rx1)
                    SampleRateChangedHandlers?.Invoke(1, m_nOldSampleRateRX1, sample_rate_rx1);
            }
        }

        private int sample_rate_rx2 = 0;//[2.10.2.3]MW0LGE change to 0 so that comboAudioSampleRate1_SelectedIndexChanged will do its thing is system is shutdown with 48000 selected
        private int m_nOldSampleRateRX2 = 0;
        public int SampleRateRX2
        {
            get { return sample_rate_rx2; }
            set
            {
                m_nOldSampleRateRX2 = sample_rate_rx2;

                sample_rate_rx2 = value;

                Audio.SampleRateRX2 = value;
                Display.SampleRateRX2 = value;
                switch (rx1_dsp_mode)
                {
                    case DSPMode.SPEC:
                        SetRX1Mode(DSPMode.SPEC);
                        break;
                }

                switch (Display.CurrentDisplayMode)
                {
                    case DisplayMode.PANADAPTER:
                    case DisplayMode.WATERFALL:
                    case DisplayMode.PANAFALL:
                    case DisplayMode.PANASCOPE:
                        CalcRX2DisplayFreq();
                        btnDisplayPanCenter.PerformClick();
                        break;
                    case DisplayMode.SPECTRUM:
                    case DisplayMode.HISTOGRAM:
                        UpdateRXSpectrumDisplayVars();
                        break;
                }

                if (m_nOldSampleRateRX2 != sample_rate_rx2)
                    SampleRateChangedHandlers?.Invoke(2, m_nOldSampleRateRX2, sample_rate_rx2);
            }
        }

        private int sample_rate_tx = 192000;
        public int SampleRateTX
        {
            get { return sample_rate_tx; }
            set
            {
                sample_rate_tx = value;
                Audio.OutRateTX = value; //[2.10.3.4]MW0LGE added
                Audio.BlockSizeTX = cmaster.GetBuffSize(value); //[2.10.3.4]MW0LGE added
                Audio.SampleRateTX = value;
                if (!IsSetupFormNull)  //[2.10.3.5]MW0LGE added
                    Audio.ScopeTime = SetupForm.ScopeTime;
                Display.SampleRateTX = value;
                cmaster.SetXmtrChannelOutrate(0, value, cmaster.MONMixState);

                switch (rx1_dsp_mode)
                {
                    case DSPMode.SPEC:
                        break;
                }

                switch (Display.CurrentDisplayMode)
                {
                    case DisplayMode.PANADAPTER:
                    case DisplayMode.WATERFALL:
                    case DisplayMode.PANAFALL:
                    case DisplayMode.PANASCOPE:
                        CalcTXDisplayFreq();
                        btnDisplayPanCenter.PerformClick();
                        break;
                    case DisplayMode.SPECTRUM:
                    case DisplayMode.HISTOGRAM:
                        UpdateTXSpectrumDisplayVars();
                        break;
                }
            }
        }

        private int sample_rate2 = 48000;
        public int SampleRate2
        {
            get { return sample_rate2; }
            set
            {
                sample_rate2 = value;
                Audio.SampleRate2 = value;
            }
        }

        private int sample_rate3 = 48000;
        public int SampleRate3
        {
            get { return sample_rate3; }
            set
            {
                sample_rate3 = value;
                Audio.SampleRate3 = value;
            }
        }

        private int block_size1;
        public int BlockSize1
        {
            get { return block_size1; }
            set
            {
                block_size1 = value;
                Audio.BlockSize = value;
            }
        }

        private int block_size_rx2;
        public int BlockSizeRX2
        {
            get { return block_size_rx2; }
            set
            {
                block_size_rx2 = value;
                Audio.BlockSizeRX2 = value;
            }
        }

        //[2.10.3.4]MW0LGE added for completeness
        private int block_size_tx;
        public int BlockSizeTX
        {
            get { return block_size_tx; }
            set
            {
                block_size_tx = value;
                Audio.BlockSizeTX = value;
            }
        }

        private int block_size2;
        public int BlockSize2
        {
            get { return block_size2; }
            set
            {
                block_size2 = value;
                Audio.BlockSizeVAC = value;
            }
        }

        private int block_size3;
        public int BlockSize3
        {
            get { return block_size3; }
            set
            {
                block_size3 = value;
                Audio.BlockSizeVAC2 = value;
            }
        }

        private int peak_text_delay = 500;
        public int PeakTextDelay
        {
            get { return peak_text_delay; }
            set
            {
                peak_text_delay = value;
                timer_peak_text.Interval = value;
            }
        }

        private int meter_delay = 50;
        public int MeterDelay
        {
            get { return meter_delay; }
            set
            {
                meter_delay = value;
                MultimeterPeakHoldTime = MultimeterPeakHoldTime;
            }
        }

        private int meter_dig_delay = 200;
        public int MeterDigDelay
        {
            get { return meter_dig_delay; }
            set { meter_dig_delay = value; }
        }

        private int cpu_meter_delay = 1000;
        public int CPUMeterDelay
        {
            get { return cpu_meter_delay; }
            set
            {
                cpu_meter_delay = value;
                timer_cpu_volts_meter.Interval = value;
            }
        }

        private int RX1display_grid_x = 0;
        public int RX1DisplayGridX
        {
            get { return RX1display_grid_x; }
            set
            {
                RX1display_grid_x = value;
            }
        }

        private int RX1display_grid_w = 0;
        public int RX1DisplayGridW {
            get { return RX1display_grid_w; }
            set
            {
                RX1display_grid_w = value;
            }
        }
        private int RX2display_grid_x = 0;
        public int RX2DisplayGridX {
            get { return RX2display_grid_x; }
            set {
                RX2display_grid_x = value;
            }
        }

        private int RX2display_grid_w = 0;
        public int RX2DisplayGridW {
            get { return RX2display_grid_w; }
            set {
                RX2display_grid_w = value;
            }
        }

        private int _display_fps = 60;
        private double _display_delay = 1000 / 60f;
        public int DisplayFPS
        {
            get { return _display_fps; }
            set
            {
                _display_fps = value;
                if (_display_fps > MAX_FPS) _display_fps = MAX_FPS;
                if (_display_fps < 1) _display_fps = 1;
                _display_delay = 1000 / (float)_display_fps;

                Display.CurrentFPS = _display_fps; //MW0LGE_21k8 pre init

                int wdspFps = (int)Math.Max(1, _display_fps * 1.1f); //[2.10.3]MW0LGE add in 10% extra so frames are more often avaialble for use in RunDisplay()
                specRX.GetSpecRX(0).FrameRate = wdspFps;
                specRX.GetSpecRX(1).FrameRate = wdspFps;
                specRX.GetSpecRX(cmaster.inid(1, 0)).FrameRate = wdspFps;
            }
        }

        private int multimeter_peak_hold_time = 500;
        private int multimeter_peak_hold_samples = 10;
        public int MultimeterPeakHoldTime
        {
            get { return multimeter_peak_hold_time; }
            set
            {
                multimeter_peak_hold_time = value;
                multimeter_peak_hold_samples = value / meter_delay;
            }
        }

        private int multimeter_text_peak_time = 500;
        private int multimeter_text_peak_samples = 5;
        public int MultimeterTextPeakTime
        {
            get { return multimeter_text_peak_time; }
            set
            {
                multimeter_text_peak_time = value;
                multimeter_text_peak_samples = value / meter_delay;
                if (multimeter_text_peak_samples > meter_text_history.Length)
                {
                    float[] temp = new float[multimeter_text_peak_samples];
                    for (int i = 0; i < meter_text_history.Length; i++)
                        temp[i] = meter_text_history[i];
                    meter_text_history = temp;
                }
            }
        }

        private Pen txtvfoafreq_forecolor_pen = new Pen(Color.Yellow, 2.0f);
        private Color vfo_text_light_color = Color.Yellow;
        public Color VFOTextLightColor
        {
            get { return vfo_text_light_color; }
            set
            {
                if (chkPower.Checked)
                {
                    txtVFOAFreq.ForeColor = value;
                    txtVFOAMSD.ForeColor = value;
                    txtvfoafreq_forecolor_pen.Color = vfo_text_light_color;
                }

                vfo_text_light_color = value;
            }
        }

        private Color vfo_text_dark_color = Color.Olive;
        public Color VFOTextDarkColor
        {
            get { return vfo_text_dark_color; }
            set
            {
                if (!chkPower.Checked)
                {
                    txtVFOAFreq.ForeColor = value;
                    txtVFOAMSD.ForeColor = value;
                    txtVFOALSD.ForeColor = value;
                    txtvfoafreq_forecolor_pen.Color = vfo_text_dark_color;
                }
                if (!chkVFOSplit.Checked)
                {
                    txtVFOBFreq.ForeColor = value;
                    txtVFOBMSD.ForeColor = value;
                    txtVFOBLSD.ForeColor = value;
                }

                vfo_text_dark_color = value;
            }
        }

        private Color band_text_light_color = Color.Lime;
        public Color BandTextLightColor
        {
            get { return band_text_light_color; }
            set
            {
                if (chkPower.Checked)
                    txtVFOABand.ForeColor = value;
                if (chkVFOSplit.Checked)
                    txtVFOBBand.ForeColor = value;

                band_text_light_color = value;
            }
        }

        private Color band_text_dark_color = Color.Green;
        public Color BandTextDarkColor
        {
            get { return band_text_dark_color; }
            set
            {
                if (!chkPower.Checked)
                    txtVFOABand.ForeColor = value;
                if (!chkVFOSplit.Checked)
                    txtVFOBBand.ForeColor = value;

                band_text_dark_color = value;
            }
        }

        private Color peak_text_color = Color.DodgerBlue;
        public Color PeakTextColor
        {
            get { return peak_text_color; }
            set
            {
                peak_text_color = value;
                infoBar.ForeColor = peak_text_color;
            }
        }

        private Color out_of_band_color = Color.DimGray;
        public Color OutOfBandColor
        {
            get { return out_of_band_color; }
            set
            {
                out_of_band_color = value;
                if (!IsSetupFormNull)
                    txtVFOAFreq_LostFocus(this, EventArgs.Empty);
            }
        }

        private Color button_selected_color = Color.Yellow;
        public Color ButtonSelectedColor
        {
            get { return button_selected_color; }
            set
            {
                button_selected_color = value;
                rx1_band_color = button_selected_color;
                CheckSelectedButtonColor();
            }
        }

        private Color meter_left_color = Color.Green;
        public Color MeterLeftColor
        {
            get { return meter_left_color; }
            set
            {
                meter_left_color = value;
                picMultiMeterDigital.Invalidate();
            }
        }

        private Color meter_right_color = Color.Lime;
        public Color MeterRightColor
        {
            get { return meter_right_color; }
            set
            {
                meter_right_color = value;
                picMultiMeterDigital.Invalidate();
            }
        }

        private Color rx1_band_color = Color.Yellow;
        public Color RX1BandColor
        {
            get { return rx1_band_color; }
            set
            {
                rx1_band_color = value;
            }
        }

        private Color rx2_band_color = Color.Green;
        public Color RX2BandColor
        {
            get { return rx2_band_color; }
            set
            {
                rx2_band_color = value;
            }
        }

        private Color tx_band_color = Color.Red;
        public Color TXBandColor
        {
            get { return tx_band_color; }
            set
            {
                tx_band_color = value;
            }
        }

        private Keys key_tune_up_1 = Keys.Q;
        public Keys KeyTuneUp1
        {
            get { return key_tune_up_1; }
            set { key_tune_up_1 = value; }
        }

        private Keys key_tune_down_1 = Keys.A;
        public Keys KeyTuneDown1
        {
            get { return key_tune_down_1; }
            set { key_tune_down_1 = value; }
        }

        private Keys key_tune_up_2 = Keys.W;
        public Keys KeyTuneUp2
        {
            get { return key_tune_up_2; }
            set { key_tune_up_2 = value; }
        }

        private Keys key_tune_down_2 = Keys.S;
        public Keys KeyTuneDown2
        {
            get { return key_tune_down_2; }
            set { key_tune_down_2 = value; }
        }

        private Keys key_tune_up_3 = Keys.E;
        public Keys KeyTuneUp3
        {
            get { return key_tune_up_3; }
            set { key_tune_up_3 = value; }
        }

        private Keys key_tune_down_3 = Keys.D;
        public Keys KeyTuneDown3
        {
            get { return key_tune_down_3; }
            set { key_tune_down_3 = value; }
        }

        private Keys key_tune_up_4 = Keys.R;
        public Keys KeyTuneUp4
        {
            get { return key_tune_up_4; }
            set { key_tune_up_4 = value; }
        }

        private Keys key_tune_down_4 = Keys.F;
        public Keys KeyTuneDown4
        {
            get { return key_tune_down_4; }
            set { key_tune_down_4 = value; }
        }

        private Keys key_tune_up_5 = Keys.T;
        public Keys KeyTuneUp5
        {
            get { return key_tune_up_5; }
            set { key_tune_up_5 = value; }
        }

        private Keys key_tune_down_5 = Keys.G;
        public Keys KeyTuneDown5
        {
            get { return key_tune_down_5; }
            set { key_tune_down_5 = value; }
        }

        private Keys key_tune_up_6 = Keys.Y;
        public Keys KeyTuneUp6
        {
            get { return key_tune_up_6; }
            set { key_tune_up_6 = value; }
        }

        private Keys key_tune_down_6 = Keys.H;
        public Keys KeyTuneDown6
        {
            get { return key_tune_down_6; }
            set { key_tune_down_6 = value; }
        }

        private Keys key_tune_up_7 = Keys.U;
        public Keys KeyTuneUp7
        {
            get { return key_tune_up_7; }
            set { key_tune_up_7 = value; }
        }

        private Keys key_tune_down_7 = Keys.J;
        public Keys KeyTuneDown7
        {
            get { return key_tune_down_7; }
            set { key_tune_down_7 = value; }
        }

        private Keys key_rit_up = Keys.O;
        public Keys KeyRITUp
        {
            get { return key_rit_up; }
            set { key_rit_up = value; }
        }

        private Keys key_rit_down = Keys.I;
        public Keys KeyRITDown
        {
            get { return key_rit_down; }
            set { key_rit_down = value; }
        }

        private int rit_step_rate = 50;
        public int RITStepRate
        {
            get { return rit_step_rate; }
            set { rit_step_rate = value; }
        }

        private Keys key_xit_up = Keys.OemOpenBrackets;
        public Keys KeyXITUp
        {
            get { return key_xit_up; }
            set { key_xit_up = value; }
        }

        private Keys key_xit_down = Keys.P;
        public Keys KeyXITDown
        {
            get { return key_xit_down; }
            set { key_xit_down = value; }
        }

        private int xit_step_rate = 50;
        public int XITStepRate
        {
            get { return xit_step_rate; }
            set { xit_step_rate = value; }
        }

        private Keys key_band_up = Keys.M;
        public Keys KeyBandUp
        {
            get { return key_band_up; }
            set { key_band_up = value; }
        }

        private Keys key_band_down = Keys.N;
        public Keys KeyBandDown
        {
            get { return key_band_down; }
            set { key_band_down = value; }
        }

        private Keys key_filter_up = Keys.B;
        public Keys KeyFilterUp
        {
            get { return key_filter_up; }
            set { key_filter_up = value; }
        }

        private Keys key_filter_down = Keys.V;
        public Keys KeyFilterDown
        {
            get { return key_filter_down; }
            set { key_filter_down = value; }
        }

        private Keys key_mode_up = Keys.X;
        public Keys KeyModeUp
        {
            get { return key_mode_up; }
            set { key_mode_up = value; }
        }

        private Keys key_mode_down = Keys.Z;
        public Keys KeyModeDown
        {
            get { return key_mode_down; }
            set { key_mode_down = value; }
        }

        private Keys key_cw_dot = Keys.None;
        public Keys KeyCWDot
        {
            get { return key_cw_dot; }
            set { key_cw_dot = value; }
        }

        private Keys key_cw_dash = Keys.None;
        public Keys KeyCWDash
        {
            get { return key_cw_dash; }
            set { key_cw_dash = value; }
        }

        private Keys key_ptt_tx = Keys.None;
        public Keys KeyPTTTx
        {
            get { return key_ptt_tx; }
            set { key_ptt_tx = value; }
        }

        private Keys key_ptt_rx = Keys.None;
        public Keys KeyPTTRx
        {
            get { return key_ptt_rx; }
            set { key_ptt_rx = value; }
        }

        private bool rfe_pa_tr_enable = false;
        public bool RFE_PA_TR_enable
        {
            get { return rfe_pa_tr_enable; }
            set
            {
                rfe_pa_tr_enable = value;
                if (!IsSetupFormNull)
                    SetupForm.RFE_PA_TR = value;
            }
        }

        private Keys key_space_ptt = Keys.Space;
        public Keys KeySpacePTT
        {
            get { return key_space_ptt; }
            set { key_space_ptt = value; }
        }



        private bool xvtr_present = false;
        public bool XVTRPresent
        {
            get { return xvtr_present; }
            set
            {
                xvtr_present = value;
                radBand2.Enabled = value;
                //   Hdw.XVTRPresent = value;
                if (value)
                    MaxFreq = 146.0;
                else
                    MaxFreq = 65.0;

                if (path_Illustrator != null)
                    path_Illustrator.pi_Changed();
            }
        }

        private bool pa_present = false;
        public bool PAPresent
        {
            get { return pa_present; }
            set
            {
                bool oldValue = pa_present;

                pa_present = value;

                if (pa_present || alexpresent)
                {
                    if (comboMeterTXMode.SelectedIndex < 0)
                        comboMeterTXMode.SelectedIndex = 0;
                }
                else
                {
                    string cur_txt = comboMeterTXMode.Text;

                    comboMeterTXMode.Text = cur_txt;
                    if (comboMeterTXMode.SelectedIndex < 0 &&
                        comboMeterTXMode.Items.Count > 0)
                        comboMeterTXMode.SelectedIndex = 0;
                }
                ptbPWR_Scroll(this, EventArgs.Empty);

                if (oldValue != pa_present) PAPresentChangedHandlers?.Invoke(oldValue, pa_present); //MW0LGE_[2.9.0.7]
            }
        }

        private bool atu_present = false;
        public bool ATUPresent
        {
            get { return atu_present; }
            set
            {
                atu_present = value;
                comboTuneMode.Visible = atu_present;
                comboTuneMode.SelectedIndex = 0;
            }
        }

        private bool usb_present = false;
        public bool USBPresent
        {
            get { return usb_present; }
            set
            {
                usb_present = value;

            }
        }

        private bool m_bShowSystemCPUUsage = true;
        public volatile PerformanceCounter total_cpu_usage = null;
        public volatile PerformanceCounter total_thetis_usage = null;
        private volatile string _sInstanceName = "";
        private volatile bool _getInstanceNameComplete = false;

        private void getInstanceName()
        {
            //MW0LGE_21k9 updated to get actual process name used by perf counter
            //moved to thread, as GetInstanceNames is very very slow

            _sInstanceName = "";

            try
            {
                string sMachineName = System.Environment.MachineName;

                Process p = Process.GetCurrentProcess();

                PerformanceCounterCategory pcc = new PerformanceCounterCategory("Process", sMachineName);
                string[] sInstanceNames = pcc.GetInstanceNames();

                foreach (string sName in sInstanceNames.Where(o => o.StartsWith(p.ProcessName)))
                {
                    using (PerformanceCounter processId = new PerformanceCounter("Process", "ID Process", sName, true))
                    {
                        if (p.Id == (int)processId.RawValue)
                        {
                            _sInstanceName = sName;
                            break;
                        }
                    }
                }

                _getInstanceNameComplete = true;
            }
            catch
            {

            }
            Debug.Print("Get instance name done");
        }
        private bool _cpu_usage_setup = false;
        private void CpuUsage()
        {
            _cpu_usage_setup = false;

            if (!_getInstanceNameComplete)
            {
                disableCpuVoltsUsage();
                return; // thread has not finished getting the process counter related instance name            
            }

            try
            {
                systemToolStripMenuItem.Checked = m_bShowSystemCPUUsage;
                thetisOnlyToolStripMenuItem.Checked = !m_bShowSystemCPUUsage;

                string sMachineName = System.Environment.MachineName;

                if (total_cpu_usage != null)
                {
                    total_cpu_usage.Close();
                    total_cpu_usage.Dispose(); //MW0LGE_21k8
                    total_cpu_usage = null;
                }

                if (total_thetis_usage != null)
                {
                    total_thetis_usage.Close();
                    total_thetis_usage.Dispose(); //MW0LGE_21k8
                    total_thetis_usage = null;
                }

                //NOTE: run 'lodctr /R' on admin command prompt to rebuild performance counters

                Version osVersion = Environment.OSVersion.Version;
                bool isWindows7 = osVersion.Major == 6 && osVersion.Minor == 1;

                if (isWindows7)
                {
                    total_cpu_usage = new PerformanceCounter("Processor", "% Processor Time", "_Total", sMachineName);
                }
                else
                {
                    total_cpu_usage = new PerformanceCounter("Processor Information", "% Processor Utility", "_Total", sMachineName);
                }
                float tmp = total_cpu_usage.NextValue();

                if (!string.IsNullOrEmpty(_sInstanceName))
                {
                    total_thetis_usage = new PerformanceCounter("Process", "% Processor Time", _sInstanceName, sMachineName);
                    tmp = total_thetis_usage.NextValue();
                }

                _cpu_usage_setup = true;
            }
            catch
            {
                disableCpuVoltsUsage();
            }
        }

        private void disableCpuVoltsUsage()
        {
            timer_cpu_volts_meter.Enabled = false;

            systemToolStripMenuItem.Checked = false;
            thetisOnlyToolStripMenuItem.Checked = false;
            toolStripDropDownButton_CPU.Visible = false;

            //[2.10.3.4]MW0LGE volts/amps as well because there are both part of the same timer tick
            toolStripStatusLabel_Volts.Visible = false;
            toolStripStatusLabel_Amps.Visible = false;
        }

        private int scope_time = 50;
        public int ScopeTime
        {
            get { return scope_time; }
            set
            {
                scope_time = value;
                Display.ScopeTime = value;
            }
        }

        // Added 6/11/05 BT to support CAT
        public float MultiMeterCalOffset
        {
            get { return rx1_meter_cal_offset; }
        }

        //Added 7/11/2010 BT to support CAT
        public float RX2MeterCalOffset
        {
            get { return rx2_meter_cal_offset; }
        }

        public float PreampOffset
        {
            get { return rx1_preamp_offset[(int)rx1_preamp_mode]; }
        }

        private bool m_bAntiAlias = false;
        public bool AntiAlias {
            get { return m_bAntiAlias; }
            set {
                m_bAntiAlias = value;
                Display.AntiAlias = m_bAntiAlias;
            }
        }

        private MultiMeterMeasureMode m_eMeasureMode = MultiMeterMeasureMode.DBM;
        public MultiMeterMeasureMode MMMeasureMode {
            get { return m_eMeasureMode; }
            set { m_eMeasureMode = value; }
        }

        private bool spacebar_last_btn = false;
        public bool SpaceBarLastBtn
        {
            get { return spacebar_last_btn; }
            set { spacebar_last_btn = value; }
        }

        private bool spacebar_ptt = true;
        public bool SpaceBarPTT
        {
            get { return spacebar_ptt; }
            set { spacebar_ptt = value; }
        }

        private bool spacebar_vox = false;
        public bool SpaceBarVOX
        {
            get { return spacebar_vox; }
            set { spacebar_vox = value; }
        }

        private bool spacebar_mic_mute = false;
        public bool SpaceBarMicMute
        {
            get { return spacebar_mic_mute; }
            set { spacebar_mic_mute = value; }
        }

        public bool RXEQ
        {
            get
            {
                if (chkRXEQ != null) return chkRXEQ.Checked;
                else return false;
            }
            set
            {
                if (chkRXEQ != null) chkRXEQ.Checked = value;
            }
        }

        public bool TXEQ
        {
            get
            {
                if (chkTXEQ != null) return chkTXEQ.Checked;
                else return false;
            }
            set
            {
                if (chkTXEQ != null) chkTXEQ.Checked = value;
            }
        }

        private bool disable_split_on_bandchange = false;
        public bool DisableSplitOnBandchange
        {
            get { return disable_split_on_bandchange; }
            set { disable_split_on_bandchange = value; }
        }
        private bool _preventTXonDifferentBandToRXband = false;
        public bool PreventTXonDifferentBandToRXband
        {
            get { return _preventTXonDifferentBandToRXband; }
            set { _preventTXonDifferentBandToRXband = value; }
        }
        private bool spacenav_controlvfos = true;
        public bool SpaceNavControlVFOs
        {
            get { return spacenav_controlvfos; }
            set { spacenav_controlvfos = value; }
        }

        private bool spacenav_flypanadapter = false;
        public bool SpaceNavFlyPanadapter
        {
            get { return spacenav_flypanadapter; }
            set { spacenav_flypanadapter = value; }
        }

        private bool enable_vu_power_curve = true;
        public bool Enable_VU_Power_Curve
        {
            get { return enable_vu_power_curve; }
            set { enable_vu_power_curve = value; }
        }

        private string current_skin = "Default";
        public string CurrentSkin
        {
            get { return current_skin; }
            set
            {
                current_skin = value;
            }
        }

        private bool radar_color_update = false;
        public bool RadarColorUpdate
        {
            get { return radar_color_update; }
            set
            {
                radar_color_update = value;
            }
        }

        private double fm_tx_offset_mhz = 0;
        public double FMTXOffsetMHz
        {
            get { return fm_tx_offset_mhz; }
            set
            {
                if (value < (double)udFMOffset.Minimum || value > (double)udFMOffset.Maximum) return; //MW0LGE_21k9

                fm_tx_offset_mhz = value;
                if (udFMOffset.Value != (decimal)fm_tx_offset_mhz)
                    udFMOffset.Value = (decimal)fm_tx_offset_mhz;
            }
        }

        private FMTXMode current_fm_tx_mode = FMTXMode.Simplex;
        public FMTXMode CurrentFMTXMode
        {
            get { return current_fm_tx_mode; }
            set
            {
                current_fm_tx_mode = value;
                switch (current_fm_tx_mode)
                {
                    case FMTXMode.High:
                        if (!chkFMTXHigh.Checked)
                            chkFMTXHigh.Checked = true;
                        break;
                    case FMTXMode.Simplex:
                        if (!chkFMTXSimplex.Checked)
                            chkFMTXSimplex.Checked = true;
                        break;
                    case FMTXMode.Low:
                        if (!chkFMTXLow.Checked)
                            chkFMTXLow.Checked = true;
                        break;
                }
                txtVFOAFreq_LostFocus(this, EventArgs.Empty);
            }
        }

        private int fm_deviation_hz = 5000;
        public int FMDeviation_Hz
        {
            get { return fm_deviation_hz; }
            set
            {
                fm_deviation_hz = value;
                if (fm_deviation_hz == 5000)
                {
                    radFMDeviation2kHz.Checked = false;
                    radFMDeviation5kHz.Checked = true;
                }
                else if (fm_deviation_hz == 2500)
                {
                    radFMDeviation5kHz.Checked = false;
                    radFMDeviation2kHz.Checked = true;
                }
            }
        }

        private bool show_agc = true;
        public bool ShowAGC
        {
            get { return show_agc; }
            set
            {
                show_agc = value;
                Display.ShowAGC = value;
            }
        }

        private bool display_agc_hang_line = true;
        public bool DisplayAGCHangLine
        {
            get { return display_agc_hang_line; }
            set
            {
                display_agc_hang_line = value;
                Display.DisplayAGCHangLine = value;
            }
        }
        private bool display_rx2_gain_line = true;
        public bool DisplayRX2GainLine
        {
            get { return display_rx2_gain_line; }
            set
            {
                display_rx2_gain_line = value;
                Display.DisplayRX2GainLine = value;
            }
        }

        private bool display_rx2_hang_line = true;
        public bool DisplayRX2HangLine
        {
            get { return display_rx2_hang_line; }
            set
            {
                display_rx2_hang_line = value;
                Display.DisplayRX2HangLine = value;
            }
        }

        #endregion

        #region Display Routines

        private static bool isBitSet(int n, int pos)
        {
            return (n & (1 << pos)) != 0;
        }
        //
        public void ShowSEQLog()
        {
            m_frmSeqLog.InitAndShow();
            m_frmSeqLog.BringToFront();
        }

        private float _avNumRX1 = -200;
        private float _avNumRX2 = -200;

        public float RXOffset(int rx)
        {
            float fOffset = 0;
            if (rx == 1)
            {
                fOffset = rx1_step_att_present ? (float)rx1_attenuator_data : rx1_preamp_offset[(int)rx1_preamp_mode];
                fOffset += rx1_meter_cal_offset + rx1_xvtr_gain_offset + rx1_6m_gain_offset;
            }
            else //rx2
            {
                if (current_hpsdr_model == HPSDRModel.ANAN100D ||
                    current_hpsdr_model == HPSDRModel.ANAN200D ||
                    current_hpsdr_model == HPSDRModel.ORIONMKII ||
                    current_hpsdr_model == HPSDRModel.ANAN7000D ||
                    current_hpsdr_model == HPSDRModel.ANAN8000D ||
                    current_hpsdr_model == HPSDRModel.ANAN_G2 ||
                    current_hpsdr_model == HPSDRModel.ANAN_G2_1K ||
                    rx2_preamp_present)
                {
                    if (rx2_step_att_present)
                        fOffset = (float)rx2_attenuator_data;
                    else
                        fOffset = rx2_preamp_offset[(int)rx2_preamp_mode];
                }
                else
                {
                    if (rx1_step_att_present)
                        fOffset = (float)rx1_attenuator_data;
                    else
                        fOffset = rx1_preamp_offset[(int)rx1_preamp_mode];
                }
                fOffset += rx2_meter_cal_offset + rx2_xvtr_gain_offset;
                if (current_hpsdr_model == HPSDRModel.ANAN7000D || current_hpsdr_model == HPSDRModel.ANAN8000D ||
                    current_hpsdr_model == HPSDRModel.ANAN_G2 || current_hpsdr_model == HPSDRModel.ANAN_G2_1K) fOffset += rx2_6m_gain_offset;
            }
            return fOffset;
        }
        public float RXPBsnr(int rx)
        {
            float offset = RXOffset(rx);
            if (rx == 1)
            {
                if (!Display.FastAttackNoiseFloorRX1 && _lastRX1NoiseFloorGood)
                {
                    float num = WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.AVG_SIGNAL_STRENGTH) + offset;
                    spectralCalculations(1, num, out double bin_width, out double dRWB, out int passbandWidth, out double noise_floor_power_spectral_density, out double estimated_passband_noise_power, out double estimated_snr, out double rx_dBHz, out double rbw_dBHz);
                    return (float)estimated_snr;
                }
                else
                    return -999;
            }
            else
            {
                if (!Display.FastAttackNoiseFloorRX2 && _lastRX2NoiseFloorGood)
                {
                    float num = WDSP.CalculateRXMeter(2, 0, WDSP.MeterType.AVG_SIGNAL_STRENGTH) + offset;
                    spectralCalculations(2, num, out double bin_width, out double dRWB, out int passbandWidth, out double noise_floor_power_spectral_density, out double estimated_passband_noise_power, out double estimated_snr, out double rx_dBHz, out double rbw_dBHz);
                    return (float)estimated_snr;
                }
                else
                    return -999;
            }
        }
        private double m_fRX1_PBSNR_shift = 0;
        private double m_fRX2_PBSNR_shift = 0;
        public double RX1PBsnrShift
        {
            get { return m_fRX1_PBSNR_shift; }
            set
            {
                m_fRX1_PBSNR_shift = value;
            }
        }
        public double RX2PBsnrShift
        {
            get { return m_fRX2_PBSNR_shift; }
            set
            {
                m_fRX2_PBSNR_shift = value;
            }
        }
        private void spectralCalculations(int rx, double signal, out double bin_width, out double dRWB, out int passbandWidth, out double noise_floor_power_spectral_density, out double estimated_passband_noise_power, out double estimated_snr, out double rx_dBHz, out double rbw_dBHz)
        {
            estimated_snr = 0;

            if (rx == 1)
            {
                bin_width = (double)specRX.GetSpecRX(0).SampleRate / (double)specRX.GetSpecRX(0).FFTSize;
                dRWB = specRX.GetSpecRX(0).DisplayENB * bin_width;
                passbandWidth = Display.RX1FilterHigh - Display.RX1FilterLow;

                noise_floor_power_spectral_density = _lastRX1NoiseFloor - (10 * Math.Log10(dRWB));
                estimated_passband_noise_power = noise_floor_power_spectral_density + (10 * Math.Log10(passbandWidth));

                if (!MOX)
                {
                    estimated_snr = signal - estimated_passband_noise_power + m_fRX1_PBSNR_shift;
                }
            }
            else//rx2
            {
                bin_width = (double)specRX.GetSpecRX(1).SampleRate / (double)specRX.GetSpecRX(1).FFTSize;
                dRWB = specRX.GetSpecRX(1).DisplayENB * bin_width;
                passbandWidth = Display.RX2FilterHigh - Display.RX2FilterLow;

                noise_floor_power_spectral_density = _lastRX2NoiseFloor - (10 * Math.Log10(dRWB));
                estimated_passband_noise_power = noise_floor_power_spectral_density + (10 * Math.Log10(passbandWidth));

                if (!MOX)
                {
                    estimated_snr = signal - estimated_passband_noise_power + m_fRX2_PBSNR_shift;
                }
            }
            rx_dBHz = 10 * Math.Log10((double)passbandWidth);//MW0LGE_22b
            rbw_dBHz = 10 * Math.Log10(dRWB);
        }
        private class HistoricAttenuatorReading
        {
            public int stepAttenuator = -1;
            public PreampMode preampMode = PreampMode.FIRST;
        }
        private bool _have_sync = false;
        private bool _had_radio_sync = false;
        private int[] _adc_overload_level = new int[3] { 0, 0, 0 }; // increases by one each cycle to max of 10
        private bool[] _adc_overloaded = new bool[3] { false, false, false };
        private int[] _adc_step_shift = new int[3] { 0, 0, 0 }; // from 0 to 31, which will get applied to any att
        private Stack<HistoricAttenuatorReading> _historic_attenuator_readings_rx1 = new Stack<HistoricAttenuatorReading>();
        private Stack<HistoricAttenuatorReading> _historic_attenuator_readings_rx2 = new Stack<HistoricAttenuatorReading>();
        private Stack<HistoricAttenuatorReading> _historic_attenuator_readings_tx = new Stack<HistoricAttenuatorReading>();       
        private bool _auto_attTX_when_not_in_ps = false;
        private bool _auto_undoTXatt = false;
        private bool _auto_attTX_rx1 = false;
        private bool _auto_attTX_rx2 = false;
        private bool _auto_att_undo_rx1 = false;
        private bool _auto_att_undo_rx2 = false;
        private int _auto_att_hold_delay_rx1 = 5;
        private int _auto_att_hold_delay_rx2 = 5;
        private DateTime _auto_att_last_hold_time_rx1 = DateTime.Now;
        private DateTime _auto_att_last_hold_time_rx2 = DateTime.Now;
        public bool AutoAttRX1
        {
            get { return _auto_attTX_rx1; }
            set { _auto_attTX_rx1 = value; }
        }
        public bool AutoAttUndoRX1
        {
            get { return _auto_att_undo_rx1; }
            set { _auto_att_undo_rx1 = value; }
        }
        public int AutoAttUndoDelayRX1
        {
            get { return _auto_att_hold_delay_rx1; }
            set { _auto_att_hold_delay_rx1 = value; }
        }
        public bool AutoAttRX2
        {
            get { return _auto_attTX_rx2; }
            set { _auto_attTX_rx2 = value; }
        }
        public bool AutoAttUndoRX2
        {
            get { return _auto_att_undo_rx2; }
            set { _auto_att_undo_rx2 = value; }
        }
        public int AutoAttUndoDelayRX2
        {
            get { return _auto_att_hold_delay_rx2; }
            set { _auto_att_hold_delay_rx2 = value; }
        }
        public bool HaveSync
        {
            get 
            {
                return _have_sync;
            }
            set 
            {
                _have_sync = value;
            }
        }
        public bool AutoAttTXWhenNotInPS
        {
            get { return _auto_attTX_when_not_in_ps; }
            set 
            { 
                _auto_attTX_when_not_in_ps = value;
                if (_auto_attTX_when_not_in_ps && !ATTOnTX) ATTOnTX = true;

                //check setup if we are turning this off
                if (!_auto_attTX_when_not_in_ps && !IsSetupFormNull)
                {
                    if (ATTOnTX && !SetupForm.ATTOnTXChecked) ATTOnTX = false;
                }
            }
        }
        public bool UndoAutoATttTX
        {
            get { return _auto_undoTXatt; }
            set { _auto_undoTXatt = value; }
        }
        private async void checkOverloads()
        {
            string sWarning = "";
            bool red_warning = false;
            bool overload_only = true;

            _have_sync = NetworkIO.getHaveSync() == 1;
            if (!_have_sync)
            {
                // set ui to power off if lost connection to radio
                if (chkPower.Checked) chkPower.Checked = false;
                if (_had_radio_sync)
                {
                    sWarning = "Lost Radio Sync   ";
                    _had_radio_sync = false;
                    overload_only = false;
                }
            }
            else if (!_had_radio_sync) _had_radio_sync = true;

            // check for amp overload
            bool amp_oload = amp_protect && cmaster.GetAndResetAmpProtect(0) == 1;
            if (amp_oload)
            {
                ptbPWR.Value -= 2;
                ptbPWR_Scroll(this, EventArgs.Empty);
                await Task.Delay(100);
                cmaster.GetAndResetAmpProtect(0);

                sWarning += "AMP Overload  ";
                overload_only = false;
            }

            string[] adc_names = { "ADC0", "ADC1", "ADC2" }; // adc2 not used for anything atm, but here for completeness

            int adc_oload_num = NetworkIO.getAndResetADC_Overload();
            if(adc_oload_num > 0)
            {
                // this is done so that if in a constant overload state, the above call to getAndResetADC_Overload would return 0,
                // this call below will 'use' this up just like amp overload above
                NetworkIO.getAndResetADC_Overload();
            }
            /*
                    overload adc_oload_num
            | adc[0] | adc[1] | adc[2] |          |
            |--------|--------|--------|----------|
            |   0    |   0    |   0    |    0     |
            |   1    |   0    |   0    |    1     |
            |   0    |   1    |   0    |    2     |
            |   1    |   1    |   0    |    3     |
            |   0    |   0    |   1    |    4     |
            |   1    |   0    |   1    |    5     |
            |   0    |   1    |   1    |    6     |
            |   1    |   1    |   1    |    7     |
            */

            for (int i = 0; i < 3; i++)
            {
                _adc_overloaded[i] = ((adc_oload_num >> i) & 1) != 0;

                if (_adc_overloaded[i])
                {
                    _adc_overload_level[i] += 2;
                    if (_adc_overload_level[i] > 5)
                        _adc_overload_level[i] = 5;

                    red_warning = _adc_overload_level[i] > 3; // turn red
                }
                else
                {
                    if(_adc_overload_level[i] > 0) _adc_overload_level[i]--;
                }

                if (_adc_overload_level[i] > 0)
                {
                    sWarning += $"{adc_names[i]} Overload   ";
                }
            }

            // set the adc warning
            if (!string.IsNullOrEmpty(sWarning))
            {
                sWarning = sWarning.Trim();
                infoBar.Warning(sWarning, red_warning, overload_only ? 1000 : 2000);
            }

            //adjust s-att offset
            handleOverload();
        }
        private void handleOverload()
        {            
            for (int i = 0; i < 3; i++)
            {
                if (_adc_overloaded[i])
                {
                    _adc_step_shift[i]++;
                    if (_adc_step_shift[i] > 31) _adc_step_shift[i] = 31;
                }
                else
                {
                    if (_adc_step_shift[i] > 0) _adc_step_shift[i]--;
                }
            }

            // deal with TX when not in PS-AUTO
            if (_auto_attTX_when_not_in_ps)
            {
                if (psform != null && !psform.AutoCalEnabled)
                {
                    if (_mox)
                    {
                        if (_adc_overloaded[0]) // always adc0 when in tx
                        {
                            HistoricAttenuatorReading har = new HistoricAttenuatorReading();
                            har.stepAttenuator = TxAttenData;

                            int att = har.stepAttenuator + _adc_step_shift[0];
                            if (att > 31) att = 31;

                            if (att != har.stepAttenuator)
                            {
                                if (!ATTOnTX) ATTOnTX = true;
                                TxAttenData = att;
                                _historic_attenuator_readings_tx.Push(har);
                            }
                        }
                    }
                    else if (_historic_attenuator_readings_tx.Any())
                    {
                        // no overload, unwind
                        HistoricAttenuatorReading har = _historic_attenuator_readings_tx.Pop();
                        if (_auto_undoTXatt && har != null && har.stepAttenuator != TxAttenData)
                        {
                            TxAttenData = har.stepAttenuator;
                        }
                    }
                }
                else
                    _historic_attenuator_readings_tx.Clear();
            }

            if (!_mox)
            {
                // deal with rx
                int nRX1DDCinUse = -1, nRX2DDCinUse = -1, sync1 = -1, sync2 = -1, psrx = -1, pstx = -1;
                GetDDC(out nRX1DDCinUse, out nRX2DDCinUse, out sync1, out sync2, out psrx, out pstx);                               

                DateTime now = DateTime.Now;

                bool radioHasRx1Att = current_hpsdr_model == HPSDRModel.ANAN10 || current_hpsdr_model == HPSDRModel.ANAN10E ||
                            current_hpsdr_model == HPSDRModel.ANAN100 || current_hpsdr_model == HPSDRModel.ANAN100B ||
                            current_hpsdr_model == HPSDRModel.ANAN100D || current_hpsdr_model == HPSDRModel.ANAN200D ||
                            current_hpsdr_model == HPSDRModel.ANAN7000D || current_hpsdr_model == HPSDRModel.ANAN8000D ||
                            current_hpsdr_model == HPSDRModel.ANAN_G2 || current_hpsdr_model == HPSDRModel.ANAN_G2_1K;

                if (_auto_attTX_rx1 && radioHasRx1Att)
                {
                    int nRX1ADCinUse = GetADCInUse(nRX1DDCinUse); // (rx1)

                    // rx1
                    if ((_adc_overloaded[0] && nRX1ADCinUse == 0) || (_adc_overloaded[1] && nRX1ADCinUse == 1)) // rx1 overload
                    {
                        HistoricAttenuatorReading har = new HistoricAttenuatorReading();
                        if (RX1StepAttPresent)
                        {
                            har.stepAttenuator = RX1AttenuatorData;

                            int att = har.stepAttenuator + (_adc_overloaded[0] ? _adc_step_shift[0] : _adc_step_shift[1]);
                            if (att > 31) att = 31;

                            if (att != har.stepAttenuator)
                            {
                                RX1AttenuatorData = att;
                                _auto_att_last_hold_time_rx1 = now;
                                _historic_attenuator_readings_rx1.Push(har);
                            }
                        }
                        else
                        {
                            har.preampMode = RX1PreampMode;

                            PreampMode pam = har.preampMode;
                            switch (pam)
                            {
                                case PreampMode.HPSDR_OFF:
                                case PreampMode.HPSDR_ON:
                                    pam = PreampMode.SA_MINUS10;
                                    break;
                                case PreampMode.SA_MINUS10:
                                    pam = PreampMode.SA_MINUS20;
                                    break;
                                case PreampMode.SA_MINUS20:
                                    pam = PreampMode.SA_MINUS30;
                                    break;
                            }
                            if (pam != har.preampMode)
                            {
                                RX1PreampMode = pam;
                                _auto_att_last_hold_time_rx1 = now;
                                _historic_attenuator_readings_rx1.Push(har);
                            }
                        }
                    }
                    else if ((nRX1ADCinUse == 0 || nRX1ADCinUse == 1) && _historic_attenuator_readings_rx1.Any()) // no overload rx1
                    {
                        if (!_auto_att_undo_rx1 || (_auto_att_undo_rx1 && ((now - _auto_att_last_hold_time_rx1).TotalSeconds > _auto_att_hold_delay_rx1)))
                        {
                            // unwind
                            HistoricAttenuatorReading har = _historic_attenuator_readings_rx1.Pop();
                            if (har != null && _auto_att_undo_rx1)
                            {
                                if (RX1StepAttPresent && har.stepAttenuator != -1)
                                {
                                    if (har.stepAttenuator != RX1AttenuatorData) RX1AttenuatorData = har.stepAttenuator;
                                }
                                else if (har.preampMode != PreampMode.FIRST)
                                {
                                    if (har.preampMode != RX1PreampMode) RX1PreampMode = har.preampMode;
                                }
                            }
                        }
                    }
                }

                bool radioHasRx2Att = current_hpsdr_model == HPSDRModel.ANAN100D || current_hpsdr_model == HPSDRModel.ANAN200D || 
                            current_hpsdr_model == HPSDRModel.ANAN7000D || current_hpsdr_model == HPSDRModel.ANAN8000D ||
                            current_hpsdr_model == HPSDRModel.ANAN_G2 || current_hpsdr_model == HPSDRModel.ANAN_G2_1K;

                if (_auto_attTX_rx2 && radioHasRx2Att)
                {
                    int nRX2ADCinUse = GetADCInUse(nRX2DDCinUse); // (rx2)

                    // rx2
                    if ((_adc_overloaded[0] && nRX2ADCinUse == 0) || (_adc_overloaded[1] && nRX2ADCinUse == 1)) // rx2 overload
                    {
                        HistoricAttenuatorReading har = new HistoricAttenuatorReading();
                        if (RX2StepAttPresent)
                        {
                            har.stepAttenuator = RX2AttenuatorData;                            

                            int att = har.stepAttenuator + (_adc_overloaded[0] ? _adc_step_shift[0] : _adc_step_shift[1]);
                            if (att > 31) att = 31;

                            if (att != har.stepAttenuator)
                            {
                                RX2AttenuatorData = att;
                                _auto_att_last_hold_time_rx2 = now;
                                _historic_attenuator_readings_rx2.Push(har);
                            }
                        }
                        else
                        {
                            har.preampMode = RX2PreampMode;

                            PreampMode pam = har.preampMode;
                            switch (pam)
                            {
                                case PreampMode.HPSDR_OFF:
                                case PreampMode.HPSDR_ON:
                                    pam = PreampMode.SA_MINUS10;
                                    break;
                                case PreampMode.SA_MINUS10:
                                    pam = PreampMode.SA_MINUS20;
                                    break;
                                case PreampMode.SA_MINUS20:
                                    pam = PreampMode.SA_MINUS30;
                                    break;
                            }
                            if (pam != har.preampMode)
                            {
                                RX2PreampMode = pam;
                               _auto_att_last_hold_time_rx2 = now;
                                _historic_attenuator_readings_rx2.Push(har);
                            }
                        }
                    }
                    else if ((nRX2ADCinUse == 0 || nRX2ADCinUse == 1) && _historic_attenuator_readings_rx2.Any()) // no overload rx2
                    {
                        if (!_auto_att_undo_rx2 || (_auto_att_undo_rx2 && ((now - _auto_att_last_hold_time_rx2).TotalSeconds > _auto_att_hold_delay_rx2)))
                        {
                            // unwind
                            HistoricAttenuatorReading har = _historic_attenuator_readings_rx2.Pop();
                            if (har != null && _auto_att_undo_rx2)
                            {
                                if (RX2StepAttPresent && har.stepAttenuator != -1)
                                {
                                    if (har.stepAttenuator != RX2AttenuatorData) RX2AttenuatorData = har.stepAttenuator;
                                }
                                else if (har.preampMode != PreampMode.FIRST)
                                {
                                    if (har.preampMode != RX2PreampMode) RX2PreampMode = har.preampMode;
                                }
                            }
                        }
                    }
                }
            }            
        }
        private async void pollOverloadSyncSeqErr()
        {
            int count = 0;
            bool run = false;

            try
            {
                if (this.InvokeRequired)
                {
                    this.Invoke(new MethodInvoker(() =>
                    {
                        run = this.chkPower.Checked;
                    }));
                }
                else
                    run = this.chkPower.Checked;
            }
            catch { }

            while (run)
            {
                try
                {
                    if (this.InvokeRequired)
                    {
                        this.Invoke(new MethodInvoker(() =>
                        {
                            checkOverloads();
                            if (count == 0) checkSeqErrors();
                            run = this.chkPower.Checked;
                        }));
                    }
                    else
                    {
                        checkOverloads();
                        if (count == 0) checkSeqErrors();
                        run = this.chkPower.Checked;
                    }

                    count++;
                    if (count == 5) count = 0;
                }
                catch { }

                await Task.Delay(100);
            }
        }
        private void checkSeqErrors()
        {
            int ooo = NetworkIO.getOOO(); //Out Of Order packet
            if (ooo > 0)
            {
                //MW0LGE
                string s = "";
                if (isBitSet(ooo, 0)) s += "CC ";
                if (isBitSet(ooo, 1)) s += "DDC0 ";
                if (isBitSet(ooo, 2)) s += "DDC1 ";
                if (isBitSet(ooo, 3)) s += "DDC2 ";
                if (isBitSet(ooo, 4)) s += "DDC3 ";
                if (isBitSet(ooo, 5)) s += "DDC4 ";
                if (isBitSet(ooo, 6)) s += "DDC5 ";
                if (isBitSet(ooo, 7)) s += "DDC6 ";
                if (isBitSet(ooo, 8)) s += "Mic ";

                int[] nSeqLogData = new int[40]; //MAX_IN_SEQ_LOG
                StringBuilder sDateTimeStamp = new StringBuilder(24); // same size as dateTimeStamp in network.h

                bool bNegative = false;
                bool bDCCSeqErrors = false;
                for (int nDCC = 0; nDCC < 7; nDCC++)
                {
                    if (isBitSet(ooo, nDCC + 1))
                    {
                        bDCCSeqErrors = true;
                        string ss = "DCC" + nDCC.ToString() + System.Environment.NewLine;

                        int n = 0;
                        bool bInit = true;
                        uint rec_seq;
                        uint last_seq;
                        while (NetworkIO.getSeqInDelta(bInit, nDCC, nSeqLogData, sDateTimeStamp, out rec_seq, out last_seq))
                        {
                            bInit = false;
                            ss += "s" + n.ToString() + "=";
                            for (int ff = 0; ff < nSeqLogData.Length; ff++)
                            {
                                ss += nSeqLogData[ff].ToString() + " ";
                                if (nSeqLogData[ff] < 0) bNegative = true;// there have been negative packets, these are out of order, important !
                            }
                            ss += " r:" + rec_seq.ToString() + " l:" + last_seq.ToString() + " " + sDateTimeStamp.ToString() + System.Environment.NewLine;
                            n++;
                        }
                        m_frmSeqLog.LogString(ss);
                    }
                }

                if (bDCCSeqErrors)
                {
                    bool bShow = true;
                    if (bNegative)
                    {
                        toolStripStatusLabel_SeqWarning.BackColor = Color.Red;
                        DumpCap.StopDumpcap();
                    }
                    else
                    {
                        toolStripStatusLabel_SeqWarning.BackColor = Color.Transparent;
                        if (!DumpCap.KillOnNegativeSeqOnly) DumpCap.StopDumpcap();
                        bShow = !m_frmSeqLog.StatusBarWarningOnNegativeOnly;
                    }

                    DumpCap.StartDumpcap(2000);

                    toolStripStatusLabel_SeqWarning.Visible = bShow;
                }

                if (_bInfoBarShowSEQErrors) infoBar.Warning("Sequence error : " + ooo.ToString() + " (" + s.Trim() + ")"); //MW0LGE_21k9c show/hide flag
            }
        }
        private async void UpdatePeakText()
        {
            if (string.IsNullOrEmpty(txtVFOAFreq.Text) ||
                    txtVFOAFreq.Text == "." ||
                    txtVFOAFreq.Text == ",")
                return;

            bool bOverRX1 = !rx2_enabled;
            bool bOverRX2 = false;
            if (rx2_enabled)
            {
                if (DisplayCursorX != -1 && DisplayCursorY != -1)
                {
                    bOverRX1 = overRX(DisplayCursorX, DisplayCursorY, 1, false);
                    bOverRX2 = overRX(DisplayCursorX, DisplayCursorY, 2, false);
                }
                if (!bOverRX1 && !bOverRX2) bOverRX1 = true;
            }                                    

            // update peak value
            float x = PixelToHz(Display.MaxX);
            float y = Display.MaxY; // MW0LGE_21a this is already in dBm, not pixels

            double freq = VFOAFreq/*double.Parse(txtVFOAFreq.Text)*/ + (double)x * 0.0000010;

            //mostly copied from vfoa lost focus MW0LGE_21a
            switch (RX1DSPMode)
            {
                case DSPMode.CWL:
                    freq += cw_pitch * 1e-6;
                    break;
                case DSPMode.CWU:
                    freq -= cw_pitch * 1e-6;
                    break;
                case DSPMode.AM:
                case DSPMode.SAM:
                case DSPMode.FM:
                    if (chkTUN.Checked && !display_duplex) freq -= cw_pitch * 1e-6;
                    break;
                case DSPMode.USB:
                case DSPMode.DIGU:
                case DSPMode.DSB:
                    if (chkTUN.Checked && !display_duplex)
                    {
                        if (RX1IsOn60mChannel() && current_region == FRSRegion.US)
                            freq -= (ModeFreqOffset(rx1_dsp_mode) + cw_pitch * 1e-6);
                        else
                            freq -= cw_pitch * 1e-6;
                    }
                    break;
                case DSPMode.LSB:
                case DSPMode.DIGL:
                    if (chkTUN.Checked && !display_duplex) freq += cw_pitch * 1e-6;
                    break;
            }

            switch (Display.CurrentDisplayMode)
            {
                case DisplayMode.HISTOGRAM:
                case DisplayMode.PANADAPTER:
                case DisplayMode.SPECTRUM:
                case DisplayMode.WATERFALL:
                case DisplayMode.PANAFALL:
                case DisplayMode.PANASCOPE:
                case DisplayMode.SPECTRASCOPE:
                    infoBar.Right1(0, x.ToString("f1") + "Hz");
                    infoBar.Right2(0, y.ToString("f1") + "dBm");

                    double Freq = VFOAFreq;// double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                    string temp_text;
                    if ((click_tune_display && !_mox) || (click_tune_display && display_duplex))    // Correct Right hand peak frequency when CTUN on -G3OQD // MW0LGE_21a also when in CTD and DUP
                        temp_text = (freq + (CentreFrequency - Freq)).ToString("f6") + " MHz";      // Disply Right hand peak frequency under Spectrum - G3OQD                            
                    else
                        temp_text = freq.ToString("f6") + " MHz";  // Right hand - Peak frequency readout

                    int jper = temp_text.IndexOf(separator) + 4;
                    infoBar.Right3(0, temp_text.Insert(jper, " "));

                    break;
                default:
                    infoBar.Right1(0, "");
                    infoBar.Right2(0, "");
                    infoBar.Right3(0, "");
                    break;
            }

            if (bOverRX1 || bOverRX2)
            {
                double bin_width;
                double dRWB;
                double rx_dBHz;
                int passbandWidth;
                double rbw_dBHz;
                double noise_floor_power_spectral_density;
                double estimated_passband_noise_power;
                double estimated_snr;

                string sEstimated_snr = "";
                string sEstimated_passband_noise_power = "";

                if (bOverRX1)
                {
                    float num = -200f;
                    if (!MOX)
                    {
                        //
                        float rx1PreampOffset;
                        if (rx1_step_att_present) rx1PreampOffset = (float)rx1_attenuator_data;
                        else rx1PreampOffset = rx1_preamp_offset[(int)rx1_preamp_mode];

                        num = WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.AVG_SIGNAL_STRENGTH);
                        num = num +
                        rx1_meter_cal_offset +
                        rx1PreampOffset +
                        rx1_xvtr_gain_offset +
                        rx1_6m_gain_offset;

                        if (num > _avNumRX1) // quick rise
                            num = _avNumRX1 = num * 0.8f + _avNumRX1 * 0.2f;
                        else // slow fall
                            num = _avNumRX1 = num * 0.2f + _avNumRX1 * 0.8f;
                        //
                    }
                    spectralCalculations(1, num, out bin_width, out dRWB, out passbandWidth, out noise_floor_power_spectral_density, out estimated_passband_noise_power, out estimated_snr, out rx_dBHz, out rbw_dBHz);
                    if (!MOX)
                    {
                        estimated_snr = _avNumRX1 - estimated_passband_noise_power + m_fRX1_PBSNR_shift;

                        if (_UseSUnitsForPBNPPBSNR)
                        {
                            sEstimated_passband_noise_power = Common.GetSMeterUnits(estimated_passband_noise_power, VFOAFreq >= S9Frequency).ToString("N1") + "su";
                            sEstimated_snr = (estimated_snr / 6f).ToString("N1") + "su";
                        }
                        else
                        {
                            sEstimated_passband_noise_power = estimated_passband_noise_power.ToString("N1") + "dBm";
                            sEstimated_snr = estimated_snr.ToString("N1") + "dB";
                        }
                    }
                }
                else //rx2
                {
                    float num = -200f;
                    if (!MOX)
                    {
                        //
                        float rx2PreampOffset;
                        if (current_hpsdr_model == HPSDRModel.ANAN100D ||
                            current_hpsdr_model == HPSDRModel.ANAN200D ||
                            current_hpsdr_model == HPSDRModel.ORIONMKII ||
                            current_hpsdr_model == HPSDRModel.ANAN7000D ||
                            current_hpsdr_model == HPSDRModel.ANAN8000D ||
                            current_hpsdr_model == HPSDRModel.ANAN_G2 ||
                            current_hpsdr_model == HPSDRModel.ANAN_G2_1K ||
                            rx2_preamp_present)
                        {
                            if (rx2_step_att_present)
                                rx2PreampOffset = (float)rx2_attenuator_data;
                            else
                                rx2PreampOffset = rx2_preamp_offset[(int)rx2_preamp_mode];
                        }
                        else
                        {
                            if (rx1_step_att_present)
                                rx2PreampOffset = (float)rx1_attenuator_data;
                            else
                                rx2PreampOffset = rx1_preamp_offset[(int)rx1_preamp_mode];
                        }
                        num = WDSP.CalculateRXMeter(2, 0, WDSP.MeterType.AVG_SIGNAL_STRENGTH);
                        num = num +
                        rx2_meter_cal_offset +
                        rx2PreampOffset +
                        rx2_xvtr_gain_offset;
                        if (current_hpsdr_model == HPSDRModel.ANAN7000D || current_hpsdr_model == HPSDRModel.ANAN8000D ||
                            current_hpsdr_model == HPSDRModel.ANAN_G2 || current_hpsdr_model == HPSDRModel.ANAN_G2_1K) num += rx2_6m_gain_offset;

                        if (num > _avNumRX2) // quick rise
                            num = _avNumRX2 = num * 0.8f + _avNumRX2 * 0.2f;
                        else // slow fall
                            num = _avNumRX2 = num * 0.2f + _avNumRX2 * 0.8f;
                        //
                    }
                    spectralCalculations(2, num, out bin_width, out dRWB, out passbandWidth, out noise_floor_power_spectral_density, out estimated_passband_noise_power, out estimated_snr, out rx_dBHz, out rbw_dBHz);
                    if (!MOX)
                    {
                        estimated_snr = _avNumRX2 - estimated_passband_noise_power + m_fRX2_PBSNR_shift;

                        if (_UseSUnitsForPBNPPBSNR)
                        {
                            sEstimated_passband_noise_power = Common.GetSMeterUnits(estimated_passband_noise_power, VFOBFreq >= S9Frequency).ToString("N1") + "su";
                            sEstimated_snr = (estimated_snr / 6f).ToString("N1") + "sU";
                        }
                        else
                        {
                            sEstimated_passband_noise_power = estimated_passband_noise_power.ToString("N1") + "dBm";
                            sEstimated_snr = estimated_snr.ToString("N1") + "dBm";
                        }
                    }
                }
                rx_dBHz = 10 * Math.Log10((double)passbandWidth);//MW0LGE_22b
                rbw_dBHz = 10 * Math.Log10(dRWB);

                infoBar.Left1(1, "RBW " + dRWB.ToString("N1") + "Hz (" + rbw_dBHz.ToString("N1") + "dBHz)", 160);
                infoBar.Left2(1, "PB " + passbandWidth.ToString() + "Hz (" + rx_dBHz.ToString("N1") + "dBHz)", 160);

                if (!MOX)
                {
                    infoBar.Right1(1, "NPSD " + noise_floor_power_spectral_density.ToString("N1") + "dBm/Hz", 140);
                    infoBar.Right2(1, "PBNP " + sEstimated_passband_noise_power, 120);
                    infoBar.Right3(1, "PBSNR " + sEstimated_snr, 120);
                }
                else
                {
                    infoBar.Right1(1, "");
                    infoBar.Right2(1, "");
                    infoBar.Right3(1, "");
                }
            }
            else
            {
                infoBar.Left1(1, "");
                infoBar.Left2(1, "");

                infoBar.Right1(1, "");
                infoBar.Right2(1, "");
                infoBar.Right3(1, "");
            }
        }
        private bool _UseSUnitsForPBNPPBSNR = false;
        public bool UseSUnitsForPBNPPBSNR
        {
            get { return _UseSUnitsForPBNPPBSNR; }
            set { _UseSUnitsForPBNPPBSNR = value; }
        }
        private int HzInNPixels(int nPixelCount, int rx)
        {
            //[2.10.1.0] MW0LGE re-implemented
            getLowHighForRXn(rx, out int low, out int high);

            int width = high - low;
            return (int)((double)nPixelCount / (double)picDisplay.Width * (double)width);
        }

        private void getLowHighForRXn(int rx, out int low, out int high, bool bIncludeRitXit = true)
        {
            bool moxRX1 = _mox && (VFOATX || (VFOBTX && !RX2Enabled));
            bool moxRX2 = _mox && (VFOBTX && RX2Enabled);
            bool localMox = (moxRX1 && rx == 1) || (moxRX2 && rx == 2);
            bool specScope = rx == 1 && (Display.CurrentDisplayMode == DisplayMode.SPECTRUM || Display.CurrentDisplayMode == DisplayMode.HISTOGRAM);
            low = 0;
            high = 0;

            if (localMox)
            {
                if (rx == 1)
                {
                    if (moxRX1)
                    {
                        if (display_duplex)
                        {
                            low = specScope ? Display.RXSpectrumDisplayLow : Display.RXDisplayLow;
                            high = specScope ? Display.RXSpectrumDisplayHigh : Display.RXDisplayHigh;
                        }
                        else
                        {
                            low = specScope ? Display.TXSpectrumDisplayLow : Display.TXDisplayLow;
                            high = specScope ? Display.TXSpectrumDisplayHigh : Display.TXDisplayHigh;
                        }
                    }
                    else
                    {
                        low = Display.RXDisplayLow;
                        high = Display.RXDisplayHigh;
                    }
                }
                else
                {
                    if (moxRX2)
                    {
                        low = Display.TXDisplayLow;
                        high = Display.TXDisplayHigh;
                    }
                    else
                    {
                        low = Display.RX2DisplayLow;
                        high = Display.RX2DisplayHigh;
                    }
                }
            }
            else
            {
                if (rx == 1)
                {
                    low = specScope ? Display.RXSpectrumDisplayLow : Display.RXDisplayLow;
                    high = specScope ? Display.RXSpectrumDisplayHigh : Display.RXDisplayHigh;
                }
                else
                {
                    low = Display.RX2DisplayLow;
                    high = Display.RX2DisplayHigh;
                }
            }

            if (bIncludeRitXit)
            {
                if (rx == 1) // rit only rx1
                {
                    if (!moxRX1) // rit, only when rxing
                    {
                        if (chkRIT.Checked && !CTuneDisplay) // only need this if in ctun off mode
                        {
                            int offset = (int)udRIT.Value;
                            low += offset;
                            high += offset;
                        }
                    }
                    else // xit, only when txing
                    {
                        if (chkXIT.Checked && !display_duplex) // only when not in display duplex mode
                        {
                            int offset = (int)udXIT.Value;
                            low += offset;
                            high += offset;
                        }
                    }
                }
                else // xit can be on rx2
                {
                    if (moxRX2 && chkXIT.Checked)
                    {
                        int offset = (int)udXIT.Value;
                        low += offset;
                        high += offset;
                    }
                }
            }
        }
        private float PixelToHz(float x)
        {
            return PixelToHz(x, 1);
        }

        private float PixelToHz(float x, int rx)
        {
            //[2.10.1.0] MW0LGE re-implemented
            getLowHighForRXn(rx, out int low, out int high);

            int width = high - low;
            return (float)(low + ((double)x / (double)picDisplay.Width) * (double)width);
        }

        private int HzToPixel(float freq)
        {
            return HzToPixel(freq, 1);
        }

        private int HzToPixel(float freq, int rx)
        {
            //[2.10.1.0] MW0LGE re-implemented
            bool moxRX1 = _mox && (VFOATX || (VFOBTX && !RX2Enabled));
            bool moxRX2 = _mox && (VFOBTX && RX2Enabled);
            getLowHighForRXn(rx, out int low, out int high, false);

            // rit only rx1 when not txing
            int localRit = rx == 1 && !moxRX1 && RITOn && CTuneDisplay ? RITValue : 0;

            // xit
            int localXit = 0;
            if (rx == 1)
            {
                if (moxRX1)
                    localXit = XITOn ? XITValue : 0;
            }
            else
            {
                if (moxRX2)
                    localXit = XITOn ? XITValue : 0;
            }

            int width = high - low;
            return (int)((double)(freq - low + localRit + localXit) / (double)width * (double)picDisplay.Width);
        }

        private float PixelToDb(float y)
        {
            return (float)(Display.SpectrumGridMaxMoxModified - y * (double)(Display.SpectrumGridMaxMoxModified - Display.SpectrumGridMinMoxModified) / Display.RX1DisplayHeight);
        }

        private float PixelToRx2Db(float y)
        {
            y -= Display.RX1DisplayHeight;
            if (Display.CurrentDisplayMode == DisplayMode.PANAFALL)
            {
                // if rx1 is a panafall then we need to offset double rx1 height (height returned is just the panadapter section)
                y -= Display.RX1DisplayHeight;
            }

            return (float)(Display.RX2SpectrumGridMaxMoxModified - y * (double)(Display.RX2SpectrumGridMaxMoxModified - Display.RX2SpectrumGridMinMoxModified) / Display.RX2DisplayHeight);
        }

        private float WaterfallPixelToTime(float y, int rx)
        {
            int h;
            int localWaterFallUpdatePeriod;

            if (rx == 1)
            {
                h = Display.RX1DisplayHeight;
                localWaterFallUpdatePeriod = Display.WaterfallUpdatePeriod;
                if (Display.CurrentDisplayMode == DisplayMode.PANAFALL) y -= h;
            }
            else
            {
                if (y > picDisplay.Height / 2) y -= picDisplay.Height / 2;

                h = Display.RX2DisplayHeight;
                localWaterFallUpdatePeriod = Display.RX2WaterfallUpdatePeriod;
                if (Display.CurrentDisplayModeBottom == DisplayMode.PANAFALL) y -= h;
            }

            int nCurrentFps = Display.CurrentFPS;
            if (nCurrentFps == 0) nCurrentFps = _display_fps;

            float fRet = (y - 16) * (localWaterFallUpdatePeriod * (1000f / nCurrentFps));
            if (fRet < 0) fRet = 0;

            return fRet;
        }

        private float WaterfallPixelToTime(float y)
        {
            return WaterfallPixelToTime(y, 1);
        }

        #endregion

        #region Paint Event Handlers
        private void getMeterPixelPosAndDrawScales(int rx, Graphics g, int H, int W, double num, out int pixel_x, out int pixel_x_swr, int nStringOffsetY, bool bDrawMarkers)
        {
            //MW0LGE 
            pixel_x = 0;
            pixel_x_swr = 0;
            MeterRXMode rxMode;
            MeterTXMode txMode = chkTUN.Checked ? tune_meter_tx_mode : current_meter_tx_mode;

            bool bAboveS9Frequency;
            if (rx == 1)
            {
                rxMode = current_meter_rx_mode;
                bAboveS9Frequency = (VFOAFreq >= S9Frequency); //MW0LGE_21a
            }
            else
            {
                rxMode = rx2_meter_mode;
                bAboveS9Frequency = (VFOBFreq >= S9Frequency); //MW0LGE_21a
            }

            if (!_mox || rx == 2) // rx2 can not tx
            {
                switch (rxMode)
                {
                    case MeterRXMode.SIGNAL_STRENGTH:
                    case MeterRXMode.SIGNAL_AVERAGE:
                        if (bDrawMarkers)
                        {
                            g.FillRectangle(low_brush, 0, H - 4, (int)(W * 0.5), 2); // white horizontal line
                            g.FillRectangle(high_brush, (int)(W * 0.5), H - 4, (int)(W * 0.5) - 4, 2); // red horizontal line
                        }
                        double spacing = (W * 0.5 - 2.0) / 5.0;
                        double string_height = 0;
                        for (int i = 1; i < 6; i++)
                        {
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(low_brush, (int)(i * spacing - spacing * 0.5), H - 4 - 3, 1, 3); // short tic marks
                                g.FillRectangle(low_brush, (int)(i * spacing), H - 4 - 6, 2, 6); // long tic marks
                            }
                            SizeF size = g.MeasureString((-1 + i * 2).ToString(), font7, 1, StringFormat.GenericTypographic);
                            double string_width = size.Width - 2.0;
                            string_height = size.Height - 2.0;

                            // 1 3 5 7 9
                            g.DrawString((-1 + i * 2).ToString(), font7, low_brush, (float)((double)i * spacing - string_width + ((double)i / 5)), (float)((double)H - nStringOffsetY - string_height));
                        }
                        spacing = ((double)W * 0.5 - 2.0 - 4.0) / 3.0;
                        for (int i = 1; i < 4; i++)
                        {
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(high_brush, (int)((double)W * 0.5 + i * spacing - spacing * 0.5), H - 4 - 3, 1, 3); // short tic marks
                                g.FillRectangle(high_brush, (int)((double)W * 0.5 + i * spacing), H - 4 - 6, 2, 6); // long tic marks
                            }
                            SizeF size = g.MeasureString("+" + (i * 20).ToString(), font7, 3, StringFormat.GenericTypographic);
                            double string_width = size.Width - 2.0;

                            g.DrawString("+" + (i * 20).ToString(), font7, high_brush, (float)((double)W * 0.5 + i * spacing - string_width * 3 - (double)i / 3 * 2), (float)((double)H - nStringOffsetY - string_height));
                        }

                        if (bAboveS9Frequency)
                        {
                            if (num > -93.0) // high area
                            {
                                pixel_x = (int)(W * 0.5 + (93.0 + num) / 63.0 * (W * 0.5 - 3));
                            }
                            else
                            {
                                pixel_x = (int)((num + 153.0) / 60.0 * (W * 0.5));
                            }
                        }
                        else
                        {
                            if (num > -73.0) // high area
                            {
                                pixel_x = (int)(W * 0.5 + (73.0 + num) / 63.0 * (W * 0.5 - 3));
                            }
                            else
                            {
                                pixel_x = (int)((num + 133.0) / 60.0 * (W * 0.5));
                            }
                        }

                        break;
                    case MeterRXMode.ADC_L:
                    case MeterRXMode.ADC_R:
                    case MeterRXMode.ADC2_L:
                    case MeterRXMode.ADC2_R:
                        spacing = ((double)W - 5.0) / 6.0;
                        if (bDrawMarkers)
                        {
                            g.FillRectangle(low_brush, 0, H - 4, (int)(W - 3.0 - spacing), 2);
                            g.FillRectangle(high_brush, (int)(W - 3.0 - spacing), H - 4, (int)spacing, 2);
                        }
                        for (int i = 1; i < 7; i++)
                        {
                            SolidBrush b = low_brush;
                            if (i == 6) b = high_brush;
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(b, (int)(i * spacing - spacing / 2), H - 4 - 3, 1, 5);
                                g.FillRectangle(b, (int)(i * spacing), H - 4 - 6, 2, 8);
                            }
                            string s = (-120 + i * 20).ToString();
                            SizeF size = g.MeasureString(s, font7, 1, StringFormat.GenericTypographic);
                            double string_width = size.Width - 2.0;
                            size = g.MeasureString("0", font7, 1, StringFormat.GenericTypographic);
                            string_height = size.Height - 2.0;

                            g.DrawString(s, font7, b, (int)(i * spacing - (int)string_width * (s.Length)), (int)(H - nStringOffsetY - string_height));
                        }

                        pixel_x = (int)((num + 120.0) / 120.0 * (W - 5.0));
                        break;
                    case MeterRXMode.OFF:
                        break;
                }
            }
            else
            {
                switch (txMode)
                {
                    case MeterTXMode.MIC:
                    case MeterTXMode.EQ:
                    case MeterTXMode.LEVELER:
                    case MeterTXMode.CFC_PK:
                    case MeterTXMode.COMP:
                    case MeterTXMode.ALC:
                        if (bDrawMarkers)
                        {
                            g.FillRectangle(low_brush, 0, H - 4, (int)(W * 0.665), 2);
                            g.FillRectangle(high_brush, (int)(W * 0.665), H - 4, (int)(W * 0.335) - 2, 2);
                        }
                        double spacing = (W * 0.665 - 2.0) / 3.0;
                        double string_height = 0;
                        for (int i = 1; i < 4; i++)
                        {
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(low_brush, (int)(i * spacing - spacing * 0.5), H - 4 - 3, 1, 3);
                                g.FillRectangle(low_brush, (int)(i * spacing), H - 4 - 6, 2, 6);
                            }

                            string s = (-30 + i * 10).ToString();
                            SizeF size = g.MeasureString("0", font7, 1, StringFormat.GenericTypographic);
                            double string_width = size.Width - 2.0;
                            string_height = size.Height - 2.0;

                            g.DrawString(s, font7, low_brush, (float)((double)i * spacing - string_width * s.Length + 1.0 - ((double)i / 2) + ((double)i / 3)), (float)((double)H - nStringOffsetY - string_height));
                        }
                        spacing = (W * 0.335 - 2.0 - 3.0) / 3.0;
                        for (int i = 1; i < 4; i++)
                        {
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(high_brush, (int)((double)W * 0.665 + i * spacing - spacing * 0.5), H - 4 - 3, 1, 3);
                                g.FillRectangle(high_brush, (int)((double)W * 0.665 + i * spacing), H - 4 - 6, 2, 6);
                            }
                            string s = (i * 4).ToString();
                            SizeF size = g.MeasureString(s, font7, 3, StringFormat.GenericTypographic);
                            double string_width = size.Width - 2.0;

                            g.TextRenderingHint = TextRenderingHint.SystemDefault;
                            g.DrawString(s, font7, high_brush, (float)((double)W * 0.665 + i * spacing - string_width * s.Length), (float)((double)H - nStringOffsetY - string_height));
                        }

                        if (num > 0.0) // high area
                        {
                            pixel_x = (int)(W * 0.665 + num / 12.0 * (W * 0.335 - 4));
                        }
                        else
                        {
                            pixel_x = (int)((num + 30.0) / 30.0 * (W * 0.665 - 1.0));
                        }
                        break;
                    case MeterTXMode.ALC_GROUP:
                        //MW0LGE combined ALC + ALCcomp display
                        if (bDrawMarkers)
                        {
                            g.FillRectangle(low_brush, 0, H - 4, (int)(W * 0.5), 2); // white horizontal line
                            g.FillRectangle(high_brush, (int)(W * 0.5), H - 4, (int)(W * 0.5) - 4, 2); // red horizontal line
                                                                                                       // THE ALC section -30 to 0db
                        }
                        spacing = (W * 0.5 - 2.0) / 3.0;
                        string_height = 0;
                        for (int i = 1; i < 4; i++)
                        {
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(low_brush, (int)(i * spacing - spacing * 0.5), H - 4 - 3, 1, 3); // short tic marks
                                g.FillRectangle(low_brush, (int)(i * spacing), H - 4 - 6, 2, 6); // long tic marks
                            }
                            string s = (-30 + i * 10).ToString();
                            SizeF size = g.MeasureString("0", font7, 100, StringFormat.GenericTypographic);
                            double string_width = size.Width - 2.0;
                            string_height = size.Height - 2.0;

                            g.DrawString(s, font7, low_brush, (float)((double)i * spacing - (string_width * s.Length)), (float)((double)H - nStringOffsetY - string_height));
                        }
                        // THE ALC compression section 0 to +25db
                        spacing = (W * 0.5 - 2.0 - 3.0) / 5.0;
                        string_height = 0;
                        string[] g_list = { "5", "10", "15", "20", "+25" };
                        for (int i = 1; i < 6; i++)
                        {
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(high_brush, (int)((double)W * 0.5 + i * spacing - spacing * 0.5), H - 4 - 3, 1, 3); // long tic marks
                                g.FillRectangle(high_brush, (int)((double)W * 0.5 + i * spacing), H - 4 - 6, 2, 6); // short tic marks
                            }
                            string s = g_list[i - 1];
                            SizeF size = g.MeasureString("0", font7, 1, StringFormat.GenericTypographic);
                            double string_width = size.Width - 2.0;
                            string_height = size.Height - 2.0;
                            if (i == 5) spacing = (W * 0.50 - 2.0 - 6.0) / 5.0; // pull text back in on right edge if
                            g.DrawString(s, font7, high_brush, (float)((double)W * 0.5 + i * spacing - (string_width * s.Length)), (float)((double)H - nStringOffsetY - string_height));
                        }

                        if (num > 0.0) // high area - alc compression
                        {
                            spacing = (W * 0.5 - 2.0 - 3.0) / 5.0;
                            pixel_x = (int)((double)W * 0.5) + (int)(num / 5.0 * spacing);
                        }
                        else // alc only (sub 0db or less)
                        {
                            pixel_x = (int)((num + 30.0) / 30.0 * (W * 0.5 - 1.0));
                        }
                        break;
                    case MeterTXMode.FORWARD_POWER:
                    case MeterTXMode.REVERSE_POWER:
                        if (alexpresent || apollopresent) num = Math.Round(num);

                        if (alexpresent && ((current_hpsdr_model == HPSDRModel.ORIONMKII || current_hpsdr_model == HPSDRModel.ANAN8000D || current_hpsdr_model == HPSDRModel.ANAN_G2) && tx_xvtr_index < 0))
                        {
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(low_brush, 0, H - 4, (int)(W * 0.75), 2);
                                g.FillRectangle(high_brush, (int)(W * 0.75), H - 4, (int)(W * 0.25) - 10, 2);
                            }
                            spacing = (W * 0.75 - 2.0) / 4.0;
                            string_height = 0;
                            string[] list = { "10", "20", "100", "200" };
                            for (int i = 1; i < 5; i++)
                            {
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(low_brush, (int)(i * spacing - spacing * 0.5), H - 4 - 3, 1, 3);
                                    g.FillRectangle(low_brush, (int)(i * spacing), H - 4 - 6, 2, 6);
                                }
                                string s = list[i - 1];
                                SizeF size = g.MeasureString("0", font7, 1, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;
                                string_height = size.Height - 2.0;

                                g.DrawString(s, font7, low_brush, (float)((double)i * spacing - string_width * s.Length + ((double)i / 3) + ((double)i / 4)), (float)((double)H - nStringOffsetY - string_height));
                            }
                            spacing = (W * 0.25 - 2.0 - 10.0) / 1.0;
                            for (int i = 1; i < 2; i++)
                            {
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing - spacing * 0.5), H - 4 - 3, 1, 3);
                                    g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing), H - 4 - 6, 2, 6);
                                }
                                SizeF size = g.MeasureString("0", font7, 3, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;

                                g.TextRenderingHint = TextRenderingHint.SystemDefault;
                                g.DrawString("240+", font7, high_brush, (float)((double)W * 0.75 + i * spacing - 3.5 * string_width), (float)((double)H - nStringOffsetY - string_height));
                            }

                            if (num <= 200.0) // low area
                            {
                                spacing = (W * 0.75 - 2.0) / 4.0;
                                if (num <= 10.0)
                                    pixel_x = (int)(num / 10.0 * (int)spacing);
                                else if (num <= 20.0)
                                    pixel_x = (int)(spacing + (num - 10.0) / 10.0 * spacing);
                                else if (num <= 100.0)
                                    pixel_x = (int)(2 * spacing + (num - 20.0) / 80.0 * spacing);
                                else // <= 100
                                    pixel_x = (int)(3 * spacing + (num - 100.0) / 100.0 * spacing);
                            }
                            else
                            {
                                spacing = (W * 0.25 - 2.0 - 10.0) / 1.0;
                                if (num <= 240.0)
                                    pixel_x = (int)(W * 0.75 + (num - 200.0) / 40.0 * spacing);
                                else
                                    pixel_x = (int)(W * 0.75 + spacing + (num - 240.0) / 120.0 * spacing);
                            }
                        }

                        else if ((alexpresent || pa_present) &&
                                (current_hpsdr_model != HPSDRModel.ANAN10 &&
                                 current_hpsdr_model != HPSDRModel.ANAN10E &&
                                !apollopresent))
                        {
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(low_brush, 0, H - 4, (int)(W * 0.75), 2);
                                g.FillRectangle(high_brush, (int)(W * 0.75), H - 4, (int)(W * 0.25) - 10, 2);
                            }
                            spacing = (W * 0.75 - 2.0) / 4.0;
                            string_height = 0;
                            string[] list = { "5", "10", "50", "100" };
                            for (int i = 1; i < 5; i++)
                            {
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(low_brush, (int)(i * spacing - spacing * 0.5), H - 4 - 3, 1, 3);
                                    g.FillRectangle(low_brush, (int)(i * spacing), H - 4 - 6, 2, 6);
                                }
                                string s = list[i - 1];
                                SizeF size = g.MeasureString("0", font7, 1, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;
                                string_height = size.Height - 2.0;

                                g.DrawString(s, font7, low_brush, (float)((double)i * spacing - string_width * s.Length + ((double)i / 3) + ((double)i / 4)), (float)((double)H - nStringOffsetY - string_height));
                            }
                            spacing = (W * 0.25 - 2.0 - 10.0) / 1.0;
                            for (int i = 1; i < 2; i++)
                            {
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing - spacing * 0.5), H - 4 - 3, 1, 3);
                                    g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing), H - 4 - 6, 2, 6);
                                }

                                SizeF size = g.MeasureString("0", font7, 3, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;

                                g.TextRenderingHint = TextRenderingHint.SystemDefault;
                                g.DrawString("120+", font7, high_brush, (int)(W * 0.75 + i * spacing - (int)3.5 * string_width), (int)(H - nStringOffsetY - string_height));
                            }

                            if (num <= 100.0) // low area
                            {
                                spacing = (W * 0.75 - 2.0) / 4.0;
                                if (num <= 5.0)
                                    pixel_x = (int)(num / 5.0 * (int)spacing);
                                else if (num <= 10.0)
                                    pixel_x = (int)(spacing + (num - 5.0) / 5.0 * spacing);
                                else if (num <= 50.0)
                                    pixel_x = (int)(2 * spacing + (num - 10.0) / 40.0 * spacing);
                                else // <= 100
                                    pixel_x = (int)(3 * spacing + (num - 50.0) / 50.0 * spacing);
                            }
                            else
                            {
                                spacing = (W * 0.25 - 2.0 - 10.0) / 1.0;
                                if (num <= 120.0)
                                    pixel_x = (int)(W * 0.75 + (num - 100.0) / 20.0 * spacing);
                                else
                                    pixel_x = (int)(W * 0.75 + spacing + (num - 120.0) / 60.0 * spacing);
                            }
                        }
                        else if (current_hpsdr_model == HPSDRModel.ANAN10 ||
                                 current_hpsdr_model == HPSDRModel.ANAN10E)
                        {
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(low_brush, 0, H - 4, (int)(W * 0.75), 2);
                                g.FillRectangle(high_brush, (int)(W * 0.75), H - 4, (int)(W * 0.25) - 10, 2);
                            }
                            spacing = (W * 0.75 - 2.0) / 4.0;
                            string_height = 0;
                            string[] list = { "1", "5", "10", "15" };
                            for (int i = 1; i < 5; i++)
                            {
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(low_brush, (int)(i * spacing - spacing * 0.5), H - 4 - 3, 1, 3);
                                    g.FillRectangle(low_brush, (int)(i * spacing), H - 4 - 6, 2, 6);
                                }
                                string s = list[i - 1];

                                SizeF size = g.MeasureString("0", font7, 1, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;
                                string_height = size.Height - 2.0;

                                g.DrawString(s, font7, low_brush, (float)((double)i * spacing - string_width * s.Length + ((double)i / 3) + ((double)i / 4)), (float)((double)H - nStringOffsetY - string_height));
                            }
                            spacing = (W * 0.25 - 2.0 - 10.0) / 1.0;
                            for (int i = 1; i < 2; i++)
                            {
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing - spacing * 0.5), H - 4 - 3, 1, 3);
                                    g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing), H - 4 - 6, 2, 6);
                                }
                                SizeF size = g.MeasureString("0", font7, 2, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;

                                g.TextRenderingHint = TextRenderingHint.SystemDefault;
                                g.DrawString("25+", font7, high_brush, (int)(W * 0.75 + i * spacing - (int)3.5 * string_width), (int)(H - nStringOffsetY - string_height));
                            }

                            if (num <= 15.0) // low area
                            {
                                spacing = (W * 0.75 - 2.0) / 4.0;
                                if (num <= 1.0)
                                    pixel_x = (int)(num / 1.0 * (int)spacing);
                                else if (num <= 5.0)
                                    pixel_x = (int)(spacing + (num - 1.0) / 4.0 * spacing);
                                else if (num <= 10.0)
                                    pixel_x = (int)(2 * spacing + (num - 5.0) / 5.0 * spacing);
                                else
                                    pixel_x = (int)(3 * spacing + (num - 10.0) / 5.0 * spacing);
                            }
                            else
                            {
                                spacing = (W * 0.25 - 2.0 - 10.0) / 1.0;
                                if (num <= 25.0)
                                    pixel_x = (int)(W * 0.75 + (num - 15.0) / 10.0 * spacing);
                                else
                                    pixel_x = (int)(W * 0.75 + spacing + (num - 25.0) / 5.0 * spacing);
                            }
                        }
                        else if (apollopresent) // 30W
                        {
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(low_brush, 0, H - 4, (int)(W * 0.75), 2);
                                g.FillRectangle(high_brush, (int)(W * 0.75), H - 4, (int)(W * 0.25) - 10, 2);
                            }
                            spacing = (W * 0.75 - 2.0) / 4.0;
                            string_height = 0;
                            string[] list = { "5", "10", "20", "30" };
                            for (int i = 1; i < 5; i++)
                            {
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(low_brush, (int)(i * spacing - spacing * 0.5), H - 4 - 3, 1, 3);
                                    g.FillRectangle(low_brush, (int)(i * spacing), H - 4 - 6, 2, 6);
                                }
                                string s = list[i - 1];

                                SizeF size = g.MeasureString("0", font7, 1, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;
                                string_height = size.Height - 2.0;

                                g.DrawString(s, font7, low_brush, (float)((double)i * spacing - string_width * s.Length + ((double)i / 3) + ((double)i / 4)), (float)((double)H - nStringOffsetY - string_height));
                            }
                            spacing = (W * 0.25 - 2.0 - 10.0) / 1.0;
                            for (int i = 1; i < 2; i++)
                            {
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing - spacing * 0.5), H - 4 - 3, 1, 3);
                                    g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing), H - 4 - 6, 2, 6);
                                }
                                SizeF size = g.MeasureString("0", font7, 2, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;

                                g.TextRenderingHint = TextRenderingHint.SystemDefault;
                                g.DrawString("50+", font7, high_brush, (int)(W * 0.75 + i * spacing - (int)3.5 * string_width), (int)(H - nStringOffsetY - string_height));
                            }

                            if (num <= 30.0) // low area
                            {
                                spacing = (W * 0.75 - 2.0) / 4.0;
                                if (num <= 5.0)
                                    pixel_x = (int)(num / 5.0 * (int)spacing);
                                else if (num <= 10.0)
                                    pixel_x = (int)(spacing + (num - 5.0) / 5.0 * spacing);
                                else if (num <= 20.0)
                                    pixel_x = (int)(2 * spacing + (num - 10.0) / 10.0 * spacing);
                                else // <= 30
                                    pixel_x = (int)(3 * spacing + (num - 20.0) / 10.0 * spacing);
                            }
                            else
                            {
                                spacing = (W * 0.25 - 2.0 - 10.0) / 1.0;
                                if (num <= 50.0)
                                    pixel_x = (int)(W * 0.75 + (num - 30.0) / 20.0 * spacing);
                                else
                                    pixel_x = (int)(W * 0.75 + spacing + (num - 50.0) / 25.0 * spacing);
                            }

                        }
                        else // 1W version
                        {
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(low_brush, 0, H - 4, (int)(W * 0.75), 2);
                                g.FillRectangle(low_brush, (int)(W * 0.75), H - 4, (int)(W * 0.25) - 9, 2);
                            }
                            spacing = (W * 0.75 - 2.0) / 4.0;
                            string_height = 0;
                            string[] list = { "100", "250", "500", "800", "1000" };
                            for (int i = 1; i < 5; i++)
                            {
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(low_brush, (int)(i * spacing - spacing * 0.5), H - 4 - 3, 1, 3);
                                    g.FillRectangle(low_brush, (int)(i * spacing), H - 4 - 6, 2, 6);
                                }
                                string s = list[i - 1];

                                SizeF size = g.MeasureString("0", font7, 1, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;
                                string_height = size.Height - 2.0;

                                g.DrawString(s, font7, low_brush, (float)((double)i * spacing - string_width * s.Length + 1.0 + ((double)i / 2) - ((double)i / 4)), (float)((double)H - nStringOffsetY - string_height));
                            }
                            spacing = (W * 0.25 - 2.0 - 9.0) / 1.0;
                            for (int i = 1; i < 2; i++)
                            {
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(low_brush, (int)((double)W * 0.75 + i * spacing - spacing * 0.5), H - 4 - 3, 1, 3);
                                    g.FillRectangle(low_brush, (int)((double)W * 0.75 + i * spacing), H - 4 - 6, 2, 6);
                                }

                                SizeF size = g.MeasureString("0", font7, 3, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;

                                g.DrawString("1000", font7, low_brush, (int)(W * 0.75 + 2 + i * spacing - (int)4.0 * string_width), (int)(H - nStringOffsetY - string_height));
                            }

                            // num *= 1000;
                            if (num < 801.0) // low area
                            {
                                spacing = (W * 0.75 - 2.0) / 4.0;
                                if (num <= 100.0)
                                    pixel_x = (int)(num / 100.0 * spacing);
                                else if (num <= 250.0)
                                    pixel_x = (int)(spacing + (num - 100.0) / 150.0 * spacing);
                                else if (num <= 500.0)
                                    pixel_x = (int)(2 * spacing + (num - 250.0) / 250.0 * spacing);
                                else // <801.0
                                    pixel_x = (int)(3 * spacing + (num - 500.0) / 300.0 * spacing);
                            }
                            else // >801
                            {
                                spacing = (W * 0.25 - 2.0 - 9.0) / 1.0;
                                pixel_x = (int)(W * 0.75 + (num - 800.0) / 200.0 * spacing);
                            }
                        }
                        break;
                    case MeterTXMode.SWR_POWER:

                        if ((alexpresent || pa_present) &&
                            (current_hpsdr_model != HPSDRModel.ANAN10 &&
                             current_hpsdr_model != HPSDRModel.ANAN10E &&
                            !apollopresent))
                        {
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(high_brush, (int)(W * 0.75), (H / 2) - 1, (int)(W * 0.25) - 4, 2);
                                g.FillRectangle(low_brush, 0, (H / 2) - 1, (int)(W * 0.75), 4); // horizontal white line
                                g.FillRectangle(high_brush, (int)(W * 0.75), (H / 2) + 1, (int)(W * 0.25) - 9, 2); //horizontal red line
                            }                                                               // SWR stuff first
                            spacing = (W * 0.5) / 10.0;
                            string_height = 0;
                            string[] swrx_list = { "1.5", "2" };
                            for (int i = 1; i < 10; i++)
                            {
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(low_brush, (int)(i * spacing), (H / 2) - 4, 1, 3);
                                }
                            }
                            for (int i = 1; i < 3; i++)
                            {
                                spacing = (W * 0.5) / 2.0;
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(low_brush, (int)(i * spacing), (H / 2) - 7, 2, 6);
                                }
                                string s = swrx_list[i - 1];

                                SizeF size = g.MeasureString("0", font7, 1, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;
                                string_height = size.Height - 2.0;

                                g.DrawString(s, font7, low_brush, (float)((double)i * spacing - string_width * s.Length + 2.0 - 1 * ((double)i / 2) + 3 * ((double)i / 4)), (float)(((double)H / 2) - 6/*8*/ - string_height));
                            }
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(low_brush, (int)(W * 0.625), (H / 2) - 4, 1, 3); // small tic 2.5:1
                            }

                            string[] swrx_hi_list = { "3", "4", "5" };

                            for (int i = 1; i < 4; i++)
                            {
                                spacing = (W * 0.25 - 6.0) / 2.0;
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing - spacing * 0.5), (H / 2) - 4, 1, 3);
                                    g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing - spacing), (H / 2) - 7, 2, 6);
                                }

                                string s = swrx_hi_list[i - 1];

                                SizeF size = g.MeasureString("0", font7, 1, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;
                                string_height = size.Height - 2.0;

                                g.DrawString(s, font7, high_brush, (float)((double)W * 0.75 + i * spacing - spacing - 1.0 * string_width), (float)(((double)H / 2) - 6/*8*/ - string_height));
                            }

                            if (current_swrmeter_data <= 3.0) // low area
                            {
                                spacing = (W * 0.75) / 3.0;

                                if (current_swrmeter_data <= 1.5)
                                    pixel_x_swr = (int)((current_swrmeter_data - 1.0) / 0.5 * spacing);
                                else if (current_swrmeter_data <= 2.0)
                                    pixel_x_swr = (int)(spacing + (current_swrmeter_data - 1.5) / 0.5 * spacing);
                                else
                                    pixel_x_swr = (int)(2 * spacing + (current_swrmeter_data - 2.0) / 1.0 * spacing);
                            }
                            else
                            {
                                spacing = (W * 0.25 - 6.0) / 2.0;
                                if (current_swrmeter_data <= 4.0)
                                    pixel_x_swr = (int)(W * 0.75 + (current_swrmeter_data - 3.0) / 1.0 * spacing);
                                else if (current_swrmeter_data <= 5.0)
                                    pixel_x_swr = (int)(W * 0.75 + spacing + (current_swrmeter_data - 4.0) / 1.0 * spacing);
                                else
                                    pixel_x_swr = (int)(W * 0.75 + 2 * spacing + (current_swrmeter_data - 5.0) / 4.0 * spacing);
                            }
                            if (double.IsInfinity(current_swrmeter_data)) pixel_x_swr = W - 2;

                            //PWR
                            spacing = (W * 0.75 - 2.0) / 4.0;
                            string_height = 0;
                            string[] list = { "5", "10", "50", "100" };
                            for (int i = 1; i < 5; i++)
                            {
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(low_brush, (int)(i * spacing - spacing * 0.5), (H / 2) + 3, 1, 3);
                                    g.FillRectangle(low_brush, (int)(i * spacing), (H / 2) + 3, 2, 6);
                                }
                                string s = list[i - 1];

                                SizeF size = g.MeasureString("0", font7, 1, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;
                                string_height = size.Height - 2.0;

                                g.DrawString(s, font7, low_brush, (float)((double)i * spacing - string_width * s.Length + ((double)i / 3) + ((double)i / 4)), (float)((double)H - 1 - string_height));
                            }
                            spacing = (W * 0.25 - 2.0 - 10.0) / 1.0;
                            for (int i = 1; i < 2; i++)
                            {
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing - spacing * 0.5), (H / 2) + 3, 1, 3);
                                    g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing), (H / 2) + 3, 2, 6);
                                }

                                SizeF size = g.MeasureString("0", font7, 2, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;

                                g.TextRenderingHint = TextRenderingHint.SystemDefault;
                                g.DrawString("120+", font7, high_brush, (float)((double)W * 0.75 + i * spacing - 3.5 * string_width), (float)((double)H - 1 - string_height));
                            }

                            if (num <= 100.0) // low area
                            {
                                spacing = (W * 0.75 - 2.0) / 4.0;
                                if (num <= 5.0)
                                    pixel_x = (int)(num / 5.0 * (int)spacing);
                                else if (num <= 10.0)
                                    pixel_x = (int)(spacing + (num - 5.0) / 5.0 * spacing);
                                else if (num <= 50.0)
                                    pixel_x = (int)(2 * spacing + (num - 10.0) / 40.0 * spacing);
                                else
                                    pixel_x = (int)(3 * spacing + (num - 50.0) / 50.0 * spacing);
                            }
                            else
                            {
                                spacing = (W * 0.25 - 2.0 - 10.0) / 1.0;
                                if (num <= 120.0)
                                    pixel_x = (int)(W * 0.75 + (num - 100.0) / 20.0 * spacing);
                                else
                                    pixel_x = (int)(W * 0.75 + spacing + (num - 120.0) / 60.0 * spacing);
                            }
                        }

                        else if (current_hpsdr_model == HPSDRModel.ANAN10 ||
                                 current_hpsdr_model == HPSDRModel.ANAN10E)
                        {
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(high_brush, (int)(W * 0.75), (H / 2) - 1, (int)(W * 0.25) - 4, 2);
                                g.FillRectangle(low_brush, 0, (H / 2) - 1, (int)(W * 0.75), 4); // horizontal white line
                                g.FillRectangle(high_brush, (int)(W * 0.75), (H / 2) + 1, (int)(W * 0.25) - 9, 2); //horizontal red line
                                                                                                                   // SWR stuff first
                            }
                            spacing = (W * 0.5) / 10.0;
                            string_height = 0;
                            string[] swrx_list = { "1.5", "2" };
                            for (int i = 1; i < 10; i++)
                            {
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(low_brush, (int)(i * spacing), (H / 2) - 4, 1, 3);
                                }
                            }
                            for (int i = 1; i < 3; i++)
                            {
                                spacing = (W * 0.5) / 2.0;
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(low_brush, (int)(i * spacing), (H / 2) - 7, 2, 6);
                                }
                                string s = swrx_list[i - 1];

                                SizeF size = g.MeasureString("0", font7, 1, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;
                                string_height = size.Height - 2.0;

                                g.DrawString(s, font7, low_brush, (float)((double)i * spacing - string_width * s.Length + 2.0 - 1 * ((double)i / 2) + 3 * ((double)i / 4)), (float)(((double)H / 2) - 9 - string_height));
                            }
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(low_brush, (int)(W * 0.625), (H / 2) - 4, 1, 3); // small tic 2.5:1
                            }

                            string[] swrx_hi_list = { "3", "4", "5" };

                            for (int i = 1; i < 4; i++)
                            {
                                spacing = (W * 0.25 - 6.0) / 2.0;
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing - spacing * 0.5), (H / 2) - 4, 1, 3);
                                    g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing - spacing), (H / 2) - 7, 2, 6);
                                }

                                string s = swrx_hi_list[i - 1];

                                SizeF size = g.MeasureString("0", font7, 1, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;
                                string_height = size.Height - 2.0;

                                g.DrawString(s, font7, high_brush, (float)((double)W * 0.75 + i * spacing - spacing - 1.0 * string_width), (float)(((double)H / 2) - 9 - string_height));
                            }


                            if (current_swrmeter_data <= 3.0) // low area
                            {
                                spacing = (W * 0.75) / 3.0;

                                if (current_swrmeter_data <= 1.5)
                                    pixel_x_swr = (int)((current_swrmeter_data - 1.0) / 0.5 * spacing);
                                else if (current_swrmeter_data <= 2.0)
                                    pixel_x_swr = (int)(spacing + (current_swrmeter_data - 1.5) / 0.5 * spacing);
                                else
                                    pixel_x_swr = (int)(2 * spacing + (current_swrmeter_data - 2.0) / 1.0 * spacing);
                            }
                            else
                            {
                                spacing = (W * 0.25 - 6.0) / 2.0;
                                if (current_swrmeter_data <= 4.0)
                                    pixel_x_swr = (int)(W * 0.75 + (current_swrmeter_data - 3.0) / 1.0 * spacing);
                                else if (current_swrmeter_data <= 5.0)
                                    pixel_x_swr = (int)(W * 0.75 + spacing + (current_swrmeter_data - 4.0) / 1.0 * spacing);
                                else
                                    pixel_x_swr = (int)(W * 0.75 + 2 * spacing + (current_swrmeter_data - 5.0) / 4.0 * spacing);
                            }
                            if (double.IsInfinity(current_swrmeter_data)) pixel_x_swr = W - 2;


                            // PWR
                            spacing = (W * 0.75 - 2.0) / 4.0;
                            string[] list = { "1", "5", "10", "15" };
                            for (int i = 1; i < 5; i++)
                            {
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(low_brush, (int)(i * spacing - spacing * 0.5), (H / 2) + 3, 1, 3);
                                    g.FillRectangle(low_brush, (int)(i * spacing), (H / 2) + 3, 2, 6);
                                }
                                string s = list[i - 1];

                                SizeF size = g.MeasureString("0", font7, 1, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;
                                string_height = size.Height - 2.0;

                                g.DrawString(s, font7, low_brush, (float)((double)i * spacing - string_width * s.Length + ((double)i / 3) + ((double)i / 4)), (float)((double)H - 1 - string_height));
                            }
                            spacing = (W * 0.25 - 2.0 - 10.0) / 1.0;
                            for (int i = 1; i < 2; i++)
                            {
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing - spacing * 0.5), (H / 2) + 3, 1, 3);
                                    g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing), (H / 2) + 3, 2, 6);
                                }

                                SizeF size = g.MeasureString("0", font7, 2, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;

                                g.TextRenderingHint = TextRenderingHint.SystemDefault;
                                g.DrawString("25+", font7, high_brush, (float)((double)W * 0.75 + i * spacing - 3.5 * string_width), (float)((double)H - 1 - string_height));
                            }

                            if (num <= 15.0) // low area
                            {
                                spacing = (W * 0.75 - 2.0) / 4.0;
                                if (num <= 1.0)
                                    pixel_x = (int)(num / 1.0 * (int)spacing);
                                else if (num <= 5.0)
                                    pixel_x = (int)(spacing + (num - 1.0) / 4.0 * spacing);
                                else if (num <= 10.0)
                                    pixel_x = (int)(2 * spacing + (num - 5.0) / 5.0 * spacing);
                                else
                                    pixel_x = (int)(3 * spacing + (num - 10.0) / 5.0 * spacing);
                            }
                            else
                            {
                                spacing = (W * 0.25 - 2.0 - 10.0) / 1.0;
                                if (num <= 25.0)
                                    pixel_x = (int)(W * 0.75 + (num - 15.0) / 10.0 * spacing);
                                else
                                    pixel_x = (int)(W * 0.75 + spacing + (num - 25.0) / 5.0 * spacing);
                            }
                        }

                        else if (apollopresent)
                        {
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(high_brush, (int)(W * 0.75), (H / 2) - 1, (int)(W * 0.25) - 4, 2);
                                g.FillRectangle(low_brush, 0, (H / 2) - 1, (int)(W * 0.75), 4); // horizontal white line
                                g.FillRectangle(high_brush, (int)(W * 0.75), (H / 2) + 1, (int)(W * 0.25) - 9, 2); //horizontal red line
                                                                                                                   // SWR stuff first
                            }
                            spacing = (W * 0.5) / 10.0;
                            string_height = 0;
                            string[] swrx_list = { "1.5", "2" };
                            for (int i = 1; i < 10; i++)
                            {
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(low_brush, (int)(i * spacing), (H / 2) - 4, 1, 3);
                                }
                            }
                            for (int i = 1; i < 3; i++)
                            {
                                spacing = (W * 0.5) / 2.0;
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(low_brush, (int)(i * spacing), (H / 2) - 7, 2, 6);
                                }
                                string s = swrx_list[i - 1];

                                SizeF size = g.MeasureString("0", font7, 1, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;
                                string_height = size.Height - 2.0;

                                g.DrawString(s, font7, low_brush, (float)((double)i * spacing - string_width * s.Length + 2.0 - 1 * ((double)i / 2) + 3 * ((double)i / 4)), (float)(((double)H / 2) - 9 - string_height));
                            }
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(low_brush, (int)(W * 0.625), (H / 2) - 4, 1, 3); // small tic 2.5:1
                            }

                            string[] swrx_hi_list = { "3", "4", "5" };

                            for (int i = 1; i < 4; i++)
                            {
                                spacing = (W * 0.25 - 6.0) / 2.0;
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing - spacing * 0.5), (H / 2) - 4, 1, 3);
                                    g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing - spacing), (H / 2) - 7, 2, 6);
                                }

                                string s = swrx_hi_list[i - 1];

                                SizeF size = g.MeasureString("0", font7, 1, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;
                                string_height = size.Height - 2.0;

                                g.DrawString(s, font7, high_brush, (float)((double)W * 0.75 + i * spacing - spacing - 1.0 * string_width), (float)(((double)H / 2) - 9 - string_height));
                            }


                            if (current_swrmeter_data <= 3.0) // low area
                            {
                                spacing = (W * 0.75) / 3.0;

                                if (current_swrmeter_data <= 1.5)
                                    pixel_x_swr = (int)((current_swrmeter_data - 1.0) / 0.5 * spacing);
                                else if (current_swrmeter_data <= 2.0)
                                    pixel_x_swr = (int)(spacing + (current_swrmeter_data - 1.5) / 0.5 * spacing);
                                else
                                    pixel_x_swr = (int)(2 * spacing + (current_swrmeter_data - 2.0) / 1.0 * spacing);
                            }
                            else
                            {
                                spacing = (W * 0.25 - 6.0) / 2.0;
                                if (current_swrmeter_data <= 4.0)
                                    pixel_x_swr = (int)(W * 0.75 + (current_swrmeter_data - 3.0) / 1.0 * spacing);
                                else if (current_swrmeter_data <= 5.0)
                                    pixel_x_swr = (int)(W * 0.75 + spacing + (current_swrmeter_data - 4.0) / 1.0 * spacing);
                                else
                                    pixel_x_swr = (int)(W * 0.75 + 2 * spacing + (current_swrmeter_data - 5.0) / 4.0 * spacing);
                            }
                            if (double.IsInfinity(current_swrmeter_data)) pixel_x_swr = W - 2;

                            // PWR
                            spacing = (W * 0.75 - 2.0) / 4.0;
                            string[] list = { "5", "10", "20", "30" };
                            for (int i = 1; i < 5; i++)
                            {
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(low_brush, (int)(i * spacing - spacing * 0.5), (H / 2) + 3, 1, 3);
                                    g.FillRectangle(low_brush, (int)(i * spacing), (H / 2) + 3, 2, 6);
                                }
                                string s = list[i - 1];

                                SizeF size = g.MeasureString("0", font7, 1, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;
                                string_height = size.Height - 2.0;

                                g.DrawString(s, font7, low_brush, (float)((double)i * spacing - string_width * s.Length + ((double)i / 3) + ((double)i / 4)), (float)((double)H - 1 - string_height));
                            }
                            spacing = (W * 0.25 - 2.0 - 10.0) / 1.0;
                            for (int i = 1; i < 2; i++)
                            {
                                if (bDrawMarkers)
                                {
                                    g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing - spacing * 0.5), (H / 2) + 3, 1, 3);
                                    g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing), (H / 2) + 3, 2, 6);
                                }

                                SizeF size = g.MeasureString("0", font7, 2, StringFormat.GenericTypographic);
                                double string_width = size.Width - 2.0;

                                g.TextRenderingHint = TextRenderingHint.SystemDefault;
                                g.DrawString("50+", font7, high_brush, (float)((double)W * 0.75 + i * spacing - 3.5 * string_width), (float)((double)H - 1 - string_height));
                            }

                            if (num <= 30.0) // low area
                            {
                                spacing = (W * 0.75 - 2.0) / 4.0;
                                if (num <= 5.0)
                                    pixel_x = (int)(num / 5.0 * (int)spacing);
                                else if (num <= 10.0)
                                    pixel_x = (int)(spacing + (num - 5.0) / 5.0 * spacing);
                                else if (num <= 20.0)
                                    pixel_x = (int)(2 * spacing + (num - 10.0) / 10.0 * spacing);
                                else
                                    pixel_x = (int)(3 * spacing + (num - 20.0) / 10.0 * spacing);
                            }
                            else
                            {
                                spacing = (W * 0.25 - 2.0 - 10.0) / 1.0;
                                if (num <= 50.0)
                                    pixel_x = (int)(W * 0.75 + (num - 30.0) / 20.0 * spacing);
                                else
                                    pixel_x = (int)(W * 0.75 + spacing + (num - 50.0) / 25.0 * spacing);
                            }
                        }
                        break;
                    case MeterTXMode.SWR:
                        if (bDrawMarkers)
                        {
                            g.FillRectangle(low_brush, 0, H - 4, (int)(W * 0.75), 2);
                            g.FillRectangle(high_brush, (int)(W * 0.75), H - 4, (int)(W * 0.25) - 4, 2);
                        }

                        spacing = (W * 0.5) / 10.0;
                        string_height = 0;

                        string[] swr_list = { "1.5", "2" };
                        for (int i = 1; i < 10; i++)
                        {
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(low_brush, (int)(i * spacing), H - 4 - 3, 1, 3);
                            }
                        }
                        for (int i = 1; i < 3; i++)
                        {
                            spacing = (W * 0.5) / 2.0;
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(low_brush, (int)(i * spacing), H - 4 - 6, 2, 6);
                            }
                            string s = swr_list[i - 1];

                            SizeF size = g.MeasureString("0", font7, 1, StringFormat.GenericTypographic);
                            double string_width = size.Width - 2.0;
                            string_height = size.Height - 2.0;

                            g.DrawString(s, font7, low_brush, (float)((double)i * spacing - string_width * s.Length + 2.0 - 1 * ((double)i / 2) + 3 * ((double)i / 4)), (float)((double)H - nStringOffsetY - string_height));
                        }
                        if (bDrawMarkers)
                        {
                            g.FillRectangle(low_brush, (int)(W * 0.625), H - 4 - 3, 1, 3); // small tic 2.5:1
                        }

                        string[] swr_hi_list = { "3", "4", "5" };

                        for (int i = 1; i < 4; i++)
                        {
                            spacing = (W * 0.25 - 6.0) / 2.0;
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing - spacing * 0.5), H - 4 - 3, 1, 3);
                                g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing - spacing), H - 4 - 6, 2, 6);
                            }

                            string s = swr_hi_list[i - 1];

                            SizeF size = g.MeasureString("0", font7, 1, StringFormat.GenericTypographic);
                            double string_width = size.Width - 2.0;
                            string_height = size.Height - 2.0;

                            g.DrawString(s, font7, high_brush, (float)((double)W * 0.75 + i * spacing - spacing - 1.0 * string_width), (float)((double)H - nStringOffsetY - string_height));
                        }

                        if (num <= 3.0) // low area
                        {
                            spacing = (W * 0.75) / 3.0;

                            if (num <= 1.5)
                                pixel_x = (int)((num - 1.0) / 0.5 * spacing);
                            else if (num <= 2.0)
                                pixel_x = (int)(spacing + (num - 1.5) / 0.5 * spacing);
                            else
                                pixel_x = (int)(2 * spacing + (num - 2.0) / 1.0 * spacing);
                        }
                        else
                        {
                            spacing = (W * 0.25 - 6.0) / 2.0;
                            if (num <= 4.0)
                                pixel_x = (int)(W * 0.75 + (num - 3.0) / 1.0 * spacing);
                            else if (num <= 5.0)
                                pixel_x = (int)(W * 0.75 + spacing + (num - 4.0) / 1.0 * spacing);
                            else
                                pixel_x = (int)(W * 0.75 + 2 * spacing + (num - 5.0) / 4.0 * spacing);
                        }
                        if (double.IsInfinity(num)) pixel_x = W - 2;
                        break;
                    case MeterTXMode.ALC_G:
                    case MeterTXMode.LVL_G:
                    case MeterTXMode.CFC_G:
                        if (bDrawMarkers)
                        {
                            g.FillRectangle(low_brush, 0, H - 4, (int)(W * 0.75), 2);
                            g.FillRectangle(high_brush, (int)(W * 0.75), H - 4, (int)(W * 0.25) - 9, 2);
                        }
                        spacing = (W * 0.75 - 2.0) / 4.0;
                        string_height = 0;
                        string[] gain_list = { "5", "10", "15", "20", "25" };
                        for (int i = 1; i < 5; i++)
                        {
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(low_brush, (int)(i * spacing - spacing * 0.5), H - 4 - 3, 1, 3);
                                g.FillRectangle(low_brush, (int)(i * spacing), H - 4 - 6, 2, 6);
                            }

                            string s = gain_list[i - 1];

                            SizeF size = g.MeasureString("0", font7, 1, StringFormat.GenericTypographic);
                            double string_width = size.Width - 2.0;
                            string_height = size.Height - 2.0;

                            g.DrawString(s, font7, low_brush, (float)((double)i * spacing - string_width * s.Length + ((double)i / 3)), (float)((double)H - nStringOffsetY - string_height));
                        }
                        spacing = (W * 0.25 - 2.0 - 9.0) / 1.0;
                        for (int i = 1; i < 2; i++)
                        {
                            if (bDrawMarkers)
                            {
                                g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing - spacing * 0.5), H - 4 - 3, 1, 3);
                                g.FillRectangle(high_brush, (int)((double)W * 0.75 + i * spacing), H - 4 - 6, 2, 6);
                            }

                            SizeF size = g.MeasureString("0", font7, 3, StringFormat.GenericTypographic);
                            double string_width = size.Width - 2.0;

                            g.DrawString("25+", font7, high_brush, (float)((double)W * 0.75 + i * spacing - 2.5 * string_width), (float)((double)H - nStringOffsetY - string_height));
                        }


                        spacing = (W * 0.75 - 2.0) / 4.0;
                        pixel_x = (int)(num / 5.0 * spacing);
                        break;
                    case MeterTXMode.OFF:
                        break;
                }
            }
        }

        private int m_nSignalHistoryDuration = 2000;
        private HiPerfTimer m_objRX1HistoryDelayTimer = new HiPerfTimer();
        private HiPerfTimer m_objRX2HistoryDelayTimer = new HiPerfTimer();

        public int SignalHistoryDuration {
            get { return m_nSignalHistoryDuration; }
            set { m_nSignalHistoryDuration = value; }
        }
        private void storeRX1SignalPixels_X(float x)
        {
            int dly = Math.Min(meter_delay, meter_dig_delay);

            if (m_objRX1HistoryDelayTimer.ElapsedMsec < Math.Max(dly, 2000)) //MW0LGE_21a
            {
                // ignore at least 2 second of smeter history to prevent meter from jumping around at start
                return;
            }
            m_objRX1HistoryDelayTimer.Stop();

            m_RX1SignalPixels_X.Add(x);

            int toRemove = m_RX1SignalPixels_X.Count - (m_nSignalHistoryDuration / dly);
            // the list is sized based on delay
            if (toRemove > 0) m_RX1SignalPixels_X.RemoveRange(0, toRemove);
        }
        private void storeRX2SignalPixels_X(float x)
        {
            int dly = Math.Min(meter_delay, meter_dig_delay);

            if (m_objRX2HistoryDelayTimer.ElapsedMsec < Math.Max(dly, 2000)) //MW0LGE_21a
            {
                // ignore at least 2 second of smeter history to prevent meter from jumping around at start
                return;
            }
            m_objRX2HistoryDelayTimer.Stop();

            m_RX2SignalPixels_X.Add(x);

            int toRemove = m_RX2SignalPixels_X.Count - (m_nSignalHistoryDuration / dly);
            // the list is sized based on delay
            if (toRemove > 0) m_RX2SignalPixels_X.RemoveRange(0, toRemove);
        }

        private void clearRXSignalPixels(int rx)
        {
            if (rx == 1)
            {
                m_RX1SignalPixels_X.Clear();
                m_objRX1HistoryDelayTimer.Reset();
            }
            else if (rx == 2)
            {
                m_RX2SignalPixels_X.Clear();
                m_objRX2HistoryDelayTimer.Reset();

            }
        }

        private Color m_clrSignalHistoryColour = Color.LimeGreen;
        public Color SignalHistoryColour {
            get { return m_clrSignalHistoryColour; }
            set {
                m_clrSignalHistoryColour = value;
                m_SignalHistoryColourPen.Color = value;
            }
        }

        private bool m_bUseSignalHistory = false;
        public bool UseSignalHistory {
            get { return m_bUseSignalHistory; }
            set { m_bUseSignalHistory = value; }
        }

        private Font font7 = new Font("Microsoft Sans Serif", 7.0f, FontStyle.Bold);
        private double avg_num = Display.CLEAR_FLAG;//- 130.0;
        private List<float> m_RX1SignalPixels_X = new List<float>();
        private List<float> m_RX2SignalPixels_X = new List<float>();
        private Pen m_SignalHistoryColourPen = new Pen(Color.LimeGreen);

        private void picMultiMeterDigital_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            int H = picMultiMeterDigital.ClientSize.Height;
            int W = picMultiMeterDigital.ClientSize.Width;
            Graphics g = e.Graphics;
            double num = -200.0f;
            int pixel_x;// = 0;
            int pixel_x_swr;// = 0;
            string output = "";

            if (meter_data_ready)
            {
                current_meter_data = new_meter_data;
                current_swrmeter_data = new_swrmeter_data;
            }

            if (avg_num == Display.CLEAR_FLAG) // reset average -- just use new value
            {
                num = avg_num = current_meter_data;
                clearRXSignalPixels(1);
            }
            else
            {
                if (current_meter_data > avg_num)
                    num = avg_num = current_meter_data * 0.8 + avg_num * 0.2; // fast rise
                else
                    num = avg_num = current_meter_data * 0.2 + avg_num * 0.8; // slow decay
            }

            MeterTXMode txMode = chkTUN.Checked ? tune_meter_tx_mode : current_meter_tx_mode;

            switch (current_meter_display_mode)
            {
                case MultiMeterDisplayMode.Original:
                    #region Original                    
                    g.FillRectangle(meter_background_pen.Brush, 0, 0, W, H);

                    getMeterPixelPosAndDrawScales(1, g, H, W, num, out pixel_x, out pixel_x_swr, 1, false);

                    if ((!_mox && current_meter_rx_mode != MeterRXMode.OFF) ||
                        (_mox && !(txMode == MeterTXMode.OFF || txMode == MeterTXMode.SWR_POWER))
                        )
                    {
                        pixel_x = Math.Max(1, pixel_x);
                        pixel_x = Math.Min(W - 3, pixel_x);

                        if (!_mox && num != -200) storeRX1SignalPixels_X((float)pixel_x / W);

                        using (LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, pixel_x, H - 10),
                            meter_left_color, meter_right_color, LinearGradientMode.Horizontal))

                            g.FillRectangle(brush, 0, 0, pixel_x, H - 10);

                        for (int i = 0; i < (W / 8) - 1; i++)
                            g.DrawLine(meter_background_pen, 8 + i * 8, 0, 8 + i * 8, H - 10);

                        g.DrawLine(Pens.Red, pixel_x, 0, pixel_x, H - 10);
                        g.FillRectangle(meter_background_pen.Brush, pixel_x + 1, 0, W - pixel_x, H - 10);

                        if (pixel_x >= meter_peak_value)
                        {
                            meter_peak_count = 0;
                            meter_peak_value = pixel_x;
                        }
                        else
                        {
                            if (meter_peak_count++ >= multimeter_peak_hold_samples)
                            {
                                meter_peak_count = 0;
                                meter_peak_value = pixel_x;
                            }
                            else
                            {
                                g.DrawLine(Pens.Red, meter_peak_value, 0, meter_peak_value, H - 10);
                                g.DrawLine(Pens.Red, meter_peak_value - 1, 0, meter_peak_value - 1, H - 10);
                            }
                        }

                        if (m_bUseSignalHistory && !_mox && m_RX1SignalPixels_X.Count > 0)
                        {
                            // the history swing
                            float fMin = m_RX1SignalPixels_X.Min() * W;
                            float fMax = m_RX1SignalPixels_X.Max() * W;
                            g.FillRectangle(m_SignalHistoryColourPen.Brush, fMin, H - 10, fMax - fMin, 10);
                            //
                        }
                    }
                    else if (_mox && txMode == MeterTXMode.SWR_POWER)
                    {
                        //MW0LGE to do, just draw lines atm
                        pixel_x = Math.Max(1, pixel_x);
                        pixel_x = Math.Min(W - 3, pixel_x);
                        pixel_x_swr = Math.Max(1, pixel_x_swr);
                        pixel_x_swr = Math.Min(W - 3, pixel_x_swr);

                        using (LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, pixel_x_swr, (H / 2) - 8),
                            meter_left_color, meter_right_color, LinearGradientMode.Horizontal))
                            g.FillRectangle(brush, 0, 8, pixel_x_swr, (H / 2) - 8);

                        using (LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, pixel_x, (H / 2) - 8),
                            meter_left_color, meter_right_color, LinearGradientMode.Horizontal))
                            g.FillRectangle(brush, 0, H / 2, pixel_x, (H / 2) - 8);


                        for (int i = 0; i < (W / 8) - 1; i++)
                        {
                            g.DrawLine(meter_background_pen, 8 + i * 8, H / 2, 8 + i * 8, H - 8);
                            g.DrawLine(meter_background_pen, 8 + i * 8, 10, 8 + i * 8, (H / 2) - 8);
                        }

                        g.DrawLine(Pens.Red, pixel_x, H / 2, pixel_x, H); // drop down end lines so we can see them
                        g.DrawLine(Pens.Red, pixel_x_swr, 0, pixel_x_swr, H / 2);

                        g.FillRectangle(meter_background_pen.Brush, pixel_x + 1, H / 2, W - pixel_x, (H / 2) - 8);
                        g.FillRectangle(meter_background_pen.Brush, pixel_x_swr + 1, 8, W - pixel_x_swr, (H / 2) - 8);

                        if (pixel_x >= meter_peak_value)
                        {
                            meter_peak_count = 0;
                            meter_peak_value = pixel_x;
                        }
                        else
                        {
                            if (meter_peak_count++ >= multimeter_peak_hold_samples)
                            {
                                meter_peak_count = 0;
                                meter_peak_value = pixel_x;
                            }
                            else
                            {
                                g.DrawLine(Pens.Red, meter_peak_value, H / 2, meter_peak_value, H);
                                g.DrawLine(Pens.Red, meter_peak_value - 1, H / 2, meter_peak_value - 1, H);
                            }
                        }
                    }
                    break;
                #endregion
                case MultiMeterDisplayMode.Edge:
                    #region Edge
                    g.DrawRectangle(edge_meter_background_pen, 0, 0, W, H);

                    //MW0LGE moved all code into common function, used by both edge and original meter
                    getMeterPixelPosAndDrawScales(1, g, H, W, num, out pixel_x, out pixel_x_swr, 12, true);
                    //-

                    // draw meter movement
                    if ((!_mox && current_meter_rx_mode != MeterRXMode.OFF) ||
                        (_mox && !(txMode == MeterTXMode.OFF || txMode == MeterTXMode.SWR_POWER))
                        )
                    {
                        pixel_x = Math.Max(0, pixel_x);
                        pixel_x = Math.Min(W - 3, pixel_x);

                        if (!_mox && num != -200) storeRX1SignalPixels_X((float)pixel_x / W);

                        line_dark_pen.Color =
                            Color.FromArgb((edge_avg_color.R + edge_meter_background_color.R) / 2,
                            (edge_avg_color.G + edge_meter_background_color.G) / 2,
                            (edge_avg_color.B + edge_meter_background_color.B) / 2);

                        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                        g.SmoothingMode = SmoothingMode.HighQuality;

                        if (m_bUseSignalHistory && !_mox && m_RX1SignalPixels_X.Count > 0)
                        {
                            // the history swing
                            float fMin = m_RX1SignalPixels_X.Min() * W;
                            float fMax = m_RX1SignalPixels_X.Max() * W;
                            g.FillRectangle(m_SignalHistoryColourPen.Brush, fMin, 0, fMax - fMin, H);
                            //
                        }

                        g.DrawLine(line_dark_pen, pixel_x - 1, 0, pixel_x - 1, H); // left side
                        g.DrawLine(line_pen, pixel_x, 0, pixel_x, H); // center line
                        g.DrawLine(line_dark_pen, pixel_x + 1, 0, pixel_x + 1, H);// right side

                        g.InterpolationMode = InterpolationMode.Default;
                        g.SmoothingMode = SmoothingMode.Default;
                    }
                    else if (_mox && txMode == MeterTXMode.SWR_POWER)
                    {
                        pixel_x = Math.Max(0, pixel_x);
                        pixel_x = Math.Min(W - 3, pixel_x);
                        pixel_x_swr = Math.Max(0, pixel_x_swr);
                        pixel_x_swr = Math.Min(W - 3, pixel_x_swr);

                        line_dark_pen.Color =
                            Color.FromArgb((edge_avg_color.R + edge_meter_background_color.R) / 2,
                            (edge_avg_color.G + edge_meter_background_color.G) / 2,
                            (edge_avg_color.B + edge_meter_background_color.B) / 2);

                        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                        g.SmoothingMode = SmoothingMode.HighQuality;
                        if (!_mox)
                        {
                            g.DrawLine(line_dark_pen, pixel_x - 1, 0, pixel_x - 1, H); // left side
                            g.DrawLine(line_pen, pixel_x, 0, pixel_x, H); // center line
                            g.DrawLine(line_dark_pen, pixel_x + 1, 0, pixel_x + 1, H);// right side
                        }
                        else
                        {
                            g.DrawLine(line_dark_pen, pixel_x - 1, H / 2 + 3, pixel_x - 1, H); // left side
                            g.DrawLine(line_pen, pixel_x, H / 2 + 3, pixel_x, H); // center line
                            g.DrawLine(line_dark_pen, pixel_x + 1, H / 2 + 3, pixel_x + 1, H);// right side

                            g.DrawLine(line_dark_pen, pixel_x_swr - 1, 0, pixel_x_swr - 1, H / 2 - 3); // left side
                            g.DrawLine(line_pen, pixel_x_swr, 0, pixel_x_swr, H / 2 - 3); // center line
                            g.DrawLine(line_dark_pen, pixel_x_swr + 1, 0, pixel_x_swr + 1, H / 2 - 3);// right side
                        }

                        g.InterpolationMode = InterpolationMode.Default;
                        g.SmoothingMode = SmoothingMode.Default;
                    }
                    break;
                #endregion
                case MultiMeterDisplayMode.Analog:
                    #region Analog

                    #endregion
                    break;
            }

            meter_timer.Stop();

            string format = "f0";
            if (meter_detail) format = "f1";

            if (meter_timer.DurationMsec >= meter_dig_delay)
            {
                if (!_mox)
                {
                    switch (current_meter_rx_mode)
                    {
                        case MeterRXMode.SIGNAL_STRENGTH:
                        case MeterRXMode.SIGNAL_AVERAGE:
                            switch (m_eMeasureMode)
                            {
                                case MultiMeterMeasureMode.SMeter:
                                    output = Common.SMeterFromDBM(num, VFOAFreq >= S9Frequency);
                                    break;
                                case MultiMeterMeasureMode.DBM:
                                    output = num.ToString(format) + " dBm";
                                    break;
                                case MultiMeterMeasureMode.UV:
                                    if (meter_detail) format = "f2";
                                    output = Common.UVfromDBM(num).ToString(format) + " uV";
                                    break;
                            }
                            break;
                        case MeterRXMode.ADC_L:
                        case MeterRXMode.ADC_R:
                        case MeterRXMode.ADC2_L:
                        case MeterRXMode.ADC2_R:
                            output = num.ToString("f1") + " dBFS";
                            break;
                        case MeterRXMode.OFF:
                            output = "";
                            break;
                    }
                }
                else
                {
                    switch (txMode)
                    {
                        case MeterTXMode.MIC:
                        case MeterTXMode.LEVELER:
                        case MeterTXMode.LVL_G:
                        case MeterTXMode.EQ:
                        case MeterTXMode.CFC_PK:
                        case MeterTXMode.CFC_G:
                        case MeterTXMode.COMP:
                        case MeterTXMode.ALC:
                        case MeterTXMode.ALC_G:
                        case MeterTXMode.ALC_GROUP:
                            output = num.ToString(format) + " dB";
                            break;
                        case MeterTXMode.FORWARD_POWER:
                        case MeterTXMode.REVERSE_POWER:
                        case MeterTXMode.SWR_POWER:
                            if (current_hpsdr_model == HPSDRModel.ANAN10 ||
                                current_hpsdr_model == HPSDRModel.ANAN10E ||
                                apollopresent) output = num.ToString(format) + " W";
                            else if (alexpresent || pa_present) output = num.ToString(format) + " W";
                            else output = num.ToString(format) + " mW";
                            break;
                        case MeterTXMode.SWR:
                            output = num.ToString("f1") + " : 1";
                            break;
                        case MeterTXMode.OFF:
                            output = "";
                            break;
                    }
                }
                txtMultiText.Text = output;
                meter_timer.Start();
            }

            if (meter_data_ready)
            {
                meter_data_ready = false;  //We do NOT want to do this before we have consumed it!!!! so do it here.
            }
        }

        private double rx2_avg_num = Display.CLEAR_FLAG;//- 130.0;
        private void picRX2Meter_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            int H = picRX2Meter.ClientSize.Height;
            int W = picRX2Meter.ClientSize.Width;
            Graphics g = e.Graphics;
            double num = -200.0f;
            int pixel_x = 0;
            int pixel_x_swr = 0;
            string output = "";

            if (rx2_meter_data_ready)
            {
                rx2_meter_current_data = rx2_meter_new_data;
                rx2_meter_data_ready = false;
            }

            if (rx2_avg_num == Display.CLEAR_FLAG) // reset average -- just use new value
            {
                num = rx2_avg_num = rx2_meter_current_data;
                clearRXSignalPixels(2);
            }
            else
            {
                if (rx2_meter_current_data > rx2_avg_num)
                    num = rx2_avg_num = rx2_meter_current_data * 0.8 + rx2_avg_num * 0.2; // fast rise
                else
                    num = rx2_avg_num = rx2_meter_current_data * 0.2 + rx2_avg_num * 0.8; // slow decay
            }

            switch (current_meter_display_mode)
            {
                case MultiMeterDisplayMode.Original:
                    #region Original
                    g.FillRectangle(meter_background_pen.Brush, 0, 0, W, H);

                    if (rx2_meter_mode != MeterRXMode.OFF)
                    {
                        getMeterPixelPosAndDrawScales(2, g, H, W, num, out pixel_x, out pixel_x_swr, 1, false);

                        pixel_x = Math.Max(1, pixel_x);
                        pixel_x = Math.Min(W - 3, pixel_x);

                        if (num != -200) storeRX2SignalPixels_X((float)pixel_x / W);

                        // MW0LGE reworked size/heights
                        using (LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, pixel_x, H - 10),
                            meter_left_color, meter_right_color, LinearGradientMode.Horizontal))

                            g.FillRectangle(brush, 0, 0, pixel_x, H - 10);

                        for (int i = 0; i < (W / 8) - 1; i++)
                            g.DrawLine(meter_background_pen, 8 + i * 8, 0, 8 + i * 8, H - 10);

                        g.DrawLine(Pens.Red, pixel_x, 0, pixel_x, H - 10);
                        g.FillRectangle(meter_background_pen.Brush, pixel_x + 1, 0, W - pixel_x, H - 10);

                        if (pixel_x >= rx2_meter_peak_value)
                        {
                            rx2_meter_peak_count = 0;
                            rx2_meter_peak_value = pixel_x;
                        }
                        else
                        {
                            if (rx2_meter_peak_count++ >= multimeter_peak_hold_samples)
                            {
                                rx2_meter_peak_count = 0;
                                rx2_meter_peak_value = pixel_x;
                            }
                            else
                            {
                                g.DrawLine(Pens.Red, rx2_meter_peak_value, 0, rx2_meter_peak_value, H - 10);
                                g.DrawLine(Pens.Red, rx2_meter_peak_value - 1, 0, rx2_meter_peak_value - 1, H - 10);
                            }
                        }

                        if (m_bUseSignalHistory && m_RX2SignalPixels_X.Count > 0)
                        {
                            // the history swing
                            float fMin = m_RX2SignalPixels_X.Min() * W;
                            float fMax = m_RX2SignalPixels_X.Max() * W;
                            g.FillRectangle(m_SignalHistoryColourPen.Brush, fMin, H - 10, fMax - fMin, 10);
                            //
                        }
                    }
                    break;
                #endregion
                case MultiMeterDisplayMode.Edge:
                    #region Edge
                    g.DrawRectangle(edge_meter_background_pen, 0, 0, W, H);

                    // draw meter movement
                    if (rx2_meter_mode != MeterRXMode.OFF)
                    {
                        //MW0LGE moved all code into common function, used by both edge and original meter
                        getMeterPixelPosAndDrawScales(2, g, H, W, num, out pixel_x, out pixel_x_swr, 12, true);
                        //-

                        pixel_x = Math.Max(0, pixel_x);
                        pixel_x = Math.Min(W - 3, pixel_x);

                        if (num != -200) storeRX2SignalPixels_X((float)pixel_x / W);

                        line_dark_pen.Color =
                            Color.FromArgb((edge_avg_color.R + edge_meter_background_color.R) / 2,
                            (edge_avg_color.G + edge_meter_background_color.G) / 2,
                            (edge_avg_color.B + edge_meter_background_color.B) / 2);

                        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                        g.SmoothingMode = SmoothingMode.HighQuality;

                        if (m_bUseSignalHistory && m_RX2SignalPixels_X.Count > 0)
                        {
                            // the history swing
                            float fMin = m_RX2SignalPixels_X.Min() * W;
                            float fMax = m_RX2SignalPixels_X.Max() * W;
                            g.FillRectangle(m_SignalHistoryColourPen.Brush, fMin, 0, fMax - fMin, H);
                            //
                        }

                        g.DrawLine(line_dark_pen, pixel_x - 1, 0, pixel_x - 1, H); // left side
                        g.DrawLine(line_pen, pixel_x, 0, pixel_x, H); // center line
                        g.DrawLine(line_dark_pen, pixel_x + 1, 0, pixel_x + 1, H);// right side

                        g.InterpolationMode = InterpolationMode.Default;
                        g.SmoothingMode = SmoothingMode.Default;
                    }

                    if (rx2_meter_mode != MeterRXMode.OFF)
                    {
                        pixel_x = Math.Max(0, pixel_x);
                        pixel_x = Math.Min(W - 3, pixel_x);

                        line_dark_pen.Color =
                            Color.FromArgb((edge_avg_color.R + edge_meter_background_color.R) / 2,
                            (edge_avg_color.G + edge_meter_background_color.G) / 2,
                            (edge_avg_color.B + edge_meter_background_color.B) / 2);

                        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                        g.SmoothingMode = SmoothingMode.HighQuality;

                        g.DrawLine(line_dark_pen, pixel_x - 1, 0, pixel_x - 1, H); // left side
                        g.DrawLine(line_pen, pixel_x, 0, pixel_x, H); // center line
                        g.DrawLine(line_dark_pen, pixel_x + 1, 0, pixel_x + 1, H);// right side

                        g.InterpolationMode = InterpolationMode.Default;
                        g.SmoothingMode = SmoothingMode.Default;
                    }
                    break;
                #endregion
                case MultiMeterDisplayMode.Analog:
                    #region Analog

                    #endregion
                    break;
            }

            rx2_meter_timer.Stop();

            string format = "f0";
            if (meter_detail) format = "f1";

            if (rx2_meter_timer.DurationMsec >= meter_dig_delay)
            {
                switch (rx2_meter_mode)
                {
                    case MeterRXMode.SIGNAL_STRENGTH:
                    case MeterRXMode.SIGNAL_AVERAGE:
                        switch (m_eMeasureMode)
                        {
                            case MultiMeterMeasureMode.SMeter:
                                output = Common.SMeterFromDBM(num, VFOBFreq >= S9Frequency);
                                break;
                            case MultiMeterMeasureMode.DBM:
                                output = num.ToString(format) + " dBm";
                                break;
                            case MultiMeterMeasureMode.UV:
                                if (meter_detail) format = "f2";
                                output = Common.UVfromDBM(num).ToString(format) + " uV";
                                break;
                        }
                        break;
                    case MeterRXMode.ADC_L:
                    case MeterRXMode.ADC_R:
                    case MeterRXMode.ADC2_L:
                    case MeterRXMode.ADC2_R:
                        output = num.ToString("f1") + " dBFS";
                        break;
                    case MeterRXMode.OFF:
                        output = "";
                        break;
                }

                txtRX2Meter.Text = output;
                rx2_meter_timer.Start();
            }

            if (rx2_meter_data_ready)
            {
                rx2_meter_data_ready = false;  //We do NOT want to do this before we have consumed it!!!! so do it here.
            }
        }

        private void ResetMultiMeterPeak()
        {
            meter_peak_count = multimeter_peak_hold_samples;
            avg_num = Display.CLEAR_FLAG;
            clearRXSignalPixels(1);
        }

        private void ResetRX2MeterPeak()
        {
            rx2_meter_peak_count = multimeter_peak_hold_samples;
            rx2_avg_num = Display.CLEAR_FLAG; // MW0LGE_21a
            clearRXSignalPixels(2);
        }

        private void panelVFOAHover_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            if (vfoa_hover_digit < 0)
                return;

            int x = 0;
            int width = 0;

            if (small_lsd && txtVFOALSD.Visible)
            {
                x += (vfo_char_width + vfo_char_space) * vfoa_hover_digit;
                if (vfoa_hover_digit > 3)
                    x += (vfo_decimal_space - vfo_char_space);

                if (vfoa_hover_digit > 6)
                {
                    x += vfo_small_char_width;
                    x += (vfo_small_char_width + vfo_small_char_space - vfo_char_width - vfo_char_space) * (vfoa_hover_digit - 6);
                    width = x + vfo_small_char_width;
                }
                else width = x + vfo_char_width;
            }
            else
            {
                x += (vfo_char_width + vfo_char_space) * vfoa_hover_digit;
                if (vfoa_hover_digit > 3)
                    x += (vfo_decimal_space - vfo_char_space);
                width = x + vfo_char_width;
            }
            e.Graphics.DrawLine(txtvfoafreq_forecolor_pen, x, 1, width, 1);
        }

        private void panelVFOBHover_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            if (vfob_hover_digit < 0)
                return;

            int x = 0;
            int width = 0;

            if (small_lsd && txtVFOBLSD.Visible)
            {
                x += (vfo_char_width + vfo_char_space) * vfob_hover_digit;
                if (vfob_hover_digit > 3)
                    x += (vfo_decimal_space - vfo_char_space);

                if (vfob_hover_digit > 6)
                {
                    x += vfo_small_char_width;
                    x += (vfo_small_char_width + vfo_small_char_space - vfo_char_width - vfo_char_space) * (vfob_hover_digit - 6);
                    width = x + vfo_small_char_width;
                }
                else width = x + vfo_char_width;
            }
            else
            {
                x += (vfo_char_width + vfo_char_space) * vfob_hover_digit;
                if (vfob_hover_digit > 3)
                    x += (vfo_decimal_space - vfo_char_space);
                width = x + vfo_char_width;
            }
            using (Pen p = new Pen(txtVFOBFreq.ForeColor, 2.0f))
                e.Graphics.DrawLine(p, x, 1, width, 1);
        }
        #endregion

        #region Thread and Timer Routines
        // ======================================================
        // Thread Routines
        // ======================================================

        private bool m_bUseAccurateFrameTiming = false;
        public bool UseAccurateFramingTiming {
            get { return m_bUseAccurateFrameTiming; }
            set { m_bUseAccurateFrameTiming = value; }
        }

        //private Thread _spectrum_thread = null;
        //private bool _spectrumLoopRunning = false;       
        public Mutex _spectrum_mutex = new Mutex();
        //private void RunSpectrum()
        //{
        //    const int centreSubSpan = 0;
        //    const int nFps = 20;

        //    int nOldFFTSize = -1;
        //    double[,] spectrum_data = null;
        //    int flag = 0;

        //    _spectrumLoopRunning = true;
        //    while (_spectrumLoopRunning)
        //    {
        //        if (chkPower.Checked)
        //        {
        //            if (!MeterManager.SpectrumReady)
        //            {                        
        //                int fftSize = specRX.GetSpecRX(0).FFTSize;

        //                if (spectrum_data == null || nOldFFTSize != fftSize)
        //                {
        //                    spectrum_data = new double[fftSize, 2];
        //                    nOldFFTSize = fftSize;
        //                }

        //                _spectrum_mutex.WaitOne();
        //                unsafe
        //                {
        //                    fixed (double* ptr = &(spectrum_data[0, 0]))
        //                        SpecHPSDRDLL.SnapSpectrum(0, centreSubSpan, 0, ptr);
        //                }
        //                _spectrum_mutex.ReleaseMutex();

        //                if (flag == 1)
        //                {
        //                    float[] pbSpec = getPassbandSpectrum(1, fftSize, spectrum_data);
        //                    if (pbSpec != null)
        //                    {
        //                        int nLen = pbSpec.Length;

        //                        MeterManager.ResizeSpectrum(nLen);

        //                        unsafe
        //                        {
        //                            fixed (void* srcptr = &pbSpec[0])
        //                            fixed (void* destptr = &MeterManager._newSpectrumPassband[0])
        //                                Win32.memcpy(destptr, srcptr, nLen * sizeof(float));
        //                        }

        //                        MeterManager.SpectrumReady = true;
        //                    }
        //                }
        //            }
        //        }
        //        Thread.Sleep(1000 / nFps);
        //    }
        //}
        private void resetWDSPdisplayBuffers(int rx, bool tx)
        {
            if (rx == 1)
            {
                if (tx)
                {
                    if (!display_duplex)
                    {
                        if (chkVFOATX.Checked || !chkRX2.Checked)
                        {
                            specRX.GetSpecRX(cmaster.inid(1, 0)).resetPixelBuffers();
                        }
                        else
                        {
                            specRX.GetSpecRX(0).resetPixelBuffers();
                        }
                    }
                    else
                    {
                        specRX.GetSpecRX(0).resetPixelBuffers();
                    }
                }
                else
                {
                    specRX.GetSpecRX(0).resetPixelBuffers();
                }
            }
            else
            {
                if (tx && VFOBTX)
                {
                    specRX.GetSpecRX(cmaster.inid(1, 0)).resetPixelBuffers();
                }
                else
                {
                    specRX.GetSpecRX(1).resetPixelBuffers();
                }
            }
        }
        private bool _wdsp_mox_transition_buffer_clear = false;
        public bool WDSPMOXTransitionBufferClear
        {
            get { return _wdsp_mox_transition_buffer_clear; }
            set
            {
                _wdsp_mox_transition_buffer_clear = value;
                Display.WDSPMOXTransitionBufferClear = _wdsp_mox_transition_buffer_clear;
            }
        }
        unsafe private void RunDisplay()
        {
            m_bDisplayLoopRunning = true;

            try
            {
                HiPerfTimer objStopWatch = new HiPerfTimer();
                double fFractionOfMs = 0;
                double fThreadSleepOverRun = 0;
                bool bOldLocalMox = Display.MOX;

                while (m_bDisplayLoopRunning)
                {
                    #region debug_text
                    if (m_bEnableDisplayDebug)
                    {
                        Display.DebugText = "chkVFOSplit : " + chkVFOSplit.Checked.ToString() + Environment.NewLine +
                            "VFOATX : " + VFOATX.ToString() + Environment.NewLine +
                            "VFOBTX : " + VFOBTX.ToString() + Environment.NewLine +
                            "VFOA : " + VFOAFreq.ToString() + Environment.NewLine +
                            "VFOB : " + VFOBFreq.ToString() + Environment.NewLine +
                            "VFOAsub : " + VFOASubFreq.ToString() + Environment.NewLine +
                            "CenRX1 : " + CentreFrequency.ToString() + Environment.NewLine +
                            "CenRX2 : " + CentreRX2Frequency.ToString() + Environment.NewLine +
                            "DisplayVFOA : " + Display.VFOA.ToString() + Environment.NewLine +
                            "DisplayVFOB : " + Display.VFOB.ToString() + Environment.NewLine +
                            "DisplayVFOAsub : " + Display.VFOASub.ToString() + Environment.NewLine +
                            //"DisplayVFOBsub : " + Display.VFOBSub.ToString() + Environment.NewLine + // not used for anything
                            "DisplayFreqDiff : " + Display.FreqDiff.ToString() + Environment.NewLine +
                            "DisplayRX2FreqDiff : " + Display.RX2FreqDiff.ToString() + Environment.NewLine +
                            "Xpixels : " + picDisplay.Width.ToString() + Environment.NewLine +
                            "Ypixels : " + picDisplay.Height.ToString() + Environment.NewLine +
                            "rx1_click_tune_drag : " + rx1_click_tune_drag.ToString() + Environment.NewLine +
                            "rx1_spectrum_tune_drag : " + rx1_spectrum_tune_drag.ToString() + Environment.NewLine +
                            "rx1_spectrum_drag : " + rx1_spectrum_drag.ToString() + Environment.NewLine +
                            "click_tune_display : " + click_tune_display.ToString() + Environment.NewLine +
                            "rx2_click_tune_drag : " + rx2_click_tune_drag.ToString() + Environment.NewLine +
                            "rx2_spectrum_tune_drag : " + rx2_spectrum_tune_drag.ToString() + Environment.NewLine +
                            "rx2_spectrum_drag : " + rx2_spectrum_drag.ToString() + Environment.NewLine +
                            "click_tune_rx2_display : " + click_tune_rx2_display.ToString() + Environment.NewLine +
                            "ClickTuneDrag : " + ClickTuneDrag.ToString() + Environment.NewLine +
                            "display_duplex : " + display_duplex.ToString() + Environment.NewLine +
                            "cachedMeasureStrings : " + Display.CachedMeasureStringsCount.ToString() + Environment.NewLine +
                            "cachedDXBrushes : " + Display.CachedDXBrushes.ToString() + Environment.NewLine +
                            //"AttackFastFramesRX1 : " + Display.AttackFastFramesRX1.ToString() + Environment.NewLine +
                            //"AttackFastFramesRX2 : " + Display.AttackFastFramesRX2.ToString() + Environment.NewLine +
                            "CurrentClickTuneMode : " + CurrentClickTuneMode.ToString() + Environment.NewLine +
                            "Cursor : " + picDisplay.Cursor.ToString() + Environment.NewLine +
                            "rx1_squelch_state : " + rx1_squelch_state.ToString() + Environment.NewLine +
                            "rx1_fm_squelch_state : " + rx1_fm_squelch_state.ToString() + Environment.NewLine +
                            "rx1_squelch_threshold_scroll : " + rx1_squelch_threshold_scroll.ToString() + Environment.NewLine +
                            "rx1_fm_squelch_threshold_scroll : " + rx1_fm_squelch_threshold_scroll.ToString() + Environment.NewLine +
                            "rx1_voice_squelch_threshold_scroll : " + rx1_voice_squelch_threshold_scroll.ToString() + Environment.NewLine +
                            "rx2_squelch_state : " + rx2_squelch_state.ToString() + Environment.NewLine +
                            "rx2_fm_squelch_state : " + rx2_fm_squelch_state.ToString() + Environment.NewLine +
                            "rx2_squelch_threshold_scroll : " + rx2_squelch_threshold_scroll.ToString() + Environment.NewLine +
                            "rx2_fm_squelch_threshold_scroll : " + rx2_fm_squelch_threshold_scroll.ToString() + Environment.NewLine +
                            "rx2_voice_squelch_threshold_scroll : " + rx2_voice_squelch_threshold_scroll.ToString() + Environment.NewLine +
                            "RXDisplayLow : " + Display.RXDisplayLow.ToString() + Environment.NewLine +
                            "RXDisplayHigh : " + Display.RXDisplayHigh.ToString() + Environment.NewLine +
                            "RX2DisplayLow : " + Display.RX2DisplayLow.ToString() + Environment.NewLine +
                            "RX2DisplayHigh : " + Display.RX2DisplayHigh.ToString() + Environment.NewLine +
                            "TXDisplayLow : " + Display.TXDisplayLow.ToString() + Environment.NewLine +
                            "TXDisplayHigh : " + Display.TXDisplayHigh.ToString() + Environment.NewLine +
                            "RX1DisplayCalOffset : " + Display.RX1DisplayCalOffset.ToString() + Environment.NewLine +
                            "RX2DisplayCalOffset : " + Display.RX2DisplayCalOffset.ToString() + Environment.NewLine +
                            "TXDisplayCalOffset : " + Display.TXDisplayCalOffset.ToString() + Environment.NewLine +
                            "mon_recall : " + mon_recall.ToString();
                    }
                    #endregion

                    objStopWatch.Reset();

                    if (m_bResizeDX2Display)
                    {
                        Display.Target = picDisplay;
                        m_bResizeDX2Display = false;
                    }

                    uint top_thread = 0;
                    uint bottom_thread = 2;
                    int flag = -1;
                    int flag2 = -1;
                    bool bDataReady = false;
                    bool bWaterfallDataReady = false;
                    bool bN1mm = false;
                    bool bLocalMox = Display.MOX; // gets updated in UIMOXChangedTrue/UIMOXChangedFalse after _mox is changed
                    bool bGetPixelIssue = true;
                    bool bGetPixelIssueBottom = RX2Enabled;

                    //MW0LGE_21g
                    if (bLocalMox)
                    {
                        if (chkVFOATX.Checked || !chkRX2.Checked) top_thread = 1;
                        else if (chkVFOBTX.Checked && chkRX2.Checked) bottom_thread = 1;
                    }

                    if (bLocalMox != bOldLocalMox)
                    {
                        // if the mox state is different, reset the analyzer to remove
                        // possibilty of tx data being in the rx buffers, and vice versa
                        if (_wdsp_mox_transition_buffer_clear)
                        {
                            resetWDSPdisplayBuffers(1, bLocalMox);
                            if (RX2Enabled)
                                resetWDSPdisplayBuffers(2, bLocalMox);
                        }

                        Display.PurgeBuffers();

                        bOldLocalMox = bLocalMox;
                    }

                    if ((!Display.DataReady || !Display.WaterfallDataReady) ||
                        (chkSplitDisplay.Checked && (!Display.DataReadyBottom || !Display.WaterfallDataReadyBottom)))
                    {
                        if (calibration_running)
                        {
                            calibration_mutex.WaitOne();
                            displaydidit = true;
                        }

                        if (!_pause_DisplayThread) // skip any of this
                        {
                            if ((!Display.DataReady || !Display.WaterfallDataReady) &&
                                Display.CurrentDisplayMode != DisplayMode.OFF)
                            {
                                flag2 = -1;
                                bDataReady = false;
                                bWaterfallDataReady = false;
                                bN1mm = false;

                                switch (Display.CurrentDisplayMode)
                                {
                                    case DisplayMode.WATERFALL:
                                    case DisplayMode.PANAFALL:
                                        if (bLocalMox && !display_duplex)
                                        {
                                            if (chkVFOATX.Checked || !chkRX2.Checked)
                                            {
                                                fixed (float* ptr = &Display.new_display_data[0])
                                                    SpecHPSDRDLL.GetPixels(cmaster.inid(1, 0), 0, ptr, ref flag);
                                                bDataReady = (flag == 1);
                                                fixed (float* ptr = &Display.new_waterfall_data[0])
                                                    SpecHPSDRDLL.GetPixels(cmaster.inid(1, 0), 1, ptr, ref flag);
                                                bWaterfallDataReady = (flag == 1);
                                            }
                                            else
                                            {
                                                fixed (float* ptr = &Display.new_display_data[0])
                                                    SpecHPSDRDLL.GetPixels(0, 0, ptr, ref flag);
                                                bDataReady = (flag == 1);
                                                fixed (float* ptr = &Display.new_waterfall_data[0])
                                                    SpecHPSDRDLL.GetPixels(0, 1, ptr, ref flag);
                                                bWaterfallDataReady = (flag == 1);
                                            }
                                        }
                                        else //rx
                                        {
                                            fixed (float* ptr = &Display.new_display_data[0])
                                                SpecHPSDRDLL.GetPixels(0, 0, ptr, ref flag);
                                            bDataReady = (flag == 1);
                                            bN1mm = true;
                                            fixed (float* ptr = &Display.new_waterfall_data[0])
                                                SpecHPSDRDLL.GetPixels(0, 1, ptr, ref flag);
                                            bWaterfallDataReady = (flag == 1);
                                        }
                                        break;
                                    case DisplayMode.SPECTRUM:
                                    case DisplayMode.HISTOGRAM:
                                    case DisplayMode.SPECTRASCOPE:
                                    case DisplayMode.PANADAPTER:
                                    case DisplayMode.PANASCOPE:
                                        if (bLocalMox && !display_duplex)
                                        {
                                            if (chkVFOATX.Checked || !chkRX2.Checked)
                                            {
                                                fixed (float* ptr = &Display.new_display_data[0])
                                                    SpecHPSDRDLL.GetPixels(cmaster.inid(1, 0), 0, ptr, ref flag);
                                                bDataReady = (flag == 1);
                                            }
                                            else
                                            {
                                                fixed (float* ptr = &Display.new_display_data[0])
                                                    SpecHPSDRDLL.GetPixels(0, 0, ptr, ref flag);
                                                bDataReady = (flag == 1);
                                            }
                                        }
                                        else
                                        {
                                            fixed (float* ptr = &Display.new_display_data[0])
                                                SpecHPSDRDLL.GetPixels(0, 0, ptr, ref flag);
                                            bDataReady = (flag == 1);
                                            bN1mm = Display.CurrentDisplayMode == DisplayMode.PANADAPTER || Display.CurrentDisplayMode == DisplayMode.PANASCOPE;
                                        }
                                        break;
                                    case DisplayMode.SCOPE:  //[2.10.3.4]MW0LGE not used anymore since scope was coded in cmaster.cs
                                    case DisplayMode.SCOPE2:
                                        bDataReady = true;
                                        break;
                                    case DisplayMode.PHASE:
                                        fixed (float* ptr = &Display.new_display_data[0])
                                        {
                                            if (top_thread != 1)
                                                WDSP.RXAGetaSipF1(WDSP.id(top_thread, 0), ptr, Display.PhaseNumPts);
                                            else
                                                WDSP.TXAGetaSipF1(WDSP.id(top_thread, 0), ptr, Display.PhaseNumPts);
                                        }
                                        bDataReady = true;
                                        break;
                                    case DisplayMode.PHASE2:
                                        if (Audio.phase_buf_l != null && Audio.phase_buf_r != null) // MW0LGE would be null if audio not running (ie not connected?)
                                        {
                                            for (int i = 0; i < Display.PhaseNumPts; i++)
                                            {
                                                Display.new_display_data[i * 2] = Audio.phase_buf_l[i];
                                                Display.new_display_data[i * 2 + 1] = Audio.phase_buf_r[i];
                                            }
                                            bDataReady = true;
                                        }
                                        break;
                                }

                                Display.DataReady = bDataReady;
                                Display.WaterfallDataReady = bWaterfallDataReady;
                                if (bN1mm && N1MM.IsStarted)
                                {
                                    if (bDataReady)
                                        N1MM.CopyData(1, Display.new_display_data);
                                    else if (bWaterfallDataReady)
                                        N1MM.CopyData(1, Display.new_waterfall_data);
                                }

                                bGetPixelIssue = !bDataReady && !bWaterfallDataReady;
                            }

                            if (chkSplitDisplay.Checked &&
                                (!Display.DataReadyBottom || !Display.WaterfallDataReadyBottom) &&
                                Display.CurrentDisplayModeBottom != DisplayMode.OFF)
                            {
                                flag2 = -1;
                                bDataReady = false;
                                bWaterfallDataReady = false;
                                bN1mm = false;

                                switch (Display.CurrentDisplayModeBottom)
                                {
                                    case DisplayMode.SPECTRUM:
                                    case DisplayMode.HISTOGRAM:
                                        break;
                                    case DisplayMode.WATERFALL:
                                        if (bLocalMox && VFOBTX)
                                        {
                                            fixed (float* ptr = &Display.new_waterfall_data_bottom[0])
                                                SpecHPSDRDLL.GetPixels(cmaster.inid(1, 0), 1, ptr, ref flag2);
                                            bWaterfallDataReady = (flag2 == 1);
                                        }
                                        else
                                        {
                                            fixed (float* ptr = &Display.new_waterfall_data_bottom[0])
                                                SpecHPSDRDLL.GetPixels(1, 1, ptr, ref flag2);
                                            bWaterfallDataReady = (flag2 == 1);
                                            bN1mm = true;
                                        }
                                        break;
                                    case DisplayMode.PANADAPTER:
                                        if (bLocalMox && VFOBTX)
                                        {
                                            fixed (float* ptr = &Display.new_display_data_bottom[0])
                                                SpecHPSDRDLL.GetPixels(cmaster.inid(1, 0), 0, ptr, ref flag2);
                                            bDataReady = (flag2 == 1);
                                        }
                                        else
                                        {
                                            fixed (float* ptr = &Display.new_display_data_bottom[0])
                                                SpecHPSDRDLL.GetPixels(1, 0, ptr, ref flag2);
                                            bDataReady = (flag2 == 1);
                                            bN1mm = true;
                                        }
                                        break;
                                    case DisplayMode.PANAFALL:  // MW0LGE
                                        if (bLocalMox && VFOBTX)
                                        {
                                            fixed (float* ptr = &Display.new_display_data_bottom[0])
                                                SpecHPSDRDLL.GetPixels(cmaster.inid(1, 0), 0, ptr, ref flag2);
                                            bDataReady = (flag2 == 1);
                                            fixed (float* ptr = &Display.new_waterfall_data_bottom[0])
                                                SpecHPSDRDLL.GetPixels(cmaster.inid(1, 0), 1, ptr, ref flag2);
                                            bWaterfallDataReady = (flag2 == 1);
                                        }
                                        else
                                        {
                                            fixed (float* ptr = &Display.new_display_data_bottom[0])
                                                SpecHPSDRDLL.GetPixels(1, 0, ptr, ref flag2);
                                            bDataReady = (flag2 == 1);
                                            bN1mm = true;
                                            fixed (float* ptr = &Display.new_waterfall_data_bottom[0])
                                                SpecHPSDRDLL.GetPixels(1, 1, ptr, ref flag2);
                                            bWaterfallDataReady = (flag2 == 1);
                                        }
                                        break;
                                    case DisplayMode.SCOPE:  //[2.10.3.4]MW0LGE not used anymore since scope was coded in cmaster.cs
                                    case DisplayMode.SCOPE2:
                                        bDataReady = true;
                                        break;
                                    case DisplayMode.PHASE:
                                        fixed (float* ptr = &Display.new_display_data_bottom[0])
                                        {
                                            if (bottom_thread != 1)
                                                WDSP.RXAGetaSipF1(WDSP.id(bottom_thread, 0), ptr, Display.PhaseNumPts);
                                            else
                                                WDSP.TXAGetaSipF1(WDSP.id(bottom_thread, 0), ptr, Display.PhaseNumPts);
                                        }
                                        bDataReady = true;
                                        break;
                                    case DisplayMode.PHASE2:
                                        if (Audio.phase_buf_l != null && Audio.phase_buf_r != null) // MW0LGE would be null if audio not running (ie not connected?)
                                        {
                                            for (int i = 0; i < Display.PhaseNumPts; i++)
                                            {
                                                Display.new_display_data_bottom[i * 2] = Audio.phase_buf_l[i];
                                                Display.new_display_data_bottom[i * 2 + 1] = Audio.phase_buf_r[i];
                                            }
                                            bDataReady = true;
                                        }
                                        break;
                                }

                                Display.DataReadyBottom = bDataReady;
                                Display.WaterfallDataReadyBottom = bWaterfallDataReady;
                                if (bN1mm && N1MM.IsStarted)
                                {
                                    if (bDataReady)
                                        N1MM.CopyData(2, Display.new_display_data_bottom);
                                    else if (bWaterfallDataReady)
                                        N1MM.CopyData(2, Display.new_waterfall_data_bottom);
                                }

                                bGetPixelIssueBottom = !bDataReady && !bWaterfallDataReady;
                            }
                        }

                        if (displaydidit)
                        {
                            displaydidit = false;
                            calibration_mutex.ReleaseMutex();
                        }
                    }

                    //WDSP could not return us data this frame if one of these are set
                    //display engine will use last good
                    Display.GetPixelsIssueRX1 = bGetPixelIssue;
                    Display.GetPixelsIssueRX2 = bGetPixelIssueBottom;

                    //render everything
                    if (!_pause_DisplayThread) Display.RenderDX2D();

                    #region FrameTiming
                    //MW0LGE consider how long all the above took (reset at start of loop), and remove any inaccuarcy from Thread.Sleep
                    //fThreadSleepOverRun will have some value if the Thread.Sleep(x) took longer than x. If so we need to
                    //delay slightly less this time
                    double dly = _display_delay - objStopWatch.ElapsedMsec - fThreadSleepOverRun;
                    if (dly < 0)
                    {
                        if (dly <= -1) Display.FrameRateIssue = true;
                        dly = 0;
                        fFractionOfMs = 0;
                    }
                    else
                        Display.FrameRateIssue = false;

                    if (m_bUseAccurateFrameTiming)
                    {
                        // wait for the calculated delay
                        objStopWatch.Reset();
                        while (objStopWatch.ElapsedMsec <= dly) ;
                        fThreadSleepOverRun = objStopWatch.ElapsedMsec - dly;
                    }
                    else
                    {
                        // accumulate the fractional delay
                        int nIntegerDelay = (int)dly;
                        fFractionOfMs += dly - nIntegerDelay;
                        int nIntegerFractions = (int)fFractionOfMs;
                        fFractionOfMs -= nIntegerFractions;

                        int nWantToWait = nIntegerDelay + nIntegerFractions;
                        fThreadSleepOverRun = 0;

                        if (nWantToWait > 0)
                        {
                            // time how long we actually sleep for, and use this difference to lower dly time next time around
                            objStopWatch.Reset();
                            Thread.Sleep(nWantToWait); // not guaranteed to be the delay we want, but it will be AT LEAST what we want
                            fThreadSleepOverRun = objStopWatch.ElapsedMsec - nWantToWait;
                        }
                        else if (fFractionOfMs > 0)
                        {
                            objStopWatch.Reset();
                            while (objStopWatch.ElapsedMsec <= fFractionOfMs) ;
                            fFractionOfMs = objStopWatch.ElapsedMsec - fFractionOfMs;
                        }
                    }
                    #endregion
                }
            }
            catch (Exception e)
            {
                Common.LogException(e);
            }

            m_bDisplayLoopRunning = false;
            Debug.Print("display ended");
        }

        private HiPerfTimer meter_timer = new HiPerfTimer();
        private Dictionary<Reading, float> _RX1MeterValues;
        private Dictionary<Reading, float> _RX2MeterValues;

        private async void UpdateMultimeter()
        {
            meter_timer.Start();
            while (_useLegacyMeters && chkPower.Checked)
            {
                if (!meter_data_ready)
                {
                    if (!_mox)
                    {
                        MeterRXMode mode = CurrentMeterRXMode;
                        float num = 0.0f;
                        float rx1PreampOffset = 0.0f;

                        if (rx1_step_att_present) rx1PreampOffset = (float)rx1_attenuator_data;
                        else rx1PreampOffset = rx1_preamp_offset[(int)rx1_preamp_mode];

                        switch (mode)
                        {
                            case MeterRXMode.SIGNAL_STRENGTH:
                                num = WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.SIGNAL_STRENGTH);
                                num = num +
                                 rx1_meter_cal_offset +
                                 rx1PreampOffset +
                                 rx1_xvtr_gain_offset +
                                 rx1_6m_gain_offset;

                                new_meter_data = num;
                                break;
                            case MeterRXMode.SIGNAL_AVERAGE:
                                num = WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.AVG_SIGNAL_STRENGTH);
                                num = num +
                                  rx1_meter_cal_offset +
                                   rx1PreampOffset +
                                   rx1_xvtr_gain_offset +
                                   rx1_6m_gain_offset;
                                new_meter_data = num;
                                break;
                            case MeterRXMode.ADC_L:
                                num = WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.ADC_REAL);
                                new_meter_data = num;
                                break;
                            case MeterRXMode.ADC_R:
                                num = WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.ADC_IMAG);
                                new_meter_data = num;
                                break;
                            case MeterRXMode.ADC2_L:
                                num = WDSP.CalculateRXMeter(2, 0, WDSP.MeterType.ADC_REAL);
                                new_meter_data = num;
                                break;
                            case MeterRXMode.ADC2_R:
                                num = WDSP.CalculateRXMeter(2, 0, WDSP.MeterType.ADC_IMAG);
                                new_meter_data = num;
                                break;
                            case MeterRXMode.OFF:
                                new_meter_data = -200.0f;
                                break;
                        }
                    }
                    else
                    {
                        MeterTXMode mode = CurrentMeterTXMode;
                        float num = 0f;

                        switch (mode)
                        {
                            case MeterTXMode.MIC:
                                num = (float)Math.Max(-195.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.MIC_PK));
                                new_meter_data = num;
                                break;
                            case MeterTXMode.EQ:
                                num = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.EQ_PK));
                                new_meter_data = num;
                                break;
                            case MeterTXMode.LEVELER:
                                num = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.LEVELER_PK));
                                new_meter_data = num;
                                break;
                            case MeterTXMode.LVL_G:
                                num = (float)Math.Max(0, WDSP.CalculateTXMeter(1, WDSP.MeterType.LVL_G));
                                new_meter_data = num;
                                break;
                            case MeterTXMode.CFC_PK:
                                num = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.CFC_PK));
                                new_meter_data = num;
                                break;
                            case MeterTXMode.CFC_G:
                                num = (float)Math.Max(0, -WDSP.CalculateTXMeter(1, WDSP.MeterType.CFC_G));
                                new_meter_data = num;
                                break;
                            case MeterTXMode.COMP:
                                if (peak_tx_meter) num = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.CPDR_PK));
                                else num = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.CPDR));
                                new_meter_data = num;
                                break;
                            case MeterTXMode.ALC:
                                if (peak_tx_meter) num = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC_PK));
                                else num = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC));
                                new_meter_data = num;
                                break;
                            case MeterTXMode.ALC_G:
                                num = (float)Math.Max(0, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC_G));
                                new_meter_data = num;
                                break;
                            case MeterTXMode.ALC_GROUP: //MW0LGE ALC_GROUP is the sum of ALC and ALC_G
                                if (peak_tx_meter) num = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC_PK));
                                else num = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC));

                                num += (float)Math.Max(0, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC_G));

                                new_meter_data = num;
                                break;
                            case MeterTXMode.FORWARD_POWER:
                            case MeterTXMode.SWR_POWER:
                                if (alexpresent || apollopresent)
                                {
                                    if (current_hpsdr_model == HPSDRModel.ANAN8000D)
                                    {
                                        if (tx_xvtr_index >= 0)
                                        {
                                            new_meter_data = drivepwr;
                                        }
                                        else
                                        {
                                            new_meter_data = calfwdpower;
                                        }
                                    }
                                    else
                                    {
                                        new_meter_data = calfwdpower;
                                    }
                                }
                                else
                                    new_meter_data = drivepwr;

                                if (current_meter_tx_mode == MeterTXMode.SWR_POWER) new_swrmeter_data = alex_swr;
                                break;
                            case MeterTXMode.REVERSE_POWER:
                                if (alexpresent || apollopresent)
                                {
                                    new_meter_data = (float)alex_rev;
                                }
                                break;
                            case MeterTXMode.SWR:
                                new_meter_data = alex_swr;
                                break;
                            case MeterTXMode.OFF:
                                //output = "";
                                new_meter_data = -200.0f;
                                break;
                        }

                        if (pa_values)
                        {
                            SetupForm.textDriveFwdADCValue.Text = average_drvadc.ToString("f0");
                            SetupForm.textFwdADCValue.Text = average_fwdadc.ToString("f0");
                            SetupForm.textRevADCValue.Text = average_revadc.ToString("f0");
                            SetupForm.textDrivePower.Text = average_drivepwr.ToString("f0") + " mW";
                            SetupForm.textPAFwdPower.Text = alex_fwd.ToString("f1") + " W";
                            SetupForm.textPARevPower.Text = alex_rev.ToString("f1") + " W";
                            SetupForm.textCaldFwdPower.Text = calfwdpower.ToString("f1") + " W";
                            SetupForm.textSWR.Text = alex_swr.ToString("f2") + ":1";
                        }

                    }
                    meter_data_ready = true;
                    picMultiMeterDigital.Invalidate();
                }

                await Task.Delay(Math.Min(meter_delay, meter_dig_delay));
            }
        }

        private HiPerfTimer rx2_meter_timer = new HiPerfTimer();

        private async void UpdateRX2MeterData()
        {
            rx2_meter_timer.Start();
            while (_useLegacyMeters && chkPower.Checked && rx2_enabled)
            {
                if (!rx2_meter_data_ready)
                {
                    //MW0LGE_21d step atten
                    MeterRXMode mode = RX2MeterMode;
                    float rx2PreampOffset = 0;
                    if (current_hpsdr_model == HPSDRModel.ANAN100D ||
                        current_hpsdr_model == HPSDRModel.ANAN200D ||
                        current_hpsdr_model == HPSDRModel.ORIONMKII ||
                        current_hpsdr_model == HPSDRModel.ANAN7000D ||
                        current_hpsdr_model == HPSDRModel.ANAN8000D ||
                        current_hpsdr_model == HPSDRModel.ANAN_G2 ||
                        current_hpsdr_model == HPSDRModel.ANAN_G2_1K ||
                        rx2_preamp_present)
                    {
                        if (rx2_step_att_present)
                            rx2PreampOffset = (float)rx2_attenuator_data;
                        else
                            rx2PreampOffset = rx2_preamp_offset[(int)rx2_preamp_mode];
                    }
                    else
                    {
                        if (rx1_step_att_present)
                        {
                            rx2PreampOffset = (float)rx1_attenuator_data;
                        }
                        else
                        {
                            rx2PreampOffset = rx1_preamp_offset[(int)rx1_preamp_mode];
                        }
                    }

                    float num;
                    switch (mode)
                    {
                        case MeterRXMode.SIGNAL_STRENGTH:
                            num = WDSP.CalculateRXMeter(2, 0, WDSP.MeterType.SIGNAL_STRENGTH);

                            num = num +
                              rx2_meter_cal_offset + // MW0LGE was rx1_meter_cal_offset
                              rx2PreampOffset +
                              rx2_xvtr_gain_offset;
                            if (current_hpsdr_model == HPSDRModel.ANAN7000D || current_hpsdr_model == HPSDRModel.ANAN8000D ||
                                current_hpsdr_model == HPSDRModel.ANAN_G2 || current_hpsdr_model == HPSDRModel.ANAN_G2_1K) num += rx2_6m_gain_offset;
                            rx2_meter_new_data = num;
                            break;
                        case MeterRXMode.SIGNAL_AVERAGE:
                            num = WDSP.CalculateRXMeter(2, 0, WDSP.MeterType.AVG_SIGNAL_STRENGTH);
                            num = num +
                            rx2_meter_cal_offset + // MW0LGE was rx1_meter_cal_offset
                            rx2PreampOffset +
                            rx2_xvtr_gain_offset;
                            if (current_hpsdr_model == HPSDRModel.ANAN7000D || current_hpsdr_model == HPSDRModel.ANAN8000D ||
                                current_hpsdr_model == HPSDRModel.ANAN_G2 || current_hpsdr_model == HPSDRModel.ANAN_G2_1K) num += rx2_6m_gain_offset;
                            rx2_meter_new_data = num;
                            break;
                        case MeterRXMode.ADC_L:
                            num = WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.ADC_REAL);
                            rx2_meter_new_data = num;
                            break;
                        case MeterRXMode.ADC_R:
                            num = WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.ADC_IMAG);
                            rx2_meter_new_data = num;
                            break;
                        case MeterRXMode.ADC2_L:
                            num = WDSP.CalculateRXMeter(2, 0, WDSP.MeterType.ADC_REAL);
                            rx2_meter_new_data = num;
                            break;
                        case MeterRXMode.ADC2_R:
                            num = WDSP.CalculateRXMeter(2, 0, WDSP.MeterType.ADC_IMAG);
                            rx2_meter_new_data = num;
                            break;
                        case MeterRXMode.OFF:
                            rx2_meter_new_data = -200.0f;
                            break;
                    }
                    rx2_meter_data_ready = true;
                    picRX2Meter.Invalidate();
                }

                await Task.Delay(Math.Min(meter_delay, meter_dig_delay));
            }
        }

        public float computeHermesDCVoltage()
        {
            float volt_div = (4.7f + 0.82f) / 0.82f; // Voltage divider (R1 + R2) / R2
            int adc = NetworkIO.getHermesDCVoltage();
            float volts = (float)adc / 4095 * 3.3f;
            float batt_volts = volts * volt_div;
            return batt_volts;
        }

        private float _MKIIPAVolts = 0f;
        private float _MKIIPAAmps = 0f;
        private ConcurrentQueue<int> _voltsQueue = new ConcurrentQueue<int>();
        private ConcurrentQueue<int> _ampsQueue = new ConcurrentQueue<int>();
        public float MKIIPAVolts
        {
            get { return _MKIIPAVolts; }
        }
        private async void readMKIIPAVoltsAmps()
        {
            string sVALog = Path.Combine(AppDataPath, "VALog.txt");

            // MW0LGE_21k9c
            // old method ran ~100ms of volts and ~100ms of amps, then waited 600ms, total time for 100 readings of each = 800ms
            // new method takes two readings every 8ms into a threadsafe fifo queue, so those 100 of each will be spread over 800ms
            // MW0LGE [2.9.0.7] changed volts to 150
            //G8NJJ need similar code for Saturn here, but rates from Ssaturn will be different
            while (chkPower.Checked && (current_hpsdr_model == HPSDRModel.ANAN7000D || current_hpsdr_model == HPSDRModel.ANAN8000D ||
                                        current_hpsdr_model == HPSDRModel.ANAN_G2 || current_hpsdr_model == HPSDRModel.ANAN_G2_1K))         //G8NJJ
            {
                int adc0 = NetworkIO.getUserADC0();
                int adc1 = NetworkIO.getUserADC1();
                _voltsQueue.Enqueue(adc0);
                _ampsQueue.Enqueue(adc1);

                bool bOk;
                int nTries = 0;
                while (_voltsQueue.Count > 150 && nTries < 100) // keep max 150 in the queue
                {
                    bOk = _voltsQueue.TryDequeue(out int tmp);
                    if (!bOk)
                    {
                        await Task.Delay(1);
                        nTries++;
                    }
                }

                nTries = 0;
                while (_ampsQueue.Count > 100 && nTries < 100) // keep max 100 in the queue
                {
                    bOk = _ampsQueue.TryDequeue(out int tmp);
                    if (!bOk)
                    {
                        await Task.Delay(1);
                        nTries++;
                    }
                }

                await Task.Delay(8);

                // [2.10.1.0]MW0LGE log data to VALog.txt
                if (_logVA)
                {
                    DateTime now = DateTime.Now;
                    if (now.Subtract(_lastSaveTime).TotalSeconds >= 1)
                    {
                        try
                        {
                            using (StreamWriter writer = File.AppendText(sVALog))
                            {
                                writer.WriteLine($"{now:yyyy-MM-dd HH:mm:ss}\tadc0(v)={adc0}\tadc1(a)={adc1}\tvolts={convertToVolts(adc0).ToString("f2")}\tamps={convertToAmps(adc1).ToString("f2")}");
                            }
                        }
                        catch
                        {

                        }
                        finally
                        {
                            _lastSaveTime = DateTime.Now;
                        }

                        if (now.Subtract(_firstSaveTime).TotalMinutes >= 60)
                        {
                            // we left it on, turn it off
                            if (!IsSetupFormNull) SetupForm.LogVA = false;
                        }
                    }
                }
                //
            }
            _MKIIPAVolts = 0f;
            _MKIIPAAmps = 0;

            //there is no clear for ConcurrentQueues, we need to dequeue to clear
            int tries;
            tries = _voltsQueue.Count;
            while (_voltsQueue.Count > 0 && tries > 0)
            {
                _voltsQueue.TryDequeue(out int tmp);
                tries--;
            }
            tries = _ampsQueue.Count;
            while (_ampsQueue.Count > 0 && tries > 0)
            {
                _ampsQueue.TryDequeue(out int tmp);
                tries--;
            }
        }
        private DateTime _lastSaveTime = DateTime.MinValue;
        private DateTime _firstSaveTime = DateTime.MinValue;
        private bool _logVA = false;
        public bool LogVA
        {
            get { return _logVA; }
            set
            {
                try
                {
                    if (value)
                    {
                        string sVALog = Path.Combine(AppDataPath, "VALog.txt");

                        using (StreamWriter writer = File.AppendText(sVALog))
                        {
                            writer.WriteLine(ProductVersion + "\n" + BasicTitleBar);
                            writer.WriteLine($"Volts/Amps Log \t_amp_voff={_amp_voff}\t_amp_sens={_amp_sens}");
                        }
                        _firstSaveTime = DateTime.Now;
                    }

                    _logVA = value;
                }
                catch
                {

                }
            }
        }
        private void computeMKIIPAVoltsAmps()
        {
            float voltAverage = _voltsQueue.Count > 0 ? (float)_voltsQueue.Average() : 0;
            float ampAverage = _ampsQueue.Count > 0 ? (float)_ampsQueue.Average() : 0;

            //volts
            _MKIIPAVolts = convertToVolts(voltAverage);

            //amps
            _MKIIPAAmps = convertToAmps(ampAverage);
        }
        private float convertToVolts(float IOreading)
        {
            float volt_div = (22.0f + 1.0f) / 1.1f; // Voltage divider (R1 + R2) / R2
            float volts = (IOreading / 4095.0f) * 5.0f;
            volts = volts * volt_div;
            return volts;
        }
        private float _amp_voff = 360.0f;
        private float _amp_sens = 120.0f;
        public float AmpVoff
        {
            get { return _amp_voff; }
            set {
                float tmp = value;
                if (tmp < 0) tmp = 0.0f;

                _amp_voff = tmp;
            }
        }
        public float AmpSens
        {
            get { return _amp_sens; }
            set
            {
                float tmp = value;
                if (tmp < 0.001f) tmp = 0.001f;

                _amp_sens = tmp;
            }
        }
        private float convertToAmps(float IOreading)
        {
            //float voff = 360.0f, sens = 120.0f;
            //if (current_hpsdr_model == HPSDRModel.ANAN7000D)
            //{
            //    voff = 340.0f;
            //    sens = 88.0f;
            //}
            float voff = _amp_voff;
            float sens = _amp_sens;
            float fwdvolts = (IOreading * 5000.0f) / 4095.0f;
            if (fwdvolts < 0) fwdvolts = 0.0f;
            float amps = ((fwdvolts - voff) / sens);
            //  float amps = (0.01f * adc - 2.91f);
            if (amps < 0) amps = 0.0f;
            return amps;
        }

        public float computeRefPower()
        {
            float adc = 0;
            const float alpha = 0.90f;

            float bridge_volt = 0;
            float refvoltage = 0;
            int adc_cal_offset = 0;

            switch (current_hpsdr_model)
            {
                case HPSDRModel.ANAN100:
                case HPSDRModel.ANAN100B:
                    bridge_volt = 0.095f;
                    if (tx_band == Band.B6M)
                        bridge_volt = 0.5f;
                    refvoltage = 3.3f;
                    adc_cal_offset = 3;
                    break;
                case HPSDRModel.ANAN100D:
                    bridge_volt = 0.095f;
                    if (tx_band == Band.B6M)
                        bridge_volt = 0.5f;
                    refvoltage = 3.3f;
                    adc_cal_offset = 3;
                    break;
                case HPSDRModel.ANAN200D:
                    bridge_volt = 0.108f;
                    if (tx_band == Band.B6M)
                        bridge_volt = 0.5f;
                    refvoltage = 5.0f;
                    adc_cal_offset = 2;
                    break;
                case HPSDRModel.ANAN7000D:
                case HPSDRModel.ANAN_G2:
                case HPSDRModel.ANAN_G2_1K:                 // will need to be edited for scaling
                    bridge_volt = 0.15f;
                    if (tx_band == Band.B6M)
                        bridge_volt = 0.7f;
                    refvoltage = 5.0f;
                    adc_cal_offset = 28;
                    break;
                case HPSDRModel.ORIONMKII:
                case HPSDRModel.ANAN8000D:
                    bridge_volt = 0.08f;
                    if (tx_band == Band.B6M)
                        bridge_volt = 0.08f;
                    refvoltage = 5.0f;
                    adc_cal_offset = 16;
                    break;
                default:
                    bridge_volt = 0.09f;
                    if (tx_band == Band.B6M)
                        bridge_volt = 0.09f;
                    refvoltage = 3.3f;
                    adc_cal_offset = 3;
                    break;
            }

            adc = NetworkIO.getRevPower();

            if (adc < 0) adc = 0;

            float volts = (float)((adc - adc_cal_offset) / 4095.0 * refvoltage);
            if (volts < 0) volts = 0;
            float watts = (float)(Math.Pow(volts, 2) / bridge_volt);
            if (watts < 0) watts = 0;

            if (MeterManager.RequiresUpdate(1, Reading.REV_VOLT)) _RX1MeterValues[Reading.REV_VOLT] = volts; //MW0LGE_[2.9.0.7]
            if (PAValues)
            {
                average_revadc = alpha * average_revadc + (1.0f - alpha) * adc;
                SetupForm.textRevVoltage.Text = volts.ToString("f2") + " V";
            }

            return watts;
        }

        // private int pwr_avg_i = 0;
        public float computeAlexFwdPower()
        {
            float adc = 0;
            const float alpha = 0.90f;
            float bridge_volt = 0;
            float refvoltage = 0;
            int adc_cal_offset = 0;

            switch (current_hpsdr_model)
            {
                case HPSDRModel.ANAN100:
                case HPSDRModel.ANAN100B:
                    bridge_volt = 0.095f;
                    refvoltage = 3.3f;
                    adc_cal_offset = 6;
                    break;
                case HPSDRModel.ANAN100D:
                    bridge_volt = 0.095f;
                    refvoltage = 3.3f;
                    adc_cal_offset = 6;
                    break;
                case HPSDRModel.ANAN200D:
                    bridge_volt = 0.108f;
                    refvoltage = 5.0f;
                    adc_cal_offset = 4;
                    break;
                case HPSDRModel.ANAN7000D:
                case HPSDRModel.ANAN_G2:
                case HPSDRModel.ANAN_G2_1K:             // !K will need different scaling
                    bridge_volt = 0.12f;
                    refvoltage = 5.0f;
                    adc_cal_offset = 32;
                    break;
                case HPSDRModel.ORIONMKII:
                case HPSDRModel.ANAN8000D:
                    bridge_volt = 0.08f;
                    refvoltage = 5.0f;
                    adc_cal_offset = 18;
                    break;
                default:
                    bridge_volt = 0.09f;
                    refvoltage = 3.3f;
                    adc_cal_offset = 6;
                    break;
            }

            adc = NetworkIO.getFwdPower();

            if (adc < 0) adc = 0;

            float volts = (float)((adc - adc_cal_offset) / 4095.0f * refvoltage);
            if (volts < 0) volts = 0;
            float watts = (float)(Math.Pow(volts, 2) / bridge_volt);

            if (MeterManager.RequiresUpdate(1, Reading.FWD_VOLT)) _RX1MeterValues[Reading.FWD_VOLT] = volts; //MW0LGE_[2.9.0.7]
            if (PAValues)
            {
                average_fwdadc = alpha * average_fwdadc + (1.0f - alpha) * adc;
                SetupForm.textFwdVoltage.Text = volts.ToString("f2") + " V";
            }
            if (watts < 0) watts = 0;
            return watts;
        }

        public float computeExciterPower()
        {
            int power_int = NetworkIO.getExciterPower();
            double power_f = (double)power_int;
            double result = 0.0;

            if (MeterManager.RequiresUpdate(1, Reading.FWD_ADC)) _RX1MeterValues[Reading.FWD_ADC] = (float)power_int; //MW0LGE_[2.9.0.7]
            if (PAValues)
            {
                SetupForm.textDriveFwdADCValue.Text = power_int.ToString();
            }

            if (power_int <= 2095)
            {
                if (power_int <= 874)
                {
                    if (power_int <= 98)
                    {
                        result = 0.0;
                    }
                    else  // > 98 
                    {
                        result = (power_f - 98.0) * 0.065703;
                    }
                }
                else  // > 874 
                {
                    if (power_int <= 1380)
                    {
                        result = 50.0 + ((power_f - 874.0) * 0.098814);
                    }
                    else  // > 1380 
                    {
                        result = 100.0 + ((power_f - 1380.0) * 0.13986);
                    }
                }
            }
            else  // > 2095 
            {
                if (power_int <= 3038)
                {
                    if (power_int <= 2615)
                    {
                        result = 200.0 + ((power_f - 2095.0) * 0.192308);
                    }
                    else  // > 2615, <3038 
                    {
                        result = 300.0 + ((power_f - 2615.0) * 0.236407);
                    }
                }
                else  // > 3038 
                {
                    result = 400.0 + ((power_f - 3038.0) * 0.243902);
                }
            }

            return (float)result;
        }

        public float computeOrionMkIIExciterPower()
        {
            int power_int = NetworkIO.getExciterPower();
            double power_f = (double)power_int;
            double result = 0.0;

            if (MeterManager.RequiresUpdate(1, Reading.FWD_ADC)) _RX1MeterValues[Reading.FWD_ADC] = (float)power_int; //MW0LGE_[2.9.0.7]
            if (PAValues)
            {
                SetupForm.textDriveFwdADCValue.Text = power_int.ToString();
            }

            if (power_int <= 1340)
            {
                if (power_int <= 580)
                {
                    if (power_int <= 60)
                    {
                        result = 0.0;
                    }
                    else  // > 68 
                    {
                        result = (power_f - 60.0) * 0.097656;
                    }
                }
                else  // > 580
                {
                    if (power_int <= 905)
                    {
                        result = 50.0 + ((power_f - 580.0) * 0.153846);
                    }
                    else  // > 905
                    {
                        result = 100.0 + ((power_f - 905.0) * 0.229885);
                    }
                }
            }
            else  // > 1340
            {
                if (power_int <= 1950)
                {
                    if (power_int <= 1680)
                    {
                        result = 200.0 + ((power_f - 1340.0) * 0.294118);
                    }
                    else  // > 1680, <1950 
                    {
                        result = 300.0 + ((power_f - 1680.0) * 0.370370);
                    }
                }
                else  // > 1950
                {
                    result = 400.0 + ((power_f - 1950.0) * 0.540540);
                }
            }

            return (float)result;
        }

        public float computeOrionExciterPower()
        {
            int power_int = NetworkIO.getExciterPower();
            double power_f = (double)power_int;
            double result = 0.0;

            if (MeterManager.RequiresUpdate(1, Reading.FWD_ADC)) _RX1MeterValues[Reading.FWD_ADC] = (float)power_int; //MW0LGE_[2.9.0.7]
            if (PAValues)
            {
                SetupForm.textDriveFwdADCValue.Text = power_int.ToString();
            }

            if (power_int <= 1340)
            {
                if (power_int <= 580)
                {
                    if (power_int <= 68)
                    {
                        result = 0.0;
                    }
                    else  // > 68 
                    {
                        result = (power_f - 68.0) * 0.097656;
                    }
                }
                else  // > 580
                {
                    if (power_int <= 905)
                    {
                        result = 50.0 + ((power_f - 580.0) * 0.153846);
                    }
                    else  // > 905
                    {
                        result = 100.0 + ((power_f - 905.0) * 0.229885);
                    }
                }
            }
            else  // > 1340
            {
                if (power_int <= 1950)
                {
                    if (power_int <= 1680)
                    {
                        result = 200.0 + ((power_f - 1340.0) * 0.294118);
                    }
                    else  // > 1680, <1950 
                    {
                        result = 300.0 + ((power_f - 1680.0) * 0.370370);
                    }
                }
                else  // > 1950
                {
                    result = 400.0 + ((power_f - 1950.0) * 0.540540);
                }
            }

            return (float)result;
        }

        public float computeANANExciterPower()
        {
            int power_int = NetworkIO.getExciterPower();
            double power_f = (double)power_int;
            double result = 0.0;

            if (power_int <= 2551)
            {
                if (power_int <= 1253)
                {
                    if (power_int <= 68)
                    {
                        result = 0.0;
                    }
                    else  // > 68 
                    {
                        result = (power_f - 68.0) * 0.008439;
                    }
                }

                else  // > 1253
                {
                    if (power_int <= 1856)
                    {
                        result = 10.0 + ((power_f - 1253.0) * 0.024876);
                    }
                    else  // > 1856
                    {
                        result = 25.0 + ((power_f - 1856.0) * 0.035971);
                    }
                }
            }

            else  // > 2551
            {
                if (power_int <= 3628)
                {
                    if (power_int <= 3101)
                    {
                        result = 50.0 + ((power_f - 2551.0) * 0.045454);
                    }
                    else  // > 3101, <3628 
                    {
                        result = 75.0 + ((power_f - 3101.0) * 0.370370);
                    }
                }
                else  // > 3628
                {
                    result = 100.0 + ((power_f - 3628.0) * 0.064935);
                }
            }

            if (MeterManager.RequiresUpdate(1, Reading.FWD_ADC)) _RX1MeterValues[Reading.FWD_ADC] = (float)power_int; //MW0LGE_[2.9.0.7]
            if (PAValues)
            {
                SetupForm.textFwdADCValue.Text = power_int.ToString();
            }

            return (float)result;
        }

        private float sql_data = -200.0f;
        private async void UpdateSQL()
        {
            while (chkPower.Checked)
            {
                if (!_mox)
                {
                    float rx1PreampOffset;
                    if (rx1_step_att_present) rx1PreampOffset = (float)rx1_attenuator_data;
                    else rx1PreampOffset = rx1_preamp_offset[(int)rx1_preamp_mode];

                    float num = WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.SIGNAL_STRENGTH);
                    num = num +
                    rx1_meter_cal_offset +
                    rx1PreampOffset;
                    sql_data = num;
                    picSquelch.Invalidate();
                }

                await Task.Delay(100);
            }
        }

        private float rx2_sql_data = -200.0f;
        private async void UpdateRX2SQL()
        {
            while (chkPower.Checked && rx2_enabled)
            {
                if (!_mox)
                {
                    float rx2PreampOffset;
                    if (rx2_step_att_present) rx2PreampOffset = (float)rx2_attenuator_data;
                    else rx2PreampOffset = rx2_preamp_offset[(int)rx2_preamp_mode];

                    float num = WDSP.CalculateRXMeter(2, 0, WDSP.MeterType.SIGNAL_STRENGTH);
                    num = num +
                    rx2_meter_cal_offset +
                    rx2PreampOffset;
                    rx2_sql_data = num;
                    picRX2Squelch.Invalidate();
                }

                await Task.Delay(100);
            }
        }

        private float noise_gate_data = -200.0f;
        private async void UpdateNoiseGate()
        {
            while (chkPower.Checked)
            {
                if (_mox)
                {
                    float num = -WDSP.CalculateTXMeter(1, WDSP.MeterType.MIC);
                    noise_gate_data = num + 3.0f;
                    picNoiseGate.Invalidate();
                }
                await Task.Delay(100);
            }
        }

        private async void UpdateVOX()
        {
            while (chkPower.Checked)
            {
                switch (rx1_dsp_mode)
                {
                    case DSPMode.LSB:
                    case DSPMode.USB:
                    case DSPMode.DSB:
                    case DSPMode.AM:
                    case DSPMode.SAM:
                    case DSPMode.FM:
                        picVOX.Invalidate();
                        break;
                }
                await Task.Delay(100);
            }
        }
        
        private bool mon_recall = false;
        private static readonly HiPerfTimer vox_timer = new HiPerfTimer();

        private async void PollPTT()
        {
            while (chkPower.Checked)
            {
                int dotdashptt = NetworkIO.nativeGetDotDashPTT();
                DSPMode tx_mode = chkVFOBTX.Checked && chkRX2.Checked ? rx2_dsp_mode : rx1_dsp_mode;

                if (!manual_mox && !disable_ptt && !rx_only && !_tx_inhibit && !QSKEnabled)
                {
                    bool mic_ptt = (dotdashptt & 0x01) != 0; // PTT from radio
                    bool cw_ptt = CWInput.KeyerPTT; // CW serial PTT
                    bool vox_ptt = Audio.VOXActive;
                    bool cat_ptt = (ptt_bit_bang_enabled && serialPTT != null && serialPTT.isPTT()) | // CAT serial PTT
                                   (!ptt_bit_bang_enabled && CWInput.CATPTT) | _cat_ptt;

                    if (!_mox)
                    {                        
                        // we can come in here from a ToT ( StopAllTX() ) //[2.10.3.6]MWLGE fixes #518
                        // however we dont want switch anything back on, unless all of the above have been released
                        if (_stop_all_tx)
                        {
                            if (mic_ptt || cw_ptt || cat_ptt || vox_ptt || _tci_ptt)
                            {
                                await Task.Delay(1);
                                continue; // skip all, and restart the loop
                            }
                            else
                                _stop_all_tx = false;
                        }

                        //Audio.VACBypass = (chkVAC1.Checked && m_allow_micvox_bypass); //[2.10.3.6]MW0LGE originally from PR #87, by W4WMT. We dont want to do this every 1ms
                        if (chkVAC1.Checked && (((mic_ptt || cw_ptt) && _allow_vac_bypass) || (VOXEnable && _allow_micvox_bypass)))
                        {
                            if(!Audio.VACBypass) Audio.VACBypass = true;
                        }
                        else if (chkVAC1.Checked && Audio.VACBypass)
                        {
                            Audio.VACBypass = false;
                        }

                        if (_tci_ptt)
                        {
                            _current_ptt_mode = PTTMode.TCI;
                            chkMOX.Checked = true;
                        }

                        if (cat_ptt)
                        {
                            _current_ptt_mode = PTTMode.CAT;
                            chkMOX.Checked = true;
                        }

                        if ((tx_mode == DSPMode.CWL || tx_mode == DSPMode.CWU) && (cw_ptt || mic_ptt))
                        {
                            _current_ptt_mode = PTTMode.CW;

                            //if (chkVAC1.Checked && allow_vac_bypass) //[2.10.3.6]MW0LGE see above
                            //    Audio.VACBypass = true;

                            chkMOX.Checked = true;
                        }

                        if ((tx_mode == DSPMode.LSB ||
                            tx_mode == DSPMode.USB ||
                            tx_mode == DSPMode.DSB ||
                            tx_mode == DSPMode.AM ||
                            tx_mode == DSPMode.SAM ||
                            tx_mode == DSPMode.DIGU ||
                            tx_mode == DSPMode.DIGL ||
                            tx_mode == DSPMode.FM ||
                            _all_mode_mic_ptt) &&
                            mic_ptt &&
                            _current_ptt_mode != PTTMode.CW)
                        {
                            _current_ptt_mode = PTTMode.MIC;

                            //if (chkVAC1.Checked && allow_vac_bypass) //[2.10.3.6]MW0LGE see above
                            //    Audio.VACBypass = true;

                            chkMOX.Checked = true;
                        }

                        if ((tx_mode == DSPMode.LSB ||
                            tx_mode == DSPMode.USB ||
                            tx_mode == DSPMode.DSB ||
                            tx_mode == DSPMode.AM ||
                            tx_mode == DSPMode.SAM ||
                            tx_mode == DSPMode.DIGU ||
                            tx_mode == DSPMode.DIGL ||
                            tx_mode == DSPMode.FM) &&
                            vox_ptt)
                        {
                            _current_ptt_mode = PTTMode.VOX;
                            chkMOX.Checked = true;
                        }
                    }
                    else // else if(mox)
                    {
                        bool vac_bypass_disable = false;
                        switch (_current_ptt_mode)
                        {
                            case PTTMode.TCI:
                                if (!_tci_ptt)
                                {
                                    chkMOX.Checked = false;
                                }
                                vac_bypass_disable = true;
                                break;
                            case PTTMode.CAT:
                                //if (chkVAC1.Checked && _allow_micvox_bypass)
                                //    Audio.VACBypass = false;
                                if (!cat_ptt)
                                {
                                    chkMOX.Checked = false;
                                }
                                vac_bypass_disable = true;
                                break;
                            case PTTMode.MIC:
                                if (!mic_ptt)
                                {
                                    chkMOX.Checked = false;
                                    vac_bypass_disable = true;
                                    //if (chkVAC1.Checked && Audio.VACBypass)
                                    //    Audio.VACBypass = false;
                                }
                                break;
                            case PTTMode.CW:
                                if (!cw_ptt && !mic_ptt)
                                {
                                    chkMOX.Checked = false;
                                    vac_bypass_disable = true;
                                }
                                break;
                            case PTTMode.VOX:
                                if (!vox_ptt)
                                {
                                    chkMOX.Checked = false;
                                }
                                break;
                        }

                        if (chkVAC1.Checked && vac_bypass_disable)
                        {
                            if (Audio.VACBypass) Audio.VACBypass = false;
                        }
                    }
                }
                await Task.Delay(1);
            }
        }

        private int last_dot = 0;
        private int last_dash = 0;
        private async void PollCW()
        {
            while (chkPower.Checked)
            {
                int dotdashptt = NetworkIO.nativeGetDotDashPTT();
                bool state_dot = (dotdashptt & 0x04) != 0; // dot                  
                if ((dotdashptt & 0x04) != (last_dot & 0x04))
                {
                    FWDot = state_dot;
                    if ((rx1_dsp_mode == DSPMode.CWL || rx1_dsp_mode == DSPMode.CWU) &&
                     current_breakin_mode == BreakIn.Manual)
                        AudioMOXChanged(state_dot);
                }

                bool state_dash = (dotdashptt & 0x02) != 0; // dash                   
                if ((dotdashptt & 0x02) != (last_dash & 0x02))
                {
                    FWDash = state_dash;
                    if ((rx1_dsp_mode == DSPMode.CWL || rx1_dsp_mode == DSPMode.CWU) &&
                     current_breakin_mode == BreakIn.Manual)
                        AudioMOXChanged(state_dash);
                }

                last_dash = last_dot = dotdashptt;
                await Task.Delay(1);
            }
        }

        private void cwAutoModeTick(object o)
        {
            bool bRx2 = (bool)o;

            if (_old_cw_auto_mode != DSPMode.FIRST)
            {
                if (bRx2)
                {
                    if (InvokeRequired)
                        Invoke(new Action(() => { RX2DSPMode = _old_cw_auto_mode; }));
                    else
                        RX2DSPMode = _old_cw_auto_mode;
                }
                else
                {
                    if (InvokeRequired)
                        Invoke(new Action(() => { RX1DSPMode = _old_cw_auto_mode; }));
                    else
                        RX1DSPMode = _old_cw_auto_mode;
                }
            }
        }
        private DSPMode _old_cw_auto_mode = DSPMode.FIRST;
        private bool _return_from_cw_auto_mode_switch = false;
        private int _return_from_cw_auto_mode_switch_ms = 2000;
        private System.Threading.Timer _cwAutoModeTick = null;
        private bool fw_dot = false;
        public bool AutoModeSwitchCWReturn
        {
            get { return _return_from_cw_auto_mode_switch; }
            set { _return_from_cw_auto_mode_switch = value; }
        }
        public int AutoModeSwitchCWReturnMs
        {
            get { return _return_from_cw_auto_mode_switch_ms; }
            set { _return_from_cw_auto_mode_switch_ms = value; }
        }
        public bool FWDot
        {
            get { return fw_dot; }
            set
            {
                //[2.10.1.0] MW0LGE modified to implement #70
                bool bTxOnRx2 = RX2Enabled && VFOBTX;
                DSPMode currentMode = bTxOnRx2 ? RX2DSPMode : RX1DSPMode;
                bool bInCW = currentMode == DSPMode.CWL || currentMode == DSPMode.CWU;

                fw_dot = value;

                if (value && cw_auto_mode_switch)
                {
                    if (!bInCW)
                    {
                        if (_return_from_cw_auto_mode_switch && _old_cw_auto_mode != currentMode)
                            _old_cw_auto_mode = currentMode;

                        switch (currentMode)
                        {
                            case DSPMode.CWL:
                            case DSPMode.CWU:
                                break;
                            case DSPMode.LSB:
                            case DSPMode.DIGL:
                                if (bTxOnRx2)
                                    RX2DSPMode = DSPMode.CWL;
                                else
                                    RX1DSPMode = DSPMode.CWL;
                                break;
                            default:
                                if (bTxOnRx2)
                                    RX2DSPMode = DSPMode.CWU;
                                else
                                    RX1DSPMode = DSPMode.CWU;
                                break;
                        }
                    }

                    // return after some time, start timer
                    if (_return_from_cw_auto_mode_switch)
                    {
                        if (_cwAutoModeTick != null)
                        {
                            _cwAutoModeTick.Change(Timeout.Infinite, Timeout.Infinite);
                            _cwAutoModeTick.Dispose();
                            _cwAutoModeTick = null;
                        }

                        _cwAutoModeTick = new System.Threading.Timer(cwAutoModeTick, bTxOnRx2, _return_from_cw_auto_mode_switch_ms, Timeout.Infinite);
                    }
                    else
                        _old_cw_auto_mode = DSPMode.FIRST;
                }
            }
        }

        private bool fw_dash = false;
        public bool FWDash
        {
            get { return fw_dash; }
            set
            {
                fw_dash = value;

                if (value && cw_auto_mode_switch)
                {
                    switch (rx1_dsp_mode)
                    {
                        case DSPMode.CWL:
                        case DSPMode.CWU:
                            break;
                        case DSPMode.LSB:
                        case DSPMode.DIGL:
                            RX1DSPMode = DSPMode.CWL;
                            break;
                        default:
                            RX1DSPMode = DSPMode.CWU;
                            break;
                    }
                }
            }
        }

        private bool update_preamp_mutex = false;
        private PreampMode preamp;
        private PreampMode rx2_preamp;
        private bool old_satt = false;
        private int old_satt_data = 0;
        private bool old_rx2_satt = false;
        private int old_rx2_satt_data = 0;
        private bool update_preamp = true;
        private bool update_preamp_mode = false;

        private void UpdatePreamps()
        {
            if (current_hpsdr_model == HPSDRModel.HPSDR)
            {
                update_preamp = false;
                update_preamp_mode = false;
                return;
            }

            if (!_mox && m_bAttontx && !initializing)
            {
                if (update_preamp_mode && !update_preamp_mutex)
                {
                    update_preamp_mutex = true;

                    SetupForm.RX1EnableAtt = old_satt;
                    SetupForm.ATTOnRX1 = old_satt_data;
                    RX1PreampMode = preamp;

                    if (current_hpsdr_model == HPSDRModel.ANAN100D ||
                        current_hpsdr_model == HPSDRModel.ANAN200D ||
                        current_hpsdr_model == HPSDRModel.ORIONMKII ||
                        current_hpsdr_model == HPSDRModel.ANAN7000D ||
                        current_hpsdr_model == HPSDRModel.ANAN8000D ||
                        current_hpsdr_model == HPSDRModel.ANAN_G2 ||
                        current_hpsdr_model == HPSDRModel.ANAN_G2_1K)
                    {
                        SetupForm.RX2EnableAtt = old_rx2_satt;
                        SetupForm.ATTOnRX2 = old_rx2_satt_data; //MW0LGE_21d atten
                        RX2PreampMode = rx2_preamp;
                    }
                    update_preamp_mode = false;
                    update_preamp_mutex = false;

                }

                if (update_preamp && !update_preamp_mutex)
                {
                    old_satt = rx1_step_att_present;
                    old_satt_data = SetupForm.ATTOnRX1;
                    preamp = RX1PreampMode;				// save current preamp mode

                    if (current_hpsdr_model == HPSDRModel.ANAN100D ||
                        current_hpsdr_model == HPSDRModel.ANAN200D ||
                        current_hpsdr_model == HPSDRModel.ORIONMKII ||
                        current_hpsdr_model == HPSDRModel.ANAN7000D ||
                        current_hpsdr_model == HPSDRModel.ANAN8000D ||
                        current_hpsdr_model == HPSDRModel.ANAN_G2 ||
                        current_hpsdr_model == HPSDRModel.ANAN_G2_1K)
                    {
                        old_rx2_satt = SetupForm.RX2EnableAtt;
                        old_rx2_satt_data = SetupForm.ATTOnRX2;// MW0LGE_21d atten          rx2_attenuator_data;// RX2AttenuatorData;
                        rx2_preamp = RX2PreampMode;
                    }
                    update_preamp = false;
                }
            }
        }

        //bool audio_amp_mute;
        private async void PollTXInhibit()
        {
            //WIP bool b_andromeda_or_newIOboard = false;
            while (chkPower.Checked)
            {
                //MW0LGE_22b converted to protocol, so we use correctly named userI functions
                if (_useTxInhibit && current_hpsdr_model != HPSDRModel.HPSDR)
                {
                    bool inhibit_input;

                    if (NetworkIO.CurrentRadioProtocol == RadioProtocol.USB)
                    {
                        // protocol 1
                        if (current_hpsdr_model == HPSDRModel.ANAN7000D || current_hpsdr_model == HPSDRModel.ANAN8000D)
                            inhibit_input = !NetworkIO.getUserI02(); // bit[2] of C1 where C0 = 00000000 (C&C)
                        else
                            inhibit_input = !NetworkIO.getUserI01(); // bit[1] of C1 where C0 = 00000000 (C&C)
                    }
                    else
                    {
                        // protocol 2
                        if (current_hpsdr_model == HPSDRModel.ANAN7000D || current_hpsdr_model == HPSDRModel.ANAN8000D ||
                            current_hpsdr_model == HPSDRModel.ANAN_G2 || current_hpsdr_model == HPSDRModel.ANAN_G2_1K)
                            inhibit_input = !NetworkIO.getUserI05_p2(); // bit[1] of byte 59 from the HPSP 1025 packet
                        else
                            inhibit_input = !NetworkIO.getUserI04_p2(); // bit[0] of byte 59 from the HPSP 1025 packet
                    }

                    if (_reverseTxInhibit) inhibit_input = !inhibit_input;

                    if (TXInhibit != inhibit_input) TXInhibitChangedHandlers?.Invoke(TXInhibit, inhibit_input);
                }
                else if (!_useTxInhibit && TXInhibit) // used if previously on, and now swithced off in setup
                    TXInhibitChangedHandlers?.Invoke(TXInhibit, false);

                await Task.Delay(100);
            }
        }

        private UdpClient n1mm_udp_client;
        private async void PollN1MMPacket()
        {
            if (n1mm_udp_client != null) n1mm_udp_client.Close();
            IPEndPoint udp_ep = new IPEndPoint(IPAddress.Any, focus_master_udp_port);
            n1mm_udp_client = new UdpClient(udp_ep);

            while (focus_master_mode == FocusMasterMode.Logger)
            {
                try
                {
                    {
                        byte[] data = n1mm_udp_client.Receive(ref udp_ep);
                        string tmp = Encoding.UTF8.GetString(data);
                        HandleXml(tmp);
                    }
                }
                catch (SocketException e) // handle blocking exception
                {
                    await Task.Delay(500);
                    continue;
                }
                catch // MW0LGE_21d
                {
                }
            }

            if (n1mm_udp_client != null)
            {
                n1mm_udp_client.Close();
                n1mm_udp_client = null;
            }

        }

        private void n1mm_delay_Elapsed(object sender, ElapsedEventArgs e)
        {
            if (selectByClick & !initializing)
            {
                IntPtr curHandle = Win32.GetForegroundWindow();
                if (curHandle != myHandle)
                {
                    n1mm_handle = curHandle;
                    selectByClick = false;
                    SetFocusMaster(false);
                    int slen = Win32.GetWindowTextLengthW(n1mm_handle);
                    StringBuilder wtxt = new StringBuilder(slen + 1);
                    Win32.GetWindowTextW(n1mm_handle, wtxt, 256);
                    SetupForm.FocusMasterTitle = wtxt.ToString();
                }
                else
                {
                    ToggleFocusMasterTimer();
                }
            }

            if (n1mm_handle != IntPtr.Zero && !Win32.IsWindow(n1mm_handle))
            {
                n1mm_handle = IntPtr.Zero;
                SetupForm.FocusMasterMode = FocusMasterMode.None;
                SetupForm.FocusMasterTitle = "";
            }

            if (n1mm_state == 3)
            {
                n1mm_state = 0;
                if (n1mm_handle != IntPtr.Zero)
                    Win32.SetForegroundWindow(n1mm_handle);
            }
        }

        void HandleXml(string str)
        {
            XElement elem = XElement.Parse(str);
            if (elem.Name == "RadioInfo")
            {
                //MW0LGE_21d
                bool bOk = Int32.TryParse(elem.Element("FocusEntry").Value, out int nTmp);
                if (bOk) n1mm_handle = (IntPtr)nTmp;
            }
        }

        private void ToggleFocusMasterTimer()
        {
            if (focus_master_mode != FocusMasterMode.None && n1mm_state != 1 && n1mm_delay != null)
            {
                n1mm_state = 3;
                n1mm_delay.Enabled = false;
                n1mm_delay.Enabled = true;
            }
        }

        private async void PollPAPWR()
        {
            const float alpha = 0.90f;
            float rho = 0;
            float swr = 0;
            int high_swr_count = 0;
            bool swr_pass = false;

            while (chkPower.Checked)
            {
                if (_mox)
                {
                    alex_fwd = computeAlexFwdPower(); //high power
                    alex_rev = computeRefPower();

                    switch (current_hpsdr_model)
                    {
                        case HPSDRModel.ANAN200D:
                            drivepwr = computeOrionExciterPower();
                            break;
                        case HPSDRModel.ORIONMKII:
                        case HPSDRModel.ANAN7000D:
                        case HPSDRModel.ANAN8000D:
                        case HPSDRModel.ANAN_G2:
                        case HPSDRModel.ANAN_G2_1K:
                            drivepwr = computeOrionMkIIExciterPower();
                            break;
                        default:
                            drivepwr = computeExciterPower(); // low power
                            break;
                    }

                    calfwdpower = CalibratedPAPower();
                    average_drivepwr = alpha * average_drivepwr + (1.0f - alpha) * drivepwr;

                    rho = (float)Math.Sqrt(alex_rev / alex_fwd);
                    if (float.IsNaN(rho) || float.IsInfinity(rho))
                        swr = 1.0f;
                    else
                        swr = (1.0f + rho) / (1.0f - rho);

                    if ((alex_fwd <= 2.0f && alex_rev <= 2.0f) || swr < 1.0f) swr = 1.0f;

                    //[2.10.3.6]MW0LGE modifications to use setup config for swr and tune ignore power. Implements #221 (https://github.com/ramdor/Thetis/issues/221)
                    if (alexpresent || apollopresent)
                    {
                        // in following 'if', K2UE recommends not checking open antenna for the 8000 model
                        // if (swrprotection && alex_fwd > 10.0f && (alex_fwd - alex_rev) < 1.0f)
                        //-W2PA Changed to allow 35w - some amplifier tuners need about 30w to reliably start working
                        //if (swrprotection && alex_fwd > 35.0f && (alex_fwd - alex_rev) < 1.0f
                        if (!chkTUN.Checked && (swrprotection && alex_fwd > 10.0f && (alex_fwd - alex_rev) < 1.0f //[2.10.3.6]MW0LGE ignored if tuning, and returned the 10.0f
                            && current_hpsdr_model != HPSDRModel.ANAN8000D)) // open ant condition
                        {
                            swr = 50.0f;
                            NetworkIO.SWRProtect = 0.01f;
                            chkMOX.Checked = false;

                            MessageBox.Show("Please check your antenna connection.",
                            "High SWR condition detected",
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Warning,
                            MessageBoxDefaultButton.Button1,
                            (MessageBoxOptions)0x40000); // MB_TOPMOST

                            goto end;
                        }
                    }
                    else
                    {
                        swr = 1.0f;
                        alex_fwd = 0;
                        alex_rev = 0;
                    }

                    if (chkTUN.Checked && disable_swr_on_tune && (alexpresent || apollopresent))
                    {
                        int tunePowerSliderValue; // need to get the correct slider

                        if (chk2TONE.Checked)
                        {
                            switch (TwoToneDrivePowerOrigin)
                            {
                                case DrivePowerSource.TUNE_SLIDER:
                                    tunePowerSliderValue = ptbTune.Value;
                                    break;
                                case DrivePowerSource.DRIVE_SLIDER:
                                    tunePowerSliderValue = ptbPWR.Value;
                                    break;
                                default:
                                    tunePowerSliderValue = ptbPWR.Value;
                                    break;
                            }
                        }
                        else
                        {
                            switch (TuneDrivePowerOrigin)
                            {
                                case DrivePowerSource.TUNE_SLIDER:
                                    tunePowerSliderValue = ptbTune.Value;
                                    break;
                                case DrivePowerSource.DRIVE_SLIDER:
                                    tunePowerSliderValue = ptbPWR.Value;
                                    break;
                                default:
                                    tunePowerSliderValue = ptbPWR.Value;
                                    break;
                            }
                        }

                        if (alex_fwd >= 1.0f && alex_fwd <= _tunePowerSwrIgnore && tunePowerSliderValue <= 70)
                        {
                            swr_pass = true;
                        }
                        else swr_pass = false;
                    }

                    if (tx_xvtr_index >= 0 || hf_tr_relay)
                        swr_pass = true;

                    float alex_fwd_limit = 5.0f;
                    if (current_hpsdr_model == HPSDRModel.ANAN8000D)        // K2UE idea:  try to determine if Hi-Z or Lo-Z load
                        alex_fwd_limit = 2.0f * (float)ptbPWR.Value;        //    by comparing alex_fwd with power setting

                    if (swr > _swrProtectionLimit && alex_fwd > alex_fwd_limit && swrprotection && !swr_pass)
                    {
                        high_swr_count++;
                        if (high_swr_count >= 4)
                        {
                            high_swr_count = 0;
                            NetworkIO.SWRProtect = (float)(_swrProtectionLimit / (swr + 1.0f));
                            HighSWR = true;
                        }
                    }
                    else
                    {
                        high_swr_count = 0;
                        NetworkIO.SWRProtect = 1.0f;
                        HighSWR = false;
                    }

                end:
                    swr_pass = false;
                    if (float.IsNaN(swr) || float.IsInfinity(swr) || swr < 1.0f)
                        alex_swr = 1.0f;
                    else
                        alex_swr = swr;
                }
                else if (high_swr) HighSWR = false;

                if (_mox)
                    await Task.Delay(1);
                else
                    await Task.Delay(10);
            }

            alex_fwd = 0;
            alex_rev = 0;
            drivepwr = 0;
            calfwdpower = 0;
            alex_swr = 0;
            average_drivepwr = 0;
        }

        private float _swrProtectionLimit = 2.0f;
        public float SwrProtectionLimit
        {
            get { return _swrProtectionLimit; }
            set { _swrProtectionLimit = value; }
        }
        private float _tunePowerSwrIgnore = 35.0f;
        public float TunePowerSwrIgnore
        {
            get { return _tunePowerSwrIgnore; }
            set { _tunePowerSwrIgnore = value; }
        }
        private double SWRScale(double ref_pow)
        {
            if (ref_pow < 19) return 1.0;
            else return Math.Max((ref_pow * -0.01774) + 1.137097, 0.25); // mx+b found using 80% at 19, 25% at 50
        }

        private float _oldMKIIPAVolts = 0f;
        private float _oldMKIIPAAmps = 0f;
        private float _cpu_perc_smoothed = 0;
        private void timer_cpu_volts_meter_Tick(object sender, System.EventArgs e)
        {
            if ((current_hpsdr_model == HPSDRModel.ANAN7000D || current_hpsdr_model == HPSDRModel.ANAN8000D ||
                 current_hpsdr_model == HPSDRModel.ANAN_G2 || current_hpsdr_model == HPSDRModel.ANAN_G2_1K) && ANAN8000DLEDisplayVoltsAmps)
            {
                computeMKIIPAVoltsAmps(); //MW0LGE_21k9c

                if (!toolStripStatusLabel_Volts.Visible) toolStripStatusLabel_Volts.Visible = true;
                if (!toolStripStatusLabel_Amps.Visible) toolStripStatusLabel_Amps.Visible = true;

                //MW0LGE [2.9.0.7] added to prevent edge case flicker due to rounding
                if (Math.Abs(_MKIIPAVolts - _oldMKIIPAVolts) >= 0.1f)
                {
                    toolStripStatusLabel_Volts.Text = String.Format("{0:#0.0}V", _MKIIPAVolts);
                    _oldMKIIPAVolts = _MKIIPAVolts;
                }
                else
                {
                    toolStripStatusLabel_Volts.Text = String.Format("{0:#0.0}V", _oldMKIIPAVolts);
                }

                if (Math.Abs(_MKIIPAAmps - _oldMKIIPAAmps) >= 0.1f)
                {
                    toolStripStatusLabel_Amps.Text = String.Format("{0:#0.0}A", _MKIIPAAmps);
                    _oldMKIIPAAmps = _MKIIPAAmps;
                }
                else
                {
                    toolStripStatusLabel_Amps.Text = String.Format("{0:#0.0}A", _oldMKIIPAAmps);
                }

            }
            else
            {
                if (toolStripStatusLabel_Volts.Visible) toolStripStatusLabel_Volts.Visible = false;
                if (toolStripStatusLabel_Amps.Visible) toolStripStatusLabel_Amps.Visible = false;
            }

            // cpu ussage
            if (_cpu_usage_setup && Environment.ProcessorCount > 0)
            {
                if ((total_cpu_usage != null && m_bShowSystemCPUUsage) || (total_thetis_usage != null && !m_bShowSystemCPUUsage))
                {
                    if (!toolStripDropDownButton_CPU.Visible) toolStripDropDownButton_CPU.Visible = true;

                    float cpuPerc = 0f;
                    if (m_bShowSystemCPUUsage)
                        cpuPerc = total_cpu_usage.NextValue();
                    else
                        cpuPerc = total_thetis_usage.NextValue() / (float)Environment.ProcessorCount;

                    _cpu_perc_smoothed = (_cpu_perc_smoothed * 0.8f) + (cpuPerc * 0.2f);
                    toolStripDropDownButton_CPU.Text = String.Format("{0:##0}%", _cpu_perc_smoothed);
                }
            }
        }

        private void timer_peak_text_Tick(object sender, System.EventArgs e)
        {
            UpdatePeakText();
        }

        private void timer_clock_Tick(object sender, System.EventArgs e)
        {
            DateTime now = DateTime.Now;
            DateTime UTCnow = DateTime.UtcNow;
            toolStripStatusLabel_UTCTime.Text = UTCnow.ToString("HH:mm:ss") + " utc";
            toolStripStatusLabel_LocalTime.Text = now.ToString("HH:mm:ss") + " loc";
            toolStripStatusLabel_Date.Text = now.ToString("ddd d MMM yyyy");//DateTime.Now.ToLongDateString();

            // qso timer
            updateQSOTimerStatusbar();
            updateQSOTimer();
            // end qso timer
        }

        private bool tx_cal = false;
        public bool TXCal
        {
            get { return tx_cal; }
            set { tx_cal = value; }
        }

        #endregion

        #region Event Handlers
        // ======================================================
        // Event Handlers
        // ======================================================

        // Console Events

        private void Console_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
        {
            if (callsignfocus == 1) return; // ke9ns add to focus on waterfall ID text
            if (e.KeyChar == (char)Keys.Enter)
            {
                if (!(txtVFOAFreq.Focused || txtVFOBFreq.Focused || txtVFOABand.Focused))
                    btnHidden.Focus(); // only do this if vfo boxes dont have focus //MW0LGE
                                       // reason being is that txtVFOA/B has enter key detection already
                                       // and doing both causes potential multiple lost focus
            }
        }
        private void Console_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
        {
            if (!Common.ShiftKeyDown) Display.DisplayShiftKeyDown = false;

            if (!Common.ShiftKeyDown) DisplaySpot = true;

            ToggleFocusMasterTimer();
            if (callsignfocus == 1) return; // ke9ns add to focus on waterfall ID text
        }

        // MW0LGE
        // functions to enabled/disable outside spectral mouse wheel tuning
        // implemented to fix issue with keyboard shortcut using mouse wheel code
        // to change vfo
        // NOTE: call enableOutside... before restoreOutside...
        private bool m_bTempOutsideSpectral = false;
        private void enableOutsideSpectral()
        {
            m_bTempOutsideSpectral = m_bWheelTunesOutsideSpectral;
            m_bWheelTunesOutsideSpectral = true;
        }
        private void restoreOutsideSpectral()
        {
            m_bWheelTunesOutsideSpectral = m_bTempOutsideSpectral;
        }
        //--end spectral helpers

        //MW0LGE_21d private static bool m_bControlKeyDown = false; // ke9ns add (used for an extra right click + CTRL function: add bandstacking and hyperlinking) // MW0LGE changed to bool
        public static bool ALTM = false; // ke9ns add
        private void Console_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
        {
            if (Common.ShiftKeyDown) Display.DisplayShiftKeyDown = true;

            if (Common.ShiftKeyDown && (callsignfocus == 0))// ke9ns add (check for CTRL key but not while callsign text box is in focus)
            {
                DisplaySpot = false; // display the spotter instead of the spot
            }

            if (e.Alt == true) // ke9ns add
            {
                switch (e.KeyCode)
                {
                    case Keys.M: // add to memory list
                        ALTM = true;
                        if (memoryForm == null || memoryForm.IsDisposed) memoryForm = new MemoryForm(this);

                        memoryForm.MemoryRecordAdd_Click(memoryForm.MemoryRecordAdd, EventArgs.Empty); // 

                        break;
                }
            } // alt key + M

            ALTM = false;

            if (Common.CtrlKeyDown) // ke9ns add (check for CTRL key press to do a QRZ lookup) 
            {
                if ((SpotControl.SP4_Active == 0) && (SpotControl.SP_Active > 2) && (SpotControl.DX_Index > 0))  // Do below if not in the middle of processing a DX spot, but DX spotting is Active
                {


                    int x = DX_X;
                    int y = DX_Y;
                    //======================================================================================================    

                    int xx = picDisplay.Width;  // size of picdisplay as user scales it to their screen
                    int yy = picDisplay.Height;

                    int xxx = 1000; // actuall unscaled size of map in picdisplay
                    int yyy = 507;

                    Debug.WriteLine(" width " + xx);
                    Debug.WriteLine(" Height " + yy);

                    Point p = picDisplay.PointToClient(Cursor.Position); // mouse cursor when you hit the ctrl key

                    int XX = 0;
                    int YY = 0;

                    float scalex = ((float)xxx / (float)xx);
                    XX = (int)((float)p.X * scalex);

                    float scaley = ((float)yyy / (float)yy);
                    YY = (int)((float)p.Y * scaley);

                    Debug.WriteLine(" unscalledX " + XX);
                    Debug.WriteLine(" unscalledY " + YY);

                    Debug.WriteLine(" cursor " + p);

                    int iii = 500;

                    for (int ii = 0; ii < SpotControl.DX_Index; ii++) // check all red dots on Panadapter
                    {

                        if ((SpotControl.DX_X[ii] > 5) && (SpotControl.DX_Y[ii] > 5) && (XX <= (SpotControl.DX_X[ii] + 5)) && (XX >= (SpotControl.DX_X[ii] - 5))
                            && (YY <= (SpotControl.DX_Y[ii] + 5)) && (YY >= (SpotControl.DX_Y[ii] - 5)))
                        {
                            Debug.WriteLine("Good trace ii " + ii);

                            SpotForm.DX_SELECTED = ii;    // ke9ns add to keep the dx spotter window always highlighted
                            SpotForm.DX_TEXT = SpotForm.textBox1.Text.Substring((SpotForm.DX_SELECTED * SpotForm.LineLength) + 16, 40);  // ke9ns add
                            SpotControl.Map_Last = 2;
                            SpotForm.processTCPMessage();
                            iii = ii;
                            break;
                        }
                        else
                        {
                            Debug.WriteLine("trace X " + SpotControl.DX_X[ii] + " Y " + SpotControl.DX_Y[ii]);
                        }

                    }

                    if (iii != 500) // only go to the DX spot freq if you found it directly up above in the for loop
                    {

                        int freq1 = SpotControl.DX_Freq[iii];

                        Debug.WriteLine("freq ii " + freq1);

                        if ((freq1 < 5000000) || ((freq1 > 6000000) && (freq1 < 8000000))) // check for bands using LSB
                        {
                            if (SpotForm.chkDXMode.Checked == true)
                            {
                                if (SpotControl.DX_Mode[iii] == 0) RX1DSPMode = DSPMode.LSB;
                                else if (SpotControl.DX_Mode[iii] == 1) RX1DSPMode = DSPMode.CWL;
                                else if (SpotControl.DX_Mode[iii] == 2) RX1DSPMode = DSPMode.DIGL;
                                else if (SpotControl.DX_Mode[iii] == 3) RX1DSPMode = DSPMode.DIGL;
                                else if (SpotControl.DX_Mode[iii] == 4) RX1DSPMode = DSPMode.DIGL;
                                else if (SpotControl.DX_Mode[iii] == 5) RX1DSPMode = DSPMode.DIGL;
                                else if (SpotControl.DX_Mode[iii] == 6) RX1DSPMode = DSPMode.DIGL;
                                else if (SpotControl.DX_Mode[iii] == 7) RX1DSPMode = DSPMode.DIGL;
                                else if (SpotControl.DX_Mode[iii] == 8) RX1DSPMode = DSPMode.DIGL;
                                else if (SpotControl.DX_Mode[iii] == 9) RX1DSPMode = DSPMode.DIGL;
                                else if (SpotControl.DX_Mode[iii] == 10) RX1DSPMode = DSPMode.DIGL;
                                else if (SpotControl.DX_Mode[iii] == 11) RX1DSPMode = DSPMode.FM;
                                else if (SpotControl.DX_Mode[iii] == 12) RX1DSPMode = DSPMode.LSB;
                                else if (SpotControl.DX_Mode[iii] == 13) RX1DSPMode = DSPMode.DIGL;
                                else if (SpotControl.DX_Mode[iii] == 14) RX1DSPMode = DSPMode.SAM;
                                else RX1DSPMode = DSPMode.LSB;

                            }
                            else
                            {
                                RX1DSPMode = DSPMode.LSB;
                            }

                        } // LSB
                        else
                        {
                            if (SpotForm.chkDXMode.Checked == true)
                            {

                                if (SpotControl.DX_Mode[iii] == 0) RX1DSPMode = DSPMode.USB;
                                else if (SpotControl.DX_Mode[iii] == 1) RX1DSPMode = DSPMode.CWU;
                                else if (SpotControl.DX_Mode[iii] == 2) RX1DSPMode = DSPMode.DIGU;
                                else if (SpotControl.DX_Mode[iii] == 3) RX1DSPMode = DSPMode.DIGU;
                                else if (SpotControl.DX_Mode[iii] == 4) RX1DSPMode = DSPMode.DIGU;
                                else if (SpotControl.DX_Mode[iii] == 5) RX1DSPMode = DSPMode.DIGU;
                                else if (SpotControl.DX_Mode[iii] == 6) RX1DSPMode = DSPMode.DIGU;
                                else if (SpotControl.DX_Mode[iii] == 7) RX1DSPMode = DSPMode.DIGU;
                                else if (SpotControl.DX_Mode[iii] == 8) RX1DSPMode = DSPMode.DIGU;
                                else if (SpotControl.DX_Mode[iii] == 9) RX1DSPMode = DSPMode.DIGU;
                                else if (SpotControl.DX_Mode[iii] == 10) RX1DSPMode = DSPMode.DIGU;
                                else if (SpotControl.DX_Mode[iii] == 11) RX1DSPMode = DSPMode.FM;
                                else if (SpotControl.DX_Mode[iii] == 12) RX1DSPMode = DSPMode.USB;
                                else if (SpotControl.DX_Mode[iii] == 13) RX1DSPMode = DSPMode.DIGU;
                                else if (SpotControl.DX_Mode[iii] == 14) RX1DSPMode = DSPMode.SAM;
                                else RX1DSPMode = DSPMode.USB;

                            }
                            else
                            {
                                RX1DSPMode = DSPMode.USB;
                            }

                        } // USB
                        VFOAFreq = (double)freq1 / 1000000; // convert to MHZ

                        if (SpotForm.chkDXMode.Checked == true)
                        {

                            if (SpotControl.DX_Mode2[iii] != 0)
                            {

                                VFOBFreq = (double)(freq1 + SpotControl.DX_Mode2[iii]) / 1000000; // convert to MHZ
                                chkVFOSplit.Checked = true; // turn on  split

                                Debug.WriteLine("split here" + (freq1 + SpotControl.DX_Mode2[iii]));

                            }
                            else
                            {
                                chkVFOSplit.Checked = false; // turn off split

                            }


                        } // chkdxmode checked

                        SpotControl.Map_Last = 2; // UPDATE SPOTS ON MAP

                        return;
                    } // if you found a red dot matching your dx spot list



                    //======================================================================================================

                    for (byte ii = 0; ii < DXK; ii++) // check all spot on Panadapter
                    {

                        if ((x >= DXX[ii]) && (x <= (DXX[ii] + (DXW[ii]) * 3 / 4)) && (y >= DXY[ii]) && (y <= (DXY[ii] + DXH[ii])))
                        {

                            var DXtemp = new StringBuilder("https://www.qrz.com/db/");
                            DXtemp.Append(DXS[ii]);

                            try
                            {
                                System.Diagnostics.Process.Start(DXtemp.ToString());
                            }
                            catch
                            {
                                Debug.WriteLine("bad station");
                            }

                            return;

                        } // index
                        else if ((x >= DXX[ii] + (DXW[ii] * 3 / 4)) && (x <= (DXX[ii] + DXW[ii])) && (y >= DXY[ii]) && (y <= (DXY[ii] + DXH[ii]))) // check for rotor Beam heading 
                        {
                            Debug.WriteLine("BEAM HEADING TRANSMIT FROM Display");

                            spotDDUtil_Rotor = "AP1" + SpotControl.DX_Beam[ii].ToString().PadLeft(3, '0') + ";";
                            spotDDUtil_Rotor = ";";
                            spotDDUtil_Rotor = "AM1;";


                        } // check if you clicked on the last half of the call sign


                    } // for loop

                    if (chkRX2.Checked == true)  // check RX2 click
                    {
                        for (byte ii = 0; ii < DXK2; ii++)
                        {

                            if ((x >= DXX[ii + 50]) && (x <= (DXX[ii + 50] + DXW[ii + 50] * 3 / 4)) && (y >= DXY[ii + 50]) && (y <= (DXY[ii + 50] + DXH[ii + 50])))
                            {
                                var DXtemp = new StringBuilder("https://www.qrz.com/db/");
                                DXtemp.Append(DXS[ii + 50]);

                                try
                                {
                                    System.Diagnostics.Process.Start(DXtemp.ToString());
                                }
                                catch
                                {
                                    Debug.WriteLine("bad station");
                                }

                                break;

                            } // index
                            else if ((x <= (DXX[ii + 50] + DXW[ii + 50] * 3 / 4)) && (y >= DXY[ii + 50]) && (y <= (DXY[ii + 50] + DXH[ii + 50])))
                            {
                                Debug.WriteLine("BEAM HEADING TRANSMIT FROM Display RX2");

                                spotDDUtil_Rotor = "AP1" + SpotControl.DX_Beam[ii].ToString().PadLeft(3, '0') + ";";
                                spotDDUtil_Rotor = ";";
                                spotDDUtil_Rotor = "AM1;";


                            } // check if you clicked on the last half of the call sign


                        } // for loop

                    } // rx2 checked on 


                }



                //---------------------------------------------------------------------------------
                //---------------------------------------------------------------------------------
                //---------------------------------------------------------------------------------
                //---------------------------------------------------------------------------------
                //ke9ns memory in Pan

                if ((SpotControl.SP6_Active == 1))
                {
                    int x = DX_X;
                    int y = DX_Y;


                    for (int ii = 0; ii < MMK3; ii++) // check all spot on Panadapter
                    {

                        if ((x >= MMX[ii]) && (x <= (MMX[ii] + MMW[ii])) && (y >= MMY[ii]) && (y <= (MMY[ii] + MMH[ii])))
                        {
                            try
                            {
                                changeComboFMMemory(MMM[ii]);
                            }
                            catch
                            {
                                Debug.WriteLine("bad station");
                            }

                            return;

                        } // index

                    } // for loop

                    //-------------------------------------------------------


                    if (chkRX2.Checked == true)  // check RX2 click
                    {
                        for (int ii = 0; ii < MMK4; ii++)
                        {

                            if ((x >= MMX[ii + 50]) && (x <= (MMX[ii + 50] + DXW[ii + 50])) && (y >= MMY[ii + 50]) && (y <= (MMY[ii + 50] + MMH[ii + 50])))
                            {
                                try
                                {
                                    changeComboFMMemory(MMM[ii]);
                                }
                                catch
                                {
                                    Debug.WriteLine("bad station");
                                }

                                break;

                            } // index


                        } // for loop

                    } // rx2 checked on 


                } // memory ON pAN ACTIVE

                //---------------------------------------------------------------------------------
                //---------------------------------------------------------------------------------
                //---------------------------------------------------------------------------------
                //---------------------------------------------------------------------------------
                //ke9ns SWL lookup on google
                if ((SpotControl.SP1_Active == 1))
                {

                    // Debug.WriteLine("test====");

                    int x = DX_X;
                    int y = DX_Y;

                    for (byte ii = 0; ii < SXK; ii++)
                    {

                        if ((x >= SXX[ii]) && (x <= (SXX[ii] + SXW[ii])) && (y >= SXY[ii]) && (y <= (SXY[ii] + SXH[ii])))
                        {

                            var SXtemp = new StringBuilder("https://www.google.com/#q=");
                            SXtemp.Append(SXS[ii] + " shortwave");

                            try
                            {
                                System.Diagnostics.Process.Start(SXtemp.ToString());
                            }
                            catch
                            {
                                Debug.WriteLine("bad station");
                            }

                            return;

                        } // index

                    } // for loop

                }

            }

            SpotControl.Map_Last = 2; // force map update

            if (callsignfocus == 1) return; // ke9ns add to focus on waterfall ID text



            //==================================================================


            if (e.Control == true && e.Alt == true)
            {
                switch (e.KeyCode)
                {
                    case Keys.D4:
                        break;
                    case Keys.D:
                        break;
                    case Keys.R:
                        break;
                    case Keys.U:
                        break;
                    case Keys.F:
                        break;
                }
            }
            else if (!enable_kb_shortcuts)
            {
                e.Handled = true;
                return;
            }
            else if (e.Control && !e.Alt)		// control key is pressed
            {
                int low;
                int high;

                switch (e.KeyCode)
                {
                    // IK4JPN+ 9/11/2014
                    case Keys.F1: // CWX memory 1
                    case Keys.F2:
                    case Keys.F3:
                    case Keys.F4:
                    case Keys.F5:
                    case Keys.F6:
                    case Keys.F7:
                    case Keys.F8:
                    case Keys.F9: // CWX memory 9
                    case Keys.F10: // CWX memory stop
                        int t_memory_num = 0;
                        if (e.KeyCode == Keys.F1) t_memory_num = 1;
                        else if (e.KeyCode == Keys.F2) t_memory_num = 2;
                        else if (e.KeyCode == Keys.F3) t_memory_num = 3;
                        else if (e.KeyCode == Keys.F4) t_memory_num = 4;
                        else if (e.KeyCode == Keys.F5) t_memory_num = 5;
                        else if (e.KeyCode == Keys.F6) t_memory_num = 6;
                        else if (e.KeyCode == Keys.F7) t_memory_num = 7;
                        else if (e.KeyCode == Keys.F8) t_memory_num = 8;
                        else if (e.KeyCode == Keys.F9) t_memory_num = 9;

                        if (t_memory_num == 0) CWXForm.CWXStop(); // stop memory
                        else CWXForm.StartQueue = t_memory_num; // tx memory N

                        e.Handled = true;
                        break;
                    // IK4JPN-
                    case Keys.Add:
                        if (ptbRF.Value != ptbRF.Maximum)
                        {
                            RF++;
                        }
                        break;
                    case Keys.Subtract:
                        if (ptbRF.Value != ptbRF.Minimum)
                        {
                            RF--;
                        }
                        break;
                    case Keys.Left:
                        ChangeTuneStepUp();
                        e.Handled = true;
                        break;
                    case Keys.Right:
                        ChangeTuneStepDown();
                        e.Handled = true;
                        break;
                    case Keys.Up:
                        enableOutsideSpectral();
                        Console_MouseWheel(this, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 120));
                        restoreOutsideSpectral();
                        e.Handled = true;
                        break;
                    case Keys.Down:
                        enableOutsideSpectral();
                        Console_MouseWheel(this, new MouseEventArgs(MouseButtons.None, 0, 0, 0, -120));
                        restoreOutsideSpectral();
                        e.Handled = true;
                        break;
                    case Keys.A:
                        if (RX1AGCMode == AGCMode.FAST)
                            RX1AGCMode = AGCMode.FIXD;
                        else RX1AGCMode++;
                        break;
                    case Keys.B:
                        chkNR.Checked = !chkNR.Checked;
                        break;
                    case Keys.C:
                        btnMemoryQuickSave_Click(this, EventArgs.Empty);
                        break;
                    case Keys.D:
                        switch (Display.CurrentDisplayMode)
                        {
                            case DisplayMode.PANADAPTER:
                                comboDisplayMode.Text = "Spectrum";
                                break;
                            case DisplayMode.SPECTRUM:
                                comboDisplayMode.Text = "Panadapter";
                                break;
                            default:
                                comboDisplayMode.Text = "Panadapter";
                                break;
                        }
                        break;
                    case Keys.E:
                        if (ptbRF.Value != ptbRF.Minimum)
                        {
                            RF--;
                        }
                        break;
                    case Keys.F:
                        low = (int)udFilterLow.Value;
                        high = (int)udFilterHigh.Value;

                        SelectRX1VarFilter(false); //MW0LGE_21k8

                        switch (rx1_dsp_mode)
                        {
                            case DSPMode.AM:
                            case DSPMode.SAM:
                            case DSPMode.DSB:
                            case DSPMode.FM:
                            case DSPMode.CWU:
                            case DSPMode.CWL:
                                UpdateRX1Filters(low + 10, high - 10);
                                break;
                            case DSPMode.USB:
                            case DSPMode.DIGU:
                                UpdateRX1Filters(low, high - 50);
                                break;
                            case DSPMode.LSB:
                            case DSPMode.DIGL:
                                UpdateRX1Filters(low + 50, high);
                                break;
                        }

                        e.Handled = true;
                        return;
                    case Keys.J:
                        low = (int)udFilterLow.Value;
                        high = (int)udFilterHigh.Value;
                        int increment = 0;

                        SelectRX1VarFilter(false); //MW0LGE_21k8

                        switch (rx1_dsp_mode)
                        {
                            case DSPMode.CWL:
                            case DSPMode.CWU:
                            case DSPMode.DIGL:
                            case DSPMode.DIGU:
                                increment = 10;
                                break;
                            default:
                                increment = 50;
                                break;
                        }
                        UpdateRX1Filters(low - increment, high - increment);
                        e.Handled = true;
                        return;
                    case Keys.L:
                        if (chkVFOLock.Enabled)
                            chkVFOLock.Checked = !chkVFOLock.Checked;
                        break;
                    case Keys.M:
                        if (chkMOX.Enabled)
                            chkMOX.Checked = !_mox;
                        break;
                    case Keys.N:
                        chkANF.Checked = !chkANF.Checked;
                        break;
                    case Keys.P:
                        RX1PreampMode = (PreampMode)(((int)rx1_preamp_mode + 1) % (int)PreampMode.LAST);
                        break;
                    case Keys.R:
                        if (ptbRF.Value != ptbRF.Maximum)
                        {
                            RF++;
                        }
                        break;
                    case Keys.S:
                        if (chkVFOSplit.Enabled)
                            chkVFOSplit.Checked = !chkVFOSplit.Checked;
                        break;
                    case Keys.V:
                        btnMemoryQuickRestore_Click(this, EventArgs.Empty);
                        break;
                    case Keys.W:
                        if (ptbCWSpeed.Value != ptbCWSpeed.Minimum)
                        {
                            ptbCWSpeed.Value--;
                            ptbCWSpeed_Scroll(this, EventArgs.Empty);
                        }
                        break;
                }
            }
            else if (e.Alt && !e.Control) // Alt key is pressed
            {
                int low;
                int high;

                switch (e.KeyCode)
                {
                    case Keys.Up:
                        if (ptbMic.Value != ptbMic.Maximum)
                        {
                            ptbMic.Value++;
                            ptbMic_Scroll(this, EventArgs.Empty);
                        }
                        break;
                    case Keys.Down:
                        if (ptbMic.Value != ptbMic.Minimum)
                        {
                            ptbMic.Value--;
                            ptbMic_Scroll(this, EventArgs.Empty);
                        }
                        break;
                    case Keys.Right:
                        if (ptbVOX.Value != ptbVOX.Maximum)
                        {
                            ptbVOX.Value++;
                            ptbVOX_Scroll(this, EventArgs.Empty);
                        }
                        break;
                    case Keys.Left:
                        if (ptbVOX.Value != ptbVOX.Minimum)
                        {
                            ptbVOX.Value--;
                            ptbVOX_Scroll(this, EventArgs.Empty);
                        }
                        break;
                    case Keys.B:
                        chkNB.Checked = !chkNB.Checked;
                        break;
                    case Keys.D:
                        chkEnableMultiRX.Checked = !chkEnableMultiRX.Checked;
                        break;
                    case Keys.F:
                        low = (int)udFilterLow.Value;
                        high = (int)udFilterHigh.Value;

                        SelectRX1VarFilter(false); //MW0LGE_21k8

                        switch (rx1_dsp_mode)
                        {
                            case DSPMode.AM:
                            case DSPMode.SAM:
                            case DSPMode.DSB:
                            case DSPMode.FM:
                            case DSPMode.CWU:
                            case DSPMode.CWL:
                                UpdateRX1Filters(low - 10, high + 10);
                                break;
                            case DSPMode.USB:
                            case DSPMode.DIGU:
                                UpdateRX1Filters(low, high + 50);
                                break;
                            case DSPMode.LSB:
                            case DSPMode.DIGL:
                                UpdateRX1Filters(low - 50, high);
                                break;
                        }

                        e.Handled = true;
                        return;
                    case Keys.G:
                        btnVFOAtoB_Click(this, EventArgs.Empty);
                        break;
                    case Keys.H:
                        btnVFOBtoA_Click(this, EventArgs.Empty);
                        break;
                    case Keys.I:
                        btnFilterShiftReset_Click(this, EventArgs.Empty);
                        break;
                    case Keys.J:
                        low = (int)udFilterLow.Value;
                        high = (int)udFilterHigh.Value;
                        int increment = 0;

                        SelectRX1VarFilter(false); //MW0LGE_21k8

                        switch (rx1_dsp_mode)
                        {
                            case DSPMode.CWL:
                            case DSPMode.CWU:
                            case DSPMode.DIGL:
                            case DSPMode.DIGU:
                                increment = 10;
                                break;
                            default:
                                increment = 50;
                                break;
                        }
                        UpdateRX1Filters(low + increment, high + increment);
                        e.Handled = true;
                        return;
                    case Keys.N:
                        chkDSPNB2.Checked = !chkDSPNB2.Checked;
                        break;
                    case Keys.P:
                        break;
                    case Keys.Q:
                        if (ptbCWSpeed.Value != ptbCWSpeed.Maximum)
                        {
                            ptbCWSpeed.Value++;
                            ptbCWSpeed_Scroll(this, EventArgs.Empty);
                        }
                        break;
                    case Keys.R:
                        btnRITReset_Click(this, EventArgs.Empty);
                        break;
                    case Keys.T:
                        chkTUN.Checked = !chkTUN.Checked;
                        break;
                    case Keys.V:
                        btnVFOSwap_Click(this, EventArgs.Empty);
                        break;
                    case Keys.Y:
                        btnXITReset_Click(this, EventArgs.Empty);
                        break;
                    case Keys.Z:
                        if (btnZeroBeat.Enabled)
                            btnZeroBeat_Click(this, EventArgs.Empty);
                        break;
                }
            }
            else if (!e.Alt && !e.Control)
            {
                if (this.ActiveControl is TextBoxTS || this.ActiveControl is NumericUpDownTS)
                {
                    if (e.KeyCode == Keys.Space)
                    {
                        btnHidden.Focus();
                        e.SuppressKeyPress = true;
                    }
                    else
                        return;
                }

                switch (e.KeyCode)
                {
                    case Keys.Space:
                        {
                            if (chkPower.Checked)
                            {
                                if (spacebar_ptt)
                                {
                                    _current_ptt_mode = PTTMode.SPACE;
                                    chkMOX.Checked = !chkMOX.Checked;
                                    if (chkMOX.Checked)
                                    {
                                        if (chkVAC1.Checked && allow_space_bypass)
                                            Audio.VACBypass = true;
                                    }
                                    else
                                    {
                                        if (chkVAC1.Checked && Audio.VACBypass)
                                            Audio.VACBypass = false;
                                    }

                                    e.Handled = true;
                                }
                                else if (spacebar_vox)
                                {
                                    chkVOX.Checked = !chkVOX.Checked;
                                    e.Handled = true;
                                }
                                else if (spacebar_mic_mute)
                                {
                                    chkMicMute.Checked = !chkMicMute.Checked;
                                    e.Handled = true;
                                }
                                else if (_spacebar_vfobtx)
                                {
                                    //[2.10.1.0]MW0LGE ideas from WD5Y
                                    // flip TX vfos, they can be either or, so setting one, unsets the other
                                    if (VFOATX)
                                        VFOBTX = true;
                                    else
                                        VFOATX = true;

                                    e.Handled = true;
                                }
                                else if (spacebar_last_btn)
                                {
                                    break;
                                }
                            }
                            else
                            {
                                if (spacebar_last_btn)
                                {
                                    break;
                                }
                                else e.Handled = true;
                            }
                        }
                        break;
                    case Keys.Multiply:
                        chkMUT.Checked = !chkMUT.Checked;
                        break;
                    case Keys.Add:
                        if (ptbAF.Value != ptbAF.Maximum)
                        {
                            ptbAF.Value++;
                            ptbAF_Scroll(this, EventArgs.Empty);
                        }
                        break;
                    case Keys.Subtract:
                        if (ptbAF.Value != ptbAF.Minimum)
                        {
                            ptbAF.Value--;
                            ptbAF_Scroll(this, EventArgs.Empty);
                        }
                        break;
                        //MW0LGE_218k moved K/L to cltr/alt J so not to conflict with anything user defined as L/K
                }

                if (e.KeyCode == key_tune_up_1)
                {
                    double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                    freq += 1.0;
                    VFOAFreq = freq;
                }
                else if (e.KeyCode == key_tune_down_1)
                {
                    double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                    freq -= 1.0;
                    VFOAFreq = freq;
                }
                else if (e.KeyCode == key_tune_up_2)
                {
                    double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                    freq += 0.1;
                    VFOAFreq = freq;
                }
                else if (e.KeyCode == key_tune_down_2)
                {
                    double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                    freq -= 0.1;
                    VFOAFreq = freq;
                }
                else if (e.KeyCode == key_tune_up_3)
                {
                    double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                    freq += 0.01;
                    VFOAFreq = freq;
                }
                else if (e.KeyCode == key_tune_down_3)
                {
                    double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                    freq -= 0.01;
                    VFOAFreq = freq;
                }
                else if (e.KeyCode == key_tune_up_4)
                {
                    double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                    freq += 0.001;
                    VFOAFreq = freq;
                }
                else if (e.KeyCode == key_tune_down_4)
                {
                    double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                    freq -= 0.001;
                    VFOAFreq = freq;
                }
                else if (e.KeyCode == key_tune_up_5)
                {
                    double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                    freq += 0.0001;
                    VFOAFreq = freq;
                }
                else if (e.KeyCode == key_tune_down_5)
                {
                    double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                    freq -= 0.0001;
                    VFOAFreq = freq;
                }
                else if (e.KeyCode == key_tune_up_6)
                {
                    double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                    freq += 0.00001;
                    VFOAFreq = freq;
                }
                else if (e.KeyCode == key_tune_down_6)
                {
                    double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                    freq -= 0.00001;
                    VFOAFreq = freq;
                }
                else if (e.KeyCode == key_tune_up_7)
                {
                    double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                    freq += 0.000001;
                    VFOAFreq = freq;
                }
                else if (e.KeyCode == key_tune_down_7)
                {
                    double freq = VFOAFreq;// Double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                    freq -= 0.000001;
                    VFOAFreq = freq;
                }
                else if (e.KeyCode == key_rit_up)
                {
                    udRIT.Value += udRIT.Increment;
                }
                else if (e.KeyCode == key_rit_down)
                {
                    udRIT.Value -= udRIT.Increment;
                }
                else if (e.KeyCode == key_xit_up)
                {
                    udXIT.Value += udXIT.Increment;
                }
                else if (e.KeyCode == key_xit_down)
                {
                    udXIT.Value -= udXIT.Increment;
                }
                else if (e.KeyCode == key_filter_up)
                {
                    if (rx1_filter == Filter.NONE)
                        return;
                    if (rx1_filter == Filter.VAR2)
                        RX1Filter = Filter.F1;
                    else
                        RX1Filter++;
                }
                else if (e.KeyCode == key_filter_down)
                {
                    if (rx1_filter == Filter.NONE)
                        return;
                    if (rx1_filter == Filter.F1)
                        RX1Filter = Filter.VAR2;
                    else
                        RX1Filter--;
                }
                else if (e.KeyCode == key_mode_up)
                {
                    switch (rx1_dsp_mode)
                    {
                        case DSPMode.LSB:
                            RX1DSPMode = DSPMode.USB;
                            break;
                        case DSPMode.USB:
                            RX1DSPMode = DSPMode.DSB;
                            break;
                        case DSPMode.DSB:
                            RX1DSPMode = DSPMode.CWL;
                            break;
                        case DSPMode.CWL:
                            RX1DSPMode = DSPMode.CWU;
                            break;
                        case DSPMode.CWU:
                            RX1DSPMode = DSPMode.FM;
                            break;
                        case DSPMode.FM:
                            RX1DSPMode = DSPMode.AM;
                            break;
                        case DSPMode.AM:
                            RX1DSPMode = DSPMode.SAM;
                            break;
                        case DSPMode.SAM:
                            RX1DSPMode = DSPMode.DIGL;
                            break;
                        case DSPMode.DIGL:
                            RX1DSPMode = DSPMode.DIGU;
                            break;
                        case DSPMode.DIGU:
                            RX1DSPMode = DSPMode.SPEC;
                            break;
                        case DSPMode.SPEC:
                            RX1DSPMode = DSPMode.DRM;
                            break;
                        case DSPMode.DRM:
                            RX1DSPMode = DSPMode.LSB;
                            break;
                    }
                }
                else if (e.KeyCode == key_mode_down)
                {
                    switch (rx1_dsp_mode)
                    {
                        case DSPMode.LSB:
                            RX1DSPMode = DSPMode.DRM;
                            break;
                        case DSPMode.USB:
                            RX1DSPMode = DSPMode.LSB;
                            break;
                        case DSPMode.DSB:
                            RX1DSPMode = DSPMode.USB;
                            break;
                        case DSPMode.CWL:
                            RX1DSPMode = DSPMode.DSB;
                            break;
                        case DSPMode.CWU:
                            RX1DSPMode = DSPMode.CWL;
                            break;
                        case DSPMode.FM:
                            RX1DSPMode = DSPMode.CWU;
                            break;
                        case DSPMode.AM:
                            RX1DSPMode = DSPMode.FM;
                            break;
                        case DSPMode.SAM:
                            RX1DSPMode = DSPMode.AM;
                            break;
                        case DSPMode.DIGL:
                            RX1DSPMode = DSPMode.SAM;
                            break;
                        case DSPMode.DIGU:
                            RX1DSPMode = DSPMode.DIGL;
                            break;
                        case DSPMode.SPEC:
                            RX1DSPMode = DSPMode.DIGU;
                            break;
                        case DSPMode.DRM:
                            RX1DSPMode = DSPMode.SPEC;
                            break;
                    }
                }
                else if (e.KeyCode == key_band_up && !(VFOLock == CheckState.Checked))
                {
                    BandStackFilter bsf = BandStackManager.GetFilter(RX1Band);
                    if (bsf != null)
                    {
                        int n = bsf.IndexOfCurrent;
                        if (n == -1 || n == bsf.NumberOfEntries - 1)
                        {
                            // last one
                            // next band up
                            Band b = RX1Band;
                            b++;
                            if (b > Band.B6M) b = Band.B160M;

                            RX1Band = b;
                            bsf = BandStackManager.GetFilter(b);
                            if (bsf != null)
                            {
                                // move to first in this new one
                                bsf.IndexOfCurrent = 0;
                                BandStackEntry bse = bsf.Current();
                                if (bse != null)
                                {
                                    setRX1BandFromBandStackEntry(bse);
                                }
                                else
                                {
                                    // none in band?
                                    setRX1BandFromBandStackEntry(bsf.LastVisited.Copy());
                                }
                                BandStack2Form.UpdateSelected();
                            }
                        }
                        else
                        {
                            BandStackEntry bse = bsf.Next();
                            if (bse != null)
                            {
                                setRX1BandFromBandStackEntry(bse);
                            }
                            else
                            {
                                // none in band?
                                setRX1BandFromBandStackEntry(bsf.LastVisited.Copy());
                            }
                            BandStack2Form.UpdateSelected();
                        }
                    }
                    e.Handled = true;
                    return;
                }
                else if (e.KeyCode == key_band_down && VFOLock != CheckState.Checked)
                {
                    BandStackFilter bsf = BandStackManager.GetFilter(RX1Band);
                    if (bsf != null)
                    {
                        int n = bsf.IndexOfCurrent;
                        if (n <= 0) // < work for empty
                        {
                            // drop down a band
                            Band b = RX1Band;
                            b--;
                            if (b < Band.B160M) b = Band.B6M;

                            RX1Band = b;
                            bsf = BandStackManager.GetFilter(b);
                            if (bsf != null)
                            {
                                // move to last in the list
                                bsf.IndexOfCurrent = bsf.NumberOfEntries - 1;
                                BandStackEntry bse = bsf.Current();
                                if (bse != null)
                                {
                                    setRX1BandFromBandStackEntry(bse);
                                }
                                else
                                {
                                    // none in band?
                                    setRX1BandFromBandStackEntry(bsf.LastVisited.Copy());
                                }
                                BandStack2Form.UpdateSelected();
                            }
                        }
                        else
                        {
                            BandStackEntry bse = bsf.Previous();
                            if (bse != null)
                            {
                                setRX1BandFromBandStackEntry(bse);
                            }
                            else
                            {
                                // none in band?
                                setRX1BandFromBandStackEntry(bsf.LastVisited.Copy());
                            }
                            BandStack2Form.UpdateSelected();
                        }
                    }
                    e.Handled = true;
                    return;
                }
                else if (e.KeyCode == key_cw_dot)
                {

                }
                else if (e.KeyCode == key_cw_dash)
                {

                }
                else if (e.KeyCode == key_ptt_rx)
                {
                    if (chkPower.Checked)
                    {
                        if (key_ptt_rx != key_ptt_tx)
                        {
                            if (_mox) chkMOX.Checked = false;
                        }
                        else
                        {
                            // toggle if both keys the same
                            chkMOX.Checked = !chkMOX.Checked;
                        }
                        e.Handled = true;
                    }
                    return;
                }
                else if (e.KeyCode == key_ptt_tx)
                {
                    if (chkPower.Checked)
                    {
                        if (key_ptt_rx != key_ptt_tx)
                        {
                            if (!_mox) chkMOX.Checked = true;
                        }
                        else
                        {
                            // toggle if both keys the same
                            chkMOX.Checked = !chkMOX.Checked;
                        }
                        e.Handled = true;
                    }
                    return;
                }
                else if (VFOLock == CheckState.Checked || !quick_qsy)
                {
                    return;
                }
                else if ((int)e.KeyCode >= 48 && (int)e.KeyCode <= 57)
                {
                    if (small_lsd)
                    {
                        txtVFOAMSD.Visible = false;
                        txtVFOALSD.Visible = false;
                    }
                    txtVFOAFreq.Focus();
                    txtVFOAFreq.Text = ((int)(e.KeyCode - 48)).ToString();
                    txtVFOAFreq.Select(1, 0);
                }
                else if ((int)e.KeyCode >= 96 && (int)e.KeyCode <= 105)
                {
                    if (small_lsd)
                    {
                        txtVFOAMSD.Visible = false;
                        txtVFOALSD.Visible = false;
                    }
                    txtVFOAFreq.Focus();
                    txtVFOAFreq.Text = ((int)e.KeyCode - 96).ToString();
                    txtVFOAFreq.Select(1, 0);
                }
                else if (e.KeyCode.Equals(Keys.Decimal) ||
                    (separator == "." && e.KeyCode.Equals(Keys.OemPeriod)) ||
                    (separator == "," && e.KeyCode.Equals(Keys.Oemcomma)))
                {
                    if (small_lsd)
                    {
                        txtVFOAMSD.Visible = false;
                        txtVFOALSD.Visible = false;
                    }
                    txtVFOAFreq.Focus();
                    txtVFOAFreq.Text = separator;
                    txtVFOAFreq.Select(1, 0);
                }
            }
        }
        private void setupLegacyMeterThreads(int rx)
        {
            if (_useLegacyMeters && chkPower.Checked)
            {
                if (rx == 1 && (multimeter_thread == null || !multimeter_thread.IsAlive))
                {
                    multimeter_thread = new Thread(new ThreadStart(UpdateMultimeter))
                    {
                        Name = "Multimeter Thread",
                        Priority = ThreadPriority.Lowest,
                        IsBackground = true
                    };
                    multimeter_thread.Start();
                }

                if (rx2_enabled)
                {
                    if (rx == 2 && (rx2_meter_thread == null || !rx2_meter_thread.IsAlive))
                    {
                        rx2_meter_thread = new Thread(new ThreadStart(UpdateRX2MeterData))
                        {
                            Name = "RX2 Meter Thread",
                            Priority = ThreadPriority.Lowest,
                            IsBackground = true
                        };
                        rx2_meter_thread.Start();
                    }
                }
            }
        }
        private bool DataFlowing = false;
        private byte[] id_bytes = new byte[1];
        private void chkPower_CheckedChanged(object sender, System.EventArgs e)
        {
            // ignore if dbman shown, prevents external sources from doing this such as midi/cat
            // whilst DB man is in use
            if(DBMan.IsVisible && chkPower.Checked)
            {
                PowerOn = false;
                return;
            }

            if (chkPower.Checked)
            {
                chkPower.BackColor = button_selected_color;
                txtVFOAFreq.ForeColor = vfo_text_light_color;
                txtVFOAMSD.ForeColor = vfo_text_light_color;
                txtVFOALSD.ForeColor = small_vfo_color;

                UpdateDDCs(rx2_enabled);
                UpdateVFOASub();

                if (rx2_enabled)
                {
                    update_rx2_display = false;
                    chkRX2_CheckedChanged(this, EventArgs.Empty);
                }

                fwc_dds_freq = 0.0f;
                rx2_dds_freq = 0.0f;

                txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                comboDisplayMode_SelectedIndexChanged(this, EventArgs.Empty);
                // wjt added 
                if (PTTBitBangEnabled && serialPTT == null) // we are enabled but don't have port object 
                {
                    PTTBitBangEnabled = true; // force creation of serial ptt 
                }

                Audio.CurrentAudioState1 = Audio.AudioState.DTTSP;

                if (vac_enabled) VACEnabled = true;  //Don't trigger StopAudioIVAC if the VACs aren't needed now
                if (vac2_enabled) VAC2Enabled = true;

                Thread.Sleep(100); // wait for hardware to settle before starting audio (possible sample rate change)
                psform.ForcePS();

                if (m_bAttontx)
                {
                    int txatt = getTXstepAttenuatorForBand(tx_band);
                    NetworkIO.SetTxAttenData(txatt); //[2.10.3.6]MW0LGE att_fixes
                    Display.TXAttenuatorOffset = txatt;
                }
                else
                {
                    NetworkIO.SetTxAttenData(0);
                    Display.TXAttenuatorOffset = 0;
                }

                enableAudioAmplfier(); // MW0LGE_22b

                if (!Audio.Start())   // starts JanusAudio running
                {
                    chkPower.Checked = false;
                    return;
                }

                //MW0LGE_21k9 these two moved after the audio start
                //seems to fix issue that was causing multiRX to be silent when starting up and it was switched on
                if (chkEnableMultiRX.Checked) chkEnableMultiRX_CheckedChanged(this, EventArgs.Empty);
                if (chkVFOSplit.Checked) chkVFOSplit_CheckedChanged(this, EventArgs.Empty);

                setupLegacyMeterThreads(1);

                //multimeter2 MW0LGE_[2.9.0.7]
                if (multimeter2_thread_rx1 == null || !multimeter2_thread_rx1.IsAlive)
                {
                    multimeter2_thread_rx1 = new Thread(new ThreadStart(MultiMeter2UpdateRX1))
                    {
                        Name = "Multimeter2 RX1 Thread",
                        Priority = ThreadPriority.Lowest,
                        IsBackground = true
                    };
                    multimeter2_thread_rx1.Start();
                }
                //

                if (rx2_enabled)
                {
                    setupLegacyMeterThreads(2);

                    //multimeter2 MW0LGE_[2.9.0.7]
                    if (multimeter2_thread_rx2 == null || !multimeter2_thread_rx2.IsAlive)
                    {
                        multimeter2_thread_rx2 = new Thread(new ThreadStart(MultiMeter2UpdateRX2))
                        {
                            Name = "Multimeter2 RX2 Thread",
                            Priority = ThreadPriority.Lowest,
                            IsBackground = true
                        };
                        multimeter2_thread_rx2.Start();
                    }
                    //

                    if (rx2_sql_update_thread == null || !rx2_sql_update_thread.IsAlive)
                    {
                        rx2_sql_update_thread = new Thread(new ThreadStart(UpdateRX2SQL))
                        {
                            Name = "Update RX2 SQL",
                            Priority = ThreadPriority.Normal,
                            IsBackground = true
                        };
                        rx2_sql_update_thread.Start();
                    }
                }

                if (sql_update_thread == null || !sql_update_thread.IsAlive)
                {
                    sql_update_thread = new Thread(new ThreadStart(UpdateSQL))
                    {
                        Name = "Update SQL",
                        Priority = ThreadPriority.Normal,
                        IsBackground = true
                    };
                    sql_update_thread.Start();
                }

                if (noise_gate_update_thread == null || !noise_gate_update_thread.IsAlive)
                {
                    noise_gate_update_thread = new Thread(new ThreadStart(UpdateNoiseGate))
                    {
                        Name = "Update NoiseGate",
                        Priority = ThreadPriority.Normal,
                        IsBackground = true
                    };
                    noise_gate_update_thread.Start();
                }

                if (vox_update_thread == null || !vox_update_thread.IsAlive)
                {
                    vox_update_thread = new Thread(new ThreadStart(UpdateVOX))
                    {
                        Name = "Update VOX",
                        Priority = ThreadPriority.Normal,
                        IsBackground = true
                    };
                    vox_update_thread.Start();
                }

                if (poll_ptt_thread == null || !poll_ptt_thread.IsAlive)
                {
                    poll_ptt_thread = new Thread(new ThreadStart(PollPTT))
                    {
                        Name = "Poll PTT Thread",
                        Priority = ThreadPriority.Normal,
                        IsBackground = true
                    };
                    poll_ptt_thread.Start();
                }

                if (poll_cw_thread == null || !poll_cw_thread.IsAlive)
                {
                    poll_cw_thread = new Thread(new ThreadStart(PollCW))
                    {
                        Name = "Poll CW Thread",
                        Priority = ThreadPriority.BelowNormal,
                        IsBackground = true
                    };
                    poll_cw_thread.Start();
                }

                if (poll_pa_pwr_thread == null || !poll_pa_pwr_thread.IsAlive)
                {
                    poll_pa_pwr_thread = new Thread(new ThreadStart(PollPAPWR))
                    {
                        Name = "Poll PA PWR Thread",
                        Priority = ThreadPriority.BelowNormal,
                        IsBackground = true
                    };
                    poll_pa_pwr_thread.Start();
                }

                if (_overload_thread == null || !_overload_thread.IsAlive)
                {
                    _overload_thread = new Thread(new ThreadStart(pollOverloadSyncSeqErr))
                    {
                        Name = "Overload Thread",
                        Priority = ThreadPriority.BelowNormal,
                        IsBackground = true
                    };
                    _overload_thread.Start();
                }

                if (poll_tx_inhibit_thead == null || !poll_tx_inhibit_thead.IsAlive)
                {
                    poll_tx_inhibit_thead = new Thread(new ThreadStart(PollTXInhibit))
                    {
                        Name = "Poll TX Inhibit input Thread",
                        Priority = ThreadPriority.Normal,
                        IsBackground = true
                    };
                    poll_tx_inhibit_thead.Start();
                }

                if ((display_volts_amps_thead == null || !display_volts_amps_thead.IsAlive) && (current_hpsdr_model == HPSDRModel.ANAN7000D || current_hpsdr_model == HPSDRModel.ANAN8000D ||
                    current_hpsdr_model == HPSDRModel.ANAN_G2 || current_hpsdr_model == HPSDRModel.ANAN_G2_1K))
                {
                    display_volts_amps_thead = new Thread(new ThreadStart(readMKIIPAVoltsAmps))
                    {
                        Name = "Update Volts Amps Thread",
                        Priority = ThreadPriority.BelowNormal,// Normal, // MW0LGE_12k9c
                        IsBackground = true
                    };
                    display_volts_amps_thead.Start();
                }

                if (m_frmCWXForm != null && !m_frmCWXForm.IsDisposed)
                    m_frmCWXForm.StopEverything(chkPower.Checked); //[2.10.3]MW0LGE

                if (!rx_only)
                {
                    chkMOX.Enabled = true;
                    chkTUN.Enabled = true;
                    chk2TONE.Enabled = true; //MW0LGE_21a
                }
                chkVFOLock.Enabled = true;
                chkVFOBLock.Enabled = true;
                timer_peak_text.Enabled = true;
                CurrentHPSDRHardware = NetworkIO.BoardID;
                UpdateDDCs(rx2_enabled);
                UpdateAAudioMixerStates();

                WDSP.SetChannelState(WDSP.id(0, 0), 1, 1);
                if (radio.GetDSPRX(0, 1).Active) WDSP.SetChannelState(WDSP.id(0, 1), 1, 1);
                if (radio.GetDSPRX(1, 0).Active) WDSP.SetChannelState(WDSP.id(2, 0), 1, 1);

                DataFlowing = true;
                SetupForm.UpdateGeneraHardware();
                SetMicGain();
                chkQSK_CheckStateChanged(this, EventArgs.Empty);

                if (RX1DSPMode != DSPMode.CWL && RX1DSPMode != DSPMode.CWU)
                    CWFWKeyer = false; // Disallow the FW to key the rig except in CW modes

                if (andromeda_cat_enabled) NetworkIO.ATU_Tune(1); // set default state of J16 pin 10 to high for Andromeda
                else NetworkIO.ATU_Tune(0);
            }
            else
            {
                DataFlowing = false;
                SetupForm.TestIMD = false;

                if (HaveSync) //fix
                {
                    WDSP.SetChannelState(WDSP.id(0, 0), 0, 1);
                    if (radio.GetDSPRX(0, 1).Active) WDSP.SetChannelState(WDSP.id(0, 1), 0, 1);
                    if (radio.GetDSPRX(1, 0).Active) WDSP.SetChannelState(WDSP.id(2, 0), 0, 1);
                }

                UpdateAAudioMixerStates();
                UpdateDDCs(rx2_enabled);

                if (m_frmCWXForm != null && !m_frmCWXForm.IsDisposed)
                    m_frmCWXForm.StopEverything(chkPower.Checked); //[2.10.3]MW0LGE

                chkMOX.Checked = false;
                chkMOX.Enabled = false;
                chkTUN.Checked = false;
                chkTUN.Enabled = false;
                chk2TONE.Checked = false;  // MW0LGE_21a
                chk2TONE.Enabled = false;

                if (serialPTT != null)  // let go of serial port
                {
                    serialPTT.Destroy();
                    serialPTT = null;
                }

                chkVFOLock.Enabled = false;

                chkPower.BackColor = SystemColors.Control;
                txtVFOAFreq.ForeColor = vfo_text_dark_color;
                txtVFOAMSD.ForeColor = vfo_text_dark_color;
                txtVFOALSD.ForeColor = vfo_text_dark_color;
                UpdateVFOASub();

                txtVFOBFreq.ForeColor = vfo_text_dark_color;
                txtVFOBMSD.ForeColor = vfo_text_dark_color;
                txtVFOBLSD.ForeColor = vfo_text_dark_color;
                txtVFOBBand.ForeColor = band_text_dark_color;

                timer_peak_text.Enabled = false;

                NetworkIO.StopAudio();

                if (vac_enabled)
                {
                    ivac.SetIVACrun(0, 0);
                    ivac.StopAudioIVAC(0);
                }

                if (vac2_enabled)
                {
                    ivac.SetIVACrun(1, 0);
                    ivac.StopAudioIVAC(1);
                }

                if (multimeter_thread != null)
                {
                    if (!multimeter_thread.Join(/*500*/Math.Max(meter_delay, meter_dig_delay) + 50)) //MW0LGE change to meter delay
                        multimeter_thread.Abort();
                }
                if (rx2_meter_thread != null)
                {
                    if (!rx2_meter_thread.Join(/*500*/Math.Max(meter_delay, meter_dig_delay) + 50)) //MW0LGE change to meter delay
                        rx2_meter_thread.Abort();
                }
                //MW0LGE_[2.9.0.7]
                if (multimeter2_thread_rx1 != null)
                {
                    if (!multimeter2_thread_rx1.Join(MeterManager.QuickestUpdateInterval(1, MOX)))
                        multimeter2_thread_rx1.Abort();
                }
                if (multimeter2_thread_rx2 != null)
                {
                    if (!multimeter2_thread_rx2.Join(MeterManager.QuickestUpdateInterval(2, MOX)))
                        multimeter2_thread_rx2.Abort();
                }
                //
                if (rx2_sql_update_thread != null)
                {
                    if (!rx2_sql_update_thread.Join(500))
                        rx2_sql_update_thread.Abort();
                }
                if (rx2_sql_update_thread != null)
                {
                    if (!rx2_sql_update_thread.Join(500))
                        rx2_sql_update_thread.Abort();
                }
                if (sql_update_thread != null)
                {
                    if (!sql_update_thread.Join(500))
                        sql_update_thread.Abort();
                }
                if (noise_gate_update_thread != null)
                {
                    if (!noise_gate_update_thread.Join(500))
                        noise_gate_update_thread.Abort();
                }
                if (vox_update_thread != null)
                {
                    if (!vox_update_thread.Join(500))
                        vox_update_thread.Abort();
                }
                if (poll_ptt_thread != null)
                {
                    if (!poll_ptt_thread.Join(500))
                        poll_ptt_thread.Abort();
                }
                if (poll_cw_thread != null)
                {
                    if (!poll_cw_thread.Join(500))
                        poll_cw_thread.Abort();
                }
                if (poll_pa_pwr_thread != null)
                {
                    if (!poll_pa_pwr_thread.Join(500))
                        poll_pa_pwr_thread.Abort();
                }
                if(_overload_thread != null)
                {
                    if (!_overload_thread.Join(500))
                        _overload_thread.Abort();
                }
                if (poll_tx_inhibit_thead != null)
                {
                    if (!poll_tx_inhibit_thead.Join(500))
                        poll_tx_inhibit_thead.Abort();
                }
                if (display_volts_amps_thead != null)
                {
                    if (!display_volts_amps_thead.Join(650)) // there is a sleep 600 in there MW0LGE
                        display_volts_amps_thead.Abort();
                }
                if (ATUTunetokenSource != null &&
                    ATUTunetokenSource.IsCancellationRequested == false)
                {
                    ATUTunetokenSource.Cancel();
                }

            }

            panelVFOAHover.Invalidate();
            panelVFOBHover.Invalidate();

            //MW0LGE_21d6
            //only here will we have a valid on or valid off
            if (m_bOldPower != chkPower.Checked)
            {
                PowerChangeHanders?.Invoke(m_bOldPower, chkPower.Checked);
                m_bOldPower = chkPower.Checked;
            }
        }
        private bool m_bOldPower = false; // used to store the difference in power state from old to new

        //MW0LGE [2.9.0.8] re-implemented by Warren
        unsafe public void UpdateAAudioMixerStates()
        {
            int RX1 = 1 << WDSP.id(0, 0);
            int RX1S = 1 << WDSP.id(0, 1);
            int RX2 = 1 << WDSP.id(2, 0);
            int MON = 1 << WDSP.id(1, 0);
            int RX2EN;
            if (rx2_enabled)
                RX2EN = 1 << WDSP.id(2, 0);
            else
                RX2EN = 0;
            switch (NetworkIO.CurrentRadioProtocol)
            {
                case RadioProtocol.USB:
                    switch (current_hpsdr_model)
                    {
                        // 2-DDC Models
                        case HPSDRModel.ANAN10E:
                        case HPSDRModel.ANAN100B:
                            cmaster.SetAAudioMixStates((void*)0, 0, RX1 + RX1S + RX2 + MON, RX1 + RX1S + RX2 + MON);
                            cmaster.SetAntiVOXSourceStates(0, RX1 + RX1S + RX2, RX1 + RX1S + RX2);
                            break;
                        // 4 & 5 DDC Models
                        case HPSDRModel.HERMES:
                        case HPSDRModel.ANAN10:
                        case HPSDRModel.ANAN100:
                        case HPSDRModel.ANAN100D:
                        case HPSDRModel.ANAN200D:
                        case HPSDRModel.ORIONMKII:
                        case HPSDRModel.ANAN7000D:
                        case HPSDRModel.ANAN8000D:
                            cmaster.SetAAudioMixStates((void*)0, 0, RX1 + RX1S + RX2 + MON, RX1 + RX1S + RX2 + MON);
                            cmaster.SetAntiVOXSourceStates(0, RX1 + RX1S + RX2, RX1 + RX1S + RX2);
                            break;
                    }
                    break;
                case RadioProtocol.ETH:
                    switch (current_hpsdr_model)
                    {
                        // 2-DDC Models
                        case HPSDRModel.HERMES:
                        case HPSDRModel.ANAN10E:
                        case HPSDRModel.ANAN10:
                        case HPSDRModel.ANAN100B:
                        case HPSDRModel.ANAN100:
                            if (chkPower.Checked)
                            {
                                if (!_mox)
                                {
                                    if (!diversity2)
                                    {
                                        if (!psform.PSEnabled)
                                        {
                                            cmaster.SetAAudioMixStates((void*)0, 0, RX1 + RX1S + RX2 + MON, RX1 + RX1S + RX2EN + MON);
                                            cmaster.SetAntiVOXSourceStates(0, RX1 + RX1S + RX2, RX1 + RX1S + RX2EN);
                                        }
                                        else
                                        {
                                            cmaster.SetAAudioMixStates((void*)0, 0, RX1 + RX1S + RX2 + MON, RX1 + RX1S + RX2EN + MON);
                                            cmaster.SetAntiVOXSourceStates(0, RX1 + RX1S + RX2, RX1 + RX1S + RX2EN);
                                        }
                                    }
                                    else
                                    {
                                        if (!psform.PSEnabled)
                                        {
                                            cmaster.SetAAudioMixStates((void*)0, 0, RX1 + RX1S + RX2 + MON, RX1 + RX1S + MON);
                                            cmaster.SetAntiVOXSourceStates(0, RX1 + RX1S + RX2, RX1 + RX1S);
                                        }
                                        else
                                        {
                                            cmaster.SetAAudioMixStates((void*)0, 0, RX1 + RX1S + RX2 + MON, RX1 + RX1S + MON);
                                            cmaster.SetAntiVOXSourceStates(0, RX1 + RX1S + RX2, RX1 + RX1S);
                                        }
                                    }
                                }
                                else
                                {
                                    if (!diversity2)
                                    {
                                        if (!psform.PSEnabled)
                                        {
                                            cmaster.SetAAudioMixStates((void*)0, 0, RX1 + RX1S + RX2 + MON, RX1 + RX1S + RX2EN + MON);
                                            cmaster.SetAntiVOXSourceStates(0, RX1 + RX1S + RX2, RX1 + RX1S + RX2EN);
                                        }
                                        else
                                        {
                                            cmaster.SetAAudioMixStates((void*)0, 0, RX1 + RX1S + RX2 + MON, MON);
                                            cmaster.SetAntiVOXSourceStates(0, RX1 + RX1S + RX2, 0);
                                        }
                                    }
                                    else
                                    {
                                        if (!psform.PSEnabled)
                                        {
                                            cmaster.SetAAudioMixStates((void*)0, 0, RX1 + RX1S + RX2 + MON, RX1 + RX1S + MON);
                                            cmaster.SetAntiVOXSourceStates(0, RX1 + RX1S + RX2, RX1 + RX1S);
                                        }
                                        else
                                        {
                                            cmaster.SetAAudioMixStates((void*)0, 0, RX1 + RX1S + RX2 + MON, MON);
                                            cmaster.SetAntiVOXSourceStates(0, RX1 + RX1S + RX2, 0);
                                        }
                                    }
                                }
                                cmaster.MONMixState = true;
                            }
                            else
                            {
                                cmaster.MONMixState = false;
                                cmaster.SetAAudioMixStates((void*)0, 0, RX1 + RX1S + RX2 + MON, 0);
                                cmaster.SetAntiVOXSourceStates(0, RX1 + RX1S + RX2, 0);
                            }
                            break;
                        // 4-DDC Models
                        case HPSDRModel.ANAN100D:
                        case HPSDRModel.ANAN200D:
                        case HPSDRModel.ORIONMKII:
                        case HPSDRModel.ANAN7000D:
                        case HPSDRModel.ANAN8000D:
                        case HPSDRModel.ANAN_G2:
                        case HPSDRModel.ANAN_G2_1K:
                            if (chkPower.Checked)
                            {
                                // If POWER is ON, we always have data flow for RX1 and RX1-Sub; we have data flow for
                                // RX2 if 'rx2_enabled'; we always have data flow (MIC samples) for the TX MON.
                                cmaster.MONMixState = true;
                                cmaster.SetAAudioMixStates((void*)0, 0, RX1 + RX1S + RX2 + MON, RX1 + RX1S + RX2EN + MON);
                                cmaster.SetAntiVOXSourceStates(0, RX1 + RX1S + RX2, RX1 + RX1S + RX2EN);
                            }
                            else
                            {
                                // If POWER is OFF, there is no data flow for anything.
                                // It's OK to turn something OFF again if it's already OFF.
                                cmaster.MONMixState = false;
                                cmaster.SetAAudioMixStates((void*)0, 0, RX1 + RX1S + RX2 + MON, 0);
                                cmaster.SetAntiVOXSourceStates(0, RX1 + RX1S + RX2, 0);
                            }
                            break;
                        default:

                            break;
                    }
                    break;
            }
        }
        public void comboDisplayMode_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            _pause_DisplayThread = true;
            DisplayMode old_mode = Display.CurrentDisplayMode;

            switch (comboDisplayMode.Text)
            {
                case "Spectrum":
                    Display.CurrentDisplayMode = DisplayMode.SPECTRUM;
                    SpecDisplay = false;
                    UpdateRXDisplayVars((int)udFilterLow.Value, (int)udFilterHigh.Value);
                    UpdateTXDisplayVars((int)udTXFilterLow.Value, (int)udTXFilterHigh.Value);
                    WDSP.SetRXASpectrum(WDSP.id(0, 0), 1, 0, 0, 0);
                    break;
                case "Panadapter":
                    Display.CurrentDisplayMode = DisplayMode.PANADAPTER;
                    WDSP.SetRXASpectrum(WDSP.id(0, 0), 0, 0, 0, 0);
                    CalcDisplayFreq();
                    CalcRX2DisplayFreq();
                    CalcTXDisplayFreq();
                    SpecDisplay = true;
                    break;
                case "Scope":
                    Display.CurrentDisplayMode = DisplayMode.SCOPE;
                    break;
                case "Scope2":
                    Display.CurrentDisplayMode = DisplayMode.SCOPE2;
                    break;
                case "Phase":
                    Display.CurrentDisplayMode = DisplayMode.PHASE;
                    break;
                case "Phase2":
                    Display.CurrentDisplayMode = DisplayMode.PHASE2;
                    break;
                case "Waterfall":
                    Display.CurrentDisplayMode = DisplayMode.WATERFALL;
                    WDSP.SetRXASpectrum(WDSP.id(0, 0), 0, 0, 0, 0);
                    CalcDisplayFreq();
                    CalcRX2DisplayFreq();
                    CalcTXDisplayFreq();
                    SpecDisplay = true;
                    break;
                case "Histogram":
                    Display.CurrentDisplayMode = DisplayMode.HISTOGRAM;
                    SpecDisplay = false;
                    UpdateRXDisplayVars((int)udFilterLow.Value, (int)udFilterHigh.Value);
                    UpdateTXDisplayVars((int)udTXFilterLow.Value, (int)udTXFilterHigh.Value);
                    WDSP.SetRXASpectrum(WDSP.id(0, 0), 1, 0, 0, 0);
                    break;
                case "Panafall":
                    Display.CurrentDisplayMode = DisplayMode.PANAFALL;
                    WDSP.SetRXASpectrum(WDSP.id(0, 0), 0, 0, 0, 0);
                    CalcDisplayFreq();
                    CalcRX2DisplayFreq();
                    CalcTXDisplayFreq();
                    SpecDisplay = true;
                    break;
                case "Panascope":
                    Display.CurrentDisplayMode = DisplayMode.PANASCOPE;
                    WDSP.SetRXASpectrum(WDSP.id(0, 0), 0, 0, 0, 0);
                    CalcDisplayFreq();
                    CalcRX2DisplayFreq();
                    CalcTXDisplayFreq();
                    SpecDisplay = true;
                    UpdateTXSpectrumDisplayVars();
                    break;
                case "Spectrascope":
                    Display.CurrentDisplayMode = DisplayMode.SPECTRASCOPE;
                    SpecDisplay = false;
                    UpdateRXDisplayVars((int)udFilterLow.Value, (int)udFilterHigh.Value);
                    UpdateTXDisplayVars((int)udTXFilterLow.Value, (int)udTXFilterHigh.Value);
                    WDSP.SetRXASpectrum(WDSP.id(0, 0), 1, 0, 0, 0);
                    break;
                case "Off":
                    Display.CurrentDisplayMode = DisplayMode.OFF;
                    break;
            }

            switch (old_mode)
            {
                case DisplayMode.PANADAPTER:
                case DisplayMode.WATERFALL:
                case DisplayMode.PANAFALL:
                case DisplayMode.PANASCOPE:
                    switch (Display.CurrentDisplayMode)
                    {
                        case DisplayMode.PANADAPTER:
                        case DisplayMode.WATERFALL:
                        case DisplayMode.PANAFALL:
                        case DisplayMode.PANASCOPE:
                            break;
                        default:
                            RX1Filter = rx1_filter; // reset filter display limits
                            TXFilterLow = TXFilterLow;
                            break;
                    }
                    break;
            }

            switch (Display.CurrentDisplayMode)
            {
                case DisplayMode.PHASE:
                case DisplayMode.PHASE2:
                case DisplayMode.SCOPE:
                case DisplayMode.SCOPE2:
                case DisplayMode.OFF:
                    break;
                case DisplayMode.WATERFALL:
                    //MW0LGE
                    Display.ResetWaterfallTimers();

                    chkDisplayAVG.Enabled = true;
                    if (chkDisplayAVG.Checked)
                        chkDisplayAVG.BackColor = button_selected_color;
                    chkDisplayPeak.Enabled = true;
                    if (chkDisplayPeak.Checked)
                        chkDisplayPeak.BackColor = button_selected_color;
                    radio.GetDSPRX(0, 0).SpectrumPreFilter = true;
                    radio.GetDSPRX(1, 0).SpectrumPreFilter = true;

                    picDisplay.BringToFront();

                    break;
                case DisplayMode.PANADAPTER:
                    chkDisplayAVG.Enabled = true;
                    if (chkDisplayAVG.Checked)
                        chkDisplayAVG.BackColor = button_selected_color;
                    chkDisplayPeak.Enabled = true;
                    if (chkDisplayPeak.Checked)
                        chkDisplayPeak.BackColor = button_selected_color;

                    radio.GetDSPRX(0, 0).SpectrumPreFilter = true;
                    radio.GetDSPRX(1, 0).SpectrumPreFilter = true;

                    picDisplay.BringToFront();

                    break;
                case DisplayMode.SPECTRUM:
                case DisplayMode.HISTOGRAM:
                case DisplayMode.SPECTRASCOPE:
                    chkDisplayAVG.Enabled = true;
                    if (chkDisplayAVG.Checked)
                        chkDisplayAVG.BackColor = button_selected_color;
                    chkDisplayPeak.Enabled = true;
                    if (chkDisplayPeak.Checked)
                        chkDisplayPeak.BackColor = button_selected_color;
                    //  btnZeroBeat.Enabled = chkDisplayAVG.Checked;
                    if (rx1_dsp_mode != DSPMode.SPEC)
                    {
                        radio.GetDSPRX(0, 0).SpectrumPreFilter = false;
                        radio.GetDSPRX(1, 0).SpectrumPreFilter = false;
                    }
                    else
                    {
                        radio.GetDSPRX(0, 0).SpectrumPreFilter = true;
                        radio.GetDSPRX(1, 0).SpectrumPreFilter = true;
                    }
                    RX1Filter = rx1_filter;
                    break;
                case DisplayMode.PANAFALL:
                    //MW0LGE
                    Display.ResetWaterfallTimers();

                    chkDisplayAVG.Enabled = true;
                    if (chkDisplayAVG.Checked)
                        chkDisplayAVG.BackColor = button_selected_color;
                    chkDisplayPeak.Enabled = true;
                    if (chkDisplayPeak.Checked)
                        chkDisplayPeak.BackColor = button_selected_color;

                    radio.GetDSPRX(0, 0).SpectrumPreFilter = true;
                    radio.GetDSPRX(1, 0).SpectrumPreFilter = true;
                    break;
                case DisplayMode.PANASCOPE:
                    chkDisplayAVG.Enabled = true;
                    if (chkDisplayAVG.Checked)
                        chkDisplayAVG.BackColor = button_selected_color;
                    chkDisplayPeak.Enabled = true;
                    if (chkDisplayPeak.Checked)
                        chkDisplayPeak.BackColor = button_selected_color;

                    radio.GetDSPRX(0, 0).SpectrumPreFilter = true;
                    radio.GetDSPRX(1, 0).SpectrumPreFilter = true;
                    break;
                default:
                    chkDisplayAVG.Enabled = true;
                    if (chkDisplayAVG.Checked)
                        chkDisplayAVG.BackColor = button_selected_color;
                    chkDisplayPeak.Enabled = true;
                    if (chkDisplayPeak.Checked)
                        chkDisplayPeak.BackColor = button_selected_color;

                    if (rx1_dsp_mode != DSPMode.SPEC)
                    {
                        radio.GetDSPRX(0, 0).SpectrumPreFilter = false;
                        radio.GetDSPRX(1, 0).SpectrumPreFilter = false;
                    }
                    else
                    {
                        radio.GetDSPRX(0, 0).SpectrumPreFilter = true;
                        radio.GetDSPRX(1, 0).SpectrumPreFilter = true;
                    }
                    break;
            }

            was_panadapter = false;
            was_waterfall = false;
            UpdateRX1DisplayOffsets();
            UpdateRX2DisplayOffsets();

            if (comboDisplayMode.Focused)
                btnHidden.Focus();
            _pause_DisplayThread = false;
        }

        private void chkBIN_CheckedChanged(object sender, System.EventArgs e)
        {
            if (chkBIN.Checked) chkBIN.BackColor = button_selected_color;
            else chkBIN.BackColor = SystemColors.Control;
            radio.GetDSPRX(0, 0).BinOn = chkBIN.Checked;
            radio.GetDSPRX(0, 1).BinOn = chkBIN.Checked;
            BINToolStripMenuItem.Checked = chkBIN.Checked;
        }

        private void comboAGC_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            if (comboAGC.SelectedIndex < 0) return;
            radio.GetDSPRX(0, 0).RXAGCMode = (AGCMode)comboAGC.SelectedIndex;
            radio.GetDSPRX(0, 1).RXAGCMode = (AGCMode)comboAGC.SelectedIndex;
            lblAGCLabel.Text = "AGC: " + comboAGC.Text;

            m_RX1agcMode = (AGCMode)comboAGC.SelectedIndex; // MW0LGE

            // set whether custom controls are active
            switch ((AGCMode)comboAGC.SelectedIndex)
            {
                case AGCMode.LONG:
                    SetupForm.CustomRXAGCEnabled = false;

                    radio.GetDSPRX(0, 0).RXAGCHang = 2000;
                    radio.GetDSPRX(0, 1).RXAGCHang = 2000;
                    radio.GetDSPRX(0, 0).RXAGCDecay = 2000;
                    radio.GetDSPRX(0, 1).RXAGCDecay = 2000;

                    SetupForm.tbDSPAGCHangThreshold.Enabled = true;
                    SetupForm.AGCRX1HangThreshold = SetupForm.tbDSPAGCHangThreshold.Value;
                    toolTip1.SetToolTip(comboAGC, "Automatic Gain Control Mode Setting:\n" +
                        "Long (Attack 2ms, Hang 2000ms, Decay 2000ms)");
                    break;
                case AGCMode.SLOW:
                    SetupForm.CustomRXAGCEnabled = false;

                    radio.GetDSPRX(0, 0).RXAGCHang = 1000;
                    radio.GetDSPRX(0, 1).RXAGCHang = 1000;
                    radio.GetDSPRX(0, 0).RXAGCDecay = 500;
                    radio.GetDSPRX(0, 1).RXAGCDecay = 500;

                    SetupForm.tbDSPAGCHangThreshold.Enabled = true;
                    SetupForm.AGCRX1HangThreshold = SetupForm.tbDSPAGCHangThreshold.Value;
                    toolTip1.SetToolTip(comboAGC, "Automatic Gain Control Mode Setting:\n" +
                        "Slow (Attack 2ms, Hang 1000ms, Decay 500ms)");
                    break;
                case AGCMode.MED:
                    SetupForm.CustomRXAGCEnabled = false;

                    radio.GetDSPRX(0, 0).RXAGCHang = 0;
                    radio.GetDSPRX(0, 1).RXAGCHang = 0;
                    radio.GetDSPRX(0, 0).RXAGCDecay = 250;
                    radio.GetDSPRX(0, 1).RXAGCDecay = 250;

                    WDSP.SetRXAAGCHangThreshold(WDSP.id(0, 0), 100);

                    SetupForm.tbDSPAGCHangThreshold.Enabled = false;
                    toolTip1.SetToolTip(comboAGC, "Automatic Gain Control Mode Setting:\n" +
                        "Medium (Attack 2ms, Hang OFF, Decay 250ms)");
                    break;
                case AGCMode.FAST:
                    SetupForm.CustomRXAGCEnabled = false;

                    radio.GetDSPRX(0, 0).RXAGCHang = 0;
                    radio.GetDSPRX(0, 1).RXAGCHang = 0;
                    radio.GetDSPRX(0, 0).RXAGCDecay = 50;
                    radio.GetDSPRX(0, 1).RXAGCDecay = 50;

                    WDSP.SetRXAAGCHangThreshold(WDSP.id(0, 0), 100);
                    SetupForm.tbDSPAGCHangThreshold.Enabled = false;
                    toolTip1.SetToolTip(comboAGC, "Automatic Gain Control Mode Setting:\n" +
                        "Fast (Attack 2ms, Hang OFF, Decay 50ms)");
                    break;
                case AGCMode.CUSTOM:
                    SetupForm.CustomRXAGCEnabled = true;

                    SetupForm.tbDSPAGCHangThreshold.Enabled = true;
                    SetupForm.AGCRX1HangThreshold = SetupForm.tbDSPAGCHangThreshold.Value;
                    toolTip1.SetToolTip(comboAGC, "Automatic Gain Control Mode Setting:\n" +
                        "Custom - Set specifics in Setup Form -> DSP -> AGC/ALC");
                    break;
                case AGCMode.FIXD:
                    SetupForm.CustomRXAGCEnabled = false;
                    toolTip1.SetToolTip(comboAGC, "Automatic Gain Control Mode Setting:\n" +
                        "Fixed - Set gain with AGC-T control above");
                    break;
            }

            // set RF control to Max or Fixed gain depending on mode
            switch ((AGCMode)comboAGC.SelectedIndex)
            {
                case AGCMode.FIXD:
                    RF = SetupForm.AGCFixedGain;
                    break;
                default:
                    RF = SetupForm.AGCMaxGain;
                    break;
            }

            if (RX1DSPMode != DSPMode.CWL && RX1DSPMode != DSPMode.CWU)
                non_qsk_agc = (AGCMode)comboAGC.SelectedIndex;

            if (comboAGC.Focused)
                btnHidden.Focus();
        }

        private ShutdownForm _frmShutDownForm = null;
        private void Console_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {            
            shutdownLogStringToPath("Inside Console_Closing()");

            shutdownLogStringToPath("Before ThetisBotDiscord.Disconnect()");
            ThetisBotDiscord.Shutdown();

            // MW0LGE
            // show a shutdown window
            _frmShutDownForm = new ShutdownForm();
            _frmShutDownForm.Location = new Point(this.Location.X + this.Size.Width / 2 - _frmShutDownForm.Size.Width / 2, this.Location.Y + this.Size.Height / 2 - _frmShutDownForm.Size.Height / 2);
            _frmShutDownForm.Show();
            Application.DoEvents();

            if (_autoLoadFormTimerFormTimer != null)
            {
                shutdownLogStringToPath("Before _autoLoadFormTimerFormTimer.Stop()");
                _autoLoadFormTimerFormTimer.Stop();
            }

            shutdownLogStringToPath("Before autoLaunchTryToClose()");
            autoLaunchTryToClose();

            if (m_tcpTCIServer != null)
            {
                shutdownLogStringToPath("Before m_tcpTCIServer.StopServer()");
                bool wasRunning = m_tcpTCIServer.IsServerRunning;
                m_tcpTCIServer.StopServer();
                if (wasRunning) removeTCIDelegates();
            }
            if (m_tcpCATServer != null)
            {
                shutdownLogStringToPath("Before m_tcpCATServer.StopServer()");
                bool wasRunning = m_tcpCATServer.IsServerRunning;
                m_tcpCATServer.StopServer();
                if (wasRunning) removeTCPIPcatDelegates();
            }

            shutdownLogStringToPath("Before infoBar.ShutDown()");
            if (infoBar != null)
                infoBar.ShutDown();

            shutdownLogStringToPath("Before serial disable");

            CATEnabled = false;
            //[2.10.3.1]MW0LGE not being done anywhere
            if (Sio2listen != null) Sio2listen.disableCAT2();
            if (Sio3listen != null) Sio3listen.disableCAT3();
            if (Sio4listen != null) Sio4listen.disableCAT4();
            //
            AndromedaCATEnabled = false;
            AriesCATEnabled = false;
            GanymedeCATEnabled = false;

            shutdownLogStringToPath("Before power off");
            if (chkPower.Checked == true)  // If we're quitting without first clicking off the "Power" button            
                chkPower.Checked = false;

            Thread.Sleep(100);

            if (psform != null)
            {
                shutdownLogStringToPath("Before psform.CloseAmpView()");
                psform.CloseAmpView(); //[2.10.4.3]MW0LGE
                shutdownLogStringToPath("Before psform.StopPSThread()");
                psform.StopPSThread();
            }

            shutdownLogStringToPath("Before undoXVTRantennaModify()");
            undoXVTRantennaModify(0);
            undoXVTRantennaModify(1);

            shutdownLogStringToPath("Before SaveState()");
            SaveState();

            shutdownLogStringToPath("Before MemoryList.Save()");
            MemoryList.Save();

            if (!IsSetupFormNull)
            {
                shutdownLogStringToPath("Before SetupForm.CloseUsbBcdDevice()");
                SetupForm.CloseUsbBcdDevice();

                shutdownLogStringToPath("Before SetupForm.SaveNotchesToDatabase()");
                SetupForm.SaveNotchesToDatabase();

                SetupForm.Owner = null;
                SetupForm.Hide();
            }

            shutdownLogStringToPath("Before hides");
            if (_frmReleaseNotes != null) _frmReleaseNotes.Hide();
            if (m_frmCWXForm != null) m_frmCWXForm.Hide();
            if (EQForm != null) EQForm.Hide();
            if (XVTRForm != null) XVTRForm.Hide();
            if (memoryForm != null) memoryForm.Hide();
            if (diversityForm != null) diversityForm.Hide();

            if (psform != null) psform.Hide();
            if (m_frmNotchPopup != null) m_frmNotchPopup.Hide();
            if (m_frmSeqLog != null) m_frmSeqLog.Hide();

            cmaster.Hidewb(0);

            shutdownLogStringToPath("Before Display.ShutdownDX2D()");
            m_bDisplayLoopRunning = false; // will cause the display loop to exit
            if (draw_display_thread != null && draw_display_thread.IsAlive) draw_display_thread.Join(1100); // added 1100, slightly longer than 1fps MW0LGE [2.9.0.7]
            Display.ShutdownDX2D(); // MW0LGE

            shutdownLogStringToPath("Before removeDelegates()");
            //MW0LGE_21a un-register delegates
            removeDelegates();
            if (!IsSetupFormNull) SetupForm.RemoveDelegates(); // MW0LGE_22b
            //

            shutdownLogStringToPath("Before TimeOutTimerManager.Shutdown()");
            TimeOutTimerManager.Shutdown();

            //MW0LGE
            //Change to check if existing save is happening. Without this
            //it is possible to crash on save and corrupt settings file
            if (!IsSetupFormNull)
            {
                shutdownLogStringToPath("Before SetupForm save");

                SetupForm.IgnoreButtonState = true; // prevents threads from updating controls in the blocked thead caused by WaitForSaveLoad
                Debug.Write("waiting existing save/load...");
                SetupForm.WaitForSaveLoad(10000); // MW0LGE [2.9.0.8] wait 10 seconds, should be enough?
                if (SetupForm.StillWaitingForSaveLoad)
                {
                    // save didnt complete
                    MessageBox.Show("Saving to the database did not complete in the alloted time. Your settings will not be saved.",
                    "DB Save TimeOut",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                }
                Debug.Write("done...");
                SetupForm.SaveOptions();
                Debug.WriteLine("Saved!");
                shutdownLogStringToPath("Before MultiMeterIOStopTimers()");
                SetupForm.MultiMeterIOStopTimers();
                shutdownLogStringToPath("Leaving SetupForm save");
            }

            shutdownLogStringToPath("Before MeterManager.Shutdown()"); //[2.10.3.6]MW0LGE moved from after hidewb so that listeners can save as part of setup
            MeterManager.Shutdown();

            shutdownLogStringToPath("Before forms close");
            if (EQForm != null) EQForm.Close();
            if (memoryForm != null) memoryForm.Close();
            if (diversityForm != null) diversityForm.Close();

            if (psform != null) psform.Close();
            if (_frmReleaseNotes != null) _frmReleaseNotes.Close();
            if (m_frmCWXForm != null && !m_frmCWXForm.IsDisposed) m_frmCWXForm.StopEverything(); //[2.10.3.1]MW0LGE

            cmaster.Closewb(0);

            shutdownLogStringToPath("Before DumpCap.StopDumpcap()");
            DumpCap.StopDumpcap();

            shutdownLogStringToPath("Before SpotForm.ForceSave()");
            //cause spot form to save out, because it wont if currently shown, the _closing event does not fire on the form
            if (SpotForm != null && !SpotForm.IsDisposed) SpotForm.ForceSave();

            //MW0LGE_21d -- the db is updated with everything
            //all stored as part of DB.Exit below
            //we are shutting down, but may have moved frquency and not stored that into the current active slot, so do it now
            //so we can use it when we restart
            shutdownLogStringToPath("Before Bandstack Save");
            BandStackFilter bsf = BandStackManager.GetFilter(RX1Band, false);
            if (bsf != null)
            {
                bsf.UpdateCurrentWithLastVisitedData(m_bIgnoreFrequencyDupes);
                bsf.GenerateFilteredList(true);
            }
            //now save it all
            BandStackManager.SaveToDB();
            if (m_frmBandStack2 != null) BandStack2Form.Store();  // using frm variable, as we may reach here without the singlton being instanced, and there is no point doing so
                                                                  // this happens on a DB merge etc.

            shutdownLogStringToPath("Before SetupForm.SaveTXProfileData()");
            if (!IsSetupFormNull && SaveTXProfileOnExit)    // save the tx profile
            {
                SetupForm.SaveTXProfileData();
            }

            shutdownLogStringToPath("Before chkPower + ckQuickRec");
            chkPower.Checked = false;	// make sure power is off		
            ckQuickRec.Checked = false; // make sure recording is stopped

            shutdownLogStringToPath("Before hide()");
            this.Hide();
            //note frm shutdown close is done in dispose now

            shutdownLogStringToPath("Leaving Console_Closing()");
        }
        private long getErrorLogSize()
        {
            string errorLogPath = Path.Combine(AppDataPath, "ErrorLog.txt");
            if (File.Exists(errorLogPath))
            {
                FileInfo fileInfo = new FileInfo(errorLogPath);
                return fileInfo.Length;
            }
            return -1;
        }
        private void shutdownLogStringToPath(string entry)
        {
            if (!m_bLogShutdown || string.IsNullOrEmpty(entry)) return;

            try
            {
                using (StreamWriter w = File.AppendText(AppDataPath + "\\shutdown_log.txt"))
                {
                    //using block will auto close stream
                    w.WriteLine(entry);
                }
            }
            catch { }
        }
        private void removeShutdownLog()
        {
            try
            {
                if (File.Exists(AppDataPath + "\\shutdown_log.txt"))
                    File.Delete(AppDataPath + "\\shutdown_log.txt");
            }
            catch { }
        }
        private void comboPreamp_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            PreampMode mode = PreampMode.FIRST;
            bool exit = false;

            switch (comboPreamp.Text)
            {
                case "-20dB":
                    if (CurrentHPSDRModel == HPSDRModel.HPSDR) //MW0LGE_21d step atten
                    {
                        mode = PreampMode.HPSDR_OFF;
                    }
                    else
                    {
                        mode = PreampMode.SA_MINUS20;
                    }
                    break;

                case "0dB":
                    mode = PreampMode.HPSDR_ON;
                    break;
                case "-10dB":
                    mode = PreampMode.SA_MINUS10;
                    break;
                case "-30dB":
                    mode = PreampMode.SA_MINUS30;
                    break;
                // NOTE: lower case db !!! not a very nice implemention //MW0LGE_22b commented
                case "-10db":
                    mode = PreampMode.HPSDR_MINUS10;
                    break;

                case "-20db":
                    mode = PreampMode.HPSDR_MINUS20;
                    break;

                case "-30db":
                    mode = PreampMode.HPSDR_MINUS30;
                    break;

                case "-40db":
                    mode = PreampMode.HPSDR_MINUS40;
                    break;

                case "-50db":
                    mode = PreampMode.HPSDR_MINUS50;
                    break;

                default:
                    exit = true;
                    break;
            }

            if (comboPreamp.Focused)
                btnHidden.Focus();

            if (exit) return;

            RX1PreampMode = mode;

            if (!_mox)
            {
                update_preamp = true;
                UpdatePreamps();
            }
        }

        private void comboRX2Preamp_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            PreampMode mode = PreampMode.FIRST;
            bool exit = false;

            switch (comboRX2Preamp.Text)
            {
                case "-20dB":
                    if (CurrentHPSDRModel == HPSDRModel.HPSDR) //MW0LGE_21d step atten
                    {
                        mode = PreampMode.HPSDR_OFF;
                    }
                    else
                    {
                        mode = PreampMode.SA_MINUS20;
                    }
                    break;
                case "0dB":
                    mode = PreampMode.HPSDR_ON;
                    break;
                case "-10dB":
                    mode = PreampMode.SA_MINUS10;
                    break;
                case "-30dB":
                    mode = PreampMode.SA_MINUS30;
                    break;
                default:
                    exit = true;
                    break;
            }

            if (comboRX2Preamp.Focused)
                btnHidden.Focus();

            if (exit) return;

            RX2PreampMode = mode;
            if (!_mox)
            {
                update_preamp = true;
                UpdatePreamps();
            }
        }

        private bool m_bRXAFSlidersWillUnmute = false;
        private bool m_bMuteWillMuteVAC1 = false;
        private bool m_bMuteWillMuteVAC2 = false;
        public bool RXAFSlidersWillUnmute
        {
            get
            {
                return m_bRXAFSlidersWillUnmute;
            }
            set
            {
                m_bRXAFSlidersWillUnmute = value;
            }
        }
        public bool MuteWillMuteVAC1
        {
            get { return m_bMuteWillMuteVAC1; }
            set
            {
                m_bMuteWillMuteVAC1 = value;
                ptbRX0Gain_Scroll(this, EventArgs.Empty); //MW0LGE_21k9
            }
        }
        public bool MuteWillMuteVAC2
        {
            get { return m_bMuteWillMuteVAC2; }
            set
            {
                m_bMuteWillMuteVAC2 = value;
                ptbRX2Gain_Scroll(this, EventArgs.Empty); //MW0LGE_21k9
            }
        }
        private void chkMUT_CheckedChanged(object sender, System.EventArgs e)
        {
            bool bOldMute = Audio.MuteRX1;

            if (chkMUT.Checked)
            {
                Audio.MuteRX1 = true;

                if (m_bMuteWillMuteVAC1)
                {
                    radio.GetDSPRX(0, 0).RXOutputGain = 0.0; //MW0LGE_21j
                    radio.GetDSPRX(0, 1).RXOutputGain = 0.0; //MW0LGE_21j
                }

                chkMUT.BackColor = button_selected_color;
                lblRX1MuteVFOA.Text = "MUTE";
                lblRX1MuteVFOA.Show(); //[2.10.1.0] from WD5Y
            }
            else
            {
                Audio.MuteRX1 = false;

                radio.GetDSPRX(0, 0).RXOutputGain = (double)ptbRX0Gain.Value / ptbRX0Gain.Maximum;
                radio.GetDSPRX(0, 1).RXOutputGain = (double)ptbRX1Gain.Value / ptbRX1Gain.Maximum; //MW0LGE_21j do this always

                ptbAF_Scroll(this, EventArgs.Empty);
                chkMUT.BackColor = SystemColors.Control;
                lblRX1MuteVFOA.Text = "";
                lblRX1MuteVFOA.Hide(); //[2.10.1.0] from WD5Y
            }
            if (sliderForm != null) sliderForm.RX1MuteOnOff = chkMUT.Checked;

            if (chkMUT.Focused)
                btnHidden.Focus();

            if (path_Illustrator != null)
                path_Illustrator.pi_Changed();

            if (bOldMute != Audio.MuteRX1)
                MuteChangedHandlers?.Invoke(1, bOldMute, Audio.MuteRX1);
        }

        public bool ModelIsHPSDRorHermes()
        {
            if (current_hpsdr_model == HPSDRModel.HPSDR)
            {
                return true;
            }
            if (current_hpsdr_model == HPSDRModel.HERMES)
            {
                return true;
            }
            return false;
        }
        private void OnDriveSliderUpdateTimerTick(object sender, ElapsedEventArgs e)
        {
            if (_bDelayUpdateDriveLabel) UpdateDriveLabel(false, EventArgs.Empty);
        }
        private void OnTuneSliderUpdateTimerTick(object sender, ElapsedEventArgs e)
        {
            if (_bDelayUpdateTuneLabel) UpdateTuneLabel(false, EventArgs.Empty);
        }
        private bool _bDelayUpdateDriveLabel = false;
        private bool _bDelayUpdateTuneLabel = false;
        public void UpdateDriveLabel(bool bShowLimitValue, System.EventArgs e)
        {
            if (IsSetupFormNull) return;

            bool bUsePower = SetupForm.GetPABandUsesMaxPower(TXBand);

            int drv;
            if (bShowLimitValue)
            {
                PrettyTrackBar.LimitConstraint lc = e as PrettyTrackBar.LimitConstraint;
                drv = lc.LimitValue;
                if (lc.MouseWheel)
                {
                    _bDelayUpdateDriveLabel = true;

                    if (_tmrDriveSliderUpdate == null)
                    {
                        _tmrDriveSliderUpdate = new System.Timers.Timer(500);
                        _tmrDriveSliderUpdate.Elapsed += OnDriveSliderUpdateTimerTick;
                        _tmrDriveSliderUpdate.AutoReset = false;
                        _tmrDriveSliderUpdate.Enabled = true;
                    }
                    else
                    {
                        _tmrDriveSliderUpdate.Stop();
                        _tmrDriveSliderUpdate.Start();
                    }
                }
            }
            else if (ptbPWR.IsConstrained)
                drv = ptbPWR.ConstrainedValue;
            else
                drv = ptbPWR.Value;

            string sValue;
            if (bUsePower)
            {
                int nValue = (int)((drv / (float)(ptbPWR.Maximum - ptbPWR.Minimum)) * SetupForm.GetPABandMaxPower(TXBand));
                sValue = nValue.ToString();
            }
            else
            {
                sValue = drv.ToString();
            }

            if (!bShowLimitValue)
            {
                if (ptbPWR.IsConstrained)
                    lblPWR.Text = "Drive: (" + sValue + " w)";
                else
                    lblPWR.Text = "Drive: " + sValue + " w";
            }
            else
            {
                lblPWR.Text = "Limit: " + sValue + " w";
            }

            //wd5y
            if (SetupForm.chkAmpDRVLim.Checked == true & chkExternalPA.Checked == true)
            {
                int drvlimpwr = (int)(ptbPWR.Value / (float)(ptbPWR.Maximum - ptbPWR.Minimum) * SetupForm.GetPABandMaxPower(TXBand));
                int tunlimpwr = (int)(ptbTune.Value / (float)(ptbTune.Maximum - ptbTune.Minimum) * SetupForm.GetPABandMaxPower(TXBand));

                if (SetupForm.numUpDnDRVLim.Value < drvlimpwr & SetupForm.numUpDnTUNLim.Value < tunlimpwr)
                {
                    RXOnly = true;
                    chkExternalPA.Checked = false;
                    ptbPWR.Value = 0;
                    lblPWR.Text = "Drive: " + 0 + "w";
                    lblPWR2.Text = "Drive:" + 0 + "w";
                    ptbTune.Value = 0;
                    lblTune.Text = "Tune: " + 0 + "w";
                    lblTune2.Text = "Tune:" + 0 + "w";

                    MessageBox.Show("The Drive And/Or Tune Power Is Above The Maximum Limit.", "Release PTT And Reset Power.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    RXOnly = false;
                    chkExternalPA.Checked = true;
                    return;
                }
            }

            if (SetupForm.chkAmpDRVLim.Checked == true & chkExternalPA.Checked == true)
            {
                int drvlimpwr = (int)(ptbPWR.Value / (float)(ptbPWR.Maximum - ptbPWR.Minimum) * SetupForm.GetPABandMaxPower(TXBand));

                if (SetupForm.numUpDnDRVLim.Value < drvlimpwr)
                {
                    RXOnly = true;
                    chkExternalPA.Checked = false;
                    ptbPWR.Value = 0;
                    lblPWR.Text = "Drive: " + 0 + "w";
                    lblPWR2.Text = "Drive:" + 0 + "w";

                    MessageBox.Show("The Drive And/Or Tune Power Is Above The Maximum Limit.", "Release PTT And Reset Power.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    RXOnly = false;
                    chkExternalPA.Checked = true;
                    return;
                }
            }

            lblPWR2.Text = lblPWR.Text;
            //wd5y
        }
        public string PAProfile
        {
            get
            {
                if (IsSetupFormNull)
                    return "";
                else
                    return SetupForm.PAProfileName;
            }
            set { lblPAProfile.Text = "PA Profile: " + value; }
        }
        private void ptbPWR_MouseUp(object sender, MouseEventArgs e)
        {
            UpdateDriveLabel(false, EventArgs.Empty);
        }
        private double m_fDrivePower = -1;
        private void ptbPWR_Scroll(object sender, System.EventArgs e)
        {
            if (IsSetupFormNull)
                return;

            PrettyTrackBar.LimitConstraint lc = e as PrettyTrackBar.LimitConstraint; // the event args will contain a LimitConstraint if we are using the right click/drag of a limit

            if (lc != null)
                limitPower_by_band[(int)tx_band] = lc.LimitValue; // store the adjusted limit level

            int new_pwr = setPowerFromDriveSlider(out bool bUseConstrain, e != EventArgs.Empty);
            power_by_band[(int)tx_band] = ptbPWR.Value;

            UpdateDriveLabel(lc != null && bUseConstrain, e);

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbPWR.Focus();
            }

            double pct = Convert.ToDouble(new_pwr) / 100.0;  //-W2PA Send LED update back to Behringer
            if (pct <= 0.0) pct = 0.0;
            else if (pct < 1.0 / 15.0) pct = 1.0 / 15.0; //-W2PA Don't let the last LED go out until zero
            Midi2Cat.SendUpdateToMidi(CatCmd.DriveLevel, pct);

            //-W2PA Update LEDs on Behringer MIDI controller mini wheel
            pct = Convert.ToDouble(ptbPWR.Value - ptbPWR.Minimum) / Convert.ToDouble(ptbPWR.Maximum - ptbPWR.Minimum);
            Midi2Cat.SendUpdateToMidi(CatCmd.DriveLevel_inc, pct);

            if (sliderForm != null)
            {
                sliderForm.TXDrive = ptbPWR.Value;

                //wd5y
                sliderForm.lblDRV.Text = lblPWR.Text;
                //wd5y
            }

            if (m_fDrivePower != new_pwr)  // MW0LGE_21k9d
            {
                m_fDrivePower = new_pwr;
                DrivePowerChangedHandlers?.Invoke(1, new_pwr, TUN || chk2TONE.Checked); // only rx1
            }
        }

        private void ptbAF_Scroll(object sender, System.EventArgs e)
        {
            lblAF.Text = "Master AF:  " + ptbAF.Value.ToString();

            //[2.10.1.0] MW0LGE added
            if (!initializing && !_mox && e != EventArgs.Empty && m_bRXAFSlidersWillUnmute)
            {
                if (chkMUT.Checked) chkMUT.Checked = false;
                if (RX2Enabled && chkRX2Mute.Checked) chkRX2Mute.Checked = false;
            }

            if (_mox && !chkMON.Checked)
            {
                // monitor is muted
                // Audio.MonitorVolume = 0.0;
            }
            else
            {
                if ((rx1_dsp_mode == DSPMode.CWL || rx1_dsp_mode == DSPMode.CWU) &&
                    (!_mox && Audio.MOX) &&
                    current_breakin_mode == BreakIn.Manual)
                {
                    Audio.MonitorVolume = 0.0;
                    if (!m_bIgnoreAFChangeForMonitor) TXAF = ptbAF.Value; //MW0LGE_21k9d the if
                }
                else Audio.MonitorVolume = ptbAF.Value / 100.0;
            }

            if ((!MOX && !Audio.MOX) ||
                (MOX && !Audio.MOX)) RXAF = ptbAF.Value;
            else if (MOX && chkMON.Checked && !m_bIgnoreAFChangeForMonitor) TXAF = ptbAF.Value; //MW0LGE_21k9 ingore the monitor AF slider change when in mox //MW0LGE_22b added chMON, so only adjust txaf if monitoring

            setLinkedAF(0, ptbAF.Value); //[2.10.1.0] MW0LGE

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbAF.Focus();
            }
            if (sliderForm != null)
            {
                sliderForm.MasterAFGain = ptbAF.Value;

                //wd5y
                sliderForm.lblaf.Text = ptbAF.Value.ToString();
                //wd5y
            }
        }
        private void ptbRF_Scroll(object sender, System.EventArgs e)
        {
            switch (RX1AGCMode)
            {
                case AGCMode.FIXD:
                    lblRF.Text = "Fixed Gain:  " + ptbRF.Value.ToString();
                    if (!IsSetupFormNull) SetupForm.AGCFixedGain = ptbRF.Value;
                    break;
                default:
                    lblRF.Text = "AGC Gain:  " + ptbRF.Value.ToString();
                    if (!IsSetupFormNull) SetupForm.AGCMaxGain = ptbRF.Value;
                    break;
            }

            rx1_agct_by_band[(int)rx1_band] = ptbRF.Value;

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbRF.Focus();
            }

            //-W2PA Update LEDs on Behringer MIDI controller
            double pct = Convert.ToDouble(ptbRF.Value - ptbRF.Minimum) / Convert.ToDouble(ptbRF.Maximum - ptbRF.Minimum);
            Midi2Cat.SendUpdateToMidi(CatCmd.AGCLevel_inc, pct);
            if (sliderForm != null)
            {
                sliderForm.RX1RFGainAGC = ptbRF.Value;

                //wd5y
                if (AutoAGCRX1)
                {
                    sliderForm.chkAGCAut.Checked = true;
                }
                else
                {
                    sliderForm.chkAGCAut.Checked = false;
                }

                sliderForm.lblRX1rf.Text = ptbRF.Value.ToString();
                //wd5y
            }

            //wd5y
            lblRF2.Size = new Size(34, 23);
            lblRF2.Text = "RF:   " + ptbRF.Value.ToString();
            //wd5y
        }
        public bool MicMute
        {
            get { return chkMicMute.Checked; }
            set { chkMicMute.Checked = value; }
        }
        private void chkMicMute_CheckedChanged(object sender, System.EventArgs e)
        {
            if (chkMicMute.Checked)
                ptbMic_Scroll(this, EventArgs.Empty);
            else Audio.MicPreamp = 0.0;
        }

        private void ptbMic_Scroll(object sender, System.EventArgs e)
        {
            ptbMic.Minimum = mic_gain_min;
            ptbMic.Maximum = mic_gain_max;
            lblMicVal.Text = ptbMic.Value.ToString() + " dB";
            if (radio.GetDSPTX(0).CurrentDSPMode != DSPMode.FM)
            {
                double gain_db = (double)ptbMic.Value;
                if (mic_boost)
                {
                    toolTip1.SetToolTip(ptbMic, (ptbMic.Value + 20).ToString());
                }
                else if (line_in)
                {
                    toolTip1.SetToolTip(ptbMic, (ptbMic.Value + line_in_boost).ToString());
                }
                else
                {
                    toolTip1.SetToolTip(ptbMic, "");
                }

                Audio.MicPreamp = Math.Pow(10.0, gain_db / 20.0); // convert to scalar 
            }

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbMic.Focus();
            }
            if (sliderForm != null)
            {
                sliderForm.MicGain = ptbMic.Value;

                //wd5y
                sliderForm.lblmic.Text = lblMicVal.Text;
                //wd5y
            }
        }

        private void ptbCWSpeed_Scroll(object sender, System.EventArgs e)
        {
            lblCWSpeed.Text = "Speed:  " + ptbCWSpeed.Value.ToString() + " WPM";
            NetworkIO.SetCWKeyerSpeed(ptbCWSpeed.Value);
            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbCWSpeed.Focus();
            }

            //-W2PA Update LEDs on Behringer MIDI controller
            double pct = Convert.ToDouble(ptbCWSpeed.Value) / Convert.ToDouble(60);
            if (pct < 1.0 / 15.0) pct = 1.0 / 15.0;  //-W2PA Don't let the last LED go out
            Midi2Cat.SendUpdateToMidi(CatCmd.CWSpeed_inc, pct);
        }

        private void chkVOX_CheckedChanged(object sender, System.EventArgs e)
        {
            if (!IsSetupFormNull) SetupForm.VOXEnable = chkVOX.Checked;

            if (chkVOX.Checked)
            {
                chkVOX.BackColor = button_selected_color;
            }
            else
            {
                Audio.VOXActive = false;
                chkVOX.BackColor = SystemColors.Control;
            }

            LineInBoost = line_in_boost;
        }
        private void picSquelch_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            int signal_x = (int)((sql_data + 160.0) * (picSquelch.Width - 1) / 160.0);
            int sql_x = (int)(((float)ptbSquelch.Value + 160.0) * (picSquelch.Width - 1) / 160.0);

            if (_mox) signal_x = sql_x = 0;
            e.Graphics.FillRectangle(Brushes.LimeGreen, 0, 0, signal_x, picSquelch.Height);
            if (sql_x < signal_x)
                e.Graphics.FillRectangle(Brushes.Red, sql_x + 1, 0, signal_x - sql_x - 1, picSquelch.Height);
        }

        private void chkNoiseGate_CheckedChanged(object sender, System.EventArgs e)
        {
            if (!IsSetupFormNull) SetupForm.NoiseGateEnabled = chkNoiseGate.Checked;

            if (chkNoiseGate.Checked) chkNoiseGate.BackColor = button_selected_color;
            else chkNoiseGate.BackColor = SystemColors.Control;
        }

        private void ptbVACRXGain_Scroll(object sender, System.EventArgs e)
        {
            lblRXGain.Text = "RX Gain:  " + ptbVACRXGain.Value.ToString();
            if (!IsSetupFormNull)
                if (!(chkRX2.Checked && chkVAC2.Checked && chkVFOBTX.Checked))
                {
                    lblVACRXIndicator.Text = "VAC1";
                    lblVACTXIndicator.Text = "VAC1";
                    SetupForm.VACRXGain = ptbVACRXGain.Value;
                    vac_rx_gain = ptbVACRXGain.Value;
                }
                else
                {
                    lblVACRXIndicator.Text = "VAC2";
                    lblVACTXIndicator.Text = "VAC2";
                    SetupForm.VAC2RXGain = ptbVACRXGain.Value;
                    vac2_rx_gain = ptbVACRXGain.Value;
                }

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbVACRXGain.Focus();
            }
        }

        private void ptbVACTXGain_Scroll(object sender, System.EventArgs e)
        {
            lblTXGain.Text = "TX Gain:  " + ptbVACTXGain.Value.ToString();
            if (!IsSetupFormNull)
            {
                if (!(chkRX2.Checked && chkVAC2.Checked && chkVFOBTX.Checked))
                {
                    lblVACRXIndicator.Text = "VAC1";
                    lblVACTXIndicator.Text = "VAC1";
                    SetupForm.VACTXGain = ptbVACTXGain.Value;
                    vac_tx_gain = ptbVACTXGain.Value;
                }
                else
                {
                    lblVACRXIndicator.Text = "VAC2";
                    lblVACTXIndicator.Text = "VAC2";
                    SetupForm.VAC2TXGain = ptbVACTXGain.Value;
                    vac2_tx_gain = ptbVACTXGain.Value;
                }
            }

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbVACTXGain.Focus();
            }
        }

        private void ptbVOX_Scroll(object sender, System.EventArgs e)
        {
            lblVOXVal.Text = ptbVOX.Value.ToString();
            if (!IsSetupFormNull) SetupForm.VOXSens = ptbVOX.Value;

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbVOX.Focus();
            }
        }

        unsafe private void picVOX_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            double audio_peak = 0.0;
            cmaster.GetDEXPPeakSignal(0, &audio_peak);
            if (mic_boost) audio_peak /= Audio.VOXGain;
            int peak_x = (int)(picVOX.Width - 20.0 * Math.Log10(audio_peak) * picVOX.Width / ptbVOX.Minimum);
            int vox_x = picVOX.Width - ptbVOX.Value * picVOX.Width / ptbVOX.Minimum;
            if (peak_x < 0) peak_x = vox_x = 0;
            e.Graphics.FillRectangle(Brushes.LimeGreen, 0, 0, peak_x, picVOX.Height);
            if (vox_x < peak_x)
                e.Graphics.FillRectangle(Brushes.Red, vox_x + 1, 0, peak_x - vox_x - 1, picVOX.Height);
        }

        private void ptbNoiseGate_Scroll(object sender, System.EventArgs e)
        {
            lblNoiseGateVal.Text = ptbNoiseGate.Value.ToString();

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbNoiseGate.Focus();
            }
        }

        private void picNoiseGate_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            int signal_x = (int)((noise_gate_data + 160.0) * (picNoiseGate.Width - 1) / 160.0);
            int noise_x = (int)(((float)ptbNoiseGate.Value + 160.0) * (picNoiseGate.Width - 1) / 160.0);

            if (!_mox) signal_x = noise_x = 0;
            e.Graphics.FillRectangle(Brushes.LimeGreen, 0, 0, signal_x, picNoiseGate.Height);
            if (noise_x < signal_x)
                e.Graphics.FillRectangle(Brushes.Red, noise_x + 1, 0, signal_x - noise_x - 1, picNoiseGate.Height);
        }

        private void WheelTune_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                ChangeTuneStepUp();
        }

        private void chkMON_CheckedChanged(object sender, System.EventArgs e)
        {
            bool oldMON = Audio.MON;

            Audio.MON = chkMON.Checked;

            if (chkMON.Checked)
                chkMON.BackColor = button_selected_color;
            else
                chkMON.BackColor = SystemColors.Control;

            if (!(chkMON.Checked == false && _mox))
                ptbAF_Scroll(this, EventArgs.Empty);

            if (path_Illustrator != null)
                path_Illustrator.pi_Changed();

            if (Audio.MON != oldMON)
                MONChangedHandlers?.Invoke(oldMON, Audio.MON);
        }

        private void AudioMOXChanged(bool tx)
        {
            if (tx)
            {
                Audio.MOX = tx;
                ptbAF.Value = txaf;
            }
            else // rx
            {
                ptbAF.Value = rxaf;
                Audio.MOX = tx;
            }

            ptbAF_Scroll(this, EventArgs.Empty);
        }

        private void HdwMOXChanged(bool tx, double freq)
        {
            if (tx)
            {
                if (m_bQSOResetTimerOnMox) QSOTimerReset();
                if (m_bQSOTimerDuringMoxOnly && !m_bQSOTimerRunning) QSOTimerRunning = true;

                if (bpf2_gnd) NetworkIO.SetBPF2Gnd(1);

                updateVFOFreqs(tx);

                // make sure TX freq has been set

                UpdateRX1DDSFreq();
                UpdateRX2DDSFreq();
                UpdateTXDDSFreq();

                Band lo_band = BandByFreq(XVTRForm.TranslateFreq(VFOAFreq), rx1_xvtr_index, current_region);
                Band lo_bandb = BandByFreq(XVTRForm.TranslateFreq(VFOBFreq), rx2_xvtr_index, current_region);

                if (penny_ext_ctrl_enabled) //MW0LGE_21k
                {
                    int bits = Penny.getPenny().UpdateExtCtrl(lo_band, lo_bandb, _mox, tuning, SetupForm.TestIMD, chkExternalPA.Checked); //MW0LGE_21j
                    if (!IsSetupFormNull) SetupForm.UpdateOCLedStrip(_mox, bits);
                }

                UpdateTRXAnt();
                if (rx1_xvtr_index >= 0)
                {
                    Alex.getAlex().UpdateAlexAntSelection(lo_band, _mox, alex_ant_ctrl_enabled, true);
                }
                else
                {
                    Alex.getAlex().UpdateAlexAntSelection(tx_band, _mox, alex_ant_ctrl_enabled, false);
                }
                UpdateTRXAnt(); //[2.3.10.6]MW0LGE added

                NetworkIO.SetTRXrelay(1);
                if (cw_fw_keyer &&
                    (RX1DSPMode == DSPMode.CWL || RX1DSPMode == DSPMode.CWU) &&
                     !chkTUN.Checked &&
                     _current_ptt_mode != PTTMode.SPACE &&
                    _current_ptt_mode != PTTMode.CAT &&
                    _current_ptt_mode != PTTMode.CW)
                    NetworkIO.SetPttOut(0);
                else NetworkIO.SetPttOut(1);
                if (serialPTT != null) serialPTT.setDTR(true);
            }
            else // rx
            {
                if (m_bQSOTimerDuringMoxOnly && m_bQSOTimerRunning) QSOTimerRunning = false;

                NetworkIO.SetPttOut(0);
                NetworkIO.SetTRXrelay(0);

                if (serialPTT != null) serialPTT.setDTR(false);

                if (!rx1_step_att_present)
                    RX1PreampMode = rx1_preamp_mode;

                updateVFOFreqs(tx);

                UpdateRX1DDSFreq();
                UpdateRX2DDSFreq();
                UpdateTXDDSFreq();

                Band lo_band = Band.FIRST;
                Band lo_bandb = Band.FIRST;
                lo_band = BandByFreq(XVTRForm.TranslateFreq(VFOAFreq), rx1_xvtr_index, current_region);
                lo_bandb = BandByFreq(XVTRForm.TranslateFreq(VFOBFreq), rx2_xvtr_index, current_region);

                if (penny_ext_ctrl_enabled) //MW0LGE_21k
                {
                    int bits = Penny.getPenny().UpdateExtCtrl(lo_band, lo_bandb, _mox, tuning, SetupForm.TestIMD, chkExternalPA.Checked); //MW0LGE_21j
                    if (!IsSetupFormNull) SetupForm.UpdateOCLedStrip(_mox, bits);
                }

                UpdateTRXAnt(); //[2.3.10.6]MW0LGE added
                if (rx1_xvtr_index >= 0)
                {
                    Alex.getAlex().UpdateAlexAntSelection(lo_band, _mox, alex_ant_ctrl_enabled, true);
                }
                else
                {
                    Alex.getAlex().UpdateAlexAntSelection(rx1_band, _mox, alex_ant_ctrl_enabled, false);
                }
                NetworkIO.SetBPF2Gnd(0);
                UpdateTRXAnt();
            }
        }

        private CheckState NB_CheckState;
        private void UIMOXChangedTrue()
        {
            NB_CheckState = chkNB.CheckState; // save current state of NB
            if (display_duplex) chkNB.CheckState = CheckState.Unchecked; // turn off NB/NB2 while transmitting with DUP enabled
            meter_peak_count = multimeter_peak_hold_samples;		// reset multimeter peak

            comboMeterRXMode.ForeColor = Color.Gray;
            comboMeterTXMode.ForeColor = Color.White;
            comboMeterTXMode_SelectedIndexChanged(this, EventArgs.Empty);

            if (((rx1_dsp_mode == DSPMode.CWL ||
                rx1_dsp_mode == DSPMode.CWU) &&
                !disable_ui_mox_changes) ||
                    (rx1_dsp_mode != DSPMode.CWL &&
                    rx1_dsp_mode != DSPMode.CWU))
            {
                DisableAllBands();
                DisableAllModes();
                chkVFOSplit.Enabled = false;
                btnVFOAtoB.Enabled = false;
                btnVFOBtoA.Enabled = false;
                btnVFOSwap.Enabled = false;
                chkPower.BackColor = Color.Red;
            }

            chkVFOLock.Enabled = !chkMOX.Checked; //MW0LGE_21d3
            chkVFOBLock.Enabled = !chkMOX.Checked; //MW0LGE_21d3

            //if (m_bAttontx) //[2.10.3.6]MW0LGE att_fixes
            //{
            //    comboPreamp.Enabled = !chkMOX.Checked;
            //}
            updateAttNudsCombos();

            SetupForm.MOX = chkMOX.Checked;
            ResetMultiMeterPeak();
            picSquelch.Invalidate();
        }

        private void UIMOXChangedFalse()
        {
            if (display_duplex) chkNB.CheckState = NB_CheckState; // restore saved state of NB

            if (((rx1_dsp_mode == DSPMode.CWL ||
               rx1_dsp_mode == DSPMode.CWU) &&
               !disable_ui_mox_changes) ||
                   (rx1_dsp_mode != DSPMode.CWL &&
                   rx1_dsp_mode != DSPMode.CWU))
            {
                if (!VFOALock) //MW0LGE_21d only unlock them if the vfo is unlocked
                {
                    EnableAllBands();
                    EnableAllModes();
                }
                chkVFOSplit.Enabled = true;
                btnVFOAtoB.Enabled = true;
                btnVFOBtoA.Enabled = true;
                btnVFOSwap.Enabled = true;
            }
            if (PowerOn) chkPower.BackColor = button_selected_color;
            comboMeterTXMode.ForeColor = Color.Gray;
            comboMeterRXMode.ForeColor = Color.White;
            comboMeterRXMode_SelectedIndexChanged(this, EventArgs.Empty);
            comboRX2MeterMode_SelectedIndexChanged(this, EventArgs.Empty);
            comboMeterTXMode_SelectedIndexChanged(this, EventArgs.Empty);

            pa_fwd_power = 0;
            pa_rev_power = 0;

            Audio.HighSWRScale = 1.0;
            HighSWR = false;

            for (int i = 0; i < meter_text_history.Length; i++)
                meter_text_history[i] = 0.0f;

            chkVFOLock.Enabled = !chkMOX.Checked; //MW0LGE_21d3
            chkVFOBLock.Enabled = !chkMOX.Checked; //MW0LGE_21d3

            //if (m_bAttontx) //[2.10.3.6]MW0LGE att_fixes
            //{
            //    comboPreamp.Enabled = !chkMOX.Checked;
            //}
            updateAttNudsCombos();

            SetupForm.MOX = chkMOX.Checked;
            ResetMultiMeterPeak();
            chkMOX.BackColor = SystemColors.Control;

            picNoiseGate.Invalidate();
        }

        private void updateAttNudsCombos()
        {
            if (rx1_step_att_present)
                udRX1StepAttData.BringToFront();
            else
                comboPreamp.BringToFront();
            if (rx2_step_att_present)
                udRX2StepAttData.BringToFront();
            else
                comboRX2Preamp.BringToFront();

            //update the nud and combos, for attenuators, both rx and tx
            bool bShowOnMox = _mox && (_isexpanded || (_iscollapsed && !(_showAndromedaTopControls || _showAndromedaButtonBar)));
            if (bShowOnMox)
            {
                if (VFOATX || (VFOBTX && !rx2_enabled))
                {
                    //if txing on rx1 (split or non-split), then the att combo and nud will be disabled for rx1
                    comboPreamp.Enabled = false;
                    udRX1StepAttData.Enabled = false;
                    comboRX2Preamp.Enabled = true;
                    udRX2StepAttData.Enabled = true;

                    //move it to rx1
                    udTXStepAttData.Location = udRX1StepAttData.Location;
                    udTXStepAttData.Parent = udRX1StepAttData.Parent;
                    udTXStepAttData.BringToFront();
                    udTXStepAttData.Visible = m_bAttontx;
                    lblPreamp.Text = m_bAttontx ? "Tx-ATT" : (rx1_step_att_present ? "S-ATT" : "ATT");
                }
                else if (VFOBTX && rx2_enabled)
                {
                    //if txing on rx2 then the att combo and nud will be disabled for rx2
                    comboPreamp.Enabled = true;
                    udRX1StepAttData.Enabled = true;
                    comboRX2Preamp.Enabled = false;
                    udRX2StepAttData.Enabled = false;

                    //move it to rx2
                    udTXStepAttData.Location = udRX2StepAttData.Location;
                    udTXStepAttData.Parent = udRX2StepAttData.Parent;
                    udTXStepAttData.BringToFront();
                    udTXStepAttData.Visible = m_bAttontx;
                    lblRX2Preamp.Text = m_bAttontx ? "Tx-ATT" : (rx2_step_att_present ? "S-ATT" : "ATT");
                }
                else
                {
                    // should not get here
                }
            }
            else
            { //rx
                comboPreamp.Enabled = true;
                udRX1StepAttData.Enabled = true;
                comboRX2Preamp.Enabled = rx2_preamp_present;
                udRX2StepAttData.Enabled = rx2_preamp_present;
                udTXStepAttData.Visible = false;
                lblPreamp.Text = rx1_step_att_present ? "S-ATT" : "ATT";
                lblRX2Preamp.Text = rx2_step_att_present ? "S-ATT" : (rx2_preamp_present ? "ATT" : "");
            }

            if (_iscollapsed && !_isexpanded)
            {
                //MW0LGE we need to move the meters to top, because in collasped mode the bring to fronts above
                //will cause the combo to be above everything, including meters.
                MeterManager.BringToFront();
            }
        }

        private bool _mox = false;
        private PreampMode temp_mode = PreampMode.HPSDR_OFF; // HPSDR preamp mode
        private PreampMode temp_mode2 = PreampMode.HPSDR_OFF; // HPSDR preamp mode

        private bool _forceATTwhenPSAoff = true; //MW0LGE [2.9.0.7] added
        public bool ForceATTwhenPSAoff
        {
            get { return _forceATTwhenPSAoff; }
            set { _forceATTwhenPSAoff = value; }
        }
        private bool _forceATTwhenPowerChangesWhenPSAon = true; //MW0LGE [2.9.3.5] added
        private float _lastPower = -1;
        public bool ForceATTwhenOutputPowerChangesWhenPSAon
        {
            get { return _forceATTwhenPowerChangesWhenPSAon; }
            set
            {
                if (value != _forceATTwhenPowerChangesWhenPSAon) _lastPower = -1;
                _forceATTwhenPowerChangesWhenPSAon = value;
            }
        }

        private void chkMOX_CheckedChanged2(object sender, System.EventArgs e)
        {
            bool bOldMox = _mox; //MW0LGE_21b used for state change delgates at end of fn

            MoxPreChangeHandlers?.Invoke(rx2_enabled && VFOBTX ? 2 : 1, _mox, chkMOX.Checked); // MW0LGE_21k8

            NetworkIO.SendHighPriority(1);
            if (rx_only && chkMOX.Checked)
            {
                chkMOX.Checked = false;
                return;
            }

            if (allow_mox_bypass && _current_ptt_mode != PTTMode.MIC &&
                                    _current_ptt_mode != PTTMode.SPACE &&
                                    _current_ptt_mode != PTTMode.CAT)
            {
                if (chkMOX.Checked)
                {
                    if (chkVAC1.Checked)
                        Audio.VACBypass = true;
                }
                else
                {
                    if (chkVAC1.Checked && Audio.VACBypass)
                        Audio.VACBypass = false;
                }
            }

            bool tx = chkMOX.Checked;

            //[2.10.1.0]MW0LGE changed
            if (!tx)
            {
                if (CATPTT) CATPTT = false;
                if (TCIPTT) TCIPTT = false;
            }

            if (tx) _mox = tx;
            double freq = 0.0;

            if (tx)
            {
                //FM Offsets
                if (radio.GetDSPTX(0).CurrentDSPMode == DSPMode.FM && current_fm_tx_mode != FMTXMode.Simplex
                    && !chkVFOSplit.Checked)
                {
                    switch (current_fm_tx_mode)
                    {
                        case FMTXMode.Low:
                            if (!chkFMTXRev.Checked)
                                TXFreq -= fm_tx_offset_mhz; // usual case
                            else
                                TXFreq += fm_tx_offset_mhz;
                            break;
                        case FMTXMode.High:
                            if (!chkFMTXRev.Checked)
                                TXFreq += fm_tx_offset_mhz; // usual case
                            else
                                TXFreq -= fm_tx_offset_mhz;
                            break;
                    }
                }

                if (chkVFOBTX.Checked || (!chkRX2.Checked && chkVFOSplit.Checked))
                    freq = VFOBFreq;// double.Parse(txtVFOBFreq.Text); //[2.10.3.6]freq changes.
                else if (chkRX2.Checked && chkVFOSplit.Checked)
                    freq = VFOASubFreq;// double.Parse(txtVFOABand.Text); //[2.10.3.6]freq changes.
                else
                    freq = VFOAFreq;// double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.

                if (chkXIT.Checked)
                    freq += (int)udXIT.Value * 0.000001;

                if (!calibrating)
                {
                    //MW0LGE [2.9.0.7]
                    if (_preventTXonDifferentBandToRXband && ((!RX2Enabled && VFOBTX && RX1Band != TXBand) || (RX2Enabled && VFOBTX && RX2Band != TXBand)))
                    {
                        if (m_frmCWXForm != null && !m_frmCWXForm.IsDisposed)
                            m_frmCWXForm.StopEverything(chkPower.Checked);

                        chkMOX.Checked = false;

                        // note RX2 enabled with a TXvfoB will always TX
                        MessageBox.Show("Your TX band is different to your RX band and you have selected the option to prevent this.",
                        "Transmit Error: TX/RX bands different",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                        return;
                    }

                    if (tx_band == Band.B60M && current_region == FRSRegion.US && !extended)
                    {
                        switch (radio.GetDSPTX(0).CurrentDSPMode)
                        {
                            case DSPMode.USB:
                            case DSPMode.CWL:
                            case DSPMode.CWU:
                            case DSPMode.DIGU:
                                break;
                            default:
                                MessageBox.Show(rx1_dsp_mode.ToString() + " mode is not allowed on 60M band.",
                                    "Transmit Error: Mode/Band",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                                chkMOX.Checked = false;
                                return;
                        }
                    }

                    if (!CheckValidTXFreq(current_region, freq, radio.GetDSPTX(0).CurrentDSPMode, chkTUN.Checked))	// out of band
                    {
                        if (tx_band == Band.B60M && current_region == FRSRegion.US &&
                            CheckValidTXFreq_Private(current_region, freq) && !extended)
                        {
                            MessageBox.Show("The transmit filter you have selected exceeds the bandwidth\n" +
                                "constraints (2.8kHz) for the 60m band in this region.",
                                "60m Bandwidth",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                        }
                        else
                        {
                            switch (radio.GetDSPTX(0).CurrentDSPMode)
                            {
                                case DSPMode.CWL:
                                case DSPMode.CWU:
                                    MessageBox.Show("The frequency " + freq.ToString("f6") + "MHz is not within the\n" +
                                        "Band specifications for your region (" + current_region.ToString() + ").",
                                        "Transmit Error: Out Of Band",
                                        MessageBoxButtons.OK,
                                        MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                                    break;
                                default:
                                    if (!chkTUN.Checked)
                                    {
                                        MessageBox.Show("The frequency " + freq.ToString("f6") + "MHz in combination with your TX filter\n" +
                                            "settings [" + Display.TXFilterLow.ToString() + ", " + Display.TXFilterHigh.ToString() + "] are not within the " +
                                            "Band specifications for your region (" + current_region.ToString() + ").",
                                            "Transmit Error: Out Of Band",
                                            MessageBoxButtons.OK,
                                            MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                                    }
                                    else
                                    {
                                        MessageBox.Show("The frequency " + freq.ToString("f6") + "MHz is not within the\n" +
                                               "Band specifications for your region (" + current_region.ToString() + ").",
                                               "Transmit Error: Out Of Band",
                                               MessageBoxButtons.OK,
                                               MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                                    }
                                    break;
                            }
                        }
                        chkMOX.Checked = false;
                        return;
                    }
                }

                switch (rx1_dsp_mode)
                {
                    case DSPMode.CWL:
                        freq += (double)cw_pitch * 0.0000010;
                        break;
                    case DSPMode.CWU:
                        freq -= (double)cw_pitch * 0.0000010;
                        break;
                }
            }
            else
            {
                _current_ptt_mode = PTTMode.NONE;

                //Undo FM Offsets
                if (radio.GetDSPTX(0).CurrentDSPMode == DSPMode.FM && current_fm_tx_mode != FMTXMode.Simplex
                    && !chkVFOSplit.Checked)
                {
                    switch (current_fm_tx_mode)
                    {
                        case FMTXMode.Low:
                            if (!chkFMTXRev.Checked)
                                TXFreq += fm_tx_offset_mhz; // usual case
                            else
                                TXFreq -= fm_tx_offset_mhz;
                            break;
                        case FMTXMode.High:
                            if (!chkFMTXRev.Checked)
                                TXFreq -= fm_tx_offset_mhz; // usual case
                            else
                                TXFreq += fm_tx_offset_mhz;
                            break;
                    }
                }
            }

            _pause_DisplayThread = true; // MW0LGE_21k8 turn display off whilst everything is being setup, prevents flashes of pixels etc

            if (tx)                     // change to TX mode
            {
                //
                if (!chkTUN.Checked && !chk2TONE.Checked) ptbPWR_Scroll(this, EventArgs.Empty); //MW0LGE_22b need this here as we may have adjusted power via tune slider when not in mox
                //
                if (!full_duplex)       // shutdown RX1 and RX2 as appropriate
                {
                    bool RX1_shutdown = chkVFOATX.Checked || (chkVFOBTX.Checked && !RX2Enabled) || mute_rx1_on_vfob_tx || (chkVFOBTX.Checked && current_hpsdr_model == HPSDRModel.ANAN10E && psform.PSEnabled);
                    bool RX2_shutdown = (chkVFOBTX.Checked && RX2Enabled) || mute_rx2_on_vfoa_tx || (chkVFOATX.Checked && RX2Enabled && current_hpsdr_model == HPSDRModel.ANAN10E && psform.PSEnabled);
                    if (RX1_shutdown && !RX2_shutdown)
                    {
                        WDSP.SetChannelState(WDSP.id(0, 1), 0, 0);
                        WDSP.SetChannelState(WDSP.id(0, 0), 0, 1);
                    }
                    if (!RX1_shutdown && RX2_shutdown)
                        WDSP.SetChannelState(WDSP.id(2, 0), 0, 1);
                    if (RX1_shutdown && RX2_shutdown)
                    {
                        WDSP.SetChannelState(WDSP.id(0, 1), 0, 0);
                        WDSP.SetChannelState(WDSP.id(0, 0), 0, 0);
                        WDSP.SetChannelState(WDSP.id(2, 0), 0, 1);
                    }
                }

                if (m_bAttontx)
                {
                    if (current_hpsdr_model == HPSDRModel.HPSDR)
                    {
                        temp_mode = RX1PreampMode;
                        SetupForm.RX1EnableAtt = false;
                        RX1PreampMode = PreampMode.HPSDR_OFF;			// set to -20dB
                        if (rx2_preamp_present)
                        {
                            temp_mode2 = RX2PreampMode;
                            RX2PreampMode = PreampMode.HPSDR_OFF;
                        }
                    }
                    else
                    {
                        ////MW0LGE [2.9.0.7] added option to always apply 31 att from setup form when not in ps
                        //if ((!chkFWCATUBypass.Checked && _forceATTwhenPSAoff) ||
                        //                (radio.GetDSPTX(0).CurrentDSPMode == DSPMode.CWL ||
                        //                 radio.GetDSPTX(0).CurrentDSPMode == DSPMode.CWU)) SetupForm.ATTOnTX = 31; // reset when PS is OFF or in CW mode

                        //MW0LGE [2.9.0.7] added option to always apply 31 att from setup form when not in ps
                        int txAtt = getTXstepAttenuatorForBand(tx_band);
                        if ((!chkFWCATUBypass.Checked && _forceATTwhenPSAoff) ||
                                        (radio.GetDSPTX(0).CurrentDSPMode == DSPMode.CWL ||
                                         radio.GetDSPTX(0).CurrentDSPMode == DSPMode.CWU)) txAtt = 31; // reset when PS is OFF or in CW mode

                        SetupForm.ATTOnRX1 = getRX1stepAttenuatorForBand(rx1_band); //[2.10.3.6]MW0LGE att_fixes
                        SetupForm.ATTOnTX = txAtt; //[2.10.3.6]MW0LGE att_fixes NOTE: this will eventually call Display.TXAttenuatorOffset with the value
                        NetworkIO.SetTxAttenData(txAtt); //[2.10.3.6]MW0LGE att_fixes

                        //SetupForm.RX1EnableAtt = true; //[2.10.3.6]MW0LGE att_fixes
                        //comboRX2Preamp.Enabled = false; //[2.10.3.6]MW0LGE att_fixes
                        //udRX2StepAttData.Enabled = false; //[2.10.3.6]MW0LGE att_fixes
                        updateAttNudsCombos();
                    }
                }
                else
                {
                    NetworkIO.SetTxAttenData(0);
                    Display.TXAttenuatorOffset = 0; //[2.10.3.6]MW0LGE att_fixes
                }

                UpdateAAudioMixerStates();
                UpdateDDCs(rx2_enabled);

                HdwMOXChanged(tx, freq);   // flip the hardware
                Display.MOX = tx;
                psform.Mox = tx;
                cmaster.Mox = tx;          // loads router bit, among other things

                Audio.RX1BlankDisplayTX = blank_rx1_on_vfob_tx;

                if (radio.GetDSPTX(0).CurrentDSPMode != DSPMode.CWL &&
                    radio.GetDSPTX(0).CurrentDSPMode != DSPMode.CWU) // turn on the transmitter unless in CW mode
                {
                    if (rf_delay > 0)
                        Thread.Sleep(rf_delay);
                    AudioMOXChanged(tx);    // set MOX in audio.cs - wait 'til here to allow last audio to clear AAMix before changing to MON volume
                    WDSP.SetChannelState(WDSP.id(1, 0), 1, 0);
                }
                else
                    AudioMOXChanged(tx);    // set MOX in audio.cs
            }
            else                        // change to RX mode
            {
                if (space_mox_delay > 0)
                    Thread.Sleep(space_mox_delay); // default 0 // from PSDR MW0LGE

                _mox = tx;
                psform.Mox = tx;
                WDSP.SetChannelState(WDSP.id(1, 0), 0, 1);  // turn off the transmitter (no action if it's already off)

                if (radio.GetDSPTX(0).CurrentDSPMode == DSPMode.CWL ||
                    radio.GetDSPTX(0).CurrentDSPMode == DSPMode.CWU)
                {
                    if (!cw_fw_keyer && key_up_delay > 0)
                        Thread.Sleep(key_up_delay);
                }
                else
                {
                    if (mox_delay > 0)
                        Thread.Sleep(mox_delay); // default 10, allows in-flight samples to clear
                }
                UpdateDDCs(rx2_enabled);
                UpdateAAudioMixerStates();

                AudioMOXChanged(tx);    // set audio.cs to RX
                HdwMOXChanged(tx, freq);// flip the hardware
                Display.MOX = tx;
                cmaster.Mox = tx;       // loads router bit, among other things
                if (ptt_out_delay > 0)
                    Thread.Sleep(ptt_out_delay);                 //wcp:  added 2018-12-24, time for HW to switch
                WDSP.SetChannelState(WDSP.id(0, 0), 1, 0);  // turn on appropriate receivers
                if (RX2Enabled)
                    WDSP.SetChannelState(WDSP.id(2, 0), 1, 0);
                if (radio.GetDSPRX(0, 1).Active)
                    WDSP.SetChannelState(WDSP.id(0, 1), 1, 0);

                Audio.RX1BlankDisplayTX = blank_rx1_on_vfob_tx;

                if (m_bAttontx)
                {
                    if (current_hpsdr_model == HPSDRModel.HPSDR)
                    {
                        RX1PreampMode = temp_mode;
                        if (rx2_preamp_present)
                            RX2PreampMode = temp_mode2;
                    }
                    else
                    {
                        //comboRX2Preamp.Enabled = true; //[2.10.3.6]MW0LGE att_fixes
                        //udRX2StepAttData.Enabled = true; //[2.10.3.6]MW0LGE att_fixes
                        updateAttNudsCombos();

                        update_preamp_mode = true;
                        update_preamp = true;
                        UpdatePreamps();
                    }
                }
                else
                {
                    NetworkIO.SetTxAttenData(0);
                    Display.TXAttenuatorOffset = 0; //[2.10.3.6]MW0LGE att_fixes
                }
            }

            if (!tx)
            {
                pa_fwd_power = 0;
                pa_rev_power = 0;
                HighSWR = false;
            }

            if (tx) UIMOXChangedTrue();
            else UIMOXChangedFalse();

            AndromedaIndicatorCheck(EIndicatorActions.eINMOX, false, tx);

            _pause_DisplayThread = false; //MW0LGE_21k8 re-enable

            if (bOldMox != tx) MoxChangeHandlers?.Invoke(rx2_enabled && VFOBTX ? 2 : 1, bOldMox, tx); // MW0LGE_21a
        }
        private void chkMOX_Click(object sender, System.EventArgs e)
        {
            if (chkMOX.Checked)			// because the CheckedChanged event fires first
            {
                manual_mox = true;
                if (cw_fw_keyer &&
                   (RX1DSPMode == DSPMode.CWL ||
                    RX1DSPMode == DSPMode.CWU))
                    NetworkIO.SetPttOut(1);
            }
            else
            {
                manual_mox = false;
                if (chkTUN.Checked)
                    chkTUN.Checked = false;
                if (chk2TONE.Checked) //MW0LGE_21a
                    chk2TONE.Checked = false;
            }

        }

        private void comboMeterRXMode_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            if (comboMeterRXMode.Items.Count == 0 ||
                comboMeterRXMode.SelectedIndex < 0)
            {
                current_meter_rx_mode = MeterRXMode.FIRST;
            }
            else
            {
                MeterRXMode mode = MeterRXMode.FIRST;
                switch (comboMeterRXMode.Text)
                {
                    case "Signal":
                        mode = MeterRXMode.SIGNAL_STRENGTH;
                        break;
                    case "Sig Avg":
                        mode = MeterRXMode.SIGNAL_AVERAGE;
                        break;
                    case "ADC L":
                        mode = MeterRXMode.ADC_L;
                        break;
                    case "ADC R":
                        mode = MeterRXMode.ADC_R;
                        break;
                    case "ADC2 L":
                        mode = MeterRXMode.ADC2_L;
                        break;
                    case "ADC2 R":
                        mode = MeterRXMode.ADC2_R;
                        break;
                    case "Off":
                        mode = MeterRXMode.OFF;
                        break;
                }
                current_meter_rx_mode = mode;
                if (show_rx1)                                      // collapsed label is RX1/2 dependent
                    lblRXMeter.Text = comboMeterRXMode.Text;

                if (!_mox)
                {
                    ResetMultiMeterPeak();
                }
            }

            picMultiMeterDigital.Invalidate();

            if (comboMeterRXMode.Focused)
                btnHidden.Focus();
        }

        private void comboMeterTXMode_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            MeterTXMode mode = MeterTXMode.FIRST;

            switch (comboMeterTXMode.Text)
            {
                case "Fwd Pwr":
                    mode = MeterTXMode.FORWARD_POWER;
                    break;
                case "Ref Pwr":
                    mode = MeterTXMode.REVERSE_POWER;
                    break;
                case "Fwd SWR":
                    mode = MeterTXMode.SWR_POWER;
                    break;
                case "Mic":
                    mode = MeterTXMode.MIC;
                    break;
                case "EQ":
                    mode = MeterTXMode.EQ;
                    break;
                case "Leveler":
                    mode = MeterTXMode.LEVELER;
                    break;
                case "Lev Gain":
                    mode = MeterTXMode.LVL_G;
                    break;
                case "CFC":
                    mode = MeterTXMode.CFC_PK;
                    break;
                case "CFC Comp":
                    mode = MeterTXMode.CFC_G;
                    break;
                case "COMP":
                    mode = MeterTXMode.COMP;
                    break;
                case "ALC":
                    mode = MeterTXMode.ALC;
                    break;
                case "ALC Comp":
                    mode = MeterTXMode.ALC_G;
                    break;
                case "ALC Group":
                    mode = MeterTXMode.ALC_GROUP; //MW0LGE
                    break;
                case "SWR":
                    mode = MeterTXMode.SWR;
                    break;
                case "Off":
                    mode = MeterTXMode.OFF;
                    break;
            }

            if (chkTUN.Checked)
            {
                if (isMeterModeAvailableWhenTune(mode))
                {
                    tune_meter_tx_mode = mode;
                    if (!IsSetupFormNull) SetupForm.TuneMeterTXMode = mode;
                }
                else
                {
                    CurrentMeterTXMode = tune_meter_tx_mode;
                    return;
                }
            }
            current_meter_tx_mode = mode;

            if (_mox)
            {
                ResetMultiMeterPeak();
            }

            picMultiMeterDigital.Invalidate();

            if (comboMeterTXMode.Focused)
                btnHidden.Focus();
        }
        private bool isMeterModeAvailableWhenTune(MeterTXMode meterMode)
        {
            // used to validate if the meter mode selected is ok for TX tune
            // this should mirror the setup combo
            bool bRet =
                meterMode == MeterTXMode.FORWARD_POWER ||
                meterMode == MeterTXMode.REVERSE_POWER ||
                meterMode == MeterTXMode.SWR_POWER ||
                meterMode == MeterTXMode.SWR ||
                meterMode == MeterTXMode.OFF;

            return bRet;
        }

        private void chkDisplayAVG_CheckedChanged(object sender, System.EventArgs e)
        {
            //MW0LGE_21 not used
            specRX.GetSpecRX(0).AverageOn = chkDisplayAVG.Checked;
            UpdateRXSpectrumDisplayVars();
            specRX.GetSpecRX(cmaster.inid(1, 0)).AverageOn = chkDisplayAVG.Checked;
            UpdateTXSpectrumDisplayVars();

            if (chkDisplayAVG.Checked)
            {
                chkDisplayAVG.BackColor = button_selected_color;
            }
            else
            {
                chkDisplayAVG.BackColor = SystemColors.Control;
            }
            RX1AVGToolStripMenuItem.Checked = chkDisplayAVG.Checked;
        }

        private void chkDisplayPeak_CheckedChanged(object sender, System.EventArgs e)
        {
            //MW0LGE_21 not used
            specRX.GetSpecRX(0).PeakOn = chkDisplayPeak.Checked;
            UpdateRXSpectrumDisplayVars();
            specRX.GetSpecRX(cmaster.inid(1, 0)).PeakOn = chkDisplayPeak.Checked;
            UpdateTXSpectrumDisplayVars();

            if (chkDisplayPeak.Checked)
            {
                chkDisplayPeak.BackColor = button_selected_color;
            }
            else
            {
                chkDisplayPeak.BackColor = SystemColors.Control;
            }
            RX1PeakToolStripMenuItem.Checked = chkDisplayPeak.Checked;
        }

        private void updateVFOFreqs(bool tx, bool isTune = false)
        {
            if (!RX2Enabled || !tx)
            {
                if (tx)
                {
                    if (PSState || (!VFOATX && VFOBTX))
                    {
                        txtVFOAFreq_LostFocus(this, EventArgs.Empty); //[2.10.1.0] MW0LGE added to fix issue when in spit single rx, rit/xit would not be applied correctly on mox
                        txtVFOBFreq_LostFocus(this, EventArgs.Empty);
                    }
                    else if (VFOATX && !VFOBTX)
                        txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                }
                else
                {
                    txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                    txtVFOBFreq_LostFocus(this, EventArgs.Empty);
                }
            }
            else
            {
                if (PSState)
                {
                    txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                    txtVFOBFreq_LostFocus(this, EventArgs.Empty);
                }
                else if (tx)
                {
                    if (!VFOATX && VFOBTX)
                        txtVFOBFreq_LostFocus(this, EventArgs.Empty);
                    else if (VFOATX && !VFOBTX)
                        txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                }
            }
        }

        private MeterTXMode old_meter_tx_mode_before_tune;
        private DSPMode old_dsp_mode;
        private async void chkTUN_CheckedChanged(object sender, System.EventArgs e)
        {
            bool oldTune = tuning; //MW0LGE_21k9d

            if (chkTUN.Checked)
            {
                if (!PowerOn)
                {
                    MessageBox.Show("Power must be on to turn on the Tune function.",
                        "Power is off",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                    chkTUN.Checked = false;
                    return;
                }

                //MW0LGE_21a
                // stop twotone if currently running
                if (SetupForm.TestIMD || chk2TONE.Checked)
                {
                    // remove the handler then re-add back after
                    // as we need to get this to happen right now
                    chk2TONE.CheckedChanged -= new System.EventHandler(chk2TONE_CheckedChanged);
                    chk2TONE.Checked = false;
                    chk2TONE_CheckedChanged(this, EventArgs.Empty); // do now
                    chk2TONE.CheckedChanged += new System.EventHandler(chk2TONE_CheckedChanged);
                    await Task.Delay(300);
                }
                //

                tuning = true;                                                  // used for a few things
                chkTUN.BackColor = button_selected_color;

                old_meter_tx_mode_before_tune = current_meter_tx_mode;
                if (current_meter_tx_mode != tune_meter_tx_mode)                // switch meter mode to power
                {
                    CurrentMeterTXMode = tune_meter_tx_mode;
                    comboMeterTXMode_SelectedIndexChanged(this, EventArgs.Empty);
                }

                switch (Audio.TXDSPMode)                                        // put tone in opposite sideband
                {
                    case DSPMode.LSB:
                    case DSPMode.CWL:
                    case DSPMode.DIGL:
                        radio.GetDSPTX(0).TXPostGenToneFreq = -cw_pitch;
                        break;
                    default:
                        radio.GetDSPTX(0).TXPostGenToneFreq = +cw_pitch;
                        break;
                }

                radio.GetDSPTX(0).TXPostGenToneMag = 0.99999;
                radio.GetDSPTX(0).TXPostGenMode = 0;
                radio.GetDSPTX(0).TXPostGenRun = 1;

                // remember old power //MW0LGE_22b
                if (_tuneDrivePowerSource == DrivePowerSource.FIXED)
                    PreviousPWR = ptbPWR.Value;
                // set power
                int new_pwr = SetPowerUsingTargetDBM(out bool bUseConstrain, out double targetdBm, true, true, false);
                //
                if (_tuneDrivePowerSource == DrivePowerSource.FIXED)
                {
                    PWRSliderLimitEnabled = false;
                    PWR = new_pwr;
                }
                //          

                old_dsp_mode = radio.GetDSPTX(0).CurrentDSPMode;                // save current mode
                switch (old_dsp_mode)
                {
                    case DSPMode.CWL:
                        CWFWKeyer = false;
                        Audio.CurrentAudioState1 = Audio.AudioState.DTTSP;      // for CAT, apparently
                        Audio.TXDSPMode = DSPMode.LSB;                          // set a non-CW mode of the same sex
                        radio.GetDSPTX(0).CurrentDSPMode = DSPMode.LSB;         // do that here too
                        break;
                    case DSPMode.CWU:
                        CWFWKeyer = false;
                        Audio.CurrentAudioState1 = Audio.AudioState.DTTSP;
                        Audio.TXDSPMode = DSPMode.USB;
                        radio.GetDSPTX(0).CurrentDSPMode = DSPMode.USB;
                        break;
                }

                if (andromeda_cat_enabled && aries_cat_enabled &&
                   (aries_ant1_enabled || aries_ant2_enabled || aries_ant3_enabled))
                {
                    ATUTunetokenSource = new CancellationTokenSource();
                    ATUTunetoken = ATUTunetokenSource.Token;
                    await Task.Run(() => ATUTune(ATUTunetoken), ATUTunetoken);
                }

                chkMOX.Checked = true;

                await Task.Delay(100); // MW0LGE_21k8
                // go for it
                if (!_mox)
                {
                    chkTUN.Checked = false;
                    return;
                }
                // MW0LGE_21k8 moved below mox
                updateVFOFreqs(chkTUN.Checked, true);

                _current_ptt_mode = PTTMode.MANUAL;
                manual_mox = true;

                NetworkIO.SetUserOut0(1);       // why this?? CHECK
                NetworkIO.SetUserOut2(1);

                if (apollopresent && apollo_tuner_enabled)
                    NetworkIO.EnableApolloAutoTune(1);
            }
            else
            {
                chkMOX.Checked = false;                                         // we're done
                await Task.Delay(100);
                radio.GetDSPTX(0).TXPostGenRun = 0;
                chkTUN.BackColor = SystemColors.Control;

                switch (old_dsp_mode)                                           // restore old mode if it was changed
                {
                    case DSPMode.CWL:
                    case DSPMode.CWU:
                        radio.GetDSPTX(0).CurrentDSPMode = old_dsp_mode;
                        Audio.TXDSPMode = old_dsp_mode;
                        CWFWKeyer = true;
                        break;
                }
                tuning = false;

                updateVFOFreqs(chkTUN.Checked, true);

                if (apollopresent)
                    NetworkIO.EnableApolloAutoTune(0);

                //MW0LGE_22b
                if (_tuneDrivePowerSource == DrivePowerSource.FIXED)
                {
                    PWRSliderLimitEnabled = true;
                    PWR = PreviousPWR;
                }

                if (current_meter_tx_mode != old_meter_tx_mode_before_tune) //MW0LGE_21j
                    CurrentMeterTXMode = old_meter_tx_mode_before_tune;

                NetworkIO.SetUserOut0(0);      // why this?? CHECK
                NetworkIO.SetUserOut2(0);

                manual_mox = false;

                if (ATUTunetokenSource != null &&
                    ATUTunetokenSource.IsCancellationRequested == false)
                {
                    ATUTunetokenSource.Cancel();
                }
            }

            AndromedaIndicatorCheck(EIndicatorActions.eINTune, false, chkTUN.Checked);
            if (AriesCATEnabled)
                SetAriesTuneState(chkTUN.Checked);              // G8NJJ tell ARIES that tune is active

            setupTuneDriveSlider(); // MW0LGE_22b

            if (oldTune != tuning) TuneChangedHandlers?.Invoke(1, oldTune, tuning); //MW0LGE_21kd9 // just rx1
        }
        public bool PWRSliderLimitEnabled
        {
            get { return ptbPWR.LimitEnabled; }
            set { ptbPWR.LimitEnabled = value; }
        }

        private CancellationTokenSource ATUTunetokenSource;
        private CancellationToken ATUTunetoken;
        private static readonly AsyncLock _mutex = new AsyncLock(); // AsyncLock class EOF
        private async void ATUTune(CancellationToken t)
        {
            using (await _mutex.LockAsync())
            {
                if (t.IsCancellationRequested)
                {
                    NetworkIO.ATU_Tune(1); // reset line to high state
                }
                else
                {
                    try
                    {
                        NetworkIO.ATU_Tune(0); // send ATU low to start auto tune
                        await Task.Delay(1000, t);
                        NetworkIO.ATU_Tune(1); // reset line to high state
                    }
                    catch (OperationCanceledException)
                    {
                        NetworkIO.ATU_Tune(1); // reset line to high state
                    }
                }
            }
        }

        private void comboTuneMode_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            if (comboTuneMode.Focused)
                btnHidden.Focus();
        }

        private void HideFocus(object sender, EventArgs e)
        {
            btnHidden.Focus();
        }

        private void textbox_GotFocus(object sender, EventArgs e)
        {
            SetFocusMaster(false);
        }

        private void textbox_LostFocus(object sender, EventArgs e)
        {
            SetFocusMaster(true);
        }

        private void combo_OpenDropDown(object sender, EventArgs e)
        {
            SetFocusMaster(false);
        }

        private void combo_CloseDropDown(object sender, EventArgs e)
        {
            SetFocusMaster(true);
        }

        private void chkVFOLock_CheckedChanged(object sender, System.EventArgs e)
        {
            if (chkVFOLock.Checked == VFOALock) return;
            VFOALock = chkVFOLock.Checked;
            //if (chkVFOLock.Checked == true)//[2.10.3.6]MW0LGE moved this to vfoalock property
            //    lblLockLabel.BackColor = System.Drawing.Color.Blue;
            //else
            //    lblLockLabel.BackColor = System.Drawing.Color.Transparent;
            //AndromedaIndicatorCheck(EIndicatorActions.eINVFOLock, true, chkVFOLock.Checked); 
        }

        private void chkVFOBLock_CheckedChanged(object sender, EventArgs e)
        {
            if (chkVFOBLock.Checked == VFOBLock) return;
            VFOBLock = chkVFOBLock.Checked;
            //if (chkVFOBLock.Checked == true)//[2.10.3.6]MW0LGE moved this to vfoblock property
            //    lblRX2LockLabel.BackColor = System.Drawing.Color.Blue;
            //else
            //    lblRX2LockLabel.BackColor = System.Drawing.Color.Transparent;
            //AndromedaIndicatorCheck(EIndicatorActions.eINVFOLock, false, chkVFOBLock.Checked);
        }
        private void repopulateForms()
        {
            if (bandPopupForm != null) bandPopupForm.RepopulateForm();
            if (modePopupForm != null) modePopupForm.RepopulateForm();
            if (filterPopupForm != null) filterPopupForm.RepopulateForm();
        }
        public void BandPanelVisible(bool all_hidden = false)
        {
            if (all_hidden)
            {
                //rx1 done by this
                setBandPanelVisible(false, false, false, true);
                //rx2
                lblRX2Band.Visible = false;
                comboRX2Band.Visible = false;
                return;
            }

            //rx1 done by this
            setBandPanelVisible(_bands_GEN_selected, _bands_HF_selected, _bands_VHF_selected, true);
            //rx2
            lblRX2Band.Visible = !LegacyItemController.HideBands;
            comboRX2Band.Visible = !LegacyItemController.HideBands;
        }
        public void ModePanelVisible(bool visible)
        {
            panelMode.Visible = visible;

            //rx2
            panelRX2Mode.Visible = visible;
        }
        public void VFOAVisible(bool visible)
        {
            grpVFOA.Visible = visible;
        }
        public void VFOBVisible(bool visible)
        {
            grpVFOB.Visible = visible;
        }
        public void VFOSyncVisible(bool visible)
        {
            grpVFOBetween.Visible = visible;
        }
        public void FilterPanelVisible(bool visible)
        {
            // at the moment, can only hide controls, as have not implemented the sliders in the meter control
            radFilter1.Visible = visible;
            radFilter2.Visible = visible;
            radFilter3.Visible = visible;
            radFilter4.Visible = visible;
            radFilter5.Visible = visible;
            radFilter6.Visible = visible;
            radFilter7.Visible = visible;
            radFilter8.Visible = visible;
            radFilter9.Visible = visible;
            radFilter10.Visible = visible;
            radFilterVar1.Visible = visible;
            radFilterVar2.Visible = visible;

            //rx2
            radRX2Filter1.Visible = visible;
            radRX2Filter2.Visible = visible;
            radRX2Filter3.Visible = visible;
            radRX2Filter4.Visible = visible;
            radRX2Filter5.Visible = visible;
            radRX2Filter6.Visible = visible;
            radRX2Filter7.Visible = visible;
            radRX2FilterVar1.Visible = visible;
            radRX2FilterVar2.Visible = visible;
        }
        public void ExtendPanelDisplaySizeRight(bool expand)
        {
            if (IsCollapsedView && !IsExpandedView) // to be sure to be sure
            {
                //do nothing
            }
            else if (IsExpandedView && !IsCollapsedView)
            {
                if (expand)
                {
                    int h = panelDisplay.Size.Height;
                    int w = this.ClientSize.Width - gr_display_basis.X - 8;

                    panelDisplay.Size = new Size(w, h);
                }
                else
                    panelDisplay.Size = new Size(gr_display_size_basis.Width + h_delta, panelDisplay.Size.Height);
            }
        }
        public void ExtendPanelDisplaySizeTop(bool expand)
        {
            if (IsCollapsedView && !IsExpandedView) // to be sure to be sure
            {
                //do nothing
            }
            else if (IsExpandedView && !IsCollapsedView)
            {
                if (expand)
                {
                    Point old_loc = new Point(panelDisplay.Location.X, panelDisplay.Location.Y);
                    panelDisplay.Location = new Point(gr_display_basis.X, menuStrip1.Height);

                    int h = panelDisplay.Size.Height + (old_loc.Y - panelDisplay.Location.Y);
                    int w = panelDisplay.Size.Width;

                    panelDisplay.Size = new Size(w, h);
                }
                else
                {
                    panelDisplay.Location = gr_display_basis;
                    panelDisplay.Size = new Size(panelDisplay.Size.Width, gr_display_size_basis.Height + v_delta);
                }
            }
        }
        private void setBandPanelVisible(bool gen, bool hf, bool vhf, bool force = false)
        {
            //[2.10.3.6]MW0LGE reimplemented all this including repopulateForms
            // can only be one true, should have an enum.. todo
            if(!force)
            {
                if (gen && _bands_GEN_selected) return;
                if (hf && _bands_HF_selected) return;
                if (vhf && _bands_VHF_selected) return;
            }

            if (gen)
            {
                hf = false;
                vhf = false;
            }
            else if(hf)
            {
                gen = false;
                vhf = false;
            }
            else if (vhf)
            {
                gen = false;
                hf = false;
            }
            //

            bool all_off = !(gen || hf || vhf);

            if (all_off)
            {
                panelBandGEN.Visible = false;
                panelBandHF.Visible = false;
                panelBandVHF.Visible = false;
            }
            else
            {
                panelBandGEN.Visible = gen && !LegacyItemController.HideBands;
                panelBandHF.Visible = hf && !LegacyItemController.HideBands;
                panelBandVHF.Visible = vhf && !LegacyItemController.HideBands;
            }

            if (!all_off) // if all disabled, then do nothing with the state. This is probably done when andromeda button bar is shown to hide everything
            {
                bool old_gen = _bands_GEN_selected;
                bool old_hf = _bands_HF_selected;
                bool old_vhf = _bands_VHF_selected;

                _bands_GEN_selected = gen;
                _bands_HF_selected = hf;
                _bands_VHF_selected = vhf;

                if (old_gen != _bands_GEN_selected || old_hf != _bands_HF_selected || old_vhf != _bands_VHF_selected)
                    BandPanelChangeHandlers?.Invoke(1, _bands_GEN_selected, _bands_HF_selected, _bands_VHF_selected);
            }
        }
        private void btnBandVHF_Click(object sender, System.EventArgs e)
        {
            setBandPanelVisible(false, false, true);

            //MW0LGE_22b re-instated this. It is such a bad way to get the band bars to redraw, but no desire to rework compressed view
            if (collapsedDisplay)
                CollapseDisplay();

            lblRX1MuteVFOA.SendToBack();
            lblRX1APF.SendToBack();
            repopulateForms();
        }

        private void btnBandHF_Click(object sender, System.EventArgs e)
        {
            setBandPanelVisible(false, true, false);

            //MW0LGE_22b re-instated this. It is such a bad way to get the band bars to redraw, but no desire to rework compressed view
            if (collapsedDisplay)
                CollapseDisplay();

            lblRX1MuteVFOA.BringToFront();
            lblRX1APF.BringToFront();
            repopulateForms();
        }

        private void btnBandGEN_Click(object sender, EventArgs e) // ke9ns add hf screen click on GEN button
        {
            setBandPanelVisible(true, false, false);

            //MW0LGE_22b re-instated this. It is such a bad way to get the band bars to redraw, but no desire to rework compressed view
            if (collapsedDisplay)
                CollapseDisplay();

            lblRX1MuteVFOA.SendToBack();
            lblRX1APF.SendToBack();
            repopulateForms();
        }
        //
        public bool BandGENSelected
        {
            get { return _bands_GEN_selected; }
            set
            {
                //_bands_GEN_selected = value;
                //if (_bands_GEN_selected)
                //    btnBandGEN_Click(this, EventArgs.Empty);
                if(value)
                    setBandPanelVisible(true, false, false);
            }
        }
        public bool BandHFSelected
        {
            get { return _bands_HF_selected; }
            set
            {
                //_bands_HF_selected = value;
                //if (_bands_HF_selected)
                //    btnBandHF_Click(this, EventArgs.Empty);
                if (value)
                    setBandPanelVisible(false, true, false);
            }
        }
        public bool BandVHFSelected
        {
            get { return _bands_VHF_selected; }
            set
            {
                //_bands_VHF_selected = value;
                //if (_bands_VHF_selected)
                //    btnBandVHF_Click(this, EventArgs.Empty);
                if (value)
                    setBandPanelVisible(false, false, true);
            }
        }
        //
        private void udFilterLow_LostFocus(object sender, EventArgs e)
        {
            udFilterLow_ValueChanged(sender, e);
        }

        private void udFilterHigh_LostFocus(object sender, EventArgs e)
        {
            udFilterHigh_ValueChanged(sender, e);
        }

        private void udRIT_LostFocus(object sender, EventArgs e)
        {
            udRIT_ValueChanged(sender, e);
        }

        private void udXIT_LostFocus(object sender, EventArgs e)
        {
            udXIT_ValueChanged(sender, e);
        }

        private void btnChangeTuneStepSmaller_Click(object sender, System.EventArgs e)
        {
            ChangeTuneStepDown();
        }

        private void btnChangeTuneStepLarger_Click(object sender, System.EventArgs e)
        {
            ChangeTuneStepUp();
        }

        private void comboTXProfile_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            if (IsSetupFormNull || initializing ||
                rx1_dsp_mode == DSPMode.DIGL ||
                 rx1_dsp_mode == DSPMode.DIGU ||
                 rx1_dsp_mode == DSPMode.FM ||
                rx1_dsp_mode == DSPMode.AM ||
                rx1_dsp_mode == DSPMode.SAM) return;
            SetupForm.TXProfile = comboTXProfile.Text;

            if (comboTXProfile.Focused) btnHidden.Focus();
        }

        private void comboDigTXProfile_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            if (IsSetupFormNull || initializing ||
                (rx1_dsp_mode != DSPMode.DIGL &&
                rx1_dsp_mode != DSPMode.DIGU)) return;
            SetupForm.TXProfile = comboDigTXProfile.Text;

            if (comboDigTXProfile.Focused) btnHidden.Focus();
        }

        private void comboFMTXProfile_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (IsSetupFormNull || initializing ||
                rx1_dsp_mode != DSPMode.FM) return;
            SetupForm.TXProfile = comboFMTXProfile.Text;

            if (comboFMTXProfile.Focused) btnHidden.Focus();
        }

        //MW0LGE_21j used by setup form whenever a TX profile is loaded
        //When a digimode is selected, a number of settings are disabled.
        //These are restored if leaving a digimode.
        public void LoadedTXProfile()
        {
            if (IsSetupFormNull) return;

            if (rx1_dsp_mode == DSPMode.DIGL || rx1_dsp_mode == DSPMode.DIGU)
            {
                SetDigiMode(1, DigiMode.DigiModeSettingState.dmssStore, true); // store bunch of profile settings
                SetDigiMode(1, DigiMode.DigiModeSettingState.dmssTurnOffSettings, true); // set it into digi mode
            }
            else
            {
                if (rx1dm != null && (rx1dm.Mode == DigiMode.DigiModeSettingState.dmssTurnOffSettings || rx1dm.Mode == DigiMode.DigiModeSettingState.dmssStore))
                {
                    SetDigiMode(1, DigiMode.DigiModeSettingState.dmssRecall, true); // restore those profile settings, may be case where not initialised
                }
            }

            if (rx2_dsp_mode == DSPMode.DIGL || rx2_dsp_mode == DSPMode.DIGU)
            {
                SetDigiMode(2, DigiMode.DigiModeSettingState.dmssStore, true); // store bunch of profile settings
                SetDigiMode(2, DigiMode.DigiModeSettingState.dmssTurnOffSettings, true); // set it into digi mode
            }
            else
            {
                if (rx2dm != null && (rx2dm.Mode == DigiMode.DigiModeSettingState.dmssTurnOffSettings || rx2dm.Mode == DigiMode.DigiModeSettingState.dmssStore))
                {
                    SetDigiMode(2, DigiMode.DigiModeSettingState.dmssRecall, true); // restore those profile settings, may be case where not initialised
                }
            }
        }

        private void comboAMTXProfile_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (IsSetupFormNull || initializing ||
            (rx1_dsp_mode != DSPMode.AM &&
            rx1_dsp_mode != DSPMode.SAM)) return;
            SetupForm.TXProfile = comboAMTXProfile.Text;

            if (comboAMTXProfile.Focused) btnHidden.Focus();
        }

        private void chkShowTXFilter_CheckedChanged(object sender, System.EventArgs e)
        {
            Display.DrawTXFilter = chkShowTXFilter.Checked;
        }

        private void chkVACStereo_CheckedChanged(object sender, System.EventArgs e)
        {
            if (!IsSetupFormNull)
            {
                if (!(chkRX2.Checked && chkVAC2.Checked && chkVFOBTX.Checked))
                {
                    SetupForm.VACStereo = chkVACStereo.Checked;
                    vac_stereo = chkVACStereo.Checked;
                }
                else
                {
                    SetupForm.VAC2Stereo = chkVACStereo.Checked;
                    vac2_stereo = chkVACStereo.Checked;
                }
            }
        }

        private void chkCWIambic_CheckedChanged(object sender, System.EventArgs e)
        {
            if (!IsSetupFormNull) SetupForm.CWIambic = chkCWIambic.Checked;
        }

        private void chkCWSidetone_CheckedChanged(object sender, System.EventArgs e)
        {
            if (!IsSetupFormNull) SetupForm.CWDisableMonitor = chkCWSidetone.Checked;
        }

        private void udCWPitch_ValueChanged(object sender, System.EventArgs e)
        {
            if (!IsSetupFormNull) SetupForm.CWPitch = (int)udCWPitch.Value;
            if (udCWPitch.Focused) btnHidden.Focus();
        }

        private void comboVACSampleRate_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            if (!IsSetupFormNull)
            {
                // G8NJJ: change so that it sets the correct VAC 1 or 2 sample rate in setup
                if (!(chkRX2.Checked && chkVAC2.Checked && chkVFOBTX.Checked))
                    SetupForm.VACSampleRate = comboVACSampleRate.Text;
                else
                    SetupForm.VAC2SampleRate = comboVACSampleRate.Text;
            }
            if (comboVACSampleRate.Focused) btnHidden.Focus();


        }

        private void chkX2TR_CheckedChanged(object sender, System.EventArgs e)
        {
            ClickTuneRX2Display = chkX2TR.Checked;

            //MW0LGE_21d
            if (m_bLinkCTUNonVFOSync && chkVFOSync.Checked)
            {
                chkFWCATU.Checked = chkX2TR.Checked;
            }

            if (chkX2TR.Checked == true)
                lblRX2CtunLabel.BackColor = System.Drawing.Color.Blue;
            else
                lblRX2CtunLabel.BackColor = System.Drawing.Color.Transparent;

            txtVFOBFreq_LostFocus(this, EventArgs.Empty);
            AndromedaIndicatorCheck(EIndicatorActions.eINCTune, false, chkX2TR.Checked);

            setupZTBButton(); //MW0LGE_21k9
        }

        private void chkShowTXCWFreq_CheckedChanged(object sender, System.EventArgs e)
        {
            Display.DrawTXCWFreq = chkShowTXCWFreq.Checked;
        }

        private void chkShowCWZero_CheckedChanged(object sender, System.EventArgs e)
        {
            Display.ShowCWZeroLine = chkShowCWZero.Checked;
        }

        private void udCWBreakInDelay_ValueChanged(object sender, System.EventArgs e)
        {
            if (!IsSetupFormNull) SetupForm.BreakInDelay = (int)udCWBreakInDelay.Value;
            if (udCWBreakInDelay.Focused)
                btnHidden.Focus();
        }

        private void udCWBreakInDelay_LostFocus(object sender, System.EventArgs e)
        {
            udCWBreakInDelay_ValueChanged(sender, e);
        }

        private void chkCWAPFEnabled_CheckedChanged(object sender, System.EventArgs e)
        {
            if (!IsSetupFormNull)
            {
                if (SetupForm.RX1APFControls)
                    SetupForm.RX1APFEnable = chkCWAPFEnabled.Checked;
                if (SetupForm.RX1subAPFControls)
                    SetupForm.RX1subAPFEnable = chkCWAPFEnabled.Checked;
                if (SetupForm.RX2APFControls)
                    SetupForm.RX2APFEnable = chkCWAPFEnabled.Checked;
                else SetupForm.RX2APFEnable = SetupForm.RX2APFEnable;

                if (chkCWAPFEnabled.Checked) cat_apf_status = 1; //-W2PA Added to enable extended CAT control
                else cat_apf_status = 0;
            }
        }

        private void ptbCWAPFFreq_Scroll(object sender, System.EventArgs e)
        {
            if (!IsSetupFormNull)
            {
                if (SetupForm.RX1APFControls)
                    SetupForm.RX1APFFreq = ptbCWAPFFreq.Value;
                if (SetupForm.RX1subAPFControls)
                    SetupForm.RX1subAPFFreq = ptbCWAPFFreq.Value;
                if (SetupForm.RX2APFControls)
                    SetupForm.RX2APFFreq = ptbCWAPFFreq.Value;
            }
            lblCWAPFTune.Text = "Tune:  " + ptbCWAPFFreq.Value.ToString();
            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbCWAPFFreq.Focus();
            }
        }

        private void ptbCWAPFBandwidth_Scroll(object sender, System.EventArgs e)
        {
            if (!IsSetupFormNull)
            {
                if (SetupForm.RX1APFControls)
                    SetupForm.RX1APFBandwidth = ptbCWAPFBandwidth.Value;
                if (SetupForm.RX1subAPFControls)
                    SetupForm.RX1subAPFBandwidth = ptbCWAPFBandwidth.Value;
                if (SetupForm.RX2APFControls)
                    SetupForm.RX2APFBandwidth = ptbCWAPFBandwidth.Value;
            }
            lblCWAPFBandwidth.Text = "Bandwidth:  " + ptbCWAPFBandwidth.Value.ToString();

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbCWAPFBandwidth.Focus();
            }
        }

        private void ptbCWAPFGain_Scroll(object sender, System.EventArgs e)
        {
            if (!IsSetupFormNull)
            {
                if (SetupForm.RX1APFControls)
                    SetupForm.RX1APFGain = ptbCWAPFGain.Value;
                if (SetupForm.RX1subAPFControls)
                    SetupForm.RX1subAPFGain = ptbCWAPFGain.Value;
                if (SetupForm.RX2APFControls)
                    SetupForm.RX2APFGain = ptbCWAPFGain.Value;
            }
            double gain_value = Math.Round(ptbCWAPFGain.Value / 10.0, 0);

            lblCWAPFGain.Text = "Gain:  " + gain_value.ToString();

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbCWAPFGain.Focus();
            }
        }

        public void DisableDAX()
        {
            // disable VAC on console. dax_audio_enum = false by default
            chkVAC1.Checked = false;
            chkVAC1.Enabled = false;
            chkVAC2.Checked = false;
            chkVAC2.Enabled = false;
        }

        public void EnableDAX()
        {
            // enable VAC on console
            chkVAC1.Enabled = true;
            chkVAC2.Enabled = false;  // set to true later if RX2 installed 
        }

        private void chkVAC1_CheckedChanged(object sender, System.EventArgs e)
        {
            bool bSync = !IsSetupFormNull && Common.ShiftKeyDown;

            if (!bSync)
            {
                if (!IsSetupFormNull) SetupForm.VACEnable = chkVAC1.Checked;
                if (chkVAC1.Checked)
                {
                    chkVAC1.BackColor = button_selected_color;

                    if (chkVOX.Checked)
                    {
                        chkVOX.Checked = false;
                        if (!IsSetupFormNull) SetupForm.VOXEnable = chkVOX.Checked;
                        Audio.VOXActive = false;
                        chkVOX.BackColor = SystemColors.Control;
                    }
                }
                else chkVAC1.BackColor = SystemColors.Control;
            }
            else //MW0LGE_22b
            {
                if (!IsSetupFormNull) SetupForm.VACEnable = chkVAC1.Checked;
                if (!IsSetupFormNull) SetupForm.VAC2Enable = chkVAC1.Checked;

                if (chkVAC1.Checked)
                {
                    chkVAC1.BackColor = button_selected_color;
                    chkVAC2.BackColor = button_selected_color;

                    if (chkVOX.Checked)
                    {
                        chkVOX.Checked = false;
                        if (!IsSetupFormNull) SetupForm.VOXEnable = chkVOX.Checked;
                        Audio.VOXActive = false;
                        chkVOX.BackColor = SystemColors.Control;
                    }
                }
                else
                {
                    chkVAC1.BackColor = SystemColors.Control;
                    chkVAC2.BackColor = SystemColors.Control;
                }

            }
        }

        private void chkVAC2_CheckedChanged(object sender, EventArgs e)
        {
            if (!IsSetupFormNull) SetupForm.VAC2Enable = chkVAC2.Checked;

            if (chkVFOBTX.Checked)
            {
                if (chkVAC2.Checked)
                {
                    ptbVACRXGain.Value = vac2_rx_gain;
                    ptbVACRXGain_Scroll(this, EventArgs.Empty);

                    ptbVACTXGain.Value = vac2_tx_gain;
                    ptbVACTXGain_Scroll(this, EventArgs.Empty);

                    comboVACSampleRate.Text = vac2_sample_rate;

                    chkVACStereo.Checked = vac2_stereo;
                }
                else
                {
                    ptbVACRXGain.Value = vac_rx_gain;
                    ptbVACRXGain_Scroll(this, EventArgs.Empty);

                    ptbVACTXGain.Value = vac_tx_gain;
                    ptbVACTXGain_Scroll(this, EventArgs.Empty);

                    comboVACSampleRate.Text = vac_sample_rate;

                    chkVACStereo.Checked = vac_stereo;
                }
            }

            if (chkVAC2.Checked)
            {
                chkVAC2.BackColor = button_selected_color;

                if (chkVOX.Checked)
                {
                    chkVOX.Checked = false;
                    if (!IsSetupFormNull) SetupForm.VOXEnable = chkVOX.Checked;
                    Audio.VOXActive = false;
                    chkVOX.BackColor = SystemColors.Control;
                }
            }
            else chkVAC2.BackColor = SystemColors.Control;
        }

        private void chkRXEQ_CheckedChanged(object sender, System.EventArgs e)
        {
            if (chkRXEQ.Checked) chkRXEQ.BackColor = button_selected_color;
            else chkRXEQ.BackColor = SystemColors.Control;
            if (EQForm != null) EQForm.RXEQEnabled = chkRXEQ.Checked;
        }

        private bool _oldTXEQ = false; // it is false in frm design
        private void chkTXEQ_CheckedChanged(object sender, System.EventArgs e)
        {
            if (chkTXEQ.Checked) chkTXEQ.BackColor = button_selected_color;
            else chkTXEQ.BackColor = SystemColors.Control;
            if (EQForm != null) EQForm.TXEQEnabled = chkTXEQ.Checked;

            if (_oldTXEQ != chkTXEQ.Checked)
            {
                EQChangedHandlers?.Invoke(_oldTXEQ, chkTXEQ.Checked);
                _oldTXEQ = chkTXEQ.Checked;
            }
        }

        #endregion

        #region VFO Events

        private enum TuneLocation
        {
            VFOA = 0,
            VFOB,
            VFOASub,
            DisplayBottom,
            DisplayTop,
            Other,
        }

        private TuneLocation TuneHitTest(int x, int y)
        {
            int left, right, top, bottom;
            left = grpVFOA.Left + txtVFOAFreq.Left;
            right = left + txtVFOAFreq.Width;
            top = grpVFOA.Top + txtVFOAFreq.Top;
            bottom = top + txtVFOAFreq.Height;
            // MW0LGE in collapsed mode this is only true if we are showing rx1, technically correct to add similar to vfoB, but not required as fall through will handle it
            if ((!collapsedDisplay && x > left && x < right && y > top && y < bottom) || (collapsedDisplay && show_rx1 && x > left && x < right && y > top && y < bottom))
                return TuneLocation.VFOA;

            left = grpVFOB.Left + txtVFOBFreq.Left;
            right = left + txtVFOBFreq.Width;
            top = grpVFOB.Top + txtVFOBFreq.Top;
            bottom = top + txtVFOBFreq.Height;
            if (x > left && x < right && y > top && y < bottom)
                return TuneLocation.VFOB;

            left = grpVFOA.Left + txtVFOABand.Left;
            right = left + txtVFOABand.Width;
            top = grpVFOA.Top + txtVFOABand.Top;
            bottom = top + txtVFOABand.Height;
            if (x > left && x < right && y > top && y < bottom)
                return TuneLocation.VFOASub;

            left = panelDisplay.Left + picDisplay.Left;
            right = left + picDisplay.Width;
            top = panelDisplay.Top + picDisplay.Top + picDisplay.Height / 2;
            bottom = top + picDisplay.Height / 2;
            if (x > left && x < right && y > top && y < bottom)
                return TuneLocation.DisplayBottom;

            left = panelDisplay.Left + picDisplay.Left;
            right = left + picDisplay.Width;
            top = panelDisplay.Top + picDisplay.Top;
            bottom = top + picDisplay.Height;
            if (x > left && x < right && y > top && y < bottom)
                return TuneLocation.DisplayTop;

            return TuneLocation.Other;
        }

        private void Console_MouseWheel(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (this.ActiveControl is PrettyTrackBar)
            {
                btnHidden.Focus();
                return;
            }

            if (this.ActiveControl is TextBoxTS ||
                this.ActiveControl is NumericUpDownTS ||
                this.ActiveControl is TrackBarTS ||
                this.ActiveControl is PrettyTrackBar)
            {
                // MW0LGE Console_KeyPress(this, new KeyPressEventArgs((char)Keys.Enter));
                // console keypress does nothing but buttonfocus
                btnHidden.Focus();
                return;
            }

            if (ClientRectangle.Contains(Form.MousePosition.X - Location.X,
                                        Form.MousePosition.Y - Location.Y))
                ToggleFocusMasterTimer();

            if (e.Delta == 0) return;
            int num_steps = 0;
            if (WheelReverse)
                num_steps = (e.Delta > 0 ? -1 : 1);	// 1 per click
            else num_steps = (e.Delta > 0 ? 1 : -1);	// 1 per click
            //int numberToMove = e.Delta / 120;	// 1 per click

            // MW0LGE before all, handle the notch size change
            if (SelectedNotch != null && num_steps != 0)
            {
                notchMouseWheel(num_steps);
                return;
            }

            if (vfo_char_width == 0)
                GetVFOCharWidth();

            if (num_steps == 0) return;
            int step = CurrentTuneStepHz;
            if (Common.ShiftKeyDown && step >= 10) step /= 10; //MW0LGE

            switch (TuneHitTest(e.X, e.Y))
            {
                case TuneLocation.VFOA:
                    if (_mox) return;
                    double freq = VFOAFreq;// double.Parse(txtVFOAFreq.Text); //[2.10.3.6]freq changes.
                    double mult = 1000.0;
                    int right = grpVFOA.Left + txtVFOAFreq.Left + txtVFOAFreq.Width;
                    if (vfoa_hover_digit < 0)
                    {
                        int x = right + 2 - (vfo_pixel_offset - 5);
                        while (x < e.X && mult > 0.0000011)
                        {
                            mult /= 10.0;
                            x += vfo_char_width;
                            if (mult == 1.0)
                                x += vfo_decimal_space;
                            else x += vfo_char_space;
                        }
                    }
                    else
                    {
                        mult = Math.Pow(10, -vfoa_hover_digit) * 1000.0;
                    }

                    if (mult <= 1.0)
                    {
                        freq += mult * num_steps;
                        VFOAFreq = freq;
                    }
                    break;

                case TuneLocation.VFOB:
                    if (_mox && VFOBTX) return;
                    freq = VFOBFreq;// double.Parse(txtVFOBFreq.Text); //[2.10.3.6]freq changes.
                    mult = 1000.0;
                    right = grpVFOB.Left + txtVFOBFreq.Left + txtVFOBFreq.Width;
                    if (vfob_hover_digit < 0)
                    {
                        int x = right + 2 - (vfo_pixel_offset - 5);
                        while (x < e.X && mult > 0.0000011)
                        {
                            mult /= 10;
                            x += vfo_char_width;
                            if (mult == 1.0)
                                x += vfo_decimal_space;
                            else x += vfo_char_space;
                        }
                    }
                    else
                    {
                        mult = Math.Pow(10, -vfob_hover_digit) * 1000.0;
                    }

                    if (mult <= 1.0)
                    {
                        freq += mult * num_steps;
                        VFOBFreq = freq;
                    }
                    break;

                case TuneLocation.VFOASub:
                    if (rx2_enabled && (chkEnableMultiRX.Checked || chkVFOSplit.Checked))
                    {
                        freq = VFOASubFreq;
                        mult = 1000.0;
                        right = grpVFOA.Left + txtVFOABand.Left + txtVFOABand.Width;
                        if (vfoa_sub_hover_digit < 0)
                        {
                            int x = right + 2 - (vfo_sub_pixel_offset - 5);
                            while (x < e.X && mult > 0.0000011)
                            {
                                mult /= 10;
                                x += vfo_sub_char_width;
                                if (mult == 1.0)
                                    x += vfo_sub_decimal_space;
                                else x += vfo_sub_char_space;
                            }
                        }
                        else
                        {
                            mult = Math.Pow(10, -vfoa_sub_hover_digit) * 1000.0;
                        }

                        if (mult <= 1.0)
                        {
                            freq += mult * num_steps;
                            VFOASubFreq = freq;
                        }
                    }
                    else
                    {
                        VFOAFreq = SnapTune(VFOAFreq, step, num_steps);
                    }
                    break;

                case TuneLocation.DisplayBottom:
                    if (rx2_enabled && chkVFOSplit.Checked && current_click_tune_mode == ClickTuneMode.VFOB && wheel_tunes_vfob)
                        VFOASubFreq = SnapTune(VFOASubFreq, step, num_steps);
                    else if (rx2_enabled || (current_click_tune_mode == ClickTuneMode.VFOB && wheel_tunes_vfob))
                        VFOBFreq = SnapTune(VFOBFreq, step, num_steps);
                    else
                        VFOAFreq = SnapTune(VFOAFreq, step, num_steps);
                    break;

                case TuneLocation.Other:
                    // MW0LGE
                    if (!m_bWheelTunesOutsideSpectral) break; // break out because we are not permitted to tune outside spectral/vfo boxes
                    goto case TuneLocation.DisplayTop;        // give me fall through c# gods
                case TuneLocation.DisplayTop:
                    // MW0LGE this was other, but now we assume it is top of spectral display
                    if (current_click_tune_mode == ClickTuneMode.VFOB && wheel_tunes_vfob)
                    {
                        if (rx2_enabled && chkVFOSplit.Checked)
                            VFOASubFreq = SnapTune(VFOASubFreq, step, num_steps);
                        else
                            VFOBFreq = SnapTune(VFOBFreq, step, num_steps);
                    }
                    else
                        if (!_mox) VFOAFreq = SnapTune(VFOAFreq, step, num_steps);
                    break;
            }
        }

        /// <summary>
        /// Calculates a "Snapped" frequency that lies on an integer multiple of the Tune Step.
        /// </summary>
        /// <param name="freq_mhz">The starting frequency in MHz</param>
        /// <param name="step_size_hz">The selected step size in Hz</param>
        /// <param name="num_steps">Indicates both the number and direction of steps.  Negative
        /// numbers indicate steps down while positive numbers indicate steps up.</param>
        /// <returns>The adjusted frequency in MHz</returns>
        public double SnapTune(double freq_mhz, int step_size_hz, int num_steps)
        {
            long freq_hz = (long)Math.Round(freq_mhz * 1e6); // convert frequency to Hz -- use long to support >4GHz
            long temp = freq_hz / step_size_hz; // do integer division to end up on a step size boundary

            // handle when starting frequency was already on a step size boundary and tuning down
            if (num_steps < 0 && freq_hz % step_size_hz != 0)
                num_steps++; // off boundary -- add one as the divide takes care of one step

            temp += num_steps; // increment by the number of steps (positive or negative

            freq_hz = temp * step_size_hz; // multiply back up to get hz
            return Math.Round(freq_hz * 1e-6, 6); // return freq in MHz
        }

        private bool m_bCATChangesCenterFreq = true;
        public bool CATChangesCenterFreq
        {
            get { return m_bCATChangesCenterFreq; }
            set { m_bCATChangesCenterFreq = value; }
        }

        private bool m_bLimitCTMouseOnly = false;
        public bool LimitCTMouseOnly
        {
            get { return m_bLimitCTMouseOnly; }
            set { m_bLimitCTMouseOnly = value; }
        }
        private bool m_bLimitCTToSpectralArea = false;
        public bool LimitCTUNToSpectralArea
        {
            get { return m_bLimitCTToSpectralArea; }
            set { m_bLimitCTToSpectralArea = value; }
        }
        private bool m_bVFOAChangedByKeys = false;  // true if frequency has been changed by pressing enter on vfo box
        private bool m_bVFOBChangedByKeys = false;
        private bool m_bVFOABandChangedByKeys = false;

        private void txtVFOAFreq_LostFocus(object sender, System.EventArgs e)
        {
            if (initializing) return;

            double dOldFreq = Math.Round(saved_vfoa_freq, 6);
            Band oldBand = RX1Band;
            DSPMode oldMode = RX1DSPMode;
            Filter oldFilter = RX1Filter;
            double oldCentreFreq = CentreFrequency;
            bool oldCtun = ClickTuneDisplay;
            int oldZoomSlider = ptbDisplayZoom.Value;

            //check if valid
            double dValue;
            if (Double.TryParse(txtVFOAFreq.Text, out dValue) == false)
            {
                // not a value
                VFOAFreq = saved_vfoa_freq;
                return;
            }
            else
            {
                // we have a valid value
                if (m_bVFOAChangedByKeys)
                {
                    m_dVFOAFreq = dValue;
                    m_bVFOAChangedByKeys = false;
                }
            }

            if (current_hpsdr_model == HPSDRModel.ANAN200D ||
                 current_hpsdr_model == HPSDRModel.ORIONMKII ||
                 current_hpsdr_model == HPSDRModel.ANAN7000D ||
                 current_hpsdr_model == HPSDRModel.ANAN8000D ||
                 current_hpsdr_model == HPSDRModel.ANAN_G2 ||
                 current_hpsdr_model == HPSDRModel.ANAN_G2_1K) UpdateDDCs(rx2_enabled);// UpdateRXADCCtrl();

            double freq = m_dVFOAFreq;

            //MW0LGE_21k8
            //override freq if using any splt split when TX'ing
            bool bUpdateVFOA = true;
            if (chkVFOSplit.Checked)
            {
                if (_mox)
                {
                    if (VFOATX && !VFOBTX) // some belts and braces, should never be able to have both
                    {
                        // use the sub freq, as we are tx'ing on A, but there is a split set
                        freq = VFOASubFreq;
                        bUpdateVFOA = false;
                    }
                    else if (!VFOATX && VFOBTX) // some belts and braces, should never be able to have both
                    {
                        // use VFOB freq
                        freq = VFOBFreq;
                        bUpdateVFOA = false;
                    }
                }
            }
            //

            if (!click_tune_display || update_centerfreq) // !!!! - G3OQD - !!!!
            {
                // used by CAT
                CentreFrequency = freq;
                update_centerfreq = false;
            }

            double passbandWidth = (Convert.ToDouble(Display.RX1FilterHigh) - Convert.ToDouble(Display.RX1FilterLow));
            double dispWidth = Convert.ToDouble(Display.RXDisplayHigh) - Convert.ToDouble(Display.RXDisplayLow);
            double dispMargin = 0.05; // Margin from display edge to start scrolling - in fraction of total display width   

            // Lock the display //-W2PA Don't freeze display if we are zoomed in too far to fit the passband
            bool bCanFitInView = passbandWidth < (dispWidth * (1.0 - 2.0 * dispMargin));

            bool bLimitToSpectral = m_bLimitCTToSpectralArea && ((m_bLimitCTMouseOnly && rx1_click_tune_drag) || !m_bLimitCTMouseOnly);

            bool bRitOk = !_mox || (_mox && VFOBTX && RX2Enabled); //[2.10.1.0] MW0LGE we can apply rit

            if (click_tune_display && bCanFitInView && ((_mox && VFOBTX && RX2Enabled) || !_mox || display_duplex)) //[2.10.1.0] MW0LGE want if moxing rx2
            {
                double rx1_osc = Math.Round(-(freq - CentreFrequency) * 1.0e6);

                double Lmargin = Convert.ToDouble(-Display.RX1FilterLow);
                double Hmargin = Convert.ToDouble(Display.RX1FilterHigh);
                if (Lmargin < 0.0) Lmargin = 0.0;
                if (Hmargin < 0.0) Hmargin = 0.0;
                double Ldisp = Convert.ToDouble(Display.RXDisplayLow) + dispWidth * dispMargin;
                double Hdisp = Convert.ToDouble(Display.RXDisplayHigh) - dispWidth * dispMargin;
                double freqJumpThresh = 0.5e6;  // definition of jumping far, e.g. with memory recall - causes a re-centering

                if (!m_bIgnoreLimitsForZTB) // MW0LGE_21k9
                {
                    if (!ClickTuneDrag)
                    {
                        if (((-rx1_osc) - Lmargin) < Ldisp || ((-rx1_osc) + Hmargin) > Hdisp) // re-center if we've jumped far
                        {
                            CentreFrequency = freq;
                            rx1_osc = 0.0;
                        }
                    }
                    else
                    {
                        if (!rx1_spectrum_tune_drag)
                        {
                            //-W2PA If we tune beyond the display limits, re-center or scroll display, and keep going.  Original code above just stops tuning at edges.
                            if (((-rx1_osc) - Lmargin) < (Ldisp - freqJumpThresh) || ((-rx1_osc) + Hmargin) > (Hdisp + freqJumpThresh)) // re-center if we've jumped far
                            {
                                CentreFrequency = freq;
                                rx1_osc = 0.0;
                            }
                            else  // not a jump - more like tuning
                            if (!bLimitToSpectral && (((-rx1_osc) - Lmargin) < Ldisp)) // scroll the spectrum display smoothly at the edge and keep going
                            {
                                double adjustFreq = Ldisp - ((-rx1_osc) - Lmargin);
                                CentreFrequency -= adjustFreq * 1e-6;
                                rx1_osc -= adjustFreq;
                            }
                            else
                            if (!bLimitToSpectral && (((-rx1_osc) + Hmargin) > Hdisp))
                            {
                                double adjustFreq = ((-rx1_osc) + Hmargin) - Hdisp;
                                CentreFrequency += adjustFreq * 1e-6;
                                rx1_osc += adjustFreq;
                            }
                        }
                    }
                }

                if (chkRIT.Checked && bRitOk)
                    rx1_osc -= (int)udRIT.Value;

                // check if we move outside sample area
                bool bBelowLow = (-rx1_osc < (-(sample_rate_rx1 * 0.92) / 2) + Lmargin);
                bool bAboveHigh = (-rx1_osc > ((sample_rate_rx1 * 0.92) / 2) - Hmargin);

                if (bBelowLow || bAboveHigh)
                {
                    double diff;

                    diff = ((sample_rate_rx1 * 0.92) / 2) - Math.Abs(rx1_osc);
                    diff = (-rx1_osc >= 0) ? -diff + Hmargin : diff - Lmargin;

                    freq -= diff * 1e-6;

                    // we have moved out of the IF
                    rx1_osc += diff;
                }
                //

                if (!m_bIgnoreLimitsForZTB)
                {
                    if (!rx1_spectrum_tune_drag && bLimitToSpectral)  // MW0LGE_21k9 repos if limited to spectral
                    {
                        //check if outside view
                        bool bOutsideViewLow = -rx1_osc < ((double)(Display.RXDisplayLow) + Lmargin);
                        bool bOutsideViewHigh = -rx1_osc > ((double)(Display.RXDisplayHigh) - Hmargin);

                        if (bOutsideViewLow || bOutsideViewHigh)
                        {
                            double diff;

                            if (bOutsideViewLow)
                                diff = -(double)(Display.RXDisplayLow) - Math.Abs(rx1_osc);
                            else
                                diff = (double)(Display.RXDisplayHigh) - Math.Abs(rx1_osc);

                            diff = (-rx1_osc >= 0) ? -diff + Hmargin : diff - Lmargin;
                            freq -= diff * 1e-6;
                            rx1_osc += diff;
                        }
                    }
                }

                radio.GetDSPRX(0, 0).RXOsc = rx1_osc; // keep tuning
                Display.FreqDiff = (int)radio.GetDSPRX(0, 0).RXOsc;
            }
            else
            {
                if (!bCanFitInView && click_tune_display && !rx1_spectrum_tune_drag)
                {
                    // if filter is off the edge of view, most likey because of high zoom
                    CentreFrequency = freq;
                }

                radio.GetDSPRX(0, 0).RXOsc = 0.0; // keep tuning
                if (rx1_dsp_mode == DSPMode.DRM)
                {
                    Display.FreqDiff = -12000;
                }
                else
                {
                     Display.FreqDiff = (int)radio.GetDSPRX(0, 0).RXOsc;
                }
            }

            if (click_tune_display && ((_mox && VFOBTX && RX2Enabled) || !_mox || display_duplex)) //[2.10.1.0] MW0LGE want this to happen if moxing on rx2
            {
                Display.VFOA = (long)(CentreFrequency * 1e6); // freeze display vfo
            }
            else
            {
                if (rx1_dsp_mode == DSPMode.DRM)
                {
                    Display.VFOA = (long)(freq * 1e6) - 12000;
                }
                else
                    Display.VFOA = (long)(freq * 1e6);
            }

            //MW0LGE_21k8
            if (bUpdateVFOA) UpdateVFOAFreq(freq.ToString("f6"));

            long cwPitchShift = 0;
            if (chkTUN.Checked && chkVFOATX.Checked && !display_duplex) // MW0LGE only if not display duplex
            {
                switch (radio.GetDSPTX(0).CurrentDSPMode)
                {
                    case DSPMode.CWL:
                    case DSPMode.LSB:
                    case DSPMode.DIGL:
                        cwPitchShift = cw_pitch;
                        break;
                    case DSPMode.CWU:
                    case DSPMode.USB:
                    case DSPMode.DIGU:
                    case DSPMode.AM:
                    case DSPMode.SAM:
                    case DSPMode.FM:
                    case DSPMode.DSB:
                        if (RX1IsOn60mChannel() && current_region == FRSRegion.US)
                            cwPitchShift = -(long)((ModeFreqOffset(rx1_dsp_mode) * 1e6) + cw_pitch);
                        else
                            cwPitchShift = -cw_pitch;
                        break;
                }
            }
            Display.VFOA += cwPitchShift;

            //MW0LGE_21k8
            if (VFOATX && chkVFOSplit.Checked)
            {
                if (_mox)
                {
                    Display.VFOASub = (long)(freq * 1e6); // freq is modified above
                }
                else
                {
                    Display.VFOASub = (long)(VFOASubFreq * 1e6); // we need to reset this
                }

                if (chkTUN.Checked && !display_duplex)
                {
                    Display.VFOASub += cwPitchShift;
                }
            }

            if (XVTRForm.XVTRFreq(freq) != rx1_xvtr_index)
                RX1XVTRIndex = XVTRForm.XVTRFreq(freq);

            if (!chkVFOSplit.Checked && !chkVFOBTX.Checked)
                tx_xvtr_index = rx1_xvtr_index;

            if (rx1_xvtr_index < 0) //in HF
            {
                int old_xvtr_index = XVTRForm.XVTRFreq(saved_vfoa_freq);
                if (old_xvtr_index >= 0 && freq >= max_freq)
                {
                    VFOAFreq = saved_vfoa_freq;
                    return;
                }
            }

            //rx
            if (rx1_xvtr_index >= 0)
            {
                RX1XVTRGainOffset = XVTRForm.GetRXGain(rx1_xvtr_index);
                VHFTRRelay = XVTRForm.GetDisablePA(tx_xvtr_index);

                if (vhf_tr_relay)
                {
                    NetworkIO.SetXVTREnable(1);
                    NetworkIO.DisablePA(1);
                }
                else
                {
                    NetworkIO.SetXVTREnable(0);
                    NetworkIO.DisablePA(0);
                }
            }

            if (rx1_xvtr_index < 0)
            {
                RX1XVTRGainOffset = 0.0f;

                if (hf_tr_relay)
                {
                    NetworkIO.DisablePA(1);
                }
                else
                {
                    NetworkIO.DisablePA(0);
                }

                if (enable_xvtr_hf)
                    NetworkIO.SetXVTREnable(1); // enable
                else
                    NetworkIO.SetXVTREnable(0); // disable
            }

            //tx
            if (last_tx_xvtr_index != tx_xvtr_index)
            {
                if (tx_xvtr_index >= 0)
                {
                    if (last_tx_xvtr_index == -1)
                        saved_rx_only = rx_only;

                    RXOnly = XVTRForm.GetRXOnly(tx_xvtr_index);
                }

                if (tx_xvtr_index < 0)
                {
                    if (last_tx_xvtr_index >= 0)
                        RXOnly = saved_rx_only;
                }

            }

            // update Band Info
            string bandInfo;
            double db_freq = freq;
            if (RX1IsIn60m() && current_region == FRSRegion.US) db_freq -= ModeFreqOffset(rx1_dsp_mode);

            if (!DB.BandText(db_freq, out bandInfo))
                txtVFOABand.BackColor = out_of_band_color;
            else
                txtVFOABand.BackColor = band_background_color;

            if (!(rx2_enabled && (chkEnableMultiRX.Checked || chkVFOSplit.Checked))) 
                txtVFOABand.Text = bandInfo;

            Band b = BandByFreq(freq, rx1_xvtr_index, current_region);
            if (b != rx1_band)
                SetRX1Band(b);

            Band old_tx_band = tx_band;
            if (!chkVFOSplit.Checked && !chkVFOBTX.Checked)
            {
                b = BandByFreq(freq, tx_xvtr_index, current_region);

                Band b1 = getTXBandWhenExtended(b, freq);
                if (b1 != tx_band)
                    SetTXBand(b1, b != b1);
            }

            Band lo_band = Band.FIRST;
            Band lo_bandb = Band.FIRST;

            // added G8NJJ for Aries ATU: see if ARIES needs a new frequency update and antenna band update
            // and at this point so that TX band has been set
            DisplayAriesRXAntenna();
            if ((AriesCATEnabled) && (chkVFOATX.Checked))
            {
                SetAriesTXFrequency(freq);
                DisplayAriesTXAntenna();
            }

            if (chkPower.Checked)
            {
                lo_band = BandByFreq(XVTRForm.TranslateFreq(VFOAFreq), rx1_xvtr_index, current_region);
                lo_bandb = BandByFreq(XVTRForm.TranslateFreq(VFOBFreq), rx2_xvtr_index, current_region);

                if (penny_ext_ctrl_enabled) //MW0LGE_21k
                {
                    int bits = Penny.getPenny().UpdateExtCtrl(lo_band, lo_bandb, _mox, tuning, SetupForm.TestIMD, chkExternalPA.Checked); //MW0LGE_21j
                    if (!IsSetupFormNull) SetupForm.UpdateOCLedStrip(_mox, bits);
                }

                UpdateTRXAnt();
                if (rx1_xvtr_index >= 0)
                {
                    modifyXVTRantenna(0, freq, rx1_xvtr_index);
                    Alex.getAlex().UpdateAlexAntSelection(lo_band, _mox, alex_ant_ctrl_enabled, true);
                }
                else
                {
                    undoXVTRantennaModify(0);
                    Alex.getAlex().UpdateAlexAntSelection(RX1Band, _mox, alex_ant_ctrl_enabled, false);
                }
                UpdateTRXAnt();
            }

            if (tx_band != old_tx_band)
            {
                if (tx_band == Band.B60M)
                {
                    chkXIT.Enabled = false;
                    chkXIT.Checked = false;
                }
                else
                    chkXIT.Enabled = true;
            }

            saved_vfoa_freq = freq;

            double f_LO = 0.0;
            if (rx1_xvtr_index >= 0)
            {
                f_LO = freq - XVTRForm.TranslateFreq(freq);
                freq -= f_LO;
            }
            else
            {
                if (freq < min_freq)
                {
                    freq = min_freq;
                    UpdateVFOAFreq(freq.ToString("f6"));
                }
                else if (freq > max_freq)
                {
                    freq = max_freq;
                    UpdateVFOAFreq(freq.ToString("f6"));
                }
            }

            if (current_hpsdr_model == HPSDRModel.ANAN7000D || current_hpsdr_model == HPSDRModel.ANAN8000D ||
                current_hpsdr_model == HPSDRModel.ANAN_G2 || current_hpsdr_model == HPSDRModel.ANAN_G2_1K)
            {
                if (alexpresent && rx1_band == Band.B6M && // chksr button was hidden and always unchecked. This has become the 2TON button MW0LGE_21a
                   ((!disable_6m_lna_on_rx && !bpf1_6bp_bypass && !alex_hpf_bypass)))
                    RX16mGainOffset = -RX6mGainOffset;
                else RX16mGainOffset = 0;
            }
            else
            {
                if (alexpresent && rx1_band == Band.B6M &&
                   ((!disable_6m_lna_on_rx && !alex6bphpf_bypass && !alex_hpf_bypass)) &&
                    current_hpsdr_model != HPSDRModel.ANAN10 &&
                    current_hpsdr_model != HPSDRModel.ANAN10E)
                    RX16mGainOffset = -RX6mGainOffset;
                else RX16mGainOffset = 0;
            }

            double rx_freq = freq;
            double tx_freq = freq;

            if (chkRIT.Checked && bRitOk)
                rx_freq += (int)udRIT.Value * 0.000001;

            if (rx_freq < min_freq) rx_freq = min_freq;
            else if (rx_freq > max_freq) rx_freq = max_freq;

            if (chkXIT.Checked)
                tx_freq += (int)udXIT.Value * 0.000001;

            if (tx_freq < min_freq) tx_freq = min_freq;
            else if (tx_freq > max_freq) tx_freq = max_freq;

            if (_mox && !chkVFOSplit.Checked && !full_duplex && !chkVFOBTX.Checked)
            {
                if (!CheckValidTXFreq(current_region, tx_freq, radio.GetDSPTX(0).CurrentDSPMode, chkTUN.Checked))
                {
                    switch (radio.GetDSPTX(0).CurrentDSPMode)
                    {
                        case DSPMode.CWL:
                        case DSPMode.CWU:
                            MessageBox.Show("The frequency " + tx_freq.ToString("f6") + "MHz is not within the\n" +
                                "Band specifications for your region (" + current_region.ToString() + ").",
                                "Transmit Error: Out Of Band",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                            break;
                        default:
                            if (!chkTUN.Checked)
                            {
                                MessageBox.Show("The frequency " + tx_freq.ToString("f6") + "MHz in combination with your TX filter\n" +
                                    "settings [" + Display.TXFilterLow.ToString() + ", " + Display.TXFilterHigh.ToString() + "] are not within the " +
                                    "Band specifications for your region (" + current_region.ToString() + ").",
                                    "Transmit Error: Out Of Band",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                            }
                            else
                            {
                                MessageBox.Show("The frequency " + tx_freq.ToString("f6") + "MHz is not within the\n" +
                                       "Band specifications for your region (" + current_region.ToString() + ").",
                                       "Transmit Error: Out Of Band",
                                       MessageBoxButtons.OK,
                                       MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                            }
                            break;
                    }
                    chkMOX.Checked = false;
                    return;
                }
            }

            if (rx1_dsp_mode == DSPMode.CWL)
            {
                rx_freq += (double)cw_pitch * 0.0000010;
                if (!cw_fw_keyer || (cw_fw_keyer && chkTUN.Checked))
                    tx_freq += (double)cw_pitch * 0.0000010;
            }
            else if (rx1_dsp_mode == DSPMode.CWU)
            {
                rx_freq -= (double)cw_pitch * 0.0000010;
                if (!cw_fw_keyer || (cw_fw_keyer && chkTUN.Checked))
                    tx_freq -= (double)cw_pitch * 0.0000010;
            }

            switch (RX1DSPMode)
            {
                case DSPMode.AM:
                case DSPMode.SAM:
                case DSPMode.FM:
                    if (chkTUN.Checked) tx_freq -= cw_pitch * 1e-6;
                    break;
                case DSPMode.USB:
                case DSPMode.DIGU:
                case DSPMode.DSB:
                    if (chkTUN.Checked)
                    {
                        if (RX1IsOn60mChannel() && current_region == FRSRegion.US)
                            tx_freq -= (ModeFreqOffset(rx1_dsp_mode) + cw_pitch * 1e-6);
                        else
                            tx_freq -= cw_pitch * 1e-6;
                    }
                    break;
                case DSPMode.LSB:
                case DSPMode.DIGL:
                    if (chkTUN.Checked) tx_freq += cw_pitch * 1e-6;
                    break;
            }

            if (rx_freq < min_freq) rx_freq = min_freq;
            else if (rx_freq > max_freq) rx_freq = max_freq;
            if (tx_freq < min_freq) tx_freq = min_freq;
            else if (tx_freq > max_freq) tx_freq = max_freq;

            if (chkPower.Checked)
            {
                if (Audio.WavePlayback)
                {
                    double f = (wave_freq - (VFOAFreq * 1e6) % sample_rate_rx1);
                    if (f > sample_rate_rx1 / 2) f -= sample_rate_rx1;
                    if (f < -sample_rate_rx1 / 2) f += sample_rate_rx1;
                    radio.GetDSPRX(0, 0).RXOsc = f;
                }
                else
                {
                    if (!chkFullDuplex.Checked && !chkVFOBTX.Checked)
                    {
                        tx_dds_freq_mhz = tx_freq;
                        UpdateTXDDSFreq(); // update tx freq
                    }
                    if (!click_tune_display)
                        FWCDDSFreq = rx_freq; // update rx freq

                    if (click_tune_display) //-W2PA This was preventing proper receiver adjustment
                    {
                        // MW0LGE_21b changed this block to include CW shift with xvtr
                        double dTmpFreq = (rx1_xvtr_index >= 0) ? XVTRForm.TranslateFreq(CentreFrequency) : CentreFrequency;
                        switch (RX1DSPMode)  //-W2PA Account for offset when in CW modes.
                        {
                            case DSPMode.CWL:
                                dTmpFreq += CWPitch * 1.0e-6;
                                break;
                            case DSPMode.CWU:
                                dTmpFreq -= CWPitch * 1.0e-6;
                                break;
                        }
                        FWCDDSFreq = dTmpFreq;
                    }

                    if (chkEnableMultiRX.Checked && !_mox) //MW0LGE [2.7.0.9] only when RX'ing. Fixes issue where multirx would be outside sample area after a tx
                    {
                        int diff;
                        if (rx2_enabled) diff = (int)((VFOASubFreq - VFOAFreq) * 1e6);
                        else diff = (int)((VFOBFreq - VFOAFreq) * 1e6);
                        if (chkRIT.Checked && !_mox && bRitOk) diff -= (int)udRIT.Value;
                        int rx2_osc = (int)(radio.GetDSPRX(0, 0).RXOsc - diff);
                        if (rx2_osc > -sample_rate_rx1 / 2 && rx2_osc < sample_rate_rx1 / 2)
                        {
                            radio.GetDSPRX(0, 1).RXOsc = rx2_osc;
                        }
                        else chkEnableMultiRX.Checked = false;
                    }

                }
            }
            else if (rx1_xvtr_index >= 0)
                FWCDDSFreq = XVTRForm.TranslateFreq(CentreFrequency);
            else
                FWCDDSFreq = CentreFrequency;

            if (chkVFOSync.Checked) //MW0LGE_21k9  //[2.10.1.0] MW0LGE not used anymore
            {
                if (!initializing && RX2Enabled) // MW0LGE_21a
                {
                    if (RX2DSPMode != RX1DSPMode) RX2DSPMode = RX1DSPMode; // MW0LGE only set if different
                    if (RX2Filter != RX1Filter) RX2Filter = RX1Filter; // MW0LGE only set if different
                }
                if (VFOBFreq != VFOAFreq) VFOBFreq = VFOAFreq; // MW0LGE_21k9 we only want to do if different, but we always want to align the filters.
                                                               // Moved after the mode change due to freq change occuring which prevented mode change
            }

            if (small_lsd)
            {
                txtVFOAMSD.Visible = true;
                txtVFOALSD.Visible = true;
            }

            //last_rx1_xvtr_index = rx1_xvtr_index;
            //last_tx_xvtr_index = tx_xvtr_index;

            WDSP.RXANBPSetTuneFrequency(WDSP.id(0, 0), (FWCDDSFreq + f_LO) * 1.0e6);
            WDSP.RXANBPSetTuneFrequency(WDSP.id(0, 1), (FWCDDSFreq + f_LO) * 1.0e6);

            UpdatePreamps();

            //MW0LGE_21d
            if (dOldFreq != VFOAFreq)
                VFOAFrequencyChangeHandlers?.Invoke(oldBand, RX1Band, oldMode, RX1DSPMode, oldFilter, RX1Filter, dOldFreq, VFOAFreq,
                    oldCentreFreq, CentreFrequency, oldCtun, ClickTuneDisplay, oldZoomSlider, ptbDisplayZoom.Value, radio.GetDSPRX(0, 0).RXOsc, 1);

            if (TXFreq != _old_tx_freq || old_tx_band != TXBand)
            {
                TXFrequncyChangedHandlers?.Invoke(_old_tx_freq, TXFreq, _old_tx_band, TXBand);
                _old_tx_freq = TXFreq;
                _old_tx_band = TXBand;
            }
        }

        private Band[] _band_used_for_xvtr_modify;
        private int[] _ant_before_xvtr_modify;
        private void setupModifyXVTRantennaArray()
        {
            _band_used_for_xvtr_modify = new Band[2];
            _ant_before_xvtr_modify = new int[2];

            for (int rx = 0; rx < 2; rx++)
            { 
                _band_used_for_xvtr_modify[rx] = Band.LAST;
                _ant_before_xvtr_modify[rx] = -1;
            }
        }
        private void modifyXVTRantenna(int rx, double freq, int rx_xvtr_index)
        {
            if (rx < 0 || rx > 1) return;
            if (rx_xvtr_index < 0 || rx_xvtr_index > 15) return;
            // modify xvtr rx antenna
            if (!IsSetupFormNull)
            {
                int required_ant = XVTRForm.GetRXAntenna(rx_xvtr_index);
                if (required_ant >= 1 && required_ant <= 3)
                {
                    Band xvtr_rx_band = BandByFreq(XVTRForm.TranslateFreq(freq), -1, current_region);
                    int xvtr_rx_band_ant = SetupForm.GetRXAntenna(xvtr_rx_band);
                    if (required_ant != xvtr_rx_band_ant)
                    {
                        //Debug.Print("Change xvtr rx antenna to : " + required_ant.ToString());
                        undoXVTRantennaModify(rx);
                        xvtr_rx_band_ant = SetupForm.GetRXAntenna(xvtr_rx_band); // this needs to re-obtained as the undo above might adjust revert the antennas back
                        _ant_before_xvtr_modify[rx] = xvtr_rx_band_ant;
                        _band_used_for_xvtr_modify[rx] = xvtr_rx_band;
                        SetupForm.SetRXAntenna(required_ant, xvtr_rx_band);
                    }
                }
                else
                {
                    // return to default
                    undoXVTRantennaModify(rx);
                }
            }
        }
        private void undoXVTRantennaModify(int rx)
        {
            if (rx < 0 || rx > 1) return;
            if (_band_used_for_xvtr_modify[rx] != Band.LAST)
            {
                if (!IsSetupFormNull)
                    SetupForm.SetRXAntenna(_ant_before_xvtr_modify[rx], _band_used_for_xvtr_modify[rx]);

                _ant_before_xvtr_modify[rx] = -1;
                _band_used_for_xvtr_modify[rx] = Band.LAST;
            }
        }
        private Band getTXBandWhenExtended(Band b, double frequency = -1)
        {
            if (!extended) return b;

            Band b1 = b;

            if (Band.BLMF == b) b1 = Band.B160M;
            else if (Band.B120M == b) b1 = Band.B160M;
            else if (Band.B90M == b) b1 = Band.B80M;
            else if (Band.B61M == b) b1 = Band.B80M;
            else if (Band.B49M == b) b1 = Band.B60M;
            else if (Band.B41M == b) b1 = Band.B40M;
            else if (Band.B31M == b) b1 = Band.B30M;
            else if (Band.B25M == b) b1 = Band.B20M;
            else if (Band.B22M == b) b1 = Band.B20M;
            else if (Band.B19M == b) b1 = Band.B17M;
            else if (Band.B16M == b) b1 = Band.B17M;
            else if (Band.B14M == b) b1 = Band.B15M;
            else if (Band.B13M == b) b1 = Band.B12M;
            else if (Band.B11M == b) b1 = Band.B10M;

            if (b1 != b) return b1; // changed from above to a ham band

            // check if ham band, return if that is the case
            if (b >= Band.B160M && b <= Band.B6M) return b;

            // check if xvtr band, return if that is the case
            if (b >= Band.VHF0 && b <= Band.VHF13) return b;

            // otherwise find nearest band to frequency and use that
            if (frequency != -1)
            {
                Band bn = BandStackManager.GetNearestBandForFrequency(frequency, true, true);
                if (bn != Band.FIRST) b = bn;
            }

            return b;
        }

        private void txtVFOAFreq_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
        {
            string separator = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
            int KeyCode = (int)e.KeyChar;
            if ((KeyCode < 48 || KeyCode > 57) &&			// numeric keys
                KeyCode != 8 &&								// backspace
                !e.KeyChar.ToString().Equals(separator) &&	// decimal
                KeyCode != 27)								// escape
            {
                e.Handled = true;
            }
            else
            {
                if (e.KeyChar.ToString().Equals(separator))
                {
                    e.Handled = (((TextBoxTS)sender).Text.IndexOf(separator) >= 0);
                }
                else if (KeyCode == 27)
                {
                    m_bVFOAChangedByKeys = false; //MW0LGE_21a
                    btnHidden.Focus();
                }
            }
            if (e.KeyChar == (char)Keys.Enter)
            {
                m_bVFOAChangedByKeys = true;
                btnHidden.Focus();
            }
        }

        private void txtVFOAFreq_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (this.ContainsFocus)
            {
                int old_digit = vfoa_hover_digit;
                int digit_index = 0;
                if (vfo_char_width == 0)
                    GetVFOCharWidth();

                int x = txtVFOAFreq.Width - (vfo_pixel_offset - 5);
                while (x < e.X)
                {
                    digit_index++;

                    if (small_lsd && txtVFOALSD.Visible)
                    {
                        if (digit_index < 6)
                            x += (vfo_char_width + vfo_char_space);
                        else
                            x += (vfo_small_char_width + vfo_small_char_space);

                        if (digit_index == 3)
                            x += (vfo_decimal_space - vfo_char_space);
                        if (digit_index == 6)
                            x += vfo_small_char_width;
                    }
                    else
                    {
                        x += vfo_char_width;
                        if (digit_index == 3)
                            x += vfo_decimal_space;
                        else
                            x += vfo_char_space;
                    }
                }

                if (digit_index < 3) digit_index = -1;
                if (digit_index > 9) digit_index = 9;
                vfoa_hover_digit = digit_index;
                if (vfoa_hover_digit != old_digit)
                    panelVFOAHover.Invalidate();
            }
        }

        private void txtVFOAFreq_MouseLeave(object sender, System.EventArgs e)
        {
            vfoa_hover_digit = -1;
            panelVFOAHover.Invalidate();
        }

        private void txtVFOABand_LostFocus(object sender, System.EventArgs e)
        {
            if (!rx2_enabled || (!chkEnableMultiRX.Checked && !chkVFOSplit.Checked)) return;
            if (txtVFOABand.Text == "." || string.IsNullOrEmpty(txtVFOABand.Text))
            {
                VFOASubFreq = VFOAFreq;
                return;
            }

            double vfoa = VFOAFreq;

            double freq;
            if (m_bVFOABandChangedByKeys)
            {
                freq = VFOASubFreq;// double.Parse(txtVFOABand.Text); //MW0LGE //[2.10.3.6]freq changes.
                m_dVFOASubFreq = freq;
                m_bVFOABandChangedByKeys = false;
            }
            else
            {
                freq = VFOASubFreq;
            }

            Display.VFOASub = (long)(freq * 1e6);
            if (chkTUN.Checked && chkVFOATX.Checked && chkVFOSplit.Checked)
            {
                switch (radio.GetDSPTX(0).CurrentDSPMode)
                {
                    case DSPMode.CWL:
                    case DSPMode.LSB:
                    case DSPMode.DIGL:
                        Display.VFOASub += cw_pitch;
                        break;
                    case DSPMode.CWU:
                    case DSPMode.USB:
                    case DSPMode.DIGU:
                    case DSPMode.AM:
                    case DSPMode.SAM:
                    case DSPMode.FM:
                    case DSPMode.DSB:
                        Display.VFOASub -= cw_pitch;
                        break;
                }
            }
            saved_vfoa_sub_freq = freq;

            if (!CheckValidTXFreq(current_region, freq, radio.GetDSPTX(0).CurrentDSPMode, chkTUN.Checked))
            {
                if (chkVFOSplit.Checked && _mox && !extended)
                    chkMOX.Checked = false;
            }

            if (chkEnableMultiRX.Checked)
            {
                int diff = (int)((freq - vfoa) * 1e6);
                double sub_osc = radio.GetDSPRX(0, 0).RXOsc - diff;

                if (sub_osc < -sample_rate_rx1 / 2)
                {
                    VFOASubFreq = vfoa + (sample_rate_rx1 / 2 + radio.GetDSPRX(0, 0).RXOsc - 1) * 0.0000010;
                    return;
                }
                else if (sub_osc > sample_rate_rx1 / 2)
                {
                    VFOASubFreq = vfoa + (-sample_rate_rx1 / 2 + radio.GetDSPRX(0, 0).RXOsc + 1) * 0.0000010;
                    return;
                }

                if (sub_osc > -sample_rate_rx1 / 2 && sub_osc < sample_rate_rx1 / 2)
                {
                    radio.GetDSPRX(0, 1).RXOsc = sub_osc;
                }
            }

            if (chkVFOSplit.Checked)
            {
                tx_xvtr_index = XVTRForm.XVTRFreq(freq);
                Band old_tx_band = tx_band;
                Band b = BandByFreq(freq, tx_xvtr_index, current_region);

                Band b1 = getTXBandWhenExtended(b, freq);

                if (chkVFOSplit.Checked && old_tx_band != b1)
                    SetTXBand(b1, b != b1); // ke9ns mod b1

                //tx
                if (last_tx_xvtr_index != tx_xvtr_index)
                {
                    if (tx_xvtr_index >= 0)
                    {
                        SetupForm.RXOnly = XVTRForm.GetRXOnly(tx_xvtr_index);
                    }
                }

                if (tx_xvtr_index >= 0)
                    freq = XVTRForm.TranslateFreq(freq);

                if (old_tx_band != tx_band)
                {
                    if (tx_band == Band.B60M)
                    {
                        chkXIT.Enabled = false;
                        chkXIT.Checked = false;
                    }
                    else
                        chkXIT.Enabled = true;
                }

                if (chkXIT.Checked)
                    freq += (int)udXIT.Value * 0.000001;

                if (freq < min_freq) freq = min_freq;
                else if (freq > max_freq) freq = max_freq;

                switch (radio.GetDSPTX(0).CurrentDSPMode)
                {
                    case DSPMode.AM:
                    case DSPMode.SAM:
                    case DSPMode.FM:
                    case DSPMode.USB:
                    case DSPMode.DIGU:
                        if (chkTUN.Checked) freq -= (double)cw_pitch * 1e-6;
                        break;
                    case DSPMode.LSB:
                    case DSPMode.DIGL:
                        if (chkTUN.Checked) freq += (double)cw_pitch * 1e-6;
                        break;
                    case DSPMode.CWL:
                        freq += (double)cw_pitch * 0.0000010;
                        break;
                    case DSPMode.CWU:
                        freq -= (double)cw_pitch * 0.0000010;
                        break;
                }

                if (!rx1_sub_drag)
                {
                    tx_dds_freq_mhz = freq;
                    UpdateTXDDSFreq();
                }
                last_tx_xvtr_index = tx_xvtr_index;
            }
        }

        private void txtVFOABand_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
        {
            if (!rx2_enabled || (!chkEnableMultiRX.Checked && !chkVFOSplit.Checked))
            {
                e.Handled = true;
                return;
            }

            string separator = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
            int KeyCode = (int)e.KeyChar;
            if ((KeyCode < 48 || KeyCode > 57) &&			// numeric keys
                KeyCode != 8 &&								// backspace
                !e.KeyChar.ToString().Equals(separator) &&	// decimal
                KeyCode != 27)								// escape
            {
                e.Handled = true;
            }
            else
            {
                if (e.KeyChar.ToString().Equals(separator))
                {
                    e.Handled = (((TextBoxTS)sender).Text.IndexOf(separator) >= 0);
                }
                else if (KeyCode == 27)
                {
                    VFOASubFreq = saved_vfoa_sub_freq;
                    btnHidden.Focus();
                }
            }
            if (e.KeyChar == (char)Keys.Enter)
            {
                m_bVFOABandChangedByKeys = true;
                btnHidden.Focus();
            }
        }

        // txtVFOBFreq
        private void txtVFOBFreq_LostFocus(object sender, System.EventArgs e)
        {
            if (initializing) return;

            //MW0LGE_21d
            double dOldFreq = Math.Round(saved_vfob_freq, 6);

            Band oldBand;
            DSPMode oldMode;
            Filter oldFilter;
            double oldCentreFreq;
            bool oldCtun;
            if (rx2_enabled)
            {
                oldBand = RX2Band;
                oldMode = RX2DSPMode;
                oldFilter = RX2Filter;
                oldCentreFreq = CentreRX2Frequency;
                oldCtun = ClickTuneRX2Display;
            }
            else
            {
                oldBand = RX1Band;
                oldMode = RX1DSPMode;
                oldFilter = RX1Filter;
                oldCentreFreq = CentreFrequency;
                oldCtun = ClickTuneDisplay;
            }

            int oldZoomSlider = ptbDisplayZoom.Value;

            //check if valid
            double dValue;
            if (Double.TryParse(txtVFOBFreq.Text, out dValue) == false)
            {
                // not a value
                VFOBFreq = saved_vfob_freq;
                return;
            }
            else
            {
                // we have a valid value
                if (m_bVFOBChangedByKeys)
                {
                    m_dVFOBFreq = dValue;
                    m_bVFOBChangedByKeys = false;
                }
            }

            double freq = m_dVFOBFreq;

            if (current_hpsdr_model == HPSDRModel.ANAN7000D || current_hpsdr_model == HPSDRModel.ANAN8000D ||
                current_hpsdr_model == HPSDRModel.ANAN_G2 || current_hpsdr_model == HPSDRModel.ANAN_G2_1K)
            {
                if (alexpresent && rx2_band == Band.B6M && // chkSR2 button was hidden and always unchecked. This has become the 2TON button MW0LGE_21a
                   ((!disable_6m_lna_on_rx && !alex26bphpf_bypass && !alex2_hpf_bypass)))
                    RX26mGainOffset = -RX6mGainOffsetRx2;
                else RX26mGainOffset = 0; // MW0LGE_21d doing this always !
            }

            if (!click_tune_rx2_display || update_rx2_centerfreq)
            {
                // used by CAT
                CentreRX2Frequency = freq;
                update_rx2_centerfreq = false;
            }

            double passbandWidth = (Convert.ToDouble(Display.RX2FilterHigh) - Convert.ToDouble(Display.RX2FilterLow));
            double dispWidth = Convert.ToDouble(Display.RX2DisplayHigh) - Convert.ToDouble(Display.RX2DisplayLow);
            double dispMargin = 0.05; // Margin from display edge to start scrolling - in fraction of total display width   

            // Lock the display //-W2PA Don't freeze display if we are zoomed in too far to fit the passband
            bool bCanFitInView = passbandWidth < (dispWidth * (1.0 - 2.0 * dispMargin));

            bool bLimitToSpectral = m_bLimitCTToSpectralArea && ((m_bLimitCTMouseOnly && rx2_click_tune_drag) || !m_bLimitCTMouseOnly);

            bool bRitOk = !_mox || (_mox && VFOATX && RX2Enabled); //[2.10.1.0] MW0LGE we can apply rit to rx2

            if (rx2_enabled)
            {
                if (click_tune_rx2_display && bCanFitInView && ((_mox && VFOATX && RX2Enabled) || !_mox)) //[2.10.1.0] MW0LGE want if moxing
                {
                    double rx2_osc = Math.Round(-(freq - CentreRX2Frequency) * 1e6);

                    //MW0LGE
                    double Lmargin = Convert.ToDouble(-Display.RX2FilterLow);
                    double Hmargin = Convert.ToDouble(Display.RX2FilterHigh);
                    if (Lmargin < 0.0) Lmargin = 0.0;
                    if (Hmargin < 0.0) Hmargin = 0.0;
                    double Ldisp = Convert.ToDouble(Display.RX2DisplayLow) + dispWidth * dispMargin;
                    double Hdisp = Convert.ToDouble(Display.RX2DisplayHigh) - dispWidth * dispMargin;
                    double freqJumpThresh = 0.5e6;  // Definition of jumping far, e.g. with memory recall - causes a re-centering

                    if (!m_bIgnoreLimitsForZTB) // MW0LGE_21k9
                    {
                        if (!ClickTuneDrag)
                        {
                            //-W2PA Original 3.4.1 code
                            if (((-rx2_osc) - Lmargin) < Ldisp || ((-rx2_osc) + Hmargin) > Hdisp) // re-center if we've jumped far
                            {
                                CentreRX2Frequency = freq;
                                rx2_osc = 0.0;
                            }
                        }
                        else
                        {
                            if (!rx2_spectrum_tune_drag)
                            {
                                //-W2PA If we tune beyond the display limits, re-center or scroll display, and keep going.  Original code above just stops tuning at edges.
                                if (((-rx2_osc) - Lmargin) < (Ldisp - freqJumpThresh) || ((-rx2_osc) + Hmargin) > (Hdisp + freqJumpThresh)) // re-center if we've jumped far
                                {
                                    CentreRX2Frequency = freq;
                                    rx2_osc = 0.0;
                                }
                                else  // not a jump - more like tuning
                                if (!bLimitToSpectral && (((-rx2_osc) - Lmargin) < Ldisp)) // scroll the spectrum display smoothly at the edge and keep going
                                {
                                    double adjustFreq = Ldisp - ((-rx2_osc) - Lmargin);
                                    CentreRX2Frequency -= adjustFreq * 1.0e-6;
                                    rx2_osc -= adjustFreq;
                                }
                                else if (!bLimitToSpectral && (((-rx2_osc) + Hmargin) > Hdisp))
                                {
                                    double adjustFreq = ((-rx2_osc) + Hmargin) - Hdisp;
                                    CentreRX2Frequency += adjustFreq * 1.0e-6;
                                    rx2_osc += adjustFreq;
                                }
                            }
                        }
                    }

                    if (chkRIT.Checked && VFOSync && bRitOk)
                        rx2_osc -= (int)udRIT.Value;

                    bool bBelowLow = (-rx2_osc < (-(sample_rate_rx2 * 0.92) / 2) + Lmargin);
                    bool bAboveHigh = (-rx2_osc > ((sample_rate_rx2 * 0.92) / 2) - Hmargin);

                    if (bBelowLow || bAboveHigh)
                    {
                        double diff;

                        diff = ((sample_rate_rx2 * 0.92) / 2) - Math.Abs(rx2_osc);
                        diff = (-rx2_osc >= 0) ? -diff + Hmargin : diff - Lmargin;

                        freq -= diff * 1e-6;

                        // we have moved out of the IF
                        rx2_osc += diff;
                    }
                    //

                    if (!m_bIgnoreLimitsForZTB)
                    {
                        if (!rx2_spectrum_tune_drag && bLimitToSpectral) // MW0LGE_21k9
                        {
                            //check if outside view
                            bool bOutsideViewLow = -rx2_osc < ((double)(Display.RXDisplayLow) + Lmargin);
                            bool bOutsideViewHigh = -rx2_osc > ((double)(Display.RXDisplayHigh) - Hmargin);

                            if (bOutsideViewLow || bOutsideViewHigh)
                            {
                                double diff;

                                if (bOutsideViewLow)
                                    diff = -(double)(Display.RXDisplayLow) - Math.Abs(rx2_osc);
                                else
                                    diff = (double)(Display.RXDisplayHigh) - Math.Abs(rx2_osc);

                                diff = (-rx2_osc >= 0) ? -diff + Hmargin : diff - Lmargin;
                                freq -= diff * 1e-6;
                                rx2_osc += diff;
                            }
                        }
                    }

                    radio.GetDSPRX(1, 0).RXOsc = rx2_osc; // keep tuning
                    Display.RX2FreqDiff = (int)radio.GetDSPRX(1, 0).RXOsc;
                }
                else
                {
                    if (!bCanFitInView && click_tune_rx2_display && !rx2_spectrum_tune_drag)
                    {
                        // if filter is off the edge of view, most likey because of high zoom
                        CentreRX2Frequency = freq;
                    }

                    radio.GetDSPRX(1, 0).RXOsc = 0.0;
                    Display.RX2FreqDiff = (int)radio.GetDSPRX(1, 0).RXOsc;
                }
            }

            if (chkEnableMultiRX.Checked && !rx2_enabled && !_mox)  //MW0LGE [2.7.0.9] only when RX'ing. Fixes issue where multirx would be outside sample area after a tx
            {
                int diff = (int)((VFOBFreq - VFOAFreq) * 1e6);

                double rx2_osc = radio.GetDSPRX(0, 0).RXOsc - diff;

                if (rx2_osc > -sample_rate_rx1 / 2 && rx2_osc < sample_rate_rx1 / 2)
                {
                    radio.GetDSPRX(0, 1).RXOsc = rx2_osc;
                }
                else chkEnableMultiRX.Checked = false; // MW0LGE [2.9.0.7] same as vfoA lost focus
            }

            UpdateVFOBFreq(freq.ToString("f6"));

            if (rx2_enabled)
            {
                //-W2PA Freeze display unless we are zoomed in too far to fit the passband
                if (click_tune_rx2_display && ((_mox && VFOATX && RX2Enabled) || !_mox)) // [2.10.1.0] MW0LGE want if moxing
                {
                    Display.VFOB = (long)(CentreRX2Frequency * 1e6);
                }
                else
                    Display.VFOB = (long)(freq * 1e6);

                if (chkTUN.Checked && chkVFOBTX.Checked) // MW0LGE only if not duplex //MW0LGE_21k8 !display_duplex commented as always in dup off mode on rx2 when tx'ing tune
                {
                    switch (radio.GetDSPTX(0).CurrentDSPMode)
                    {
                        case DSPMode.CWL:
                        case DSPMode.LSB:
                        case DSPMode.DIGL:
                            Display.VFOB += cw_pitch;
                            break;
                        case DSPMode.CWU:
                        case DSPMode.USB:
                        case DSPMode.DIGU:
                        case DSPMode.AM:
                        case DSPMode.SAM:
                        case DSPMode.FM:
                        case DSPMode.DSB:
                            Display.VFOB -= cw_pitch;
                            break;
                    }
                }

                if (_mox && (CurrentHPSDRHardware == HPSDRHW.Hermes ||
                            CurrentHPSDRHardware == HPSDRHW.HermesII))
                {
                    if (chkVFOSplit.Checked)
                    {
                        if (display_duplex && !PSState && !click_tune_display)
                            Display.VFOASub = (long)(VFOAFreq * 1e6);
                        else if (display_duplex && !PSState && click_tune_display)
                            Display.VFOASub = (long)(CentreFrequency * 1e6);

                        else
                            UpdateVFOASub();

                    }

                    else if (!chkVFOSplit.Checked && chkVFOBTX.Checked)
                    {
                        if (PSState)
                            Display.VFOA = (long)(VFOBFreq * 1e6);
                    }
                    else if (!chkVFOSplit.Checked && !chkVFOBTX.Checked &&
                        PSState && display_duplex)
                        Display.VFOA = (long)(VFOAFreq * 1e6);
                    else
                        txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                }
            }
            else
            {
                if (_mox)
                {
                    if (CurrentHPSDRHardware == HPSDRHW.Hermes ||
                         CurrentHPSDRHardware == HPSDRHW.HermesII)
                    {
                        if (chkVFOSplit.Checked)
                        {
                            if (PSState && !display_duplex)
                                Display.VFOASub = (long)(freq * 1e6);
                            else if (!PSState && !display_duplex)
                                Display.VFOASub = (long)(freq * 1e6);
                            else if (!PSState)
                                Display.VFOASub = (long)(CentreFrequency * 1e6);
                            else if (PSState)
                                Display.VFOASub = (long)(freq * 1e6);
                        }
                        else if (click_tune_display && PSState && display_duplex)
                        {
                            Display.VFOA = (long)(VFOAFreq * 1e6);
                        }
                        else if (click_tune_display && PSState && !display_duplex)
                        {
                            Display.VFOA = (long)(VFOAFreq * 1e6);
                        }
                        else
                            Display.VFOASub = (long)(VFOAFreq * 1e6);
                    }
                    else if (display_duplex)
                        Display.VFOASub = (long)(freq * 1e6); //MW0LGE_21k8
                    else //MW0LGE_21k8
                        Display.VFOASub = (long)(freq * 1e6);
                }
                else
                    Display.VFOASub = (long)(freq * 1e6);

                if (chkTUN.Checked && chkVFOBTX.Checked && !display_duplex) // MW0LGE_21k8 only if not duplex
                {
                    switch (radio.GetDSPTX(0).CurrentDSPMode)
                    {
                        case DSPMode.CWL:
                        case DSPMode.LSB:
                        case DSPMode.DIGL:
                            Display.VFOA += cw_pitch;
                            Display.VFOASub += cw_pitch; // needed if only rx1 in use, and we are split. Display uses VFOASub to display split freq MW0LGE_21k8
                            break;
                        case DSPMode.CWU:
                        case DSPMode.USB:
                        case DSPMode.DIGU:
                        case DSPMode.AM:
                        case DSPMode.SAM:
                        case DSPMode.FM:
                        case DSPMode.DSB:
                            Display.VFOA -= cw_pitch;
                            Display.VFOASub -= cw_pitch;
                            break;
                    }
                }
            }

            if (XVTRForm != null)
            {
                if (XVTRForm.XVTRFreq(freq) != rx2_xvtr_index)
                    RX2XVTRIndex = XVTRForm.XVTRFreq(freq);
                if (rx2_xvtr_index < 0)
                {
                    int old_xvtr_index = XVTRForm.XVTRFreq(saved_vfob_freq);
                    if (old_xvtr_index >= 0 && freq >= max_freq)
                    {
                        VFOBFreq = saved_vfob_freq;
                        return;
                    }
                }
            }

            // update Band Info
            string bandInfo;
            double db_freq = freq;
            if (current_region == FRSRegion.US)
            {
                if (RX2IsIn60m())
                    db_freq -= ModeFreqOffset(rx2_dsp_mode);
                else if (RX1IsIn60m())
                    db_freq -= ModeFreqOffset(rx1_dsp_mode);
            }

            if (!DB.BandText(db_freq, out bandInfo))
                txtVFOBBand.BackColor = Color.DimGray;
            else 
                txtVFOBBand.BackColor = band_background_color;

            txtVFOBBand.Text = bandInfo;

            Band lo_band = Band.FIRST;
            Band lo_banda = Band.FIRST;

            if (chkPower.Checked)
            {
                lo_band = BandByFreq(XVTRForm.TranslateFreq(VFOBFreq), rx2_xvtr_index, current_region);
                lo_banda = BandByFreq(XVTRForm.TranslateFreq(VFOAFreq), rx1_xvtr_index, current_region);

                if (penny_ext_ctrl_enabled) //MW0LGE_21k
                {
                    int bits = Penny.getPenny().UpdateExtCtrl(lo_banda, lo_band, _mox, tuning, SetupForm.TestIMD, chkExternalPA.Checked); //MW0LGE_21j
                    if (!IsSetupFormNull) SetupForm.UpdateOCLedStrip(_mox, bits);
                }
            }

            saved_vfob_freq = freq;

            if (chkVFOBTX.Checked) goto set_tx_freq;
            if (chkVFOATX.Checked) goto set_rx2_freq;
            else if (chkVFOSplit.Checked || full_duplex)
                goto set_tx_freq;
            else goto end;

            set_tx_freq:
            tx_xvtr_index = rx2_xvtr_index;
            double tx_freq = freq;
            Band old_tx_band = tx_band;
            Band b = BandByFreq(tx_freq, tx_xvtr_index, current_region);

            Band b1 = getTXBandWhenExtended(b, tx_freq);

            if (old_tx_band != b1)
                SetTXBand(b1, b != b1); // ke9ns mod b1

            if (tx_xvtr_index >= 0)
            {
                tx_freq = XVTRForm.TranslateFreq(tx_freq);

                if (XVTRForm.GetDisablePA(tx_xvtr_index))
                {
                    NetworkIO.SetXVTREnable(1);
                    NetworkIO.DisablePA(1);
                }
                else
                {
                    NetworkIO.SetXVTREnable(0);
                    NetworkIO.DisablePA(0);
                }

            }

            //tx
            if (last_tx_xvtr_index != tx_xvtr_index)
            {
                if (tx_xvtr_index >= 0)
                {
                    if (last_tx_xvtr_index == -1)
                        saved_rx_only = rx_only;
                    RXOnly = XVTRForm.GetRXOnly(tx_xvtr_index);
                }
                else if (tx_xvtr_index < 0)
                {
                    if (last_tx_xvtr_index >= 0)
                        RXOnly = saved_rx_only;
                }
            }

            if (tx_xvtr_index < 0) //tx on HF
            {
                int old_xvtr_index = XVTRForm.XVTRFreq(saved_vfob_freq);
                if (old_xvtr_index >= 0 && freq >= max_freq)
                {
                    VFOBFreq = saved_vfob_freq;
                    return;
                }

                if (hf_tr_relay)
                {
                    NetworkIO.DisablePA(1);
                }
                else
                {
                    NetworkIO.DisablePA(0);
                }

                if (enable_xvtr_hf)
                    NetworkIO.SetXVTREnable(1); // enable
                else
                    NetworkIO.SetXVTREnable(0); // disable
            }

            if (old_tx_band != tx_band)
            {
                if (tx_band == Band.B60M)
                {
                    chkXIT.Enabled = false;
                    chkXIT.Checked = false;
                }
                else
                    chkXIT.Enabled = true;
            }
            if (chkXIT.Checked)
                tx_freq += (int)udXIT.Value * 0.000001;

            if (tx_freq < min_freq) tx_freq = min_freq;
            else if (tx_freq > max_freq) tx_freq = max_freq;

            DSPMode tx_mode = radio.GetDSPTX(0).CurrentDSPMode;

            //MW0LGE_21d should happen before the check below
            switch (tx_mode)
            {
                case DSPMode.AM:
                case DSPMode.SAM:
                case DSPMode.FM:
                case DSPMode.USB:
                case DSPMode.DIGU:
                case DSPMode.DSB:
                    if (chkTUN.Checked) tx_freq -= (double)cw_pitch * 1e-6;
                    break;
                case DSPMode.LSB:
                case DSPMode.DIGL:
                    if (chkTUN.Checked) tx_freq += (double)cw_pitch * 1e-6;
                    break;
                case DSPMode.CWL:
                    if (!cw_fw_keyer || (cw_fw_keyer && chkTUN.Checked))
                        tx_freq += (double)cw_pitch * 0.0000010;
                    break;
                case DSPMode.CWU:
                    if (!cw_fw_keyer || (cw_fw_keyer && chkTUN.Checked))
                        tx_freq -= (double)cw_pitch * 0.0000010;
                    break;
            }

            if (_mox)
            {
                if (!CheckValidTXFreq(current_region, tx_freq, tx_mode, chkTUN.Checked))
                {
                    switch (radio.GetDSPTX(0).CurrentDSPMode)
                    {
                        case DSPMode.CWL:
                        case DSPMode.CWU:
                            MessageBox.Show("The frequency " + tx_freq.ToString("f6") + "MHz is not within the\n" +
                                "Band specifications for your region (" + current_region.ToString() + ").",
                                "Transmit Error: Out Of Band",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                            break;
                        default:
                            if (!chkTUN.Checked)
                            {
                                MessageBox.Show("The frequency " + tx_freq.ToString("f6") + "MHz in combination with your TX filter\n" +
                                    "settings [" + Display.TXFilterLow.ToString() + ", " + Display.TXFilterHigh.ToString() + "] are not within the " +
                                    "Band specifications for your region (" + current_region.ToString() + ").",
                                    "Transmit Error: Out Of Band",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                            }
                            else
                            {
                                MessageBox.Show("The frequency " + tx_freq.ToString("f6") + "MHz is not within the\n" +
                                       "Band specifications for your region (" + current_region.ToString() + ").",
                                       "Transmit Error: Out Of Band",
                                       MessageBoxButtons.OK,
                                       MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                            }
                            break;
                    }
                    chkMOX.Checked = false;
                    return;
                }
            }

            if (!rx1_sub_drag)
            {
                tx_dds_freq_mhz = tx_freq;
                UpdateTXDDSFreq();
                goto set_rx2_freq;
            }
            goto end;

        set_rx2_freq:
            Band band = BandByFreq(freq, rx2_xvtr_index, current_region);
            if (band != rx2_band)
                SetRX2Band(band);
            double f_LO = 0.0;
            if (rx2_xvtr_index >= 0)
            {
                f_LO = freq - XVTRForm.TranslateFreq(freq);
                freq -= f_LO;
            }

            if (rx2_xvtr_index < 0)
            {
                RX2XVTRGainOffset = 0.0f;
            }
            else
            {
                freq = XVTRForm.TranslateFreq(freq);
                RX2XVTRGainOffset = XVTRForm.GetRXGain(rx2_xvtr_index);
            }

            if (chkRIT.Checked && VFOSync && bRitOk)
                freq += (int)udRIT.Value * 0.000001;

            if (freq < min_freq) freq = min_freq;
            else if (freq > max_freq) freq = max_freq;

            if (rx2_dsp_mode == DSPMode.CWL)
                freq += (double)cw_pitch * 0.0000010;
            else if (rx2_dsp_mode == DSPMode.CWU)
                freq -= (double)cw_pitch * 0.0000010;

            if (!click_tune_rx2_display || set_rx2_freq)
                RX2DDSFreq = freq;

            if (click_tune_rx2_display) //-W2PA This was preventing proper receiver adjustment
            {
                // MW0LGE_21i changed this block to include CW shift with xvtr
                double dTmpFreq = (rx2_xvtr_index >= 0) ? XVTRForm.TranslateFreq(CentreRX2Frequency) : CentreRX2Frequency;
                switch (RX2DSPMode)  //-W2PA Account for offset when in CW modes.
                {
                    case DSPMode.CWL:
                        dTmpFreq += CWPitch * 1.0e-6;
                        break;
                    case DSPMode.CWU:
                        dTmpFreq -= CWPitch * 1.0e-6;
                        break;
                }
                RX2DDSFreq = dTmpFreq;
            }

            set_rx2_freq = false;

            WDSP.RXANBPSetTuneFrequency(WDSP.id(2, 0), (RX2DDSFreq + f_LO) * 1.0e6);
            goto end;

        end:

            // added G8NJJ for Aries ATU: see if ARIES needs a new frequency update and antenna band update
            DisplayAriesRXAntenna();
            if ((AriesCATEnabled) && (chkVFOBTX.Checked))
            {
                SetAriesTXFrequency(freq);
                DisplayAriesTXAntenna();
            }


            if (chkVFOSync.Checked) //MW0LGE_21k9
            {
                if (!initializing && RX2Enabled) // MW0LGE_21a
                {
                    if (RX1DSPMode != RX2DSPMode) RX1DSPMode = RX2DSPMode;
                    if (RX1Filter != RX2Filter) RX1Filter = RX2Filter;
                }
                if (VFOAFreq != VFOBFreq) VFOAFreq = VFOBFreq; // MW0LGE_21k9 we only want to do if different, but we always want to align the filters/
                                                               // Moved after the mode change due to freq change occuring which prevented mode change
            }

            if (small_lsd)
            {
                txtVFOBMSD.Visible = true;
                txtVFOBLSD.Visible = true;
            }
            //last_tx_xvtr_index = tx_xvtr_index;
            //last_rx2_xvtr_index = rx2_xvtr_index;

            if(RX2Enabled)
            {
                if (dOldFreq != VFOBFreq)
                    VFOBFrequencyChangeHandlers?.Invoke(oldBand, RX2Band, oldMode, RX2DSPMode, oldFilter, RX2Filter, dOldFreq, VFOBFreq,
                        oldCentreFreq, CentreRX2Frequency, oldCtun, ClickTuneRX2Display, oldZoomSlider, ptbDisplayZoom.Value, radio.GetDSPRX(1, 0).RXOsc, 2);
            }
            else
            {
                if (dOldFreq != VFOBFreq)
                {
                    Band tmpBand = BandByFreq(VFOBFreq, rx1_xvtr_index, current_region);

                    VFOBFrequencyChangeHandlers?.Invoke(oldBand, tmpBand, oldMode, RX1DSPMode, oldFilter, RX1Filter, dOldFreq, VFOBFreq,
                        oldCentreFreq, CentreFrequency, oldCtun, ClickTuneDisplay, oldZoomSlider, ptbDisplayZoom.Value, radio.GetDSPRX(0, 0).RXOsc, 1);
                }
            }
            if (TXFreq != _old_tx_freq || _old_tx_band != TXBand)
            {
                TXFrequncyChangedHandlers?.Invoke(_old_tx_freq, TXFreq, _old_tx_band, TXBand);
                _old_tx_freq = TXFreq;
                _old_tx_band = TXBand;
            }
        }

        private void txtVFOBFreq_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
        {
            string separator = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
            int KeyCode = (int)e.KeyChar;
            if ((KeyCode < 48 || KeyCode > 57) &&			// numeric keys
                KeyCode != 8 &&								// backspace
                !e.KeyChar.ToString().Equals(separator) &&	// decimal
                KeyCode != 27)								// escape
            {
                e.Handled = true;
            }
            else
            {
                if (e.KeyChar.ToString().Equals(separator))
                {
                    e.Handled = (((TextBoxTS)sender).Text.IndexOf(separator) >= 0);
                }
                else if (KeyCode == 27)
                {
                    m_bVFOBChangedByKeys = false; //MW0LGE_21a
                    btnHidden.Focus();
                }
            }
            if (e.KeyChar == (char)Keys.Enter)
            {
                m_bVFOBChangedByKeys = true;
                btnHidden.Focus();
            }
        }

        private void txtVFOBFreq_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (this.ContainsFocus)
            {
                int old_digit = vfob_hover_digit;
                int digit_index = 0;
                if (vfo_char_width == 0)
                    GetVFOCharWidth();

                int x = txtVFOBFreq.Width - (vfo_pixel_offset - 5);
                while (x < e.X)
                {
                    digit_index++;

                    if (small_lsd && txtVFOBLSD.Visible)
                    {
                        if (digit_index < 6)
                            x += (vfo_char_width + vfo_char_space);
                        else
                            x += (vfo_small_char_width + vfo_small_char_space);

                        if (digit_index == 3)
                            x += (vfo_decimal_space - vfo_char_space);
                        if (digit_index == 6)
                            x += vfo_small_char_width;
                    }
                    else
                    {
                        x += vfo_char_width;
                        if (digit_index == 3)
                            x += vfo_decimal_space;
                        else
                            x += vfo_char_space;
                    }
                }

                if (digit_index < 3) digit_index = -1;
                if (digit_index > 9) digit_index = 9;
                vfob_hover_digit = digit_index;
                if (vfob_hover_digit != old_digit)
                    panelVFOBHover.Invalidate();
            }
        }

        private void txtVFOBFreq_MouseLeave(object sender, System.EventArgs e)
        {
            vfob_hover_digit = -1;
            panelVFOBHover.Invalidate();
        }

        private void panelVFOAHover_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            Control c1 = (Control)sender;
            Control c2 = txtVFOAFreq;
            int client_width = (c1.Size.Width - c1.ClientSize.Width) + (c2.Size.Width - c2.ClientSize.Width);
            int client_height = (c1.Size.Height - c1.ClientSize.Height) + (c2.Size.Height - c2.ClientSize.Height);
            int x_offset = c1.Left - c2.Left - client_width / 2;
            int y_offset = c1.Top - c2.Top - client_height / 2;
            txtVFOAFreq_MouseMove(sender, new MouseEventArgs(e.Button, e.Clicks, e.X + x_offset, e.Y + y_offset, e.Delta));
        }

        private void panelVFOBHover_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            Control c1 = (Control)sender;
            Control c2 = txtVFOBFreq;
            int client_width = (c1.Size.Width - c1.ClientSize.Width) + (c2.Size.Width - c2.ClientSize.Width);
            int client_height = (c1.Size.Height - c1.ClientSize.Height) + (c2.Size.Height - c2.ClientSize.Height);
            int x_offset = c1.Left - c2.Left - client_width / 2;
            int y_offset = c1.Top - c2.Top - client_height / 2;
            txtVFOBFreq_MouseMove(sender, new MouseEventArgs(e.Button, e.Clicks, e.X + x_offset, e.Y + y_offset, e.Delta));
        }

        private void txtVFOALSD_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            txtVFOAMSD.Visible = false;
            txtVFOALSD.Visible = false;
            txtVFOAFreq.Focus();
            txtVFOAFreq.SelectAll();
        }

        private void txtVFOALSD_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            Control c1 = (Control)sender;
            Control c2 = txtVFOAFreq;
            int client_width = (c1.Size.Width - c1.ClientSize.Width) + (c2.Size.Width - c2.ClientSize.Width);
            int client_height = (c1.Size.Height - c1.ClientSize.Height) + (c2.Size.Height - c2.ClientSize.Height);
            int x_offset = c1.Left - c2.Left - client_width / 2;
            int y_offset = c1.Top - c2.Top - client_height / 2;
            txtVFOAFreq_MouseMove(sender, new MouseEventArgs(e.Button, e.Clicks, e.X + x_offset, e.Y + y_offset, e.Delta));
        }

        private void txtVFOAMSD_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            txtVFOAMSD.Visible = false;
            txtVFOALSD.Visible = false;
            txtVFOAFreq.Focus();
            txtVFOAFreq.SelectAll();
        }

        private void txtVFOAMSD_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            txtVFOAFreq_MouseMove(txtVFOAMSD,
                new MouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta));
        }

        private void txtVFOAMSD_MouseLeave(object sender, System.EventArgs e)
        {
            txtVFOAFreq_MouseLeave(txtVFOAMSD, e);
        }

        private void txtVFOBMSD_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            txtVFOBMSD.Visible = false;
            txtVFOBLSD.Visible = false;
            txtVFOBFreq.Focus();
            txtVFOBFreq.SelectAll();
        }

        private void txtVFOBMSD_MouseLeave(object sender, System.EventArgs e)
        {
            txtVFOBFreq_MouseLeave(txtVFOBMSD, e);
        }

        private void txtVFOBMSD_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            txtVFOBFreq_MouseMove(txtVFOBMSD,
                new MouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta));
        }

        private void txtVFOBLSD_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            txtVFOBMSD.Visible = false;
            txtVFOBLSD.Visible = false;
            txtVFOBFreq.Focus();
            txtVFOBFreq.SelectAll();
        }

        private void txtVFOBLSD_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            Control c1 = (Control)sender;
            Control c2 = txtVFOBFreq;
            int client_width = (c1.Size.Width - c1.ClientSize.Width) + (c2.Size.Width - c2.ClientSize.Width);
            int client_height = (c1.Size.Height - c1.ClientSize.Height) + (c2.Size.Height - c2.ClientSize.Height);
            int x_offset = c1.Left - c2.Left - client_width / 2;
            int y_offset = c1.Top - c2.Top - client_height / 2;
            txtVFOBFreq_MouseMove(sender, new MouseEventArgs(e.Button, e.Clicks, e.X + x_offset, e.Y + y_offset, e.Delta));
        }

        #endregion

        #region Display Events

        private bool rx1_low_filter_drag = false;
        private bool rx1_high_filter_drag = false;
        private bool rx1_whole_filter_drag = false;
        private bool rx1_sub_drag = false;
        private bool rx1_spectrum_drag = false;

        private bool rx2_low_filter_drag = false;
        private bool rx2_high_filter_drag = false;
        private bool rx2_whole_filter_drag = false;

        private bool rx2_spectrum_drag = false;

        private bool tx_low_filter_drag = false;
        private bool tx_high_filter_drag = false;
        private bool tx_whole_filter_drag = false;

        private int whole_filter_start_x = 0;
        private int whole_filter_start_low = 0;
        private int whole_filter_start_high = 0;
        private int sub_drag_last_x = 0;
        private int spectrum_drag_last_x = 0;
        private double sub_drag_start_freq = 0.0;
        private bool agc_knee_drag = false;
        private Point agc_knee_drag_start_point = new Point(0, 0);
        private bool agc_hang_drag = false;
        private bool rx1_click_tune_drag = false;
        private bool rx2_click_tune_drag = false;
        private bool rx1_spectrum_tune_drag = false;
        private bool rx2_spectrum_tune_drag = false;

        private bool rx1_grid_adjust = false;
        private bool rx2_grid_adjust = false;
        private bool tx1_grid_adjust = false;
        private bool tx2_grid_adjust = false;
        private bool gridmaxadjust = false;
        private bool wfmaxadjust = false;
        private bool wfminadjust = false;
        private bool gridminmaxadjust = false;

        private Point grid_minmax_drag_start_point = new Point(0, 0);

        private float grid_minmax_max_y = 0;
        private float grid_minmax_min_y = 0;
        private Cursor grab = new Cursor(msgrab);
        private Cursor grabbing = new Cursor(msgrabbing);
        private Cursor _cross_outlined = new Cursor(mscross_outlined);

        private bool overRX(int x, int y, int rx, bool bIgnorePanafallWaterfall = true)
        {
            int nMinHeightRX1 = 0;
            int nMaxHeightRX1 = picDisplay.Height;
            int nMinHeightRX2 = picDisplay.Height / 2;
            int nMaxHeightRX2 = picDisplay.Height;

            if (rx2_enabled)
            {
                // top half only
                nMaxHeightRX1 = picDisplay.Height / 2;

                if (Display.CurrentDisplayModeBottom == DisplayMode.PANAFALL && bIgnorePanafallWaterfall)
                {
                    //top half, of bottom half is available only
                    nMaxHeightRX2 = (picDisplay.Height / 4) * 3;
                }
            }

            if (Display.CurrentDisplayMode == DisplayMode.PANAFALL && bIgnorePanafallWaterfall)
            {
                if (!rx2_enabled)
                {
                    // top half is available only
                    nMaxHeightRX1 = Display.PanafallSplitBarPos;//picDisplay.Height / 2;
                }
                else
                {
                    // top half, of top half is available only
                    nMaxHeightRX1 = picDisplay.Height / 4;
                }
            }

            if (rx1_enabled && rx == 1)
            {
                switch (Display.CurrentDisplayMode)
                {
                    case DisplayMode.PANADAPTER:
                    case DisplayMode.SPECTRUM:
                    case DisplayMode.HISTOGRAM:
                    case DisplayMode.PANAFALL:
                    case DisplayMode.WATERFALL:
                    case DisplayMode.PANASCOPE:
                    case DisplayMode.SPECTRASCOPE:
                        // check if we are anywhere over area that filters etc can be adjusted
                        if ((x >= 0 && x < picDisplay.Width) &&
                         (y < nMaxHeightRX1 && y >= nMinHeightRX1)) // + 10))
                        {
                            return true;
                        }

                        break;
                }
            }
            else if (rx2_enabled && rx == 2)
            {
                switch (Display.CurrentDisplayModeBottom)
                {
                    case DisplayMode.PANADAPTER:
                    case DisplayMode.SPECTRUM:
                    case DisplayMode.HISTOGRAM:
                    case DisplayMode.PANAFALL:
                    case DisplayMode.WATERFALL:
                    case DisplayMode.PANASCOPE:
                    case DisplayMode.SPECTRASCOPE:
                        // check if we are anywhere over area that filters etc can be adjusted
                        if ((x >= 0 && x < picDisplay.Width) &&
                         (y < nMaxHeightRX2 && y >= nMinHeightRX2)) // + 10))
                        {
                            return true;
                        }
                        break;
                }
            }

            return false;
        }

        //NOTCH MW0LGE
        private Point drag_notch_start_point;
        private double drag_notch_start_data = 0;
        private bool m_bDraggingNotch = false;
        private bool m_bDraggingNotchBW = false;
        private bool m_BDragginNotchBWRightSide = false;
        private int m_nNotchRX = 0; //MW0LGE_21e

        private MNotch m_objSelectedNotch;
        private MNotch SelectedNotch {
            get { return m_objSelectedNotch; }
            set {
                m_objSelectedNotch = value;
                Display.HighlightNotch = m_objSelectedNotch;
            }
        }
        private void notchMouseWheel(int wheelDelta)
        {
            if (SelectedNotch == null) return;

            double tmp = SelectedNotch.FWidth;

            if (Common.ShiftKeyDown) {
                tmp += wheelDelta;
            }
            else {
                tmp += wheelDelta * 10;
            }

            if (tmp < 0) tmp = 0;
            if (tmp > max_filter_width) tmp = max_filter_width;

            // check to see if outside frequency limits
            bool bOk = true;
            if (SelectedNotch.FCenter - (tmp / 2) < 0) bOk = false;
            if (SelectedNotch.FCenter + (tmp / 2) > max_freq * 1e6) bOk = false;

            if (bOk) changeNotchBW(SelectedNotch, tmp);
        }
        //END NOTCH

        private bool currentDSPhasTwoSidebands(int rx)
        {
            DSPMode dspMode;

            if (rx == 1)
                dspMode = rx1_dsp_mode;
            else
                dspMode = rx2_dsp_mode;

            return (dspMode == DSPMode.AM || dspMode == DSPMode.DSB || dspMode == DSPMode.FM || dspMode == DSPMode.SAM || dspMode == DSPMode.SPEC || dspMode == DSPMode.DRM);
        }
        private float agcCalOffset(int rx)
        {
            float agc_cal_offset;
            if (rx == 1)
            {
                switch (RX1AGCMode)
                {
                    case AGCMode.FIXD:
                        agc_cal_offset = 0.0f;
                        break;
                    default:
                        agc_cal_offset = 2.0f + (Display.RX1DisplayCalOffset +
                            (Display.RX1PreampOffset - Display.AlexPreampOffset) - Display.RX1FFTSizeOffset);
                        break;
                }
            }
            else //rx == 2
            {
                switch (RX2AGCMode)
                {
                    case AGCMode.FIXD:
                        agc_cal_offset = 0.0f;
                        break;
                    default:
                        agc_cal_offset = 2.0f + (Display.RX2DisplayCalOffset +
                            (Display.RX2PreampOffset - Display.AlexPreampOffset) - Display.RX2FFTSizeOffset); //MW0LGE_21k5 change to rx2
                        break;
                }
            }
            return agc_cal_offset;
        }
        unsafe private void picDisplay_MouseMove(object sender, MouseEventArgs e)
        {
            try
            {
                Cursor next_cursor = _useOutlinedCrossCursor ? _cross_outlined : Cursors.Cross;

                // get filter location information
                int filt_low_x = 0;
                int filt_high_x = 0;

                //MW0LGE_21h
                int RX1diff = HzToPixel((float)((VFOAFreq - CentreFrequency) * 1e6));
                int RX2diff = HzToPixel((float)((VFOBFreq - CentreRX2Frequency) * 1e6), 2);

                if (rx2_enabled && e.Y > picDisplay.Height / 2) // if RX2 is enabled and the cursor is in the lower half of the display
                {
                    if (_mox)
                    {
                        filt_low_x = HzToPixel(radio.GetDSPTX(0).TXFilterLow, 2);
                        filt_high_x = HzToPixel(radio.GetDSPTX(0).TXFilterHigh, 2);
                    }
                    else
                    {
                        //MW0LGE_21h changes so that CTUN on works for filter drag                        
                        filt_low_x = RX2diff + HzToPixel(radio.GetDSPRX(1, 0).RXFilterLow, 2) - HzToPixel(0.0f, 2);
                        filt_high_x = RX2diff + HzToPixel(radio.GetDSPRX(1, 0).RXFilterHigh, 2) - HzToPixel(0.0f, 2);
                    }
                }
                else
                {
                    if (_mox)
                    {
                        if (display_duplex) //[2.10.1.0] MW0LGE support duplex
                        {
                            filt_low_x = RX1diff + HzToPixel(radio.GetDSPTX(0).TXFilterLow) - HzToPixel(0.0f);
                            filt_high_x = RX1diff + HzToPixel(radio.GetDSPTX(0).TXFilterHigh) - HzToPixel(0.0f);
                        }
                        else
                        {
                            filt_low_x = HzToPixel(radio.GetDSPTX(0).TXFilterLow);
                            filt_high_x = HzToPixel(radio.GetDSPTX(0).TXFilterHigh);
                        }
                    }
                    else
                    {
                        //MW0LGE_21h changes so that CTUN on works for filter drag
                        filt_low_x = RX1diff + HzToPixel(radio.GetDSPRX(0, 0).RXFilterLow) - HzToPixel(0.0f);
                        filt_high_x = RX1diff + HzToPixel(radio.GetDSPRX(0, 0).RXFilterHigh) - HzToPixel(0.0f);
                    }
                }

                // get VFO A Sub + Filter location information
                int vfoa_sub_x = 0;
                int vfoa_sub_low_x = 0;
                int vfoa_sub_high_x = 0;
                if (chkEnableMultiRX.Checked && !_mox)
                {
                    if (!rx2_enabled)
                    {
                        vfoa_sub_x = HzToPixel((float)((VFOBFreq - VFOAFreq) * 1e6));
                        vfoa_sub_low_x = vfoa_sub_x + (HzToPixel(radio.GetDSPRX(0, 0).RXFilterLow) - HzToPixel(0.0f));
                        vfoa_sub_high_x = vfoa_sub_x + (HzToPixel(radio.GetDSPRX(0, 0).RXFilterHigh) - HzToPixel(0.0f));
                    }
                    else
                    {
                        vfoa_sub_x = HzToPixel((float)((VFOASubFreq - VFOAFreq) * 1e6));
                        vfoa_sub_low_x = vfoa_sub_x + (HzToPixel(radio.GetDSPRX(0, 1).RXFilterLow) - HzToPixel(0.0f));
                        vfoa_sub_high_x = vfoa_sub_x + (HzToPixel(radio.GetDSPRX(0, 1).RXFilterHigh) - HzToPixel(0.0f));
                    }
                }

                // get VFO B filter location information
                int vfob_low_x = 0;
                int vfob_high_x = 0;
                if (rx2_enabled)
                {
                    vfob_low_x = RX2diff + (HzToPixel(radio.GetDSPRX(1, 0).RXFilterLow, 2) - HzToPixel(0.0f, 2));
                    vfob_high_x = RX2diff + (HzToPixel(radio.GetDSPRX(1, 0).RXFilterHigh, 2) - HzToPixel(0.0f, 2));
                }

                rx1_grid_adjust = false;
                rx2_grid_adjust = false;

                bool bOverRX1 = overRX(e.X, e.Y, 1, true);
                bool bOverRX2 = overRX(e.X, e.Y, 2, true);
                #region Notches
                //NOTCH MW0LGE
                bool bDraggingAFilter = rx1_high_filter_drag || rx1_low_filter_drag || rx2_high_filter_drag || rx2_low_filter_drag ||
                    rx1_sub_drag || rx1_whole_filter_drag || rx2_whole_filter_drag || tx_low_filter_drag || tx_high_filter_drag || tx_whole_filter_drag ||
                    rx1_click_tune_drag || rx2_click_tune_drag;

                if (!SetupForm.NotchAdminBusy && !m_frmNotchPopup.Visible & !bDraggingAFilter) // only highlight/select if we are not actively adding/edditing via setup form, or the popup is hidden
                {
                    int nRX = 0;
                    if (bOverRX1 && (Display.CurrentDisplayMode == DisplayMode.PANADAPTER || Display.CurrentDisplayMode == DisplayMode.PANAFALL))
                    {
                        nRX = 1;
                    }
                    else if (bOverRX2 && (Display.CurrentDisplayModeBottom == DisplayMode.PANADAPTER || Display.CurrentDisplayModeBottom == DisplayMode.PANAFALL))
                    {
                        nRX = 2;
                    }

                    if (!m_bDraggingNotch && !m_bDraggingNotchBW && nRX != 0)
                    {
                        double dVfo = 0;
                        double dCentreFreq = 0;
                        int nL = 0;
                        int nH = 0;

                        if (nRX == 1)
                        {
                            dCentreFreq = CentreFrequency * 1e6;
                            dVfo = dCentreFreq + PixelToHz(e.X, 1);
                            nL = Display.RXDisplayLow;
                            nH = Display.RXDisplayHigh;
                            if (rx1_dsp_mode == DSPMode.CWL)
                                dVfo += (double)cw_pitch;
                            else if (rx1_dsp_mode == DSPMode.CWU)
                                dVfo -= (double)cw_pitch;
                        }
                        else if (nRX == 2)
                        {
                            dCentreFreq = CentreRX2Frequency * 1e6;
                            dVfo = dCentreFreq + PixelToHz(e.X, 2);
                            nL = Display.RX2DisplayLow;
                            nH = Display.RX2DisplayHigh;
                            if (rx2_dsp_mode == DSPMode.CWL)
                                dVfo += (double)cw_pitch;
                            else if (rx2_dsp_mode == DSPMode.CWU)
                                dVfo -= (double)cw_pitch;
                        }

                        if (nRX != 0)  // we are over a RX with the mouse
                        {
                            // ok are we over the top of a notch?
                            // we pad it with 1pixel worth of hz to make it selectable at low zoom
                            SelectedNotch = MNotchDB.NotchThatSurroundsFrequencyInBW(dCentreFreq, nL - max_filter_width, nH + max_filter_width, dVfo, HzInNPixels(1, nRX));
                        }
                        else
                        {
                            if (SelectedNotch != null) SelectedNotch = null;
                        }
                    }
                    else if (m_bDraggingNotch && nRX != 0)
                    {
                        // drag the whole notch
                        double diff = PixelToHz(e.X, nRX) - PixelToHz(drag_notch_start_point.X, nRX);

                        //MW0LGE_21e XVTR
                        double f = drag_notch_start_data + diff;
                        double tmpMin = min_freq;
                        double tmpMax = max_freq;
                        if (nRX == 1 && rx1_xvtr_index >= 0)
                        {
                            int nIndex = XVTRForm.XVTRFreq(f * 1e-6);
                            if (nIndex == rx1_xvtr_index)
                            {
                                tmpMin = XVTRForm.GetBegin(nIndex);
                                tmpMax = XVTRForm.GetEnd(nIndex);
                            }
                        }
                        else if (nRX == 2 && rx2_xvtr_index >= 0)
                        {
                            int nIndex = XVTRForm.XVTRFreq(f * 1e-6);
                            if (nIndex == rx2_xvtr_index)
                            {
                                tmpMin = XVTRForm.GetBegin(nIndex);
                                tmpMax = XVTRForm.GetEnd(nIndex);
                            }
                        }
                        //

                        if (SelectedNotch != null)
                        {
                            // check to see if outside frequency limits
                            bool bOk = true;
                            if (f - (SelectedNotch.FWidth / 2) < tmpMin * 1e6) bOk = false;
                            if (f + (SelectedNotch.FWidth / 2) > tmpMax * 1e6) bOk = false;

                            if (bOk)
                            {
                                SelectedNotch.FCenter = drag_notch_start_data + diff;
                                changeNotchCentreFrequency(SelectedNotch, SelectedNotch.FCenter, m_nNotchRX); //MW0LGE [2.9.0.7] update on drag
                            }
                        }
                    }
                    else if (m_bDraggingNotchBW && nRX != 0)
                    {
                        // drag the bw edges of the notch
                        double diff = 0;
                        if (m_BDragginNotchBWRightSide)
                        {
                            diff = PixelToHz(e.X, nRX) - PixelToHz(drag_notch_start_point.X, nRX);
                        }
                        else
                        {
                            diff = PixelToHz(drag_notch_start_point.X, nRX) - PixelToHz(e.X, nRX);
                        }

                        double tmp = drag_notch_start_data + (diff * 2); // we want double the diff, as we are doing 'both sides'

                        if (tmp < 0) tmp = 0;
                        if (tmp > max_filter_width) tmp = max_filter_width;

                        //MW0LGE_21e XVTR
                        double tmpMin = min_freq;
                        double tmpMax = max_freq;
                        if (nRX == 1 && rx1_xvtr_index >= 0)
                        {
                            int nIndex = XVTRForm.XVTRFreq(SelectedNotch.FCenter * 1e-6);
                            if (nIndex == rx1_xvtr_index)
                            {
                                tmpMin = XVTRForm.GetBegin(nIndex);
                                tmpMax = XVTRForm.GetEnd(nIndex);
                            }
                        }
                        else if (nRX == 2 && rx2_xvtr_index >= 0)
                        {
                            int nIndex = XVTRForm.XVTRFreq(SelectedNotch.FCenter * 1e-6);
                            if (nIndex == rx2_xvtr_index)
                            {
                                tmpMin = XVTRForm.GetBegin(nIndex);
                                tmpMax = XVTRForm.GetEnd(nIndex);
                            }
                        }
                        //
                        // check to see if outside frequency limits
                        bool bOk = true;
                        if (SelectedNotch.FCenter - (tmp / 2) < tmpMin * 1e6) bOk = false;
                        if (SelectedNotch.FCenter + (tmp / 2) > tmpMax * 1e6) bOk = false;

                        if (bOk)
                        {
                            SelectedNotch.FWidth = tmp;
                            changeNotchBW(SelectedNotch, SelectedNotch.FWidth);
                        }
                    }
                }
                //END NOTCH
                #endregion
                bool bHighlightNumberScaleRX1 = false;
                bool bHighlightNumberScaleRX2 = false;
                int nHighlightedBandStackEntryIndex = -1; // no bandstackoverlay highlighted

                if (bOverRX1 && !bDraggingAFilter)
                {
                    switch (Display.CurrentDisplayMode)
                    {
                        case DisplayMode.PANADAPTER:
                        case DisplayMode.SPECTRUM:
                        case DisplayMode.HISTOGRAM:
                        case DisplayMode.PANAFALL:
                        case DisplayMode.PANASCOPE:
                        case DisplayMode.SPECTRASCOPE:
                            // check if we are over scale on left
                            if (e.X > RX1display_grid_x && e.X < RX1display_grid_w)
                            {
                                if (gridminmaxadjust || gridmaxadjust) next_cursor = grabbing;
                                else next_cursor = grab;
                                rx1_grid_adjust = true;
                                bHighlightNumberScaleRX1 = true;
                            }
                            break;
                    }

                    #region BandStackHighlight
                    //BandstackOverlay highlight MW0LGE_21h
                    //only do this if not doing something else
                    if (m_bShowBandStackOverlays && bOverRX1 && !(rx1_sub_drag || bHighlightNumberScaleRX1 || bDraggingAFilter || m_bDraggingNotch || m_bDraggingNotchBW || m_bDraggingPanafallSplit))
                    {
                        if (Display.BandStackOverlays != null && Display.BandStackOverlays.Length > 0)
                        {
                            if (bOverRX1 && (Display.CurrentDisplayMode == DisplayMode.PANADAPTER || Display.CurrentDisplayMode == DisplayMode.PANAFALL))
                            {
                                // convert mouse pos into HZ
                                double nMousePosHZ = (CentreFrequency * 1e6) + PixelToHz(e.X, 1); // only rx1

                                for (int n = 0; n < Display.BandStackOverlays.Length; n++)
                                {
                                    BandStackEntry bse = Display.BandStackOverlays[n];

                                    double dL = (bse.Frequency * 1e6) + bse.LowFilter;
                                    double dH = (bse.Frequency * 1e6) + bse.HighFilter;

                                    if (dL <= nMousePosHZ && dH >= nMousePosHZ)
                                    {
                                        nHighlightedBandStackEntryIndex = n;
                                        break; // use first hit
                                    }
                                }
                            }
                        }
                    }
                    //
                    #endregion
                }

                if (rx2_enabled && bOverRX2 && !(bHighlightNumberScaleRX2 || bDraggingAFilter || m_bDraggingNotch || m_bDraggingNotchBW || m_bDraggingPanafallSplit))
                {
                    switch (Display.CurrentDisplayModeBottom)
                    {
                        case DisplayMode.PANADAPTER:
                        case DisplayMode.SPECTRUM:
                        case DisplayMode.HISTOGRAM:
                        case DisplayMode.PANAFALL:
                        case DisplayMode.PANASCOPE:
                        case DisplayMode.SPECTRASCOPE:
                            // check if we are over scale on left
                            if (e.X > RX2display_grid_x && e.X < RX2display_grid_w)
                            {
                                if (gridminmaxadjust || gridmaxadjust) next_cursor = grabbing;
                                else next_cursor = grab;
                                rx2_grid_adjust = true;
                                bHighlightNumberScaleRX2 = true;
                            }
                            break;
                    }
                }

                // update the display
                Display.HighlightNumberScaleRX1 = bHighlightNumberScaleRX1;
                Display.HighlightNumberScaleRX2 = bHighlightNumberScaleRX2;
                Display.HighlightedBandStackEntryIndex = nHighlightedBandStackEntryIndex;

                //MIDDLE OF PANAFALL MOVEUPDOWN MW0LGE
                if (!rx2_enabled && Display.CurrentDisplayMode == DisplayMode.PANAFALL)
                {
                    if (m_bDraggingPanafallSplit)
                    {
                        float f = (float)e.Y / (float)picDisplay.Height;
                        f = Math.Max(0.1f, f);
                        f = Math.Min(0.9f, f);
                        Display.PanafallSplitBarPerc = f;
                    }
                }
                //END SPLITTER DRAG

                #region GridAdjust
                if (rx1_grid_adjust || rx2_grid_adjust)
                {
                    if (rx1_grid_adjust)
                    {
                        if (gridminmaxadjust)
                        {
                            int delta_y = e.Y - grid_minmax_drag_start_point.Y;
                            double delta_db = (delta_y / 10) * Display.SpectrumGridStep;
                            float val = grid_minmax_max_y;
                            val += (float)delta_db;
                            float min_val = grid_minmax_min_y;
                            min_val += (float)delta_db;

                            if (min_val < -200)
                            {
                                min_val = -200;
                                if (val - min_val < 24) val = min_val + 24;
                            }

                            if (val > 200)
                            {
                                val = 200;
                                if (val - min_val < 24) min_val = val - 24;
                            }

                            if (!tx1_grid_adjust)
                            {
                                SetupForm.DisplayGridMax = val;
                                SetupForm.DisplayGridMin = min_val;

                                //MW0LGE
                                if (m_bWaterfallUseRX1SpectrumMinMax)
                                {
                                    // use display directly so we dont change any band based thresholds in setupform
                                    Display.WaterfallHighThreshold = val;
                                    Display.WaterfallLowThreshold = min_val;
                                }

                                //MW0LGE_21d set rx2 grid - change to shift key
                                if (Common.ShiftKeyDown && RX2Enabled)
                                {
                                    SetupForm.RX2DisplayGridMax = val;
                                    SetupForm.RX2DisplayGridMin = min_val;

                                    if (m_bWaterfallUseRX2SpectrumMinMax)
                                    {
                                        // use display directly so we dont change any band based thresholds in setupform
                                        Display.RX2WaterfallHighThreshold = val;
                                        Display.RX2WaterfallLowThreshold = min_val;
                                    }
                                }
                            }
                            else
                            {
                                SetupForm.TXGridMax = val;
                                SetupForm.TXGridMin = min_val;
                            }
                        }

                        if (gridmaxadjust)
                        {
                            int delta_y = e.Y - grid_minmax_drag_start_point.Y;
                            double delta_db = (delta_y / 10) * Display.SpectrumGridStep;
                            float val = grid_minmax_max_y;
                            val += (float)delta_db;

                            if (!tx1_grid_adjust)
                            {
                                if (val - SetupForm.DisplayGridMin < 24) val = SetupForm.DisplayGridMin + 24;

                                SetupForm.DisplayGridMax = val;

                                //MW0LGE
                                if (m_bWaterfallUseRX1SpectrumMinMax)
                                {
                                    // use display directly so we dont change any band based thresholds in setupform
                                    Display.WaterfallHighThreshold = val;
                                }

                                //MW0LGE_21d set rx2 grid - changed to shift key
                                if (Common.ShiftKeyDown && RX2Enabled)
                                {
                                    SetupForm.RX2DisplayGridMax = val;

                                    if (m_bWaterfallUseRX2SpectrumMinMax)
                                    {
                                        // use display directly so we dont change any band based thresholds in setupform
                                        Display.RX2WaterfallHighThreshold = val;
                                    }
                                }
                            }
                            else
                            {
                                if (val - SetupForm.TXGridMin < 24) val = SetupForm.TXGridMin + 24;

                                SetupForm.TXGridMax = val;
                            }
                        }
                    }
                    else if (rx2_grid_adjust)
                    {
                        if (gridminmaxadjust)
                        {
                            int delta_y = e.Y - grid_minmax_drag_start_point.Y;
                            double delta_db = (delta_y / 10) * Display.SpectrumGridStep;
                            float val = grid_minmax_max_y;
                            val += (float)delta_db;
                            float min_val = grid_minmax_min_y;
                            min_val += (float)delta_db;

                            if (min_val < -200)
                            {
                                min_val = -200;
                                if (val - min_val < 24) val = min_val + 24;
                            }

                            if (val > 200)
                            {
                                val = 200;
                                if (val - min_val < 24) min_val = val - 24;
                            }

                            if (!tx2_grid_adjust)
                            {
                                SetupForm.RX2DisplayGridMax = val;
                                SetupForm.RX2DisplayGridMin = min_val;

                                //MW0LGE
                                if (m_bWaterfallUseRX2SpectrumMinMax)
                                {
                                    // use display directly so we dont change any band based thresholds in setupform
                                    Display.RX2WaterfallHighThreshold = val;
                                    Display.RX2WaterfallLowThreshold = min_val;
                                }

                                //MW0LGE_21d set rx1 grid - changed to shift key
                                if (Common.ShiftKeyDown)
                                {
                                    SetupForm.DisplayGridMax = val;
                                    SetupForm.DisplayGridMin = min_val;

                                    if (m_bWaterfallUseRX2SpectrumMinMax)
                                    {
                                        // use display directly so we dont change any band based thresholds in setupform
                                        Display.WaterfallHighThreshold = val;
                                        Display.WaterfallLowThreshold = min_val;
                                    }
                                }
                            }
                            else
                            {
                                SetupForm.TXGridMax = val;
                                SetupForm.TXGridMin = min_val;
                            }
                        }
                        if (gridmaxadjust)
                        {
                            int delta_y = e.Y - grid_minmax_drag_start_point.Y;
                            double delta_db = (delta_y / 10) * Display.SpectrumGridStep;
                            float val = grid_minmax_max_y;
                            val += (float)delta_db;

                            if (!tx2_grid_adjust)
                            {
                                if (val - SetupForm.RX2DisplayGridMin < 24) val = SetupForm.RX2DisplayGridMin + 24;

                                SetupForm.RX2DisplayGridMax = val;

                                //MW0LGE
                                if (m_bWaterfallUseRX2SpectrumMinMax)
                                {
                                    // use display directly so we dont change any band based thresholds in setupform
                                    Display.RX2WaterfallHighThreshold = val;
                                }

                                //MW0LGE_21d set rx1 grid - changed to shift key
                                if (Common.ShiftKeyDown)
                                {
                                    SetupForm.DisplayGridMax = val;

                                    if (m_bWaterfallUseRX2SpectrumMinMax)
                                    {
                                        // use display directly so we dont change any band based thresholds in setupform
                                        Display.WaterfallHighThreshold = val;
                                    }
                                }
                            }
                            else
                            {
                                if (val - SetupForm.TXGridMin < 24) val = SetupForm.TXGridMin + 24;

                                SetupForm.TXGridMax = val;
                            }
                        }
                    }
                }
                #endregion

                //MW0LGE_21k9
                bool bShowCursorData = false;
                //

                // TCI SPOTS
                _highlightedSpot = SpotManager2.HighlightSpot(e.X, e.Y);
                //

                #region AGC, Filter Dragging and edge highlighting
                switch (Display.CurrentDisplayMode)
                {
                    case DisplayMode.HISTOGRAM:
                    case DisplayMode.SPECTRUM:
                        bShowCursorData = true;
                        break;
                    case DisplayMode.PANADAPTER:
                    case DisplayMode.WATERFALL:
                    case DisplayMode.PANAFALL:
                    case DisplayMode.PANASCOPE:
                        bShowCursorData = true;
                        switch (Display.CurrentDisplayMode)
                        {
                            case DisplayMode.PANAFALL:
                            case DisplayMode.PANASCOPE:
                            case DisplayMode.PANADAPTER:
                                float cal_offset = 0.0f;
                                if (rx2_enabled && e.Y > picDisplay.Height / 2)
                                    cal_offset = agcCalOffset(2);
                                else
                                    cal_offset = agcCalOffset(1);

                                if (!_mox)
                                {
                                    if (show_agc)
                                    {
                                        if (rx2_enabled && e.Y > picDisplay.Height / 2)
                                        {
                                            if (Display.AGCRX2Knee.Contains(e.X, e.Y))
                                            {
                                                if (agc_knee_drag) next_cursor = grabbing;
                                                else next_cursor = grab;
                                            }
                                            if (Display.AGCRX2Hang.Contains(e.X, e.Y))
                                            {
                                                if (agc_hang_drag) next_cursor = grabbing;
                                                else next_cursor = grab;
                                            }
                                        }
                                        else
                                        {
                                            if (Display.AGCKnee.Contains(e.X, e.Y))
                                            {
                                                if (agc_knee_drag) next_cursor = grabbing;
                                                else next_cursor = grab;
                                            }
                                            if (Display.AGCHang.Contains(e.X, e.Y))
                                            {
                                                if (agc_hang_drag) next_cursor = grabbing;
                                                else next_cursor = grab;
                                            }
                                        }
                                    }
                                }

                                if (agc_knee_drag && show_agc)
                                {
                                    if (rx2_enabled && e.Y > picDisplay.Height / 2)
                                    {
                                        double agc_rx2_thresh_point = (double)PixelToRx2Db(e.Y + 4);
                                        agc_rx2_thresh_point -= (double)cal_offset;
                                        if (agc_rx2_thresh_point > 2) agc_rx2_thresh_point = 2;
                                        if (agc_rx2_thresh_point < -143.0) agc_rx2_thresh_point = -143.0;

                                        double agc_rx2_top = 0.0;

                                        double size = (double)specRX.GetSpecRX(1).FFTSize; // MW0LGE_21k7
                                        WDSP.SetRXAAGCThresh(WDSP.id(2, 0), agc_rx2_thresh_point, size/*4096.0*/, sample_rate_rx2); //MW0LGE_21k5 was sample_rate_rx1

                                        WDSP.GetRXAAGCTop(WDSP.id(2, 0), &agc_rx2_top);

                                        agc_rx2_top = Math.Round(agc_rx2_top);

                                        switch (RX2AGCMode)
                                        {
                                            case AGCMode.FIXD:
                                                if (agc_rx2_top > 120) agc_rx2_top = 120;
                                                if (agc_rx2_top < -20.0) agc_rx2_top = -20.0;

                                                if (!IsSetupFormNull) SetupForm.AGCRX2FixedGain = (int)agc_rx2_top;// agc_top;
                                                break;
                                            default:
                                                if (agc_rx2_top > 120) agc_rx2_top = 120;
                                                if (agc_rx2_top < -20.0) agc_rx2_top = -20.0;

                                                if (!IsSetupFormNull) SetupForm.AGCRX2MaxGain = (int)agc_rx2_top;
                                                break;
                                        }
                                    }
                                    else
                                    {
                                        double agc_thresh_point = (double)PixelToDb(e.Y + 4);
                                        agc_thresh_point -= (double)cal_offset;
                                        if (agc_thresh_point > 2) agc_thresh_point = 2;
                                        if (agc_thresh_point < -160.0) agc_thresh_point = -160.0; //[2.10.3.6]MW0LGE changed from -143

                                        double agc_top = 0.0;

                                        double size = (double)specRX.GetSpecRX(0).FFTSize; // MW0LGE_21k7
                                        WDSP.SetRXAAGCThresh(WDSP.id(0, 0), agc_thresh_point, size, sample_rate_rx1);

                                        WDSP.GetRXAAGCTop(WDSP.id(0, 0), &agc_top);
                                        agc_top = Math.Round(agc_top);

                                        switch (RX1AGCMode)
                                        {
                                            case AGCMode.FIXD:
                                                if (agc_top > 120) agc_top = 120;
                                                if (agc_top < -20.0) agc_top = -20.0;

                                                if (!IsSetupFormNull) SetupForm.AGCFixedGain = (int)agc_top;
                                                break;
                                            default:
                                                if (agc_top > 120) agc_top = 120;
                                                if (agc_top < -20.0) agc_top = -20.0;

                                                if (!IsSetupFormNull) SetupForm.AGCMaxGain = (int)agc_top;
                                                break;
                                        }
                                    }
                                }

                                if (agc_hang_drag && show_agc)
                                {
                                    if (rx2_enabled && e.Y > picDisplay.Height / 2)
                                    {
                                        double agc_hang_point = (double)PixelToRx2Db(e.Y + 4);
                                        agc_hang_point -= (double)cal_offset;

                                        if (agc_hang_point > 4.0) agc_hang_point = 4.0;
                                        if (agc_hang_point < -121.0) agc_hang_point = -121.0;

                                        int hang_threshold = 0;

                                        WDSP.SetRXAAGCHangLevel(WDSP.id(2, 0), agc_hang_point);

                                        WDSP.GetRXAAGCHangThreshold(WDSP.id(2, 0), &hang_threshold);
                                        if (hang_threshold > 100)
                                        {
                                            hang_threshold = 100;
                                        }
                                        if (hang_threshold < 0) hang_threshold = 0;

                                        if (!IsSetupFormNull) SetupForm.AGCRX2HangThreshold = hang_threshold;
                                    }
                                    else
                                    {
                                        double agc_hang_point = (double)PixelToDb(e.Y + 4);
                                        agc_hang_point -= (double)cal_offset;
 
                                        if (agc_hang_point > 4.0) agc_hang_point = 4.0;
                                        if (agc_hang_point < -121.0) agc_hang_point = -121.0;

                                        int hang_threshold = 0;

                                        WDSP.SetRXAAGCHangLevel(WDSP.id(0, 0), agc_hang_point);

                                        WDSP.GetRXAAGCHangThreshold(WDSP.id(0, 0), &hang_threshold);
                                        if (hang_threshold > 100)
                                        {
                                            hang_threshold = 100;

                                        }
                                        if (hang_threshold < 0) hang_threshold = 0;

                                        if (!IsSetupFormNull) SetupForm.AGCRX1HangThreshold = hang_threshold;
                                    }
                                }
                                break;
                            case DisplayMode.WATERFALL:
                                break;
                        }

                        bool bOkToChangeRX1 = bOverRX1 && rx1_enabled && !rx1_click_tune_drag && !rx1_spectrum_drag && (rx1_dsp_mode != DSPMode.DRM) && !(_mox && (VFOATX || (RX2Enabled && VFOSplit))); //[2.10.1.0] MW0LGE prevent highlight when MOX
                        bool bOkToChangeRX2 = bOverRX2 && rx2_enabled && !rx2_click_tune_drag && !rx2_spectrum_drag && (rx2_dsp_mode != DSPMode.DRM) && !(_mox && RX2Enabled && VFOBTX);

                        if (bOkToChangeRX1 || bOkToChangeRX2)
                        {
                            if (!rx1_spectrum_tune_drag && !rx2_spectrum_tune_drag && current_click_tune_mode == ClickTuneMode.Off)
                            {
                                bool bLowEdge = (bOkToChangeRX1 && (!rx1_whole_filter_drag && (Math.Abs(e.X - filt_low_x) < 3 || rx1_low_filter_drag))) ||
                                                (bOkToChangeRX2 && (!rx2_whole_filter_drag && (Math.Abs(e.X - vfob_low_x) < 3 || rx2_low_filter_drag)));

                                bool bHighEdge = (bOkToChangeRX1 && (!rx1_whole_filter_drag && (Math.Abs(e.X - filt_high_x) < 3 || rx1_high_filter_drag))) ||
                                                 (bOkToChangeRX2 && (!rx2_whole_filter_drag && (Math.Abs(e.X - vfob_high_x) < 3 || rx2_high_filter_drag)));

                                int highlightRX1 = 0;
                                int highlightRX2 = 0;

                                if (bLowEdge || bHighEdge)
                                {
                                    next_cursor = Cursors.SizeWE;

                                    //MW0LGE_21h
                                    if (bOkToChangeRX1)
                                    {
                                        if (bLowEdge && !bHighEdge) highlightRX1 = -1;
                                        else if (!bLowEdge && bHighEdge) highlightRX1 = 1;
                                    }
                                    else if (bOkToChangeRX2)
                                    {
                                        if (bLowEdge && !bHighEdge) highlightRX2 = -1;
                                        else if (!bLowEdge && bHighEdge) highlightRX2 = 1;
                                    }
                                }
                                else if (bOverRX1 && e.X > filt_low_x && e.X < filt_high_x)
                                {
                                    // middle of the filter, but only when in CTUN on, or holding shift
                                    if ((click_tune_display || Common.ShiftKeyDown) && _highlightedSpot == null)
                                        next_cursor = Cursors.NoMoveHoriz;
                                }
                                else if (bOverRX2 && e.X > vfob_low_x && e.X < vfob_high_x)
                                {
                                    // middle of the filter, but only when in CTUN on, or holding shift
                                    if ((click_tune_rx2_display || Common.ShiftKeyDown) && _highlightedSpot == null)
                                        next_cursor = Cursors.NoMoveHoriz;
                                }

                                //MW0LGE_21k9 added the filter info onto the cursor info, also done below on the filter drags
                                if (highlightRX1 == -1)
                                    Display.OtherData2CursorDisplay = radio.GetDSPRX(0, 0).RXFilterLow.ToString();
                                else if (highlightRX1 == 1)
                                    Display.OtherData2CursorDisplay = radio.GetDSPRX(0, 0).RXFilterHigh.ToString();

                                if (highlightRX2 == -1)
                                    Display.OtherData2CursorDisplay = radio.GetDSPRX(1, 0).RXFilterLow.ToString();
                                else if (highlightRX2 == 1)
                                    Display.OtherData2CursorDisplay = radio.GetDSPRX(1, 0).RXFilterHigh.ToString();

                                if (highlightRX1 == 0 && highlightRX2 == 0) Display.OtherData2CursorDisplay = "";
                                //

                                Display.HightlightFilterEdgeRX1 = highlightRX1;
                                Display.HightlightFilterEdgeRX2 = highlightRX2;
                            }

                            if (rx1_high_filter_drag)
                            {
                                int lowerLimit;
                                int new_low;

                                bool bMirrorSidebands = Common.ShiftKeyDown && currentDSPhasTwoSidebands(1);

                                if (bMirrorSidebands)
                                    lowerLimit = 10;
                                else
                                    lowerLimit = radio.GetDSPRX(0, 0).RXFilterLow + 10;

                                int new_high = (int)Math.Max(HzInNPixels(e.X - RX1diff, 1), lowerLimit);

                                if (bMirrorSidebands)
                                    new_low = -new_high;
                                else
                                    new_low = radio.GetDSPRX(0, 0).RXFilterLow;

                                SelectRX1VarFilter(false);

                                UpdateRX1Filters(new_low, new_high);

                                //update VAR1 low to be current low
                                rx1_filters[(int)rx1_dsp_mode].SetLow(Filter.VAR1, m_nLowOutRX1);
                                //update VAR1 high to be new high
                                rx1_filters[(int)rx1_dsp_mode].SetHigh(Filter.VAR1, m_nHighOutRX1);

                                Display.OtherData2CursorDisplay = radio.GetDSPRX(0, 0).RXFilterHigh.ToString();
                            }
                            else if (rx1_low_filter_drag)
                            {
                                int upperLimit;
                                int new_high;

                                bool bMirrorSidebands = Common.ShiftKeyDown && currentDSPhasTwoSidebands(1);

                                if (bMirrorSidebands)
                                    upperLimit = -10;
                                else
                                    upperLimit = radio.GetDSPRX(0, 0).RXFilterHigh - 10;

                                int new_low = (int)Math.Min(HzInNPixels(e.X - RX1diff, 1), upperLimit);

                                if (bMirrorSidebands)
                                    new_high = new_low * -1;
                                else
                                    new_high = radio.GetDSPRX(0, 0).RXFilterHigh;

                                SelectRX1VarFilter(false);

                                UpdateRX1Filters(new_low, new_high);

                                //update VAR1 low to be new low
                                rx1_filters[(int)rx1_dsp_mode].SetLow(Filter.VAR1, m_nLowOutRX1);
                                //update VAR1 high to be current high
                                rx1_filters[(int)rx1_dsp_mode].SetHigh(Filter.VAR1, m_nHighOutRX1);

                                Display.OtherData2CursorDisplay = radio.GetDSPRX(0, 0).RXFilterLow.ToString();
                            }
                            else if (rx1_whole_filter_drag)
                            {
                                SelectRX1VarFilter(false);
                                int diff = (int)(PixelToHz(e.X) - PixelToHz(whole_filter_start_x));
                                int nLow = whole_filter_start_low + diff;
                                int nHigh = whole_filter_start_high + diff;
                                limitFilterToSidebands(ref nLow, ref nHigh, 1, true);
                                UpdateRX1Filters(nLow, nHigh);
                            }
                            else if (rx1_sub_drag)
                            {
                                int diff = (int)(PixelToHz(e.X) - PixelToHz(sub_drag_last_x));
                                if (rx2_enabled)
                                    VFOASubFreq = sub_drag_start_freq + diff * 1e-6;
                                else VFOBFreq = sub_drag_start_freq + diff * 1e-6;
                            }
                            else if (rx2_high_filter_drag)
                            {
                                int lowerLimit;
                                int new_low;

                                bool bMirrorSidebands = Common.ShiftKeyDown && currentDSPhasTwoSidebands(2);

                                if (bMirrorSidebands)
                                    lowerLimit = 10;
                                else
                                    lowerLimit = radio.GetDSPRX(1, 0).RXFilterLow + 10;

                                int new_high = (int)Math.Max(HzInNPixels(e.X - RX2diff, 2), lowerLimit);

                                if (bMirrorSidebands)
                                    new_low = -new_high;
                                else
                                    new_low = radio.GetDSPRX(1, 0).RXFilterLow;

                                SelectRX2VarFilter(false);

                                UpdateRX2Filters(new_low, new_high);

                                //update VAR1 low to be current low
                                rx2_filters[(int)rx2_dsp_mode].SetLow(Filter.VAR1, m_nLowOutRX2);
                                //update VAR1 high to be new high
                                rx2_filters[(int)rx2_dsp_mode].SetHigh(Filter.VAR1, m_nHighOutRX2);

                                Display.OtherData2CursorDisplay = radio.GetDSPRX(1, 0).RXFilterHigh.ToString();
                            }
                            else if (rx2_low_filter_drag)
                            {
                                int upperLimit;
                                int new_high;

                                bool bMirrorSidebands = Common.ShiftKeyDown && currentDSPhasTwoSidebands(2);

                                if (bMirrorSidebands)
                                    upperLimit = -10;
                                else
                                    upperLimit = radio.GetDSPRX(1, 0).RXFilterHigh - 10;

                                int new_low = (int)Math.Min(HzInNPixels(e.X - RX2diff, 2), upperLimit);

                                if (bMirrorSidebands)
                                    new_high = new_low * -1;
                                else
                                    new_high = radio.GetDSPRX(1, 0).RXFilterHigh;

                                SelectRX2VarFilter(false);

                                UpdateRX2Filters(new_low, new_high);

                                //update VAR1 low to be new low
                                rx2_filters[(int)rx2_dsp_mode].SetLow(Filter.VAR1, m_nLowOutRX2);
                                //update VAR1 high to be current high
                                rx2_filters[(int)rx2_dsp_mode].SetHigh(Filter.VAR1, m_nHighOutRX2);

                                Display.OtherData2CursorDisplay = radio.GetDSPRX(1, 0).RXFilterLow.ToString();
                            }
                            else if (rx2_whole_filter_drag)
                            {
                                SelectRX2VarFilter(false);
                                int diff = (int)(PixelToHz(e.X, 2) - PixelToHz(whole_filter_start_x, 2));
                                int nLow = whole_filter_start_low + diff;
                                int nHigh = whole_filter_start_high + diff;
                                limitFilterToSidebands(ref nLow, ref nHigh, 2, true);
                                UpdateRX2Filters(nLow, nHigh);
                            }
                            else if (tx_high_filter_drag)
                            {
                                int new_high = (int)Math.Max(Math.Abs(PixelToHz(e.X)), tx_filter_low + 10);
                                SetupForm.TXFilterHigh = new_high;
                            }
                            else if (tx_low_filter_drag)
                            {
                                int new_low = (int)(Math.Min(Math.Abs(PixelToHz(e.X)), tx_filter_high - 10));
                                SetupForm.TXFilterLow = new_low;
                            }
                            else if (tx_whole_filter_drag)
                            {
                                int diff = (int)(PixelToHz(e.X) - PixelToHz(whole_filter_start_x));
                                switch (rx1_dsp_mode)
                                {
                                    case DSPMode.LSB:
                                    case DSPMode.DIGL:
                                        SetupForm.TXFilterLow = whole_filter_start_low - diff;
                                        SetupForm.TXFilterHigh = whole_filter_start_high - diff;
                                        break;
                                    case DSPMode.USB:
                                    case DSPMode.DIGU:
                                        SetupForm.TXFilterLow = whole_filter_start_low + diff;
                                        SetupForm.TXFilterHigh = whole_filter_start_high + diff;
                                        break;
                                    case DSPMode.AM:
                                    case DSPMode.SAM:
                                    case DSPMode.FM:
                                    case DSPMode.DSB:
                                        SetupForm.TXFilterHigh = whole_filter_start_high + diff;
                                        break;
                                }
                            }
                        }

                        break;
                    default:

                        break;
                }
                #endregion

                #region Cursor and Info bar data
                //re-implemented cursor info MW0LGE_21k9
                if (bShowCursorData)
                {
                    float xposHz = 0;
                    float y = 0;
                    double rf_freq;
                    string temp_text;
                    int jper;

                    double localFreq;
                    double loclCentreFrequency;
                    bool localClickTuneDisplay;
                    DSPMode localDSPMode;
                    bool bShowDBM = false;
                    bool bShowWaterfallSeconds = false;

                    bool bOn60mChan;
                    bool bRx2 = rx2_enabled && e.Y > picDisplay.Height / 2; // if RX2 is enabled and the cursor is in the lower half of the display

                    if (bRx2)
                    {
                        localDSPMode = RX2DSPMode;
                        bOn60mChan = RX2IsOn60mChannel();
                        xposHz = PixelToHz(e.X, 2);
                        double localVFOfreq = Display.VFOB * 1e-6; //[2.10.1.0] MW0LGE change to use the display VFO as that is what we are considering
                        rf_freq = localVFOfreq + (double)xposHz * 1e-6;
                        localFreq = localVFOfreq;
                        loclCentreFrequency = CentreRX2Frequency;
                        localClickTuneDisplay = click_tune_rx2_display;

                        switch (Display.CurrentDisplayModeBottom)
                        {
                            case DisplayMode.PANADAPTER:
                                bShowDBM = true;
                                bShowWaterfallSeconds = false;
                                break;
                            case DisplayMode.PANAFALL:
                                bShowDBM = e.Y > ((picDisplay.Height / 2) + 8) && e.Y < ((picDisplay.Height / 2) + (picDisplay.Height / 4)); // +8 for the splitter, which is normally 16 pixels, but is now half height as we are displaying rx1+rx2
                                bShowWaterfallSeconds = e.Y >= ((picDisplay.Height / 2) + (picDisplay.Height / 4)) + 16;
                                break;
                            case DisplayMode.WATERFALL:
                                bShowDBM = false;
                                bShowWaterfallSeconds = e.Y > (picDisplay.Height / 2) + 16;
                                break;
                        }

                        if (bShowDBM) y = PixelToRx2Db(e.Y);
                        else if (bShowWaterfallSeconds) y = WaterfallPixelToTime(e.Y, 2);
                    }
                    else
                    {
                        localDSPMode = RX1DSPMode;
                        bOn60mChan = RX1IsOn60mChannel();
                        xposHz = PixelToHz(e.X, 1);
                        double localVFOfreq = Display.VFOA * 1e-6; //[2.10.1.0] MW0LGE change to use the display VFO as that is what we are considering
                        rf_freq = localVFOfreq + (double)xposHz * 1e-6;
                        localFreq = localVFOfreq;
                        loclCentreFrequency = CentreFrequency;
                        localClickTuneDisplay = click_tune_display;

                        switch (Display.CurrentDisplayMode)
                        {
                            case DisplayMode.HISTOGRAM:
                            case DisplayMode.SPECTRASCOPE:
                            case DisplayMode.SPECTRUM:
                            case DisplayMode.PANADAPTER:
                                bShowDBM = true;
                                bShowWaterfallSeconds = false;
                                break;
                            case DisplayMode.PANAFALL:
                                bShowDBM = !rx2_enabled ? e.Y < Display.PanafallSplitBarPos : e.Y < picDisplay.Height / 4;
                                bShowWaterfallSeconds = !rx2_enabled ? e.Y >= Display.PanafallSplitBarPos + 16 : e.Y < picDisplay.Height / 2 && e.Y >= (picDisplay.Height / 4) + 16;
                                break;
                            case DisplayMode.PANASCOPE:
                                bShowDBM = e.Y < picDisplay.Height / 2;
                                bShowWaterfallSeconds = false;
                                break;
                            case DisplayMode.WATERFALL:
                                bShowDBM = false;
                                bShowWaterfallSeconds = e.Y > 16;
                                break;
                        }

                        if (bShowDBM) y = PixelToDb(e.Y);
                        else if (bShowWaterfallSeconds) y = WaterfallPixelToTime(e.Y, 1);
                    }

                    DisplayCursorX = e.X; // update display cursor position (crosshairs)
                    DisplayCursorY = e.Y;
                    Display.MouseFrequency = xposHz; // for the filter overlay

                    switch (localDSPMode)
                    {
                        case DSPMode.CWL:
                            rf_freq += cw_pitch * 1e-6;
                            break;
                        case DSPMode.CWU:
                            rf_freq -= cw_pitch * 1e-6;
                            break;
                        case DSPMode.AM:
                        case DSPMode.SAM:
                        case DSPMode.FM:
                            break;
                        case DSPMode.USB:
                        case DSPMode.DIGU:
                        case DSPMode.DSB:
                            break;
                        case DSPMode.LSB:
                        case DSPMode.DIGL:
                            break;
                    }

                    infoBar.Left1(0, xposHz.ToString("f1") + "Hz");

                    bool localMox = _mox && ((RX2Enabled && (!bRx2 && VFOATX) || (bRx2 && VFOBTX)) || !RX2Enabled); //[2.10.1.0] MW0LGE consider if we are over the RX that is in mox
                    if ((localClickTuneDisplay && !localMox) || (localClickTuneDisplay && (display_duplex && !bRx2)))    // Correct cursor frequency when CTUN on -G3OQD  // MW0LGE_21a also when in CTD and DUP //[2.10.1.0] MW0LGE ignore rx2 if dup
                        rf_freq += (loclCentreFrequency - localFreq);

                    temp_text = rf_freq.ToString("f6") + " MHz";      // Disply cursor frequency under Spectrum  
                    jper = temp_text.IndexOf(separator) + 4;

                    string sTmp = temp_text.Insert(jper, " ");

                    infoBar.Left3(0, sTmp);

                    Display.MHzCursorDisplay = sTmp;

                    if (bShowDBM)
                        sTmp = y.ToString("f1") + "dBm";
                    else if (bShowWaterfallSeconds)
                        sTmp = (y / 1000.0f).ToString("f1") + "sec";
                    else
                        sTmp = "";

                    infoBar.Left2(0, sTmp);

                    Display.OtherData1CursorDisplay = sTmp;
                }
                else
                {
                    infoBar.Left1(0, "");
                    infoBar.Left2(0, "");
                    infoBar.Left3(0, "");
                }
                #endregion

                #region Dragging
                if (rx1_spectrum_tune_drag)
                {
                    if (!_mox || (rx2_enabled && chkVFOBTX.Checked))
                    {
                        float start_freq = PixelToHz(spectrum_drag_last_x);
                        float end_freq = PixelToHz(e.X);
                        spectrum_drag_last_x = e.X;
                        float delta = end_freq - start_freq;
                        CentreFrequency -= delta * 0.0000010;
                        txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                    }
                }

                if (rx2_spectrum_tune_drag)
                {
                    if (rx2_enabled && (!_mox || chkVFOATX.Checked))
                    {
                        float start_freq = PixelToHz(spectrum_drag_last_x, 2);
                        float end_freq = PixelToHz(e.X, 2);
                        spectrum_drag_last_x = e.X;
                        float delta = end_freq - start_freq;
                        CentreRX2Frequency -= delta * 0.0000010;
                        txtVFOBFreq_LostFocus(this, EventArgs.Empty);
                    }
                }


                if (rx1_spectrum_drag)
                {
                    if (!_mox || (rx2_enabled && chkVFOBTX.Checked))
                    {
                        float start_freq = PixelToHz(spectrum_drag_last_x);
                        float end_freq = PixelToHz(e.X);
                        spectrum_drag_last_x = e.X;
                        float delta = end_freq - start_freq;
                        VFOAFreq -= delta * 0.0000010;
                    }
                }

                if (rx2_spectrum_drag)
                {
                    if (rx2_enabled && (!_mox || chkVFOATX.Checked))
                    {
                        float start_freq = PixelToHz(spectrum_drag_last_x, 2);
                        float end_freq = PixelToHz(e.X, 2);
                        spectrum_drag_last_x = e.X;
                        float delta = end_freq - start_freq;
                        VFOBFreq -= delta * 0.0000010;
                    }
                }

                if (rx1_click_tune_drag)
                {
                    if (!_mox || (rx2_enabled && chkVFOBTX.Checked))
                    {
                        float start_freq = PixelToHz(spectrum_drag_last_x);
                        float end_freq = PixelToHz(e.X);
                        spectrum_drag_last_x = e.X;
                        float delta = start_freq - end_freq;
                        VFOAFreq -= delta * 0.0000010;
                    }
                }

                if (rx2_click_tune_drag)
                {
                    if (rx2_enabled && (!_mox || chkVFOATX.Checked))
                    {
                        float start_freq = PixelToHz(spectrum_drag_last_x, 2);
                        float end_freq = PixelToHz(e.X, 2);
                        spectrum_drag_last_x = e.X;
                        float delta = start_freq - end_freq;
                        VFOBFreq -= delta * 0.0000010;
                    }
                }
                #endregion

                // top drag area - this will override hover over filter
                if (bOverRX2 && e.Y < ((picDisplay.Height / 2) + 15))
                    next_cursor = Cursors.SizeWE;
                else if (bOverRX1 && e.Y < 15)
                    next_cursor = Cursors.SizeWE;
                //

                if ((!rx2_enabled && Display.CurrentDisplayMode == DisplayMode.PANAFALL) && m_bDraggingPanafallSplit) //MW0LGE_21k9c changes to this and below
                    next_cursor = Cursors.SizeNS; // down here so we catch moving out of the splitter bar, but is still enabled
                                                  // otherwise we get flickering

                // nothing applied yet
                if (next_cursor == Cursors.Cross || next_cursor == _cross_outlined)
                {
                    if (agc_knee_drag || agc_hang_drag) next_cursor = grabbing; // agc grab handles
                    else if (rx1_spectrum_drag || rx2_spectrum_drag || rx1_spectrum_tune_drag || rx2_spectrum_tune_drag) next_cursor = Cursors.SizeWE; // dragging the spectrum
                    else if (rx1_click_tune_drag || rx2_click_tune_drag) next_cursor = grabbing; // dragging the tune in CTUN on mode
                    else if ((!rx2_enabled && Display.CurrentDisplayMode == DisplayMode.PANAFALL) && e.Y >= Display.PanafallSplitBarPos && e.Y < Display.PanafallSplitBarPos + 20) next_cursor = Cursors.SizeNS; // over the splitter
                }

                picDisplay.Cursor = next_cursor;
            }
            catch (Exception)
            {

            }
        }
        private void getFilterEdgesInPixels(MouseEventArgs e, ref int low_x, ref int high_x, ref int vfoa_sub_x, ref int vfoa_sub_low_x, ref int vfoa_sub_high_x)
        {
            if (rx2_enabled && e.Y > picDisplay.Height / 2)//rx2
            {
                if (_mox)
                {
                    if (VFOBTX)
                    {
                        low_x = HzToPixel(radio.GetDSPTX(0).TXFilterLow, 2);
                        high_x = HzToPixel(radio.GetDSPTX(0).TXFilterHigh, 2);
                    }
                    else
                    {
                        //[2.10.1.0] MW0LGE changes so that CTUN on works for filter drag
                        int diff = HzToPixel((float)((VFOBFreq - CentreRX2Frequency) * 1e6), 2);
                        low_x = diff + HzToPixel(radio.GetDSPRX(1, 0).RXFilterLow, 2) - HzToPixel(0.0f, 2);
                        high_x = diff + HzToPixel(radio.GetDSPRX(1, 0).RXFilterHigh, 2) - HzToPixel(0.0f, 2);
                    }
                }
                else if (rx2_dsp_mode != DSPMode.DRM)
                {
                    //MW0LGE_21h changes so that CTUN on works for filter drag
                    int diff = HzToPixel((float)((VFOBFreq - CentreRX2Frequency) * 1e6), 2);
                    low_x = diff + HzToPixel(radio.GetDSPRX(1, 0).RXFilterLow, 2) - HzToPixel(0.0f, 2);
                    high_x = diff + HzToPixel(radio.GetDSPRX(1, 0).RXFilterHigh, 2) - HzToPixel(0.0f, 2);
                }
            }
            else
            {
                if (_mox)
                {
                    low_x = HzToPixel(radio.GetDSPTX(0).TXFilterLow);
                    high_x = HzToPixel(radio.GetDSPTX(0).TXFilterHigh);
                }
                else if (rx1_dsp_mode != DSPMode.DRM)
                {
                    //MW0LGE_21h changes so that CTUN on works for filter drag
                    int diff = HzToPixel((float)((VFOAFreq - CentreFrequency) * 1e6));
                    low_x = diff + HzToPixel(radio.GetDSPRX(0, 0).RXFilterLow) - HzToPixel(0.0f);
                    high_x = diff + HzToPixel(radio.GetDSPRX(0, 0).RXFilterHigh) - HzToPixel(0.0f);
                }

                if (chkEnableMultiRX.Checked && !_mox)
                {
                    if (!rx2_enabled)
                    {
                        vfoa_sub_x = HzToPixel((float)((VFOBFreq - VFOAFreq) * 1000000.0));
                        vfoa_sub_low_x = vfoa_sub_x + (HzToPixel((int)udFilterLow.Value) - HzToPixel(0.0f));
                        vfoa_sub_high_x = vfoa_sub_x + (HzToPixel((int)udFilterHigh.Value) - HzToPixel(0.0f));
                    }
                    else
                    {
                        vfoa_sub_x = HzToPixel((float)((VFOASubFreq - VFOAFreq) * 1000000.0));
                        vfoa_sub_low_x = vfoa_sub_x + (HzToPixel((int)udFilterLow.Value) - HzToPixel(0.0f));
                        vfoa_sub_high_x = vfoa_sub_x + (HzToPixel((int)udFilterHigh.Value) - HzToPixel(0.0f));
                    }
                }
            }
        }
        private void picDisplay_MouseLeave(object sender, System.EventArgs e)
        {
            if (!m_frmNotchPopup.Visible) SelectedNotch = null; // clear the selected notch (if there was one)
            m_bDraggingPanafallSplit = false;

            Display.HighlightNumberScaleRX1 = false;
            Display.HighlightNumberScaleRX2 = false;

            Display.HighlightedBandStackEntryIndex = -1; //MW0LGE_21h
            m_bBandStackOverlayClicked = false;

            Display.HightlightFilterEdgeRX1 = 0;
            Display.HightlightFilterEdgeRX2 = 0;

            infoBar.Left1(0, "");
            infoBar.Left2(0, "");
            infoBar.Left3(0, "");

            DisplayCursorX = -1;
            DisplayCursorY = -1;
            Cursor = Cursors.Default;
        }

        private void dragWholeFilter(MouseEventArgs e)
        {
            whole_filter_start_x = e.X;
            if (rx2_enabled && e.Y > picDisplay.Height / 2)
            {
                if (_mox && chkVFOBTX.Checked)
                {
                    tx_whole_filter_drag = true;
                    whole_filter_start_low = SetupForm.TXFilterLow;
                    whole_filter_start_high = SetupForm.TXFilterHigh;
                }
                else
                {
                    rx2_whole_filter_drag = true;
                    whole_filter_start_low = radio.GetDSPRX(1, 0).RXFilterLow;
                    whole_filter_start_high = radio.GetDSPRX(1, 0).RXFilterHigh;
                }
            }
            else
            {
                if (!_mox)
                {
                    rx1_whole_filter_drag = true;
                    whole_filter_start_low = radio.GetDSPRX(0, 0).RXFilterLow;
                    whole_filter_start_high = radio.GetDSPRX(0, 0).RXFilterHigh;
                }
                else
                {
                    tx_whole_filter_drag = true;
                    whole_filter_start_low = SetupForm.TXFilterLow;
                    whole_filter_start_high = SetupForm.TXFilterHigh;
                }
            }
        }
        private double adjustForSnapClickTuning(int rx, double freq)
        {
            DSPMode mode;
            if (rx == 1)
                mode = RX1DSPMode;
            else //rx == 2
                mode = RX2DSPMode;
            if (mode == DSPMode.FIRST || mode == DSPMode.LAST) return freq;

            if (snap_to_click_tuning &&
                (current_click_tune_mode != ClickTuneMode.Off || click_tune_drag) &&
                mode != DSPMode.CWL &&
                mode != DSPMode.CWU &&
                mode != DSPMode.DIGL &&
                mode != DSPMode.DIGU &&
                Audio.WavePlayback == false)
            {
                // round freq to the nearest tuning step
                long f = (long)(freq * 1000000.0);
                int mult = CurrentTuneStepHz;
                if (f % mult > mult / 2) f += (mult - f % mult);
                else f -= f % mult;
                freq = (double)f * 0.0000010;
            }

            return freq;
        }
        private SpotManager2.smSpot _highlightedSpot = null;

        private void picDisplay_MouseDown(object sender, MouseEventArgs e)
        {
            if (m_frmNotchPopup.Visible) return;
            if (_highlightedSpot != null)
            {
                if (e.Button == MouseButtons.Right)
                {
                    _highlightedSpot.BrowseQRZ();
                }
                else if (_highlightedSpot.Highlight[0])
                {

                    // rx1
                    if (_highlightedSpot.mode != DSPMode.FIRST && RX1DSPMode != _highlightedSpot.mode) RX1DSPMode = _highlightedSpot.mode;
                    if (VFOAFreq != _highlightedSpot.frequencyHZ * 1e-6) VFOAFreq = _highlightedSpot.frequencyHZ * 1e-6;

                    SpotClickedHandlers?.Invoke(_highlightedSpot.callsign, _highlightedSpot.frequencyHZ, 1, false);
                }
                else if (_highlightedSpot.Highlight[1] && rx2_enabled)
                {
                    // rx2
                    if (_highlightedSpot.mode != DSPMode.FIRST && RX2DSPMode != _highlightedSpot.mode) RX2DSPMode = _highlightedSpot.mode;
                    if (VFOBFreq != _highlightedSpot.frequencyHZ * 1e-6) VFOBFreq = _highlightedSpot.frequencyHZ * 1e-6;

                    SpotClickedHandlers?.Invoke(_highlightedSpot.callsign, _highlightedSpot.frequencyHZ, 2, false);
                }
                return;
            }

            Cursor next_cursor = _useOutlinedCrossCursor ? _cross_outlined : Cursors.Cross;

            switch (e.Button)
            {
                case MouseButtons.Left:

                    bool bOverRX1 = overRX(e.X, e.Y, 1, false);  //MW0LGE
                    bool bOverRX2 = overRX(e.X, e.Y, 2, false);

                    //NOTCH MW0LGE
                    if (SelectedNotch != null)
                    {
                        // this will be the notch we have mouse over                        

                        int nRX = 0;
                        if (bOverRX1 && (Display.CurrentDisplayMode == DisplayMode.PANADAPTER || Display.CurrentDisplayMode == DisplayMode.PANAFALL))
                        {
                            nRX = 1;
                        }
                        else if (bOverRX2 && (Display.CurrentDisplayModeBottom == DisplayMode.PANADAPTER || Display.CurrentDisplayModeBottom == DisplayMode.PANAFALL))
                        {
                            nRX = 2;
                        }
                        if (nRX != 0)
                        {
                            // the inital click point, delta is worked in mouse_move
                            drag_notch_start_point = new Point(e.X, e.Y);

                            double dMouseVFO = 0;
                            double dCentreFreq = 0;
                            double dCWoffset = 0;

                            if (nRX == 1)
                            {
                                dCentreFreq = CentreFrequency * 1e6;
                                dMouseVFO = dCentreFreq + PixelToHz(e.X, 1);
                                if (rx1_dsp_mode == DSPMode.CWL)
                                    dCWoffset = (double)cw_pitch;
                                else if (rx1_dsp_mode == DSPMode.CWU)
                                    dCWoffset = -(double)cw_pitch;
                            }
                            else
                            {
                                dCentreFreq = CentreRX2Frequency * 1e6;
                                dMouseVFO = dCentreFreq + PixelToHz(e.X, 2);
                                if (rx2_dsp_mode == DSPMode.CWL)
                                    dCWoffset = (double)cw_pitch;
                                else if (rx2_dsp_mode == DSPMode.CWU)
                                    dCWoffset = -(double)cw_pitch;
                            }
                            dMouseVFO += dCWoffset;

                            // upper and lower sides of the notch
                            double dL = SelectedNotch.FCenter - (SelectedNotch.FWidth / 2);
                            double dH = SelectedNotch.FCenter + (SelectedNotch.FWidth / 2);

                            // convert the upper and lower sides into pixels from left edge of picDispay
                            int nLpx = HzToPixel((float)(dL - dCentreFreq - dCWoffset), nRX);
                            int nHpx = HzToPixel((float)(dH - dCentreFreq - dCWoffset), nRX);

                            bool bNearEdge = false;

                            // default this based on which side of middle the mouse is
                            // so that we get inuative feeling when using shift modifier to resize
                            // ie we are not draggin an edge
                            m_BDragginNotchBWRightSide = (dMouseVFO >= SelectedNotch.FCenter);

                            if (nHpx - nLpx > 8)
                            {
                                // ok, the edges are far enough appart in pixels to actually check to see if we are over low or high side
                                if (Math.Abs(e.X - nLpx) < 4)
                                {
                                    m_BDragginNotchBWRightSide = false;
                                    bNearEdge = true;
                                }
                                else if (Math.Abs(e.X - nHpx) < 4)
                                {
                                    m_BDragginNotchBWRightSide = true;
                                    bNearEdge = true;
                                }
                            }

                            m_nNotchRX = nRX; // MW0LGE_21e

                            if (bNearEdge || Common.ShiftKeyDown) // can also hold shift drag to resize the notch
                            {
                                // near edge of notch, let us drag the width
                                drag_notch_start_data = SelectedNotch.FWidth;
                                m_bDraggingNotchBW = true;
                            }
                            else
                            {
                                // drag whole notch, as we are not near the edge
                                drag_notch_start_data = SelectedNotch.FCenter;
                                m_bDraggingNotch = true;
                            }
                            return;
                        }
                    }
                    //END NOTCH

                    //BandstackOverlay click MW0LGE_21h
                    //only do this if not doing something else
                    if (m_bShowBandStackOverlays && bOverRX1 && !(rx1_sub_drag || m_bDraggingNotch || m_bDraggingNotchBW || m_bDraggingPanafallSplit))
                    {
                        if (Display.BandStackOverlays != null && Display.BandStackOverlays.Length > 0)
                        {
                            bool panafall_check = Display.CurrentDisplayMode == DisplayMode.PANAFALL && ((!rx2_enabled && e.Y < Display.PanafallSplitBarPos) || (rx2_enabled && e.Y < picDisplay.Height / 4)); //[2.10.3.6]MW0LGE fixes issue where you could try to qsy click on the waterfall
                            if (bOverRX1 && (Display.CurrentDisplayMode == DisplayMode.PANADAPTER || panafall_check))                                                                                          //under a band stack entry that was shown on the panadaptor area in a panafall display
                            {                                                                                                                                                                                  //and it would not qsy             
                                // convert mouse pos into HZ
                                double nMousePosHZ = (CentreFrequency * 1e6) + PixelToHz(e.X, 1); // only rx1

                                m_bBandStackOverlayClicked = false;

                                for (int n = 0; n < Display.BandStackOverlays.Length; n++)
                                {
                                    BandStackEntry bse = Display.BandStackOverlays[n];

                                    double dL = (bse.Frequency * 1e6) + bse.LowFilter;
                                    double dH = (bse.Frequency * 1e6) + bse.HighFilter;

                                    if (dL <= nMousePosHZ && dH >= nMousePosHZ)
                                    {
                                        m_bBandStackOverlayClicked = true;
                                        return;
                                    }
                                }
                            }
                        }
                    }
                    //

                    //MIDDLE OF PANAFALL MOVEUPDOWN MW0LGE
                    if (!rx2_enabled && Display.CurrentDisplayMode == DisplayMode.PANAFALL)
                    {
                        m_bDraggingPanafallSplit = (e.Y >= Display.PanafallSplitBarPos && e.Y < Display.PanafallSplitBarPos + 20);
                        if (m_bDraggingPanafallSplit) return;
                    }
                    //END SPLITTER DRAG

                    // if (!mox)
                    // {
                    switch (Display.CurrentDisplayMode)
                    {
                        case DisplayMode.PANADAPTER:
                        case DisplayMode.PANAFALL:
                        case DisplayMode.HISTOGRAM:
                        case DisplayMode.SPECTRUM:
                        case DisplayMode.PANASCOPE:
                        case DisplayMode.SPECTRASCOPE:
                            if (!_mox)
                            {
                                if (rx1_grid_adjust)
                                {
                                    grid_minmax_drag_start_point = new Point(e.X, e.Y);
                                    gridminmaxadjust = true;
                                    tx1_grid_adjust = false;
                                    grid_minmax_max_y = Display.SpectrumGridMax;
                                    grid_minmax_min_y = Display.SpectrumGridMin;
                                    next_cursor = grabbing;
                                }

                                if (rx2_grid_adjust)
                                {
                                    grid_minmax_drag_start_point = new Point(e.X, e.Y);
                                    gridminmaxadjust = true;
                                    tx1_grid_adjust = false;
                                    grid_minmax_max_y = Display.RX2SpectrumGridMax;
                                    grid_minmax_min_y = Display.RX2SpectrumGridMin;
                                    next_cursor = grabbing;
                                }
                            }
                            else
                            {
                                if ((rx1_grid_adjust && !Display.TXOnVFOB) ||
                                    (rx1_grid_adjust && Display.TXOnVFOB && !RX2Enabled))
                                {
                                    grid_minmax_drag_start_point = new Point(e.X, e.Y);
                                    gridminmaxadjust = true;
                                    tx1_grid_adjust = true;
                                    grid_minmax_max_y = Display.TXSpectrumGridMax;
                                    grid_minmax_min_y = Display.TXSpectrumGridMin;
                                    next_cursor = grabbing;
                                }
                                else if (rx1_grid_adjust && Display.TXOnVFOB)
                                {
                                    grid_minmax_drag_start_point = new Point(e.X, e.Y);
                                    gridminmaxadjust = true;
                                    tx1_grid_adjust = false;
                                    grid_minmax_max_y = Display.SpectrumGridMax;
                                    grid_minmax_min_y = Display.SpectrumGridMin;
                                    next_cursor = grabbing;
                                }

                                if (rx2_grid_adjust && Display.TXOnVFOB)
                                {
                                    grid_minmax_drag_start_point = new Point(e.X, e.Y);
                                    gridminmaxadjust = true;
                                    tx2_grid_adjust = true;
                                    grid_minmax_max_y = Display.TXSpectrumGridMax;
                                    grid_minmax_min_y = Display.TXSpectrumGridMin;
                                    next_cursor = grabbing;
                                }
                                else if (rx2_grid_adjust && !Display.TXOnVFOB)
                                {
                                    grid_minmax_drag_start_point = new Point(e.X, e.Y);
                                    gridminmaxadjust = true;
                                    tx2_grid_adjust = false;
                                    grid_minmax_max_y = Display.RX2SpectrumGridMax;
                                    grid_minmax_min_y = Display.RX2SpectrumGridMin;
                                    next_cursor = grabbing;
                                }
                            }
                            break;
                        case DisplayMode.WATERFALL:
                            break;
                    }
                    // }

                    if (!_mox)
                    {
                        switch (Display.CurrentDisplayMode)
                        {
                            case DisplayMode.PANAFALL:
                            case DisplayMode.PANASCOPE:
                            case DisplayMode.PANADAPTER:
                                if (rx2_enabled && e.Y > picDisplay.Height / 2)
                                {
                                    if (Display.AGCRX2Knee.Contains(e.X, e.Y) && show_agc)
                                    {
                                        agc_knee_drag = true;
                                        next_cursor = grabbing;
                                    }
                                    else
                                        if (Display.AGCRX2Hang.Contains(e.X, e.Y) && show_agc)
                                    {
                                        agc_hang_drag = true;
                                        next_cursor = grabbing;
                                    }
                                    else
                                    {
                                        agc_knee_drag = false;
                                        agc_hang_drag = false;
                                    }
                                }
                                else
                                {
                                    if (Display.AGCKnee.Contains(e.X, e.Y) && show_agc)
                                    {
                                        agc_knee_drag = true;
                                        next_cursor = grabbing;
                                    }
                                    else
                                        if (Display.AGCHang.Contains(e.X, e.Y) && show_agc)
                                    {
                                        agc_hang_drag = true;
                                        next_cursor = grabbing;
                                    }
                                    else
                                    {
                                        agc_knee_drag = false;
                                        agc_hang_drag = false;
                                    }
                                }
                                break;
                        }

                        if (bOverRX1 && agc_knee_drag) AutoAGCRX1 = false; // MW0LGE_21k8 turn of auto agc if we click knee
                        else if (bOverRX2 && agc_knee_drag) AutoAGCRX2 = false;
                    }

                    if (Display.HightlightFilterEdgeRX1 == 0 && Display.HightlightFilterEdgeRX2 == 0 &&
                        !agc_knee_drag &&
                        !agc_hang_drag &&
                        !gridminmaxadjust &&
                        !gridmaxadjust &&
                        (current_click_tune_mode != ClickTuneMode.Off || (click_tune_display && bOverRX1) || (click_tune_rx2_display && bOverRX2)))
                    {
                        switch (Display.CurrentDisplayMode)
                        {
                            case DisplayMode.SPECTRUM:
                            case DisplayMode.WATERFALL:
                            case DisplayMode.HISTOGRAM:
                            case DisplayMode.PANADAPTER:
                            case DisplayMode.PANAFALL:
                            case DisplayMode.PANASCOPE:
                                float x = PixelToHz(e.X);
                                double freq;
                                if (rx2_enabled && e.Y > picDisplay.Height / 2) //RX2
                                {
                                    x = PixelToHz(e.X, 2);

                                    bool bShift = true;
                                    if (click_tune_rx2_display && current_click_tune_mode != ClickTuneMode.Off)
                                        freq = CentreRX2Frequency + (double)x * 0.0000010;
                                    else if (current_click_tune_mode != ClickTuneMode.Off)
                                        freq = /*double.Parse(txtVFOBFreq.Text)*/ VFOBFreq + (double)x * 0.0000010; // click tune w/x-hairs //[2.10.3.6]freq changes.
                                    else if (click_tune_drag)
                                        freq = CentreRX2Frequency + (double)x * 0.0000010; // click tune & drag vfo
                                    else
                                    {
                                        bShift = false; // the shift is already applied to the vfo, we dont want to do it again ! MW0LGE_21k9rc6
                                        freq = /*double.Parse(txtVFOBFreq.Text);*/ VFOBFreq; // click & drag vfo //[2.10.3.6]freq changes.
                                    }

                                    if (bShift)
                                    {
                                        switch (rx2_dsp_mode)
                                        {
                                            case DSPMode.CWL:
                                                freq += (float)cw_pitch * 0.0000010;
                                                break;
                                            case DSPMode.CWU:
                                                freq -= (float)cw_pitch * 0.0000010;
                                                break;
                                            case DSPMode.DIGL:
                                                freq += (float)digl_click_tune_offset * 0.0000010;
                                                break;
                                            case DSPMode.DIGU:
                                                freq -= (float)digu_click_tune_offset * 0.0000010;
                                                break;
                                        }
                                    }

                                    freq = adjustForSnapClickTuning(2, freq);
                                }
                                else
                                {
                                    bool bShift = true;
                                    if (click_tune_display && current_click_tune_mode != ClickTuneMode.Off)
                                        freq = CentreFrequency + (double)x * 0.0000010;
                                    else if (current_click_tune_mode != ClickTuneMode.Off)
                                        freq = /*double.Parse(txtVFOAFreq.Text)*/ VFOAFreq + (double)x * 0.0000010; // click tune w/x-hairs //[2.10.3.6]freq changes.
                                    else if (click_tune_drag)
                                        freq = CentreFrequency + (double)x * 0.0000010; // click tune & drag vfo
                                    else
                                    {
                                        bShift = false; // the shift is already applied to the vfo, we dont want to do it again ! MW0LGE_21k9rc6
                                        freq = /*double.Parse(txtVFOAFreq.Text);*/ VFOAFreq; // click & drag vfo //[2.10.3.6]freq changes.
                                    }

                                    if (bShift)
                                    {
                                        switch (rx1_dsp_mode)
                                        {
                                            case DSPMode.CWL:
                                                freq += (float)cw_pitch * 0.0000010;
                                                break;
                                            case DSPMode.CWU:
                                                freq -= (float)cw_pitch * 0.0000010;
                                                break;
                                            case DSPMode.DIGL:
                                                if (!ClickTuneFilter) freq += (float)digl_click_tune_offset * 0.0000010;
                                                break;
                                            case DSPMode.DIGU:
                                                if (!ClickTuneFilter) freq -= (float)digu_click_tune_offset * 0.0000010;
                                                break;
                                        }
                                    }

                                    freq = adjustForSnapClickTuning(1, freq);
                                }

                                // MW0LGE block below handles dragging top frequency bars

                                int low_x = 0, high_x = 0;
                                int vfoa_sub_x = 0;
                                int vfoa_sub_low_x = 0;
                                int vfoa_sub_high_x = 0;
                                getFilterEdgesInPixels(e, ref low_x, ref high_x, ref vfoa_sub_x, ref vfoa_sub_low_x, ref vfoa_sub_high_x);

                                bool bOverTopOfDragSpectrum = false;
                                if (bOverRX2 && e.Y < ((picDisplay.Height / 2) + 15))
                                    bOverTopOfDragSpectrum = true;
                                else if (bOverRX1 && e.Y < 15)
                                    bOverTopOfDragSpectrum = true;

                                if (current_click_tune_mode == ClickTuneMode.Off || bOverTopOfDragSpectrum)
                                {
                                    if (rx2_enabled && e.Y > picDisplay.Height / 2)
                                    {
                                        spectrum_drag_last_x = e.X;
                                        if (click_tune_rx2_display)
                                        {
                                            if (e.Y < ((picDisplay.Height / 2) + 15))
                                            {
                                                rx2_spectrum_tune_drag = true;
                                                next_cursor = Cursors.SizeWE;
                                            }
                                            else
                                            {
                                                if (!(Common.ShiftKeyDown && (e.X > low_x && e.X < high_x))) // ignore if shift down, so that we move the filter, and not the frequency MW0LGE_21k9d
                                                {
                                                    rx2_click_tune_drag = true;
                                                    next_cursor = grabbing;
                                                }
                                                else
                                                {
                                                    next_cursor = Cursors.SizeWE;
                                                }
                                            }
                                        }
                                        else rx2_spectrum_drag = true;
                                    }
                                    else
                                    {
                                        spectrum_drag_last_x = e.X;
                                        if (click_tune_display)
                                        {
                                            if (e.Y < 15)
                                            {
                                                rx1_spectrum_tune_drag = true;
                                                next_cursor = Cursors.SizeWE;
                                            }
                                            else
                                            {
                                                if (!(Common.ShiftKeyDown && (e.X > low_x && e.X < high_x))) // ignore if shift down, so that we move the filter, and not the frequency MW0LGE_21k9d
                                                {
                                                    rx1_click_tune_drag = true;
                                                    next_cursor = grabbing;
                                                }
                                                else
                                                {
                                                    next_cursor = Cursors.SizeWE;
                                                }
                                            }
                                        }
                                        else rx1_spectrum_drag = true;
                                    }
                                }
                                // }

                                //set freq to where you click as part of the ctun off dragging
                                if (!rx1_spectrum_drag && !rx2_spectrum_drag)
                                {
                                    if (!rx2_enabled)
                                    {
                                        if (!rx1_spectrum_tune_drag)
                                        {
                                            if (!(Common.ShiftKeyDown && (e.X > low_x && e.X < high_x))) //MW0LGE_21k9d do not set freq, so we can shift the filter instead
                                            {
                                                if (!(!m_bCTUNputsZeroOnMouse && (e.X > low_x && e.X < high_x)) || current_click_tune_mode != ClickTuneMode.Off)
                                                {
                                                    if (current_click_tune_mode == ClickTuneMode.VFOA ||
                                                        (click_tune_display && current_click_tune_mode != ClickTuneMode.VFOB))
                                                    {
                                                        VFOAFreq = Math.Round(freq, 6);
                                                    }
                                                    else
                                                        VFOBFreq = Math.Round(freq, 6);
                                                }
                                            }
                                            else
                                            {
                                                // shift filter MW0LGE_21k9d
                                                dragWholeFilter(e);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        if (current_click_tune_mode == ClickTuneMode.VFOB && // red cross hairs
                                            (chkVFOSplit.Checked || chkEnableMultiRX.Checked))
                                        {
                                            VFOASubFreq = Math.Round(freq, 6);
                                        }
                                        else
                                        {
                                            if (!(Common.ShiftKeyDown && (e.X > low_x && e.X < high_x))) //MW0LGE_21k9d do not set freq, so we can shift the filter instead
                                            {
                                                if (!(!m_bCTUNputsZeroOnMouse && (e.X > low_x && e.X < high_x)) || current_click_tune_mode != ClickTuneMode.Off)
                                                {
                                                    if (e.Y <= picDisplay.Height / 2)
                                                    {
                                                        if (!rx1_spectrum_tune_drag)
                                                            VFOAFreq = Math.Round(freq, 6);
                                                    }

                                                    else
                                                    {
                                                        if (!rx2_spectrum_tune_drag)
                                                            VFOBFreq = Math.Round(freq, 6);
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                // shift filter MW0LGE_21k9d
                                                dragWholeFilter(e);
                                            }
                                        }
                                    }
                                }

                                if (chkMOX.Checked && chkXIT.Checked && current_click_tune_mode == ClickTuneMode.VFOB)
                                    udXIT.Value = 0;
                                break;
                            default:
                                break;
                        }
                    }
                    // resize filter code
                    else if ( !agc_knee_drag &&
                              !agc_hang_drag &&
                              !gridminmaxadjust &&
                              !gridmaxadjust)
                    {
                        switch (Display.CurrentDisplayMode)
                        {
                            case DisplayMode.PANADAPTER:
                            case DisplayMode.WATERFALL:
                            case DisplayMode.PANAFALL:
                            case DisplayMode.PANASCOPE:
                                int low_x = 0, high_x = 0;
                                int vfoa_sub_x = 0;
                                int vfoa_sub_low_x = 0;
                                int vfoa_sub_high_x = 0;
                                getFilterEdgesInPixels(e, ref low_x, ref high_x, ref vfoa_sub_x, ref vfoa_sub_low_x, ref vfoa_sub_high_x);

                                if (Math.Abs(e.X - low_x) < 3 && e.X < high_x)
                                {
                                    if (rx2_enabled && e.Y > picDisplay.Height / 2)
                                    {
                                        if (_mox && chkVFOBTX.Checked)
                                        {
                                            if (!click_tune_rx2_display) //[2.10.1.0] not when in ctun
                                            {
                                                switch (radio.GetDSPTX(0).CurrentDSPMode)
                                                {
                                                    case DSPMode.LSB:
                                                    case DSPMode.CWL:
                                                    case DSPMode.DIGL:
                                                    case DSPMode.AM:
                                                    case DSPMode.SAM:
                                                    case DSPMode.FM:
                                                    case DSPMode.DSB:
                                                        tx_high_filter_drag = true;
                                                        break;
                                                    default:
                                                        tx_low_filter_drag = true;
                                                        break;
                                                }
                                            }
                                        }
                                        else rx2_low_filter_drag = true;
                                    }
                                    else
                                    {
                                        if (_mox && (!chkSplitDisplay.Checked || chkVFOATX.Checked))
                                        {
                                            if (!click_tune_display) //[2.10.1.0] not when in ctun
                                            {
                                                switch (radio.GetDSPTX(0).CurrentDSPMode)
                                                {
                                                    case DSPMode.LSB:
                                                    case DSPMode.CWL:
                                                    case DSPMode.DIGL:
                                                    case DSPMode.AM:
                                                    case DSPMode.SAM:
                                                    case DSPMode.FM:
                                                    case DSPMode.DSB:
                                                        tx_high_filter_drag = true;
                                                        break;
                                                    default:
                                                        tx_low_filter_drag = true;
                                                        break;
                                                }
                                            }
                                        }
                                        else rx1_low_filter_drag = true;
                                    }
                                }
                                else if (Math.Abs(e.X - high_x) < 3)
                                {
                                    if (rx2_enabled && e.Y > picDisplay.Height / 2)
                                    {
                                        if (_mox && chkVFOBTX.Checked)
                                        {
                                            if (!click_tune_rx2_display) //[2.10.1.0] not when in ctun
                                            {
                                                switch (radio.GetDSPTX(0).CurrentDSPMode)
                                                {
                                                    case DSPMode.LSB:
                                                    case DSPMode.CWL:
                                                    case DSPMode.DIGL:
                                                        tx_low_filter_drag = true;
                                                        break;
                                                    default:
                                                        tx_high_filter_drag = true;
                                                        break;
                                                }
                                            }
                                        }
                                        else rx2_high_filter_drag = true;
                                    }
                                    else if (_mox && (!chkSplitDisplay.Checked || (chkSplitDisplay.Checked && chkVFOATX.Checked)))
                                    {
                                        if (!click_tune_display) //[2.10.1.0] not when in ctun
                                        {
                                            switch (radio.GetDSPTX(0).CurrentDSPMode)
                                            {
                                                case DSPMode.LSB:
                                                case DSPMode.CWL:
                                                case DSPMode.DIGL:
                                                    tx_low_filter_drag = true;
                                                    break;
                                                default:
                                                    tx_high_filter_drag = true;
                                                    break;
                                            }
                                        }
                                    }
                                    else rx1_high_filter_drag = true;
                                }
                                else if (e.X > low_x && e.X < high_x && Common.ShiftKeyDown) // need shift held to drag the filter in ctun off mode MW0LGE_21k9d
                                {
                                    dragWholeFilter(e);
                                }
                                else if (chkEnableMultiRX.Checked && !_mox &&
                                    (e.X > vfoa_sub_low_x - 3 && e.X < vfoa_sub_high_x + 3))
                                {
                                    sub_drag_last_x = e.X;
                                    if (rx2_enabled) sub_drag_start_freq = VFOASubFreq;
                                    else sub_drag_start_freq = VFOBFreq;
                                    rx1_sub_drag = true;
                                }
                                else
                                {
                                    spectrum_drag_last_x = e.X;
                                    if (rx2_enabled && e.Y > picDisplay.Height / 2) rx2_spectrum_drag = true;
                                    else rx1_spectrum_drag = true;
                                    next_cursor = Cursors.SizeWE;
                                }

                                break;
                        }
                    }
                    break;
                case MouseButtons.Right:
                    // if we have a notch highlighted, then all other right click is ignored
                    if (SelectedNotch != null) return;

                    // right click in the middle splitter bar will recentre it
                    if (!rx2_enabled && Display.CurrentDisplayMode == DisplayMode.PANAFALL)
                    {
                        if (e.Y >= Display.PanafallSplitBarPos && e.Y < Display.PanafallSplitBarPos + 20)
                        {
                            Display.PanafallSplitBarPerc = 0.5f;
                            return;
                        }
                    }

                    //
                    if (Common.CtrlKeyDown)
                    {
                        int rx;
                        double dFreq;
                        // add notch from cross hair mode with middle mouse
                        if (rx2_enabled && e.Y > picDisplay.Height / 2)
                        {
                            dFreq = getFrequencyAtPixel(e.X, 2);
                            rx = 2;
                        }
                        else
                        {
                            dFreq = getFrequencyAtPixel(e.X, 1);
                            rx = 1;
                        }
                        addNotch(dFreq, rx);
                        return;
                    }
                    //

                    if (!_mox && (rx1_grid_adjust || rx2_grid_adjust))
                    {
                        if (rx1_grid_adjust)
                        {
                            grid_minmax_drag_start_point = new Point(e.X, e.Y);
                            gridmaxadjust = true;
                            tx1_grid_adjust = false;
                            grid_minmax_max_y = Display.SpectrumGridMax;
                            next_cursor = grabbing;
                        }

                        if (rx2_grid_adjust)
                        {
                            grid_minmax_drag_start_point = new Point(e.X, e.Y);
                            gridmaxadjust = true;
                            tx1_grid_adjust = false;
                            grid_minmax_max_y = Display.RX2SpectrumGridMax;
                            next_cursor = grabbing;
                        }
                    }
                    else if (_mox && (rx1_grid_adjust || rx2_grid_adjust))
                    {
                        if ((rx1_grid_adjust && !Display.TXOnVFOB) ||
                            (rx1_grid_adjust && Display.TXOnVFOB && !RX2Enabled))
                        {
                            grid_minmax_drag_start_point = new Point(e.X, e.Y);
                            gridmaxadjust = true;
                            tx1_grid_adjust = true;
                            grid_minmax_max_y = Display.TXSpectrumGridMax;
                            next_cursor = grabbing;
                        }
                        else if (rx1_grid_adjust && Display.TXOnVFOB)
                        {
                            grid_minmax_drag_start_point = new Point(e.X, e.Y);
                            gridmaxadjust = true;
                            tx1_grid_adjust = false;
                            grid_minmax_max_y = Display.SpectrumGridMax;
                            next_cursor = grabbing;
                        }

                        if (rx2_grid_adjust && Display.TXOnVFOB)
                        {
                            grid_minmax_drag_start_point = new Point(e.X, e.Y);
                            gridmaxadjust = true;
                            tx2_grid_adjust = true;
                            grid_minmax_max_y = Display.TXSpectrumGridMax;
                            next_cursor = grabbing;
                        }
                        else if (rx2_grid_adjust && !Display.TXOnVFOB)
                        {
                            grid_minmax_drag_start_point = new Point(e.X, e.Y);
                            gridmaxadjust = true;
                            tx2_grid_adjust = false;
                            grid_minmax_max_y = Display.RX2SpectrumGridMax;
                            next_cursor = grabbing;
                        }
                    }
                    else
                    {
                        switch (current_click_tune_mode)
                        {
                            case ClickTuneMode.Off:
                                CurrentClickTuneMode = ClickTuneMode.VFOA;
                                break;
                            case ClickTuneMode.VFOA:
                                if (chkVFOSplit.Checked || chkEnableMultiRX.Checked)
                                    CurrentClickTuneMode = ClickTuneMode.VFOB;
                                else
                                    CurrentClickTuneMode = ClickTuneMode.Off;
                                break;
                            case ClickTuneMode.VFOB:
                                CurrentClickTuneMode = ClickTuneMode.Off;
                                break;
                        }
                    }
                    break;
                case MouseButtons.Middle:
                    if (SelectedNotch != null)
                    {
                        // move or toggle notch
                        if (Common.ShiftKeyDown)
                        {
                            if (removeNotch(SelectedNotch)) SelectedNotch = null; // remove the notch, and if ok clear selected MW0LGE
                        }
                        else
                        {
                            toggleNotchActive(SelectedNotch);
                        }
                    }
                    
                    // carry onto the tune step, but give notch priority
                    else if (mouse_tune_step)
                    {
                        if (Common.ShiftKeyDown) ChangeTuneStepDown(); //MW0LGE
                        else ChangeTuneStepUp();
                    }
                    break;
            }

            if (next_cursor == Cursors.Cross || next_cursor == _cross_outlined)
            {
                // nothing happened
            }

            picDisplay.Cursor = next_cursor;
        }

        private double getFrequencyAtPixel(int x, int nRX)
        {
            //MW0LGE returns the frequecny (Hz) at a given pixel
            double dFreq = 0;

            if (nRX == 2)
            {
                if (click_tune_rx2_display)// && current_click_tune_mode != ClickTuneMode.Off)
                {
                    dFreq = (double)PixelToHz(x, 2) + (CentreRX2Frequency * 1e6);
                }
                else
                {
                    dFreq = (double)PixelToHz(x, 2) + (VFOBFreq * 1e6);
                }

                switch (rx2_dsp_mode)
                {
                    case DSPMode.CWU: dFreq -= cw_pitch; break;
                    case DSPMode.CWL: dFreq += cw_pitch; break;
                }
            }
            else
            {
                if (click_tune_display)// && current_click_tune_mode != ClickTuneMode.Off)
                {
                    dFreq = (double)PixelToHz(x, 1) + (CentreFrequency * 1e6);
                }
                else
                {
                    dFreq = (double)PixelToHz(x, 1) + (VFOAFreq * 1e6);
                }
                switch (rx1_dsp_mode)
                {
                    case DSPMode.CWU: dFreq -= cw_pitch; break;
                    case DSPMode.CWL: dFreq += cw_pitch; break;
                }
            }

            return dFreq;
        }

        //=================================================================================================
        // ke9ns mod 

        public static int[] SXX = new int[200]; // ke9ns add used for qrz hyperlinking(these are the callsign locations on the screen)
        public static int[] SXY = new int[200]; // 
        public static int[] SXW = new int[200]; //
        public static int[] SXH = new int[200]; //  
        public static string[] SXS = new string[200]; // ties it back to the real DX_Index
        public static int SXK = 0;               // number of spots on picdisplay

        public static int[] DXX = new int[200]; // ke9ns add used for qrz hyperlinking(these are the callsign locations on the screen)
        public static int[] DXY = new int[200]; // 
        public static int[] DXW = new int[200]; //
        public static int[] DXH = new int[200]; //  
        public static string[] DXS = new string[200]; // ties it back to the real DX_Index
        public static int DXK = 0;               // number of spots on picdisplay
        public static int DXK2 = 0;               // number of spots on picdisplay



        public static int[] MMX = new int[200]; // ke9ns add X used for MEMORY hyperlinking(these are the callsign locations on the screen)
        public static int[] MMY = new int[200]; //           Y
        public static int[] MMW = new int[200]; //           W
        public static int[] MMH = new int[200]; //           H
        public static int[] MMM = new int[200]; //           Index postion in Memory.xml file

        public static int MMK3 = 0;               // number of MEMORY spots on picdisplay
        public static int MMK4 = 0;               // number of spots on picdisplay

        public static bool DisplaySpot = true;               // true displays spot, false displays spotter

        public static int DX_X = 0;               //x cursor pos inside picdisplay 
        public static int DX_Y = 0;               //y  cursor pos inside picdisplay

        private bool m_bDraggingPanafallSplit = false;

        private void picDisplay_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                switch (Display.CurrentDisplayMode)
                {
                    case DisplayMode.SPECTRUM:
                    case DisplayMode.PANADAPTER:
                    case DisplayMode.WATERFALL:
                    case DisplayMode.PANAFALL:
                    case DisplayMode.PANASCOPE:
                    case DisplayMode.HISTOGRAM:
                    case DisplayMode.SPECTRASCOPE:
                        rx1_low_filter_drag = false;
                        rx1_high_filter_drag = false;
                        rx1_whole_filter_drag = false;
                        rx2_low_filter_drag = false;
                        rx2_high_filter_drag = false;
                        rx2_whole_filter_drag = false;
                        tx_low_filter_drag = false;
                        tx_high_filter_drag = false;
                        tx_whole_filter_drag = false;
                        rx1_click_tune_drag = false;
                        rx2_click_tune_drag = false;
                        rx1_spectrum_tune_drag = false;
                        rx2_spectrum_tune_drag = false;

                        agc_knee_drag = false;
                        agc_hang_drag = false;

                        gridminmaxadjust = false;
                        rx1_grid_adjust = false;
                        rx2_grid_adjust = false;
                        tx1_grid_adjust = false;
                        tx2_grid_adjust = false;

                        //MW0LGE_21i
                        Display.HightlightFilterEdgeRX1 = 0;
                        Display.HightlightFilterEdgeRX2 = 0;

                        break;
                }

                if (rx1_sub_drag)
                {
                    rx1_sub_drag = false;
                    if (rx2_enabled) txtVFOABand_LostFocus(this, EventArgs.Empty);
                    else txtVFOBFreq_LostFocus(this, EventArgs.Empty);
                }

                if (rx1_spectrum_drag)
                {
                    rx1_spectrum_drag = false;
                    txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                }
                rx2_spectrum_drag = false;

                //BandStack overlay MW0LGE_21h
                if (m_bBandStackOverlayClicked)
                {
                    if ((Display.HighlightedBandStackEntryIndex != -1) && (Display.BandStackOverlays != null))
                    {
                        if (Display.CurrentDisplayMode == DisplayMode.PANADAPTER || Display.CurrentDisplayMode == DisplayMode.PANAFALL)
                        {
                            if (Display.HighlightedBandStackEntryIndex < Display.BandStackOverlays.Length) // belts/braces
                            {
                                BandStackEntry bse = Display.BandStackOverlays[Display.HighlightedBandStackEntryIndex];
                                if (bse != null)
                                {
                                    BandStackFilter bsf = BandStackManager.GetFilter(RX1Band, false);
                                    if (bsf != null) OnEntryClicked(bsf, bse, false);
                                }
                            }
                        }
                    }
                    m_bBandStackOverlayClicked = false;
                }
                //

                if (m_bDraggingNotch)
                {
                    // finished dragging a notch, let use change its frequency MW0LGE
                    m_bDraggingNotch = false;
                    double tmp = SelectedNotch.FCenter;
                    changeNotchCentreFrequency(SelectedNotch, tmp, m_nNotchRX);
                }
                else if (m_bDraggingNotchBW) // can only do one or the other
                {
                    // finished dragging notch BW, lets us change it
                    m_bDraggingNotchBW = false;
                    double tmp = SelectedNotch.FWidth;
                    changeNotchBW(SelectedNotch, tmp);
                }

                if (m_bDraggingPanafallSplit)
                {
                    m_bDraggingPanafallSplit = false;
                }
            }

            if (e.Button == MouseButtons.Right)
            {
                switch (Display.CurrentDisplayMode)
                {
                    case DisplayMode.PANADAPTER:
                    case DisplayMode.PANAFALL:
                    case DisplayMode.HISTOGRAM:
                    case DisplayMode.SPECTRUM:
                    case DisplayMode.PANASCOPE:
                    case DisplayMode.SPECTRASCOPE:
                        gridminmaxadjust = false;
                        gridmaxadjust = false;
                        rx1_grid_adjust = false;
                        rx2_grid_adjust = false;
                        tx1_grid_adjust = false;
                        tx2_grid_adjust = false;
                        break;
                }

                if (SelectedNotch != null && !Common.CtrlKeyDown) //MW0LGE_21f only if ctrl not down, as was randomly showing when adding a new one
                {
                    Point p = new Point(e.X, e.Y);
                    m_frmNotchPopup.Left = picDisplay.PointToScreen(p).X - 16;
                    m_frmNotchPopup.Top = picDisplay.PointToScreen(p).Y - 16;
                    if (!m_frmNotchPopup.Visible) m_frmNotchPopup.Show(SelectedNotch, 0, 1000, AlwaysOnTop);
                }
            }
        }

        private void picDisplay_DoubleClick(object sender, EventArgs e)
        {
            int new_val = (int)PixelToDb(display_cursor_y);
            if (!(rx1_grid_adjust || gridmaxadjust))
            {
                if (!_mox) //RX1
                {
                    if (rx1_dsp_mode == DSPMode.FM)
                        return;

                    if (new_val > ptbSquelch.Maximum) new_val = ptbSquelch.Maximum;
                    if (new_val < ptbSquelch.Minimum) new_val = ptbSquelch.Minimum;
                    ptbSquelch.Value = new_val;
                    ptbSquelch_Scroll(this, EventArgs.Empty);
                }
                else // TX
                {
                    new_val += 24;
                    if (new_val > ptbNoiseGate.Maximum) new_val = ptbNoiseGate.Maximum;
                    if (new_val < ptbNoiseGate.Minimum) new_val = ptbNoiseGate.Minimum;
                    ptbNoiseGate.Value = new_val;
                    ptbNoiseGate_Scroll(this, EventArgs.Empty);
                }
            }

        }
        //
        private bool m_bResizeDX2Display = false;
        private async void picDisplay_Resize(object sender, System.EventArgs e)
        {
            _pause_DisplayThread = true;

            // tell display thread to resize DX2
            m_bResizeDX2Display = true;

            // wait for the resize to happen in the display thread
            while (m_bResizeDX2Display && m_bDisplayLoopRunning)
            {
                await Task.Delay(1);
            }

            if (!initializing)
            {
                //MW0LGE_21d N1MM
                N1MM.Resize(1);
                if (RX2Enabled) N1MM.Resize(2);

                //MW0LGE_21h
                updateBandstackOverlay(1);

                UpdateRXSpectrumDisplayVars();
                UpdateTXSpectrumDisplayVars();
            }

            _pause_DisplayThread = false;
        }

        private void ptbDisplayPan_Scroll(object sender, System.EventArgs e)
        {
            specRX.GetSpecRX(0).PanSlider = (double)ptbDisplayPan.Value / 1000.0;
            specRX.GetSpecRX(1).PanSlider = (double)ptbDisplayPan.Value / 1000.0;
            specRX.GetSpecRX(cmaster.inid(1, 0)).PanSlider = (double)ptbDisplayPan.Value / 1000.0;
            CalcDisplayFreq();
            CalcRX2DisplayFreq();
            CalcTXDisplayFreq();
            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbDisplayPan.Focus();
            }
        }

        private void btnDisplayPanCenter_Click(object sender, System.EventArgs e)
        {
            double spur_tune_width = 200e6 / Math.Pow(2, 16);

            int width = Display.RXDisplayHigh - Display.RXDisplayLow;

            int max_pan_width = (int)(sample_rate_rx1 - 2 * spur_tune_width - width);
            if (max_pan_width == 0)
            {
                ptbDisplayPan.Value = (ptbDisplayPan.Maximum - ptbDisplayPan.Minimum) / 2;
                ptbDisplayPan_Scroll(btnDisplayPanCenter, EventArgs.Empty);
                return;
            }

            int low = -width / 2; // target -- if width is centered at 0, low will be half the width below 0

            int abs_low = (int)(-(double)sample_rate_rx1 * 0.5 + spur_tune_width);

            int offset = low - abs_low;

            int new_val = (int)((double)offset * (double)ptbDisplayPan.Maximum / (double)max_pan_width);
            ptbDisplayPan.Value = Math.Min(Math.Max(ptbDisplayPan.Minimum, new_val), ptbDisplayPan.Maximum);
            ptbDisplayPan_Scroll(btnDisplayPanCenter, EventArgs.Empty);
        }
        private bool m_bIgnoreZoomCentre = false;
        private bool m_bIgnoreLimitsForZTB = false;
        private bool zoomToBandBandwidth(Band b, int rx)
        {
            //// only if CTUN is enabled and band is current band
            if (rx == 1 && (!ClickTuneDisplay || b != RX1Band)) return false;
            if (rx == 2 && (!ClickTuneRX2Display || b != RX2Band)) return false;

            // get band info
            List<BandFrequencyData> bfds = BandStackManager.GetFrequencyRangesForBand(b, Extended, CurrentRegion);
            if (bfds.Count != 1) return false; // ignore if multiple frequency ranges

            BandFrequencyData bfd = bfds.First<BandFrequencyData>();
            if (bfd.lowOnly) return false; // ignore if only a spot frequency like WWV etc

            double lowMHz = bfd.low;
            double highMHz = bfd.high;
            double spanMHz = highMHz - lowMHz;
            double centre = lowMHz + (spanMHz / 2.0f);

            SpecHPSDR spec;
            spec = specRX.GetSpecRX(rx - 1);

            if ((int)(spanMHz * 1e6) > spec.SampleRate)
            {
                // can't fit, so max zoom out
                ptbDisplayZoom.Value = ptbDisplayZoom.Minimum;
                ptbDisplayZoom_Scroll(this, EventArgs.Empty);
            }
            else
            {
                // calculate zoom
                double bin_width = (double)spec.SampleRate / (double)spec.FFTSize;
                int bins_per_subspan = spec.FFTSize - 2 * spec.Clip;

                int bins = spec.Stitches * bins_per_subspan;

                int spanBins = (int)((spanMHz * 1e6) / bin_width);
                spanBins = Math.Min(spanBins, bins);

                double tmp = 1.0 - ((double)spanBins / (double)bins);
                double zoom = Math.Pow(10, tmp) - 1.0;
                zoom /= 9.0;

                m_bIgnoreZoomCentre = true; //[2.10.3.5]MW0LGE used in ptbDisplayZoom_Scroll to ignore the shift key which might be held for RX2
                btnDisplayPanCenter_Click(this, EventArgs.Empty);
                ptbDisplayZoom.Value = (int)((zoom * 230.0) + 10.0);
                ptbDisplayZoom_Scroll(this, EventArgs.Empty); //force (not ideal)
                m_bIgnoreZoomCentre = false;

                m_bIgnoreLimitsForZTB = true;

                if (rx == 1)
                {
                    // shift to align for CW
                    if (rx1_dsp_mode == DSPMode.CWL)
                        centre -= (double)cw_pitch * 0.0000010;
                    else if (rx1_dsp_mode == DSPMode.CWU)
                        centre += (double)cw_pitch * 0.0000010;

                    CentreFrequency = centre;
                    txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                }
                else if (rx == 2)
                {
                    // shift to align for CW
                    if (rx2_dsp_mode == DSPMode.CWL)
                        centre -= (double)cw_pitch * 0.0000010;
                    else if (rx2_dsp_mode == DSPMode.CWU)
                        centre += (double)cw_pitch * 0.0000010;

                    CentreRX2Frequency = centre;
                    txtVFOBFreq_LostFocus(this, EventArgs.Empty);
                }

                m_bIgnoreLimitsForZTB = false;
            }

            return true;
        }
        private double lastZoomFactor = 1.0;

        private void ptbDisplayZoom_Scroll(object sender, System.EventArgs e)
        {
            double dOldZoomFactor = lastZoomFactor;//MW0LGE21d

            specRX.GetSpecRX(0).ZoomSlider = ((double)ptbDisplayZoom.Value - 10.0) / 230.0;
            specRX.GetSpecRX(1).ZoomSlider = ((double)ptbDisplayZoom.Value - 10.0) / 230.0;
            specRX.GetSpecRX(cmaster.inid(1, 0)).ZoomSlider = ((double)ptbDisplayZoom.Value - 10.0) / 230.0;
            double zoom_factor = 1.0 / ((ptbDisplayZoom.Maximum + ptbDisplayZoom.Minimum - ptbDisplayZoom.Value) * 0.01);

            if (zoom_factor == 0.5) radDisplayZoom05.Checked = true;
            else if (zoom_factor == 1.0) radDisplayZoom1x.Checked = true;
            else if (zoom_factor == 2.0) radDisplayZoom2x.Checked = true;
            else if (zoom_factor == 4.0) radDisplayZoom4x.Checked = true;
            else
            {
                radDisplayZoom05.Checked = false;
                radDisplayZoom1x.Checked = false;
                radDisplayZoom2x.Checked = false;
                radDisplayZoom4x.Checked = false;
            }

            CalcDisplayFreq();
            CalcRX2DisplayFreq();
            CalcTXDisplayFreq();

            if (initializing) lastZoomFactor = zoom_factor;
            bool zoomingIn = (zoom_factor > lastZoomFactor);

            if (!m_bIgnoreZoomCentre) //[2.10.3.5]MW0LGE fixes #345
            {
                // MW0LGE shift modifier
                bool bCentre = !m_bZoomShiftModifier || (m_bZoomShiftModifier && ((!Common.ShiftKeyDown && !m_bZoomShiftModifierReverse) || (Common.ShiftKeyDown && m_bZoomShiftModifierReverse)));

                if ((ClickTuneDisplay && zoomingIn) && bCentre)  //-W2PA Force centering display when zooming in with CTUN on, to keep the vfo within the display
                {
                    CentreFrequency = VFOAFreq;
                    txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                }
                if (rx2_enabled && (ClickTuneRX2Display && zoomingIn) && bCentre)  //MW0LGE - we should do rx2 as well !
                {
                    CentreRX2Frequency = VFOBFreq;
                    txtVFOBFreq_LostFocus(this, EventArgs.Empty);
                }
            }

            lastZoomFactor = zoom_factor;

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbDisplayZoom.Focus();
            }

            if (dOldZoomFactor != zoom_factor) ZoomFactorChangedHandlers?.Invoke(dOldZoomFactor, zoom_factor, ptbDisplayZoom.Value); //MW0LGE_21d
        }

        private void radDisplayZoom05_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radDisplayZoom05.Checked)
            {
                btnDisplayPanCenter_Click(this, EventArgs.Empty); //MW0LGE_[2.9.0.7] centre before the zoom
                ptbDisplayZoom.Value = ptbDisplayZoom.Maximum + ptbDisplayZoom.Minimum - (int)(100.0 / 0.5);
                ptbDisplayZoom_Scroll(this, EventArgs.Empty);
            }
        }

        private void radDisplayZoom1x_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radDisplayZoom1x.Checked)
            {
                btnDisplayPanCenter_Click(this, EventArgs.Empty); //MW0LGE_[2.9.0.7] centre before the zoom
                ptbDisplayZoom.Value = ptbDisplayZoom.Maximum + ptbDisplayZoom.Minimum - (int)(100.0 / 1.0);
                ptbDisplayZoom_Scroll(this, EventArgs.Empty);
            }
        }

        private void radDisplayZoom2x_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radDisplayZoom2x.Checked)
            {
                btnDisplayPanCenter_Click(this, EventArgs.Empty); //MW0LGE_[2.9.0.7] centre before the zoom
                ptbDisplayZoom.Value = ptbDisplayZoom.Maximum + ptbDisplayZoom.Minimum - (int)(100.0 / 2.0);
                ptbDisplayZoom_Scroll(this, EventArgs.Empty);
            }
        }

        private void radDisplayZoom4x_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radDisplayZoom4x.Checked)
            {
                btnDisplayPanCenter_Click(this, EventArgs.Empty); //MW0LGE_[2.9.0.7] centre before the zoom
                ptbDisplayZoom.Value = ptbDisplayZoom.Maximum + ptbDisplayZoom.Minimum - (int)(100.0 / 4.0);
                ptbDisplayZoom_Scroll(this, EventArgs.Empty);
            }
        }

        #endregion

        #region Band Button Events
        // ======================================================
        // Band Button Events
        // ======================================================

        private void radBand160_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B160M);           
        }

        private void radBand80_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B80M);           
        }

        private void radBand60_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B60M);
        }

        private void radBand40_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B40M);
        }

        private void radBand30_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B30M);
        }

        private void radBand20_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B20M);
        }

        private void radBand17_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B17M);
        }

        private void radBand15_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B15M);
        }

        private void radBand12_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B12M);
        }

        private void radBand10_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B10M);
        }

        private void radBand6_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B6M);
        }

        private void radBand2_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.B2M);
        }

        private void radBandWWV_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            BandPreChangeHandlers?.Invoke(1, Band.WWV);
        }

        private void radBandGEN_Click(object sender, EventArgs e)
        {

        }

        private void radBandVHF_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d new bandstack system
            string band = ((Control)sender).Name.Substring(7); // cut the radBand off, and just use VHF
            Band b = BandStackManager.StringToBand(band);
            BandPreChangeHandlers?.Invoke(1, b);
        }

        #endregion

        #region Mode Button Events
        // ======================================================
        // Mode Button Events
        // ======================================================

        private void setVFOAFreqNoUpdate(double freq)
        {
            m_dVFOAFreq = freq;
            txtVFOAFreq.Text = freq.ToString("f6");
        }
        private void setVFOBFreqNoUpdate(double freq)
        {
            m_dVFOBFreq = freq;
            txtVFOBFreq.Text = freq.ToString("f6");
        }
        // MW0LGE_21d used to default colours of all button+radio controls, and inside other panels or groups
        // an issue was noticed where text change colour on buttons that had
        // be selected/deseleted
        private void initControlBackColours(Control c)
        {
            foreach (Control cc in c.Controls)
            {
                // only do for buttons/radio
                Type t = cc.GetType();

                if (t == typeof(ButtonTS) || t == typeof(RadioButtonTS))
                {
                    if (cc.Name != "radRX1Show" &&  // some controls are to be ignored as no skinpacks with buttons yet
                        cc.Name != "radRX2Show" &&
                        cc.Name != "chkVACStereo")
                        cc.BackColor = SystemColors.Control;
                }
                else if (t == typeof(PanelTS)) initControlBackColours(cc);
                else if (t == typeof(GroupBoxTS)) initControlBackColours(cc);
            }
        }
        private enum ModeSpecificPanel
        {
            phone = 0,
            cw,
            fm,
            digital
        }
        private void SetRX1Mode(DSPMode new_mode)
        {
            if (new_mode == DSPMode.FIRST || new_mode == DSPMode.LAST) return;

            //MW0LGE_21d
            Band oldBand = RX1Band;
            //            
            bool bStoreDigiModeSettings = false;
            bool bRecallDigiModeSettings = false;
            bool bTurnOffSettingsForDigimode = false;

            DSPMode old_mode = rx1_dsp_mode;

            WDSP.SetChannelState(WDSP.id(0, 1), 0, 0);              // turn off the DSP channels
            WDSP.SetChannelState(WDSP.id(0, 0), 0, 1);
            Thread.Sleep(1);

            if (new_mode == DSPMode.FM)                             // set DSP samplerate
            {
                WDSP.SetDSPSamplerate(WDSP.id(0, 0), 192000);
                WDSP.SetDSPSamplerate(WDSP.id(0, 1), 192000);
            }
            else
            {
                WDSP.SetDSPSamplerate(WDSP.id(0, 0), 48000);
                WDSP.SetDSPSamplerate(WDSP.id(0, 1), 48000);
            }

            radio.GetDSPRX(0, 0).DSPMode = new_mode;				// set new DSP mode
            radio.GetDSPRX(0, 1).DSPMode = new_mode;

            if (chkVFOATX.Checked || !rx2_enabled)
            {
                Audio.TXDSPMode = new_mode;
                radio.GetDSPTX(0).CurrentDSPMode = new_mode;
            }
            Display.RX1DSPMode = new_mode;
            RadioDSP.RX1DSPMode = new_mode;

            if (new_mode == DSPMode.CWL || new_mode == DSPMode.CWU)
            {
                WDSP.SetChannelTDelayUp(WDSP.id(0, 0), 0.005);
                WDSP.SetChannelTDelayUp(WDSP.id(0, 1), 0.005);
                WDSP.SetChannelTSlewUp(WDSP.id(0, 0), 0.010);
                WDSP.SetChannelTSlewUp(WDSP.id(0, 1), 0.010);
                WDSP.SetChannelTDelayDown(WDSP.id(0, 0), 0.000);
                WDSP.SetChannelTDelayDown(WDSP.id(0, 1), 0.000);
                WDSP.SetChannelTSlewDown(WDSP.id(0, 0), 0.005);
                WDSP.SetChannelTSlewDown(WDSP.id(0, 1), 0.005);
            }
            else
            {                
                WDSP.SetChannelTDelayUp(WDSP.id(0, 0), 0.000);
                WDSP.SetChannelTDelayUp(WDSP.id(0, 1), 0.000);
                WDSP.SetChannelTSlewUp(WDSP.id(0, 0), 0.010);
                WDSP.SetChannelTSlewUp(WDSP.id(0, 1), 0.010);
                WDSP.SetChannelTDelayDown(WDSP.id(0, 0), 0.000);
                WDSP.SetChannelTDelayDown(WDSP.id(0, 1), 0.000);
                WDSP.SetChannelTSlewDown(WDSP.id(0, 0), 0.010);
                WDSP.SetChannelTSlewDown(WDSP.id(0, 1), 0.010);
            }


            double rx1_freq = VFOAFreq;

            ptbFilterShift.Value = 0;
            btnFilterShiftReset.BackColor = SystemColors.Control;

            switch (old_mode)
            {
                case DSPMode.LSB:
                    radModeLSB.BackColor = SystemColors.Control;
                    break;
                case DSPMode.USB:
                    radModeUSB.BackColor = SystemColors.Control;
                    break;
                case DSPMode.DSB:
                    radModeDSB.BackColor = SystemColors.Control;
                    break;
                case DSPMode.CWL:
                    radModeCWL.BackColor = SystemColors.Control;

                    if ((chkVFOATX.Checked || !rx2_enabled) && new_mode != DSPMode.CWU && new_mode != DSPMode.CWL)
                    {
                        chkMON.Checked = mon_recall;
                    }

                    // turn off APF
                    radio.GetDSPRX(0, 0).RXAPFRun = false;
                    radio.GetDSPRX(0, 1).RXAPFRun = false;
                    SetupForm.EnableRX1APFControl = false;
                    lblRX1APF.Hide();
                    // enable ANF
                    chkANF.Enabled = true;
                    chkANF_CheckedChanged(this, EventArgs.Empty);

                    if (!RX1IsIn60mChannel())
                    {
                        switch (new_mode)
                        {
                            case DSPMode.USB:
                                rx1_freq -= (cw_pitch * 0.0000010);
                                break;
                            case DSPMode.CWU:
                                break;
                            default:
                                rx1_freq += (cw_pitch * 0.0000010);
                                break;
                        }

                        setVFOAFreqNoUpdate(rx1_freq);
                    }
                    break;
                case DSPMode.CWU:
                    radModeCWU.BackColor = SystemColors.Control;

                    if ((chkVFOATX.Checked || !rx2_enabled) && new_mode != DSPMode.CWL && new_mode != DSPMode.CWU)
                    {
                        chkMON.Checked = mon_recall;
                    }

                    // turn off APF
                    radio.GetDSPRX(0, 0).RXAPFRun = false;
                    radio.GetDSPRX(0, 1).RXAPFRun = false;
                    SetupForm.EnableRX1APFControl = false;
                    lblRX1APF.Hide();
                    // enable ANF
                    chkANF.Enabled = true;
                    chkANF_CheckedChanged(this, EventArgs.Empty);

                    if (!RX1IsIn60mChannel())
                    {
                        switch (new_mode)
                        {
                            case DSPMode.LSB:
                                rx1_freq += (cw_pitch * 0.0000010);
                                break;
                            case DSPMode.CWL:
                                break;
                            default:
                                rx1_freq -= (cw_pitch * 0.0000010);
                                break;
                        }

                        setVFOAFreqNoUpdate(rx1_freq);
                    }
                    break;
                case DSPMode.FM:
                    radModeFMN.BackColor = SystemColors.Control;
                    if (chkVFOATX.Checked || !rx2_enabled)
                    {
                        if (new_mode != DSPMode.AM &&
                            new_mode != DSPMode.SAM)
                        {
                            // chkMON.Enabled = true;
                            chkBIN.Enabled = true;
                        }
                        chkMON.Enabled = true;

                        ptbMic_Scroll(this, EventArgs.Empty);
                    }
                    if (new_mode != DSPMode.SPEC && new_mode != DSPMode.DRM)
                        EnableAllFilters();

                    handleSqlFM(1, false);
                    break;
                case DSPMode.AM:
                    radModeAM.BackColor = SystemColors.Control;
                    if (chkVFOATX.Checked || !rx2_enabled)
                    {
                        if (new_mode != DSPMode.AM &&
                            new_mode != DSPMode.SAM)
                        {
                            chkBIN.Enabled = true;
                        }
                        chkMON.Enabled = true;
                    }
                    break;
                case DSPMode.SAM:
                    radModeSAM.BackColor = SystemColors.Control;
                    if (chkVFOATX.Checked || !rx2_enabled)
                    {
                        if (new_mode != DSPMode.AM &&
                            new_mode != DSPMode.SAM)
                        {
                            chkBIN.Enabled = true;
                        }
                        chkMON.Enabled = true;
                    }
                    break;
                case DSPMode.SPEC:
                    radModeSPEC.BackColor = SystemColors.Control;
                    comboDisplayMode.Items.Insert(1, "Panadapter");
                    comboDisplayMode.Items.Insert(5, "Waterfall");
                    ptbFilterShift.Enabled = true;
                    btnFilterShiftReset.Enabled = true;
                    if (new_mode != DSPMode.DRM && new_mode != DSPMode.FM)
                        EnableAllFilters();
                    RX1Filter = rx1_filter;
                    //if_shift = true;
                    if (was_panadapter) comboDisplayMode.Text = "Panadapter";
                    else if (was_waterfall) comboDisplayMode.Text = "Waterfall";
                    switch (Display.CurrentDisplayMode)
                    {
                        case DisplayMode.PANADAPTER:
                        case DisplayMode.WATERFALL:
                        case DisplayMode.PANAFALL:
                        case DisplayMode.PANASCOPE:
                            radio.GetDSPRX(0, 0).SpectrumPreFilter = true;
                            break;
                        default:
                            radio.GetDSPRX(0, 0).SpectrumPreFilter = false;
                            break;
                    }
                    break;
                case DSPMode.DIGL:
                    radModeDIGL.BackColor = SystemColors.Control;
                    if (vac_auto_enable &&
                        new_mode != DSPMode.DIGU &&
                        new_mode != DSPMode.DRM)
                    {
                        SetupForm.VACEnable = false;
                    }

                    if (new_mode != DSPMode.DIGU) bRecallDigiModeSettings = true; // see comment below
                    break;
                case DSPMode.DIGU:
                    radModeDIGU.BackColor = SystemColors.Control;
                    if (vac_auto_enable &&
                        new_mode != DSPMode.DIGL &&
                        new_mode != DSPMode.DRM)
                    {
                        SetupForm.VACEnable = false;
                    }

                    if (new_mode != DSPMode.DIGL) bRecallDigiModeSettings = true; //[2.10.3]MW0LGE done below after tx profile change
                    break;
                case DSPMode.DRM:
                    radModeDRM.BackColor = SystemColors.Control;

                    vfo_offset = 0.0;
                    if (vac_auto_enable &&
                        new_mode != DSPMode.DIGL &&
                        new_mode != DSPMode.DIGU)
                    {
                        SetupForm.VACEnable = false;
                    }
                    ptbFilterShift.Enabled = true;
                    btnFilterShiftReset.Enabled = true;
                    if (new_mode != DSPMode.SPEC && new_mode != DSPMode.FM)
                        EnableAllFilters();

                    chkTNF.Enabled = true;
                    btnTNFAdd.Enabled = true;
                    break;
            }
            
            switch (new_mode)
            {
                case DSPMode.LSB:
                    vfo_offset = 0.0;
                    radModeLSB.BackColor = button_selected_color;

                    if (!rx_only && PowerOn)
                        chkMOX.Enabled = true;
                    if (chkVFOATX.Checked || !rx2_enabled)
                    {
                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);
                        radio.GetDSPTX(0).TXOsc = 0.0;
                    }

                    break;
                case DSPMode.USB:
                    radModeUSB.BackColor = button_selected_color;

                    if (!rx_only && chkPower.Checked)
                        chkMOX.Enabled = true;
                    if (chkVFOATX.Checked || !rx2_enabled)
                    {
                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);
                        radio.GetDSPTX(0).TXOsc = 0.0;
                    }

                    break;
                case DSPMode.DSB:
                    radModeDSB.BackColor = button_selected_color;

                    if (!rx_only && chkPower.Checked)
                        chkMOX.Enabled = true;
                    if (chkVFOATX.Checked || !rx2_enabled)
                    {
                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);
                        radio.GetDSPTX(0).TXOsc = 0.0;
                    }

                    break;
                case DSPMode.CWL:
                    radModeCWL.BackColor = button_selected_color;

                    if (chkVFOATX.Checked || !rx2_enabled)
                    {

                        CWPitch = cw_pitch;
                        radio.GetDSPTX(0).TXOsc = 0.0;
                        if (!rx_only && chkPower.Checked)
                        {
                            chkMOX.Enabled = true;
                        }

                        if (old_mode != DSPMode.CWL && old_mode != DSPMode.CWU)
                        {
                            if (!initializing)
                                mon_recall = chkMON.Checked;
                            chkMON.Checked = cw_sidetone;
                        }
                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);
                    }

                    if (!RX1IsIn60mChannel())
                    {
                        switch (rx1_dsp_mode)
                        {
                            case DSPMode.USB:
                                rx1_freq += (cw_pitch * 1e-6);
                                break;
                            case DSPMode.CWU:
                                break;
                            default:
                                rx1_freq -= (cw_pitch * 1e-6);
                                break;
                        }

                        setVFOAFreqNoUpdate(rx1_freq);
                    }

                    // enable APF
                    SetupForm.EnableRX1APFControl = true;
                    lblRX1APF.Show();
                    // turn off ANF
                    radio.GetDSPRX(0, 0).AutoNotchFilter = false;
                    radio.GetDSPRX(0, 1).AutoNotchFilter = false;
                    chkANF.Enabled = false;

                    break;
                case DSPMode.CWU:
                    radModeCWU.BackColor = button_selected_color;

                    if (chkVFOATX.Checked || !rx2_enabled)
                    {
                        CWPitch = cw_pitch;
                        radio.GetDSPTX(0).TXOsc = 0.0;

                        if (!rx_only && chkPower.Checked)
                        {
                            chkMOX.Enabled = true;
                        }
                        
                        if (old_mode != DSPMode.CWL && old_mode != DSPMode.CWU)//[2.10.3]MW0LGE fixes #59 mon issue, did not consider old_mode and igmored CWU
                        {
                            if (!initializing)
                                mon_recall = chkMON.Checked;
                            chkMON.Checked = cw_sidetone;
                        }
                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);
                    }

                    if (!RX1IsIn60mChannel())
                    {
                        switch (rx1_dsp_mode)
                        {
                            case DSPMode.LSB:
                                rx1_freq -= (cw_pitch * 1e-6);
                                break;
                            case DSPMode.CWL:
                                break;
                            default:
                                rx1_freq += (cw_pitch * 1e-6);
                                break;
                        }

                        setVFOAFreqNoUpdate(rx1_freq);
                    }

                    // enable APF
                    SetupForm.EnableRX1APFControl = true;
                    chkANF.Enabled = false;
                    lblRX1APF.Show();
                    // turn off ANF
                    radio.GetDSPRX(0, 0).AutoNotchFilter = false;
                    radio.GetDSPRX(0, 1).AutoNotchFilter = false;

                    break;
                case DSPMode.FM:
                    radModeFMN.BackColor = button_selected_color;
                    DisableAllFilters();
                    if (chkNR.CheckState == CheckState.Indeterminate)
                        chkNR.CheckState = CheckState.Unchecked;

                    handleSqlFM(1, true);

                    if (chkVFOATX.Checked || !rx2_enabled)
                    {
                        if (!rx_only && chkPower.Checked)
                            chkMOX.Enabled = true;
                        chkMON.Checked = false;
                        chkMON.Enabled = false;
                        chkBIN.Checked = false;
                        chkBIN.Enabled = false;
                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);

                        ptbFMMic_Scroll(this, EventArgs.Empty);
                    }

                    break;
                case DSPMode.AM:
                    radModeAM.BackColor = button_selected_color;

                    if (!rx_only && chkPower.Checked)
                        chkMOX.Enabled = true;
                    if (chkVFOATX.Checked || !rx2_enabled)
                    {
                        chkBIN.Checked = false;
                        chkBIN.Enabled = false;
                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);
                    }

                    break;
                case DSPMode.SAM:
                    radModeSAM.BackColor = button_selected_color;

                    if (!rx_only && chkPower.Checked)
                        chkMOX.Enabled = true;
                    if (chkVFOATX.Checked || !rx2_enabled)
                    {
                        chkBIN.Checked = false;
                        chkBIN.Enabled = false;
                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);
                    }

                    break;
                case DSPMode.SPEC:
                    radModeSPEC.BackColor = button_selected_color;

                    if_shift = false;
                    radio.GetDSPRX(0, 0).RXOsc = 0.0;
                    DisableAllFilters();
                    ptbFilterShift.Enabled = false;
                    btnFilterShiftReset.Enabled = false;
                    bool save_pan = (Display.CurrentDisplayMode == DisplayMode.PANADAPTER);
                    bool save_water = (Display.CurrentDisplayMode == DisplayMode.WATERFALL);
                    if (save_pan || save_water)
                    {
                        comboDisplayMode.Text = "Spectrum";
                    }
                    comboDisplayMode.Items.Remove("Panadapter");
                    comboDisplayMode.Items.Remove("Waterfall");
                    was_panadapter = save_pan;
                    was_waterfall = save_water;
                    radio.GetDSPRX(0, 0).SpectrumPreFilter = true;
                    Display.RXDisplayLow = -(int)sample_rate_rx1 / 2;
                    Display.RXDisplayHigh = (int)sample_rate_rx1 / 2;
                    break;
                case DSPMode.DIGL:
                    radModeDIGL.BackColor = button_selected_color;

                    if (chkVFOATX.Checked || !rx2_enabled)
                    {
                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);
                        radio.GetDSPTX(0).TXOsc = 0.0;
                    }
                    if (vac_auto_enable)
                        SetupForm.VACEnable = true;

                    if (old_mode != DSPMode.DIGU)
                    {
                        bStoreDigiModeSettings = true; //[2.10.3]MW0LGE done after tx profile change at end as we will overwrite existng tx profile if auto save is on
                        bTurnOffSettingsForDigimode = true;
                    }
                    break;
                case DSPMode.DIGU:
                    radModeDIGU.BackColor = button_selected_color;

                    if (chkVFOATX.Checked)
                    {
                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);
                        radio.GetDSPTX(0).TXOsc = 0.0;
                    }
                    if (vac_auto_enable)
                        SetupForm.VACEnable = true;

                    if (old_mode != DSPMode.DIGL)
                    {
                        bStoreDigiModeSettings = true; //see comment above
                        bTurnOffSettingsForDigimode = true;
                    }
                    break;
                case DSPMode.DRM:
                    if_shift = false;
                    vfo_offset = -0.012;
                    radModeDRM.BackColor = button_selected_color;

                    if (vac_auto_enable)
                        SetupForm.VACEnable = true;

                    if (chkVFOATX.Checked || !rx2_enabled)
                    {
                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);
                        radio.GetDSPTX(0).TXOsc = 0.0;
                    }
                    DisableAllFilters();
                    ptbFilterShift.Enabled = false;
                    btnFilterShiftReset.Enabled = false;

                    radio.GetDSPRX(0, 0).SetRXFilter(7000, 17000);

                    btnTNFAdd.Enabled = false;
                    chkTNF.Enabled = false;
                    chkTNF.Checked = false;
                    break;
            }

            if (RX1IsOn60mChannel() && current_region == FRSRegion.US)
            {
                rx1_freq += (-ModeFreqOffset(old_mode) + ModeFreqOffset(new_mode));

                setVFOAFreqNoUpdate(rx1_freq);
            }

            // int new_txosc = (int)radio.GetDSPTX(0).TXOsc;

            FilterToolStripMenuItem1.Text = (radFilter1.Text = rx1_filters[(int)new_mode].GetName(Filter.F1));
            FilterToolStripMenuItem2.Text = (radFilter2.Text = rx1_filters[(int)new_mode].GetName(Filter.F2));
            FilterToolStripMenuItem3.Text = (radFilter3.Text = rx1_filters[(int)new_mode].GetName(Filter.F3));
            FilterToolStripMenuItem4.Text = (radFilter4.Text = rx1_filters[(int)new_mode].GetName(Filter.F4));
            FilterToolStripMenuItem5.Text = (radFilter5.Text = rx1_filters[(int)new_mode].GetName(Filter.F5));
            FilterToolStripMenuItem6.Text = (radFilter6.Text = rx1_filters[(int)new_mode].GetName(Filter.F6));
            FilterToolStripMenuItem7.Text = (radFilter7.Text = rx1_filters[(int)new_mode].GetName(Filter.F7));
            FilterToolStripMenuItem8.Text = (radFilter8.Text = rx1_filters[(int)new_mode].GetName(Filter.F8));
            FilterToolStripMenuItem9.Text = (radFilter9.Text = rx1_filters[(int)new_mode].GetName(Filter.F9));
            FilterToolStripMenuItem10.Text = (radFilter10.Text = rx1_filters[(int)new_mode].GetName(Filter.F10));
            radFilterVar1.Text = rx1_filters[(int)new_mode].GetName(Filter.VAR1);
            radFilterVar2.Text = rx1_filters[(int)new_mode].GetName(Filter.VAR2);

            rx1_dsp_mode = new_mode;

            SelectModeDependentPanel(); //MW0LGE_21k9d

            if (rx1_dsp_mode != DSPMode.SPEC && rx1_dsp_mode != DSPMode.FM && rx1_dsp_mode != DSPMode.DRM)
            {
                RX1Filter = rx1_filters[(int)new_mode].LastFilter;
            }
            else
            {
                if (rx1_dsp_mode == DSPMode.FM)
                {
                    int halfBw = (int)(radio.GetDSPTX(0).TXFMDeviation + radio.GetDSPRX(0, 0).RXFMHighCut); //[2.10.3.4]MW0LGE
                    UpdateRX1Filters(-halfBw, halfBw);
                }

                RX1Filter = Filter.NONE;
            }
            BINToolStripMenuItem.Enabled = chkBIN.Enabled;

            tbFilterWidthScroll_newMode(); // wjt 

            UpdateDSP();

            txtVFOAFreq_LostFocus(this, EventArgs.Empty);
            ptbPWR_Scroll(this, EventArgs.Empty);
            if (chkVFOSplit.Checked || full_duplex || PSState)
                txtVFOBFreq_LostFocus(this, EventArgs.Empty);

            chkSquelch_CheckStateChanged(this, EventArgs.Empty);
            CalcDisplayFreq();
            if (new_mode == DSPMode.CWL || new_mode == DSPMode.CWU)
            {
                chkCWAPFEnabled_CheckedChanged(this, EventArgs.Empty);
            }

            if (old_mode == DSPMode.FM || new_mode == DSPMode.FM)
            {
                SetupForm.ForceAudioReset();
            }

            WDSP.SetChannelState(WDSP.id(0, 0), 1, 0);              // turn on the DSP channels
            if (radio.GetDSPRX(0, 1).Active)
                WDSP.SetChannelState(WDSP.id(0, 1), 1, 0);

            // Manage QSK appropriately when switching modes --------------
            if (new_mode != DSPMode.CWL && new_mode != DSPMode.CWU)  // Changing to a non-CW mode
            {
                // Although CWFWKeyer is mostly a deprecated flag, it's useful in the QSK-enabled firmware (1.7 or later) -W2PA
                // It is used here solely to prevent keying in non-CW modes.
                CWFWKeyer = false;  // Disallow the FW to key the rig except in CW modes
                if (BreakInEnabledState == CheckState.Indeterminate) NonCWModeBreakInDisabled = true;  // Disable break-in if not in a CW mode
            }
            else // Changing to a CW mode
            {
                CWFWKeyer = true;
                NonCWModeBreakInDisabled = false; // Re-enable break-in if necessary
            }

            if ((new_mode != DSPMode.CWL && new_mode != DSPMode.CWU)
                && (old_mode == DSPMode.CWL || old_mode == DSPMode.CWU)) // Changing to a non-CW mode from CW
            {
                if (QSKEnabled)
                {
                    chkQSK.Checked = false;  // QSKEnabled = false; // If QSK was on, turn it off to return to non-QSK settings
                    qsk_in_CW = true; // But remember it was on in CW modes
                }
                else qsk_in_CW = false;
            }

            if ((new_mode == DSPMode.CWL || new_mode == DSPMode.CWU)
                && (old_mode != DSPMode.CWL && old_mode != DSPMode.CWU)) // Changing to a CW mode from non-CW
            {
                if (qsk_in_CW) chkQSK.CheckState = CheckState.Indeterminate;
            }
            // end of QSK-related code ---------------------------------------

            if (bRecallDigiModeSettings) SetDigiMode(1, DigiMode.DigiModeSettingState.dmssRecall); // recall before as TX profile may change them

            // MW0LGE from powersdr - selects tx profiles 
            switch (rx1_dsp_mode)
            {
                case DSPMode.DIGL:
                case DSPMode.DIGU:
                    comboDigTXProfile_SelectedIndexChanged(this, EventArgs.Empty);
                    break;
                case DSPMode.FM:
                    comboFMTXProfile_SelectedIndexChanged(this, EventArgs.Empty);
                    break;
                case DSPMode.AM:
                case DSPMode.SAM:
                    comboAMTXProfile.BringToFront();
                    comboAMTXProfile_SelectedIndexChanged(this, EventArgs.Empty);
                    break;
                default:
                    comboTXProfile.BringToFront();
                    comboTXProfile_SelectedIndexChanged(this, EventArgs.Empty);
                    break;
            }
            // end powersdr chunk

            if (bStoreDigiModeSettings) SetDigiMode(1, DigiMode.DigiModeSettingState.dmssStore);
            if (bTurnOffSettingsForDigimode) SetDigiMode(1, DigiMode.DigiModeSettingState.dmssTurnOffSettings);

            //MW0LGE_21b
            if (old_mode != new_mode) ModeChangeHandlers?.Invoke(1, old_mode, new_mode, oldBand, RX1Band);
        }

        private void radModeButton_CheckedChanged(object sender, System.EventArgs e)
        {
            if (sender == null) return;
            if (sender.GetType() != typeof(RadioButtonTS)) return;
            RadioButtonTS radioBtnTS = (RadioButtonTS)sender;
            if (!radioBtnTS.Checked) return;
            string radiobut = ((RadioButtonTS)sender).Text;

            DSPMode mode;

            switch (radiobut)
            {
                case "LSB":
                    mode = DSPMode.LSB;
                    break;
                case "USB":
                    mode = DSPMode.USB;
                    break;
                case "DSB":
                    mode = DSPMode.DSB;
                    break;
                case "CWL":
                    mode = DSPMode.CWL;
                    break;
                case "CWU":
                    mode = DSPMode.CWU;
                    break;
                case "FM":
                    mode = DSPMode.FM;
                    break;
                case "AM":
                    mode = DSPMode.AM;
                    break;
                case "SAM":
                    mode = DSPMode.SAM;
                    break;
                case "SPEC":
                    mode = DSPMode.SPEC;
                    break;
                case "DIGL":
                    mode = DSPMode.DIGL;
                    break;
                case "DIGU":
                    mode = DSPMode.DIGU;
                    break;
                case "DRM":
                    mode = DSPMode.DRM;
                    break;
                default:
                    mode = DSPMode.FIRST;
                    break;
            }

            if (mode != DSPMode.FIRST) //MW0LGE_21k9d4
            {
                SetRX1Mode(mode);
                lblModeLabel.Text = radiobut;
                lblModeBigLabel.Text = radiobut;
            }

            lSBToolStripMenuItem.Checked = radModeLSB.Checked;
            uSBToolStripMenuItem.Checked = radModeUSB.Checked;
            dSBToolStripMenuItem.Checked = radModeDSB.Checked;
            cWLToolStripMenuItem.Checked = radModeCWL.Checked;
            cWUToolStripMenuItem.Checked = radModeCWU.Checked;
            fMToolStripMenuItem.Checked = radModeFMN.Checked;
            aMToolStripMenuItem.Checked = radModeAM.Checked;
            sAMToolStripMenuItem.Checked = radModeSAM.Checked;
            sPECToolStripMenuItem.Checked = radModeSPEC.Checked;
            dIGLToolStripMenuItem.Checked = radModeDIGL.Checked;
            dIGUToolStripMenuItem.Checked = radModeDIGU.Checked;
            dRMToolStripMenuItem.Checked = radModeDRM.Checked;
            if (modePopupForm != null) modePopupForm.RepopulateForm();
            if (filterPopupForm != null) filterPopupForm.RepopulateForm();

            // MW0LGE_21j
            setSmallRX2ModeFilterLabels();
        }

        #endregion

        #region Filter Button Events
        // ======================================================
        // Filter Button Events
        // ======================================================

        public void SetRX1Filter(Filter new_filter)
        {
            if (rx1_dsp_mode == DSPMode.FIRST || rx1_dsp_mode == DSPMode.LAST) return;

            Filter oldFilter = rx1_filter; //MW0LGE_21d
            int oldLow, oldHigh;
            if (oldFilter == Filter.FIRST || oldFilter == Filter.LAST)
            {
                oldLow = 0;
                oldHigh = 0;
            }
            else
            {
                oldLow = rx1_filters[(int)rx1_dsp_mode].GetLow(oldFilter);
                oldHigh = rx1_filters[(int)rx1_dsp_mode].GetHigh(oldFilter);
            }

            int low = 0, high = 0;

            switch (rx1_filter)
            {
                case Filter.F1:
                    radFilter1.BackColor = SystemColors.Control;
                    break;
                case Filter.F2:
                    radFilter2.BackColor = SystemColors.Control;
                    break;
                case Filter.F3:
                    radFilter3.BackColor = SystemColors.Control;
                    break;
                case Filter.F4:
                    radFilter4.BackColor = SystemColors.Control;
                    break;
                case Filter.F5:
                    radFilter5.BackColor = SystemColors.Control;
                    break;
                case Filter.F6:
                    radFilter6.BackColor = SystemColors.Control;
                    break;
                case Filter.F7:
                    radFilter7.BackColor = SystemColors.Control;
                    break;
                case Filter.F8:
                    radFilter8.BackColor = SystemColors.Control;
                    break;
                case Filter.F9:
                    radFilter9.BackColor = SystemColors.Control;
                    break;
                case Filter.F10:
                    radFilter10.BackColor = SystemColors.Control;
                    break;
                case Filter.VAR1:
                    radFilterVar1.BackColor = SystemColors.Control;
                    udFilterLow.Enabled = false;
                    udFilterHigh.Enabled = false;
                    break;
                case Filter.VAR2:
                    radFilterVar2.BackColor = SystemColors.Control;
                    udFilterLow.Enabled = false;
                    udFilterHigh.Enabled = false;
                    break;
            }

            rx1_filter = new_filter;

            low = rx1_filters[(int)rx1_dsp_mode].GetLow(new_filter);
            high = rx1_filters[(int)rx1_dsp_mode].GetHigh(new_filter);
            rx1_filters[(int)rx1_dsp_mode].LastFilter = new_filter;

            switch (new_filter)
            {
                case Filter.F1:
                    radFilter1.BackColor = button_selected_color;
                    break;
                case Filter.F2:
                    radFilter2.BackColor = button_selected_color;
                    break;
                case Filter.F3:
                    radFilter3.BackColor = button_selected_color;
                    break;
                case Filter.F4:
                    radFilter4.BackColor = button_selected_color;
                    break;
                case Filter.F5:
                    radFilter5.BackColor = button_selected_color;
                    break;
                case Filter.F6:
                    radFilter6.BackColor = button_selected_color;
                    break;
                case Filter.F7:
                    radFilter7.BackColor = button_selected_color;
                    break;
                case Filter.F8:
                    radFilter8.BackColor = button_selected_color;
                    break;
                case Filter.F9:
                    radFilter9.BackColor = button_selected_color;
                    break;
                case Filter.F10:
                    radFilter10.BackColor = button_selected_color;
                    break;
                case Filter.VAR1:
                    radFilterVar1.BackColor = button_selected_color;
                    udFilterLow.Enabled = true;
                    udFilterHigh.Enabled = true;
                    break;
                case Filter.VAR2:
                    radFilterVar2.BackColor = button_selected_color;
                    udFilterLow.Enabled = true;
                    udFilterHigh.Enabled = true;
                    break;
                case Filter.NONE:
                    foreach (Control c in panelFilter.Controls)
                    {
                        if (c.GetType() == typeof(RadioButtonTS))
                        {
                            ((RadioButtonTS)c).Checked = false;

                            if (c.BackColor != SystemColors.Control)
                                ((RadioButtonTS)c).BackColor = SystemColors.Control;
                        }
                    }
                    return;
            }
            UpdateRX1Filters(low, high);
            if (oldFilter != rx1_filter) FilterChangedHandlers?.Invoke(1, oldFilter, rx1_filter, RX1Band, low, high, rx1_filters[(int)rx1_dsp_mode].GetName(rx1_filter));
        }

        private void radRX2Filter_CheckedChanged(object sender, EventArgs e)
        {
            if (sender == null) return;
            if (sender.GetType() != typeof(RadioButtonTS)) return;
            RadioButtonTS radioBtnTS = (RadioButtonTS)sender;
            if (!radioBtnTS.Checked) return;

            string radiobut = ((RadioButtonTS)sender).Name;

            switch (radiobut)
            {
                case "radRX2Filter1":
                    SetRX2Filter(Filter.F1);
                    kToolStripMenuItem.Text = radRX2Filter1.Text;
                    break;
                case "radRX2Filter2":
                    SetRX2Filter(Filter.F2);
                    kToolStripMenuItem1.Text = radRX2Filter2.Text;
                    break;
                case "radRX2Filter3":
                    SetRX2Filter(Filter.F3);
                    kToolStripMenuItem2.Text = radRX2Filter3.Text;
                    break;
                case "radRX2Filter4":
                    SetRX2Filter(Filter.F4);
                    kToolStripMenuItem3.Text = radRX2Filter4.Text;
                    break;
                case "radRX2Filter5":
                    SetRX2Filter(Filter.F5);
                    kToolStripMenuItem4.Text = radRX2Filter5.Text;
                    break;
                case "radRX2Filter6":
                    SetRX2Filter(Filter.F6);
                    toolStripMenuItem13.Text = radRX2Filter6.Text;
                    break;
                case "radRX2Filter7":
                    SetRX2Filter(Filter.F7);
                    toolStripMenuItem14.Text = radRX2Filter7.Text;
                    break;
                case "radRX2FilterVar1":
                    SetRX2Filter(Filter.VAR1);
                    break;
                case "radRX2FilterVar2":
                    SetRX2Filter(Filter.VAR2);
                    break;
            }

            lblRX2FilterLabel.Text = radioBtnTS.Text;

            kToolStripMenuItem.Checked = radRX2Filter1.Checked;
            kToolStripMenuItem1.Checked = radRX2Filter2.Checked;
            kToolStripMenuItem2.Checked = radRX2Filter3.Checked;
            kToolStripMenuItem3.Checked = radRX2Filter4.Checked;
            kToolStripMenuItem4.Checked = radRX2Filter5.Checked;
            toolStripMenuItem13.Checked = radRX2Filter6.Checked;
            toolStripMenuItem14.Checked = radRX2Filter7.Checked;
            if (filterPopupForm != null) filterPopupForm.RepopulateForm();          // G8NJJ update popup

        }

        private void radFilter_CheckedChanged(object sender, EventArgs e)
        {
            if (sender == null) return;
            if (sender.GetType() != typeof(RadioButtonTS)) return;
            RadioButtonTS radioBtnTS = (RadioButtonTS)sender;
            if (!radioBtnTS.Checked) return;

            string radiobut = ((RadioButtonTS)sender).Name;

            switch (radiobut)
            {
                case "radFilter1":
                    SetRX1Filter(Filter.F1);
                    FilterToolStripMenuItem1.Text = radFilter1.Text;
                    break;
                case "radFilter2":
                    SetRX1Filter(Filter.F2);
                    FilterToolStripMenuItem2.Text = radFilter2.Text;
                    break;
                case "radFilter3":
                    SetRX1Filter(Filter.F3);
                    FilterToolStripMenuItem3.Text = radFilter3.Text;
                    break;
                case "radFilter4":
                    SetRX1Filter(Filter.F4);
                    FilterToolStripMenuItem4.Text = radFilter4.Text;
                    break;
                case "radFilter5":
                    SetRX1Filter(Filter.F5);
                    FilterToolStripMenuItem5.Text = radFilter5.Text;
                    break;
                case "radFilter6":
                    SetRX1Filter(Filter.F6);
                    FilterToolStripMenuItem6.Text = radFilter6.Text;
                    break;
                case "radFilter7":
                    SetRX1Filter(Filter.F7);
                    FilterToolStripMenuItem7.Text = radFilter7.Text;
                    break;
                case "radFilter8":
                    SetRX1Filter(Filter.F8);
                    FilterToolStripMenuItem8.Text = radFilter8.Text;
                    break;
                case "radFilter9":
                    SetRX1Filter(Filter.F9);
                    FilterToolStripMenuItem9.Text = radFilter9.Text;
                    break;
                case "radFilter10":
                    SetRX1Filter(Filter.F10);
                    FilterToolStripMenuItem10.Text = radFilter10.Text;
                    break;
                case "radFilterVar1":
                    SetRX1Filter(Filter.VAR1);
                    break;
                case "radFilterVar2":
                    SetRX1Filter(Filter.VAR2);
                    break;
            }

            lblFilterLabel.Text = radioBtnTS.Text;

            FilterToolStripMenuItem1.Checked = radFilter1.Checked;
            FilterToolStripMenuItem2.Checked = radFilter2.Checked;
            FilterToolStripMenuItem3.Checked = radFilter3.Checked;
            FilterToolStripMenuItem4.Checked = radFilter4.Checked;
            FilterToolStripMenuItem5.Checked = radFilter5.Checked;
            FilterToolStripMenuItem6.Checked = radFilter6.Checked;
            FilterToolStripMenuItem7.Checked = radFilter7.Checked;
            FilterToolStripMenuItem8.Checked = radFilter8.Checked;
            FilterToolStripMenuItem9.Checked = radFilter9.Checked;
            FilterToolStripMenuItem10.Checked = radFilter10.Checked;
            if (filterPopupForm != null) filterPopupForm.RepopulateForm();      // G8NJJ update popup

            // MW0LGE
            setSmallRX2ModeFilterLabels();
        }

        private void udFilterLow_ValueChanged(object sender, System.EventArgs e)
        {
            //MW0LGE_21d filter - work if mouse over as well
            if (udFilterLow.Focused || udFilterLow.ClientRectangle.Contains(udFilterLow.PointToClient(Control.MousePosition)))
            {
                if (udFilterLow.Value >= udFilterHigh.Value - 10)
                {
                    udFilterLow.Value = udFilterHigh.Value - 10;
                    return;
                }

                UpdateRX1Filters((int)udFilterLow.Value, (int)udFilterHigh.Value);

                if (!save_filter_changes)
                    rx1_filters[(int)rx1_dsp_mode].SetLow(rx1_filter, (int)udFilterLow.Value);
            }

            if (save_filter_changes && rx1_filter >= Filter.F1 && rx1_filter <= Filter.VAR2)
                rx1_filters[(int)rx1_dsp_mode].SetLow(rx1_filter, (int)udFilterLow.Value);
        }

        private void udFilterHigh_ValueChanged(object sender, System.EventArgs e)
        {
            //MW0LGE_21d filter - work if mouse over as well
            if (udFilterHigh.Focused || udFilterHigh.ClientRectangle.Contains(udFilterHigh.PointToClient(Control.MousePosition)))
            {
                if (udFilterHigh.Value <= udFilterLow.Value + 10)
                {
                    udFilterHigh.Value = udFilterLow.Value + 10;
                    return;
                }

                UpdateRX1Filters((int)udFilterLow.Value, (int)udFilterHigh.Value);

                if (!save_filter_changes)
                    rx1_filters[(int)rx1_dsp_mode].SetHigh(rx1_filter, (int)udFilterHigh.Value);
            }

            if (save_filter_changes && rx1_filter >= Filter.F1 && rx1_filter <= Filter.VAR2)
                rx1_filters[(int)rx1_dsp_mode].SetHigh(rx1_filter, (int)udFilterHigh.Value);
        }

        private void DoFilterShift(int shift, bool redraw)
        {
            // VK6APH: Does the Filter Shift function, alters the filter low and high frequency values 
            // as the Filter Shift slider is moved. We need to keep the last Filter Shift values
            // that the variable filters use since, unlike the other filters, there are 
            // no pre-set bandwidths that they can default to when the Filter Shift is 
            // turned off. These values are stored in the public variables last_var1_shift and
            // last_var2_shift. 
            int IFShift;
            int low;
            int high;
            int bandwidth;
            int max_shift = 9999;		// needed when using variable filters so we can't exceed +/- 10kHz DSP limits

            if (rx1_dsp_mode == DSPMode.SPEC ||
                rx1_dsp_mode == DSPMode.DRM)
                return;

            bandwidth = (int)Math.Abs(udFilterHigh.Value - udFilterLow.Value); // calculate current filter bandwidth 

            // set the maximum IF Shift depending on filter bandwidth in use 
            if (bandwidth > 800)
            {
                ptbFilterShift.Maximum = 1000;  // max IF Shift +/- 1kHz for filters > 800Hz wide
                ptbFilterShift.Minimum = -1000;
            }
            else
            {
                ptbFilterShift.Maximum = 500;	// max IF Shift +/- 500Hz for filters < 800Hz wide
                ptbFilterShift.Minimum = -500;
            }
            // calculate how far the IF Shift slider has moved
            // if we are using variable bandwidth filters need to use their last shift value
            if (rx1_filter == Filter.VAR1)
                IFShift = shift - last_var1_shift;
            else if (rx1_filter == Filter.VAR2)
                IFShift = shift - last_var2_shift;
            else
                IFShift = shift - last_filter_shift;

            high = (int)Math.Min(udFilterHigh.Value + IFShift, max_shift);	// limit high shift to maximum value
            low = (int)Math.Max(udFilterLow.Value + IFShift, -max_shift);	// limit low shift to maximum value

            radio.GetDSPRX(0, 0).SetRXFilter(low, high);			// select new filters
            udFilterLow.Value = low;						// display new low value 
            udFilterHigh.Value = high;						// display new high value

            // store the last IF Shift applied for use next time
            if (rx1_filter == Filter.VAR1)
                last_var1_shift = last_var1_shift + IFShift;
            else if (rx1_filter == Filter.VAR2)
                last_var2_shift = last_var2_shift + IFShift;
            else
                last_filter_shift = last_filter_shift + IFShift;
            // show the IF Shift is active by setting the zero button colour
            if (shift != 0)
                btnFilterShiftReset.BackColor = button_selected_color;
        }
        private void limitFilterToSidebands(ref int nNewLow, ref int nNewHigh, int rx, bool filterShift = false)
        {

            if (!m_bLimitFiltersToSidebands) return;

            DSPMode dspMode;
            if (rx == 1)
            {
                dspMode = rx1_dsp_mode;
            }
            else
            {
                dspMode = rx2_dsp_mode;
            }

            switch (dspMode)
            {
                case DSPMode.LSB:
                case DSPMode.DIGL:
                case DSPMode.CWL:
                    if (nNewHigh > 0)
                    {
                        if (filterShift) nNewLow -= nNewHigh;
                        nNewHigh = 0;
                    }
                    if (nNewLow < -max_filter_shift)
                    {
                        int n = -max_filter_shift - nNewLow;
                        nNewLow += n;
                        if (filterShift) nNewHigh += n;
                    }
                    break;
                case DSPMode.USB:
                case DSPMode.DIGU:
                case DSPMode.CWU:
                    if (nNewLow < 0)
                    {
                        if (filterShift) nNewHigh += nNewLow * -1;
                        nNewLow = 0;
                    }
                    if (nNewHigh > max_filter_shift)
                    {
                        int n = nNewHigh - max_filter_shift;
                        nNewHigh -= n;
                        if (filterShift) nNewLow -= n;
                    }
                    break;
                case DSPMode.AM:
                case DSPMode.SAM:
                case DSPMode.DSB:
                case DSPMode.SPEC: //MW0LGE_21k9
                    if (nNewLow > 0)
                    {
                        if (filterShift) nNewHigh -= nNewLow;
                        nNewLow = 0;
                    }
                    if (nNewHigh < 0)
                    {
                        if (filterShift) nNewLow += nNewHigh * -1;
                        nNewHigh = 0;
                    }
                    break;
                case DSPMode.FM:
                    break;
            }
        }
        private int _oldFilterShiftCentre = -1;
        private void ptbFilterShift_Scroll(object sender, System.EventArgs e)
        {
            MouseEventArgs mouseEvent = e as MouseEventArgs;
            bool bScrollUp = mouseEvent != null ? mouseEvent.Delta >= 0 : false;

            SelectRX1VarFilter();

            int bw = (int)udFilterHigh.Value - (int)udFilterLow.Value;
            int default_center = 0;

            switch (rx1_dsp_mode)
            {
                case DSPMode.USB:
                    default_center = default_low_cut + bw / 2;
                    break;
                case DSPMode.LSB:
                    default_center = -default_low_cut - bw / 2;
                    break;
                case DSPMode.CWU:
                    default_center = cw_pitch;
                    break;
                case DSPMode.CWL:
                    default_center = -cw_pitch;
                    break;
                case DSPMode.DIGU:
                    default_center = digu_click_tune_offset;
                    break;
                case DSPMode.DIGL:
                    default_center = -digl_click_tune_offset;
                    break;
            }

            int adjusted_max = max_filter_shift;
            if (default_center > 0)
            {
                if (ptbFilterShift.Value > 0)
                {
                    adjusted_max = Math.Min(max_filter_shift, 9999 - (Math.Abs(default_center) + bw / 2));
                }
            }
            else if (default_center < 0)
            {
                if (ptbFilterShift.Value < 0)
                {
                    adjusted_max = Math.Min(max_filter_shift, 9999 - (Math.Abs(default_center) + bw / 2));
                }
            }
            else //default_center == 0
            {
                adjusted_max = Math.Min(max_filter_shift, 9999 - bw / 2);
            }

            int range = ptbFilterShift.Maximum - ptbFilterShift.Minimum;
            int new_center = default_center + (int)((float)ptbFilterShift.Value / (range / 2) * adjusted_max);

            if (new_center == _oldFilterShiftCentre) return; // if the new_center hasnt changed, ignore it MW0LGE_[2.9.0.6]
            _oldFilterShiftCentre = new_center;

            // stop filter moving over 0 MW0LGE_21k9
            int nNewLow = new_center - bw / 2;
            int nNewHigh = new_center + bw / 2;
            limitFilterToSidebands(ref nNewLow, ref nNewHigh, 1, true);

            UpdateRX1Filters(nNewLow, nNewHigh);

            btnFilterShiftReset.BackColor = button_selected_color;

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbFilterShift.Focus();
            }
        }

        private void ptbFilterShift_Update(int low, int high)
        {
            int bw = (int)udFilterHigh.Value - (int)udFilterLow.Value;
            int default_center = 0;
            int current_center = (low + high) / 2;

            switch (rx1_dsp_mode)
            {
                case DSPMode.USB:
                    default_center = default_low_cut + bw / 2;
                    break;
                case DSPMode.LSB:
                    default_center = -default_low_cut - bw / 2;
                    break;
                case DSPMode.CWU:
                    default_center = cw_pitch;
                    break;
                case DSPMode.CWL:
                    default_center = -cw_pitch;
                    break;
                case DSPMode.DIGU:
                    default_center = digu_click_tune_offset;
                    break;
                case DSPMode.DIGL:
                    default_center = -digl_click_tune_offset;
                    break;
            }

            int adjusted_max = max_filter_shift;
            if (default_center > 0)
            {
                if (current_center > default_center)
                {
                    adjusted_max = Math.Min(max_filter_shift, 9999 - (Math.Abs(default_center) + bw / 2));
                }
            }
            else if (default_center < 0)
            {
                if (current_center < default_center)
                {
                    adjusted_max = Math.Min(max_filter_shift, 9999 - (Math.Abs(default_center) + bw / 2));
                }
            }
            else //default_center == 0
            {
                adjusted_max = Math.Min(max_filter_shift, 9999 - bw / 2);
            }

            int range = ptbFilterShift.Maximum - ptbFilterShift.Minimum;
            int delta = current_center - default_center;
            int new_val = (int)((float)delta / adjusted_max * (range / 2));
            if (new_val > ptbFilterShift.Maximum) new_val = ptbFilterShift.Maximum;
            if (new_val < ptbFilterShift.Minimum) new_val = ptbFilterShift.Minimum;
            ptbFilterShift.Value = new_val;
        }

        private void btnFilterShiftReset_Click(object sender, System.EventArgs e)
        {
            int bw = (int)udFilterHigh.Value - (int)udFilterLow.Value;
            int low, high;
            switch (rx1_dsp_mode)
            {
                case DSPMode.AM:
                case DSPMode.SAM:
                case DSPMode.FM:
                case DSPMode.DSB:
                    ptbFilterShift.Value = 0;
                    ptbFilterShift_Scroll(this, EventArgs.Empty);
                    break;
                case DSPMode.USB:
                    low = default_low_cut;
                    high = low + bw;
                    UpdateRX1Filters(low, high);
                    break;
                case DSPMode.CWU:
                    low = cw_pitch - bw / 2;
                    high = cw_pitch + bw / 2;
                    if (low < 0)
                    {
                        int delta = -low;
                        low += delta;
                        high += delta;
                    }
                    else if (high > 9999)
                    {
                        int delta = high - 9999;
                        high -= delta;
                        low -= delta;
                    }
                    UpdateRX1Filters(low, high);
                    break;
                case DSPMode.DIGU:
                    low = digu_click_tune_offset - bw / 2;
                    high = digu_click_tune_offset + bw / 2;
                    if (low < 0)
                    {
                        int delta = -low;
                        low += delta;
                        high += delta;
                    }
                    else if (high > 9999)
                    {
                        int delta = high - 9999;
                        high -= delta;
                        low -= delta;
                    }
                    UpdateRX1Filters(low, high);
                    break;
                case DSPMode.LSB:
                    high = -default_low_cut;
                    low = high - bw;
                    UpdateRX1Filters(low, high);
                    break;
                case DSPMode.CWL:
                    high = -cw_pitch + bw / 2;
                    low = -cw_pitch - bw / 2;
                    if (high > 0)
                    {
                        int delta = -high;
                        low -= delta;
                        high -= delta;
                    }
                    else if (low < -9999)
                    {
                        int delta = low + 9999;
                        high += delta;
                        low += delta;
                    }
                    UpdateRX1Filters(low, high);
                    break;
                case DSPMode.DIGL:
                    high = -digl_click_tune_offset + bw / 2;
                    low = -digl_click_tune_offset - bw / 2;
                    if (high > 0)
                    {
                        int delta = -high;
                        low -= delta;
                        high -= delta;
                    }
                    else if (low < -9999)
                    {
                        int delta = low + 9999;
                        high += delta;
                        low += delta;
                    }
                    UpdateRX1Filters(low, high);
                    break;
            }
            btnFilterShiftReset.BackColor = SystemColors.Control;	// make button grey
        }

        private FilterWidthMode current_filter_width_mode = FilterWidthMode.Linear;
        public FilterWidthMode CurrentFilterWidthMode
        {
            get { return current_filter_width_mode; }
            set
            {
                current_filter_width_mode = value;
                UpdateRX1Filters((int)udFilterLow.Value, (int)udFilterHigh.Value);
            }
        }

        private void ptbFilterWidth_Update(int low, int high)
        {
            int bw = high - low;
            switch (rx1_dsp_mode)
            {
                case DSPMode.AM:
                case DSPMode.SAM:
                case DSPMode.FM:
                case DSPMode.DSB:
                    bw /= 2;
                    break;
            }

            int range = ptbFilterWidth.Maximum - ptbFilterWidth.Minimum;
            int new_val = 0;

            switch (current_filter_width_mode)
            {
                case FilterWidthMode.Linear:
                    new_val = ptbFilterWidth.Minimum + (int)((float)bw / max_filter_width * range);
                    break;
                case FilterWidthMode.Log:
                    double max_log = Math.Log(ptbFilterWidth.Maximum);
                    double temp = max_log - (float)bw / max_filter_width * max_log;
                    new_val = ptbFilterWidth.Maximum - (int)Math.Pow(Math.E, temp);
                    break;
                case FilterWidthMode.Log10:
                    max_log = Math.Log10(ptbFilterWidth.Maximum);
                    temp = max_log - (float)bw / max_filter_width * max_log;
                    new_val = ptbFilterWidth.Maximum - (int)Math.Pow(10, temp);
                    break;
            }

            if (new_val > ptbFilterWidth.Maximum) new_val = ptbFilterWidth.Maximum;
            if (new_val < ptbFilterWidth.Minimum) new_val = ptbFilterWidth.Minimum;
            ptbFilterWidth.Value = new_val;
        }

        //-W2PA Remember the width when the Width slider last hit the image limit.  Used by ptbFilterWidth_Scroll.
        private int _var1WidthAtLimit = 0;
        private int Var1WidthAtLimit
        {
            get
            {
                return _var1WidthAtLimit;
            }
            set
            {
                _var1WidthAtLimit = value;
            }
        }

        private bool beyondLimit = false;
        private int _oldFilterBW = -1;
        private void ptbFilterWidth_Scroll(object sender, System.EventArgs e)
        {
            if (rx1_dsp_mode == DSPMode.DRM || rx1_dsp_mode == DSPMode.SPEC)
            {
                return;  // no good in this mode 
            }

            MouseEventArgs mouseEvent = e as MouseEventArgs;
            bool bScrollUp = mouseEvent != null ? mouseEvent.Delta >= 0 : false;

            SelectRX1VarFilter();

            int range = ptbFilterWidth.Maximum - ptbFilterWidth.Minimum;
            int new_bw = 0;
            double tmp = 0;
            switch (current_filter_width_mode)
            {
                case FilterWidthMode.Linear:
                    tmp = (float)(ptbFilterWidth.Value - ptbFilterWidth.Minimum) / range * max_filter_width;
                    break;
                case FilterWidthMode.Log:
                    double max_log = Math.Log(ptbFilterWidth.Maximum);
                    double temp = Math.Log(Math.Max((ptbFilterWidth.Maximum - ptbFilterWidth.Value), 1.0));
                    temp = max_log - temp;
                    tmp = (float)(temp / max_log * max_filter_width);
                    break;
                case FilterWidthMode.Log10:
                    max_log = Math.Log10(ptbFilterWidth.Maximum);
                    temp = Math.Log10(Math.Max((ptbFilterWidth.Maximum - ptbFilterWidth.Value), 1.0));
                    temp = max_log - temp;
                    tmp = (float)(temp / max_log * max_filter_width);
                    break;
            }
            tmp = bScrollUp ? Math.Ceiling(tmp + 0.5f) : Math.Ceiling(tmp - 0.5); // MW0LGE_[2.9.0.6]  fix for mouse wheel
            new_bw = (int)tmp;

            new_bw = Math.Max(new_bw, 10);

            if (new_bw == _oldFilterBW) return; // if the new_center hasnt changed, ignore it MW0LGE_[2.9.0.6]
            _oldFilterBW = new_bw;

            int current_center = ((int)udFilterLow.Value + (int)udFilterHigh.Value) / 2;
            int low = 0, high = 0;
            switch (rx1_dsp_mode)
            {
                case DSPMode.AM:
                case DSPMode.SAM:
                case DSPMode.FM:
                case DSPMode.DSB:
                    low = current_center - new_bw;
                    high = current_center + new_bw;
                    if (rx1_dsp_mode != DSPMode.FM) //[2.10.3.4]MW0LGE bypass for FM
                    {
                        if (low < -max_filter_width)
                        {
                            low += (-max_filter_width - low);
                            high += (-max_filter_width - low);
                        }
                        else if (high > max_filter_width)
                        {
                            high -= (high - max_filter_width);
                            low -= (high - max_filter_width);
                        }
                    }
                    break;
                case DSPMode.LSB:
                    high = -default_low_cut;
                    low = high - new_bw;
                    break;
                case DSPMode.CWL:
                case DSPMode.DIGL:
                    if ((int)udFilterHigh.Value > 0) // If we're already starting out of bounds, suspend trying to stay on the correct side.
                    {
                        low = current_center - new_bw / 2;
                        high = current_center + new_bw / 2;
                        beyondLimit = true;
                    }
                    else
                    {
                        //-W2PA Stop shifting the passband when it hits the image limit, while allowing width to continue to increa                   
                        if (!beyondLimit)
                        {
                            if ((current_center + new_bw / 2) < 0) // new bw doesn't put us beyond limit
                            {
                                low = current_center - new_bw / 2;
                                high = current_center + new_bw / 2;
                            }
                            else  // new bw puts us beyond limit
                            {
                                Var1WidthAtLimit = Math.Abs(-current_center) * 2;
                                beyondLimit = true;
                                high = 0;
                                low = -new_bw;
                            }
                        }
                        else  // currently beyond limit
                        {
                            if (new_bw < Var1WidthAtLimit)  // new bw will go below limit
                            {
                                beyondLimit = false;
                                low = current_center - new_bw / 2;
                                high = current_center + new_bw / 2;
                            }
                            else  // new bw will still be above limit
                            {
                                high = 0;
                                low = -new_bw;
                            }
                        }
                    }

                    if (low < -9999)
                    {
                        low = -9999;
                        high = low + new_bw;
                    }
                    break;
                case DSPMode.USB:
                    low = default_low_cut;
                    high = low + new_bw;
                    break;
                case DSPMode.CWU:
                case DSPMode.DIGU:
                    if ((int)udFilterLow.Value < 0) // If we're already starting out of bounds, suspend trying to stay on the correct side.
                    {
                        low = current_center - new_bw / 2;
                        high = current_center + new_bw / 2;
                        beyondLimit = true;
                    }
                    else
                    {
                        //-W2PA Stop shifting the passband when it hits the image limit, while allowing width to continue to increa                   
                        if (!beyondLimit)
                        {
                            if ((current_center - new_bw / 2) > 0) // new bw doesn't put us beyond limit
                            {
                                low = current_center - new_bw / 2;
                                high = current_center + new_bw / 2;
                            }
                            else  // new bw puts us beyond limit
                            {
                                Var1WidthAtLimit = Math.Abs(current_center) * 2;
                                beyondLimit = true;
                                low = 0;
                                high = new_bw;
                            }
                        }
                        else  // currently beyond limit
                        {
                            if (new_bw < Var1WidthAtLimit)  // new bw will go below limit
                            {
                                beyondLimit = false;
                                low = current_center - new_bw / 2;
                                high = current_center + new_bw / 2;
                            }
                            else  // new bw will still be above limit
                            {
                                low = 0;
                                high = new_bw;
                            }
                        }
                    }

                    if (high > 9999)
                    {
                        high = 9999;
                        low = high - new_bw;
                    }
                    break;
            }
            UpdateRX1Filters(low, high);

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbFilterWidth.Focus();
            }
        }

        private void tbFilterWidthScroll_newMode()
        {
            switch (rx1_dsp_mode)
            {
                case DSPMode.SPEC:
                case DSPMode.DRM:
                    ptbFilterWidth.Enabled = false;
                    break;

                default:
                    ptbFilterWidth.Enabled = true;
                    break;
            }
        }

        #endregion

        #region VFO Button Events
        // ======================================================
        // VFO Button Events
        // ======================================================

        // Added 6/20/05 BT for CAT commands
        public void CATVFOSwap(string pChangec)
        {
            string c = pChangec;
            if (c.Length > 0)
            {
                switch (c)
                {
                    case "0":
                        btnVFOAtoB_Click(btnVFOAtoB, EventArgs.Empty);
                        break;
                    case "1":
                        btnVFOBtoA_Click(btnVFOBtoA, EventArgs.Empty);
                        break;
                    case "2":
                        btnVFOSwap_Click(btnVFOSwap, EventArgs.Empty);
                        break;
                    case "3":
                        btnIFtoVFO_Click(btnIFtoVFO, EventArgs.Empty);
                        break;
                }
            }
        }

        public void CopyVFOAtoB()
        {
            btnVFOAtoB_Click(this, EventArgs.Empty);
        }

        private void btnVFOAtoB_Click(object sender, System.EventArgs e)
        {
            if (rx2_enabled)
            {
                RX2DSPMode = rx1_dsp_mode;
                VFOBFreq = VFOAFreq;
                switch (rx1_filter)
                {
                    case Filter.F8:
                    case Filter.F9:
                    case Filter.F10:
                        RX2Filter = Filter.F1;
                        break;
                    case Filter.VAR1:
                    case Filter.VAR2:
                        RX2Filter = RX1Filter;
                        RX2FilterLow = RX1FilterLow;
                        RX2FilterHigh = RX2FilterHigh;
                        break;
                    default:
                        RX2Filter = rx1_filter;
                        break;
                }
                vfob_dsp_mode = rx1_dsp_mode;
                vfob_filter = rx1_filter;

                comboRX2AGC.Text = comboAGC.Text;
            }
            else
            {
                VFOBFreq = VFOAFreq;
                vfob_dsp_mode = rx1_dsp_mode;
                vfob_filter = rx1_filter;
            }
        }

        public void CopyVFOBtoA()
        {
            btnVFOBtoA_Click(this, EventArgs.Empty);
        }

        private void btnVFOBtoA_Click(object sender, System.EventArgs e)
        {
            if (!rx2_enabled)
            {
                if (!chkEnableMultiRX.Checked)
                {
                    RX1DSPMode = vfob_dsp_mode;
                    RX1Filter = vfob_filter;
                }
                VFOAFreq = VFOBFreq;
            }
            else
            {
                RX1DSPMode = rx2_dsp_mode;

                VFOAFreq = VFOBFreq;
                switch (rx2_filter)
                {
                    case Filter.VAR1:
                    case Filter.VAR2:
                        RX1Filter = RX2Filter;
                        RX1FilterLow = RX2FilterLow;
                        RX1FilterHigh = RX2FilterHigh;
                        break;
                    default:
                        //RX2Filter = rx1_filter;
                        RX1Filter = RX2Filter;
                        break;
                }

                comboAGC.Text = comboRX2AGC.Text;
            }
        }

        public void VFOSwap()
        {
            btnVFOSwap_Click(this, EventArgs.Empty);
        }

        private void btnVFOSwap_Click(object sender, System.EventArgs e)
        {
            if (!rx2_enabled)
            {
                double temp = VFOAFreq;

                if (!chkEnableMultiRX.Checked)
                {
                    DSPMode mode = rx1_dsp_mode;
                    Filter filter = rx1_filter;

                    RX1DSPMode = vfob_dsp_mode;
                    RX1Filter = vfob_filter;
                    vfob_dsp_mode = mode;
                    vfob_filter = filter;
                }

                VFOAFreq = VFOBFreq;
                VFOBFreq = temp;
            }
            else
            {
                double a_freq = VFOAFreq;

                DSPMode a_mode = rx1_dsp_mode;
                Filter a_filter = rx1_filter;
                int a_filter_low = 0, a_filter_high = 0;
                if (a_filter == Filter.VAR1 || a_filter == Filter.VAR2)
                {
                    a_filter_low = RX1FilterLow;
                    a_filter_high = RX1FilterHigh;
                }

                RX1DSPMode = rx2_dsp_mode;
                VFOAFreq = VFOBFreq;
                RX1Filter = rx2_filter;

                RX2DSPMode = a_mode;

                VFOBFreq = a_freq;
                switch (a_filter)
                {
                    case Filter.F8:
                    case Filter.F9:
                    case Filter.F10:
                        RX2Filter = Filter.F1;
                        break;
                    case Filter.VAR1:
                    case Filter.VAR2:
                        RX2Filter = a_filter;
                        RX2FilterLow = a_filter_low;
                        RX2FilterHigh = a_filter_high;
                        break;
                    default:
                        RX2Filter = a_filter;
                        break;
                }

                string agc = comboAGC.Text;
                comboAGC.Text = comboRX2AGC.Text;
                comboRX2AGC.Text = agc;
            }
        }

        private void UpdateVFOASub()
        {
            bool bIgnore = false;
            double dOldVFOASubFreq = VFOASubFreq;

            if (rx2_enabled)
            {
                if (chkVFOSplit.Checked)
                {
                    txtVFOABand.Font = new Font("Microsoft Sans Sarif", 14.0f, FontStyle.Regular);

                    VFOASubFreq = saved_vfoa_sub_freq;

                    tx_xvtr_index = XVTRForm.XVTRFreq(VFOASubFreq);
                    TXBand = BandByFreq(VFOASubFreq, tx_xvtr_index, current_region);
                    if (chkPower.Checked) txtVFOABand.ForeColor = Color.Red;
                    else txtVFOABand.ForeColor = Color.DarkRed;
                    txtVFOABand.TextAlign = HorizontalAlignment.Right;
                    txtVFOABand.ReadOnly = false;
                    txtVFOABand_LostFocus(this, EventArgs.Empty);
                    panelVFOASubHover.Visible = true;

                    bIgnore = true;
                }
                else if (chkEnableMultiRX.Checked)
                {
                    txtVFOABand.Font = new Font("Microsoft Sans Sarif", 14.0f, FontStyle.Regular);

                    VFOASubFreq = saved_vfoa_sub_freq;

                    if (chkPower.Checked) txtVFOABand.ForeColor = vfo_text_light_color;
                    else txtVFOABand.ForeColor = vfo_text_dark_color;
                    txtVFOABand.TextAlign = HorizontalAlignment.Right;
                    txtVFOABand.ReadOnly = false;
                    txtVFOABand_LostFocus(this, EventArgs.Empty);
                    panelVFOASubHover.Visible = true;

                    bIgnore = true;
                }
            }

            if (!bIgnore)
            {
                if (chkPower.Checked)
                {
                    txtVFOABand.Font = new Font("Microsoft Sans Sarif", 12.0f, FontStyle.Regular);
                    txtVFOABand.ForeColor = band_text_light_color;
                    txtVFOABand.TextAlign = HorizontalAlignment.Center;
                    txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                    panelVFOASubHover.Visible = false;
                }
                else
                {
                    txtVFOABand.Font = new Font("Microsoft Sans Sarif", 12.0f, FontStyle.Regular);
                    txtVFOABand.ForeColor = band_text_dark_color;
                    txtVFOABand.TextAlign = HorizontalAlignment.Center;
                    txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                    panelVFOASubHover.Visible = false;
                }
            }

            //MW0LGE [2.9.0.7] also in VFOASubUpdate
            if (dOldVFOASubFreq != VFOASubFreq)
            {
                Band ob = BandByFreq(XVTRForm.TranslateFreq(dOldVFOASubFreq), rx1_xvtr_index, current_region);
                Band nb = BandByFreq(XVTRForm.TranslateFreq(VFOASubFreq), rx1_xvtr_index, current_region);

                VFOASubFrequencyChangeHandlers?.Invoke(ob, nb, RX1DSPMode, RX1Filter, dOldVFOASubFreq, VFOASubFreq,
                    CentreFrequency, ClickTuneDisplay, ptbDisplayZoom.Value, radio.GetDSPRX(0, 1).RXOsc, 1);
            }
        }
        private bool _bOldVFOSplit = false; //MW0LGE_22a
        private void chkVFOSplit_CheckedChanged(object sender, System.EventArgs e)
        {
            Display.SplitEnabled = chkVFOSplit.Checked;
            if (chkVFOSplit.Checked)
            {
                chkVFOSplit.BackColor = button_selected_color;
                //FM front panel
                chkFMTXHigh.Enabled = false;
                chkFMTXHigh.Checked = false;
                chkFMTXLow.Enabled = false;
                chkFMTXLow.Checked = false;
                chkFMTXSimplex.Enabled = false;
                chkFMTXSimplex.Checked = false;
                chkFMTXRev.Enabled = false;
                chkFMTXRev.Checked = false;
                udFMOffset.Enabled = false;
                current_fm_tx_mode = FMTXMode.Simplex;

                lblVFOSplit.BackColor = System.Drawing.Color.Blue;

                //wd5y
                lblVFOSplit.Size = new Size(66, 17);
                //wd5y
            }
            else
            {
                chkVFOSplit.BackColor = SystemColors.Control;
                //FM front panel
                chkFMTXHigh.Enabled = true;
                chkFMTXLow.Enabled = true;
                chkFMTXSimplex.Enabled = true;
                chkFMTXSimplex.Checked = true;
                chkFMTXRev.Enabled = true;
                udFMOffset.Enabled = true;

                lblVFOSplit.BackColor = System.Drawing.Color.Transparent;

                //wd5y
                lblVFOSplit.Size = new Size(66, 17);
                //wd5y
            }

            //[2.10.1.0] MW0LGE apply a quick shift
            SetQuickSplit();
            //

            if (rx2_enabled)
            {
                UpdateVFOASub();
                if (chkVFOSplit.Checked)
                {
                    if (chkVFOBTX.Checked)
                        chkVFOATX.Checked = true;
                }
                else
                {
                    txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                }
            }
            else
            {
                if (chkVFOSplit.Checked)
                {
                    if (chkVFOSync.Checked) chkVFOSync.Checked = false;
                    TXBand = BandByFreq(VFOBFreq, tx_xvtr_index, current_region);
                    grpVFOB.Font = new Font("Microsoft Sans Serif", 8.25F, FontStyle.Bold);
                    grpVFOB.ForeColor = Color.Red;

                    grpVFOA.Font = new Font("Microsoft Sans Serif", 8.25F, FontStyle.Bold);
                    grpVFOA.ForeColor = SystemColors.ControlLightLight;
                    chkVFOBTX.Checked = true;

                    if (chkPower.Checked)
                    {
                        txtVFOBFreq.ForeColor = Color.Red;

                        txtVFOBMSD.ForeColor = vfo_text_light_color;
                        txtVFOBLSD.ForeColor = small_vfo_color;
                        txtVFOBBand.ForeColor = band_text_light_color;

                        txtVFOBFreq_LostFocus(this, EventArgs.Empty);
                    }
                }
                else
                {

                    grpVFOB.Font = new Font("Microsoft Sans Serif", 8.25F, FontStyle.Bold);
                    grpVFOB.ForeColor = SystemColors.ControlLightLight;
                    grpVFOA.Font = new Font("Microsoft Sans Serif", 8.25F, FontStyle.Bold);
                    grpVFOA.ForeColor = Color.Red;
                    chkVFOATX.Checked = true;
                    if (chkPower.Checked)
                    {
                        if (chkEnableMultiRX.Checked)
                        {
                            txtVFOBFreq.ForeColor = vfo_text_light_color;
                            txtVFOBMSD.ForeColor = vfo_text_light_color;
                            txtVFOBLSD.ForeColor = small_vfo_color;
                            txtVFOBBand.ForeColor = band_text_light_color;
                        }
                        else
                        {
                            txtVFOBFreq.ForeColor = vfo_text_dark_color;
                            txtVFOBMSD.ForeColor = vfo_text_dark_color;
                            txtVFOBLSD.ForeColor = vfo_text_dark_color;
                            txtVFOBBand.ForeColor = band_text_dark_color;
                        }

                        if (!full_duplex)
                            txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                    }
                    if (current_click_tune_mode == ClickTuneMode.VFOB && !chkEnableMultiRX.Checked && !chkFullDuplex.Checked)
                        CurrentClickTuneMode = ClickTuneMode.VFOA;
                }
            }

            //[2.10.3.5]MW0LGE TOREMOVE
#if false
			// wjtFIXME! 
			// if we're doing soft rock stuff may need to update osc (tx mainly) when split is on
			if ( current_model ==  Model.SOFTROCK40 )
			
			{
				SetSoftRockOscFreqs();
			}
#endif

            AndromedaIndicatorCheck(EIndicatorActions.eINSplit, false, chkVFOSplit.Checked);

            if (_bOldVFOSplit != chkVFOSplit.Checked) //MW0LGE_22a
            {
                SplitChangedHandlers?.Invoke(1, _bOldVFOSplit, chkVFOSplit.Checked);
                _bOldVFOSplit = chkVFOSplit.Checked;
            }
        }
        private Dictionary<string, object> _oldQuickSplitSettings = null;
        private bool _ignoreQuickSplitSet = false; // used to prevent multiple events calling this when running
        private bool _quickSplitState = false;
        public bool GetQuickSplitEnabled
        {
            get { return _quickSplitState; }
        }
        public void SetQuickSplit()
        {        
            if (_ignoreQuickSplitSet)
            {
                _ignoreQuickSplitSet = false;
                return;
            }

            bool bOldQuickSplitState = _quickSplitState;
            bool bRestore = false;
            if (!IsSetupFormNull && SetupForm.QuickSplitEnabled && !RX2Enabled)
            {
                if (chkVFOSplit.Checked)
                {
                    // store old settings
                    if (_oldQuickSplitSettings == null)
                    {
                        _oldQuickSplitSettings = new Dictionary<string, object>();

                        _oldQuickSplitSettings.Add("zoom", Zoom);
                        _oldQuickSplitSettings.Add("multirx", chkEnableMultiRX.Checked);
                        _oldQuickSplitSettings.Add("txfl", chkShowTXFilter.Checked);
                        _oldQuickSplitSettings.Add("swapwheels", Midi2Cat.SwapVFOWheelsProperty);

                        if (RX2Enabled)
                            _oldQuickSplitSettings.Add("VFOASubFreq", VFOASubFreq);
                        else
                            _oldQuickSplitSettings.Add("VFOBFreq", VFOBFreq);

                        _oldQuickSplitSettings.Add("panmain", PanMainRX);
                        _oldQuickSplitSettings.Add("pansub", PanSubRX);

                        _oldQuickSplitSettings.Add("vfosync", VFOSync);
                    }
                    //

                    double shift = SetupForm.QuickSplitShiftHz * 1e-6;

                    if (VFOSync) VFOSync = false; //[2.10.2.1] fix for issue #208
                    VFOBFreq = VFOAFreq + shift;

                    if (SetupForm.QuickSplitZoom && this.Zoom != 190)
                        this.Zoom = 190;

                    if (SetupForm.QuickSplitMultiRX && !chkEnableMultiRX.Checked)
                        chkEnableMultiRX.Checked = true;

                    if (SetupForm.QuickSplitFL && !chkShowTXFilter.Checked)
                        chkShowTXFilter.Checked = true;

                    if (SetupForm.QuickSplitSwapVFOWheels && !Midi2Cat.SwapVFOWheelsProperty)
                        Midi2Cat.SwapVFOWheelsProperty = true;

                    if (SetupForm.QuickSplitPanAudio)
                    {
                        // note this can be flipped if Swap turned on on main UI, resulting in double flip
                        if (!SetupForm.QuickSplitPanAudioFlip)
                        {
                            // main in left, sub in right
                            PanMainRX = 0;
                            PanSubRX = 100;
                        }
                        else
                        {
                            // main in right, sub in left
                            PanMainRX = 100;
                            PanSubRX = 0;
                        }
                    }
                }
                else
                {
                    bRestore = true;
                }
                _quickSplitState = true;
                chkVFOSplit.Text = "QPLT";
            }
            else
            {
                _quickSplitState = false;
                bRestore = true;
                chkVFOSplit.Text = "SPLT";
            }

            if (bRestore)
            {
                //do we have old settings?
                if (_oldQuickSplitSettings != null)
                {
                    if (_oldQuickSplitSettings.ContainsKey("zoom")) Zoom = (int)_oldQuickSplitSettings["zoom"];
                    if (_oldQuickSplitSettings.ContainsKey("multirx")) chkEnableMultiRX.Checked = (bool)_oldQuickSplitSettings["multirx"];
                    if (_oldQuickSplitSettings.ContainsKey("txfl")) chkShowTXFilter.Checked = (bool)_oldQuickSplitSettings["txfl"];
                    if (_oldQuickSplitSettings.ContainsKey("swapwheels")) Midi2Cat.SwapVFOWheelsProperty = (bool)_oldQuickSplitSettings["swapwheels"];
                    if (_oldQuickSplitSettings.ContainsKey("VFOASubFreq")) VFOASubFreq = (double)_oldQuickSplitSettings["VFOASubFreq"];
                    if (_oldQuickSplitSettings.ContainsKey("VFOBFreq")) VFOBFreq = (double)_oldQuickSplitSettings["VFOBFreq"];
                    if (_oldQuickSplitSettings.ContainsKey("panmain")) PanMainRX = (int)_oldQuickSplitSettings["panmain"];
                    if (_oldQuickSplitSettings.ContainsKey("pansub")) PanSubRX = (int)_oldQuickSplitSettings["pansub"];
                    if (_oldQuickSplitSettings.ContainsKey("vfosync")) VFOSync = (bool)_oldQuickSplitSettings["vfosync"];
                    _oldQuickSplitSettings.Clear();
                    _oldQuickSplitSettings = null;
                }
            }

            if(bOldQuickSplitState != _quickSplitState)
            {
                QuickSplitChangedHandlers?.Invoke(bOldQuickSplitState, _quickSplitState);
            }
        }

        private void chkXIT_CheckedChanged(object sender, System.EventArgs e)
        {
            if (chkXIT.Checked)
            {
                chkXIT.BackColor = button_selected_color;
                chkXIT.ForeColor = Color.Red;
                lblXITLabel.BackColor = System.Drawing.Color.Blue;
                Display.XIT = (int)udXIT.Value;
            }
            else
            {
                chkXIT.BackColor = SystemColors.Control;
                chkXIT.ForeColor = SystemColors.ControlLightLight;
                lblXITLabel.BackColor = System.Drawing.Color.Transparent;
                Display.XIT = 0;
            }
            AndromedaIndicatorCheck(EIndicatorActions.eINXIT, false, chkXIT.Checked);

            //[2.10.3.5]MW0LGE TOREMOVE
#if false
			// wjtFIXME!
			if ( current_model == Model.SOFTROCK40 )			
			{
				SetSoftRockOscFreqs();
			}
#endif

            updateVFOFreqs(_mox); //[2.10.1.0] MW0LGE we might need to update everything if tx'ing on sub, use std function
        }

        private void chkRIT_CheckedChanged(object sender, System.EventArgs e)
        {
            if (chkRIT.Checked)
            {
                chkRIT.BackColor = button_selected_color;
                chkRIT.ForeColor = Color.Red;
                lblRITLabel.BackColor = System.Drawing.Color.Blue;

                Display.RIT = (int)udRIT.Value;
            }
            else
            {
                chkRIT.BackColor = SystemColors.Control;
                chkRIT.ForeColor = SystemColors.ControlLightLight;
                lblRITLabel.BackColor = System.Drawing.Color.Transparent;
                Display.RIT = 0;
            }

            //[2.10.1.0] MW0LGE need this so that osc offset gets assigned if needed
            if (!_mox || (_mox && (VFOBTX && RX2Enabled))) txtVFOAFreq_LostFocus(this, EventArgs.Empty);
            if (!_mox || (_mox && VFOATX)) txtVFOBFreq_LostFocus(this, EventArgs.Empty);

            AndromedaIndicatorCheck(EIndicatorActions.eINRIT, false, chkRIT.Checked);

        }

        private void udRIT_ValueChanged(object sender, System.EventArgs e)
        {
            //[2.10.1.0] MW0LGE need this so that osc offset gets assigned if needed
            if (!_mox || (_mox && (VFOBTX && RX2Enabled))) txtVFOAFreq_LostFocus(this, EventArgs.Empty);
            if (!_mox || (_mox && VFOATX)) txtVFOBFreq_LostFocus(this, EventArgs.Empty);

            lblRITValue.Text = udRIT.Value.ToString();
            if (chkRIT.Checked) Display.RIT = (int)udRIT.Value;

            setRIT_LEDs();  //-W2PA Behringer LEDs

            //-W2PA Sync XIT/XIT if selected
            if (RITXITSync)
            {
                udXIT.Value = udRIT.Value;
                setXIT_LEDs();
            }
        }

        private void udXIT_ValueChanged(object sender, System.EventArgs e)
        {
            if (chkXIT.Checked)
            {
                updateVFOFreqs(_mox); //[2.10.1.0] MW0LGE we might need to update everything if tx'ing on sub, use std function
            }
            lblXITValue.Text = udXIT.Value.ToString();

            //[2.10.3.5]MW0LGE TOREMOVE
#if false
			//wjtFIXME
			else if ( current_model == Model.SOFTROCK40 )			
			{
				SetSoftRockOscFreqs();
			}
#endif


            if (chkXIT.Checked) Display.XIT = (int)udXIT.Value;

            setXIT_LEDs(); //-W2PA Behringer LEDs

            //-W2PA Sync XIT/XIT if selected
            if (RITXITSync)
            {
                udRIT.Value = udXIT.Value;
                setRIT_LEDs();
            }
        }

        private void btnXITReset_Click(object sender, System.EventArgs e)
        {
            udXIT.Value = 0;
        }

        private void btnRITReset_Click(object sender, System.EventArgs e)
        {
            udRIT.Value = 0;
        }

        private void setRIT_LEDs()
        {
            //-W2PA Update LEDs on Behringer MIDI controller, within limits of +/- 2kHz.  Beyond that range the extreme L or R LED remains lit.
            int IT_MIDIminimum = -2000; //-W2PA Change these two values to enable a broader range for the LEDs
            int IT_MIDImaximum = 2000;  //      But when you do so, it makes them change more gradually, i.e. it takes more turns
            double fracBetweenLEDs = 1.0 / 14.0;
            double negTol = 0.5 - fracBetweenLEDs;
            double posTol = 0.5 + fracBetweenLEDs;
            double fract = Convert.ToDouble(udRIT.Value - IT_MIDIminimum) / Convert.ToDouble(IT_MIDImaximum - IT_MIDIminimum);

            //-W2PA Light the center LED (#8) only if exactly at zero RIT/XIT
            if (udRIT.Value < 0 && (fract >= negTol)) fract = negTol;
            else if (udRIT.Value > 0 && (fract <= posTol)) fract = posTol;

            //-W2PA Prevent the lowest LED from going out completely.
            if (udRIT.Value <= IT_MIDIminimum + Convert.ToDecimal(fracBetweenLEDs * IT_MIDImaximum)) fract = fracBetweenLEDs;
            Midi2Cat.SendUpdateToMidi(CatCmd.RIT_inc, fract);
        }

        private void setXIT_LEDs()
        {
            //-W2PA Update LEDs on Behringer MIDI controller, within limits of +/- 2kHz
            int IT_MIDIminimum = -2000; //-W2PA Change these two values to enable a broader range for the LEDs
            int IT_MIDImaximum = 2000;  //      But when you do so, it makes them change more gradually, i.e. it takes more turns
            double fracBetweenLEDs = 1.0 / 14.0;
            double negTol = 0.5 - fracBetweenLEDs;
            double posTol = 0.5 + fracBetweenLEDs;
            double fract = Convert.ToDouble(udXIT.Value - IT_MIDIminimum) / Convert.ToDouble(IT_MIDImaximum - IT_MIDIminimum);

            //-W2PA Light the center LED (#8) only if exactly at zero RIT/XIT
            if (udXIT.Value < 0 && (fract >= negTol)) fract = negTol;
            else if (udXIT.Value > 0 && (fract <= posTol)) fract = posTol;

            //-W2PA Prevent the lowest LED from going out completely.
            if (udXIT.Value <= IT_MIDIminimum + Convert.ToDecimal(fracBetweenLEDs * IT_MIDImaximum)) fract = fracBetweenLEDs;
            Midi2Cat.SendUpdateToMidi(CatCmd.XIT_inc, fract);
        }

        private void btnZeroBeat_Click(object sender, System.EventArgs e)
        {
            if (!PowerOn) return;

            int peak_hz = FindPeakFreqInPassband();
            if (peak_hz == -1)
            {
                return; // find peak croaked - bail
            }
            // Debug.WriteLine("peak: " + peak_hz);
            int delta_hz = 0;

            // if we're in CW mode, zero beat to CWPitch, provided it is in the passband
            switch (rx1_dsp_mode)
            {
                case DSPMode.CWL:
                case DSPMode.CWU:
                case DSPMode.USB:
                case DSPMode.LSB:
                    int local_pitch = CWPitch;
                    if (rx1_dsp_mode == DSPMode.CWL || rx1_dsp_mode == DSPMode.LSB)
                    {
                        local_pitch = -local_pitch;
                    }
                    // is cwoffset in passband?
                    if (local_pitch >= udFilterLow.Value &&
                        local_pitch <= udFilterHigh.Value)
                    {
                        delta_hz = peak_hz - local_pitch;
                        // Debug.WriteLine("delta(cw): " + delta_hz);
                    }
                    else
                    {
                        // if we get here and delta_hz is still 0, the current
                        // CW pitch is not within the passband.
                        // Put strongest peak @ center of passband
                        int center_hz = ((int)udFilterHigh.Value + (int)udFilterLow.Value) / 2;
                        delta_hz = peak_hz - center_hz;
                    }
                    break;
                case DSPMode.DIGL:
                    local_pitch = -digl_click_tune_offset;
                    if (local_pitch >= udFilterLow.Value &&
                        local_pitch <= udFilterHigh.Value)
                    {
                        delta_hz = peak_hz - local_pitch;
                    }
                    else
                    {
                        // if we get here and delta_hz is still 0, the current
                        // pitch is not within the passband.
                        // Put strongest peak @ center of passband
                        int center_hz = ((int)udFilterHigh.Value + (int)udFilterLow.Value) / 2;
                        delta_hz = peak_hz - center_hz;
                    }
                    break;
                case DSPMode.DIGU:
                    local_pitch = digu_click_tune_offset;
                    if (local_pitch >= udFilterLow.Value &&
                        local_pitch <= udFilterHigh.Value)
                    {
                        delta_hz = peak_hz - local_pitch;
                    }
                    else
                    {
                        // if we get here and delta_hz is still 0, the current
                        // pitch is not within the passband.
                        // Put strongest peak @ center of passband
                        int center_hz = ((int)udFilterHigh.Value + (int)udFilterLow.Value) / 2;
                        delta_hz = peak_hz - center_hz;
                    }
                    break;
                case DSPMode.AM:
                case DSPMode.SAM:
                case DSPMode.FM:
                    delta_hz = peak_hz;
                    break;
            }

            if (zero_beat_rit)
            {
                udRIT.Value += delta_hz;
                chkRIT.Checked = true;
            }
            else
            {
                VFOAFreq += delta_hz * 0.0000010;
            }
        }
        private object _findPeakLock = new Object();
        unsafe private int FindPeakFreqInPassband()
        {            
            lock (_findPeakLock)
            {
                // convert hz to buckets in the averaging data
                int lo_cut_hz = (int)udFilterLow.Value;
                int hi_cut_hz = (int)udFilterHigh.Value;

                double hz_per_bucket = sample_rate_rx1 / (double)specRX.GetSpecRX(0).FFTSize;

                int zero_hz_bucket = specRX.GetSpecRX(0).FFTSize / 2;

                if (click_tune_display) //MW0LGE_21d
                {
                    // need to calc zero hz bucket point for freq as it wont be in the middle of FFT as above
                    double dBucketOffset = ((VFOAFreq - CentreFrequency) * 1e6) / hz_per_bucket;
                    zero_hz_bucket += (int)dBucketOffset;
                }

                int lo_bucket = (int)(lo_cut_hz / hz_per_bucket) + zero_hz_bucket;
                int hi_bucket = (int)(hi_cut_hz / hz_per_bucket) + zero_hz_bucket;

                //MW0LGE_21d belts and braces
                if (lo_bucket < 0 || hi_bucket > specRX.GetSpecRX(0).FFTSize - 1)
                {
                    return -1;
                }

                //~~~~ 
                double max_val = double.MinValue;
                double min_val = double.MaxValue;
                int max_bucket = 0;
                int ss = 0;

                double[,] spectrum_data;

                spectrum_data = new double[specRX.GetSpecRX(0).FFTSize, 2];
                if (spectrum_data == null)
                {
                    _spectrum_mutex.ReleaseMutex();
                    return -1; // bail out - not buffer 
                }

                int flag = 0;
                _spectrum_mutex.WaitOne();
                fixed (double* ptr = &(spectrum_data[0, 0]))
                    //[2.10.2.3]MW0LGE timeout version used, with 10 times frame rate to give some additional time
                    SpecHPSDRDLL.SnapSpectrumTimeout(0, ss, 0, ptr, (uint)((1000 / (float)_display_fps) * 10), ref flag);
                _spectrum_mutex.ReleaseMutex();
                if (flag == 0) return -1;

                double mag_sqr;

                int fft_size = specRX.GetSpecRX(0).FFTSize;
                double[] dbm = new double[hi_bucket - lo_bucket + 1];

                for (int i = lo_bucket; i <= hi_bucket; i++)
                {
                    mag_sqr = spectrum_data[i, 0] * spectrum_data[i, 0] + spectrum_data[i, 1] * spectrum_data[i, 1];
                    if (mag_sqr > max_val)
                    {
                        max_bucket = i;
                        max_val = mag_sqr;
                    }
                    if(mag_sqr < min_val)
                    {
                        min_val = mag_sqr;
                    }

                    dbm[i - lo_bucket] = 10.0f * Math.Log10(mag_sqr / Math.Pow(fft_size, 2));
                }

                int peak_hz = (int)((max_bucket - zero_hz_bucket) * hz_per_bucket);
                return peak_hz;
            }            
        }

        private void btnIFtoVFO_Click(object sender, System.EventArgs e)
        {
            int current_if_shift;

            bool is_centered_mode = false;
            bool is_cw_mode = false;
            bool is_lower_sb_mode = false;

            current_if_shift = ptbFilterShift.Value;

            if (current_if_shift == 0) return; // nothing to do

            switch (RX1DSPMode)
            {
                case DSPMode.DRM:
                case DSPMode.SPEC:
                case DSPMode.DIGL:
                case DSPMode.DIGU:
                    return; // nothing to do for these modes

                case DSPMode.AM:
                case DSPMode.FM:
                case DSPMode.DSB:
                case DSPMode.SAM:
                    is_centered_mode = true;
                    break;

                case DSPMode.CWL:
                    is_cw_mode = true;
                    is_lower_sb_mode = true;
                    break;
                case DSPMode.CWU:
                    is_cw_mode = true;
                    break;
                case DSPMode.LSB:
                    is_lower_sb_mode = true;
                    break;
                case DSPMode.USB:
                    break;
                default:
                    // no clue what the mode is -- bail out
                    return;
            }

            int current_width = (int)udFilterHigh.Value - (int)udFilterLow.Value;
            int current_center = (int)udFilterLow.Value + (current_width / 2);

            double new_vfo = 0;
            int new_lo = 0;
            int new_hi = 0;

            if (is_centered_mode)
            {
                new_vfo = VFOAFreq + ((double)current_center) / (1000000);
                new_lo = -(current_width / 2);
                new_hi = current_width / 2;
            }
            else  // sideband style mode
            {
                int new_center;
                if (is_cw_mode)
                {
                    new_center = cw_pitch;
                }
                else  // sideband mode
                {
                    new_center = default_low_cut + (current_width / 2);
                }
                if (is_lower_sb_mode)
                {
                    new_center = -new_center;
                }
                new_vfo = VFOAFreq + ((double)(current_center - new_center)) / (1000000);
                // now figure out filter limits
                new_lo = new_center - (current_width / 2);
                new_hi = new_center + (current_width / 2);
            }

            if (VFOAFreq > new_vfo)  // need to change this in the right order!
            {
                udFilterHigh.Value = new_hi;
                udFilterLow.Value = new_lo;
            }
            else
            {
                udFilterLow.Value = new_lo;
                udFilterHigh.Value = new_hi;
            }

            VFOAFreq = new_vfo;
            switch (RX1Filter)
            {
                case Filter.VAR1:
                    last_var1_shift = 0;
                    break;
                case Filter.VAR2:
                    last_var2_shift = 0;
                    break;
                default:
                    last_filter_shift = 0;
                    break;
            }
            btnFilterShiftReset_Click(this, EventArgs.Empty);
        }

        #endregion

        #region DSP Button Events

        private void chkANF_CheckedChanged(object sender, System.EventArgs e)
        {
            if (chkANF.Checked)
            {
                chkANF.BackColor = button_selected_color;
                lblANFLabel.Text = "ANF";
            }

            else
            {
                chkANF.BackColor = SystemColors.Control;
                lblANFLabel.Text = "---";
            }
            radio.GetDSPRX(0, 0).AutoNotchFilter = chkANF.Checked;
            radio.GetDSPRX(0, 1).AutoNotchFilter = chkANF.Checked;
            cat_anf_status = Convert.ToInt32(chkANF.Checked);
            ANFToolStripMenuItem.Checked = chkANF.Checked;
            AndromedaIndicatorCheck(EIndicatorActions.eINANF, true, chkANF.Checked);
        }

        private void chkDSPNB2_CheckedChanged(object sender, EventArgs e)
        {
            if (chkDSPNB2.Checked)
            {
                chkDSPNB2.BackColor = button_selected_color;
                lblSNBLabel.Text = "SNB";
            }
            else
            {
                chkDSPNB2.BackColor = SystemColors.Control;
                lblSNBLabel.Text = "---";
            }

            WDSP.SetRXASNBARun(WDSP.id(0, 0), chkDSPNB2.Checked);
            WDSP.SetRXASNBARun(WDSP.id(0, 1), chkDSPNB2.Checked);
            cat_snb_status = Convert.ToInt32(chkDSPNB2.Checked);
            SNBtoolStripMenuItem.Checked = chkDSPNB2.Checked;
            SNBtoolStripMenuItem1.Checked = chkRX2NB2.Checked;
            AndromedaIndicatorCheck(EIndicatorActions.eINSNB, true, chkDSPNB2.Checked);
        }

        private void chkRX2NB2_CheckedChanged(object sender, EventArgs e)
        {
            if (chkRX2NB2.Checked)
            {
                chkRX2NB2.BackColor = button_selected_color;
                lblRX2SNBLabel.Text = "SNB";
            }

            else
            {
                chkRX2NB2.BackColor = SystemColors.Control;
                lblRX2SNBLabel.Text = "---";
            }
            WDSP.SetRXASNBARun(WDSP.id(2, 0), chkRX2NB2.Checked);
            cat_rx2snb_status = Convert.ToInt32(chkRX2NB2.Checked);
            AndromedaIndicatorCheck(EIndicatorActions.eINSNB, false, chkRX2NB2.Checked);
        }

        #endregion

        #region Mode Specific Events

        private bool txosctrl = false;
        public bool TxOsctrl
        {
            get { return txosctrl; }
            set { txosctrl = value; }
        }

        private bool _oldCompandState = false; // initial state to match frm design
        private void chkCPDR_CheckedChanged(object sender, System.EventArgs e)
        {
            if (chkCPDR.Checked)
            {
                chkCPDR.BackColor = button_selected_color;
                ptbCPDR_Scroll(this, EventArgs.Empty);
            }
            else
            {
                chkCPDR.BackColor = SystemColors.Control;
            }
            if (chkCPDR.Checked)
            {
                radio.GetDSPTX(0).TXCompandOn = true;
                if (txosctrl)
                    radio.GetDSPTX(0).TXOsctrlOn = true;
                else
                    radio.GetDSPTX(0).TXOsctrlOn = false;
            }
            else
            {
                radio.GetDSPTX(0).TXCompandOn = false;
                radio.GetDSPTX(0).TXOsctrlOn = false;
            }
            cat_cmpd_status = Convert.ToInt32(chkCPDR.Checked);
            AndromedaIndicatorCheck(EIndicatorActions.eINCompanderEnabled, false, chkCPDR.Checked);

            if(_oldCompandState != chkCPDR.Checked)
            {
                CompandChangedHandlers?.Invoke(_oldCompandState, chkCPDR.Checked);
                _oldCompandState = chkCPDR.Checked;
            }
        }

        private void ptbCPDR_Scroll(object sender, System.EventArgs e)
        {
            lblCPDRVal.Text = ptbCPDR.Value.ToString() + " dB";

            if (chkCPDR.Checked)
                radio.GetDSPTX(0).TXCompandLevel = (double)ptbCPDR.Value;

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbCPDR.Focus();
            }
        }

        private void chkDX_CheckedChanged(object sender, System.EventArgs e)
        {

        }

        #endregion

        #region Memory Events
        // ======================================================
        // Memory Events
        // ======================================================

        private void btnMemoryQuickSave_Click(object sender, System.EventArgs e)
        {
            txtMemoryQuick.Text = txtVFOAFreq.Text;
            quick_save_mode = RX1DSPMode;
            quick_save_filter = RX1Filter;
        }

        private void btnMemoryQuickRestore_Click(object sender, System.EventArgs e)
        {
            //SaveBand(); // MW0LGE_21d BandStack2
            //MW0LGE_21d BandStack2 last_band = "";
            RX1DSPMode = quick_save_mode;
            //MW0LGE txtVFOAFreq.Text = txtMemoryQuick.Text;
            //MW0LGE txtVFOAFreq_LostFocus(this, EventArgs.Empty);
            VFOAFreq = freqFromString(txtMemoryQuick.Text);

            RX1Filter = quick_save_filter;
        }

        #endregion

        #region Sub RX Events

        private void ptbPanMainRX_Scroll(object sender, System.EventArgs e)
        {
            float val = (int)ptbPanMainRX.Value / 100.0f;

            if (chkPanSwap.Checked) val = 1.0f - val;
            radio.GetDSPRX(0, 0).Pan = val;

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbPanMainRX.Focus();
            }
            if (sliderForm != null)
            {
                sliderForm.RX1LRPan = ptbPanMainRX.Value;

                //wd5y
                sliderForm.lblMainPan.Text = PanMainRX.ToString();
                //wd5y
            }
        }

        private void ptbPanSubRX_Scroll(object sender, System.EventArgs e)
        {
            float val = (int)ptbPanSubRX.Value / 100.0f;
            if (chkPanSwap.Checked) val = 1.0f - val;
            radio.GetDSPRX(0, 1).Pan = val;

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbPanSubRX.Focus();
            }
            if (sliderForm != null)
            {
                sliderForm.SubRXLRPan = ptbPanSubRX.Value;

                //wd5y
                sliderForm.lblSubPan.Text = PanSubRX.ToString();
                //wd5y
            }

        }
        private bool _oldMultiRX = false;
        unsafe private void chkEnableMultiRX_CheckedChanged(object sender, System.EventArgs e)
        {
            //[2.10.3.5]MW0LGE
            if (!initializing) radio.GetDSPRX(0, 1).Active = chkEnableMultiRX.Checked; //MW0LGE only set after init complete
                                                                                       //for some reason fixes issue where multirx has no audio if
                                                                                       //thetis loaded with multirx already on
            if (chkEnableMultiRX.Checked)
            {
                cmaster.SetAAudioMixWhat((void*)0, 0, 1, true);
                if (!_mox) WDSP.SetChannelState(WDSP.id(0, 1), 1, 0);

                chkEnableMultiRX.BackColor = button_selected_color;
                if (chkPower.Checked)
                {
                    if (rx2_enabled)
                    {
                        UpdateVFOASub();
                    }
                    else
                    {
                        txtVFOBFreq_LostFocus(this, EventArgs.Empty);
                        if (chkVFOSplit.Checked)
                        {
                            _ignoreQuickSplitSet = true;
                            chkVFOSplit_CheckedChanged(this, EventArgs.Empty);
                        }
                        else
                        {
                            txtVFOBFreq.ForeColor = vfo_text_light_color;
                            txtVFOBMSD.ForeColor = vfo_text_light_color;
                            txtVFOBLSD.ForeColor = small_vfo_color;
                            txtVFOBBand.ForeColor = band_text_light_color;
                        }
                    }
                }
                radio.GetDSPRX(0, 1).SetRXFilter(
                    radio.GetDSPRX(0, 0).RXFilterLow,
                    radio.GetDSPRX(0, 0).RXFilterHigh);
            }
            else
            {
                WDSP.SetChannelState(WDSP.id(0, 1), 0, 0);
                cmaster.SetAAudioMixWhat((void*)0, 0, 1, false);

                chkEnableMultiRX.BackColor = SystemColors.Control;

                if (rx2_enabled)   // <-- rx2_enabled, so how can it be also in the else, bunch commented out MW0LGE [2.9.0.7]
                {
                    UpdateVFOASub();
                }
                else
                {
                    if (chkVFOSplit.Checked)// && !rx2_enabled)
                    {
                        _ignoreQuickSplitSet = true;
                        chkVFOSplit_CheckedChanged(this, EventArgs.Empty);
                    }
                    //else if (rx2_enabled)
                    //{
                    //    update_rx2_display = false;
                    //    chkRX2_CheckedChanged(this, EventArgs.Empty);
                    //}
                    else
                    {
                        txtVFOBFreq.ForeColor = vfo_text_dark_color;
                        txtVFOBMSD.ForeColor = vfo_text_dark_color;
                        txtVFOBLSD.ForeColor = vfo_text_dark_color;
                        txtVFOBBand.ForeColor = band_text_dark_color;
                    }
                }

                if (current_click_tune_mode == ClickTuneMode.VFOB && !chkFullDuplex.Checked && !chkVFOSplit.Checked)
                    CurrentClickTuneMode = ClickTuneMode.VFOA;

            }
            Display.SubRX1Enabled = chkEnableMultiRX.Checked;
            MultiRXToolStripMenuItem.Checked = chkEnableMultiRX.Checked;

            // MW0LGE
            setSmallRX2ModeFilterLabels();

            if (chkEnableMultiRX.Checked != _oldMultiRX)
            {
                Band nb = BandByFreq(XVTRForm.TranslateFreq(VFOASubFreq), rx1_xvtr_index, current_region);

                MultiRxHandlers?.Invoke(chkEnableMultiRX.Checked, _oldMultiRX, VFOASubFreq, nb, RX2Enabled);
                _oldMultiRX = chkEnableMultiRX.Checked;
            }

            //wd5y
            if (chkEnableMultiRX.Checked == true)
            {
                sliderForm.chkSubRX.Checked = true;
            }
            else
            {
                sliderForm.chkSubRX.Checked = false;
            }
            //wd5y
        }

        private void chkPanSwap_CheckedChanged(object sender, System.EventArgs e)
        {
            ptbPanMainRX_Scroll(this, EventArgs.Empty);
            ptbPanSubRX_Scroll(this, EventArgs.Empty);
        }

        private void ptbRX0Gain_Scroll(object sender, System.EventArgs e)
        {
            lblRX1Vol.Text = "Vol";

            //MWLGE_21k9 re-worked //[2.10.1.0] MW0LGE added eventargs empty
            if (!initializing && e != EventArgs.Empty && m_bRXAFSlidersWillUnmute && chkMUT.Checked) chkMUT.Checked = false;

            if (chkMUT.Checked && m_bMuteWillMuteVAC1) //MW0LGE_21k9
            {
                radio.GetDSPRX(0, 0).RXOutputGain = 0.0;
            }
            else
            {
                radio.GetDSPRX(0, 0).RXOutputGain = (double)ptbRX0Gain.Value / ptbRX0Gain.Maximum;                
            }
            ptbRX1AF.Value = ptbRX0Gain.Value;

            //wd5y            
            lblRX1AF.Text = "RX1 AF:  " + ptbRX0Gain.Value.ToString();

            lblAF2.Size = new Size(34, 23);
            lblAF2.Text = "AF:  " + ptbRX0Gain.Value.ToString();
            //wd5y

            setLinkedAF(1, ptbRX1AF.Value); //[2.10.1.0] MW0LGE

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbRX0Gain.Focus();
            }

            //MW0LGE_21k9 moved here (now same as ptbRX2Gain_Scroll)
            //-W2PA Update LEDs on Behringer MIDI controller
            double pct = Convert.ToDouble(ptbRX1AF.Value - ptbRX1AF.Minimum) / Convert.ToDouble(ptbRX1AF.Maximum - ptbRX1AF.Minimum);
            Midi2Cat.SendUpdateToMidi(CatCmd.VolumeVfoA_inc, pct);
            if (sliderForm != null)
            {
                sliderForm.RX1Gain = ptbRX0Gain.Value;

                //wd5y
                sliderForm.lblAFrx1.Text = ptbRX0Gain.Value.ToString();
                //wd5y
            }
        }

        private void ptbRX1Gain_Scroll(object sender, System.EventArgs e)
        {
            //
            //[2.10.1.0] MW0LGE consider mute when on vac
            if (!initializing && e != EventArgs.Empty && m_bRXAFSlidersWillUnmute && chkMUT.Checked) chkMUT.Checked = false;

            if (chkMUT.Checked && m_bMuteWillMuteVAC1)
            {
                radio.GetDSPRX(0, 1).RXOutputGain = 0.0;
            }
            else
            {
                radio.GetDSPRX(0, 1).RXOutputGain = (double)ptbRX1Gain.Value / ptbRX1Gain.Maximum;
            }
            //

            setLinkedAF(2, ptbRX1Gain.Value); //[2.10.1.0] MW0LGE

            ptbRX1Gain.Focus();
            if (sliderForm != null)
            {
                sliderForm.SubRXGain = ptbRX1Gain.Value;

                //wd5y
                sliderForm.lblSubRXAF.Text = ptbRX1Gain.Value.ToString();
                //wd5y
            }

        }

        #endregion

        private bool full_duplex = false;
        public bool FullDuplex
        {
            get { return full_duplex; }
            set
            {
                full_duplex = value;
                chkFullDuplex.Checked = value;
            }
        }

        private void chkFullDuplex_CheckedChanged(object sender, System.EventArgs e)
        {
            FullDuplex = chkFullDuplex.Checked;
            Audio.FullDuplex = chkFullDuplex.Checked;
            if (chkFullDuplex.Checked)
            {
                chkFullDuplex.BackColor = Color.Red;
                txtVFOBFreq_LostFocus(this, EventArgs.Empty);
                WDSP.SetChannelState(WDSP.id(0, 0), 1, 0);
            }
            else
            {
                chkFullDuplex.BackColor = SystemColors.Control;
                txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                if (chkMOX.Checked)
                {
                    WDSP.SetChannelState(WDSP.id(0, 0), 0, 0);
                }

                if (current_click_tune_mode == ClickTuneMode.VFOB && !chkVFOSplit.Checked && !chkEnableMultiRX.Checked)
                    CurrentClickTuneMode = ClickTuneMode.VFOA;
            }
        }

        private static Console _theConsole = null;

        public static Console getConsole()
        {
            return _theConsole;
        }

        protected override void WndProc(ref Message m)
        {
            const int WM_QUERYENDSESSION = 0x0011;
            // Listen for operating system messages. 

            if (m.Msg == WM_QUERYENDSESSION)
            {
                chkPower.Checked = false;
                this.Close();
            }
            else base.WndProc(ref m);
        }

        private void chkFWCATUBypass_Click(object sender, System.EventArgs e)
        {
        }

        private void chkSplitDisplay_CheckedChanged(object sender, System.EventArgs e)
        {
            if (chkSplitDisplay.Checked)
                chkSplitDisplay.BackColor = button_selected_color;
            else
                chkSplitDisplay.BackColor = SystemColors.Control;

            Display.SplitDisplay = chkSplitDisplay.Checked;
        }


        private void ckQuickPlay_CheckedChanged(object sender, System.EventArgs e)
        {
            if (ckQuickPlay.Checked)
            {
                WaveForm.QuickPlay = true;
                ckQuickPlay.BackColor = button_selected_color;
            }
            else
            {
                WaveForm.QuickPlay = false;
                ckQuickPlay.BackColor = SystemColors.Control;
            }
            ckQuickRec.Enabled = !ckQuickPlay.Checked;
        }

        private void ckQuickRec_CheckedChanged(object sender, System.EventArgs e)
        {
            if (ckQuickRec.Checked)
            {
                WaveForm.QuickRec = true;
                ckQuickPlay.Enabled = true;
                ckQuickRec.BackColor = button_selected_color;
            }
            else
            {
                WaveForm.QuickRec = false;
                ckQuickRec.BackColor = SystemColors.Control;
            }
            ckQuickPlay.Enabled = !ckQuickRec.Checked;
        }
        private void moveModeSpecificPanels()
        {
            panelModeSpecificPhone.Location = new Point(gr_ModePhone_basis_location.X + h_delta - (h_delta / 4), gr_ModePhone_basis_location.Y + v_delta);
            panelModeSpecificCW.Location = new Point(gr_ModeCW_basis_location.X + h_delta - (h_delta / 4), gr_ModeCW_basis_location.Y + v_delta);
            panelModeSpecificDigital.Location = new Point(gr_ModeDig_basis_location.X + h_delta - (h_delta / 4), gr_ModeDig_basis_location.Y + v_delta);
            panelModeSpecificFM.Location = new Point(gr_ModeFM_basis_location.X + h_delta - (h_delta / 4), gr_ModeFM_basis_location.Y + v_delta);
        }
        private void ResizeConsole(int h_delta, int v_delta)
        {
            // MW0LGE changes made to this function so that RX1 meter fills space to right of VFOB box, also delay repaint until all controls moved
            SuspendDrawing(this); //MW0LGE

            // This routine captures the size and location parameters *after* windows
            // has resized the image, (if the video is set for "120 dpi" in lieu of the
            // normal 96 dpi).  These will be used as the "basis" for all new size calcs.

            if ((h_delta == 0) && (v_delta == 0) && (previous_delta == 0))
            {
                // do nothing - this only occurs for my first call to Resize with both deltas zero during init
                // and at that time windows hasn't resized the display if in 120 dpi mode.
                // Use the "previous_delta" variable to ensure that if we *reduce* size back
                // to original, we do the calcs for that, too (previous_delta won't be 0 in that case);
            }
            else
            {
                panelFilter.Location = new Point(gr_filter_basis_location.X + h_delta, gr_filter_basis_location.Y + v_delta);

                panelBandHF.Location = new Point(gr_BandHF_basis_location.X + h_delta, gr_BandHF_basis_location.Y + (v_delta / 4));
                panelBandGEN.Location = new Point(gr_BandGEN_basis_location.X + h_delta, gr_BandGEN_basis_location.Y + (v_delta / 4));
                panelBandVHF.Location = new Point(gr_BandVHF_basis_location.X + h_delta, gr_BandVHF_basis_location.Y + (v_delta / 4));

                panelMode.Location = new Point(gr_Mode_basis_location.X + h_delta, gr_Mode_basis_location.Y + (v_delta / 2));

                panelVFO.Location = new Point(gr_VFO_basis_location.X + (h_delta / 4), gr_VFO_basis_location.Y + v_delta);

                grpVFOBetween.Location = new Point(gr_vfobetween_basis_location.X + (h_delta / 2), gr_vfobetween_basis_location.Y);

                if (!this.collapsedDisplay)
                {
                    moveModeSpecificPanels();// [2.10.3.4]MW0LGE  SelectModeDependentPanel will deal with this when collapsed

                    grpVFOB.Location = new Point(gr_VFOB_basis_location.X + h_delta - (h_delta / 4), gr_VFOB_basis_location.Y);
                    grpVFOA.Location = new Point(gr_VFOA_basis_location.X + (h_delta / 4), gr_VFOA_basis_location.Y);

                    setupHiddenButton();//grpVFOA);

                    //MW0LGE -- uses pad radio between meter and vfoB
                    grpMultimeterMenus.Location = new Point(gr_multi_meter_menus_basis.X + h_delta, gr_multi_meter_menus_basis.Y);

                    int tmp = (grpVFOB.Location.X + grpVFOB.Size.Width + 8) + (int)(m_fMeterPadRatio * (grpMultimeterMenus.Left - (grpVFOB.Right + 8)));


                    grpMultimeter.Location = new Point(tmp, gr_Multimeter_basis_location.Y);
                    grpMultimeter.Size = new Size(grpMultimeterMenus.Right - grpMultimeter.Left, gr_multi_meter_size_basis.Height);

                    txtMultiText.Size = new Size(grpMultimeter.Size.Width - (gr_multi_meter_size_basis.Width - txt_multi_text_size_basis.Width), txt_multi_text_size_basis.Height);
                    picMultiMeterDigital.Size = new Size(grpMultimeter.Size.Width - (gr_multi_meter_size_basis.Width - pic_multi_meter_size_basis.Width), pic_multi_meter_size_basis.Height);
                    //

                    //panelDisplay.Size = new Size(gr_display_size_basis.Width + h_delta, gr_display_size_basis.Height + v_delta);
                    int w = gr_display_size_basis.Width + h_delta;
                    int h = gr_display_size_basis.Height + v_delta;
                    if (LegacyItemController.ExpandSpectrumToRight)
                        w = this.ClientSize.Width - gr_display_basis.X - 8;
                    if (LegacyItemController.ExpandSpectrumToTop)
                        h = gr_display_size_basis.Height + v_delta + (gr_display_basis.Y - menuStrip1.Height);
                    panelDisplay.Size = new Size(w, h);

                    panelDisplay2.Location = new Point(gr_display2_basis.X + (h_delta / 2), gr_display2_basis.Y + v_delta);
                    panelDSP.Location = new Point(gr_dsp_basis.X + (h_delta / 2), gr_dsp_basis.Y + v_delta);

                    panelPower.Location = new Point(gr_power_basis.X, gr_power_basis.Y + (v_delta / 8));
                    panelRX2Power.Location = new Point(gr_rx2_enable_basis.X, gr_rx2_enable_basis.Y + v_delta);
                    panelOptions.Location = new Point(gr_options_basis.X, gr_options_basis.Y + (v_delta / 4));
                }

                panelMultiRX.Location = new Point(gr_multirx_basis.X + (h_delta / 2), gr_multirx_basis.Y + v_delta);
                panelSoundControls.Location = new Point(gr_sound_controls_basis.X, gr_sound_controls_basis.Y + (v_delta / 8) + (v_delta / 4));
                chkSquelch.Location = new Point(chk_squelch_basis.X, chk_squelch_basis.Y + (v_delta / 2));
                picSquelch.Location = new Point(pic_sql_basis.X, pic_sql_basis.Y + (v_delta / 2));
                ptbSquelch.Location = new Point(tb_sql_basis.X, tb_sql_basis.Y + (v_delta / 2));
                grpDisplaySplit.Location = new Point(gr_display_split_basis.X + (h_delta / 2), gr_display_split_basis.Y + v_delta);
                grpRX2Meter.Location = new Point(gr_rx2_meter_basis.X + h_delta, gr_rx2_meter_basis.Y + v_delta);
                panelRX2Filter.Location = new Point(gr_rx2_filter_basis.X + (int)(h_delta * 0.66), gr_rx2_filter_basis.Y + v_delta);
                panelRX2Mode.Location = new Point(gr_RX2Mode_basis_location.X + (int)(h_delta * 0.492), gr_RX2Mode_basis_location.Y + v_delta); // MW0LGE changed to gr_RX2Mode_basis_location
                panelRX2Display.Location = new Point(gr_rx2_display_basis.X + (int)(h_delta * 0.383), gr_rx2_display_basis.Y + v_delta);
                panelRX2DSP.Location = new Point(gr_rx2_dsp_basis.X + (int)(h_delta * 0.258), gr_rx2_dsp_basis.Y + v_delta);
                panelRX2RF.Location = new Point(gr_rx2_rf_basis.X + (int)(h_delta * 0.164), gr_rx2_rf_basis.Y + v_delta);

                chkRX2Squelch.Location = new Point(chk_rx2_squelch_basis.X + (int)(h_delta * 0.164), chk_rx2_squelch_basis.Y + v_delta);
                ptbRX2Squelch.Location = new Point(tb_rx2_squelch_basis.X + (int)(h_delta * 0.164), tb_rx2_squelch_basis.Y + v_delta);
                picRX2Squelch.Location = new Point(pic_rx2_squelch_basis.X + (int)(h_delta * 0.164), pic_rx2_squelch_basis.Y + v_delta);

                panelRX2Mixer.Location = new Point(gr_rx2_mixer_basis.X + (int)(h_delta * 0.078), gr_rx2_mixer_basis.Y + v_delta);

                MeterManager.SetPositionOfDockedMeters();
            }

            previous_delta = h_delta + v_delta; //we'll check this next time through...

            if (collapsedDisplay)
            {
                RepositionControlsForCollapsedlDisplay();
            }
            else
            {
                // set all Andromedia console controls to hidden
                panelButtonBar.Hide();
                panelMeterLabels.Hide();
                panelVFOALabels.Hide();
                lblModeBigLabel.Hide();
                panelVFOBLabels.Hide();
                lblRX2ModeBigLabel.Hide();
                panelVFOLabels.Hide();
                panelAndromedaMisc.Hide();

                //wd5y
                menuStrip1.Location = new Point(chkMNU.Location.X + chkMNU.Width - 10, chkMNU.Location.Y + 22 - menuStrip1.Height);
                //wd5y
            }

            setPAProfileLabelPos();  //[2.10.1.0] MW0LGE

            ResumeDrawing(this); //MW0LGE
        }

        public int HDelta
        {
            get { return h_delta; }
            set
            {
                h_delta = value;
                ResizeConsole(h_delta, v_delta);
            }
        }

        public int VDelta
        {
            get { return v_delta; }
            set
            {
                v_delta = value;
                ResizeConsole(h_delta, v_delta);
            }
        }

        public void GrabConsoleSizeBasis()
        {
            console_basis_size = this.Size;
            picdisplay_basis_size = picDisplay.Size;
            gr_filter_basis_location = this.panelFilter.Location;

            gr_Multimeter_basis_location = this.grpMultimeter.Location;
            gr_BandHF_basis_location = this.panelBandHF.Location;
            gr_BandGEN_basis_location = this.panelBandGEN.Location;
            gr_BandVHF_basis_location = this.panelBandVHF.Location;
            gr_Mode_basis_location = this.panelMode.Location;
            gr_RX2Mode_basis_location = this.panelRX2Mode.Location;
            gr_VFOB_basis_location = this.grpVFOB.Location;
            gr_VFOA_basis_location = this.grpVFOA.Location;
            gr_ModePhone_basis_location = this.panelModeSpecificPhone.Location;
            gr_ModeCW_basis_location = this.panelModeSpecificCW.Location;
            gr_ModeDig_basis_location = this.panelModeSpecificDigital.Location;
            gr_ModeFM_basis_location = this.panelModeSpecificFM.Location;
            gr_VFO_basis_location = this.panelVFO.Location;
            gr_vfobetween_basis_location = this.grpVFOBetween.Location;

            // MW0LGE_21k9rc6 new resize implementation
            tb_display_zoom_basis = this.ptbDisplayZoom.Location;
            lbl_display_zoom_basis = this.lblDisplayZoom.Location;
            tb_display_zoom_size_basis = this.ptbDisplayZoom.Size;
            lbl_display_zoom_size_basis = this.lblDisplayZoom.Size;
            tb_displaypan_basis = this.ptbDisplayPan.Location;
            lbl_displaypan_basis = this.lblDisplayPan.Location;
            tb_displaypan_size_basis = this.ptbDisplayPan.Size;
            lbl_displaypan_size_basis = this.lblDisplayPan.Size;

            btn_display_pan_center_basis = this.btnDisplayPanCenter.Location;
            tb_display_pan_size_basis = this.ptbDisplayPan.Size;
            //

            gr_display_size_basis = this.panelDisplay.Size;
            gr_display2_basis = this.panelDisplay2.Location;
            gr_dsp_basis = this.panelDSP.Location;
            gr_multirx_basis = this.panelMultiRX.Location;

            chk_power_basis = this.chkPower.Location;
            gr_power_basis = this.panelPower.Location;
            gr_rx2_enable_basis = this.panelRX2Power.Location;
            gr_options_basis = this.panelOptions.Location;
            gr_sound_controls_basis = this.panelSoundControls.Location;
            chk_squelch_basis = this.chkSquelch.Location;
            pic_sql_basis = this.picSquelch.Location;
            tb_sql_basis = this.ptbSquelch.Location;

            gr_display_split_basis = this.grpDisplaySplit.Location;
            gr_rx2_meter_basis = this.grpRX2Meter.Location;
            gr_rx2_filter_basis = this.panelRX2Filter.Location;

            gr_rx2_display_basis = this.panelRX2Display.Location;
            gr_rx2_dsp_basis = this.panelRX2DSP.Location;

            gr_rx2_rf_basis = this.panelRX2RF.Location;
            lbl_rx2_rf_basis = this.lblRX2RF.Location;
            tb_rx2_rf_basis = this.ptbRX2RF.Location;
            chk_rx2_squelch_basis = this.chkRX2Squelch.Location;
            tb_rx2_squelch_basis = this.ptbRX2Squelch.Location;
            pic_rx2_squelch_basis = this.picRX2Squelch.Location;

            gr_rx2_mixer_basis = this.panelRX2Mixer.Location;
            chk_rx2_enable_basis = this.chkRX2.Location;

            combo_rx2_preamp_basis = this.comboRX2Preamp.Location;
            lbl_rx2_band_basis = this.lblRX2Band.Location;
            combo_rx2_band_basis = this.comboRX2Band.Location;

            //MW0LGE
            txt_multi_text_size_basis = this.txtMultiText.Size;
            gr_multi_meter_menus_basis = this.grpMultimeterMenus.Location;
            gr_multi_meter_menus_size_basis = this.grpMultimeterMenus.Size;

            // :W1CEG:
            gr_multi_meter_size_basis = this.grpMultimeter.Size;
            pic_multi_meter_digital_basis = this.picMultiMeterDigital.Location;
            pic_multi_meter_size_basis = this.picMultiMeterDigital.Size;

            pic_rx2meter_basis = this.picRX2Meter.Location;
            pic_rx2meter_size_basis = this.picRX2Meter.Size;

            txt_multi_text_basis = this.txtMultiText.Location;
            txt_rx2meter_basis = this.txtRX2Meter.Location;
            txt_rx2meter_size_basis = this.txtRX2Meter.Size;
            gr_options_size_basis = this.panelOptions.Size;
            chk_mon_basis = this.chkMON.Location;
            chk_mut_basis = this.chkMUT.Location;
            chk_rx2_mut_basis = chkRX2Mute.Location; //MW0LGE
            chk_mox_basis = this.chkMOX.Location;
            chk_tun_basis = this.chkTUN.Location;
            chk_vox_basis = this.chkVOX.Location;
            chk_ps2_basis = this.chkFWCATUBypass.Location;
            chk_dup_basis = this.chkRX2SR.Location;
            chk_ctun_basis = this.chkFWCATU.Location;
            chk_x2tr_basis = this.chkX2TR.Location;

            tb_af_basis = this.ptbAF.Location;
            tb_rf_basis = this.ptbRF.Location;
            tb_pwr_basis = this.ptbPWR.Location;

            tb_rx1af_basis = this.ptbRX1AF.Location;
            tb_rx2af_basis = this.ptbRX2AF.Location;
            gr_display_basis = this.panelDisplay.Location;

            combo_display_mode_basis = this.comboDisplayMode.Location;
            combo_rx2_display_mode_basis = this.comboRX2DisplayMode.Location;
            combo_agc_basis = this.comboAGC.Location;
            combo_rx2agc_basis = this.comboRX2AGC.Location;
            combo_preamp_basis = this.comboPreamp.Location;
            combo_meter_rxmode_basis = this.comboMeterRXMode.Location;
            combo_rx2meter_mode_basis = this.comboRX2MeterMode.Location;
            combo_meter_txmode_basis = this.comboMeterTXMode.Location;
            tb_display_zoom_size_basis = this.ptbDisplayZoom.Size;
            ud_rx1_step_att_present_data_basis = this.udRX1StepAttData.Location;
            ud_rx2_step_att_present_data_basis = this.udRX2StepAttData.Location;
            gr_BandHF_basis_size = panelBandHF.Size;
            gr_BandGEN_basis_size = panelBandGEN.Size;
            gr_BandVHF_basis_size = panelBandVHF.Size;
            gr_Mode_basis_size = panelMode.Size;
            gr_RX2Mode_basis_size = panelRX2Mode.Size;
            rad_band160_basis = radBand160.Location;
            rad_band80_basis = radBand80.Location;
            rad_band60_basis = radBand60.Location;
            rad_band40_basis = radBand40.Location;
            rad_band30_basis = radBand30.Location;
            rad_band20_basis = radBand20.Location;
            rad_band17_basis = radBand17.Location;
            rad_band15_basis = radBand15.Location;
            rad_band12_basis = radBand12.Location;
            rad_band10_basis = radBand10.Location;
            rad_band6_basis = radBand6.Location;
            rad_band2_basis = radBand2.Location;
            rad_bandwwv_basis = radBandWWV.Location;
            rad_bandgen_basis = radBandGEN.Location;
            rad_bandVHF0_basis = radBandVHF0.Location;
            rad_bandVHF1_basis = radBandVHF1.Location;
            rad_bandVHF2_basis = radBandVHF2.Location;
            rad_bandVHF3_basis = radBandVHF3.Location;
            rad_bandVHF4_basis = radBandVHF4.Location;
            rad_bandVHF5_basis = radBandVHF5.Location;
            rad_bandVHF6_basis = radBandVHF6.Location;
            rad_bandVHF7_basis = radBandVHF7.Location;
            rad_bandVHF8_basis = radBandVHF8.Location;
            rad_bandVHF9_basis = radBandVHF9.Location;
            rad_bandVHF10_basis = radBandVHF10.Location;
            rad_bandVHF11_basis = radBandVHF11.Location;
            rad_bandVHF12_basis = radBandVHF12.Location;
            rad_bandVHF13_basis = radBandVHF13.Location;
            btn_bandHF_basis = btnBandHF.Location; //w3sz
            btn_bandVHF_basis = btnBandVHF.Location; //w3sz
            rad_bandGEN0_basis = radBandGEN0.Location;
            rad_bandGEN1_basis = radBandGEN1.Location;
            rad_bandGEN2_basis = radBandGEN2.Location;
            rad_bandGEN3_basis = radBandGEN3.Location;
            rad_bandGEN4_basis = radBandGEN4.Location;
            rad_bandGEN5_basis = radBandGEN5.Location;
            rad_bandGEN6_basis = radBandGEN6.Location;
            rad_bandGEN7_basis = radBandGEN7.Location;
            rad_bandGEN8_basis = radBandGEN8.Location;
            rad_bandGEN9_basis = radBandGEN9.Location;
            rad_bandGEN10_basis = radBandGEN10.Location;
            rad_bandGEN11_basis = radBandGEN11.Location;
            rad_bandGEN12_basis = radBandGEN12.Location;
            rad_bandGEN13_basis = radBandGEN13.Location;
            btn_bandHF1_basis = btnBandHF1.Location;
            rad_mode_lsb_basis = radModeLSB.Location;
            rad_mode_usb_basis = radModeUSB.Location;
            rad_mode_dsb_basis = radModeDSB.Location;
            rad_mode_cwl_basis = radModeCWL.Location;
            rad_mode_cwu_basis = radModeCWU.Location;
            rad_mode_fmn_basis = radModeFMN.Location;
            rad_mode_am_basis = radModeAM.Location;
            rad_mode_sam_basis = radModeSAM.Location;
            rad_mode_spec_basis = radModeSPEC.Location;
            rad_mode_digl_basis = radModeDIGL.Location;
            rad_mode_digu_basis = radModeDIGU.Location;
            rad_mode_drm_basis = radModeDRM.Location;
            rad_RX2mode_lsb_basis = radModeLSB.Location;
            rad_RX2mode_usb_basis = radModeUSB.Location;
            rad_RX2mode_dsb_basis = radModeDSB.Location;
            rad_RX2mode_cwl_basis = radModeCWL.Location;
            rad_RX2mode_cwu_basis = radModeCWU.Location;
            rad_RX2mode_fmn_basis = radModeFMN.Location;
            rad_RX2mode_am_basis = radModeAM.Location;
            rad_RX2mode_sam_basis = radModeSAM.Location;
            rad_RX2mode_spec_basis = radModeSPEC.Location;
            rad_RX2mode_digl_basis = radModeDIGL.Location;
            rad_RX2mode_digu_basis = radModeDIGU.Location;
            rad_RX2mode_drm_basis = radModeDRM.Location;
            // G8NJJ - to allow RIT and XIT to show in collapsed view
            chk_RIT_basis = chkRIT.Location;
            chk_XIT_basis = chkXIT.Location;
            ud_RIT_basis = udRIT.Location;
            ud_XIT_basis = udXIT.Location;
            btn_RITReset_basis = btnRITReset.Location;
            btn_XITReset_basis = btnXITReset.Location;
            lbl_RX1_Mute_VFOA_basis = lblRX1MuteVFOA.Location;
            lbl_RX2_Mute_VFOB_basis = lblRX2MuteVFOB.Location;
            lbl_RX1_APF_VFOA_basis = lblRX1APF.Location;
            lbl_RX2_APF_VFOB_basis = lblRX2APF.Location;
        }

        private string old_rx1_display_mode = "";
        private bool set_rx2_freq = false;
        private bool rx1_enabled = true; // always true for now MW0LGE_21a
        private bool rx2_enabled = false;

        //MW0LGE_21a added for completness at this stage
        public bool RX1Enabled {
            get {
                return rx1_enabled;
            }
        }
        public bool RX2Enabled
        {
            get { return rx2_enabled; }
            set
            {
                rx2_enabled = value;
                if (DataFlowing)
                {
                    if (rx2_enabled)
                    {
                        UpdateDDCs(rx2_enabled);
                    }
                    UpdateAAudioMixerStates();          // What is the 'DataFlowing' thing all about????
                    if (!rx2_enabled) UpdateDDCs(rx2_enabled);
                }
                cmaster.CMSetFRXNBRun(1);
                cmaster.CMSetFRXNB2Run(1);
                cmaster.SetRunPanadapter(1, true);
                cmaster.CMSetSRXWavePlayRun(1);
                cmaster.CMSetSRXWaveRecordRun(1);
                chkRX2.Checked = value;
                
                if (rx2_enabled)
                {
                    old_rx1_display_mode = comboDisplayMode.Text;

                    UpdateDDCs(rx2_enabled);

                    if (RX2StepAttPresent) udRX2StepAttData_ValueChanged(this, EventArgs.Empty);
                    else comboRX2Preamp_SelectedIndexChanged(this, EventArgs.Empty);

                    if (chkPower.Checked)
                    {
                        if (rx2_meter_thread == null || !rx2_meter_thread.IsAlive)
                        {
                            rx2_meter_thread = new Thread(new ThreadStart(UpdateRX2MeterData))
                            {
                                Name = "RX2 Meter Thread",
                                Priority = ThreadPriority.Lowest,
                                IsBackground = true
                            };
                            rx2_meter_thread.Start();
                        }

                        //multimeter2 MW0LGE_[2.9.0.7]
                        if (multimeter2_thread_rx2 == null || !multimeter2_thread_rx2.IsAlive)
                        {
                            multimeter2_thread_rx2 = new Thread(new ThreadStart(MultiMeter2UpdateRX2))
                            {
                                Name = "Multimeter2 RX2 Thread",
                                Priority = ThreadPriority.Lowest,
                                IsBackground = true
                            };
                            multimeter2_thread_rx2.Start();
                        }
                        //

                        if (rx2_sql_update_thread == null || !rx2_sql_update_thread.IsAlive)
                        {
                            rx2_sql_update_thread = new Thread(new ThreadStart(UpdateRX2SQL))
                            {
                                Name = "Update RX2 SQL",
                                Priority = ThreadPriority.Normal,
                                IsBackground = true
                            };
                            rx2_sql_update_thread.Start();
                        }

                        set_rx2_freq = true;
                        txtVFOBFreq_LostFocus(this, EventArgs.Empty);
                        if (!rx2_enabled) return;

                        txtVFOBFreq.ForeColor = vfo_text_light_color;
                        txtVFOBMSD.ForeColor = vfo_text_light_color;
                        txtVFOBLSD.ForeColor = small_vfo_color;
                        txtVFOBBand.ForeColor = band_text_light_color;

                        if (chkVFOSplit.Checked) chkVFOSplit_CheckedChanged(this, EventArgs.Empty);
                        if (chkEnableMultiRX.Checked) chkEnableMultiRX_CheckedChanged(this, EventArgs.Empty);
                    }

                    radio.GetDSPRX(1, 0).Active = true;

                    WDSP.SetChannelState(WDSP.id(2, 0), 1, 0);

                    if (chkEnableMultiRX.Checked)
                        txtVFOABand_LostFocus(this, EventArgs.Empty);

                    if (comboDisplayMode.SelectedIndex < 0)
                        comboDisplayMode.Text = "Panadapter";

                    if (comboDisplayMode.Items.Contains("Panascope"))
                        comboDisplayMode.Items.Remove("Panascope");
                    if (comboDisplayMode.SelectedIndex < 0)
                        comboDisplayMode.Text = "Panadapter";

                    if (comboDisplayMode.Items.Contains("Spectrascope"))
                        comboDisplayMode.Items.Remove("Spectrascope");
                    if (comboDisplayMode.SelectedIndex < 0)
                        comboDisplayMode.Text = "Pandapter";
                }
                else
                {
                    if (chkPower.Checked)
                    {
                        if (chkVFOSplit.Checked) chkVFOSplit_CheckedChanged(this, EventArgs.Empty);
                        else if (chkEnableMultiRX.Checked) chkEnableMultiRX_CheckedChanged(this, EventArgs.Empty);
                        else
                        {
                            txtVFOBFreq.ForeColor = vfo_text_dark_color;
                            txtVFOBMSD.ForeColor = vfo_text_dark_color;
                            txtVFOBLSD.ForeColor = vfo_text_dark_color;
                            txtVFOBBand.ForeColor = band_text_dark_color;
                            panelVFOASubHover.Visible = false;
                        }
                        if (chkVFOBTX.Checked && !chkVFOSplit.Checked)
                            chkVFOATX.Checked = true;
                        UpdateVFOASub();
                    }

                    radio.GetDSPRX(1, 0).Active = false;

                    WDSP.SetChannelState(WDSP.id(2, 0), 0, 0);

                    if (chkEnableMultiRX.Checked)
                        txtVFOBFreq_LostFocus(this, EventArgs.Empty);

                    if (!comboDisplayMode.Items.Contains("Panafall"))
                        comboDisplayMode.Items.Insert(comboDisplayMode.Items.Count - 1, "Panafall");
                    if (!comboDisplayMode.Items.Contains("Panascope"))
                        comboDisplayMode.Items.Insert(comboDisplayMode.Items.Count - 1, "Panascope");

                    comboDisplayMode.Text = old_rx1_display_mode;
                }

                Audio.RX2Enabled = rx2_enabled;
                Display.RX2Enabled = rx2_enabled;
                chkSplitDisplay.Checked = rx2_enabled;
            }
        }

        private bool update_rx2_display = false;
        private void chkRX2_CheckedChanged(object sender, System.EventArgs e)
        {
            _pause_DisplayThread = true; //MW0LGE_21k8 hide the changes

            bool oldRX2Enabled = RX2Enabled;

            if (oldRX2Enabled != chkRX2.Checked) RX2EnabledPreChangedHandlers?.Invoke(chkRX2.Checked);

            RX2Enabled = chkRX2.Checked;

            if (chkVFOBTX.Checked && chkVAC2.Checked && chkRX2.Checked)
            {
                ptbVACRXGain.Value = vac2_rx_gain;
                ptbVACRXGain_Scroll(this, EventArgs.Empty);

                ptbVACTXGain.Value = vac2_tx_gain;
                ptbVACTXGain_Scroll(this, EventArgs.Empty);

                comboVACSampleRate.Text = vac2_sample_rate;

                chkVACStereo.Checked = vac2_stereo;
            }
            else
            {
                ptbVACRXGain.Value = vac_rx_gain;
                ptbVACRXGain_Scroll(this, EventArgs.Empty);

                ptbVACTXGain.Value = vac_tx_gain;
                ptbVACTXGain_Scroll(this, EventArgs.Empty);

                comboVACSampleRate.Text = vac_sample_rate;

                chkVACStereo.Checked = vac_stereo;
            }

            if (chkRX2.Checked)
            {
                chkRX2.BackColor = button_selected_color;
                chkRX2DisplayAVG_CheckedChanged(this, EventArgs.Empty);
                click_tune_rx2_display = chkX2TR.Checked;
            }
            else
            {
                chkRX2.BackColor = SystemColors.Control;
                if (chkVAC2.Checked) chkVAC2.Checked = false;
                click_tune_rx2_display = false;
            }

            if (update_rx2_display)
            {
                if (chkRX2.Checked)
                {
                    if (this.Height <= MinimumSize.Height + panelRX2Filter.Height + 8)
                        this.Height += (panelRX2Filter.Height + 8);

                    console_basis_size.Height += (panelRX2Filter.Height + 8);
                }
                else
                {
                    if (this.Height <= MinimumSize.Height + panelRX2Filter.Height + 8)
                        this.Height -= (panelRX2Filter.Height + 8);

                    console_basis_size.Height -= (panelRX2Filter.Height + 8);
                }

                Console_Resize(this, EventArgs.Empty);
            }
            update_rx2_display = true;

            //MW0LGE_21d linear gradient rebuild
            Display.RebuildLinearGradientBrushRX1 = true;
            if (RX2Enabled)
            {
                Display.RebuildLinearGradientBrushRX2 = true;
                Display.FastAttackNoiseFloorRX2 = true; // MW0LGE_21k
            }

            // MW0LGE
            setSmallRX2ModeFilterLabels();

            setupZTBButton();

            // need to update anything on the info bar buttons that is relying on rx2
            SetupInfoBarButton(ucInfoBar.ActionTypes.ActivePeaks, Display.SpectralPeakHoldRX1 || (RX2Enabled && Display.SpectralPeakHoldRX2));

            if(!m_bResizeDX2Display && (oldRX2Enabled != RX2Enabled)) m_bResizeDX2Display = true; // MW0LGE_22b force resize is rx2 enabled state is changed, this may also be set by reisze calls above

            _pause_DisplayThread = false; //MW0LGE_21k8

            if (oldRX2Enabled != RX2Enabled)
            {
                SetQuickSplit(); //[2.10.1.0] MW0LGE
                RX2EnabledChangedHandlers?.Invoke(RX2Enabled);
            }
        }

        private void setSmallRX2ModeFilterLabels()
        {

            if ((chkEnableMultiRX.Checked && !rx2_enabled) || !rx2_enabled)
            {
                if (rx1_dsp_mode == DSPMode.FIRST || rx1_dsp_mode == DSPMode.LAST || rx1_filter == Filter.FIRST || rx1_filter == Filter.LAST) return;

                string sMode = rx1_dsp_mode.ToString().ToUpper();
                string sFilter = rx1_filters[(int)rx1_dsp_mode].GetName(rx1_filter);

                lblRX2ModeLabel.Text = sMode;
                lblRX2ModeBigLabel.Text = sMode;
                lblRX2FilterLabel.Text = sFilter;
            }
            else
            {
                if (rx2_dsp_mode == DSPMode.FIRST || rx2_dsp_mode == DSPMode.LAST || rx2_filter == Filter.FIRST || rx2_filter == Filter.LAST) return;

                string sMode = rx2_dsp_mode.ToString().ToUpper();
                string sFilter = rx2_filters[(int)rx2_dsp_mode].GetName(rx2_filter);

                lblRX2ModeLabel.Text = sMode;
                lblRX2ModeBigLabel.Text = sMode;
                lblRX2FilterLabel.Text = sFilter;
            }
        }

        private void chkRX2SR_CheckedChanged(object sender, System.EventArgs e)
        {
            //chkRX2SR is the DUPlex button

            if (chkRX2SR.Checked) chkRX2SR.BackColor = button_selected_color;
            else chkRX2SR.BackColor = SystemColors.Control;

            DisplayDuplex = chkRX2SR.Checked;
            Display.DisplayDuplex = chkRX2SR.Checked;

            if (path_Illustrator != null)
                path_Illustrator.pi_Changed();

            updateVFOFreqs(_mox); //[2.10.1.0] MW0LGE replaced above
        }

        private void panelVFOASubHover_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            if (!rx2_enabled || (!chkEnableMultiRX.Checked && !chkVFOSplit.Checked)) return;
            if (vfoa_sub_hover_digit < 0) return;

            int x = 0;
            int width = 0;

            x += (vfo_sub_char_width + vfo_sub_char_space) * vfoa_sub_hover_digit;
            if (vfoa_sub_hover_digit > 3)
                x += (vfo_sub_decimal_space - vfo_sub_char_space);
            width = x + vfo_sub_char_width;

            e.Graphics.DrawLine(new Pen(txtVFOABand.ForeColor, 2.0f), x, 1, width, 1);
        }

        private void panelVFOASubHover_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (!rx2_enabled || (!chkEnableMultiRX.Checked && !chkVFOSplit.Checked)) return;
            Control c1 = (Control)sender;
            Control c2 = txtVFOABand;
            int client_width = (c1.Size.Width - c1.ClientSize.Width) + (c2.Size.Width - c2.ClientSize.Width);
            int client_height = (c1.Size.Height - c1.ClientSize.Height) + (c2.Size.Height - c2.ClientSize.Height);
            int x_offset = c1.Left - c2.Left - client_width / 2;
            int y_offset = c1.Top - c2.Top - client_height / 2;
            txtVFOABand_MouseMove(sender, new MouseEventArgs(e.Button, e.Clicks, e.X + x_offset, e.Y + y_offset, e.Delta));
        }

        private void txtVFOABand_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (!rx2_enabled || (!chkEnableMultiRX.Checked && !chkVFOSplit.Checked) || !chkPower.Checked) return;
            panelVFOASubHover.Visible = true;
            if (this.ContainsFocus)
            {
                int old_digit = vfoa_sub_hover_digit;
                int digit_index = 0;
                if (vfo_sub_char_width == 0)
                    GetVFOSubCharWidth();

                int x = txtVFOABand.Width - (vfo_sub_pixel_offset - 5);
                while (x < e.X)
                {
                    digit_index++;

                    x += vfo_sub_char_width;
                    if (digit_index == 3)
                        x += vfo_sub_decimal_space;
                    else
                        x += vfo_sub_char_space;
                }

                if (digit_index < 3) digit_index = -1;
                if (digit_index > 9) digit_index = 9;
                vfoa_sub_hover_digit = digit_index;
                if (vfoa_sub_hover_digit != old_digit)
                    panelVFOASubHover.Invalidate();
            }
        }

        private void txtVFOABand_MouseLeave(object sender, System.EventArgs e)
        {
            vfoa_sub_hover_digit = -1;
            panelVFOASubHover.Invalidate();
        }

        private void SetRX2Mode(DSPMode new_mode)
        {
            if (new_mode == DSPMode.FIRST || new_mode == DSPMode.LAST) return;

            Band oldBand = RX2Band; //MW0LGE_21d
            DSPMode old_mode = rx2_dsp_mode;

            WDSP.SetChannelState(WDSP.id(2, 0), 0, 1);              // turn OFF the DSP channel

            if (new_mode == DSPMode.FM)                             // set DSP samplerate
                WDSP.SetDSPSamplerate(WDSP.id(2, 0), 192000);
            else
                WDSP.SetDSPSamplerate(WDSP.id(2, 0), 48000);

            radio.GetDSPRX(1, 0).DSPMode = new_mode;			    // set new DSP mode

            if (rx2_enabled)
            {
                if (chkVFOBTX.Checked)
                {
                    Audio.TXDSPMode = new_mode;
                    radio.GetDSPTX(0).CurrentDSPMode = new_mode;
                }
            }
            Display.RX2DSPMode = new_mode;
            RadioDSP.RX2DSPMode = new_mode;

            if (new_mode == DSPMode.CWL || new_mode == DSPMode.CWU)
            {
                WDSP.SetChannelTDelayUp(WDSP.id(2, 0), 0.005);
                WDSP.SetChannelTDelayUp(WDSP.id(2, 1), 0.005);
                WDSP.SetChannelTSlewUp(WDSP.id(2, 0), 0.010);
                WDSP.SetChannelTSlewUp(WDSP.id(2, 1), 0.010);
                WDSP.SetChannelTDelayDown(WDSP.id(2, 0), 0.000);
                WDSP.SetChannelTDelayDown(WDSP.id(2, 1), 0.000);
                WDSP.SetChannelTSlewDown(WDSP.id(2, 0), 0.005);
                WDSP.SetChannelTSlewDown(WDSP.id(2, 1), 0.005);
            }
            else
            {
                WDSP.SetChannelTDelayUp(WDSP.id(2, 0), 0.000);
                WDSP.SetChannelTDelayUp(WDSP.id(2, 1), 0.000);
                WDSP.SetChannelTSlewUp(WDSP.id(2, 0), 0.010);
                WDSP.SetChannelTSlewUp(WDSP.id(2, 1), 0.010);
                WDSP.SetChannelTDelayDown(WDSP.id(2, 0), 0.000);
                WDSP.SetChannelTDelayDown(WDSP.id(2, 1), 0.000);
                WDSP.SetChannelTSlewDown(WDSP.id(2, 0), 0.010);
                WDSP.SetChannelTSlewDown(WDSP.id(2, 1), 0.010);
            }

            double rx2_freq = VFOBFreq;
            int old_txosc = (int)radio.GetDSPTX(0).TXOsc;

            switch (old_mode)
            {
                case DSPMode.LSB:
                    radRX2ModeLSB.BackColor = SystemColors.Control;
                    break;
                case DSPMode.USB:
                    radRX2ModeUSB.BackColor = SystemColors.Control;
                    break;
                case DSPMode.DSB:
                    radRX2ModeDSB.BackColor = SystemColors.Control;
                    break;
                case DSPMode.CWL:
                    radRX2ModeCWL.BackColor = SystemColors.Control;

                    if (!RX2IsIn60mChannel())
                    {
                        switch (new_mode)
                        {
                            case DSPMode.USB:
                                rx2_freq -= (cw_pitch * 1e-6);
                                break;
                            case DSPMode.CWU:
                                break;
                            default:
                                rx2_freq += (cw_pitch * 1e-6);
                                break;
                        }

                        setVFOBFreqNoUpdate(rx2_freq);
                    }

                    radio.GetDSPRX(1, 0).RXAPFRun = false;
                    SetupForm.EnableRX2APFControl = false;
                    lblRX2APF.Hide();
                    break;
                case DSPMode.CWU:
                    radRX2ModeCWU.BackColor = SystemColors.Control;

                    if (!RX2IsIn60mChannel())
                    {
                        switch (new_mode)
                        {
                            case DSPMode.LSB:
                                rx2_freq += (cw_pitch * 1e-6);
                                break;
                            case DSPMode.CWL:
                                break;
                            default:
                                rx2_freq -= (cw_pitch * 1e-6);
                                break;
                        }

                        setVFOBFreqNoUpdate(rx2_freq);
                    }

                    radio.GetDSPRX(1, 0).RXAPFRun = false;
                    SetupForm.EnableRX2APFControl = false;
                    lblRX2APF.Hide();
                    break;
                case DSPMode.FM:
                    radRX2ModeFMN.BackColor = SystemColors.Control;
                    if (rx2_enabled)
                    {
                        if (new_mode != DSPMode.AM &&
                            new_mode != DSPMode.SAM &&
                            new_mode != DSPMode.FM)
                        {
                            if (chkVFOBTX.Checked)
                                chkMON.Enabled = true;

                            chkRX2BIN.Enabled = true;
                        }

                        if (chkVFOBTX.Checked)
                            ptbMic_Scroll(this, EventArgs.Empty);
                    }

                    if (new_mode != DSPMode.DRM)
                        EnableAllRX2Filters();

                    handleSqlFM(2, false);

                    break;
                case DSPMode.AM:
                    radRX2ModeAM.BackColor = SystemColors.Control;
                    if (rx2_enabled)
                    {
                        if (new_mode != DSPMode.AM &&
                            new_mode != DSPMode.SAM &&
                            new_mode != DSPMode.FM)
                        {
                            if (chkVFOBTX.Checked)
                                chkMON.Enabled = true;

                            chkRX2BIN.Enabled = true;
                        }
                        if (chkVFOBTX.Checked)
                            ptbMic_Scroll(this, EventArgs.Empty);
                    }

                    if (new_mode != DSPMode.DRM)
                        EnableAllRX2Filters();
                    break;
                case DSPMode.SAM:
                    radRX2ModeSAM.BackColor = SystemColors.Control;
                    if (rx2_enabled)
                    {
                        if (new_mode != DSPMode.AM &&
                            new_mode != DSPMode.SAM &&
                            new_mode != DSPMode.FM)
                        {
                            if (chkVFOBTX.Checked)
                                chkMON.Enabled = true;

                            chkRX2BIN.Enabled = true;
                        }

                        if (chkVFOBTX.Checked)
                            ptbMic_Scroll(this, EventArgs.Empty);
                    }
                    break;
                case DSPMode.DIGL:
                    radRX2ModeDIGL.BackColor = SystemColors.Control;
                    if (rx2_enabled && vac2_auto_enable &&
                        new_mode != DSPMode.DIGU &&
                        new_mode != DSPMode.DRM)
                    {
                        SetupForm.VAC2Enable = false;
                    }
                    if (new_mode != DSPMode.DIGU) SetDigiMode(2, DigiMode.DigiModeSettingState.dmssRecall);
                    break;
                case DSPMode.DIGU:
                    radRX2ModeDIGU.BackColor = SystemColors.Control;
                    if (rx2_enabled && vac2_auto_enable &&
                        new_mode != DSPMode.DIGL &&
                        new_mode != DSPMode.DRM)
                    {
                        SetupForm.VAC2Enable = false;
                    }
                    if (new_mode != DSPMode.DIGL) SetDigiMode(2, DigiMode.DigiModeSettingState.dmssRecall);
                    break;
                case DSPMode.DRM:
                    radRX2ModeDRM.BackColor = SystemColors.Control;

                    rx2_vfo_offset = 0.0;
                    if (rx2_enabled && vac_auto_enable &&
                        new_mode != DSPMode.DIGL &&
                        new_mode != DSPMode.DIGU)
                        SetupForm.VAC2Enable = false;
                    if (new_mode != DSPMode.FM)
                        EnableAllRX2Filters();

                    CalcDisplayFreq();
                    break;
            }

            switch (new_mode)
            {
                case DSPMode.LSB:
                    radRX2ModeLSB.BackColor = button_selected_color;

                    if (chkVFOBTX.Checked && rx2_enabled)
                    {
                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);
                        radio.GetDSPTX(0).TXOsc = 0.0;
                    }
                    break;
                case DSPMode.USB:
                    radRX2ModeUSB.BackColor = button_selected_color;

                    if (chkVFOBTX.Checked && rx2_enabled)
                    {
                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);
                        radio.GetDSPTX(0).TXOsc = 0.0;
                    }
                    break;
                case DSPMode.DSB:
                    radRX2ModeDSB.BackColor = button_selected_color;

                    if (chkVFOBTX.Checked && rx2_enabled)
                    {
                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);
                        radio.GetDSPTX(0).TXOsc = 0.0;
                    }
                    break;
                case DSPMode.CWL:
                    radRX2ModeCWL.BackColor = button_selected_color;

                    if (chkVFOBTX.Checked && rx2_enabled)
                    {
                        radio.GetDSPTX(0).TXOsc = 0.0;
                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);
                        CWPitch = cw_pitch;
                    }

                    if (!RX2IsIn60mChannel())
                    {
                        switch (rx2_dsp_mode)
                        {
                            case DSPMode.USB:
                                rx2_freq += (cw_pitch * 1e-6);
                                break;
                            case DSPMode.CWU:
                                break;
                            default:
                                rx2_freq -= (cw_pitch * 1e-6);
                                break;
                        }

                        setVFOBFreqNoUpdate(rx2_freq);
                    }
                    SetupForm.EnableRX2APFControl = true;
                    lblRX2APF.Show();

                    break;
                case DSPMode.CWU:
                    radRX2ModeCWU.BackColor = button_selected_color;

                    if (chkVFOBTX.Checked && rx2_enabled)
                    {
                        radio.GetDSPTX(0).TXOsc = 0.0;
                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);
                        CWPitch = cw_pitch;
                    }

                    if (!RX2IsIn60mChannel())
                    {
                        switch (rx2_dsp_mode)
                        {
                            case DSPMode.LSB:
                                rx2_freq -= (cw_pitch * 1e-6);
                                break;
                            case DSPMode.CWL:
                                break;
                            default:
                                rx2_freq += (cw_pitch * 1e-6);
                                break;
                        }

                        setVFOBFreqNoUpdate(rx2_freq);
                    }
                    SetupForm.EnableRX2APFControl = true;
                    lblRX2APF.Show();

                    break;
                case DSPMode.FM:
                    radRX2ModeFMN.BackColor = button_selected_color;
                    DisableAllRX2Filters();    //this needs to be for RX2 only
                    if (chkRX2NR.CheckState == CheckState.Indeterminate)
                        chkRX2NR.CheckState = CheckState.Unchecked;

                    handleSqlFM(2, true);

                    if (rx2_enabled)
                    {
                        if (chkVFOBTX.Checked)
                        {
                            if (!rx_only && chkPower.Checked)
                                chkMOX.Enabled = true;

                            chkMON.Checked = false;
                            chkMON.Enabled = false;

                            SetTXFilters(new_mode, tx_filter_low, tx_filter_high);

                            ptbFMMic_Scroll(this, EventArgs.Empty);
                        }

                        chkRX2BIN.Checked = false;
                        chkRX2BIN.Enabled = false;
                    }
                    break;
                case DSPMode.AM:
                    radRX2ModeAM.BackColor = button_selected_color;

                    if (chkVFOBTX.Checked)
                    {
                        if (!rx_only && chkPower.Checked)
                            chkMOX.Enabled = true;

                        chkMON.Checked = false;
                        chkMON.Enabled = false;

                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);

                        ptbFMMic_Scroll(this, EventArgs.Empty);
                    }

                    chkRX2BIN.Checked = false;
                    chkRX2BIN.Enabled = false;
                    break;
                case DSPMode.SAM:
                    radRX2ModeSAM.BackColor = button_selected_color;

                    if (chkVFOBTX.Checked)
                    {
                        if (!rx_only && chkPower.Checked)
                            chkMOX.Enabled = true;

                        chkMON.Checked = false;
                        chkMON.Enabled = false;

                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);

                        ptbFMMic_Scroll(this, EventArgs.Empty);
                    }

                    chkRX2BIN.Checked = false;
                    chkRX2BIN.Enabled = false;
                    break;
                case DSPMode.DIGL:
                    radRX2ModeDIGL.BackColor = button_selected_color;

                    if (chkVFOBTX.Checked && rx2_enabled)
                    {
                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);
                        radio.GetDSPTX(0).TXOsc = 0.0;
                    }

                    if (rx2_enabled && vac2_auto_enable)
                        SetupForm.VAC2Enable = true;

                    if (old_mode != DSPMode.DIGU)
                    {
                        SetDigiMode(2, DigiMode.DigiModeSettingState.dmssStore);
                        SetDigiMode(2, DigiMode.DigiModeSettingState.dmssTurnOffSettings);
                    }

                    break;
                case DSPMode.DIGU:
                    radRX2ModeDIGU.BackColor = button_selected_color;

                    if (chkVFOBTX.Checked && rx2_enabled)
                    {
                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);
                        radio.GetDSPTX(0).TXOsc = 0.0;
                    }
                    if (rx2_enabled && vac2_auto_enable)
                        SetupForm.VAC2Enable = true;

                    if (old_mode != DSPMode.DIGL)
                    {
                        SetDigiMode(2, DigiMode.DigiModeSettingState.dmssStore);
                        SetDigiMode(2, DigiMode.DigiModeSettingState.dmssTurnOffSettings);
                    }

                    break;
                case DSPMode.DRM:
                    rx2_vfo_offset = -0.012;
                    radRX2ModeDRM.BackColor = button_selected_color;

                    if (rx2_enabled && vac2_auto_enable)
                        SetupForm.VAC2Enable = true;

                    if (chkVFOBTX.Checked && rx2_enabled)
                    {
                        SetTXFilters(new_mode, tx_filter_low, tx_filter_high);
                        radio.GetDSPTX(0).TXOsc = 0.0;
                    }

                    radio.GetDSPRX(1, 0).SetRXFilter(7000, 17000);

                    break;
            }

            if (RX2IsOn60mChannel() && current_region == FRSRegion.US)
            {
                // adjust freq offset to ensure center of energy for new mode in 60m
                rx2_freq += (-ModeFreqOffset(old_mode) + ModeFreqOffset(new_mode));

                setVFOBFreqNoUpdate(rx2_freq);
            }

            kToolStripMenuItem.Text = radRX2Filter1.Text = rx2_filters[(int)new_mode].GetName(Filter.F1);
            kToolStripMenuItem1.Text = radRX2Filter2.Text = rx2_filters[(int)new_mode].GetName(Filter.F2);
            kToolStripMenuItem2.Text = radRX2Filter3.Text = rx2_filters[(int)new_mode].GetName(Filter.F3);
            kToolStripMenuItem3.Text = radRX2Filter4.Text = rx2_filters[(int)new_mode].GetName(Filter.F4);
            kToolStripMenuItem4.Text = radRX2Filter5.Text = rx2_filters[(int)new_mode].GetName(Filter.F5);
            toolStripMenuItem13.Text = radRX2Filter6.Text = rx2_filters[(int)new_mode].GetName(Filter.F6);
            toolStripMenuItem14.Text = radRX2Filter7.Text = rx2_filters[(int)new_mode].GetName(Filter.F7);
            radRX2FilterVar1.Text = rx2_filters[(int)new_mode].GetName(Filter.VAR1);
            radRX2FilterVar2.Text = rx2_filters[(int)new_mode].GetName(Filter.VAR2);

            rx2_dsp_mode = new_mode;

            if (rx2_dsp_mode != DSPMode.FM && rx2_dsp_mode != DSPMode.DRM)
            {
                RX2Filter = rx2_filters[(int)new_mode].LastFilter;
            }
            else
            {
                if (rx2_dsp_mode == DSPMode.FM)
                {
                    int halfBw = (int)(radio.GetDSPTX(0).TXFMDeviation + radio.GetDSPRX(1, 0).RXFMHighCut); //[2.10.3.4]MW0LGE
                    UpdateRX2Filters(-halfBw, halfBw);
                }
                RX2Filter = Filter.NONE;
            }

            if (rx2_dsp_mode != DSPMode.FM && rx2_dsp_mode != DSPMode.DRM)
            {
                RX2Filter = rx2_filters[(int)new_mode].LastFilter;
            }
            else
            {
                RX2Filter = Filter.NONE;
            }

            tbFilterWidthScroll_newMode();

            if (new_mode == DSPMode.CWL || new_mode == DSPMode.CWU)
            {
                chkCWAPFEnabled_CheckedChanged(this, EventArgs.Empty);
            }

            UpdateDSP();
            txtVFOBFreq_LostFocus(this, EventArgs.Empty);
            chkRX2Squelch_CheckStateChanged(this, EventArgs.Empty);
            ptbPWR_Scroll(this, EventArgs.Empty);

            if (old_mode == DSPMode.FM || new_mode == DSPMode.FM)
            {
                SetupForm.ForceAudioReset();
            }

            if (rx2_enabled)
                WDSP.SetChannelState(WDSP.id(2, 0), 1, 0);              // turn ON the DSP channel

            //MW0LGE_21b
            if (old_mode != new_mode) ModeChangeHandlers?.Invoke(2, old_mode, new_mode, oldBand, RX2Band);
        }

        private void radRX2ModeButton_CheckedChanged(object sender, System.EventArgs e)
        {
            if (sender == null) return;
            if (sender.GetType() != typeof(RadioButtonTS)) return;
            RadioButtonTS radioBtnTS = (RadioButtonTS)sender;
            if (!radioBtnTS.Checked) return;
            string radiobut = ((RadioButtonTS)sender).Text;

            switch (radiobut)
            {
                case "LSB":
                    SetRX2Mode(DSPMode.LSB);
                    break;
                case "USB":
                    SetRX2Mode(DSPMode.USB);
                    break;
                case "DSB":
                    SetRX2Mode(DSPMode.DSB);
                    break;
                case "CWL":
                    SetRX2Mode(DSPMode.CWL);
                    break;
                case "CWU":
                    SetRX2Mode(DSPMode.CWU);
                    break;
                case "FM":
                    SetRX2Mode(DSPMode.FM);
                    break;
                case "AM":
                    SetRX2Mode(DSPMode.AM);
                    break;
                case "SAM":
                    SetRX2Mode(DSPMode.SAM);
                    break;
                case "DIGL":
                    SetRX2Mode(DSPMode.DIGL);
                    break;
                case "DIGU":
                    SetRX2Mode(DSPMode.DIGU);
                    break;
                case "DRM":
                    SetRX2Mode(DSPMode.DRM);
                    break;
            }

            //setRX2ModeLabels(radiobut); //MW0LGE_21j
            setSmallRX2ModeFilterLabels();

            lSBToolStripMenuItem1.Checked = radRX2ModeLSB.Checked;
            uSBToolStripMenuItem1.Checked = radRX2ModeUSB.Checked;
            dSBToolStripMenuItem1.Checked = radRX2ModeDSB.Checked;
            cWLToolStripMenuItem1.Checked = radRX2ModeCWL.Checked;
            cWUToolStripMenuItem1.Checked = radRX2ModeCWU.Checked;
            fMToolStripMenuItem1.Checked = radRX2ModeFMN.Checked;
            aMToolStripMenuItem1.Checked = radRX2ModeAM.Checked;
            sAMToolStripMenuItem1.Checked = radRX2ModeSAM.Checked;
            dIGLToolStripMenuItem1.Checked = radRX2ModeDIGL.Checked;
            dIGUToolStripMenuItem1.Checked = radRX2ModeDIGU.Checked;
            dRMToolStripMenuItem1.Checked = radRX2ModeDRM.Checked;
            if (filterPopupForm != null) filterPopupForm.RepopulateForm();
            if (modePopupForm != null) modePopupForm.RepopulateForm();
        }

        private void radRX2ModeLSB_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radRX2ModeLSB.Checked)
            {
                SetRX2Mode(DSPMode.LSB);
            }
        }

        private void radRX2ModeUSB_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radRX2ModeUSB.Checked)
            {
                SetRX2Mode(DSPMode.USB);
            }
        }

        private void radRX2ModeDSB_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radRX2ModeDSB.Checked)
            {
                SetRX2Mode(DSPMode.DSB);
            }
        }

        private void radRX2ModeCWL_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radRX2ModeCWL.Checked)
            {
                SetRX2Mode(DSPMode.CWL);
            }
        }

        private void radRX2ModeCWU_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radRX2ModeCWU.Checked)
            {
                SetRX2Mode(DSPMode.CWU);
            }
        }

        private void radRX2ModeFMN_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radRX2ModeFMN.Checked)
            {
                SetRX2Mode(DSPMode.FM);
            }
        }

        private void radRX2ModeAM_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radRX2ModeAM.Checked)
            {
                SetRX2Mode(DSPMode.AM);
            }
        }

        private void radRX2ModeSAM_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radRX2ModeSAM.Checked)
            {
                SetRX2Mode(DSPMode.SAM);
            }
        }

        private void radRX2ModeDIGL_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radRX2ModeDIGL.Checked)
            {
                SetRX2Mode(DSPMode.DIGL);
            }
        }

        private void radRX2ModeDIGU_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radRX2ModeDIGU.Checked)
            {
                SetRX2Mode(DSPMode.DIGU);
            }
        }

        private void radRX2ModeDRM_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radRX2ModeDRM.Checked)
            {
                SetRX2Mode(DSPMode.DRM);
            }
        }

        public void SetRX2Filter(Filter new_filter)
        {
            if (rx2_dsp_mode == DSPMode.FIRST || rx2_dsp_mode == DSPMode.LAST) return;

            Filter oldFilter = rx2_filter; //MW0LGE_21d

            int low = 0, high = 0;

            switch (rx2_filter)
            {
                case Filter.F1:
                    radRX2Filter1.BackColor = SystemColors.Control;
                    break;
                case Filter.F2:
                    radRX2Filter2.BackColor = SystemColors.Control;
                    break;
                case Filter.F3:
                    radRX2Filter3.BackColor = SystemColors.Control;
                    break;
                case Filter.F4:
                    radRX2Filter4.BackColor = SystemColors.Control;
                    break;
                case Filter.F5:
                    radRX2Filter5.BackColor = SystemColors.Control;
                    break;
                case Filter.F6:
                    radRX2Filter6.BackColor = SystemColors.Control;
                    break;
                case Filter.F7:
                    radRX2Filter7.BackColor = SystemColors.Control;
                    break;
                case Filter.VAR1:
                    udRX2FilterLow.Enabled = false;
                    udRX2FilterHigh.Enabled = false;
                    break;
                case Filter.VAR2:
                    udRX2FilterLow.Enabled = false;
                    udRX2FilterHigh.Enabled = false;
                    break;
            }

            rx2_filter = new_filter;

            low = rx2_filters[(int)rx2_dsp_mode].GetLow(new_filter);
            high = rx2_filters[(int)rx2_dsp_mode].GetHigh(new_filter);
            rx2_filters[(int)rx2_dsp_mode].LastFilter = new_filter;

            panelRX2Filter.Text = "RX2 Filter - " + rx2_filters[(int)rx2_dsp_mode].GetName(new_filter);

            switch (new_filter)
            {
                case Filter.F1:
                    radRX2Filter1.BackColor = button_selected_color;
                    break;
                case Filter.F2:
                    radRX2Filter2.BackColor = button_selected_color;
                    break;
                case Filter.F3:
                    radRX2Filter3.BackColor = button_selected_color;
                    break;
                case Filter.F4:
                    radRX2Filter4.BackColor = button_selected_color;
                    break;
                case Filter.F5:
                    radRX2Filter5.BackColor = button_selected_color;
                    break;
                case Filter.F6:
                    radRX2Filter6.BackColor = button_selected_color;
                    break;
                case Filter.F7:
                    radRX2Filter7.BackColor = button_selected_color;
                    break;
                case Filter.VAR1:
                    udRX2FilterLow.Enabled = true;
                    udRX2FilterHigh.Enabled = true;
                    break;
                case Filter.VAR2:
                    udRX2FilterLow.Enabled = true;
                    udRX2FilterHigh.Enabled = true;
                    break;
                case Filter.NONE:
                    foreach (Control c in panelRX2Filter.Controls)
                    {
                        if (c.GetType() == typeof(RadioButtonTS))
                        {
                            ((RadioButtonTS)c).Checked = false;

                            if (c.BackColor != SystemColors.Control)
                                ((RadioButtonTS)c).BackColor = SystemColors.Control;
                        }
                    }
                    return;
            }

            UpdateRX2Filters(low, high);

            if (oldFilter != rx2_filter) FilterChangedHandlers?.Invoke(2, oldFilter, rx2_filter, RX2Band, low, high, rx2_filters[(int)rx2_dsp_mode].GetName(rx2_filter)); //MW0LGE [2.9.0.7]
        }

        private void radRX2Filter1_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radRX2Filter1.Checked)
                SetRX2Filter(Filter.F1);
        }

        private void radRX2Filter2_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radRX2Filter2.Checked)
                SetRX2Filter(Filter.F2);
        }

        private void radRX2Filter3_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radRX2Filter3.Checked)
                SetRX2Filter(Filter.F3);
        }

        private void radRX2Filter4_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radRX2Filter4.Checked)
                SetRX2Filter(Filter.F4);
        }

        private void radRX2Filter5_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radRX2Filter5.Checked)
                SetRX2Filter(Filter.F5);
        }

        private void radRX2Filter6_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radRX2Filter6.Checked)
                SetRX2Filter(Filter.F6);
        }

        private void radRX2Filter7_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radRX2Filter7.Checked)
                SetRX2Filter(Filter.F7);
        }

        private void radRX2FilterVar1_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radRX2FilterVar1.Checked)
                SetRX2Filter(Filter.VAR1);
        }

        private void radRX2FilterVar2_CheckedChanged(object sender, System.EventArgs e)
        {
            if (radRX2FilterVar2.Checked)
                SetRX2Filter(Filter.VAR2);
        }

        private void udRX2FilterLow_ValueChanged(object sender, System.EventArgs e)
        {
            //MW0LGE_21d filter
            if (udRX2FilterLow.Focused || udRX2FilterLow.ClientRectangle.Contains(udRX2FilterLow.PointToClient(Control.MousePosition)))
            {
                if (udRX2FilterLow.Value >= udRX2FilterHigh.Value - 10)
                {
                    udRX2FilterLow.Value = udRX2FilterHigh.Value - 10;
                    return;
                }

                UpdateRX2Filters((int)udRX2FilterLow.Value, (int)udRX2FilterHigh.Value);

                if (!save_filter_changes)
                    rx2_filters[(int)rx2_dsp_mode].SetLow(rx2_filter, (int)udRX2FilterLow.Value);
            }

            if (save_filter_changes && rx2_filter >= Filter.F1 && rx2_filter <= Filter.VAR2)
                rx2_filters[(int)rx2_dsp_mode].SetLow(rx2_filter, (int)udRX2FilterLow.Value);
        }

        private bool m_bBypassVACWhenPlayingRecording = false;
        public bool BypassVACWhenPlayingRecording {
            get { return m_bBypassVACWhenPlayingRecording; }
            set { m_bBypassVACWhenPlayingRecording = value; }
        }

        private void udRX2FilterHigh_ValueChanged(object sender, System.EventArgs e)
        {
            //MW0LGE_21d filter
            if (udRX2FilterHigh.Focused || udRX2FilterHigh.ClientRectangle.Contains(udRX2FilterHigh.PointToClient(Control.MousePosition)))
            {
                if (udRX2FilterHigh.Value <= udRX2FilterLow.Value + 10)
                {
                    udRX2FilterHigh.Value = udRX2FilterLow.Value + 10;
                    return;
                }

                UpdateRX2Filters((int)udRX2FilterLow.Value, (int)udRX2FilterHigh.Value);

                if (!save_filter_changes)
                    rx2_filters[(int)rx2_dsp_mode].SetHigh(rx2_filter, (int)udRX2FilterHigh.Value);
            }

            if (save_filter_changes && rx2_filter >= Filter.F1 && rx2_filter <= Filter.VAR2)
                rx2_filters[(int)rx2_dsp_mode].SetHigh(rx2_filter, (int)udRX2FilterHigh.Value);
        }

        private void chkRX2ANF_CheckedChanged(object sender, System.EventArgs e)
        {
            if (chkRX2ANF.Checked)
            {
                chkRX2ANF.BackColor = button_selected_color;
                lblRX2ANFLabel.Text = "ANF";
            }

            else
            {
                chkRX2ANF.BackColor = SystemColors.Control;
                lblRX2ANFLabel.Text = "---";
            }
            radio.GetDSPRX(1, 0).AutoNotchFilter = chkRX2ANF.Checked;
            radio.GetDSPRX(1, 1).AutoNotchFilter = chkRX2ANF.Checked;

            catrx2_anf_status = Convert.ToInt32(chkRX2ANF.Checked);
            aNF2ToolStripMenuItem.Checked = chkRX2ANF.Checked;
            AndromedaIndicatorCheck(EIndicatorActions.eINANF, false, chkRX2ANF.Checked);
        }

        private void chkRX2BIN_CheckedChanged(object sender, System.EventArgs e)
        {
            if (chkRX2BIN.Checked) chkRX2BIN.BackColor = button_selected_color;
            else chkRX2BIN.BackColor = SystemColors.Control;
            radio.GetDSPRX(1, 0).BinOn = chkRX2BIN.Checked;
            radio.GetDSPRX(1, 1).BinOn = chkRX2BIN.Checked;
            bIN2ToolStripMenuItem.Checked = chkRX2BIN.Checked;
        }

        private void comboRX2MeterMode_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            if (comboRX2MeterMode.Items.Count == 0 ||
                comboRX2MeterMode.SelectedIndex < 0)
            {
                rx2_meter_mode = MeterRXMode.FIRST;
            }
            else
            {
                MeterRXMode mode = MeterRXMode.FIRST;
                switch (comboRX2MeterMode.Text)
                {
                    case "Signal":
                        mode = MeterRXMode.SIGNAL_STRENGTH;
                        break;
                    case "Sig Avg":
                        mode = MeterRXMode.SIGNAL_AVERAGE;
                        break;
                    case "ADC L":
                        mode = MeterRXMode.ADC_L;
                        break;
                    case "ADC R":
                        mode = MeterRXMode.ADC_R;
                        break;
                    case "ADC2 L":
                        mode = MeterRXMode.ADC2_L;
                        break;
                    case "ADC2 R":
                        mode = MeterRXMode.ADC2_R;
                        break;
                    case "Off":
                        mode = MeterRXMode.OFF;
                        break;
                }
                rx2_meter_mode = mode;
                if (!show_rx1)                                          // collapsed meter is RX1/RX2 shared
                    lblRXMeter.Text = comboRX2MeterMode.Text;

                ResetRX2MeterPeak();
            }

            picRX2Meter.Invalidate();

            if (comboRX2MeterMode.Focused)
                btnHidden.Focus();
        }

        private void chkRX2Preamp_CheckedChanged(object sender, System.EventArgs e)
        {
            if (chkRX2Preamp.Checked)
            {
                chkRX2Preamp.BackColor = button_selected_color;
            }
            else
            {
                chkRX2Preamp.BackColor = SystemColors.Control;
            }

        }

        private void ptbRX2RF_Scroll(object sender, System.EventArgs e)
        {
            switch (RX2AGCMode)
            {
                case AGCMode.FIXD:
                    lblRX2RF.Text = "Fixed Gain:  " + ptbRX2RF.Value.ToString();
                    if (!IsSetupFormNull) SetupForm.AGCRX2FixedGain = ptbRX2RF.Value;
                    break;
                default:
                    lblRX2RF.Text = "AGC Gain:  " + ptbRX2RF.Value.ToString();
                    if (!IsSetupFormNull) SetupForm.AGCRX2MaxGain = ptbRX2RF.Value;
                    break;
            }

            rx2_agct_by_band[(int)rx2_band] = ptbRX2RF.Value;

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbRX2RF.Focus();
            }

            //-W2PA Update LEDs on Behringer MIDI controller
            double pct = Convert.ToDouble(ptbRX2RF.Value - ptbRX2RF.Minimum) / Convert.ToDouble(ptbRX2RF.Maximum - ptbRX2RF.Minimum);
            Midi2Cat.SendUpdateToMidi(CatCmd.RX2AGCLevel_inc, pct);
            if (sliderForm != null)
            {
                sliderForm.RX2RFGainAGC = ptbRX2RF.Value;

                //wd5y
                if (AutoAGCRX2)
                {
                    sliderForm.chkRX2AGCAut.Checked = true;
                }
                else
                {
                    sliderForm.chkRX2AGCAut.Checked = false;
                }

                sliderForm.lblRX2rf.Text = ptbRX2RF.Value.ToString();
                //wd5y
            }

            //wd5y
            lblRF3.Size = new Size(34, 23);
            lblRF3.Text = "RF:   " + ptbRX2RF.Value.ToString();
            //wd5y
        }
        private void picRX2Squelch_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            int signal_x = (int)((rx2_sql_data + 160.0) * (picRX2Squelch.Width - 1) / 160.0);
            int sql_x = (int)(((float)ptbRX2Squelch.Value + 160.0) * (ptbRX2Squelch.Width - 1) / 160.0);

            e.Graphics.FillRectangle(Brushes.LimeGreen, 0, 0, signal_x, picRX2Squelch.Height);
            if (sql_x < signal_x)
                e.Graphics.FillRectangle(Brushes.Red, sql_x + 1, 0, signal_x - sql_x - 1, picRX2Squelch.Height);
        }
        private void chkRX1Preamp_CheckedChanged(object sender, System.EventArgs e)
        {
            if (chkRX1Preamp.Checked)
            {
                chkRX1Preamp.BackColor = button_selected_color;
                chkRX1Preamp.Text = "On";
                RX1PreampMode = PreampMode.HPSDR_ON;
            }
            else
            {
                chkRX1Preamp.BackColor = SystemColors.Control;
                chkRX1Preamp.Text = "Off";
                RX1PreampMode = PreampMode.HPSDR_OFF;
            }
        }

        private void ptbRX2Pan_Scroll(object sender, System.EventArgs e)
        {
            float val = (int)ptbRX2Pan.Value / 100.0f;
            radio.GetDSPRX(1, 0).Pan = val;

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbRX2Pan.Focus();
            }
            if (sliderForm != null)
            {
                sliderForm.RX2LRPan = ptbRX2Pan.Value;

                //wd5y
                sliderForm.lblRX2Pan.Text = RX2Pan.ToString();
                //wd5y
            }

        }

        private void ptbRX2Gain_Scroll(object sender, System.EventArgs e)
        {
            //MWLGE_21k9 re-worked //[2.10.1.0] MW0LGE event args empty
            if (!initializing && e != EventArgs.Empty && m_bRXAFSlidersWillUnmute && chkRX2Mute.Checked) chkRX2Mute.Checked = false;

            if (chkRX2Mute.Checked && m_bMuteWillMuteVAC2) //MW0LGE_21k9
            {
                radio.GetDSPRX(1, 0).RXOutputGain = 0.0;
            }
            else
            {
                radio.GetDSPRX(1, 0).RXOutputGain = (double)ptbRX2Gain.Value / ptbRX2Gain.Maximum;                
            }
            ptbRX2AF.Value = ptbRX2Gain.Value;

            lblRX2AF.Text = "RX2 AF:  " + ptbRX2Gain.Value.ToString();

            //wd5y
            lblAF3.Size = new Size(34, 23);
            lblAF3.Text = "AF:  " + ptbRX2Gain.Value.ToString();
            //wd5y

            setLinkedAF(3, ptbRX2Gain.Value); //[2.10.1.0] MW0LGE

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbRX2Gain.Focus();
            }

            //-W2PA Update LEDs on Behringer MIDI controller
            double pct = Convert.ToDouble(ptbRX2AF.Value - ptbRX2AF.Minimum) / Convert.ToDouble(ptbRX2AF.Maximum - ptbRX2AF.Minimum);
            Midi2Cat.SendUpdateToMidi(CatCmd.VolumeVfoB_inc, pct);
            if (sliderForm != null)
            {
                sliderForm.RX2Gain = ptbRX2Gain.Value;

                //wd5y
                sliderForm.lblAFrx2.Text = ptbRX2Gain.Value.ToString();
                //wd5y
            }
        }

        private void chkRX2Mute_CheckedChanged(object sender, System.EventArgs e)
        {
            bool bOldMute = Audio.MuteRX2;

            if (chkRX2Mute.Checked)
            {
                Audio.MuteRX2 = true;

                if (m_bMuteWillMuteVAC2)
                {
                    radio.GetDSPRX(1, 0).RXOutputGain = 0.0; //MW0LGE_21j
                }

                lblRX2MuteVFOB.Text = "MUTE";
                lblRX2MuteVFOB.Show(); //[2.10.1.0] from WD5Y
            }
            else
            {
                Audio.MuteRX2 = false;

                radio.GetDSPRX(1, 0).RXOutputGain = (double)ptbRX2Gain.Value / ptbRX2Gain.Maximum; //MW0LGE_21j

                ptbRX2Gain_Scroll(this, EventArgs.Empty);
                lblRX2MuteVFOB.Text = "";
                lblRX2MuteVFOB.Hide(); //[2.10.1.0] from WD5Y
            }
            if (sliderForm != null) sliderForm.RX2MuteOnOff = chkRX2Mute.Checked;

            if (chkRX2Mute.Focused)
                btnHidden.Focus();

            if (path_Illustrator != null)
                path_Illustrator.pi_Changed();

            if (bOldMute != Audio.MuteRX2)
                MuteChangedHandlers?.Invoke(2, bOldMute, Audio.MuteRX2);
        }

        private void comboRX2DisplayMode_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            switch (comboRX2DisplayMode.Text)
            {
                case "Spectrum":
                    Display.CurrentDisplayModeBottom = DisplayMode.SPECTRUM;
                    if (chkSplitDisplay.Checked) UpdateRXDisplayVars((int)udFilterLow.Value, (int)udFilterHigh.Value);
                    break;
                case "Panadapter":
                    Display.CurrentDisplayModeBottom = DisplayMode.PANADAPTER;
                    if (chkSplitDisplay.Checked) CalcDisplayFreq();
                    break;
                case "Scope":
                    Display.CurrentDisplayModeBottom = DisplayMode.SCOPE;
                    break;
                case "Phase":
                    Display.CurrentDisplayModeBottom = DisplayMode.PHASE;
                    break;
                case "Phase2":
                    Display.CurrentDisplayModeBottom = DisplayMode.PHASE2;
                    break;
                case "Waterfall":
                    Display.CurrentDisplayModeBottom = DisplayMode.WATERFALL;
                    if (chkSplitDisplay.Checked) CalcDisplayFreq();
                    break;
                case "Histogram":
                    Display.CurrentDisplayModeBottom = DisplayMode.HISTOGRAM;
                    break;
                case "Panafall":
                    Display.CurrentDisplayModeBottom = DisplayMode.PANAFALL;
                    if (chkSplitDisplay.Checked) CalcDisplayFreq();
                    break;
                case "Off":
                    Display.CurrentDisplayModeBottom = DisplayMode.OFF;
                    break;
            }

            if (comboRX2DisplayMode.Focused)
                btnHidden.Focus();
        }

        private void chkRX2DisplayAVG_CheckedChanged(object sender, System.EventArgs e)
        {
            specRX.GetSpecRX(1).AverageOn = chkRX2DisplayAVG.Checked;

            if (chkRX2DisplayAVG.Checked)
            {
                chkRX2DisplayAVG.BackColor = button_selected_color;
            }
            else
            {
                chkRX2DisplayAVG.BackColor = SystemColors.Control;
            }

            RX2AVGToolStripMenuItem.Checked = chkRX2DisplayAVG.Checked;
        }

        private void chkRX2DisplayPeak_CheckedChanged(object sender, System.EventArgs e)
        {
            specRX.GetSpecRX(1).PeakOn = chkRX2DisplayPeak.Checked;

            if (chkRX2DisplayPeak.Checked)
            {
                chkRX2DisplayPeak.BackColor = button_selected_color;
            }
            else
            {
                chkRX2DisplayPeak.BackColor = SystemColors.Control;
            }
            RX2PeakToolStripMenuItem.Checked = chkRX2DisplayPeak.Checked;
        }

        private bool m_bDeferUpdateDSP = false;
        public bool DeferUpdateDSP
        {
            get { return m_bDeferUpdateDSP; }
            set {
                bool bDoUpdate = m_bDeferUpdateDSP && !value; // was defered and not now, so we call UpdateDSP
                m_bDeferUpdateDSP = value;
                if (bDoUpdate) UpdateDSP();
            }
        }
        private void UpdateDSP()
        {
            if (m_bDeferUpdateDSP) return; //MW0LGE_21k9d

            Stopwatch sw = new Stopwatch();
            sw.Start();

            int bufsizerx1 = 64, bufsizerx2 = 64, bufsizetx = 128;
            int filtsizerx1 = 4096, filtsizerx2 = 4096, filtsizetx = 4096;
            DSPFilterType filttyperx1 = DSPFilterType.Low_Latency;
            DSPFilterType filttyperx2 = DSPFilterType.Low_Latency;
            DSPFilterType filttypetx = DSPFilterType.Low_Latency;

            bool bufferSizeDifferentRX = !(dsp_buf_phone_rx == dsp_buf_fm_rx && dsp_buf_fm_rx == dsp_buf_cw_rx && dsp_buf_cw_rx == dsp_buf_dig_rx);
            bool filterSizeDifferentRX = !(dsp_filt_size_phone_rx == dsp_filt_size_fm_rx && dsp_filt_size_fm_rx == dsp_filt_size_cw_rx && dsp_filt_size_cw_rx == dsp_filt_size_dig_rx);
            bool filterTypeDifferentRX = !(dsp_filt_type_phone_rx == dsp_filt_type_fm_rx && dsp_filt_type_fm_rx == dsp_filt_type_cw_rx && dsp_filt_type_cw_rx == dsp_filt_type_dig_rx);

            bool bufferSizeDifferentTX = !(dsp_buf_phone_tx == dsp_buf_fm_tx && dsp_buf_fm_tx == dsp_buf_dig_tx);
            bool filterSizeDifferentTX = !(dsp_filt_size_phone_tx == dsp_filt_size_fm_tx && dsp_filt_size_fm_tx == dsp_filt_size_dig_tx);
            bool filterTypeDifferentTX = !(dsp_filt_type_phone_tx == dsp_filt_type_fm_tx && dsp_filt_type_fm_tx == dsp_filt_type_dig_tx);

            if (!IsSetupFormNull)
            {
                SetupForm.SetupDSPWarnings(bufferSizeDifferentRX, filterSizeDifferentRX, filterTypeDifferentRX, bufferSizeDifferentTX, filterSizeDifferentTX, filterTypeDifferentTX);
            }

            switch (rx1_dsp_mode)
            {
                case DSPMode.LSB:
                case DSPMode.USB:
                case DSPMode.DSB:
                case DSPMode.AM:
                case DSPMode.SAM:
                    bufsizerx1 = dsp_buf_phone_rx;
                    filtsizerx1 = dsp_filt_size_phone_rx;
                    filttyperx1 = dsp_filt_type_phone_rx;
                    break;
                case DSPMode.FM:
                    bufsizerx1 = dsp_buf_fm_rx;
                    filtsizerx1 = dsp_filt_size_fm_rx;
                    filttyperx1 = dsp_filt_type_fm_rx;
                    break;
                case DSPMode.CWL:
                case DSPMode.CWU:
                    bufsizerx1 = dsp_buf_cw_rx;
                    filtsizerx1 = dsp_filt_size_cw_rx;
                    filttyperx1 = dsp_filt_type_cw_rx;
                    break;
                case DSPMode.DIGL:
                case DSPMode.DIGU:
                case DSPMode.DRM:
                    bufsizerx1 = dsp_buf_dig_rx;
                    filtsizerx1 = dsp_filt_size_dig_rx;
                    filttyperx1 = dsp_filt_type_dig_rx;
                    break;
            }

            switch (rx2_dsp_mode)
            {
                case DSPMode.LSB:
                case DSPMode.USB:
                case DSPMode.DSB:
                case DSPMode.AM:
                case DSPMode.SAM:
                    bufsizerx2 = dsp_buf_phone_rx;
                    filtsizerx2 = dsp_filt_size_phone_rx;
                    filttyperx2 = dsp_filt_type_phone_rx;
                    break;
                case DSPMode.FM:
                    bufsizerx2 = dsp_buf_fm_rx;
                    filtsizerx2 = dsp_filt_size_fm_rx;
                    filttyperx2 = dsp_filt_type_fm_rx;
                    break;
                case DSPMode.CWL:
                case DSPMode.CWU:
                    bufsizerx2 = dsp_buf_cw_rx;
                    filtsizerx2 = dsp_filt_size_cw_rx;
                    filttyperx2 = dsp_filt_type_cw_rx;
                    break;
                case DSPMode.DIGL:
                case DSPMode.DIGU:
                case DSPMode.DRM:
                    bufsizerx2 = dsp_buf_dig_rx;
                    filtsizerx2 = dsp_filt_size_dig_rx;
                    filttyperx2 = dsp_filt_type_dig_rx;
                    break;
            }

            DSPMode mode = rx1_dsp_mode;
            if (chkVFOBTX.Checked) mode = rx2_dsp_mode;
            switch (mode)
            {
                case DSPMode.LSB:
                case DSPMode.USB:
                case DSPMode.DSB:
                case DSPMode.AM:
                case DSPMode.SAM:
                    bufsizetx = dsp_buf_phone_tx;
                    filtsizetx = dsp_filt_size_phone_tx;
                    filttypetx = dsp_filt_type_phone_tx;
                    break;
                case DSPMode.FM:
                    bufsizetx = dsp_buf_fm_tx;
                    filtsizetx = dsp_filt_size_fm_tx;
                    filttypetx = dsp_filt_type_fm_tx;
                    break;
                case DSPMode.CWL:
                case DSPMode.CWU:
                    // MW0LGE_21k9
                    // Firmware handles this. So we can just use current values
                    // so that buffers/filters/types are not rebuilt, saving time.
                    bufsizetx = radio.GetDSPTX(0).BufferSize;
                    filtsizetx = radio.GetDSPTX(0).FilterSize;
                    filttypetx = radio.GetDSPTX(0).FilterType;
                    break;
                case DSPMode.DIGL:
                case DSPMode.DIGU:
                case DSPMode.DRM:
                    bufsizetx = dsp_buf_dig_tx;
                    filtsizetx = dsp_filt_size_dig_tx;
                    filttypetx = dsp_filt_type_dig_tx; //rx; MW0LGE_21kd5
                    break;
            }

            Cursor c = Cursor.Current;
            Cursor.Current = Cursors.WaitCursor;

            bool bMadeAChange = false;
            // buffer size
            if (radio.GetDSPRX(0, 0).BufferSize != bufsizerx1 ||
                radio.GetDSPRX(0, 1).BufferSize != bufsizerx1)
            {
                radio.GetDSPRX(0, 0).BufferSize = bufsizerx1;
                radio.GetDSPRX(0, 1).BufferSize = bufsizerx1;
                bMadeAChange = true;
            }

            if (radio.GetDSPRX(1, 0).BufferSize != bufsizerx2 ||
                radio.GetDSPRX(1, 1).BufferSize != bufsizerx2)
            {
                radio.GetDSPRX(1, 0).BufferSize = bufsizerx2;
                radio.GetDSPRX(1, 1).BufferSize = bufsizerx2;
                bMadeAChange = true;
            }

            if (radio.GetDSPTX(0).BufferSize != bufsizetx)
            {
                radio.GetDSPTX(0).BufferSize = bufsizetx;
                bMadeAChange = true;
            }

            // filter size
            if (radio.GetDSPRX(0, 0).FilterSize != filtsizerx1 ||
                radio.GetDSPRX(0, 1).FilterSize != filtsizerx1)
            {
                radio.GetDSPRX(0, 0).FilterSize = filtsizerx1;
                radio.GetDSPRX(0, 1).FilterSize = filtsizerx1;
                bMadeAChange = true;
            }

            if (radio.GetDSPRX(1, 0).FilterSize != filtsizerx2 ||
                radio.GetDSPRX(1, 1).FilterSize != filtsizerx2)
            {
                radio.GetDSPRX(1, 0).FilterSize = filtsizerx2;
                radio.GetDSPRX(1, 1).FilterSize = filtsizerx2;
                bMadeAChange = true;
            }

            if (radio.GetDSPTX(0).FilterSize != filtsizetx)
            {
                radio.GetDSPTX(0).FilterSize = filtsizetx;
                bMadeAChange = true;
            }

            // filter type
            if (radio.GetDSPRX(0, 0).FilterType != filttyperx1 ||
                radio.GetDSPRX(0, 1).FilterType != filttyperx1)
            {
                radio.GetDSPRX(0, 0).FilterType = filttyperx1;
                radio.GetDSPRX(0, 1).FilterType = filttyperx1;
                bMadeAChange = true;
            }

            if (radio.GetDSPRX(1, 0).FilterType != filttyperx2 ||
                radio.GetDSPRX(1, 1).FilterType != filttyperx2)
            {
                radio.GetDSPRX(1, 0).FilterType = filttyperx2;
                radio.GetDSPRX(1, 1).FilterType = filttyperx2;
                bMadeAChange = true;
            }

            if (radio.GetDSPTX(0).FilterType != filttypetx)
            {
                radio.GetDSPTX(0).FilterType = filttypetx;
                bMadeAChange = true;
            }

            UpdateRXSpectrumDisplayVars();
            UpdateTXSpectrumDisplayVars();

            Cursor.Current = c;

            sw.Stop();
            if (bMadeAChange && !IsSetupFormNull)
            {
                SetupForm.DSPChangeDuration = sw.ElapsedMilliseconds;
                Display.UpdateMNFminWidth(); //[2.10.3]MW0LGE update
            }
        }

        private int dsp_buf_phone_rx = 64;
        public int DSPBufPhoneRX
        {
            get { return dsp_buf_phone_rx; }
            set
            {
                dsp_buf_phone_rx = value;
                UpdateDSP();
            }
        }

        private int dsp_buf_phone_tx = 64;
        public int DSPBufPhoneTX
        {
            get { return dsp_buf_phone_tx; }
            set
            {
                dsp_buf_phone_tx = value;
                UpdateDSP();
            }
        }

        private int dsp_buf_fm_rx = 256;
        public int DSPBufFMRX
        {
            get { return dsp_buf_fm_rx; }
            set
            {
                dsp_buf_fm_rx = value;
                UpdateDSP();
            }
        }

        private int dsp_buf_fm_tx = 128;
        public int DSPBufFMTX
        {
            get { return dsp_buf_fm_tx; }
            set
            {
                dsp_buf_fm_tx = value;
                UpdateDSP();
            }
        }

        private int dsp_buf_cw_rx = 64;
        public int DSPBufCWRX
        {
            get { return dsp_buf_cw_rx; }
            set
            {
                dsp_buf_cw_rx = value;
                UpdateDSP();
            }
        }

        private int dsp_buf_dig_rx = 64;
        public int DSPBufDigRX
        {
            get { return dsp_buf_dig_rx; }
            set
            {
                dsp_buf_dig_rx = value;
                UpdateDSP();
            }
        }

        private int dsp_buf_dig_tx = 64;

        private int dsp_filt_size_phone_rx = 4096;
        public int DSPFiltSizePhoneRX
        {
            get { return dsp_filt_size_phone_rx; }
            set
            {
                dsp_filt_size_phone_rx = value;
                UpdateDSP();
            }
        }

        private int dsp_filt_size_phone_tx = 4096;
        public int DSPFiltSizePhoneTX
        {
            get { return dsp_filt_size_phone_tx; }
            set
            {
                dsp_filt_size_phone_tx = value;
                UpdateDSP();
            }
        }

        private int dsp_filt_size_fm_rx = 4096;
        public int DSPFiltSizeFMRX
        {
            get { return dsp_filt_size_fm_rx; }
            set
            {
                dsp_filt_size_fm_rx = value;
                UpdateDSP();
            }
        }

        private int dsp_filt_size_fm_tx = 4096;
        public int DSPFiltSizeFMTX
        {
            get { return dsp_filt_size_fm_tx; }
            set
            {
                dsp_filt_size_fm_tx = value;
                UpdateDSP();
            }
        }

        private int dsp_filt_size_cw_rx = 4096;
        public int DSPFiltSizeCWRX
        {
            get { return dsp_filt_size_cw_rx; }
            set
            {
                dsp_filt_size_cw_rx = value;
                UpdateDSP();
            }
        }

        private int dsp_filt_size_dig_rx = 4096;
        public int DSPFiltSizeDigRX
        {
            get { return dsp_filt_size_dig_rx; }
            set
            {
                dsp_filt_size_dig_rx = value;
                UpdateDSP();
            }
        }

        private int dsp_filt_size_dig_tx = 4096;
        public int DSPFiltSizeDigTX
        {
            get { return dsp_filt_size_dig_tx; }
            set
            {
                dsp_filt_size_dig_tx = value;
                UpdateDSP();
            }
        }

        private DSPFilterType dsp_filt_type_phone_rx = DSPFilterType.Low_Latency;
        public DSPFilterType DSPFiltTypePhoneRX
        {
            get { return dsp_filt_type_phone_rx; }
            set
            {
                dsp_filt_type_phone_rx = value;
                UpdateDSP();
            }
        }

        private DSPFilterType dsp_filt_type_phone_tx = DSPFilterType.Low_Latency;
        public DSPFilterType DSPFiltTypePhoneTX
        {
            get { return dsp_filt_type_phone_tx; }
            set
            {
                dsp_filt_type_phone_tx = value;
                UpdateDSP();
            }
        }

        private DSPFilterType dsp_filt_type_fm_rx = DSPFilterType.Low_Latency;
        public DSPFilterType DSPFiltTypeFMRX
        {
            get { return dsp_filt_type_fm_rx; }
            set
            {
                dsp_filt_type_fm_rx = value;
                UpdateDSP();
            }
        }

        private DSPFilterType dsp_filt_type_fm_tx = DSPFilterType.Low_Latency;
        public DSPFilterType DSPFiltTypeFMTX
        {
            get { return dsp_filt_type_fm_tx; }
            set
            {
                dsp_filt_type_fm_tx = value;
                UpdateDSP();
            }
        }

        private DSPFilterType dsp_filt_type_cw_rx = DSPFilterType.Low_Latency;
        public DSPFilterType DSPFiltTypeCWRX
        {
            get { return dsp_filt_type_cw_rx; }
            set
            {
                dsp_filt_type_cw_rx = value;
                UpdateDSP();
            }
        }

        private DSPFilterType dsp_filt_type_dig_rx = DSPFilterType.Low_Latency;
        public DSPFilterType DSPFiltTypeDigRX
        {
            get { return dsp_filt_type_dig_rx; }
            set
            {
                dsp_filt_type_dig_rx = value;
                UpdateDSP();
            }
        }

        private DSPFilterType dsp_filt_type_dig_tx = DSPFilterType.Low_Latency;
        public DSPFilterType DSPFiltTypeDigTX
        {
            get { return dsp_filt_type_dig_tx; }
            set
            {
                dsp_filt_type_dig_tx = value;
                UpdateDSP();
            }
        }

        public void SetupRX2Band(Band b, bool is_for_rx1_vfo_b = false)
        {
            string sBand = BandToString(b);
            SetupRX2Band(sBand, is_for_rx1_vfo_b);
        }
        public void SetupRX2Band(string sBand, bool is_for_rx1_vfo_b = false)
        {
            //[2.10.3.6]MW0LGE no band change on TX fix
            if (MOX && is_for_rx1_vfo_b && VFOBTX && !rx2_enabled) return;
            if (MOX && VFOBTX && rx2_enabled) return;

            //[2.10.3.6]MW0LGE added frequency_only so that it can be used as a way to select a band for rx1, vfob, in the vfo display system
            //MW0LGE_21d BandStack2 ineresting... applies to rx2
            BandStackFilter bsf = BandStackManager.GetFilter(BandStackManager.StringToBand(sBand));
            if (bsf != null)
            {
                BandStackEntry bse = bsf.First();

                if (bse == null)
                {
                    bse = bsf.LastVisited.Copy(); // in case of nothing in the filter (ie deleted everything, or no entries)
                    // at least set it to the band we want
                    bse.Band = BandStackManager.StringToBand(sBand);
                }

                if (bse != null)
                {
                    if (!is_for_rx1_vfo_b)
                    {
                        RX2DSPMode = bse.Mode;
                        RX2Filter = bse.Filter;
                    }
                    VFOBFreq = bse.Frequency;
                }
            }
        }

        private void comboRX2Band_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            // MW0LGE reinstated and moved block to another function to be called from here, and via CAT
            if (comboRX2Band.Focused)
            {
                SetupRX2Band(comboRX2Band.Text);

                btnHidden.Focus();
            }
        }

        private bool m_bIncludeWindowBorders = false;
        public bool IncludeWindowBorders {
            get { return m_bIncludeWindowBorders; }
            set {
                m_bIncludeWindowBorders = value;
                includeBordersToolStripMenuItem.Checked = m_bIncludeWindowBorders;
                updateResolutionStatusBarText();
            }
        }

        private Size m_szDropShadowSize = new Size(-1, -1); // values of -1's causes DropShadowSize property to init
        private FormWindowState m_enOldWindowState;
        private Size DropShadowSize
        {
            get {
                if (((this.WindowState != m_enOldWindowState) || (m_szDropShadowSize.Width == -1 && m_szDropShadowSize.Height == -1)) && this.Visible)
                {
                    m_enOldWindowState = this.WindowState;
                    m_szDropShadowSize = Common.DropShadowSize(this);
                }

                return m_szDropShadowSize;
            }
        }
        private void updateResolutionStatusBarText()
        {
            if (m_bIncludeWindowBorders)
            {
                Size sz = this.Size - DropShadowSize; // Form.Size now includes drop shadow size, this gets removed so we see values we expect in the statusbar
                toolStripDropDownButton_ScreenSize.Text = sz.Width.ToString() + " x " + sz.Height.ToString();
            }
            else
            {
                toolStripDropDownButton_ScreenSize.Text = this.ClientSize.Width.ToString() + " x " + this.ClientSize.Height.ToString();
            }
        }

        int dpi = 0;
        SizeF base_size = new SizeF(0, 0);
        bool dpi_resize_done = false;

        private FormWindowState _old_window_state = FormWindowState.Normal;
        private void Console_Resize(object sender, System.EventArgs e)
        {
            resizeBackgroundImage();

            if (this.WindowState != _old_window_state)
            {               
                WindowStateChangedHandlers?.Invoke(this.WindowState);
                _old_window_state = this.WindowState;
            }
            updateResolutionStatusBarText();

            if (this.WindowState == FormWindowState.Minimized)
                return;
            //MW0LGE_21k5 pause_DisplayThread = true;

            if (dpi == 0)
                dpi = (int)picDisplay.CreateGraphics().DpiX;
            if (dpi > 96 && !dpi_resize_done)
            {
                if (base_size.Width == 0)
                    base_size = this.AutoScaleDimensions;

                if (this.AutoScaleDimensions != base_size)
                    dpi_resize_done = true;
                else return;
            }

            if (this.Width < console_basis_size.Width && !this.collapsedDisplay)
            {
                this.Width = console_basis_size.Width;
                return;
            }

            //MW0LGE
            //modified so that window can not be shrunk too much so that rx2 becomes hidden
            //this is all ignored if collapseddisplay is shown
            //we dont need to do anything special for collapsed view as console_basis_size is modified by RX2 button
            if (!this.collapsedDisplay)
            {
                if (this.Height < console_basis_size.Height)
                {
                    this.Height = console_basis_size.Height;
                    return;
                }
            }

            h_delta = this.Width - console_basis_size.Width;                //MW0LGE_[2.9.0.7] might actually want to set the globals
            v_delta = Math.Max(this.Height - console_basis_size.Height, 0);

            if (!IsSetupFormNull)
            {
                if (this.collapsedDisplay)
                {
                    this.SetupForm.CollapsedWidth = this.Width;
                    this.SetupForm.CollapsedHeight = this.Height;
                }
                else
                {
                    if (this.SetupForm.CollapsedWidth == 0)
                        this.SetupForm.CollapsedWidth = console_basis_size.Width;
                    if (this.SetupForm.CollapsedHeight == 0)
                        this.SetupForm.CollapsedHeight =
                            (current_hpsdr_model == HPSDRModel.HPSDR || current_hpsdr_model == HPSDRModel.HERMES) ?
                                console_basis_size.Height - (panelRX2Filter.Height + 8) :
                                console_basis_size.Height;
                }
            }

            ResizeConsole(h_delta, v_delta);
        }

        private void comboRX2AGC_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            if (IsSetupFormNull) return;
            radio.GetDSPRX(1, 0).RXAGCMode = (AGCMode)comboRX2AGC.SelectedIndex;
            lblRX2AGCLabel.Text = "AGC: " + comboRX2AGC.Text;

            m_RX2agcMode = (AGCMode)comboRX2AGC.SelectedIndex; // MW0LGE

            switch ((AGCMode)comboRX2AGC.SelectedIndex)
            {
                case AGCMode.LONG:
                    SetupForm.CustomRX2AGCEnabled = false;
                    SetupForm.tbDSPAGCRX2HangThreshold.Enabled = true;

                    radio.GetDSPRX(1, 0).RXAGCHang = 2000;
                    radio.GetDSPRX(1, 0).RXAGCDecay = 2000;
                    SetupForm.AGCRX2HangThreshold = SetupForm.tbDSPAGCRX2HangThreshold.Value;
                    toolTip1.SetToolTip(comboRX2AGC, "Automatic Gain Control Mode Setting:\n" +
                        "Long (Attack 2ms, Hang 2000ms, Decay 2000ms)");

                    break;
                case AGCMode.SLOW:
                    SetupForm.CustomRX2AGCEnabled = false;
                    SetupForm.tbDSPAGCRX2HangThreshold.Enabled = true;

                    radio.GetDSPRX(1, 0).RXAGCHang = 1000;
                    radio.GetDSPRX(1, 0).RXAGCDecay = 500;
                    SetupForm.AGCRX2HangThreshold = SetupForm.tbDSPAGCRX2HangThreshold.Value;
                    toolTip1.SetToolTip(comboRX2AGC, "Automatic Gain Control Mode Setting:\n" +
                        "Slow (Attack 2ms, Hang 1000ms, Decay 500ms)");

                    break;
                case AGCMode.MED:
                    SetupForm.CustomRX2AGCEnabled = false;
                    SetupForm.tbDSPAGCRX2HangThreshold.Enabled = false;

                    radio.GetDSPRX(1, 0).RXAGCHang = 0;
                    radio.GetDSPRX(1, 0).RXAGCDecay = 250;
                    toolTip1.SetToolTip(comboRX2AGC, "Automatic Gain Control Mode Setting:\n" +
                        "Medium (Attack 2ms, Hang OFF, Decay 250ms)");

                    break;
                case AGCMode.FAST:
                    SetupForm.CustomRX2AGCEnabled = false;
                    SetupForm.tbDSPAGCRX2HangThreshold.Enabled = false;

                    radio.GetDSPRX(1, 0).RXAGCHang = 0;
                    radio.GetDSPRX(1, 0).RXAGCDecay = 50;
                    toolTip1.SetToolTip(comboRX2AGC, "Automatic Gain Control Mode Setting:\n" +
                       "Fast (Attack 2ms, Hang OFF, Decay 50ms)");

                    break;
                case AGCMode.CUSTOM:
                    SetupForm.CustomRX2AGCEnabled = true;

                    SetupForm.tbDSPAGCRX2HangThreshold.Enabled = true;
                    SetupForm.AGCRX2HangThreshold = SetupForm.tbDSPAGCRX2HangThreshold.Value;

                    toolTip1.SetToolTip(comboRX2AGC, "Automatic Gain Control Mode Setting:\n" +
                        "Custom - Set specifics in Setup Form -> DSP -> AGC/ALC");

                    break;
                case AGCMode.FIXD:
                    SetupForm.CustomRX2AGCEnabled = false;
                    toolTip1.SetToolTip(comboAGC, "Automatic Gain Control Mode Setting:\n" +
                        "Fixed - Set gain with AGC-T control above");

                    break;
            }

            // set RF control to Max or Fixed gain depending on mode
            switch ((AGCMode)comboRX2AGC.SelectedIndex)
            {
                case AGCMode.FIXD:
                    RX2RF = SetupForm.AGCRX2FixedGain;
                    break;
                default:
                    RX2RF = SetupForm.AGCRX2MaxGain;
                    break;
            }
        }

        private bool _old_vfo_sync_state = false;
        private void chkVFOSync_CheckedChanged(object sender, System.EventArgs e)
        {
            if (chkVFOSync.Checked)
            {
                chkVFOSync.BackColor = button_selected_color;
                lblVFOSyncLabel.BackColor = System.Drawing.Color.Blue;

                //wd5y
                lblVFOSyncLabel.Size = new Size(68, 17);
                //wd5y

                if (m_bLinkCTUNonVFOSync)
                {
                    chkX2TR.Checked = chkFWCATU.Checked;
                }

                txtVFOAFreq_LostFocus(this, EventArgs.Empty);
            }
            else
            {
                chkVFOSync.BackColor = SystemColors.Control;
                lblVFOSyncLabel.BackColor = System.Drawing.Color.Transparent;

                //wd5y
                lblVFOSyncLabel.Size = new Size(68, 17);
                //wd5y
            }

            if (diversityForm != null) //[2.10.3.5]MW0LGE
                diversityForm.VFOSync = chkVFOSync.Checked;

            AndromedaIndicatorCheck(EIndicatorActions.eINVFOSync, false, chkVFOSync.Checked);

            if(chkVFOSync.Checked != _old_vfo_sync_state)
            {
                VFOSyncChangedHandlers?.Invoke(1, _old_vfo_sync_state, chkVFOSync.Checked);
                VFOSyncChangedHandlers?.Invoke(2, _old_vfo_sync_state, chkVFOSync.Checked);

                _old_vfo_sync_state = chkVFOSync.Checked;
            }
        }

        private bool mute_rx1_on_vfob_tx = true;
        public bool MuteRX1OnVFOBTX
        {
            get { return mute_rx1_on_vfob_tx; }
            set
            {
                mute_rx1_on_vfob_tx = value;
                if (chkVFOBTX.Checked)
                    Audio.FullDuplex = !value;
            }
        }

        private bool mute_rx2_on_vfoa_tx = true;
        public bool MuteRX2OnVFOATX
        {
            get { return mute_rx2_on_vfoa_tx; }
            set
            {
                mute_rx2_on_vfoa_tx = value;
                if (chkVFOATX.Checked)
                    Audio.RX2AutoMuteTX = value;
            }
        }

        private bool blank_rx1_on_vfob_tx = false;
        public bool BlankRX1OnVFOBTX
        {
            get { return blank_rx1_on_vfob_tx; }
            set
            {
                blank_rx1_on_vfob_tx = value;
                if (chkVFOBTX.Checked)
                    Audio.RX1BlankDisplayTX = value;
            }
        }
        private bool blank_rx2_on_vfoa_tx = false;
        public bool BlankRX2OnVFOATX
        {
            get { return blank_rx2_on_vfoa_tx; }
            set
            {
                blank_rx2_on_vfoa_tx = value;
                if (chkVFOATX.Checked)
                    Audio.RX2BlankDisplayTX = value;
            }
        }

        public int DSPBufDigTX
        {
            get { return dsp_buf_dig_tx; }
            set
            {
                dsp_buf_dig_tx = value;
                UpdateDSP();
            }
        }

        private void chkVFOATX_CheckedChanged(object sender, System.EventArgs e)
        {
            if (chkVFOATX.Focused && !chkVFOATX.Checked) chkVFOATX.Checked = true;
            if (chkVFOATX.Checked)
            {
                //psform.RXrcvr = 1;
                if (chkVFOBTX.Checked) chkVFOBTX.Checked = false;
                swap_vfo_ab_tx = false;
                cmaster.SetTXVAC(0, 0);

                chkVFOATX.BackColor = Color.Red;
                txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                txtVFOBFreq_LostFocus(this, EventArgs.Empty);
                chkMON_CheckedChanged(this, EventArgs.Empty);

                if (chkVAC2.Checked && chkRX2.Checked)
                {
                    ptbVACRXGain.Value = vac_rx_gain;
                    ptbVACRXGain_Scroll(this, EventArgs.Empty);

                    ptbVACTXGain.Value = vac_tx_gain;
                    ptbVACTXGain_Scroll(this, EventArgs.Empty);

                    comboVACSampleRate.Text = vac_sample_rate;

                    chkVACStereo.Checked = vac_stereo;
                }
            }
            else
            {
                chkVFOATX.BackColor = SystemColors.Control;
            }

            if (m_bLastVFOATXsetting != chkVFOATX.Checked) btnHidden.Focus();

            // as a toggle between A and B then only send when checked
            if (chkVFOATX.Checked) VFOTXChangedHandlers?.Invoke(false, m_bLastVFOATXsetting, true);  // MW0LGE_21k9c

            m_bLastVFOATXsetting = chkVFOATX.Checked; // MW0LGE_21k9d rc3
        }

        private bool psstate = false;
        public bool PSState
        {
            get { return psstate; }
            set
            {
                psstate = value;
                txtVFOBFreq_LostFocus(this, EventArgs.Empty);
            }
        }

        //public void EnableDup()
        //{
        //    if (RX2PreampPresent || (!RX2PreampPresent && !PSState))//!psform.PSEnabled))
        //        chkRX2SR.Visible = true;
        //}

        //private void DisableDup()
        //{
        //    chkRX2SR.Checked = false;
        //    chkRX2SR.Visible = false;
        //}

        private void BroadcastVFOChange(string ndx)
        {
            if (IsSetupFormNull) return;

            Dictionary<string, bool> ken = SetupForm.KenwoodAISettings;

            string cmd = "ZZSW" + ndx + ";";

            if (ken["port1"]) sioPut(Siolisten, cmd);
            if (ken["port2"]) sioPut(Sio2listen, cmd);
            if (ken["port3"]) sioPut(Sio3listen, cmd);
            if (ken["port4"]) sioPut(Sio4listen, cmd);

            //if (Siolisten != null && Siolisten.SIO != null)
            //{
            //    try
            //    {
            //        if (Siolisten.SIO.IsOpen) Siolisten.SIO.put(cmd);
            //    }
            //    catch { }
            //}

            if (m_tcpCATServer != null && ken["tcp"])
                m_tcpCATServer.SendToClients(cmd);
        }

        private bool m_bLastVFOATXsetting = false;
        private bool m_bLastVFOBTXsetting = false;
        private void chkVFOBTX_CheckedChanged(object sender, System.EventArgs e)
        {
            if (chkVFOBTX.Focused && !chkVFOBTX.Checked) chkVFOBTX.Checked = true;
            Display.TXOnVFOB = chkVFOBTX.Checked;
            if (chkVFOBTX.Checked)
            {
                if (chkVFOATX.Checked) chkVFOATX.Checked = false;
                chkVFOBTX.BackColor = button_selected_color;

                if (VAC2onSplit && VAC2Enabled) cmaster.SetTXVAC(0, 1);
                else cmaster.SetTXVAC(0, 0);

                swap_vfo_ab_tx = true;

                //[2.10.1.0] MW0LGE moved here from below
                if (chkRX2.Checked == false && chkVFOBTX.Checked)    //in case of VU/XVTR-split error
                    chkVFOSplit.Checked = true;

                updateVFOFreqs(_mox); //[2.10.1.0] MW0LGE changed to std update function
                chkMON_CheckedChanged(this, EventArgs.Empty);

                if (chkRX2.Checked)
                {
                    Audio.RX2AutoMuteTX = true;
                    Audio.FullDuplex = !mute_rx1_on_vfob_tx;
                    Audio.TXDSPMode = rx2_dsp_mode;
                    radio.GetDSPTX(0).CurrentDSPMode = rx2_dsp_mode;

                    SetRX2Mode(rx2_dsp_mode);

                    if (chkVFOSplit.Checked && chkRX2.Checked)
                        chkVFOSplit.Checked = false;

                    if (chkRX2.Checked && chkVAC2.Checked)
                    {
                        ptbVACRXGain.Value = vac2_rx_gain;
                        ptbVACRXGain_Scroll(this, EventArgs.Empty);

                        ptbVACTXGain.Value = vac2_tx_gain;
                        ptbVACTXGain_Scroll(this, EventArgs.Empty);

                        comboVACSampleRate.Text = vac2_sample_rate;

                        chkVACStereo.Checked = vac2_stereo;
                    }
                }
            }
            else // button is unchecked
            {
                if (chkRX2.Checked)
                {
                    Audio.RX2AutoMuteTX = mute_rx2_on_vfoa_tx;
                    Audio.FullDuplex = false;

                    if (chkVAC2.Checked)
                    {
                        ptbVACRXGain.Value = vac_rx_gain;
                        ptbVACRXGain_Scroll(this, EventArgs.Empty);

                        ptbVACTXGain.Value = vac_tx_gain;
                        ptbVACTXGain_Scroll(this, EventArgs.Empty);

                        comboVACSampleRate.Text = vac_sample_rate;

                        chkVACStereo.Checked = vac_stereo;
                    }
                }

                if (chkRX2.Checked == false)
                    chkVFOSplit.Checked = false;
                Audio.TXDSPMode = rx1_dsp_mode;
                radio.GetDSPTX(0).CurrentDSPMode = rx1_dsp_mode;
                SetRX1Mode(rx1_dsp_mode);
            }

            Audio.VFOBTX = chkVFOBTX.Checked;
            Penny.getPenny().VFOBTX = chkVFOBTX.Checked; // MW0LGE_21j 

            if (m_bLastVFOBTXsetting != chkVFOBTX.Checked) btnHidden.Focus();

            // as only a toggle between B and A then send when checked
            if (chkVFOBTX.Checked) VFOTXChangedHandlers?.Invoke(true, m_bLastVFOBTXsetting, true); // MW0LGE_21k9c

            m_bLastVFOBTXsetting = chkVFOBTX.Checked; // MW0LGE_21k9d rc3
        }

        private void toolStripMenuItemRX1FilterConfigure_Click(object sender, EventArgs e)
        {
            if (rx1_dsp_mode == DSPMode.DRM || rx1_dsp_mode == DSPMode.SPEC) return;

            if (filterRX1Form == null || filterRX1Form.IsDisposed)
                filterRX1Form = new FilterForm(this, rx1_filters, false);

            filterRX1Form.DSPMode = rx1_dsp_mode;
            filterRX1Form.CurrentFilter = rx1_filter;
            filterRX1Form.Show();
            filterRX1Form.Focus();
        }

        private void toolStripMenuItemRX1FilterReset_Click(object sender, EventArgs e)
        {
            DialogResult dr = MessageBox.Show(
                "Are you sure you want to reset all RX1 custom filter settings to the default?",
                "Reset Filters?",
                MessageBoxButtons.YesNo,
                MessageBoxIcon.Question, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);

            if (dr == DialogResult.No) return;

            InitFilterPresets(rx1_filters);

            radFilter1.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.F1);
            radFilter2.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.F2);
            radFilter3.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.F3);
            radFilter4.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.F4);
            radFilter5.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.F5);
            radFilter6.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.F6);
            radFilter7.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.F7);
            radFilter8.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.F8);
            radFilter9.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.F9);
            radFilter10.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.F10);
            radFilterVar1.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.VAR1);
            radFilterVar2.Text = rx1_filters[(int)rx1_dsp_mode].GetName(Filter.VAR2);
            RX1Filter = rx1_filter;

            if (filterRX1Form != null && !filterRX1Form.IsDisposed)
            {
                filterRX1Form.DSPMode = rx1_dsp_mode;
            }

            // update all
            for (Filter f = Filter.F1; f <= Filter.VAR2; f++)
            {
                if(f != rx1_filter)
                    FilterChangedHandlers?.Invoke(1, f, f, RX1Band, rx1_filters[(int)rx1_dsp_mode].GetLow(f), rx1_filters[(int)rx1_dsp_mode].GetHigh(f), rx1_filters[(int)rx1_dsp_mode].GetName(f));
            }

            // set to where it should be
            FilterChangedHandlers?.Invoke(1, rx1_filter, rx1_filter, RX1Band, rx1_filters[(int)rx1_dsp_mode].GetLow(rx1_filter), rx1_filters[(int)rx1_dsp_mode].GetHigh(rx1_filter), rx1_filters[(int)rx1_dsp_mode].GetName(rx1_filter));
        }

        private void toolStripMenuItemRX2FilterConfigure_Click(object sender, EventArgs e)
        {
            if (rx2_dsp_mode == DSPMode.DRM || rx2_dsp_mode == DSPMode.SPEC) return;

            if (filterRX2Form == null || filterRX2Form.IsDisposed)
                filterRX2Form = new FilterForm(this, rx2_filters, true);

            filterRX2Form.DSPMode = rx2_dsp_mode;
            filterRX2Form.CurrentFilter = rx2_filter;
            filterRX2Form.Show();
            filterRX2Form.Focus();
        }

        private void toolStripNotchDelete_Click(Object sender, EventArgs e)
        {
        }

        private void toolStripNotchRemember_Click(object sender, EventArgs e)
        {
        }

        private void toolStripNotchNormal_Click(object sender, EventArgs e)
        {
        }

        private void toolStripNotchDeep_Click(object sender, EventArgs e)
        {
        }

        private void toolStripNotchVeryDeep_Click(object sender, EventArgs e)
        {
        }

        private void toolStripMenuItemRX2FilterReset_Click(object sender, EventArgs e)
        {
            DialogResult dr = MessageBox.Show(
                "Are you sure you want to reset all RX2 custom filter settings to the default?",
                "Reset Filters?",
                MessageBoxButtons.YesNo,
                MessageBoxIcon.Question, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);

            if (dr == DialogResult.No) return;

            InitFilterPresets(rx2_filters);

            radRX2Filter1.Text = rx2_filters[(int)rx2_dsp_mode].GetName(Filter.F1);
            radRX2Filter2.Text = rx2_filters[(int)rx2_dsp_mode].GetName(Filter.F2);
            radRX2Filter3.Text = rx2_filters[(int)rx2_dsp_mode].GetName(Filter.F3);
            radRX2Filter4.Text = rx2_filters[(int)rx2_dsp_mode].GetName(Filter.F4);
            radRX2Filter5.Text = rx2_filters[(int)rx2_dsp_mode].GetName(Filter.F5);
            radRX2Filter6.Text = rx2_filters[(int)rx2_dsp_mode].GetName(Filter.F6);
            radRX2Filter7.Text = rx2_filters[(int)rx2_dsp_mode].GetName(Filter.F7);
            radRX2FilterVar1.Text = rx2_filters[(int)rx2_dsp_mode].GetName(Filter.VAR1);
            radRX2FilterVar2.Text = rx2_filters[(int)rx2_dsp_mode].GetName(Filter.VAR2);
            RX2Filter = rx2_filter;

            if (filterRX2Form != null && !filterRX2Form.IsDisposed)
            {
                filterRX2Form.DSPMode = rx2_dsp_mode;
            }

            // update all
            for (Filter f = Filter.F1; f <= Filter.F7; f++)
            {
                if (f != rx2_filter)
                    FilterChangedHandlers?.Invoke(2, f, f, RX2Band, rx2_filters[(int)rx2_dsp_mode].GetLow(f), rx2_filters[(int)rx2_dsp_mode].GetHigh(f), rx2_filters[(int)rx2_dsp_mode].GetName(f));
            }
            for (Filter f = Filter.VAR1; f <= Filter.VAR2; f++)
            {
                if (f != rx2_filter)
                    FilterChangedHandlers?.Invoke(2, f, f, RX2Band, rx2_filters[(int)rx2_dsp_mode].GetLow(f), rx2_filters[(int)rx2_dsp_mode].GetHigh(f), rx2_filters[(int)rx2_dsp_mode].GetName(f));
            }

            // set to where it should be
            FilterChangedHandlers?.Invoke(2, rx2_filter, rx2_filter, RX2Band, rx2_filters[(int)rx2_dsp_mode].GetLow(rx2_filter), rx2_filters[(int)rx2_dsp_mode].GetHigh(rx2_filter), rx2_filters[(int)rx2_dsp_mode].GetName(rx2_filter));
        }

        private void chkTNF_CheckedChanged(object sender, EventArgs e)
        {
            Display.TNFActive = chkTNF.Checked;
            WDSP.RXANBPSetNotchesRun(WDSP.id(0, 0), chkTNF.Checked);
            WDSP.RXANBPSetNotchesRun(WDSP.id(0, 1), chkTNF.Checked);
            WDSP.RXANBPSetNotchesRun(WDSP.id(2, 0), chkTNF.Checked);
        }

        unsafe private bool changeNotchBW(MNotch notch, double newWidth)
        {
            if (SetupForm.NotchAdminBusy) return false; // cant change it if setup is adding/editing

            bool bRet = false;
            int nIndex = MNotchDB.IndexOf(notch);

            if (nIndex >= 0)
            {
                double fcenter, fwidth;
                int active;
                bool bActive;
                // just use channel 0,0 as all others have been set the same
                WDSP.RXANBPGetNotch(WDSP.id(0, 0), nIndex, &fcenter, &fwidth, &active);

                bActive = Convert.ToBoolean(active);

                WDSP.RXANBPEditNotch(WDSP.id(0, 0), nIndex, fcenter, newWidth, bActive);
                WDSP.RXANBPEditNotch(WDSP.id(0, 1), nIndex, fcenter, newWidth, bActive);
                WDSP.RXANBPEditNotch(WDSP.id(2, 0), nIndex, fcenter, newWidth, bActive);

                bool bSelected = (SelectedNotch != null);
                SetupForm.SaveNotchesToDatabase();
                SetupForm.UpdateNotchDisplay();

                // find the previously selected notch, which would have been lost due to savenotchestodb
                if (bSelected) SelectedNotch = MNotchDB.GetFirstNotchThatMatches(fcenter, newWidth, bActive);

                bRet = true;
            }

            return bRet;
        }

        unsafe private bool changeNotchCentreFrequency(MNotch notch, double newCentreFrequencyHz, int sourceRX)
        {
            //MW0LGE_21e XVTR
            double tmpMin = min_freq;
            double tmpMax = max_freq;

            if (sourceRX == 1 && rx1_xvtr_index >= 0)
            {
                int nXIndex = XVTRForm.XVTRFreq(newCentreFrequencyHz * 1e-6);
                if (nXIndex == rx1_xvtr_index)
                {
                    tmpMin = XVTRForm.GetBegin(nXIndex);
                    tmpMax = XVTRForm.GetEnd(nXIndex);
                }
            }
            else if (sourceRX == 2 && rx2_xvtr_index >= 0)
            {
                int nXIndex = XVTRForm.XVTRFreq(newCentreFrequencyHz * 1e-6);
                if (nXIndex == rx2_xvtr_index)
                {
                    tmpMin = XVTRForm.GetBegin(nXIndex);
                    tmpMax = XVTRForm.GetEnd(nXIndex);
                }
            }
            //

            //constrain
            if (newCentreFrequencyHz < tmpMin * 1e6 || newCentreFrequencyHz > tmpMax * 1e6) return false;

            if (SetupForm.NotchAdminBusy) return false; // cant change it if setup is adding/editing

            newCentreFrequencyHz = Math.Round(newCentreFrequencyHz);

            bool bRet = false;
            int nIndex = MNotchDB.IndexOf(notch);

            if (nIndex >= 0)
            {
                double fcenter, fwidth;
                int active;
                bool bActive;
                // just use channel 0,0 as all others have been set the same
                WDSP.RXANBPGetNotch(WDSP.id(0, 0), nIndex, &fcenter, &fwidth, &active);

                bActive = Convert.ToBoolean(active);

                WDSP.RXANBPEditNotch(WDSP.id(0, 0), nIndex, newCentreFrequencyHz, fwidth, bActive);
                WDSP.RXANBPEditNotch(WDSP.id(0, 1), nIndex, newCentreFrequencyHz, fwidth, bActive);
                WDSP.RXANBPEditNotch(WDSP.id(2, 0), nIndex, newCentreFrequencyHz, fwidth, bActive);

                bool bSelected = (SelectedNotch != null);
                SetupForm.SaveNotchesToDatabase();
                SetupForm.UpdateNotchDisplay();

                // find the previously selected notch, which would have been lost due to savenotchestodb
                //if (bSelected) SelectedNotch = MNotchDB.GetFirstNotchThatMatches(fcenter, fwidth, bActive); //MW0LGE [2.9.0.7] fix old bug, we need to find the notch for the updated freq
                if (bSelected) SelectedNotch = MNotchDB.GetFirstNotchThatMatches(newCentreFrequencyHz, fwidth, bActive);
            }

            return bRet;
        }

        unsafe private bool changeNotchActive(MNotch notch, bool bActive)
        {
            if (SetupForm.NotchAdminBusy) return false; // cant change it if setup is adding/editing

            bool bRet = false;
            int nIndex = MNotchDB.IndexOf(notch);

            if (nIndex >= 0)
            {
                double fcenter, fwidth;
                int active;
                // just use channel 0,0 as all others have been set the same
                WDSP.RXANBPGetNotch(WDSP.id(0, 0), nIndex, &fcenter, &fwidth, &active);

                WDSP.RXANBPEditNotch(WDSP.id(0, 0), nIndex, fcenter, fwidth, bActive);
                WDSP.RXANBPEditNotch(WDSP.id(0, 1), nIndex, fcenter, fwidth, bActive);
                WDSP.RXANBPEditNotch(WDSP.id(2, 0), nIndex, fcenter, fwidth, bActive);

                bool bSelected = (SelectedNotch != null);
                SetupForm.SaveNotchesToDatabase();
                SetupForm.UpdateNotchDisplay();

                // find the previously selected notch, which would have been lost due to savenotchestodb
                if (bSelected) SelectedNotch = MNotchDB.GetFirstNotchThatMatches(fcenter, fwidth, bActive);

                bRet = true;
            }

            return bRet;
        }

        unsafe private bool toggleNotchActive(MNotch notch)
        {
            if (SetupForm.NotchAdminBusy) return false; // cant change it if setup is adding/editing

            bool bRet = false;
            int nIndex = MNotchDB.IndexOf(notch);

            if (nIndex >= 0)
            {
                double fcenter, fwidth;
                int active;
                bool bActive;
                // just use channel 0,0 as all others have been set the same
                WDSP.RXANBPGetNotch(WDSP.id(0, 0), nIndex, &fcenter, &fwidth, &active);

                bActive = !Convert.ToBoolean(active); // invert state

                WDSP.RXANBPEditNotch(WDSP.id(0, 0), nIndex, fcenter, fwidth, bActive);
                WDSP.RXANBPEditNotch(WDSP.id(0, 1), nIndex, fcenter, fwidth, bActive);
                WDSP.RXANBPEditNotch(WDSP.id(2, 0), nIndex, fcenter, fwidth, bActive);

                bool bSelected = (SelectedNotch != null);
                SetupForm.SaveNotchesToDatabase();
                SetupForm.UpdateNotchDisplay();

                // find the previously selected notch, which would have been lost due to savenotchestodb
                if (bSelected) SelectedNotch = MNotchDB.GetFirstNotchThatMatches(fcenter, fwidth, bActive);

                bRet = true;
            }

            return bRet;
        }

        private bool removeNotch(MNotch notch)
        {
            if (SetupForm.NotchAdminBusy) return false; // cant remove it if setup is adding/editing

            bool bRet = false;
            int nIndex = MNotchDB.IndexOf(notch);

            if (nIndex >= 0)
            {
                WDSP.RXANBPDeleteNotch(WDSP.id(0, 0), nIndex);
                WDSP.RXANBPDeleteNotch(WDSP.id(0, 1), nIndex);
                WDSP.RXANBPDeleteNotch(WDSP.id(2, 0), nIndex);

                SetupForm.SaveNotchesToDatabase();
                SetupForm.UpdateNotchDisplay();

                bRet = true;
            }

            return bRet;
        }

        private void addNotch(double fFreq, int sourceRX)
        {
            //MW0LGE_21e XVTR
            double tmpMin = min_freq;
            double tmpMax = max_freq;

            if (sourceRX == 1 && rx1_xvtr_index >= 0)
            {
                int nXIndex = XVTRForm.XVTRFreq(fFreq * 1e-6);
                if (nXIndex == rx1_xvtr_index)
                {
                    tmpMin = XVTRForm.GetBegin(nXIndex);
                    tmpMax = XVTRForm.GetEnd(nXIndex);
                }
            }
            else if (sourceRX == 2 && rx2_xvtr_index >= 0)
            {
                int nXIndex = XVTRForm.XVTRFreq(fFreq * 1e-6);
                if (nXIndex == rx2_xvtr_index)
                {
                    tmpMin = XVTRForm.GetBegin(nXIndex);
                    tmpMax = XVTRForm.GetEnd(nXIndex);
                }
            }
            //

            //constrain
            if (fFreq < tmpMin * 1e6 || fFreq > tmpMax * 1e6) return;

            fFreq = Math.Round(fFreq); //MW0LGE_21d3

            // if there is a notch within 10hz ignore 
            if (MNotchDB.NotchNearFreq(fFreq, 10)) return;

            int nNumberofExistingNotches;
            unsafe
            {
                WDSP.RXANBPGetNumNotches(WDSP.id(0, 0), &nNumberofExistingNotches);
            }

            double fWidth = 200;
            if (Common.ShiftKeyDown) fWidth = 100;

            WDSP.RXANBPAddNotch(WDSP.id(0, 0), nNumberofExistingNotches, fFreq, fWidth, true);
            WDSP.RXANBPAddNotch(WDSP.id(0, 1), nNumberofExistingNotches, fFreq, fWidth, true);
            WDSP.RXANBPAddNotch(WDSP.id(2, 0), nNumberofExistingNotches, fFreq, fWidth, true);

            SetupForm.SaveNotchesToDatabase();
            SetupForm.UpdateNotchDisplay();
        }

        private int notchSidebandShift(int rx)
        {
            int lowHz;
            int highHz;
            int middle = 0;

            if (rx == 1)
            {
                lowHz = radio.GetDSPRX(0, 0).RXFilterLow;
                highHz = radio.GetDSPRX(0, 0).RXFilterHigh;
                middle = lowHz + ((highHz - lowHz) / 2);
                if (middle == 0) // probably symetric filter such as AM
                    middle = highHz / 2;
            }
            else if (rx == 2)
            {
                lowHz = radio.GetDSPRX(1, 0).RXFilterLow;
                highHz = radio.GetDSPRX(1, 0).RXFilterHigh;
                middle = lowHz + ((highHz - lowHz) / 2);
                if (middle == 0) // probably symetric filter such as AM
                    middle = highHz / 2;
            }

            return middle;
        }

        private void btnTNFAdd_Click(object sender, EventArgs e)
        {
            if (SetupForm.NotchAdminBusy) return; // dont add if using add/edit on the setup form

            double vfoHz = VFOAFreq * 1.0e6;
            if (RITOn) vfoHz += (double)RITValue * 1e-6; // check for RIT

            // shift into sideband
            vfoHz += notchSidebandShift(1); //MW0LGE_21k9rc4

            addNotch(vfoHz, 1);
        }

        private void ptbFMMic_Scroll(object sender, EventArgs e)
        {
            ptbFMMic.Minimum = mic_gain_min;
            ptbFMMic.Maximum = mic_gain_max;
            lblMicValFM.Text = ptbFMMic.Value.ToString();
            if (radio.GetDSPTX(0).CurrentDSPMode == DSPMode.FM)
            {
                double gain_db = (double)ptbFMMic.Value;

                if (mic_boost)
                {
                    toolTip1.SetToolTip(ptbFMMic, (ptbFMMic.Value + 20).ToString());
                }
                else if (line_in)
                {
                    toolTip1.SetToolTip(ptbFMMic, (ptbFMMic.Value + line_in_boost).ToString());
                }
                else
                {
                    toolTip1.SetToolTip(ptbFMMic, "");
                }
                Audio.MicPreamp = Math.Pow(10.0, gain_db / 20.0); // convert to scalar
            }

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbFMMic.Focus();
            }
        }

        private void chkFMCTCSS_CheckedChanged(object sender, EventArgs e)
        {
            CTCSSOn = chkFMCTCSS.Checked;
        }

        private void comboFMCTCSS_SelectedIndexChanged(object sender, EventArgs e)
        {
            bool ok = double.TryParse(comboFMCTCSS.Text, out double f);
            if (ok) CTCSSFreq = f;
        }

        private void InitCTCSS()
        {
            comboFMCTCSS.Items.Clear();
            foreach (double d in CTCSS_array)
                comboFMCTCSS.Items.Add(d.ToString("f1"));
        }

        private void InitMemoryFrontPanel()
        {
            comboFMMemory.DataSource = MemoryList.List;
            comboFMMemory.DisplayMember = "Name";
            comboFMMemory.ValueMember = "Name";
        }

        private void radFMDeviation2kHz_CheckedChanged(object sender, EventArgs e)
        {
            if (radFMDeviation2kHz.Checked)
            {
                radio.GetDSPTX(0).TXFMDeviation = 2500;
                radio.GetDSPRX(0, 0).RXFMDeviation = 2500;
                if (RX1DSPMode == DSPMode.FM)
                {
                    int halfBw = (int)(radio.GetDSPTX(0).TXFMDeviation + radio.GetDSPRX(0, 0).RXFMHighCut); //[2.10.3.4]MW0LGE
                    UpdateRX1Filters(-halfBw, halfBw);
                }
                if (RX2DSPMode == DSPMode.FM)
                {
                    int halfBw = (int)(radio.GetDSPTX(0).TXFMDeviation + radio.GetDSPRX(1, 0).RXFMHighCut); //[2.10.3.4]MW0LGE
                    UpdateRX2Filters(-halfBw, halfBw);
                }
                if (radio.GetDSPTX(0).CurrentDSPMode == DSPMode.FM)
                {
                    int halfBw = (int)(radio.GetDSPTX(0).TXFMDeviation + radio.GetDSPTX(0).TXFMHighCut); //[2.10.3.4]MW0LGE
                    SetTXFilters(DSPMode.FM, -halfBw, halfBw);
                }
            }
        }

        private void radFMDeviation5kHz_CheckedChanged(object sender, EventArgs e)
        {
            if (radFMDeviation5kHz.Checked)
            {
                radio.GetDSPTX(0).TXFMDeviation = 5000;
                radio.GetDSPRX(0, 0).RXFMDeviation = 5000;
                if (RX1DSPMode == DSPMode.FM)
                {
                    int halfBw = (int)(radio.GetDSPTX(0).TXFMDeviation + radio.GetDSPRX(0, 0).RXFMHighCut); //[2.10.3.4]MW0LGE
                    UpdateRX1Filters(-halfBw, halfBw);
                }
                if (RX2DSPMode == DSPMode.FM)
                {
                    int halfBw = (int)(radio.GetDSPTX(0).TXFMDeviation + radio.GetDSPRX(1, 0).RXFMHighCut); //[2.10.3.4]MW0LGE
                    UpdateRX2Filters(-halfBw, halfBw);
                }
                if (radio.GetDSPTX(0).CurrentDSPMode == DSPMode.FM)
                {
                    int halfBw = (int)(radio.GetDSPTX(0).TXFMDeviation + radio.GetDSPTX(0).TXFMHighCut); //[2.10.3.4]MW0LGE
                    SetTXFilters(DSPMode.FM , - halfBw, halfBw);
                }
            }
        }

        private void udFMOffset_ValueChanged(object sender, EventArgs e)
        {
            FMTXOffsetMHz = (double)udFMOffset.Value; //MW0LGE_21k9
        }

        private void chkFMTXHigh_CheckedChanged(object sender, EventArgs e)
        {
            if (chkFMTXHigh.Checked)
            {
                chkFMTXSimplex.Checked = false;
                chkFMTXLow.Checked = false;

                chkFMTXRev.Enabled = true;
                chkFMTXRev.Checked = false;

                CurrentFMTXMode = FMTXMode.High;
            }
        }

        private void chkFMTXSimplex_CheckedChanged(object sender, EventArgs e)
        {
            if (chkFMTXSimplex.Checked)
            {
                chkFMTXHigh.Checked = false;
                chkFMTXLow.Checked = false;

                chkFMTXRev.Enabled = false;
                chkFMTXRev.Checked = false;

                CurrentFMTXMode = FMTXMode.Simplex;
            }
        }

        private void chkFMTXLow_CheckedChanged(object sender, EventArgs e)
        {
            if (chkFMTXLow.Checked)
            {
                chkFMTXSimplex.Checked = false;
                chkFMTXHigh.Checked = false;

                chkFMTXRev.Enabled = true;
                chkFMTXRev.Checked = false;

                CurrentFMTXMode = FMTXMode.Low;
            }
        }

        private void chkFMTXRev_CheckedChanged(object sender, EventArgs e)
        {
            if (chkFMTXRev.Checked)
            {
                switch (current_fm_tx_mode)
                {
                    case FMTXMode.Low:
                        VFOAFreq -= (fm_tx_offset_mhz);
                        break;
                    case FMTXMode.High:
                        VFOAFreq += (fm_tx_offset_mhz);
                        break;
                }
            }
            else
            {
                switch (current_fm_tx_mode)
                {
                    case FMTXMode.Low:
                        VFOAFreq += (fm_tx_offset_mhz);
                        break;
                    case FMTXMode.High:
                        VFOAFreq -= (fm_tx_offset_mhz);
                        break;
                }
            }
        }

        private void chkFMMode_Click(object sender, EventArgs e)
        {
            switch (current_fm_tx_mode)
            {
                case FMTXMode.High:
                    chkFMTXHigh.Checked = true;
                    break;

                case FMTXMode.Simplex:
                    chkFMTXSimplex.Checked = true;
                    break;

                case FMTXMode.Low:
                    chkFMTXLow.Checked = true;
                    break;
            }
        }

        private bool ctcss_on = false;
        public bool CTCSSOn
        {
            get { return ctcss_on; }
            set
            {
                ctcss_on = value;
                if (chkFMCTCSS.Checked != value)
                    chkFMCTCSS.Checked = value;

                radio.GetDSPTX(0).CTCSSFlag = chkFMCTCSS.Checked;
            }
        }

        private double ctcss_freq = 100.0;
        public double CTCSSFreq
        {
            get { return ctcss_freq; }
            set
            {
                ctcss_freq = value;
                if (comboFMCTCSS.Text != ctcss_freq.ToString("f1"))
                {
                    comboFMCTCSS.Text = ctcss_freq.ToString("f1");
                    comboFMCTCSS_SelectedIndexChanged(this, EventArgs.Empty);
                }

                radio.GetDSPTX(0).CTCSSFreqHz = value;
            }
        }

        private void mnuMemory_Click(object sender, EventArgs e)
        {
            if (memoryForm == null || memoryForm.IsDisposed)
                memoryForm = new MemoryForm(this);
            memoryForm.Show();
            memoryForm.Focus();
        }

        public void RecallMemory(MemoryRecord record)
        {
            VFOAFreq = record.RXFreq;
            RX1DSPMode = record.DSPMode;

            TuneStepIndex = TuneStepLookup(record.TuneStep);

            if (record.DSPMode == DSPMode.FM)
            {
                CurrentFMTXMode = record.RPTR;
                FMTXOffsetMHz = record.RPTROffset;
                CTCSSOn = record.CTCSSOn;
                CTCSSFreq = record.CTCSSFreq;
                FMDeviation_Hz = record.Deviation;
            }
            else
            {
                RX1Filter = record.RXFilter;
                if (record.RXFilter == Filter.VAR1 || record.RXFilter == Filter.VAR2)
                    UpdateRX1Filters(record.RXFilterLow, record.RXFilterHigh);
            }

            PWR = record.Power;
            VFOSplit = record.Split;
            TXFreq = record.TXFreq; //MW0LGE_21k9 moved here after the split, and done always
            RX1AGCMode = record.AGCMode;
            if (RF != record.AGCT && AutoAGCRX1) AutoAGCRX1 = false; // turn off 'auto agc' only if different MW0LGE_21k8
            RF = record.AGCT;

            //wd5y
            AutoAGCRX1 = record.RX1AGCAUT;
            if (sliderForm != null)
            {
                sliderForm.chkAGCAut.Checked = AutoAGCRX1;
            }

            AutoAGCRX2 = record.RX2AGCAUT;
            if (sliderForm != null)
            {
                sliderForm.chkRX2AGCAut.Checked = AutoAGCRX2;
            }
            //wd5y
        }

        private void comboFMMemory_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (comboFMMemory.Items.Count == 0 || comboFMMemory.SelectedItem == null) return;
            MemoryRecord recordToRestore = new MemoryRecord((MemoryRecord)comboFMMemory.SelectedItem);
            if (!initializing)
                RecallMemory(recordToRestore);
        }

        private void btnFMMemoryUp_Click(object sender, EventArgs e)
        {
            if (comboFMMemory.Items.Count == 0 || comboFMMemory.SelectedItem == null) return;
            comboFMMemory.SelectedIndex = (comboFMMemory.SelectedIndex + 1) % comboFMMemory.Items.Count;
        }

        private void btnFMMemoryDown_Click(object sender, EventArgs e)
        {
            if (comboFMMemory.Items.Count == 0 || comboFMMemory.SelectedItem == null) return;
            comboFMMemory.SelectedIndex = (comboFMMemory.SelectedIndex - 1 + comboFMMemory.Items.Count) % comboFMMemory.Items.Count;
        }

        public void changeComboFMMemory(int index)
        {
            if (comboFMMemory.Items.Count == 0) return;
            if (index < 0 || index > comboFMMemory.Items.Count - 1) return;

            if (comboFMMemory.SelectedIndex != index)
            {
                comboFMMemory.SelectedIndex = index;
            }
            else // memory is already set in combobox, recall it
            {
                MemoryRecord recordToRestore = new MemoryRecord((MemoryRecord)comboFMMemory.SelectedItem);
                RecallMemory(recordToRestore);
            }
        }

        private void btnFMMemory_Click(object sender, EventArgs e)
        {
            if (memoryForm == null || memoryForm.IsDisposed)
                memoryForm = new MemoryForm(this);
            if (memoryForm.InvokeRequired)
            {
                memoryForm.Invoke(new MethodInvoker(() =>
                {
                    memoryForm.Show();
                    memoryForm.Focus();
                }));
            }
            else
            {
                memoryForm.Show();
                memoryForm.Focus();
            }
        }

        private void memoryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (memoryForm == null || memoryForm.IsDisposed)
                memoryForm = new MemoryForm(this);
            if (memoryForm.InvokeRequired)
            {
                memoryForm.Invoke(new MethodInvoker(() =>
                {
                    memoryForm.Show();
                    memoryForm.Focus();
                    SetFocusMaster(false);
                }));
            }
            else
            {
                memoryForm.Show();
                memoryForm.Focus();
                SetFocusMaster(false);
            }
        }

        private void waveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (WaveForm.IsDisposed)
                WaveForm = new WaveControl(this);
            if (WaveForm.InvokeRequired)
            {
                WaveForm.Invoke(new MethodInvoker(() =>
                {
                    WaveForm.Show();
                    WaveForm.Focus();
                }));
            }
            else
            {
                WaveForm.Show();
                WaveForm.Focus();
            }
        }

        private void CollapseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.collapsedDisplay)
            {
                this.ExpandDisplay(true);
            }
            else
            {
                this.CollapseDisplay(true);
            }
        }

        private void equalizerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (EQForm == null || EQForm.IsDisposed)
                EQForm = new EQForm(this);
            if (EQForm.InvokeRequired)
            {
                EQForm.Invoke(new MethodInvoker(() =>
                {
                    EQForm.Show();
                    EQForm.Focus();
                }));
            }
            else
            {
                EQForm.Show();
                EQForm.Focus();
            }
        }

        private void xVTRsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (XVTRForm == null || XVTRForm.IsDisposed)
                XVTRForm = new XVTRForm(this);
            if (XVTRForm.InvokeRequired)
            {
                XVTRForm.Invoke(new MethodInvoker(() =>
                {
                    XVTRForm.Show();
                    XVTRForm.Focus();
                }));
            }
            else
            {
                XVTRForm.Show();
                XVTRForm.Focus();
            }
        }

        private void cWXToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (CWXForm.ForceToCWmode)
            {
                if (rx1_dsp_mode == DSPMode.LSB)
                    RX1DSPMode = DSPMode.CWL;
                else if (rx1_dsp_mode == DSPMode.USB)
                    RX1DSPMode = DSPMode.CWU;

                //double check it happened
                if (rx1_dsp_mode != DSPMode.CWL &&
                    rx1_dsp_mode != DSPMode.CWU)
                {
                    MessageBox.Show("The radio must be in CWL or CWU mode in order to open the " +
                        "CWX Control Form.",
                        "CWX Error: Wrong Mode",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                    return;
                }
            }
            else
            {
                if (rx1_dsp_mode != DSPMode.CWL &&
                    rx1_dsp_mode != DSPMode.CWU)
                {
                    MessageBox.Show("Ideally the radio should be in CWL or CWU mode.",
                    "CWX : Mode warning",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                }
            }

            //	cw_key_mode = true;
            if (CWXForm.InvokeRequired)
            {
                CWXForm.Invoke(new MethodInvoker(() =>
                {
                    CWXForm.Show();
                    CWXForm.Focus();
                }));
            }
            else
            {
                CWXForm.Show();
                CWXForm.Focus();
            }
        }

        private String[] on_off_preamp_settings = { "0dB", "-20dB" };
        private String[] anan100d_preamp_settings = { "0dB", "-10dB", "-20dB", "-30dB" };
        private String[] alex_preamp_settings = { "-10db", "-20db", "-30db", "-40db", "-50db" };

        public void SetComboPreampForHPSDR()
        {
            comboPreamp.Items.Clear();

            switch (current_hpsdr_model)
            {
                case HPSDRModel.HPSDR:
                    comboPreamp.Items.AddRange(on_off_preamp_settings);
                    if (alexpresent)
                    {
                        comboPreamp.Items.AddRange(alex_preamp_settings);
                    }

                    break;
                case HPSDRModel.HERMES:
                    if (alexpresent)
                    {
                        comboPreamp.Items.AddRange(on_off_preamp_settings);
                        comboPreamp.Items.AddRange(alex_preamp_settings);
                    }
                    else
                        comboPreamp.Items.AddRange(anan100d_preamp_settings);

                    break;
                case HPSDRModel.ANAN10:
                case HPSDRModel.ANAN10E:
                    comboPreamp.Items.AddRange(anan100d_preamp_settings);
                    break;
                case HPSDRModel.ANAN100:
                case HPSDRModel.ANAN100B:
                    comboPreamp.Items.AddRange(on_off_preamp_settings);
                    comboPreamp.Items.AddRange(alex_preamp_settings);
                    break;
                case HPSDRModel.ANAN100D:
                case HPSDRModel.ANAN200D:
                    if (alexpresent)
                    {
                        comboPreamp.Items.AddRange(on_off_preamp_settings);
                        comboPreamp.Items.AddRange(alex_preamp_settings);
                    }
                    else
                        comboPreamp.Items.AddRange(anan100d_preamp_settings);
                    break;
                case HPSDRModel.ANAN7000D:
                case HPSDRModel.ANAN8000D:
                case HPSDRModel.ORIONMKII:
                case HPSDRModel.ANAN_G2:
                case HPSDRModel.ANAN_G2_1K:
                    comboPreamp.Items.AddRange(anan100d_preamp_settings);
                    break;
            }

            comboRX2Preamp.Items.Clear();
            if (current_hpsdr_model == HPSDRModel.ANAN100D || current_hpsdr_model == HPSDRModel.ANAN200D || current_hpsdr_model == HPSDRModel.ANAN7000D ||
                current_hpsdr_model == HPSDRModel.ANAN8000D || current_hpsdr_model == HPSDRModel.ORIONMKII ||
                current_hpsdr_model == HPSDRModel.ANAN_G2 || current_hpsdr_model == HPSDRModel.ANAN_G2_1K)
                comboRX2Preamp.Items.AddRange(anan100d_preamp_settings);
            else
                comboRX2Preamp.Items.AddRange(on_off_preamp_settings);

            RX2PreampMode = rx2_preamp_by_band[(int)rx2_band];
            comboRX2Preamp_SelectedIndexChanged(this, EventArgs.Empty);
            RX2AttenuatorData = getRX2stepAttenuatorForBand(rx2_band);

            RX1PreampMode = rx1_preamp_by_band[(int)rx1_band];
            comboPreamp_SelectedIndexChanged(this, EventArgs.Empty);
            RX1AttenuatorData = getRX1stepAttenuatorForBand(rx1_band);
        }

        private string[] lineinboost = new string[32];
        private bool lineinarrayfill = false;
        private void MakeLineInList()
        {
            int k = 0;
            for (double i = -34.5; i <= 12; i += 1.5)
            {
                string s = i.ToString();
                lineinboost[k] = s;
                ++k;
            }
            lineinarrayfill = true;
        }

        public void SetMicXlr()
        {
            var v = mic_xlr ? 1 : 0;
            NetworkIO.SetMicXlr(v);
        }

        public void SetMicGain()
        {
            var v = mic_boost ? 1 : 0;
            NetworkIO.SetMicBoost(v);

            v = line_in ? 1 : 0;
            NetworkIO.SetLineIn(v);

            if (!lineinarrayfill) MakeLineInList();

            var lineboost = Array.IndexOf(lineinboost, line_in_boost.ToString());

            NetworkIO.SetLineBoost(lineboost);
        }

        private void BPF1ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!IsSetupFormNull) SetupForm.AlexHPFBypass = !BPF1ToolStripMenuItem.Checked;
        }

        private void BPF2ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!IsSetupFormNull) SetupForm.Alex2HPFBypass = !BPF2ToolStripMenuItem.Checked;
        }

        #region Collapsible Display

        ///////////////////////////////////////////////////////////////////////////////
        // Collapsible Display                                                        //
        ///////////////////////////////////////////////////////////////////////////////

        private bool show_rx1 = true;
        public bool ShowRX1
        {
            set { this.show_rx1 = value; }
            get { return show_rx1; }
        }

        private bool show_rx2 = false;
        public bool ShowRX2
        {
            set { this.show_rx2 = value; }
            get { return show_rx2; }
        }

        private Size expandedSize;

        private bool collapsedDisplay = false;
        public bool CollapsedDisplay
        {
            get { return this.collapsedDisplay; }
        }

        private bool m_bShowBandControls = true;
        public bool ShowBandControls
        {
            set
            {
                this.m_bShowBandControls = value;
                this.bandToolStripMenuItem.Visible = !m_bShowBandControls && IsCollapsedView; //[2.10.3.6]MW0LGE added && CollapsedDisplay. The item will be shown elsewhere if this property is changed whilst in expanded
                if (value == true)                      // if ON, turn andromeda menu button bar OFF
                    if (!IsSetupFormNull) SetupForm.chkShowAndromedaBar.Checked = false;

                if (this.CollapsedDisplay)
                    this.CollapseDisplay(true);
            }
        }

        private bool m_bShowModeControls = true;
        public bool ShowModeControls
        {
            set
            {
                this.m_bShowModeControls = value;
                this.modeToolStripMenuItem.Visible = !m_bShowModeControls && IsCollapsedView; //[2.10.3.6]MW0LGE added && CollapsedDisplay. The item will be shown elsewhere if this property is changed whilst in expanded
                if (value == true)                      // if ON, turn andromeda menu button bar OFF
                    if (!IsSetupFormNull) SetupForm.chkShowAndromedaBar.Checked = false;

                if (this.CollapsedDisplay)
                    this.CollapseDisplay(true);
            }
        }

        private bool _showAndromedaTopControls = false;
        public bool ShowAndromedaTopControls
        {
            set
            {
                this._showAndromedaTopControls = value;

                //wd5y
                if (this.CollapsedDisplay)
                    this.CollapseDisplay(true);
                //wd5y

            }
            get { return this._showAndromedaTopControls; }
        }

        private bool _showAndromedaButtonBar = false;
        public bool ShowAndromedaButtonBar
        {
            set
            {
                this._showAndromedaButtonBar = value;
                //wd5y
                if (value == true)                  // if andromeda bar ON, turn mode and band OFF
                {
                    if (!IsSetupFormNull)
                    {
                        SetupForm.chkShowBandControls.Checked = false;
                        SetupForm.chkShowModeControls.Checked = false;
                    }
                }
                else
                    panelButtonBar.Hide(); //[2.10.3.6]MW0LGE added so that it will hide if the setup/menu option is changed
                if (this.CollapsedDisplay)
                    this.CollapseDisplay(true);
                //wd5y
            }
        }

        private bool _modeDependentSettingsFormAutoClosedWhenExpanded = false; // used to bring it back if we go back to collapsed
        private void ExpandDisplay(bool bSuspendDraw = true)
        {
            if (initializing) return;

            if (bSuspendDraw) SuspendDrawing(this);

            //wd5y
            this.collapseToolStripMenuItem.Text = "Pana-View";

            this.collapsedDisplay = false;
            rX2ToolStripMenuItem.Visible = false;
            this.filterToolStripMenuItem.Visible = false;
            this.TopControlstoolStripMenuItem.Visible = false;
            this.RXTXGainToolStripMenuItem.Visible = false;
            this.dSPToolStripMenuItem.Visible = false;
            this.bandToolStripMenuItem.Visible = false;
            this.modeToolStripMenuItem.Visible = false;
            this.BtnBartoolStripMenuItem.Visible = false;
            int minWidth = console_basis_size.Width;
            int minHeight = console_basis_size.Height;

            this.Size = this.expandedSize;
            this.MinimumSize = new Size(minWidth, minHeight);
            comboMeterRXMode_SelectedIndexChanged(this, EventArgs.Empty);
            comboRX2MeterMode_SelectedIndexChanged(this, EventArgs.Empty);
            comboMeterTXMode_SelectedIndexChanged(this, EventArgs.Empty);
            //wd5y

            //MW0LGE
            if (!m_bShowSmallModeFilterOnVFOs)
            {
                lblModeLabel.Hide();
                lblFilterLabel.Hide();
                lblRX2ModeLabel.Hide();
                lblRX2FilterLabel.Hide();
            }

            statusStripMain.Show();

            // added G8NJJ
            panelVFOLabels.Hide();
            panelAndromedaMisc.Hide();
            panelVFOALabels.Hide();
            panelVFOBLabels.Hide();
            panelMeterLabels.Hide();
            panelButtonBar.Hide();
            lblModeBigLabel.Hide();
            lblRX2ModeBigLabel.Hide();

            panelButtonBar.Hide();
            panelMeterLabels.Hide();
            panelVFOALabels.Hide();
            lblModeBigLabel.Hide();
            panelVFOBLabels.Hide();
            lblRX2ModeBigLabel.Hide();
            panelVFOLabels.Hide();
            panelAndromedaMisc.Hide();

            chkMUT.Show();
            radRX1Show.Hide();
            radRX2Show.Hide();
            panelPower.Show();
            panelRX2Power.Show();
            grpVFOA.Show();
            grpVFOB.Show();
            grpVFOBetween.Show();

            panelOptions.Show();
            panelSoundControls.Show();
            chkSquelch.Show();
            ptbSquelch.Show();
            picSquelch.Show();

            panelVFO.Show();
            panelDSP.Show();
            panelDisplay2.Show();
            panelMultiRX.Show();
            // G8NJJ
            panelModeSpecificCW.Parent = this;
            panelModeSpecificPhone.Parent = this;
            panelModeSpecificDigital.Parent = this;
            panelModeSpecificFM.Parent = this;

            panelFilter.Show();
            panelMode.Show();
            panelBandHF.Show();

            if (BandVHFSelected)
            {
                btnBandVHF_Click(btnBandVHF, EventArgs.Empty);
            }
            else if (BandGENSelected)
            {
                btnBandGEN_Click(radBandGEN, EventArgs.Empty);
            }
            else
            {
                btnBandHF_Click(btnBandHF, EventArgs.Empty);
            }

            //wd5y
            lblAF3.Hide();
            lblAF2.Hide();
            lblRF3.Hide();

            lblRF2.Hide();
            lblPWR2.Hide();
            lblTune2.Hide();
            //wd5y

            //MW0LGE
            if (m_bShowSmallModeFilterOnVFOs)
            {
                lblModeLabel.Show();
                lblFilterLabel.Show();
                lblRX2ModeLabel.Show();
                lblRX2FilterLabel.Show();
            }

            picMultiMeterDigital.Show();
            ptbAF.Show();
            ptbRF.Show();
            ptbPWR.Show();
            ptbRX1AF.Show();
            comboPreamp.Show();
            udRX1StepAttData.Show();
            comboAGC.Show();

            txtMultiText.Show();
            chkFWCATU.Show();
            //RX2 Controls
            chkRX2.Show();
            lblRX2Band.Show();
            comboRX2Band.Show();
            panelRX2Mixer.Show();
            lblRX2RF.Show();
            ptbRX2RF.Show();
            chkRX2Squelch.Show();
            ptbRX2Squelch.Show();
            picRX2Squelch.Show();
            panelRX2DSP.Show();
            panelRX2Display.Show();
            panelRX2Mode.Show();
            panelRX2Filter.Show();

            comboRX2AGC.Show();

            picRX2Meter.Show();
            panelRX2RF.Show();
            ptbRX2AF.Show();
            chkX2TR.Show();//MW0LGE
            chkRX2Mute.Show();//MW0LGE

            if (rx2_preamp_present)
            {
                comboRX2Preamp.Show();
                udRX2StepAttData.Show();
            }
            txtRX2Meter.Show();

            int h_delta = this.Width - console_basis_size.Width;
            int v_delta = Math.Max(this.Height - console_basis_size.Height, 0);

            grpVFOA.Location = new Point(gr_VFOA_basis_location.X + (h_delta / 4), gr_VFOA_basis_location.Y);
            grpVFOB.Location = new Point(gr_VFOB_basis_location.X + h_delta - (h_delta / 4), gr_VFOB_basis_location.Y);

            picMultiMeterDigital.Parent = grpMultimeter;

            picMultiMeterDigital.Location = pic_multi_meter_digital_basis;

            //MW0LGE -- uses pad radio between meter and vfoB
            grpMultimeterMenus.Location = new Point(gr_multi_meter_menus_basis.X + h_delta, gr_multi_meter_menus_basis.Y);

            int tmp = (grpVFOB.Location.X + grpVFOB.Size.Width + 8) + (int)(m_fMeterPadRatio * (grpMultimeterMenus.Left - (grpVFOB.Right + 8)));

            grpMultimeter.Location = new Point(tmp, gr_Multimeter_basis_location.Y);
            grpMultimeter.Size = new Size(grpMultimeterMenus.Right - grpMultimeter.Left, gr_multi_meter_size_basis.Height);

            txtMultiText.Size = new Size(grpMultimeter.Size.Width - (gr_multi_meter_size_basis.Width - txt_multi_text_size_basis.Width), txt_multi_text_size_basis.Height);
            picMultiMeterDigital.Size = new Size(grpMultimeter.Size.Width - (gr_multi_meter_size_basis.Width - pic_multi_meter_size_basis.Width), pic_multi_meter_size_basis.Height);
            //

            picRX2Meter.Parent = grpRX2Meter;
            picRX2Meter.Location = pic_rx2meter_basis;
            picRX2Meter.Size = pic_rx2meter_size_basis;

            lblRX2RF.Parent = panelRX2RF;
            lblRX2RF.Location = lbl_rx2_rf_basis;
            txtMultiText.Parent = grpMultimeter;
            txtMultiText.Location = txt_multi_text_basis;
            txtRX2Meter.Parent = grpRX2Meter;
            txtRX2Meter.Location = txt_rx2meter_basis;

            comboMeterRXMode.Parent = grpMultimeterMenus; //MW0LGE
            comboMeterRXMode.Location = combo_meter_rxmode_basis;
            comboRX2MeterMode.Location = combo_rx2meter_mode_basis;
            comboRX2MeterMode.Parent = grpRX2Meter;
            comboRX2MeterMode.Location = combo_rx2meter_mode_basis;

            comboMeterTXMode.Parent = grpMultimeterMenus; //MW0LGE
            comboMeterTXMode.Location = combo_meter_txmode_basis;

            chkPower.Parent = panelPower;
            chkPower.Location = chk_power_basis;
            chkRX2.Parent = panelPower;// panelRX2Power;
            chkRX2.Location = chk_rx2_enable_basis;
            chkMON.Parent = panelOptions;
            chkMON.Location = chk_mon_basis;
            chkMUT.Parent = panelDSP;
            chkMUT.Location = chk_mut_basis;
            chkRX2Mute.Parent = panelRX2DSP; // MW0LGE
            chkRX2Mute.Location = chk_rx2_mut_basis; // MW0LGE

            chkMOX.Parent = panelOptions;
            chkMOX.Location = chk_mox_basis;
            chkTUN.Parent = panelOptions;
            chkTUN.Location = chk_tun_basis;

            chkRX2SR.Parent = panelOptions;
            chkRX2SR.Location = chk_dup_basis;

            chkFWCATU.Parent = panelDisplay2;
            chkFWCATU.Location = chk_ctun_basis;

            chkX2TR.Parent = panelRX2Display;
            chkX2TR.Location = chk_x2tr_basis;

            chkFWCATUBypass.Parent = panelOptions;
            chkFWCATUBypass.Location = chk_ps2_basis;

            ptbAF.Parent = panelSoundControls;
            ptbAF.Location = tb_af_basis;
            ptbRX1AF.Parent = panelSoundControls;
            ptbRX1AF.Location = tb_rx1af_basis;
            ptbRX2AF.Parent = panelSoundControls;
            ptbRX2AF.Location = tb_rx2af_basis;
            ptbPWR.Parent = panelSoundControls;
            ptbPWR.Location = tb_pwr_basis;

            //wd5y
            ptbTune.Parent = panelSoundControls;
            ptbTune.Location = new Point(8, 246);
            grpVFOBetween.Location = new Point(grpVFOA.Location.X + (h_delta / 2) + 10, grpVFOA.Location.Y);
            //wd5y

            ptbRF.Parent = panelSoundControls;
            ptbRF.Location = tb_rf_basis;
            ptbRX2RF.Parent = panelRX2RF;
            ptbRX2RF.Location = tb_rx2_rf_basis;

            comboAGC.Parent = panelSoundControls;
            comboAGC.Location = combo_agc_basis;
            comboRX2AGC.Parent = panelRX2DSP;
            comboRX2AGC.Location = combo_rx2agc_basis;

            comboPreamp.Parent = panelSoundControls;
            comboPreamp.Location = combo_preamp_basis;
            udRX1StepAttData.Parent = panelSoundControls;
            udRX1StepAttData.Location = ud_rx1_step_att_present_data_basis;
            comboRX2Preamp.Parent = panelRX2Power;
            comboRX2Preamp.Location = combo_rx2_preamp_basis;
            udRX2StepAttData.Parent = panelRX2Power;
            udRX2StepAttData.Location = ud_rx2_step_att_present_data_basis;
            // G8NJJ
            chkRIT.Parent = panelVFO;
            chkRIT.Location = chk_RIT_basis;
            chkXIT.Parent = panelVFO;
            chkXIT.Location = chk_XIT_basis;
            udRIT.Parent = panelVFO;
            udRIT.Location = ud_RIT_basis;
            udXIT.Parent = panelVFO;
            udXIT.Location = ud_XIT_basis;
            btnRITReset.Parent = panelVFO;
            btnRITReset.Location = btn_RITReset_basis;
            btnXITReset.Parent = panelVFO;
            btnXITReset.Location = btn_XITReset_basis;
            lblRX2Band.Parent = panelRX2Power;
            comboRX2Band.Parent = panelRX2Power;
            lblRX2Band.Location = lbl_rx2_band_basis;
            comboRX2Band.Location = combo_rx2_band_basis;
            lblRX1MuteVFOA.Location = lbl_RX1_Mute_VFOA_basis;
            lblRX2MuteVFOB.Location = lbl_RX2_Mute_VFOB_basis;
            lblRX1APF.Location = lbl_RX1_APF_VFOA_basis;
            lblRX2APF.Location = lbl_RX2_APF_VFOB_basis;

            setupHiddenButton();//grpVFOA); //MW0LGE_21a

            //[2.10.3.6]MW0LGE now down below after the expanded flag change, as updateAttNudsCombos
            //if (rx1_step_att_present)
            //{
            //    udRX1StepAttData.BringToFront();
            //}
            //else
            //{
            //    comboPreamp.BringToFront();
            //}

            //if (rx2_step_att_present)
            //{
            //    udRX2StepAttData.BringToFront();
            //}
            //else
            //{
            //    comboRX2Preamp.BringToFront();
            //}

            // G8NJJ
            comboDisplayMode.Parent = panelDisplay2;
            comboDisplayMode.Location = combo_display_mode_basis;
            comboRX2DisplayMode.Parent = panelRX2Display;
            comboRX2DisplayMode.Location = combo_rx2_display_mode_basis;
            comboDisplayMode.Show();
            comboRX2DisplayMode.Show();

            panelDisplay.Location = gr_display_basis;

            if (LegacyItemController.ExpandSpectrumToRight)
                panelDisplay.Size = new Size(this.ClientSize.Width - gr_display_basis.X - 8, gr_display_size_basis.Height + v_delta);
            else
                panelDisplay.Size = new Size(gr_display_size_basis.Width + h_delta, gr_display_size_basis.Height + v_delta);

            panelDisplay2.Location = new Point(gr_display2_basis.X + (h_delta / 2), gr_display2_basis.Y + v_delta);
            panelDSP.Location = new Point(gr_dsp_basis.X + (h_delta / 2), gr_dsp_basis.Y + v_delta);

            // replace the zoom/pan controls, MW0LGE_21k9rc6
            //lblDisplayZoom.Location = new Point(lbl_display_zoom_basis.X + h_delta, lbl_display_zoom_basis.Y + v_delta);
            //ptbDisplayZoom.Location = new Point(tb_display_zoom_basis.X + h_delta, tb_display_zoom_basis.Y + v_delta);
            
            //[2.10.3.6]MW0LGE changed the above to cope with legacy control dynamic removal, now based off left of the ztb button
            ptbDisplayZoom.Location = new Point(btnDisplayZTB.Left - tb_display_zoom_size_basis.Width - 4, tb_display_zoom_basis.Y + v_delta);
            ptbDisplayZoom.Size = tb_display_zoom_size_basis;
            lblDisplayZoom.Location = new Point(ptbDisplayZoom.Location.X - lbl_display_zoom_size_basis.Width, lbl_display_zoom_basis.Y + v_delta);

            lblDisplayPan.Location = new Point(lbl_displaypan_basis.X, lbl_displaypan_basis.Y + v_delta);
            ptbDisplayPan.Location = new Point(tb_displaypan_basis.X, tb_displaypan_basis.Y + v_delta);
            ptbDisplayPan.Size = tb_displaypan_size_basis;
            btnDisplayPanCenter.Location = new Point(ptbDisplayPan.Location.X + ptbDisplayPan.Width + 4, ptbDisplayPan.Location.Y);
            //

            // :NOTE: Force update on pan control
            ptbDisplayPan.Value = ptbDisplayPan.Value;
            ptbDisplayPan_Scroll(this, EventArgs.Empty);

            // :NOTE: Force update on zoom control
            ptbDisplayZoom.Value = ptbDisplayZoom.Value;
            ptbDisplayZoom_Scroll(this, EventArgs.Empty);

            panelBandHF.Location = new Point(gr_BandHF_basis_location.X + h_delta, gr_BandHF_basis_location.Y + (v_delta / 4));
            panelBandHF.Size = gr_BandHF_basis_size;
            radBand160.Location = rad_band160_basis;
            radBand80.Location = rad_band80_basis;
            radBand60.Location = rad_band60_basis;
            radBand40.Location = rad_band40_basis;
            radBand30.Location = rad_band30_basis;
            radBand20.Location = rad_band20_basis;
            radBand17.Location = rad_band17_basis;
            radBand15.Location = rad_band15_basis;
            radBand12.Location = rad_band12_basis;
            radBand10.Location = rad_band10_basis;
            radBand6.Location = rad_band6_basis;
            radBand2.Location = rad_band2_basis;
            radBandWWV.Location = rad_bandwwv_basis;
            radBandGEN.Location = rad_bandgen_basis;
            btnBandVHF.Location = btn_bandVHF_basis;//w3sz

            panelBandGEN.Location = new Point(gr_BandGEN_basis_location.X + h_delta, gr_BandGEN_basis_location.Y + (v_delta / 4));
            panelBandGEN.Size = gr_BandGEN_basis_size;
            radBandGEN0.Location = rad_bandGEN0_basis;
            radBandGEN1.Location = rad_bandGEN1_basis;
            radBandGEN2.Location = rad_bandGEN2_basis;
            radBandGEN3.Location = rad_bandGEN3_basis;
            radBandGEN4.Location = rad_bandGEN4_basis;
            radBandGEN5.Location = rad_bandGEN5_basis;
            radBandGEN6.Location = rad_bandGEN6_basis;
            radBandGEN7.Location = rad_bandGEN7_basis;
            radBandGEN8.Location = rad_bandGEN8_basis;
            radBandGEN9.Location = rad_bandGEN9_basis;
            radBandGEN10.Location = rad_bandGEN10_basis;
            radBandGEN11.Location = rad_bandGEN11_basis;
            radBandGEN12.Location = rad_bandGEN12_basis;
            radBandGEN13.Location = rad_bandGEN13_basis;
            btnBandHF1.Location = btn_bandHF1_basis;

            panelBandVHF.Location = new Point(gr_BandVHF_basis_location.X + h_delta, gr_BandVHF_basis_location.Y + (v_delta / 4));
            panelBandVHF.Size = gr_BandVHF_basis_size;
            radBandVHF0.Location = rad_bandVHF0_basis;
            radBandVHF1.Location = rad_bandVHF1_basis;
            radBandVHF2.Location = rad_bandVHF2_basis;
            radBandVHF3.Location = rad_bandVHF3_basis;
            radBandVHF4.Location = rad_bandVHF4_basis;
            radBandVHF5.Location = rad_bandVHF5_basis;
            radBandVHF6.Location = rad_bandVHF6_basis;
            radBandVHF7.Location = rad_bandVHF7_basis;
            radBandVHF8.Location = rad_bandVHF8_basis;
            radBandVHF9.Location = rad_bandVHF9_basis;
            radBandVHF10.Location = rad_bandVHF10_basis;
            radBandVHF11.Location = rad_bandVHF11_basis;
            radBandVHF12.Location = rad_bandVHF12_basis;
            radBandVHF13.Location = rad_bandVHF13_basis;
            btnBandHF.Location = btn_bandHF_basis;//w3sz

            panelMode.Location = new Point(gr_Mode_basis_location.X + h_delta, gr_Mode_basis_location.Y + (v_delta / 2));
            panelMode.Size = gr_Mode_basis_size;

            panelRX2Mode.Location = new Point(gr_RX2Mode_basis_location.X + (int)(h_delta * 0.492), gr_RX2Mode_basis_location.Y + v_delta);
            panelRX2Mode.Size = gr_RX2Mode_basis_size;

            radModeLSB.Location = rad_mode_lsb_basis;
            radModeUSB.Location = rad_mode_usb_basis;
            radModeDSB.Location = rad_mode_dsb_basis;
            radModeCWL.Location = rad_mode_cwl_basis;
            radModeCWU.Location = rad_mode_cwu_basis;
            radModeFMN.Location = rad_mode_fmn_basis;
            radModeAM.Location = rad_mode_am_basis;
            radModeSAM.Location = rad_mode_sam_basis;
            radModeSPEC.Location = rad_mode_spec_basis;
            radModeDIGL.Location = rad_mode_digl_basis;
            radModeDIGU.Location = rad_mode_digu_basis;
            radModeDRM.Location = rad_mode_drm_basis;
            radRX2ModeLSB.Location = rad_RX2mode_lsb_basis;
            radRX2ModeUSB.Location = rad_RX2mode_usb_basis;
            radRX2ModeDSB.Location = rad_RX2mode_dsb_basis;
            radRX2ModeCWL.Location = rad_RX2mode_cwl_basis;
            radRX2ModeCWU.Location = rad_RX2mode_cwu_basis;
            radRX2ModeFMN.Location = rad_RX2mode_fmn_basis;
            radRX2ModeAM.Location = rad_RX2mode_am_basis;
            radRX2ModeSAM.Location = rad_RX2mode_sam_basis;
            radRX2ModeSPEC.Location = rad_RX2mode_spec_basis;
            radRX2ModeDIGL.Location = rad_RX2mode_digl_basis;
            radRX2ModeDIGU.Location = rad_RX2mode_digu_basis;
            radRX2ModeDRM.Location = rad_RX2mode_drm_basis;

            // [2.10.1.0] MW0LGE
            // check if the modedependant form was used + visible, if so we should close it as the panels will have been been moved back here
            // to the expanded view and the modedependant form will be empty
            if (modeDependentSettingsForm != null && !modeDependentSettingsForm.IsDisposed && modeDependentSettingsForm.Visible)
            {
                modeDependentSettingsForm.Close();
                _modeDependentSettingsFormAutoClosedWhenExpanded = true;
            }
            else
                _modeDependentSettingsFormAutoClosedWhenExpanded = false;
            //

            _isexpanded = true;
            _iscollapsed = false;

            updateAttNudsCombos(); //[2.10.3.6]MW0LGE

            updateLegacyMeterControls(true);// [2.10.1.0] MW0LGE

            SelectModeDependentPanel(); //MW0LGE [2.9.0.7] moved here
            setPAProfileLabelPos(); //[2.10.1.0] MW0LGE

            LegacyItemController.Update();

            if (bSuspendDraw) ResumeDrawing(this);

            this.Text = BasicTitleBar; //MW0LGE_21a moved here after expaned is true so that title text gets rebuild correctly
        }
        private void setPAProfileLabelPos()
        {
            int x = -1;
            int y = -1;

            if (!_iscollapsed && _isexpanded)
            {
                // use panelModeSpecificPhone even though might not be shown, it is still repositioned
                x = panelModeSpecificPhone.Left + 4;
                y = panelModeSpecificPhone.Bottom - lblPAProfile.Height - 6;
            }
            else if (_iscollapsed && !_isexpanded)
            {
                if (_showAndromedaTopControls)
                {
                    PictureBox pb = show_rx1 ? picMultiMeterDigital : picRX2Meter; // need to know which is shown
                    x = pb.Left - 558;
                    y = pb.Bottom;
                }
            }

            if (x > -1 && y > -1)
            {
                lblPAProfile.Location = new Point(x, y);
                lblPAProfile.Visible = true;
            }
            else
                lblPAProfile.Visible = false;
        }
        public Color StatusBarBackColour {
            get { return statusStripMain.BackColor; }
            set { statusStripMain.BackColor = value; }
        }
        public Color StatusBarTextColour {
            // use one to return the colour, as all will be the same
            get { return toolStripDropDownButton_ScreenSize.ForeColor; }
            set {
                foreach (ToolStripItem c in statusStripMain.Items)
                {
                    c.ForeColor = value;
                }
            }
        }

        //
        // modified G8NJJ to add alternate top/button controls for Andromeda
        // optimised for 1024x600 touchscreen display
        //
        public void CollapseDisplay(bool bSuspendDraw = true)
        {
            LegacyItemController.Update();

            if (bSuspendDraw) SuspendDrawing(this);

            // Save expanded display size
            //if (!this.collapsedDisplay) //[2.10.3.6]MW0LGE this is not set on startup, so use IsCollapsed instead
            if(!IsCollapsedView)
                this.expandedSize = this.Size;            

            this.collapseToolStripMenuItem.Text = "Gen-View";
            this.collapsedDisplay = true;
            this.rX2ToolStripMenuItem.Visible = true;
            this.dSPToolStripMenuItem.Visible = true;

            //wd5y
            this.TopControlstoolStripMenuItem.Visible = true;
            this.RXTXGainToolStripMenuItem.Visible = true;
            this.bandToolStripMenuItem.Visible = true;
            this.modeToolStripMenuItem.Visible = true;
            this.BtnBartoolStripMenuItem.Visible = true;
            
            this.filterToolStripMenuItem.Visible = true;
            
            int minWidth = 600;
            int minHeight = 210;
            this.Text = BasicTitleBar + "    " + TitleBarEncoder; //MW0LGE_22b

            //wd5y
            chkPower.Location = new Point(25, gr_VFOA_basis_location.Y + 2);
            chkPower.Parent = this;
            chkPower.BringToFront();

            if (this._showAndromedaTopControls)
            {
                minWidth = Math.Max(minWidth, console_basis_size.Width);
                if (show_rx1)
                    minHeight += grpVFOA.Height + 10;
                if (show_rx2)
                    minHeight += grpVFOB.Height + 10;
                comboMeterRXMode_SelectedIndexChanged(this, EventArgs.Empty);
                comboRX2MeterMode_SelectedIndexChanged(this, EventArgs.Empty);
                comboMeterTXMode_SelectedIndexChanged(this, EventArgs.Empty);
            }
            
            if (this.m_bShowBandControls)
                {
                    minWidth = Math.Max(minWidth, radBand160.Width * 14 + this.Width - this.ClientSize.Width);
                    minHeight += 5 + radBand160.Height;
                }

            if (this.m_bShowModeControls)
                {
                    minWidth = Math.Max(minWidth, radModeLSB.Width * 12 + this.Width - this.ClientSize.Width);
                    minHeight += 5 + radModeLSB.Height;
                }
            //wd5y

            this.MinimumSize = new Size(minWidth, minHeight);

            panelPower.Hide();
            panelRX2Power.Hide();
            panelOptions.Hide();
            panelSoundControls.Hide();
            chkSquelch.Hide();
            ptbSquelch.Hide();
            picSquelch.Hide();

            panelVFO.Hide();
            panelDSP.Hide();
            panelDisplay2.Hide();
            panelMultiRX.Hide();
       
            panelFilter.Hide();

            if (BandHFSelected)
            {
                panelBandVHF.Hide();
                panelBandGEN.Hide();
            }
            else if (BandVHFSelected)
            {
                panelBandHF.Hide();
                panelBandGEN.Hide();
            }
            else
            {
                panelBandHF.Hide();
                panelBandVHF.Hide();
            }

            grpVFOBetween.Hide();
            grpMultimeter.Hide();
            //RX2 controls
            lblRX2Band.Hide();
            comboRX2Band.Hide();
            panelRX2Mixer.Hide();
            lblRX2RF.Hide();
            chkRX2Squelch.Hide();
            ptbRX2Squelch.Hide();
            picRX2Squelch.Hide();
            panelRX2DSP.Hide();
            panelRX2Display.Hide();
            panelRX2Mode.Hide();
            panelRX2Filter.Hide();
            panelRX2RF.Hide();

            // G8NJJ: top display with both VFO controls
            if (this._showAndromedaTopControls)
            {
                //wd5y
                chkMUT.Hide();
                comboPreamp.Hide();
                comboRX2Preamp.Hide();
                udRX1StepAttData.Hide();
                udRX2StepAttData.Hide();
                chkX2TR.Hide();                     // RX2 CTUN
                chkFWCATU.Hide();                   // RX1 CTUN
                lblAF2.Hide();
                lblRF2.Hide();

                lblPWR2.Hide();
                lblTune2.Hide();

                ptbAF.Hide();
                ptbRX1AF.Hide();
                ptbPWR.Hide();
                ptbRX2AF.Hide();
                ptbRF.Hide();
                ptbRX2RF.Hide();
                comboAGC.Hide();
                comboRX2AGC.Hide();
                comboRX2Preamp.Hide();
                udRX2StepAttData.Hide();

                panelVFOALabels.Show();
                lblModeBigLabel.Show();
                panelVFOBLabels.Show();
                lblRX2ModeBigLabel.Show();
                panelVFOLabels.Show();
                panelAndromedaMisc.Show();
                lblModeLabel.Hide();
                lblFilterLabel.Hide();
                lblRX2ModeLabel.Hide();
                lblRX2FilterLabel.Hide();
                lblRX1MuteVFOA.BringToFront();
                lblRX2MuteVFOB.BringToFront();
                //
                // move radio controlling buttons to top left
                //
                chkPower.Parent = this;
                chkPower.Show();
                chkRX2.Parent = this;
                chkRX2.Show();
                radRX1Show.Parent = this;
                radRX1Show.Show();
                radRX2Show.Parent = this;
                radRX2Show.Show();
                chkMON.Parent = this;
                chkMON.Show();
                chkMOX.Parent = this;
                chkMOX.Show();
                chkTUN.Parent = this;
                chkTUN.Show();
                chkFWCATUBypass.Parent = this;                  // PS-A
                chkFWCATUBypass.Show();
                chkRX2SR.Parent = this;             // DUP
                chkRX2SR.Show();
                grpVFOA.Show();
                grpVFOB.Show();
                //wd5y

                //
                // show meter for RX1 or RX2 in centre, and panadapter type display controls
                //
                if (show_rx1)
                {
                    // G8NJJ
                    comboDisplayMode.Show();            // display mode eg panadapter
                    comboRX2DisplayMode.Hide();
                    picMultiMeterDigital.Parent = this;
                    txtMultiText.Parent = this;

                    if (current_meter_display_mode == MultiMeterDisplayMode.Original)
                    {
                        picMultiMeterDigital.SendToBack();
                    }
                    lblRXMeter.Text = comboMeterRXMode.Text;
                }
                else if (show_rx2)
                {
                    // G8NJJ
                    comboDisplayMode.Hide();
                    comboRX2DisplayMode.Show();
                    picRX2Meter.Parent = this;
                    txtRX2Meter.Parent = this;

                    if (current_meter_display_mode == MultiMeterDisplayMode.Original)
                    {
                        picRX2Meter.SendToBack();
                    }
                    lblRXMeter.Text = comboRX2MeterMode.Text;
                }
            }
            else
            {
                comboDisplayMode.Show();
                grpVFOBetween.Hide();
                lblAF2.Hide();
                lblRF2.Hide();
                lblPWR2.Hide();
                comboPreamp.Hide();//MW0LGE
            }

            //
            // G8NJJ: if Andromeda button bar, show its button panel
            //
            if (this._showAndromedaButtonBar)
            {
                panelBandVHF.Hide();
                panelBandHF.Hide();
                panelBandGEN.Hide();
                panelMode.Hide();
                panelButtonBar.Show();
            }
            else if (this.m_bShowBandControls)
            {
                panelButtonBar.Hide();
                if (_bands_VHF_selected)
                {
                    panelBandVHF.Show();
                }
                else if (_bands_HF_selected)
                {
                    panelBandHF.Show();
                }
                else
                {
                    panelBandGEN.Show();
                }

                lblRX2Band.Show();
                comboRX2Band.Show();
                lblRX2Band.Parent = this;
                comboRX2Band.Parent = this;
            }
            else
            {
                panelBandVHF.Hide();
                panelBandHF.Hide();
                panelBandGEN.Hide();
            }            

            if (this.m_bShowModeControls)
                panelMode.Show();
            else
                panelMode.Hide();

            updateLegacyMeterControls(false);// [2.10.1.0] MW0LGE

            // [2.10.1.0] MW0LGE
            if (_modeDependentSettingsFormAutoClosedWhenExpanded)
            {
                // we closed the modedependent form when we swiched back over to expanded, let us re-show it again by
                // simulating a button press
                ExecuteButtonAction(EButtonBarActions.eBBModeSettingsForm, 0);
            }
            //

            this.Size = new Size(SetupForm.CollapsedWidth,
                SetupForm.CollapsedHeight);

            RepositionControlsForCollapsedlDisplay();

            _iscollapsed = true;
            _isexpanded = false;

            SelectModeDependentPanel(); //MW0LGE [2.9.0.7] moved here
            setPAProfileLabelPos(); //[2.10.1.0] MW0LGE

            if (bSuspendDraw) ResumeDrawing(this);
        }


        // relocate the controls on the collapsed display
        private void RepositionControlsForCollapsedlDisplay()
        {
            int top = 0;
            int h_delta = this.Width - console_basis_size.Width;
            int v_delta = Math.Max(this.Height - console_basis_size.Height, 0);

            if (_showAndromedaTopControls)
            {
                top = grpVFOA.Height + 50;
                //
                // radio controlling buttons
                //
                chkPower.Location = new Point(10, gr_VFOA_basis_location.Y + 2);
                chkRX2.Location = new Point(chkPower.Location.X + chkPower.Width + 5, chkPower.Location.Y);

                chkMON.Location = new Point(chkPower.Location.X + 5, chkPower.Location.Y + chkPower.Height + 12);
                chkTUN.Location = new Point(chkMON.Location.X + chkMON.Width + 10, chkMON.Location.Y);

                chkMOX.Location = new Point(chkMON.Location.X, chkMON.Location.Y + chkMON.Height + 4);

                chkRX2SR.Location = new Point(chkMOX.Location.X, chkMOX.Location.Y + chkMOX.Height + 4);      //DUP
                chkFWCATUBypass.Location = new Point(chkTUN.Location.X, chkRX2SR.Location.Y);     // PS-A

                //wd5y
                grpVFOA.Parent = this;
                grpVFOA.Visible = true;
                grpVFOB.Parent = this;
                grpVFOB.Visible = true;
                grpVFOBetween.Parent = this;
                grpVFOBetween.Visible = true;
                lblAF2.Hide();
                ptbRX1AF.Hide();
                lblRF2.Hide();
                ptbRF.Hide();
                udRX1StepAttData.Hide();
                comboAGC.Hide();
                comboPreamp.Hide();
                lblAF3.Hide();
                ptbRX2AF.Hide();
                lblPWR2.Hide();
                lblTune2.Hide();
                ptbPWR.Hide();
                ptbTune.Hide();
                lblRF3.Hide();
                ptbRX2RF.Hide();
                comboRX2AGC.Hide();
                udRX2StepAttData.Hide();
                comboRX2Preamp.Hide();
                chkMUT.Hide();
                chkRX2Mute.Hide();
                //wd5y

                //
                // VFO A and VFO labels
                //
                panelVFOALabels.Location = new Point(chkFWCATUBypass.Location.X + chkFWCATUBypass.Width + 185, gr_VFOA_basis_location.Y);
                grpVFOA.Location = new Point(panelVFOALabels.Location.X, panelVFOALabels.Location.Y + panelVFOALabels.Height);
                panelVFOLabels.Location = new Point(panelVFOALabels.Location.X + panelVFOALabels.Width + 10, grpVFOA.Location.Y + grpVFOA.Height - panelVFOLabels.Height);
                radRX1Show.Location = new Point(panelVFOLabels.Location.X + panelVFOLabels.Width + 10, chkRX2.Location.Y + 4);
                radRX2Show.Location = new Point(radRX1Show.Location.X + radRX1Show.Width + 5, radRX1Show.Location.Y);
                lblRX1APF.Location = new Point(txtVFOABand.Location.X + 5, txtVFOABand.Location.Y + 2);

                //wd5y
                lblRX1MuteVFOA.Location = new Point(txtVFOABand.Location.X + 47, txtVFOABand.Location.Y - 53);
                //wd5y

                //
                // VFO B at right
                //
                panelVFOBLabels.Location = new Point(panelButtonBar.Width - 10 - grpVFOB.Width + 120, gr_VFOA_basis_location.Y);
                grpVFOB.Location = new Point(panelVFOBLabels.Location.X, panelVFOBLabels.Location.Y + panelVFOBLabels.Height);
                lblRX2APF.Location = new Point(txtVFOBBand.Location.X + 5, txtVFOBBand.Location.Y + 2);

                //wd5y
                lblRX2MuteVFOB.Location = new Point(txtVFOBBand.Location.X + 19, txtVFOBBand.Location.Y - 53);
                menuStrip1.Location = new Point(chkMNU.Location.X + chkMNU.Width - 10, chkMNU.Location.Y + 22 - menuStrip1.Height);
                if (_useLegacyMeters)
                {
                    this.MinimumSize = new Size(1622, 760);
                }
                else
                {
                    this.MinimumSize = new Size(1142, 760);
                }
                //wd5y

                panelAndromedaMisc.Location = new Point(panelVFOBLabels.Location.X - panelAndromedaMisc.Width - 10, panelVFOLabels.Location.Y);

                //
                // RX1 or RX2 meter (button dependent)                //

                //wd5y
                if (show_rx1)
                {
                    txtMultiText.Location = new Point(grpVFOB.Location.X + grpVFOB.Width + 103, grpVFOB.Location.Y + 5);
                    txtMultiText.Size = new Size(grpMultimeter.Size.Width - (gr_multi_meter_size_basis.Width - txt_multi_text_size_basis.Width), txt_multi_text_size_basis.Height);
                    picMultiMeterDigital.Location = new Point(grpVFOB.Location.X + grpVFOB.Width + 100, grpVFOB.Location.Y + 43);
                    picMultiMeterDigital.Size = new Size(grpMultimeter.Size.Width - (gr_multi_meter_size_basis.Width - pic_multi_meter_size_basis.Width), pic_multi_meter_size_basis.Height);
                    comboMeterRXMode.Location = new Point(txtMultiText.Location.X - comboMeterRXMode.Width - 5,
                        txtMultiText.Location.Y + 2);
                    comboMeterTXMode.Location = new Point(txtMultiText.Location.X + txtMultiText.Width + 5,
                        txtMultiText.Location.Y + 2);
                    panelMeterLabels.Location = new Point(txtMultiText.Location.X + 125, txtMultiText.Location.Y - panelMeterLabels.Height);
                    grpVFOBetween.Location = new Point(grpVFOB.Location.X - grpVFOB.Width - 23, grpVFOA.Location.Y - 18);

                    lblAF3.Hide();
                    ptbRX2AF.Hide();
                    lblRF3.Hide();
                    ptbRX2RF.Hide();
                    udRX2StepAttData.Hide();
                    comboRX2AGC.Hide();
                    comboRX2Preamp.Hide();
                    chkRX2Mute.Hide();

                    lblAF2.Parent = this;
                    lblAF2.Size = new Size(34, 23);
                    lblAF2.TextAlign = (ContentAlignment)HorizontalAlignment.Center;
                    lblAF2.Show();
                    ptbRX1AF.Parent = this;
                    ptbRX1AF.Show();
                    lblRF2.Parent = this;
                    lblRF2.Size = new Size(34, 23);
                    lblRF2.TextAlign = (ContentAlignment)HorizontalAlignment.Center;
                    lblRF2.Show();
                    ptbRF.Parent = this;
                    ptbRF.Show();
                    lblPWR2.Parent = this;
                    lblPWR2.Size = new Size(34, 23);
                    lblPWR2.TextAlign = (ContentAlignment)HorizontalAlignment.Center;
                    lblPWR2.Show();
                    ptbPWR.Parent = this;
                    ptbPWR.Show();
                    lblTune2.Parent = this;
                    lblTune2.Size = new Size(34, 23);
                    lblTune2.TextAlign = (ContentAlignment)HorizontalAlignment.Center;
                    lblTune2.Show();
                    ptbTune.Parent = this;
                    ptbTune.Show();
                    comboAGC.Parent = this;
                    comboAGC.Size = new Size(59, 23);
                    comboAGC.Show();
                    udRX1StepAttData.Parent = this;
                    udRX1StepAttData.Size = new Size(34, 23);
                    udRX1StepAttData.Show();
                    comboPreamp.Parent = this;
                    comboPreamp.Size = new Size(53, 23);
                    comboPreamp.Show();
                    chkMUT.Parent = this;
                    chkMUT.Show();

                    lblAF2.Location = new Point(chkPower.Location.X + chkPower.Width + 75, chkPower.Location.Y);
                    ptbRX1AF.Location = new Point(lblAF2.Location.X + lblAF2.Width + 2, lblAF2.Location.Y);
                    lblRF2.Location = new Point(lblAF2.Location.X, lblAF2.Location.Y + 27);
                    ptbRF.Location = new Point(lblRF2.Location.X + lblRF2.Width + 2, lblRF2.Location.Y);
                    lblPWR2.Location = new Point(lblRF2.Location.X, lblRF2.Location.Y + 27);
                    ptbPWR.Location = new Point(lblPWR2.Location.X + lblPWR2.Width + 2, lblPWR2.Location.Y);
                    lblTune2.Location = new Point(lblPWR2.Location.X, lblPWR2.Location.Y + 27);
                    ptbTune.Location = new Point(lblTune2.Location.X + lblTune2.Width + 2, lblTune2.Location.Y);
                    comboAGC.Location = new Point(lblTune2.Location.X - 8, lblTune2.Location.Y + 27);
                    udRX1StepAttData.Location = new Point(comboAGC.Location.X + comboAGC.Width + 5, comboAGC.Location.Y);
                    comboPreamp.Location = new Point(udRX1StepAttData.Location.X + udRX1StepAttData.Width + 5, udRX1StepAttData.Location.Y);
                    chkMUT.Location = new Point(chkMOX.Location.X + chkMOX.Width + 10, chkMOX.Location.Y);

                    if (_useLegacyMeters)
                    {
                        comboMeterRXMode.Parent = this;
                        comboMeterRXMode.Show();
                        comboMeterTXMode.Parent = this;
                        comboMeterTXMode.Show();
                        panelMeterLabels.Parent = this;
                        panelMeterLabels.Show();
                        this.MinimumSize = new Size(1622, 760);
                    }
                    else
                    {
                        comboMeterRXMode.Parent = this;
                        comboMeterRXMode.Hide();
                        comboMeterTXMode.Parent = this;
                        comboMeterTXMode.Hide();
                        panelMeterLabels.Parent = this;
                        panelMeterLabels.Hide();
                        this.MinimumSize = new Size(1142, 760);
                    }
                    
                    setupHiddenButton();// grpVFOA); //MW0LGE_21a
                }
                else if (show_rx2)
                {
                    txtRX2Meter.Location = new Point(grpVFOB.Location.X + grpVFOB.Width + 103, grpVFOB.Location.Y + 5);
                    txtRX2Meter.Size = new Size(grpMultimeter.Size.Width - (gr_multi_meter_size_basis.Width - txt_multi_text_size_basis.Width), txt_multi_text_size_basis.Height);
                    picRX2Meter.Location = new Point(grpVFOB.Location.X + grpVFOB.Width + 100, grpVFOB.Location.Y + 43);
                    picRX2Meter.Size = new Size(grpMultimeter.Size.Width - (gr_multi_meter_size_basis.Width - pic_multi_meter_size_basis.Width), pic_multi_meter_size_basis.Height);
                    comboRX2MeterMode.Location = new Point(txtRX2Meter.Location.X - comboRX2MeterMode.Width - 5,
                        txtRX2Meter.Location.Y + 2);
                    comboMeterTXMode.Location = new Point(txtRX2Meter.Location.X + txtRX2Meter.Width + 5,
                        txtRX2Meter.Location.Y + 2);
                    panelMeterLabels.Location = new Point(txtRX2Meter.Location.X + 125, txtRX2Meter.Location.Y - panelMeterLabels.Height);
                    grpVFOBetween.Location = new Point(grpVFOB.Location.X - grpVFOB.Width - 23, grpVFOA.Location.Y - 18);

                    lblAF2.Hide();
                    ptbRX1AF.Hide();
                    lblRF2.Hide();
                    ptbRF.Hide();
                    udRX1StepAttData.Hide();
                    comboAGC.Hide();
                    comboPreamp.Hide();
                    chkMUT.Hide();

                    lblAF3.Parent = this;
                    lblAF3.Size = new Size(34, 23);
                    lblAF3.TextAlign = (ContentAlignment)HorizontalAlignment.Center;
                    lblAF3.Show();
                    ptbRX2AF.Parent = this;
                    ptbRX2AF.Show();
                    lblRF3.Parent = this;
                    lblRF3.Size = new Size(34, 23);
                    lblRF3.TextAlign = (ContentAlignment)HorizontalAlignment.Center;
                    lblRF3.Show();
                    ptbRX2RF.Parent = this;
                    ptbRX2RF.Show();
                    lblPWR2.Parent = this;
                    lblPWR2.Size = new Size(34, 23);
                    lblPWR2.TextAlign = (ContentAlignment)HorizontalAlignment.Center;
                    lblPWR2.Show();
                    ptbPWR.Parent = this;
                    ptbPWR.Show();
                    lblTune2.Parent = this;
                    lblTune2.Size = new Size(34, 23);
                    lblTune2.TextAlign = (ContentAlignment)HorizontalAlignment.Center;
                    lblTune2.Show();
                    ptbTune.Parent = this;
                    ptbTune.Show();
                    comboRX2AGC.Parent = this;
                    comboRX2AGC.Size = new Size(59, 23);
                    comboRX2AGC.Show();
                    udRX2StepAttData.Parent = this;
                    udRX2StepAttData.Size = new Size(34, 23);
                    udRX2StepAttData.Show();
                    comboRX2Preamp.Parent = this;
                    comboRX2Preamp.Size = new Size(53, 23);
                    comboRX2Preamp.Show();
                    chkRX2Mute.Parent = this;
                    chkRX2Mute.Show();

                    lblAF3.Location = new Point(chkPower.Location.X + chkPower.Width + 75, chkPower.Location.Y);
                    ptbRX2AF.Location = new Point(lblAF3.Location.X + lblAF3.Width + 2, lblAF3.Location.Y);
                    lblRF3.Location = new Point(lblAF3.Location.X, lblAF3.Location.Y + 27);
                    ptbRX2RF.Location = new Point(lblRF3.Location.X + lblRF3.Width + 2, lblRF3.Location.Y);
                    lblPWR2.Location = new Point(lblRF3.Location.X, lblRF3.Location.Y + 27);
                    ptbPWR.Location = new Point(lblPWR2.Location.X + lblPWR2.Width + 2, lblPWR2.Location.Y);
                    lblTune2.Location = new Point(lblPWR2.Location.X, lblPWR2.Location.Y + 27);
                    ptbTune.Location = new Point(lblTune2.Location.X + lblTune2.Width + 2, lblTune2.Location.Y);
                    comboRX2AGC.Location = new Point(lblTune2.Location.X - 8, lblTune2.Location.Y + 27);
                    udRX2StepAttData.Location = new Point(comboRX2AGC.Location.X + comboRX2AGC.Width + 5, comboRX2AGC.Location.Y);
                    comboRX2Preamp.Location = new Point(udRX2StepAttData.Location.X + udRX2StepAttData.Width + 5, udRX2StepAttData.Location.Y);
                    chkRX2Mute.Location = new Point(chkMOX.Location.X + chkMOX.Width + 10, chkMOX.Location.Y);

                    if (_useLegacyMeters)
                    {
                        comboRX2MeterMode.Parent = this;
                        comboRX2MeterMode.Show();
                        comboMeterTXMode.Parent = this;
                        comboMeterTXMode.Show();
                        panelMeterLabels.Parent = this;
                        panelMeterLabels.Show();
                        this.MinimumSize = new Size(1622, 760);
                    }
                    else
                    {
                        comboRX2MeterMode.Parent = this;
                        comboRX2MeterMode.Hide();
                        comboMeterTXMode.Parent = this;
                        comboMeterTXMode.Hide();
                        panelMeterLabels.Parent = this;
                        panelMeterLabels.Hide();
                        this.MinimumSize = new Size(1142, 760);
                    }
                    // wd5y

                    setupHiddenButton();// grpVFOA); //MW0LGE_21a
                }
            }

            panelDisplay.Location = new Point(0, top + 20);

            int height = this.ClientSize.Height - (top + 25);

            if (_showAndromedaButtonBar)
            {
                height -= panelButtonBar.Height;
            }
            else
            {
                if (this.m_bShowBandControls)
                    height -= radBand160.Height;

                if (this.m_bShowModeControls)
                    height -= radModeLSB.Height;
            }

            //wd5y
            height -= statusStripMain.Height;
            statusStripMain.Show();
            //wd5y

            panelDisplay.Size = new Size(this.ClientSize.Width, height);

            top = infoBar.Location.Y + infoBar.Size.Height + 5;
            int dynamicWidth = picDisplay.Width - (lblDisplayPan.Width + btnDisplayPanCenter.Width + 5 + comboDisplayMode.Width + 5 + lblDisplayZoom.Width + (btnDisplayZTB.Width * 5)); // *5 buttons

            lblDisplayPan.Location = new Point(picDisplay.Location.X, top);
            ptbDisplayPan.Location = new Point(lblDisplayPan.Location.X + lblDisplayPan.Width, top);
            ptbDisplayPan.Size = new Size(dynamicWidth / 2, tb_display_pan_size_basis.Height);
            btnDisplayPanCenter.Location = new Point(ptbDisplayPan.Location.X + ptbDisplayPan.Width, top);

            // :NOTE: Force update on pan control
            ptbDisplayPan.Value = ptbDisplayPan.Value;
            ptbDisplayPan_Scroll(this, EventArgs.Empty);

            comboDisplayMode.Parent = panelDisplay;
            comboDisplayMode.Location = new Point(btnDisplayPanCenter.Location.X + btnDisplayPanCenter.Width + 5, top);
            comboRX2DisplayMode.Parent = panelDisplay;
            comboRX2DisplayMode.Location = new Point(btnDisplayPanCenter.Location.X + btnDisplayPanCenter.Width + 5, top);

            lblDisplayZoom.Location = new Point(comboDisplayMode.Location.X + comboDisplayMode.Width + 5, top);
            ptbDisplayZoom.Location = new Point(lblDisplayZoom.Location.X + lblDisplayZoom.Width, top);
            ptbDisplayZoom.Size = new Size(btnDisplayZTB.Location.X - (lblDisplayZoom.Location.X + lblDisplayZoom.Size.Width), tb_display_zoom_size_basis.Height);

            // :NOTE: Force update on zoom control
            ptbDisplayZoom.Value = ptbDisplayZoom.Value;
            ptbDisplayZoom_Scroll(this, EventArgs.Empty);

            top = panelDisplay.Location.Y + panelDisplay.Height;
            // G8NJJ to add new Andromeda button bar in place of band, mode controls
            if (this._showAndromedaButtonBar)
            {
                panelButtonBar.Location = new Point(5, top);
                top = top + panelButtonBar.Height;
            }
            else
            {
                if (this.m_bShowBandControls)
                {
                    lblRX2Band.Location = new Point(5, top);
                    comboRX2Band.Location = new Point(lblRX2Band.Location.X + lblRX2Band.Width + 5, top);

                    if (BandVHFSelected)//panelBandVHF.Visible || (_bands_VHF_selected && initializing)) //MW0LGE_21a NOTE: visible state is only true IF the FORM is shown. During INIT the Form is still hidden
                                                                             //
                    {
                        panelBandVHF.Location = new Point(this.ClientSize.Width / 2 - radBandVHF0.Width * 7 + 100, top);
                        panelBandVHF.Size = new Size(radBandVHF0.Width * 15, radBandVHF0.Height);
                        radBandVHF0.Location = new Point(0, 0);
                        radBandVHF1.Location = new Point(radBandVHF0.Location.X + radBandVHF0.Width, 0);
                        radBandVHF2.Location = new Point(radBandVHF1.Location.X + radBandVHF1.Width, 0);
                        radBandVHF3.Location = new Point(radBandVHF2.Location.X + radBandVHF2.Width, 0);
                        radBandVHF4.Location = new Point(radBandVHF3.Location.X + radBandVHF3.Width, 0);
                        radBandVHF5.Location = new Point(radBandVHF4.Location.X + radBandVHF4.Width, 0);
                        radBandVHF6.Location = new Point(radBandVHF5.Location.X + radBandVHF5.Width, 0);
                        radBandVHF7.Location = new Point(radBandVHF6.Location.X + radBandVHF6.Width, 0);
                        radBandVHF8.Location = new Point(radBandVHF7.Location.X + radBandVHF7.Width, 0);
                        radBandVHF9.Location = new Point(radBandVHF8.Location.X + radBandVHF8.Width, 0);
                        radBandVHF10.Location = new Point(radBandVHF9.Location.X + radBandVHF9.Width, 0);
                        radBandVHF11.Location = new Point(radBandVHF10.Location.X + radBandVHF10.Width, 0);
                        radBandVHF12.Location = new Point(radBandVHF11.Location.X + radBandVHF11.Width, 0);
                        radBandVHF13.Location = new Point(radBandVHF12.Location.X + radBandVHF12.Width, 0);
                        btnBandHF.Location = new Point(radBandVHF13.Location.X + radBandVHF13.Width, 0);
                        top = panelBandVHF.Location.Y + panelBandVHF.Height;
                    }
                    else if (BandHFSelected)//panelBandHF.Visible || (_bands_HF_selected && initializing)) //MW0LGE_21a NOTE: visible state is only true IF the FORM is shown. During INIT the Form is still hidden
                    {
                        panelBandHF.Location = new Point(this.ClientSize.Width / 2 - radBand160.Width * 7 + 100, top);
                        panelBandHF.Size = new Size(radBand160.Width * 15, radBand160.Height);
                        radBand160.Location = new Point(0, 0);
                        radBand80.Location = new Point(radBand160.Location.X + radBand160.Width, 0);
                        radBand60.Location = new Point(radBand80.Location.X + radBand80.Width, 0);
                        radBand40.Location = new Point(radBand60.Location.X + radBand60.Width, 0);
                        radBand30.Location = new Point(radBand40.Location.X + radBand40.Width, 0);
                        radBand20.Location = new Point(radBand30.Location.X + radBand30.Width, 0);
                        radBand17.Location = new Point(radBand20.Location.X + radBand20.Width, 0);
                        radBand15.Location = new Point(radBand17.Location.X + radBand17.Width, 0);
                        radBand12.Location = new Point(radBand15.Location.X + radBand15.Width, 0);
                        radBand10.Location = new Point(radBand12.Location.X + radBand12.Width, 0);
                        radBand6.Location = new Point(radBand10.Location.X + radBand10.Width, 0);
                        radBandWWV.Location = new Point(radBand6.Location.X + radBand2.Width, 0);
                        radBandGEN.Location = new Point(radBandWWV.Location.X + radBandWWV.Width, 0);
                        btnBandVHF.Location = new Point(radBandGEN.Location.X + radBandGEN.Width, 0);
                        top = panelBandHF.Location.Y + panelBandHF.Height;
                    }
                    else
                    {
                        panelBandGEN.Location = new Point(this.ClientSize.Width / 2 - radBandGEN0.Width * 7 + 100, top);
                        panelBandGEN.Size = new Size(radBandGEN0.Width * 15, radBandGEN0.Height);
                        radBandGEN0.Location = new Point(0, 0);
                        radBandGEN1.Location = new Point(radBandGEN0.Location.X + radBandGEN0.Width, 0);
                        radBandGEN2.Location = new Point(radBandGEN1.Location.X + radBandGEN1.Width, 0);
                        radBandGEN3.Location = new Point(radBandGEN2.Location.X + radBandGEN2.Width, 0);
                        radBandGEN4.Location = new Point(radBandGEN3.Location.X + radBandGEN3.Width, 0);
                        radBandGEN5.Location = new Point(radBandGEN4.Location.X + radBandGEN4.Width, 0);
                        radBandGEN6.Location = new Point(radBandGEN5.Location.X + radBandGEN5.Width, 0);
                        radBandGEN7.Location = new Point(radBandGEN6.Location.X + radBandGEN6.Width, 0);
                        radBandGEN8.Location = new Point(radBandGEN7.Location.X + radBandGEN7.Width, 0);
                        radBandGEN9.Location = new Point(radBandGEN8.Location.X + radBandGEN8.Width, 0);
                        radBandGEN10.Location = new Point(radBandGEN9.Location.X + radBandGEN9.Width, 0);
                        radBandGEN11.Location = new Point(radBandGEN10.Location.X + radBandGEN10.Width, 0);
                        radBandGEN12.Location = new Point(radBandGEN11.Location.X + radBandGEN11.Width, 0);
                        radBandGEN13.Location = new Point(radBandGEN12.Location.X + radBandGEN12.Width, 0);
                        btnBandHF1.Location = new Point(radBandGEN13.Location.X + radBandGEN13.Width, 0);
                        top = panelBandGEN.Location.Y + panelBandGEN.Height;
                    }

                }

                if (this.m_bShowModeControls)
                {
                    panelMode.Location = new Point(this.ClientSize.Width / 2 - radModeLSB.Width * 6 + 100, top);
                    panelMode.Size = new Size(radModeLSB.Width * 12, radModeLSB.Height);
                    panelRX2Mode.Location = new Point(this.ClientSize.Width / 2 - radModeLSB.Width * 6 + 100, top);
                    panelRX2Mode.Size = new Size(radModeLSB.Width * 12, radModeLSB.Height);

                    radModeLSB.Location = new Point(0, 0);
                    radModeUSB.Location = new Point(radModeLSB.Location.X + radModeLSB.Width, 0);
                    radModeDSB.Location = new Point(radModeUSB.Location.X + radModeUSB.Width, 0);
                    radModeCWL.Location = new Point(radModeDSB.Location.X + radModeDSB.Width, 0);
                    radModeCWU.Location = new Point(radModeCWL.Location.X + radModeCWL.Width, 0);
                    radModeFMN.Location = new Point(radModeCWU.Location.X + radModeCWU.Width, 0);
                    radModeAM.Location = new Point(radModeFMN.Location.X + radModeFMN.Width, 0);
                    radModeSAM.Location = new Point(radModeAM.Location.X + radModeAM.Width, 0);
                    radModeSPEC.Location = new Point(radModeSAM.Location.X + radModeSAM.Width, 0);
                    radModeDIGL.Location = new Point(radModeSPEC.Location.X + radModeSPEC.Width, 0);
                    radModeDIGU.Location = new Point(radModeDIGL.Location.X + radModeDIGL.Width, 0);
                    radModeDRM.Location = new Point(radModeDIGU.Location.X + radModeDIGU.Width, 0);
                    radRX2ModeLSB.Location = new Point(0, 0);
                    radRX2ModeUSB.Location = new Point(radRX2ModeLSB.Location.X + radRX2ModeLSB.Width, 0);
                    radRX2ModeDSB.Location = new Point(radRX2ModeUSB.Location.X + radRX2ModeUSB.Width, 0);
                    radRX2ModeCWL.Location = new Point(radRX2ModeDSB.Location.X + radRX2ModeDSB.Width, 0);
                    radRX2ModeCWU.Location = new Point(radRX2ModeCWL.Location.X + radRX2ModeCWL.Width, 0);
                    radRX2ModeFMN.Location = new Point(radRX2ModeCWU.Location.X + radRX2ModeCWU.Width, 0);
                    radRX2ModeAM.Location = new Point(radRX2ModeFMN.Location.X + radRX2ModeFMN.Width, 0);
                    radRX2ModeSAM.Location = new Point(radRX2ModeAM.Location.X + radRX2ModeAM.Width, 0);
                    radRX2ModeSPEC.Location = new Point(radRX2ModeSAM.Location.X + radRX2ModeSAM.Width, 0);
                    radRX2ModeDIGL.Location = new Point(radRX2ModeSPEC.Location.X + radRX2ModeSPEC.Width, 0);
                    radRX2ModeDIGU.Location = new Point(radRX2ModeDIGL.Location.X + radRX2ModeDIGL.Width, 0);
                    radRX2ModeDRM.Location = new Point(radRX2ModeDIGU.Location.X + radRX2ModeDIGU.Width, 0);

                    top = panelMode.Location.Y + panelMode.Height;
                }

            }

            if (!this._showAndromedaTopControls)
            {
                grpVFOA.Location = new Point(grpVFOA.Location.X, -200);
                grpVFOB.Location = new Point(grpVFOB.Location.X, -200);
                radRX1Show.Location = new Point(radRX1Show.Location.X, -200);
                radRX2Show.Location = new Point(radRX2Show.Location.X, -200);
            }

            //wd5y
            if (this._showAndromedaTopControls)
            {
                lblAF2.BringToFront();
                lblAF3.BringToFront();
                ptbRX1AF.BringToFront();
                ptbRX2AF.BringToFront();
                lblRF2.BringToFront();
                lblRF3.BringToFront();
                ptbRF.BringToFront();
                ptbRX2RF.BringToFront();
                lblPWR2.BringToFront();
                lblTune2.BringToFront();
                ptbPWR.BringToFront();
                ptbTune.BringToFront();
                comboAGC.BringToFront();
                comboRX2AGC.BringToFront();
                comboPreamp.BringToFront();
                comboRX2Preamp.BringToFront();
                udRX1StepAttData.BringToFront();
                udRX2StepAttData.BringToFront();
                txtVFOABand.BringToFront();
                txtVFOBBand.BringToFront();
                comboMeterRXMode.BringToFront();
                comboRX2MeterMode.BringToFront();
                comboMeterTXMode.BringToFront();
            }
            if (_showAndromedaTopControls == false)
            {
                lblAF2.Hide();
                lblAF3.Hide();
                ptbRX1AF.Hide();
                ptbRX2AF.Hide();
                lblRF2.Hide();
                lblRF3.Hide();
                ptbRF.Hide();
                ptbRX2RF.Hide();
                lblPWR2.Hide();
                lblTune2.Hide();
                ptbPWR.Hide();
                ptbTune.Hide();
                comboAGC.Hide();
                comboRX2AGC.Hide();
                comboPreamp.Hide();
                comboRX2Preamp.Hide();
                udRX1StepAttData.Hide();
                udRX2StepAttData.Hide();
            }
            //wd5y
        }



        // W1CEG:  End
        #endregion Collapsible Display

        private void mnuFilter_Click(object sender, EventArgs e)
        {
            if (sender == null) return;
            if (sender.GetType() != typeof(ToolStripMenuItem)) return;
            string menu_item = ((ToolStripMenuItem)sender).Name;

            switch (menu_item)
            {
                case "FilterToolStripMenuItem1":
                    radFilter1.Checked = true;
                    break;
                case "FilterToolStripMenuItem2":
                    radFilter2.Checked = true;
                    break;
                case "FilterToolStripMenuItem3":
                    radFilter3.Checked = true;
                    break;
                case "FilterToolStripMenuItem4":
                    radFilter4.Checked = true;
                    break;
                case "FilterToolStripMenuItem5":
                    radFilter5.Checked = true;
                    break;
                case "FilterToolStripMenuItem6":
                    radFilter6.Checked = true;
                    break;
                case "FilterToolStripMenuItem7":
                    radFilter7.Checked = true;
                    break;
                case "FilterToolStripMenuItem8":
                    radFilter8.Checked = true;
                    break;
                case "FilterToolStripMenuItem9":
                    radFilter9.Checked = true;
                    break;
                case "FilterToolStripMenuItem10":
                    radFilter10.Checked = true;
                    break;
            }
        }

        private void mnuFilterRX2_Click(object sender, EventArgs e)
        {
            if (sender == null) return;
            if (sender.GetType() != typeof(ToolStripMenuItem)) return;
            string menu_item = ((ToolStripMenuItem)sender).Name;

            switch (menu_item)
            {
                case "kToolStripMenuItem":
                    radRX2Filter1.Checked = true;
                    break;
                case "kToolStripMenuItem1":
                    radRX2Filter2.Checked = true;
                    break;
                case "kToolStripMenuItem2":
                    radRX2Filter3.Checked = true;
                    break;
                case "kToolStripMenuItem3":
                    radRX2Filter4.Checked = true;
                    break;
                case "kToolStripMenuItem4":
                    radRX2Filter5.Checked = true;
                    break;
                case "toolStripMenuItem13":
                    radRX2Filter6.Checked = true;
                    break;
                case "toolStripMenuItem14":
                    radRX2Filter7.Checked = true;
                    break;
            }
        }

        private void mnuDSP_Click(object sender, EventArgs e)
        {
            if (sender == null) return;
            if (sender.GetType() != typeof(ToolStripMenuItem)) return;
            string menu_item = ((ToolStripMenuItem)sender).Text;

            switch (menu_item)
            {
                case "NR":
                    if (chkNR.CheckState == CheckState.Unchecked || chkNR.CheckState == CheckState.Indeterminate) chkNR.CheckState = CheckState.Checked;
                    else if (chkNR.CheckState == CheckState.Checked) chkNR.CheckState = CheckState.Unchecked;
                    break;
                case "NR2":
                    if (chkNR.CheckState == CheckState.Unchecked || chkNR.CheckState == CheckState.Checked) chkNR.CheckState = CheckState.Indeterminate;
                    else if (chkNR.CheckState == CheckState.Indeterminate) chkNR.CheckState = CheckState.Unchecked;
                    break;
                case "ANF":
                    chkANF.Checked = !chkANF.Checked;
                    break;
                case "NB":
                    if (chkNB.CheckState == CheckState.Unchecked || chkNB.CheckState == CheckState.Indeterminate) chkNB.CheckState = CheckState.Checked;
                    else if (chkNB.CheckState == CheckState.Checked) chkNB.CheckState = CheckState.Unchecked;
                    break;
                case "NB2":
                    if (chkNB.CheckState == CheckState.Unchecked || chkNB.CheckState == CheckState.Checked) chkNB.CheckState = CheckState.Indeterminate;
                    else if (chkNB.CheckState == CheckState.Indeterminate) chkNB.CheckState = CheckState.Unchecked;
                    break;
                case "SNB":
                    chkDSPNB2.Checked = !chkDSPNB2.Checked;
                    break;
                case "BIN":
                    chkBIN.Checked = !chkBIN.Checked;
                    break;
                case "Multi-RX":
                    chkEnableMultiRX.Checked = !chkEnableMultiRX.Checked;
                    break;
                case "AVG":
                    chkDisplayAVG.Checked = !chkDisplayAVG.Checked;
                    break;
                case "Peak":
                    chkDisplayPeak.Checked = !chkDisplayPeak.Checked;
                    break;
            }
        }

        private void mnuDSPRX2_Click(object sender, EventArgs e)
        {
            if (sender == null) return;
            if (sender.GetType() != typeof(ToolStripMenuItem)) return;
            string menu_item = ((ToolStripMenuItem)sender).Text;

            switch (menu_item)
            {
                case "NR":
                    if (chkRX2NR.CheckState == CheckState.Unchecked || chkRX2NR.CheckState == CheckState.Indeterminate) chkRX2NR.CheckState = CheckState.Checked;
                    else if (chkRX2NR.CheckState == CheckState.Checked) chkRX2NR.CheckState = CheckState.Unchecked;
                    break;
                case "NR2":
                    if (chkRX2NR.CheckState == CheckState.Unchecked || chkRX2NR.CheckState == CheckState.Checked) chkRX2NR.CheckState = CheckState.Indeterminate;
                    else if (chkRX2NR.CheckState == CheckState.Indeterminate) chkRX2NR.CheckState = CheckState.Unchecked;
                    break;
                case "ANF":
                    chkRX2ANF.Checked = !chkRX2ANF.Checked;
                    break;
                case "NB":
                    if (chkRX2NB.CheckState == CheckState.Unchecked || chkRX2NB.CheckState == CheckState.Indeterminate) chkRX2NB.CheckState = CheckState.Checked;
                    else if (chkRX2NB.CheckState == CheckState.Checked) chkRX2NB.CheckState = CheckState.Unchecked;
                    break;
                case "NB2":
                    if (chkRX2NB.CheckState == CheckState.Unchecked || chkRX2NB.CheckState == CheckState.Checked) chkRX2NB.CheckState = CheckState.Indeterminate;
                    else if (chkRX2NB.CheckState == CheckState.Indeterminate) chkRX2NB.CheckState = CheckState.Unchecked;
                    break;
                case "BIN":
                    chkRX2BIN.Checked = !chkRX2BIN.Checked;
                    break;
                case "SNB":
                    chkRX2NB2.Checked = !chkRX2NB2.Checked;
                    break;
                case "AVG":
                    chkRX2DisplayAVG.Checked = !chkRX2DisplayAVG.Checked;
                    break;
                case "Peak":
                    chkRX2DisplayPeak.Checked = !chkRX2DisplayPeak.Checked;
                    break;
            }
        }

        private void mnuBand_Click(object sender, EventArgs e)
        {
            if (sender == null) return;
            if (sender.GetType() != typeof(ToolStripMenuItem)) return;
            string menu_item = ((ToolStripMenuItem)sender).Text;

            switch (menu_item)
            {
                case "160":
                    radBand160_Click(this, EventArgs.Empty);
                    break;
                case "80":
                    radBand80_Click(this, EventArgs.Empty);
                    break;
                case "60":
                    radBand60_Click(this, EventArgs.Empty);
                    break;
                case "40":
                    radBand40_Click(this, EventArgs.Empty);
                    break;
                case "30":
                    radBand30_Click(this, EventArgs.Empty);
                    break;
                case "20":
                    radBand20_Click(this, EventArgs.Empty);
                    break;
                case "17":
                    radBand17_Click(this, EventArgs.Empty);
                    break;
                case "15":
                    radBand15_Click(this, EventArgs.Empty);
                    break;
                case "12":
                    radBand12_Click(this, EventArgs.Empty);
                    break;
                case "10":
                    radBand10_Click(this, EventArgs.Empty);
                    break;
                case "6":
                    radBand6_Click(this, EventArgs.Empty);
                    break;
                case "WWV":
                    radBandWWV_Click(this, EventArgs.Empty);
                    break;
                case "GEN":
                    radBandGEN_Click(this, EventArgs.Empty);
                    break;
            }
        }

        private void mnuBandRX2_Click(object sender, EventArgs e)
        {
            if (sender == null) return;
            if (sender.GetType() != typeof(ToolStripMenuItem)) return;
            string menu_item = ((ToolStripMenuItem)sender).Text;

            Band b = BandStackManager.StringToBand(menu_item);

            BandStackFilter bsf = BandStackManager.GetFilter(b);
            if (bsf != null)
            {
                BandStackEntry bse = bsf.First();

                if (bse != null)
                {
                    RX2DSPMode = bse.Mode;
                    RX2Filter = bse.Filter;
                    VFOBFreq = bse.Frequency;
                }
            }

            toolStripMenuItem2.Checked =
            toolStripMenuItem3.Checked =
            toolStripMenuItem4.Checked =
            toolStripMenuItem5.Checked =
            toolStripMenuItem6.Checked =
            toolStripMenuItem7.Checked =
            toolStripMenuItem8.Checked =
            toolStripMenuItem9.Checked =
            toolStripMenuItem10.Checked =
            toolStripMenuItem11.Checked =
            toolStripMenuItem12.Checked =
            wWVToolStripMenuItem.Checked =
            gENToolStripMenuItem.Checked = false;

            switch (b)
            {
                case Band.B160M:
                    toolStripMenuItem2.Checked = true;
                    break;
                case Band.B80M:
                    toolStripMenuItem3.Checked = true;
                    break;
                case Band.B60M:
                    toolStripMenuItem4.Checked = true;
                    break;
                case Band.B40M:
                    toolStripMenuItem5.Checked = true;
                    break;
                case Band.B30M:
                    toolStripMenuItem6.Checked = true;
                    break;
                case Band.B20M:
                    toolStripMenuItem7.Checked = true;
                    break;
                case Band.B17M:
                    toolStripMenuItem8.Checked = true;
                    break;
                case Band.B15M:
                    toolStripMenuItem9.Checked = true;
                    break;
                case Band.B12M:
                    toolStripMenuItem10.Checked = true;
                    break;
                case Band.B10M:
                    toolStripMenuItem11.Checked = true;
                    break;
                case Band.B6M:
                    toolStripMenuItem12.Checked = true;
                    break;
                case Band.WWV:
                    wWVToolStripMenuItem.Checked = true;
                    break;
                case Band.GEN:
                    gENToolStripMenuItem.Checked = true;
                    break;
            }

            btnHidden.Focus();
        }

        private void setupHiddenButton()
        {
            // MW0LGE_21a
            // hidden button is now put behind either vfoa or vfob group box
            // to fix issue where it was hidden when in collapsed mode when on rx2 only
            //btnHidden.Location = c.Location;

            btnHidden.Location = new Point(-1000, -1000); // [2.10.3.6]MW0LGE off screen
            //btnHidden.SendToBack();
        }
        private void mnuMode_Click(object sender, EventArgs e)
        {
            if (sender == null) return;
            if (sender.GetType() != typeof(ToolStripMenuItem)) return;
            string menu_item = ((ToolStripMenuItem)sender).Text;

            switch (menu_item)
            {
                case "LSB":
                    radModeLSB.Checked = true;
                    break;
                case "USB":
                    radModeUSB.Checked = true;
                    break;
                case "DSB":
                    radModeDSB.Checked = true;
                    break;
                case "CWL":
                    radModeCWL.Checked = true;
                    break;
                case "CWU":
                    radModeCWU.Checked = true;
                    break;
                case "FM":
                    radModeFMN.Checked = true;
                    break;
                case "AM":
                    radModeAM.Checked = true;
                    break;
                case "SAM":
                    radModeSAM.Checked = true;
                    break;
                case "SPEC":
                    radModeSPEC.Checked = true;
                    break;
                case "DIGL":
                    radModeDIGL.Checked = true;
                    break;
                case "DIGU":
                    radModeDIGU.Checked = true;
                    break;
                case "DRM":
                    radModeDRM.Checked = true;
                    break;
            }
        }

        private void mnuModeRX2_Click(object sender, EventArgs e)
        {
            if (sender == null) return;
            if (sender.GetType() != typeof(ToolStripMenuItem)) return;
            string menu_item = ((ToolStripMenuItem)sender).Text;

            switch (menu_item)
            {
                case "LSB":
                    radRX2ModeLSB.Checked = true;
                    break;
                case "USB":
                    radRX2ModeUSB.Checked = true;
                    break;
                case "DSB":
                    radRX2ModeDSB.Checked = true;
                    break;
                case "CWL":
                    radRX2ModeCWL.Checked = true;
                    break;
                case "CWU":
                    radRX2ModeCWU.Checked = true;
                    break;
                case "FM":
                    radRX2ModeFMN.Checked = true;
                    break;
                case "AM":
                    radRX2ModeAM.Checked = true;
                    break;
                case "SAM":
                    radRX2ModeSAM.Checked = true;
                    break;
                case "DIGL":
                    radRX2ModeDIGL.Checked = true;
                    break;
                case "DIGU":
                    radRX2ModeDIGU.Checked = true;
                    break;
                case "DRM":
                    radRX2ModeDRM.Checked = true;
                    break;
            }
        }
        // handlers for menu display controls events. The persistent state is held on the setup form matching controls
        private void mnuShowBandControls_Click(object sender, EventArgs e)
        {
            SetupForm.chkShowBandControls.Checked = !SetupForm.chkShowBandControls.Checked;            
        }

        private void mnuShowModeControls_Click(object sender, EventArgs e)
        {
            SetupForm.chkShowModeControls.Checked = !SetupForm.chkShowModeControls.Checked;
        }

        private void AndromedaTopControlsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetupForm.chkShowAndromedaTop.Checked = !SetupForm.chkShowAndromedaTop.Checked;
        }

        private void AndromedaButtonBarToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetupForm.chkShowAndromedaBar.Checked = !SetupForm.chkShowAndromedaBar.Checked;
        }

        private void radBand_CheckedChanged(object sender, EventArgs e)
        {
            if ((sender == null) ||
                (sender.GetType() != typeof(RadioButtonTS))) return;
            RadioButtonTS radioBtnTS = (RadioButtonTS)sender;
            if (!radioBtnTS.Checked) return;

            repopulateForms();
        }

        private void eSCToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!RX2PreampPresent) return;

            if (diversityForm == null || diversityForm.IsDisposed)
                diversityForm = new DiversityForm(this);

            if (diversityForm.InvokeRequired)
            {
                diversityForm.Invoke(new MethodInvoker(() =>
                {
                    diversityForm.Show();
                    diversityForm.Focus();
                    UpdateDiversityValues();
                    UpdateDiversityMenuItem();
                }));
            }
            else
            {
                diversityForm.Show();
                diversityForm.Focus();
                UpdateDiversityValues();
                UpdateDiversityMenuItem();
            }
        }

        private void ptbRX1AF_Scroll(object sender, EventArgs e)
        {
            //[2.10.1.0] MW0LGE
            if (!initializing && e != EventArgs.Empty && m_bRXAFSlidersWillUnmute && chkMUT.Checked) chkMUT.Checked = false;

            RX0Gain = ptbRX1AF.Value;
            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbRX1AF.Focus();
            }
        }

        private void ptbRX2AF_Scroll(object sender, EventArgs e)
        {
            //[2.10.1.0] MW0LGE
            if (!initializing && e != EventArgs.Empty && m_bRXAFSlidersWillUnmute && chkRX2Mute.Checked) chkRX2Mute.Checked = false;

            RX2Gain = ptbRX2AF.Value;
            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbRX2AF.Focus();
            }
        }

        private void radRX1Show_CheckedChanged(object sender, EventArgs e)
        {
            if (radRX1Show.Checked)
            {
                radRX2Show.Checked = false;
                show_rx2 = false;
                if (CollapsedDisplay)
                    CollapseDisplay(true);
            }
            else
            {
                radRX2Show.Checked = true;
                show_rx2 = true;
                if (CollapsedDisplay)
                    CollapseDisplay(true);
            }
            UpdateButtonBarButtons();               // G8NJJ - update the button bar
            AndromedaIndicatorCheck(EIndicatorActions.eINVFOAB, true, show_rx1);
            InitialiseAndromedaIndicators(false);           // initialise the panel LEDs
        }

        private void radRX2Show_CheckedChanged(object sender, EventArgs e)
        {
            if (radRX2Show.Checked)
            {
                radRX1Show.Checked = false;
                show_rx1 = false;
                if (CollapsedDisplay)
                    CollapseDisplay(true);
            }
            else
            {
                radRX1Show.Checked = true;
                show_rx1 = true;
                if (CollapsedDisplay)
                    CollapseDisplay(true);
            }
            UpdateButtonBarButtons();               // G8NJJ - update the button bar
            AndromedaIndicatorCheck(EIndicatorActions.eINVFOAB, true, show_rx1);
            InitialiseAndromedaIndicators(false);           // initialise the panel LEDs
        }

        private void ptbAF_DoubleClick(object sender, EventArgs e)
        {

        }

        private void ptbRX1AF_DoubleClick(object sender, EventArgs e)
        {
            if (CollapsedDisplay)
                chkMUT.Checked = !chkMUT.Checked;
        }

        private void ptbRX2AF_DoubleClick(object sender, EventArgs e)
        {
            if (CollapsedDisplay)
                chkRX2Mute.Checked = !chkRX2Mute.Checked;
        }
        private bool _updatingRX1StepAttData = false;
        private void udRX1StepAttData_ValueChanged(object sender, EventArgs e)
        {
            if (_updatingRX1StepAttData) return;
            _updatingRX1StepAttData = true;
            if (!IsSetupFormNull) SetupForm.ATTOnRX1 = (int)udRX1StepAttData.Value; //[2.10.3.6]MW0LGE
            if (udRX1StepAttData.Focused) btnHidden.Focus();
            if (sliderForm != null) sliderForm.RX1Atten = (int)udRX1StepAttData.Value;
            lblAttenLabel.Text = udRX1StepAttData.Value.ToString() + " dB";
            _updatingRX1StepAttData = false;

            //wd5y
            if (sliderForm != null)
            {
                sliderForm.lblRX1at.Text = SetupForm.ATTOnRX1.ToString();
            }
            //wd5y
        }

        private bool _updatingRX2StepAttData = false;
        private void udRX2StepAttData_ValueChanged(object sender, EventArgs e)
        {
            if (_updatingRX2StepAttData) return;
            _updatingRX2StepAttData = true;

            if (!IsSetupFormNull) SetupForm.ATTOnRX2 = (int)udRX2StepAttData.Value; //[2.10.3.6]MW0LGE
            if (udRX2StepAttData.Focused) btnHidden.Focus();
            if (sliderForm != null) sliderForm.RX2Atten = (int)udRX2StepAttData.Value;
            lblRX2AttenLabel.Text = udRX2StepAttData.Value.ToString() + " dB";
            _updatingRX2StepAttData = false;

            //wd5y
            if (sliderForm != null)
            {
                sliderForm.lblRX2at.Text = SetupForm.ATTOnRX2.ToString();
            }
            //wd5y
        }

        private void lblPreamp_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (current_hpsdr_model != HPSDRModel.HPSDR && !_mox)
            {
                SetupForm.RX1EnableAtt = !SetupForm.RX1EnableAtt;
                if (RX1RX2usingSameADC) SetupForm.RX2EnableAtt = SetupForm.RX1EnableAtt; //MW0LGE_22b
            }
        }

        private void lblRX2Preamp_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (current_hpsdr_model != HPSDRModel.HPSDR && !_mox)
            {
                SetupForm.RX2EnableAtt = !SetupForm.RX2EnableAtt;
                if (RX1RX2usingSameADC) SetupForm.RX1EnableAtt = SetupForm.RX2EnableAtt;//MW0LGE_22b
            }
        }

        private byte n1mm_state = 0;
        public void SetFocusMaster(bool state)
        {
            if (n1mm_delay != null)
            {
                if (state)
                {
                    if (n1mm_state == 1)
                    {
                        n1mm_state = 3;
                        ToggleFocusMasterTimer();
                    }
                }
                else
                {
                    if (n1mm_state == 0)
                        n1mm_state = 1;
                    else if (n1mm_state == 3)
                    {
                        n1mm_state = 1;
                        n1mm_delay.Enabled = false;
                    }

                }
            }
        }

        private bool m_bLinkCTUNonVFOSync = false;
        public bool LinkCTUNonVFOSync {
            get { return m_bLinkCTUNonVFOSync; }
            set {
                m_bLinkCTUNonVFOSync = value;

                if (chkVFOSync.Checked)
                {
                    if (chkFWCATU.Checked && !chkX2TR.Checked)
                    {
                        chkX2TR.Checked = true;
                    }
                    else if (!chkFWCATU.Checked && chkX2TR.Checked)
                    {
                        chkFWCATU.Checked = true;
                    }
                }
            }
        }
        private void chkFWCATU_CheckedChanged(object sender, EventArgs e)
        {
            if (chkFWCATU.Checked)
            {
                bool rit_on = chkRIT.Checked;
                chkRIT.Checked = false;
                ClickTuneDisplay = chkFWCATU.Checked;
                chkRIT.Checked = rit_on;
            }
            else ClickTuneDisplay = false;

            if (ClickTuneDisplay == true)
                lblCtunLabel.BackColor = System.Drawing.Color.Blue;
            else
                lblCtunLabel.BackColor = System.Drawing.Color.Transparent;

            //MW0LGE_21d
            if (m_bLinkCTUNonVFOSync && chkVFOSync.Checked)
            {
                chkX2TR.Checked = chkFWCATU.Checked;
            }       

            txtVFOAFreq_LostFocus(this, EventArgs.Empty);

            AndromedaIndicatorCheck(EIndicatorActions.eINCTune, true, chkFWCATU.Checked);

            setupZTBButton(); //MW0LGE_21k9
        }

        private void linearityToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (psform == null) return;
            psform.SetupForm();//EventArgs.Empty); //MW0LGE_21k9d (rc3) //MW0LGE_[2.9.0.7]
            psform.Show();
            psform.Focus();
        }

        private void RAtoolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (raForm == null || raForm.IsDisposed)
                raForm = new RAForm(this);
            if (raForm.InvokeRequired)
            {
                raForm.Invoke(new MethodInvoker(() =>
                {
                    raForm.Show();
                    raForm.Focus();
                }));
            }
            else
            {
                raForm.Show();
                raForm.Focus();
            }
        }

        private void SetDigiMode(int rx, DigiMode.DigiModeSettingState mode, bool bFromTXProfile = false)
        {
            if (rx == 1)
            {
                if (rx1dm == null)
                {
                    rx1dm = new DigiMode();
                    if (mode == DigiMode.DigiModeSettingState.dmssRecall) return;
                }
                rx1dm.Mode = mode;
                switch (mode)
                {
                    case DigiMode.DigiModeSettingState.dmssTurnOffSettings:
                        chkNoiseGate.Checked = false;
                        chkTXEQ.Checked = false;
                        SetupForm.TXLevelerOn = false;
                        chkCPDR.Checked = false;
                        chkRXEQ.Checked = false;
                        chkANF.Checked = false;
                        //chkNR.Checked = false;
                        chkNR.CheckState = CheckState.Unchecked;
                        SetupForm.CESSB = false;
                        CFCEnabled = false;
                        SetupForm.PhaseRotEnabled = false;
                        break;
                    case DigiMode.DigiModeSettingState.dmssStore:
                        rx1dm.DEXP = chkNoiseGate.Checked;
                        rx1dm.TXEQ = chkTXEQ.Checked;
                        rx1dm.LEVELER = SetupForm.TXLevelerOn;
                        rx1dm.COMPRESSOR = chkCPDR.Checked;
                        rx1dm.RXEQ = chkRXEQ.Checked;
                        rx1dm.ANF = chkANF.Checked;
                        rx1dm.NR = chkNR.CheckState;
                        rx1dm.CESSB = SetupForm.CESSB;
                        rx1dm.CFCEnabled = CFCEnabled;
                        rx1dm.PhaseRotEnabled = SetupForm.PhaseRotEnabled;
                        break;
                    case DigiMode.DigiModeSettingState.dmssRecall:
                        //[2.10.3]MW0LGE only recover these if not coming from a TX profile as LoadedTXProfile uses this function
                        if (!bFromTXProfile)
                        {
                            chkNoiseGate.Checked = rx1dm.DEXP;
                            chkTXEQ.Checked = rx1dm.TXEQ;
                            SetupForm.TXLevelerOn = rx1dm.LEVELER;
                            chkCPDR.Checked = rx1dm.COMPRESSOR;
                            chkRXEQ.Checked = rx1dm.RXEQ;
                        }
                        chkANF.Checked = rx1dm.ANF; // these two not stored in a TX profile
                        chkNR.CheckState = rx1dm.NR;
                        if (!bFromTXProfile)
                        {
                            SetupForm.CESSB = rx1dm.CESSB;
                            CFCEnabled = rx1dm.CFCEnabled;
                            SetupForm.PhaseRotEnabled = rx1dm.PhaseRotEnabled;
                        }
                        break;
                }
            }

            if (rx == 2)
            {
                if (rx2dm == null)
                {
                    rx2dm = new DigiMode();
                    if (mode == DigiMode.DigiModeSettingState.dmssRecall) return;
                }
                rx2dm.Mode = mode;
                switch (mode)
                {
                    case DigiMode.DigiModeSettingState.dmssTurnOffSettings:
                        chkRX2ANF.Checked = false;
                        chkRX2NR.CheckState = CheckState.Unchecked;
                        break;
                    case DigiMode.DigiModeSettingState.dmssStore:
                        rx2dm.ANF = chkRX2ANF.Checked;
                        rx2dm.NR = chkRX2NR.CheckState;
                        break;
                    case DigiMode.DigiModeSettingState.dmssRecall:
                        chkRX2ANF.Checked = rx2dm.ANF;
                        chkRX2NR.CheckState = rx2dm.NR;
                        break;
                }
            }
        }

        private void chkCWFWKeyer_CheckedChanged(object sender, EventArgs e)
        {
            CWFWKeyer = chkCWFWKeyer.Checked;
        }

        private void CAT2port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {

        }

        private void chkMON_Click(object sender, EventArgs e)
        {
            if (rx1_dsp_mode == DSPMode.CWL || rx1_dsp_mode == DSPMode.CWU)
                chkCWSidetone.Checked = chkMON.Checked;
        }

        private void chkNR_CheckStateChanged(object sender, EventArgs e)
        {
            switch (chkNR.CheckState)
            {
                case CheckState.Checked: // NR
                    radio.GetDSPRX(0, 0).RXANR2Run = 0;
                    radio.GetDSPRX(0, 1).RXANR2Run = 0;
                    radio.GetDSPRX(0, 0).NoiseReduction = true;
                    radio.GetDSPRX(0, 1).NoiseReduction = true;
                    NRToolStripMenuItem.Checked = true;
                    NR2ToolStripMenuItem1.Checked = false;
                    cat_nr2_status = 0;
                    cat_nr_status = 1;
                    chkNR.Text = "NR";
                    lblNRLabel.Text = "NR";
                    break;
                case CheckState.Indeterminate: // NR2
                    radio.GetDSPRX(0, 0).NoiseReduction = false;
                    radio.GetDSPRX(0, 1).NoiseReduction = false;
                    radio.GetDSPRX(0, 0).RXANR2Run = 1;
                    radio.GetDSPRX(0, 1).RXANR2Run = 1;
                    NRToolStripMenuItem.Checked = false;
                    NR2ToolStripMenuItem1.Checked = true;
                    cat_nr_status = 0;
                    cat_nr2_status = 1;
                    chkNR.Text = "NR2";
                    lblNRLabel.Text = "NR2";
                    break;
                case CheckState.Unchecked: // all off
                    radio.GetDSPRX(0, 0).NoiseReduction = false;
                    radio.GetDSPRX(0, 1).NoiseReduction = false;
                    radio.GetDSPRX(0, 0).RXANR2Run = 0;
                    radio.GetDSPRX(0, 1).RXANR2Run = 0;
                    NRToolStripMenuItem.Checked = false;
                    NR2ToolStripMenuItem1.Checked = false;
                    cat_nr_status = 0;
                    cat_nr2_status = 0;
                    chkNR.Text = "NR";
                    lblNRLabel.Text = "--";
                    break;
            }
            AndromedaIndicatorCheck(EIndicatorActions.eINNR, true, (chkNR.CheckState != CheckState.Unchecked));

        }

        private void chkRX2NR_CheckStateChanged(object sender, EventArgs e)
        {
            switch (chkRX2NR.CheckState)
            {
                case CheckState.Checked: // NR
                    radio.GetDSPRX(1, 0).RXANR2Run = 0;
                    radio.GetDSPRX(1, 1).RXANR2Run = 0;
                    radio.GetDSPRX(1, 0).NoiseReduction = true;
                    radio.GetDSPRX(1, 1).NoiseReduction = true;
                    nR2ToolStripMenuItem.Checked = true;
                    NR2StripMenuItem2.Checked = false;
                    cat_rx2_nr2_status = 0;
                    cat_rx2_nr_status = 1;
                    chkRX2NR.Text = "NR";
                    lblRX2NRLabel.Text = "NR";
                    break;
                case CheckState.Indeterminate: // NR2
                    radio.GetDSPRX(1, 0).RXANR2Run = 1;
                    radio.GetDSPRX(1, 1).RXANR2Run = 1;
                    radio.GetDSPRX(1, 0).NoiseReduction = false;
                    radio.GetDSPRX(1, 1).NoiseReduction = false;
                    nR2ToolStripMenuItem.Checked = false;
                    NR2StripMenuItem2.Checked = true;
                    cat_rx2_nr_status = 0;
                    cat_rx2_nr2_status = 1;
                    chkRX2NR.Text = "NR2";
                    lblRX2NRLabel.Text = "NR2";
                    break;
                case CheckState.Unchecked: // all off
                    radio.GetDSPRX(1, 0).NoiseReduction = false;
                    radio.GetDSPRX(1, 1).NoiseReduction = false;
                    radio.GetDSPRX(1, 0).RXANR2Run = 0;
                    radio.GetDSPRX(1, 1).RXANR2Run = 0;
                    nR2ToolStripMenuItem.Checked = false;
                    NR2StripMenuItem2.Checked = false;
                    cat_rx2_nr_status = 0;
                    cat_rx2_nr2_status = 0;
                    chkRX2NR.Text = "NR";
                    lblRX2NRLabel.Text = "--";
                    break;

            }
            AndromedaIndicatorCheck(EIndicatorActions.eINNR, false, (chkRX2NR.CheckState != CheckState.Unchecked));
        }

        private bool isHPFBypassed;

        public void wbClosing()
        {
            SetupForm.AlexHPFBypass = isHPFBypassed;
        }

        private void wBToolStripMenuItem_Click(object sender, EventArgs e)
        {
            cmaster.Getwb(0).WBdisplay.Init();
            if (CurrentHPSDRHardware == HPSDRHW.HermesII)
                NetworkIO.SetWBPacketsPerFrame(8);
            else NetworkIO.SetWBPacketsPerFrame(32);
            NetworkIO.SetWBEnable(0, 1);
            cmaster.Getwb(0).WBdisplay.StartDisplay(32);
            isHPFBypassed = alex_hpf_bypass;
            if (!IsSetupFormNull) SetupForm.AlexHPFBypass = true;
        }

        private void pIToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (path_Illustrator == null || path_Illustrator.IsDisposed)
                path_Illustrator = new Path_Illustrator(this);
            path_Illustrator.Show();
            path_Illustrator.Focus();
        }

        private void chkNB_CheckStateChanged(object sender, EventArgs e)
        {
            switch (chkNB.CheckState)
            {
                case CheckState.Checked: // NB
                    specRX.GetSpecRX(0).NB2On = false;
                    specRX.GetSpecRX(0).NBOn = true;
                    NB2ToolStripMenuItem.Checked = false;
                    NBToolStripMenuItem.Checked = true;
                    cat_nb1_status = 1;
                    cat_nb2_status = 0;
                    chkNB.Text = "NB";
                    lblNBLabel.Text = "NB";
                    break;
                case CheckState.Indeterminate: // NB2
                    specRX.GetSpecRX(0).NBOn = false;
                    specRX.GetSpecRX(0).NB2On = true;
                    NBToolStripMenuItem.Checked = false;
                    NB2ToolStripMenuItem.Checked = true;
                    cat_nb1_status = 0;
                    cat_nb2_status = 1;
                    chkNB.Text = "NB2";
                    lblNBLabel.Text = "NB2";
                    break;
                case CheckState.Unchecked: // all off                    
                    specRX.GetSpecRX(0).NBOn = false;
                    specRX.GetSpecRX(0).NB2On = false;
                    NB2ToolStripMenuItem.Checked = false;
                    NBToolStripMenuItem.Checked = false;
                    cat_nb1_status = 0;
                    cat_nb2_status = 0;
                    chkNB.Text = "NB";
                    lblNBLabel.Text = "--";
                    break;
            }
            cmaster.CMSetFRXNBRun(0);
            cmaster.CMSetFRXNB2Run(0);
            AndromedaIndicatorCheck(EIndicatorActions.eINNB, true, (chkNB.CheckState != CheckState.Unchecked));

        }

        private void chkRX2NB_CheckStateChanged(object sender, EventArgs e)
        {
            switch (chkRX2NB.CheckState)
            {
                case CheckState.Checked: // NB
                    specRX.GetSpecRX(1).NB2On = false;
                    specRX.GetSpecRX(1).NBOn = true;
                    nB2ToolStripMenuItem1.Checked = true;
                    nBRX2ToolStripMenuItem.Checked = false;
                    cat_rx2nb1_status = 1;
                    cat_rx2nb2_status = 0;
                    chkRX2NB.Text = "NB";
                    lblRX2NBLabel.Text = "NB";
                    break;
                case CheckState.Indeterminate: // NB2
                    specRX.GetSpecRX(1).NBOn = false;
                    specRX.GetSpecRX(1).NB2On = true;
                    nBRX2ToolStripMenuItem.Checked = true;
                    nB2ToolStripMenuItem1.Checked = false;
                    cat_rx2nb1_status = 0;
                    cat_rx2nb2_status = 1;
                    chkRX2NB.Text = "NB2";
                    lblRX2NBLabel.Text = "NB2";
                    break;
                case CheckState.Unchecked: // all off                    
                    specRX.GetSpecRX(1).NBOn = false;
                    specRX.GetSpecRX(1).NB2On = false;
                    nB2ToolStripMenuItem1.Checked = false;
                    nBRX2ToolStripMenuItem.Checked = false;
                    cat_rx2nb1_status = 0;
                    cat_rx2nb2_status = 0;
                    chkRX2NB.Text = "NB";
                    lblRX2NBLabel.Text = "--";
                    break;
            }
            cmaster.CMSetFRXNBRun(1);
            cmaster.CMSetFRXNB2Run(1);
            AndromedaIndicatorCheck(EIndicatorActions.eINNB, false, (chkRX2NB.CheckState != CheckState.Unchecked));
        }

        // RX2 Spectral Noise Blanker (SNB)
        private void chkRX2NB2_CheckStateChanged(object sender, EventArgs e)
        {
            if (chkRX2NB2.Checked)
            {
                chkRX2NB2.BackColor = button_selected_color;
                lblRX2SNBLabel.Text = "SNB";
            }

            else
            {
                chkRX2NB2.BackColor = SystemColors.Control;
                lblRX2SNBLabel.Text = "---";
            }
            WDSP.SetRXASNBARun(WDSP.id(2, 0), chkRX2NB2.Checked);
            cat_rx2snb_status = Convert.ToInt32(chkRX2NB2.Checked);
        }

        private void LoadLEDFont()
        {
            LEDLFont = GetCustomFont(Properties.Resources.digital7, 24, FontStyle.Regular);
            LEDSFont = GetCustomFont(Properties.Resources.digital7, 19, FontStyle.Regular);
            LEDMFont = GetCustomFont(Properties.Resources.digital7, 22, FontStyle.Regular);
        }

        [DllImport("gdi32.dll", ExactSpelling = true)]
        private static extern IntPtr AddFontMemResourceEx(byte[] pbFont, int cbFont, IntPtr pdv, out uint pcFonts);

        static public Font GetCustomFont(byte[] fontData, float size, FontStyle style)
        {
            if (_fontCollections == null) _fontCollections = new List<PrivateFontCollection>();
            PrivateFontCollection fontCol = new PrivateFontCollection();
            IntPtr fontPtr = Marshal.AllocCoTaskMem(fontData.Length);

            // MW0LGE
            // register the font to the system
            // ideally we should use 'RemoveFontMemResourceEx.' to clear up on app shutdown
            // but it will be tidied automatically. We are not doing anything crazy over and over with this
            // so will ignore the ideal world for now
            uint cFonts;
            AddFontMemResourceEx(fontData, fontData.Length, IntPtr.Zero, out cFonts);
            //

            Marshal.Copy(fontData, 0, fontPtr, fontData.Length);
            fontCol.AddMemoryFont(fontPtr, fontData.Length);

            Marshal.FreeCoTaskMem(fontPtr);     //<-- It works!
            _fontCollections.Add(fontCol);
            return new Font(fontCol.Families[0], size, style);
        }

        static public Font GetCustomFont(string fontFile, float size, FontStyle style)
        {
            if (_fontCollections == null) _fontCollections = new List<PrivateFontCollection>();
            PrivateFontCollection fontCol = new PrivateFontCollection();
            fontCol.AddFontFile(fontFile);
            _fontCollections.Add(fontCol);
            return new Font(fontCol.Families[0], size, style);
        }

        #region SunTrackingEct_KE9NS
        //=========================================================
        // ke9ns add open up bandstack window when you click on the bandstack index
        private void regBox1_Click(object sender, EventArgs e)
        {
            showBandStack();
        }// regBox1_Click

        //==============================================================
        // ke9ns add  open up bandstack window when you click on the bandstack index
        private void regBox_Click(object sender, EventArgs e)
        {
            btnHidden.Focus();
            Invoke(new MethodInvoker(BandStack2Form.Show)); //MW0LGE_21d
        }

        public static int noaaON = 0; // for space weather
        public static int SFI = 0;       // for Space weather
        public static int Aindex = 0;    // for Space weather
        public static int Kindex = 0;    // for Space weather
        public static string RadioBlackout = " ";    // R scale
        public static string GeoBlackout = " ";      // G scale

        //=========================================================================================
        //=========================================================================================
        // ke9ns add to allow TX filter on main console SSB panel
        private void udTXFilterHigh_ValueChanged(object sender, EventArgs e)
        {
            if (initializing) return; // MW0LGE
            if (!IsSetupFormNull) SetupForm.TXFilterHigh = (int)udTXFilterHigh.Value;
        }

        // ke9ns add
        private void udTXFilterLow_ValueChanged(object sender, EventArgs e)
        {
            if (initializing) return; // MW0LGE
            if (!IsSetupFormNull) SetupForm.TXFilterLow = (int)udTXFilterLow.Value;
        }

        //=========================================================================================
        //=========================================================================================
        // ke9ns add send hygain rotor command to DDUtil via the CAT port setup in Thetis
        public string spotDDUtil_Rotor // called from SPOT.cs routine when clicking on DX SPOT
        {
            set
            {

                try
                {
                    Debug.WriteLine("DDUTIL ROTOR1:");
                    // siolisten1.SIO.put(value);   // this is the DDUtil PORT found in setup and SIOListenerIII.cs
                }
                catch { }
            }

        } // 

        //============================================================================
        //============================================================================
        //============================================================================
        // ke9ns add to allow extra control of group panels (ie rounded edges)
        public static GraphicsPath CreatePath(float x, float y, float width, float height,
                                      float radius, bool RoundTopLeft, bool RoundTopRight, bool RoundBottomRight, bool RoundBottomLeft)
        {
            float xw = x + width;
            float yh = y + height;
            float xwr = xw - radius;
            float yhr = yh - radius;
            float xr = x + radius;
            float yr = y + radius;
            float r2 = radius * 2;
            float xwr2 = xw - r2;
            float yhr2 = yh - r2;

            GraphicsPath p = new GraphicsPath();
            p.StartFigure();

            //Top Left Corner

            if (RoundTopLeft)
            {
                p.AddArc(x, y, r2, r2, 180, 90);
            }
            else
            {
                p.AddLine(x, yr, x, y);
                p.AddLine(x, y, xr, y);

            }

            //Top Edge
            p.AddLine(xr, y, xwr, y);

            //Top Right Corner

            if (RoundTopRight)
            {
                p.AddArc(xwr2, y, r2, r2, 270, 90);
            }
            else
            {
                p.AddLine(xwr, y, xw, y);
                p.AddLine(xw, y, xw, yr);
            }


            //Right Edge
            p.AddLine(xw, yr, xw, yhr);

            //Bottom Right Corner

            if (RoundBottomRight)
            {
                p.AddArc(xwr2, yhr2, r2, r2, 0, 90);
            }
            else
            {
                p.AddLine(xw, yhr, xw, yh);
                p.AddLine(xw, yh, xwr, yh);
            }


            //Bottom Edge
            p.AddLine(xwr, yh, xr, yh);

            //Bottom Left Corner           

            if (RoundBottomLeft)
            {
                p.AddArc(x, yhr2, r2, r2, 90, 90);
            }
            else
            {
                p.AddLine(xr, yh, x, yh);
                p.AddLine(x, yh, x, yhr);
            }

            //Left Edge
            p.AddLine(x, yhr, x, yr);

            p.CloseFigure();

            return p;

        }
        #endregion

        public void ForcePureSignalAutoCalDisable()
        {
            chkFWCATUBypass.Checked = false;
        }

        private void chkFWCATUBypass_CheckedChanged(object sender, EventArgs e)
        {
            bool oldState = psform.AutoCalEnabled;
            psform.AutoCalEnabled = chkFWCATUBypass.Checked;
            AndromedaIndicatorCheck(EIndicatorActions.eINPuresignalEnabled, false, chkFWCATUBypass.Checked);

            infoBar.PSAEnabled = psform.AutoCalEnabled;

            if (oldState && !psform.AutoCalEnabled) // was on, now off
            {
                //MW0LGE [2.10.3.6] PS in autocal might have enabled AttOnTX even though setup form option is disabled, fix this case
                if (!IsSetupFormNull)
                {
                    if (!SetupForm.ATTOnTXChecked) ATTOnTX = false;
                }
            }
        }

        public bool PureSignalEnabled
        {
            get { return chkFWCATUBypass.Checked; }
            set { chkFWCATUBypass.Checked = value; }
        }

        private bool _old_rx_ant_state = false;
        private void chkRxAnt_CheckedChanged(object sender, EventArgs e)
        {
            AlexAntCtrlEnabled = alex_ant_ctrl_enabled;
            SendAriesRXAntennaMsg();

            if(_old_rx_ant_state != chkRxAnt.Checked)
            {
                AntennaRxTxHandlers?.Invoke(_old_rx_ant_state, chkRxAnt.Checked);
                _old_rx_ant_state = chkRxAnt.Checked;
            }
        }

        private void chkQSK_CheckStateChanged(object sender, EventArgs e)
        {
            if (!IsSetupFormNull) SetupForm.BreakInEnabledState = chkQSK.CheckState;
        }

        //MW0LGE
        private void ptbPanMainRX_DoubleClick(object sender, EventArgs e)
        {
            ptbPanMainRX.Value = 50;
            radio.GetDSPRX(0, 0).Pan = 0.5f;
            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbPanMainRX.Focus();
            }
        }

        private void ptbPanSubRX_DoubleClick(object sender, EventArgs e)
        {
            ptbPanSubRX.Value = 50;
            radio.GetDSPRX(0, 1).Pan = 0.5f;
            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbPanSubRX.Focus();
            }
        }

        private void ptbRX2Pan_DoubleClick(object sender, EventArgs e)
        {
            ptbRX2Pan.Value = 50;
            radio.GetDSPRX(1, 0).Pan = 0.5f;
            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbRX2Pan.Focus();
            }
        }

        //MW0LGE
        private void setBackground()
        {
            if (m_bDisableBackgroundImage || m_imgBackground == null)
                Display.SetDX2BackgoundImage((Image)null);
            else
                Display.SetDX2BackgoundImage(m_imgBackground);
        }

        private Image m_imgBackground = null;
        private bool m_bDisableBackgroundImage = false;
        public bool DisableBackgroundImage
        {
            get { return m_bDisableBackgroundImage; }
            set
            {
                m_bDisableBackgroundImage = value;

                setBackground();
            }
        }
        public Image PicDisplayBackgroundImage
        {
            get {
                return m_imgBackground;
            }
            set {
                if(m_imgBackground != null)
                    m_imgBackground.Dispose();

                try
                {
                    m_imgBackground = value.Clone() as Image;
                }
                catch
                {
                    m_imgBackground = null;
                }

                setBackground();
            }
        }
        //-

        private bool m_bZoomShiftModifier = false;
        public bool ZoomShiftModifier {
            // enable/disable the use of the shift key zoom modifier
            // where holding shift will prevent the zoom from auto centering
            get { return m_bZoomShiftModifier; }
            set {
                m_bZoomShiftModifier = value;
            }
        }

        private bool m_bZoomShiftModifierReverse = false;
        public bool ZoomShiftModifierReverse {
            // reverses the action of the shiftzoom modifier
            get { return m_bZoomShiftModifierReverse; }
            set {
                m_bZoomShiftModifierReverse = value;
            }
        }

        private bool m_bShowSmallModeFilterOnVFOs = false;
        public bool ShowSmallModeFilterOnVFOs {
            get { return m_bShowSmallModeFilterOnVFOs; }
            set {
                m_bShowSmallModeFilterOnVFOs = value;

                if (_isexpanded)
                {
                    if (m_bShowSmallModeFilterOnVFOs)
                    {
                        lblModeLabel.Show();
                        lblFilterLabel.Show();
                        lblRX2ModeLabel.Show();
                        lblRX2FilterLabel.Show();
                    }
                    else
                    {
                        lblModeLabel.Hide();
                        lblFilterLabel.Hide();
                        lblRX2ModeLabel.Hide();
                        lblRX2FilterLabel.Hide();
                    }
                }
            }
        }

        #region RawInput
        // MW0LGE
        // RAWINPUT
        private void initialiseRawInput()
        {
            if (m_objRawinput != null)
            {
                m_objRawinput.MouseMoved -= OnMouseWheelChanged;
                m_objRawinput.DevicesChanged -= OnDevicesChanged;

                m_objRawinput.RemoveMessageFilter();

                m_objRawinput = null;
            }

            m_objRawinput = new RawInput(this.Handle, !m_bGlobalListenForMouseWheel, false);

            m_objRawinput.AddMessageFilter();

            updateRawInputDevices();

            m_objRawinput.MouseMoved += OnMouseWheelChanged;
            m_objRawinput.DevicesChanged += OnDevicesChanged;
            m_objRawinput.KeyPressed += OnKeyPressedRaw; //[2.10.3.6]MW0LGE now send to MeterManager
        }

        private void updateRawInputDevices()
        {
            if (IsSetupFormNull || m_objRawinput == null) return;

            SetupForm.UpdateRawInputMouseDevices(m_objRawinput.MouseDevices());
        }

        private bool m_bWheelTunesOutsideSpectral = false;
        public bool WheelTunesOutsideSpectral
        {
            get { return m_bWheelTunesOutsideSpectral; }
            set
            {
                m_bWheelTunesOutsideSpectral = value;
            }
        }

        private bool m_bGlobalListenForMouseWheel;
        public bool GlobalListenForMouseWheel
        {
            get
            {
                return m_bGlobalListenForMouseWheel;
            }
            set
            {
                m_bGlobalListenForMouseWheel = value;

                initialiseRawInput();
            }
        }

        private bool m_bWheelOnlyAdjustsVFO;
        public bool WheelOnlyAdjustsVFO
        {
            get
            {
                return m_bWheelOnlyAdjustsVFO;
            }
            set
            {
                m_bWheelOnlyAdjustsVFO = value;
            }
        }

        private bool m_bAlsoUseSpecificMouseWheel;
        public bool AlsoUseSpecificMouseWheel
        {
            get
            {
                return m_bAlsoUseSpecificMouseWheel;
            }
            set
            {
                m_bAlsoUseSpecificMouseWheel = value;
            }
        }

        private String m_sSpecificMouseDeviceID;
        public String SpecificMouseDeviceID
        {
            get
            {
                return m_sSpecificMouseDeviceID;
            }
            set
            {
                m_sSpecificMouseDeviceID = value;
            }
        }
        private IntPtr m_nSpecificMouseDeviceHandle;
        public IntPtr SpecificMouseDeviceHandle
        {
            get
            {
                return m_nSpecificMouseDeviceHandle;
            }
            set
            {
                m_nSpecificMouseDeviceHandle = value;
            }
        }

        private void OnDevicesChanged(object sender)
        {
            updateRawInputDevices();
        }

        private ConcurrentDictionary<Keys, bool> _keyPressed = new ConcurrentDictionary<Keys, bool>();
        private void OnKeyPressedRaw(object sender, RawInputEventArg e)
        {
            bool keyState = e.KeyPressEvent.KeyPressState.Equals("MAKE", StringComparison.OrdinalIgnoreCase);
            Keys key = (Keys)e.KeyPressEvent.VKey;

            if (keyState) // make is push to make
            {
                bool available = _keyPressed.TryGetValue(key, out bool current_state);

                if (!current_state)
                {
                    // sent to meter manager, so that it can detect presses in the VfoDisplay with no focus
                    MeterManager.GlobalKeyDown((Keys)e.KeyPressEvent.VKey);

                    //CWXForm
                    if (m_frmCWXForm != null) CWXForm.GlobalKeyDown((Keys)e.KeyPressEvent.VKey);

                    if(!available) _keyPressed.TryAdd(key, true);
                }
            }
            else
            {
                _keyPressed.TryRemove(key, out bool current_state);

                if (current_state) // was pressed
                {
                    // sent to meter manager, so that it can detect presses in the VfoDisplay with no focus
                    MeterManager.GlobalKeyUp((Keys)e.KeyPressEvent.VKey); // break is other state

                    //CWXForm
                    if (m_frmCWXForm != null) CWXForm.GlobalKeyUp((Keys)e.KeyPressEvent.VKey);
                }
            }
        }

        private void OnMouseWheelChanged(object sender, RawInputEventArg e)
        {
            if (!m_bAlsoUseSpecificMouseWheel) return; // ignore because we are not also using a specific mouse wheel

            if (e.MouseEvent.DeviceName == m_sSpecificMouseDeviceID)
            {
                // this is a bit of a cludge, but next mouse wheel event is ignored
                // this will 'arrive' as the next wm_mousewheel and will be the same
                // one associateed with this rawinput event
                m_objRawinput.IgnoreNextWheelEvent = m_bWheelOnlyAdjustsVFO;

                if (!IsSetupFormNull)
                {
                    if (SetupForm.Visible)
                    {
                        SetupForm.WheelChangeNotify();
                    }
                }

                enableOutsideSpectral();// allow outside spectral display for this secondary tuning device
                Console_MouseWheel(this, new MouseEventArgs(MouseButtons.None, 0, 0, 0, e.MouseEvent.buttonData));
                restoreOutsideSpectral();
            }
        }
        #endregion

        private void incrementMutliMeterDisplayMode()
        {
            // step through the display modes for the multimeter, smeter, dbm, uv, etc

            MultiMeterMeasureMode tmp = m_eMeasureMode;
            tmp++;
            if (tmp >= MultiMeterMeasureMode.LAST) tmp = MultiMeterMeasureMode.FIRST + 1;

            //set it through setupform so that settings are updated
            if (!IsSetupFormNull) SetupForm.SetMultiMeterMode(tmp);
        }

        private void txtMultiText_Click(object sender, EventArgs e)
        {
            incrementMutliMeterDisplayMode();
        }

        private void txtRX2Meter_Click(object sender, EventArgs e)
        {
            incrementMutliMeterDisplayMode();
        }

        private void toolStripStatusLabel_SeqWarning_Click(object sender, EventArgs e)
        {
            ShowSEQLog();
        }

        private void toolStripMenuItem_4by3_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            setResolution(e.ClickedItem.Text);
        }

        private void toolStripMenuItem_16by9_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            setResolution(e.ClickedItem.Text);
        }

        private void toolStripMenuItem_16by10_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            setResolution(e.ClickedItem.Text);
        }

        private void youTubeToolStripMenuItem_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            setResolution(e.ClickedItem.Text);
        }

        private void setResolution(string resolutionString)
        {
            if (resolutionString.Length < 1) return;

            int W = 0, H = 0;
            bool bOK = false;

            if (resolutionString[resolutionString.Length - 1] == 'p')
            {
                // youtube
                if (resolutionString == "720p")
                {
                    W = 1280; H = 720;
                }
                else if (resolutionString == "1080p")
                {
                    W = 1920; H = 1080;
                }
                else if (resolutionString == "1440p")
                {
                    W = 2560; H = 1440;
                }
                else if (resolutionString == "2160p")
                {
                    W = 3840; H = 2160;
                }
                else
                {
                    W = 1280; H = 720;
                }
                bOK = true;
            }
            else if (resolutionString.Contains(" x "))
            {
                // W x H
                int xPos = resolutionString.IndexOf("x");
                bOK = int.TryParse(resolutionString.Substring(0, xPos - 1), out W);
                if (bOK)
                    bOK = int.TryParse(resolutionString.Substring(xPos + 2), out H);
                //W = int.Parse(resolutionString.Substring(0, xPos - 1));
                //H = int.Parse(resolutionString.Substring(xPos + 2));
                //bOK = true;
            }

            if (bOK)
            {
                // limit to screen
                Rectangle r = Screen.FromControl(this).Bounds;
                W = Math.Min(W, r.Width);
                H = Math.Min(H, r.Height);

                if (this.WindowState == FormWindowState.Maximized) this.WindowState = FormWindowState.Normal;

                Size s = new Size(W, H);
                if (m_bIncludeWindowBorders)
                {
                    this.Size = s + DropShadowSize; // add in the drop shadow, so the edge to edge is actually what we want //MW0LGE_21a
                }
                else
                {
                    this.ClientSize = s;
                }
            }
        }

        private void includeBordersToolStripMenuItem_Click(object sender, EventArgs e)
        {
            IncludeWindowBorders = !IncludeWindowBorders;
        }

        private bool m_bDraggingMeter = false;
        private int m_nStartDragX = 0;
        private float m_fMeterPadRatio = 0f;

        private void pnlResizeMeter_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left && !m_bDraggingMeter)
            {
                m_nStartDragX = e.X;
                m_bDraggingMeter = true;
            }
        }

        private void pnlResizeMeter_MouseMove(object sender, MouseEventArgs e)
        {
            if (m_bDraggingMeter)
            {
                int nDelta = e.X - m_nStartDragX;

                int oldLeft = grpMultimeter.Left;
                int newLeft = nDelta + grpMultimeter.Left;

                if (newLeft < grpVFOB.Right + 8)
                {
                    newLeft = grpVFOB.Right + 8;
                }
                if (newLeft > grpMultimeterMenus.Left)
                {
                    newLeft = grpMultimeterMenus.Left;
                }

                Rectangle r = new Rectangle(grpMultimeter.Location, grpMultimeter.Size);

                SuspendDrawing(grpMultimeter);
                grpMultimeter.Left = newLeft;
                grpMultimeter.Width += (oldLeft - grpMultimeter.Left);

                txtMultiText.Size = new Size(grpMultimeter.Size.Width - (gr_multi_meter_size_basis.Width - txt_multi_text_size_basis.Width), txt_multi_text_size_basis.Height);
                picMultiMeterDigital.Size = new Size(grpMultimeter.Size.Width - (gr_multi_meter_size_basis.Width - pic_multi_meter_size_basis.Width), pic_multi_meter_size_basis.Height);
                ResumeDrawing(grpMultimeter, false);

                this.Invalidate(r, true);
                this.Update();

                m_fMeterPadRatio = (float)(newLeft - (grpVFOB.Right + 8)) / (float)(grpMultimeterMenus.Left - (grpVFOB.Right + 8));
            }
        }

        private void pnlResizeMeter_MouseUp(object sender, MouseEventArgs e)
        {
            m_bDraggingMeter = false;
        }

        private void pnlResizeMeter_MouseEnter(object sender, EventArgs e)
        {
            pnlResizeMeter.BackColor = SystemColors.MenuHighlight;
        }

        private void pnlResizeMeter_MouseLeave(object sender, EventArgs e)
        {
            pnlResizeMeter.BackColor = Color.Transparent;
        }

        private void systemToolStripMenuItem_Click(object sender, EventArgs e)
        {
            m_bShowSystemCPUUsage = true;
            CpuUsage();
        }

        private void thetisOnlyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            m_bShowSystemCPUUsage = false;
            CpuUsage();
        }
        #region QSOTimer
        //qso timer
        private bool m_bQSOTimerEnabled = false;
        private BasicAudio m_objQSOTimerBasicAudio;
        private int m_nQSOTimerSeconds = 0;
        private bool m_bQSOTimerRunning = false;
        private bool m_bQSOTimerDuringMoxOnly = false;
        private int m_nQSODuration = 600;
        private bool m_bQSOAlarmSoundPlayed = false;
        private bool m_bQSOResetTimerOnMox = false;
        private bool m_bQSOTimerPlayOnExpiry = false;
        private bool m_bQSOTimerResetOnExpiry = false;
        private bool m_bQSOTimerFlashing = false;
        private bool m_bQSOTimerFlashAfterAutoReset = false;
        public bool QSOTimerFlashing
        {
            get { return m_bQSOTimerFlashing; }
        }
        public int QSOTimerSeconds
        {
            get { return m_nQSOTimerSeconds; }
        }
        public bool QSOTimerFlashAfterAutoReset {
            get { return m_bQSOTimerFlashAfterAutoReset; }
            set { m_bQSOTimerFlashAfterAutoReset = value; }
        }
        public bool QSOTimerResetOnExpiry {
            get { return m_bQSOTimerResetOnExpiry; }
            set { m_bQSOTimerResetOnExpiry = value; }
        }
        public bool QSOTimerPlayOnExpiry {
            get { return m_bQSOTimerPlayOnExpiry; }
            set { m_bQSOTimerPlayOnExpiry = value; }
        }
        public int QSOTimerDuration {
            get { return m_nQSODuration; }
            set { m_nQSODuration = value; }
        }
        public BasicAudio QSOTimerAudioPlayer {
            get {
                if (m_objQSOTimerBasicAudio == null)
                {
                    m_objQSOTimerBasicAudio = new BasicAudio();
                    m_objQSOTimerBasicAudio.LoadCompletedEvent += basicAudioLoadCompletedEvent;
                }
                return m_objQSOTimerBasicAudio;
            }
            set { }
        }
        public bool QSOTimerEnabled {
            get { return m_bQSOTimerEnabled; }
            set {
                // always disable the timer
                QSOTimerRunning = false;
                QSOTimerReset();
                //

                m_bQSOTimerEnabled = value;
                toolStripStatusLabel_timer.Visible = m_bQSOTimerEnabled;
            }
        }
        private void basicAudioLoadCompletedEvent(bool bLoadedOk)
        {
            //if (bLoadedOk) QSOTimerAudioPlayer.Play();
        }

        private bool QSOTimerRunning {
            get { return m_bQSOTimerRunning; }
            set {
                m_bQSOTimerRunning = value;
                updateQSOTimerStatusbar();
            }
        }
        public bool QSOTimerDuringMoxOnly {
            get { return m_bQSOTimerDuringMoxOnly; }
            set {
                bool bOld = m_bQSOTimerDuringMoxOnly;
                m_bQSOTimerDuringMoxOnly = value;

                if (!bOld && m_bQSOTimerDuringMoxOnly)
                {
                    // if previously false, and now true, set running based on mox state
                    QSOTimerRunning = _mox;
                }
            }
        }

        public bool QSOTimerResetOnMox {
            get { return m_bQSOResetTimerOnMox; }
            set {
                m_bQSOResetTimerOnMox = value;
            }
        }

        public void QSOTimerReset(bool bAutoReset = false)
        {
            if (bAutoReset)
            {
                // only stop the flash after an auto reset if required
                if (!m_bQSOTimerFlashAfterAutoReset) m_bQSOTimerFlashing = false;
            }
            else
            {
                // always stop the sound, and stop flashing
                QSOTimerAudioPlayer.Stop();
                m_bQSOTimerFlashing = false;
            }

            m_nQSOTimerSeconds = 0;
            m_bQSOAlarmSoundPlayed = false;
            updateQSOTimerStatusbar();
        }
        private void toolStripStatusLabel_timer_Click(object sender, EventArgs e)
        {
            if (m_bQSOTimerFlashing) // if we click it when it is flashing, clear the flashing
            {
                m_bQSOTimerFlashing = false;
                if (m_bQSOTimerResetOnExpiry) return; // dont toggle if we were flashing in the resetonexpiry mode
            }

            if (QSOTimerDuringMoxOnly) return; // ignore clicks if we are switching on mox only

            QSOTimerRunning = !QSOTimerRunning; // toggle timer off/on
        }

        private void toolStripStatusLabel_timer_MouseUp(object sender, MouseEventArgs e)
        {
            // cant check right button in toolstrip click event, so need to do it here
            // reset on right click
            if (e.Button == MouseButtons.Right) QSOTimerReset();
        }

        private void updateQSOTimer()
        {
            if (!(m_bQSOTimerEnabled && m_bQSOTimerRunning)) return;

            m_nQSOTimerSeconds++; // increment seconds only if timer running
            if (m_nQSOTimerSeconds > 3599) m_nQSOTimerSeconds = 3599; // cap it to 59 mins, 59 seconds
        }

        private void updateQSOTimerStatusbar()
        {
            if (!m_bQSOTimerEnabled) return;

            //setup the image on statusbar
            if (m_bQSOTimerRunning)
                toolStripStatusLabel_timer.Image = m_imgTimer_on;
            else
                toolStripStatusLabel_timer.Image = m_imgTimer_off;

            if (m_bQSOTimerRunning && m_nQSOTimerSeconds >= m_nQSODuration)
            {
                // timer has elapsed !
                m_bQSOTimerFlashing = true;

                if (m_bQSOTimerPlayOnExpiry && !m_bQSOAlarmSoundPlayed)
                {
                    QSOTimerAudioPlayer.Play();
                    m_bQSOAlarmSoundPlayed = true;
                }

                if (m_bQSOTimerResetOnExpiry) QSOTimerReset(true);
            }

            // flash the text if needed
            if (m_bQSOTimerRunning && m_bQSOTimerFlashing)
            {
                if (toolStripStatusLabel_timer.ForeColor == toolStripDropDownButton_ScreenSize.ForeColor)
                    toolStripStatusLabel_timer.ForeColor = ControlPaint.Dark(toolStripDropDownButton_ScreenSize.ForeColor);
                else
                    toolStripStatusLabel_timer.ForeColor = toolStripDropDownButton_ScreenSize.ForeColor;
            }
            else
            {
                if (toolStripStatusLabel_timer.ForeColor != toolStripDropDownButton_ScreenSize.ForeColor)
                    toolStripStatusLabel_timer.ForeColor = toolStripDropDownButton_ScreenSize.ForeColor;
            }

            // update the seconds
            TimeSpan t = TimeSpan.FromSeconds(m_nQSOTimerSeconds);
            toolStripStatusLabel_timer.Text = t.ToString(@"mm\:ss");
        }
        //end qso timer
        #endregion

        //-- RIGHT click on control shows related setup page // refactored
        private void chkNR_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.NR_Tab);
        }

        private void chkRX2NR_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.NR_Tab);
        }

        private void chkNB_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.NB_Tab);
        }
        private void chkDSPNB2_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.NB_Tab);
        }
        private void chkRX2NB_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.NB_Tab);
        }
        private void chkRX2NB2_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.NB_Tab);
        }
        private void radModeCWL_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.CW_Tab);
        }
        private void radModeCWU_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.CW_Tab);
        }
        private void chkVAC1_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.VAC1_Tab);
        }
        private void chkVAC2_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.VAC2_Tab);
        }
        private void radModeAM_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.AM_Tab);
        }
        private void radModeSAM_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.AM_Tab);
        }
        private void chkCWAPFEnabled_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.DSPAudio_Tab);
        }
        private void chkTNF_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.MNF_Tab);
        }
        private void chkVOX_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.VOXDE_Tab);
        }
        private void chkCPDR_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.CFC_Tab);
        }
        private void chkNoiseGate_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.VOXDE_Tab);
        }
        private void radModeFMN_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.FM_Tab);
        }
        private void comboAGC_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.ALCAGC_Tab);
        }
        private void chkMicMute_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.Transmit_Tab);
        }
        private void comboTXProfile_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.Transmit_Tab);
        }
        private void lblRF_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.ALCAGC_Tab);
        }
        private bool IsRightButton(MouseEventArgs e)
        {
            return e.Button == MouseButtons.Right;
        }
        //--
        protected override bool ProcessDialogKey(Keys keyData)
        {
            // MW0LGE generate arrow key presses by passing them to console_keydown
            // Arrow keys are not detected in keydown events
            // Should now be able to use Up/Down/Left/Right in keyboard config
            switch (keyData)
            {
                case Keys.Down:
                case Keys.Up:
                case Keys.Left:
                case Keys.Right:
                    Console_KeyDown(this, new KeyEventArgs(keyData));
                    return true;
            }
            return base.ProcessDialogKey(keyData);
        }
        //--
        private bool checkVersions()
        {
            int nCMasterVersion = -1;
            int nCMasterAsioVersion = -1;
            int nWDSPVersion = -1;
            int nPAVersion = -1;

            // channelmaster.dll
            try
            {
                nCMasterVersion = cmaster.GetCMVersion();
                if (nCMasterVersion != Versions._CMASTER_VERSION)
                {
                    DialogResult dr = MessageBox.Show("Incorrect version of channelmaster.dll installed.",
                    "Version error",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                }
            }
            catch
            {
                DialogResult dr = MessageBox.Show("Could not find GetCMVersion() in channelmaster.dll .\nEnsure correct version installed.",
                    "Version function error",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
            }

            //cmASIO.dll
            try
            {
                nCMasterAsioVersion = cmaster.GetCMasioVersion();
                if (nCMasterAsioVersion != Versions._CMASTER_ASIO_VERSION)
                {
                    DialogResult dr = MessageBox.Show("Incorrect version of cmASIO.dll installed.",
                    "Version error",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
                }
            }
            catch
            {
                DialogResult dr = MessageBox.Show("Could not find GetCMasioVersion() in cmASIO.dll .\nEnsure correct version installed.",
                    "Version function error",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, Common.MB_TOPMOST);
            }
            
            // wdsp.dll
            // Version number is in version.c where it is 121.  *10 to match Versions.WDSP_VERSION
            try
            {
                nWDSPVersion = WDSP.GetWDSPVersion() * 10; // see comment above
                if (nWDSPVersion != Versions._WDSP_VERSION)
                {
                    DialogResult dr = MessageBox.Show("Incorrect version of wdsp.dll installed.",
                    "Version error",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Warning);
                }
            }
            catch
            {
                DialogResult dr = MessageBox.Show("Could not find GetWDSPVersion() in wdsp.dll .\nEnsure correct version installed.",
                    "Version function error",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Warning);
            }

            // PortAudio.dll
            try
            {
                nPAVersion = PA19.PA_GetVersion();
                int major = (nPAVersion >> 16) & 0xFF;
                int minor = (nPAVersion >> 8) & 0xFF;
                int subminor = nPAVersion & 0xFF;
                nPAVersion = major * 100 + minor * 10 + subminor;
                if (nPAVersion != Versions._PORTAUDIO_VERSION)
                {
                    DialogResult dr = MessageBox.Show("Incorrect version of portaudio.dll installed.",
                    "Version error",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Warning);
                }
            }
            catch
            {
                DialogResult dr = MessageBox.Show("Could not find PA_GetVersion() in portaudio.dll .\nEnsure correct version installed.",
                    "Version function error",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Warning);
            }

            bool bRet = (nCMasterVersion == Versions._CMASTER_VERSION) &&
                   (nCMasterAsioVersion == Versions._CMASTER_ASIO_VERSION) &&
                   (nWDSPVersion == Versions._WDSP_VERSION) &&
                   (nPAVersion == Versions._PORTAUDIO_VERSION);

            return bRet;
        }

        // set TX antenna to 1,2 or 3
        private void ToolStripMenuItem15_Click(object sender, EventArgs e)
        {
            SetNewTXAntenna(2);
        }

        private void ToolStripMenuItem16_Click(object sender, EventArgs e)
        {
            SetNewTXAntenna(1);
        }

        private void ToolStripMenuItem17_Click(object sender, EventArgs e)
        {
            SetNewTXAntenna(3);
        }

        private void ToolStripMenuItem18_Click(object sender, EventArgs e)
        {
            SetNewRXAntenna(3);
        }

        private void ToolStripMenuItem19_Click(object sender, EventArgs e)
        {
            SetNewRXAntenna(2);
        }

        private void ToolStripMenuItem20_Click(object sender, EventArgs e)
        {
            SetNewRXAntenna(1);
        }

        private void Console_Shown(object sender, EventArgs e)
        {
            updateResolutionStatusBarText(); //MW0LGE_21b need to call this here so that drop shadow sizes can be obtained

            // set the multifunction setting to the status bar
            DataTable multitable = AndromedaSet.Tables["Multifunction Settings"];
            toolStripStatusLabelAndromedaMulti.Text = multitable.Rows[CurrentMultifunctionOption]["Multi Description"].ToString();

            // NOTE: Important if you are ading more items to the status bar
            // MW0LGE_21e could not get the designer to keep widths of these
            // so force them here
            toolStripDropDownButton_ScreenSize.Width = 110;
            toolStripDropDownButton_CPU.Width = 68;
            toolStripStatusLabel_Volts.Width = 60;
            toolStripStatusLabel_Amps.Width = 50;
            toolStripStatusLabel_SeqWarning.Width = 18;
            toolStripStatusLabel_TXInhibit.Width = 18;
            toolStripStatusLabelRXAnt.Width = 90;
            toolStripStatusLabelTXAnt.Width = 90;
            toolStripStatusLabelAndromedaMulti.Width = 140;

            toolStripStatusLabel_N1MM.Width = 22;
            toolStripStatusLabel_TCI.Width = 22;
            toolStripStatusLabel_CatTCPip.Width = 22;
            toolStripStatusLabel_CatSerial.Width = 22;
            toolStripStatusLabel_CMstatus.Width = 22;

            toolStripStatusLabel_timer.Width = 80;
            toolStripStatusLabel_UTCTime.Width = 92;
            toolStripStatusLabel_Date.Width = 104;
            toolStripStatusLabel_LocalTime.Width = 92;
        }

        //private bool twoTone = false;
        public bool Manual2Tone
        {
            get { return chk2TONE.Checked; }
            set { chk2TONE.Checked = value; }
        }
        private async void chk2TONE_CheckedChanged(object sender, EventArgs e)
        {
            if (SetupForm.TestIMD == chk2TONE.Checked) return; // same state ignore

            // stop tune if currently running and we want to run 2tone
            if (chk2TONE.Checked && chkTUN.Checked)
            {
                //dont want this to fire the checked changed event late, so unlink it, call it, then relink it
                chkTUN.CheckedChanged -= new System.EventHandler(chkTUN_CheckedChanged);
                chkTUN.Checked = false;
                chkTUN_CheckedChanged(this, EventArgs.Empty); // it needs to happen here and now
                chkTUN.CheckedChanged += new System.EventHandler(chkTUN_CheckedChanged);
                await Task.Delay(300);
            }

            SetupForm.TestIMD = chk2TONE.Checked; // this will start/stop the test

            if (SetupForm.TestIMD && chk2TONE.Checked)
            { // we are running all ok
                chk2TONE.BackColor = button_selected_color;
            }
            else if (!SetupForm.TestIMD && chk2TONE.Checked)
            { // we tried to run but there was a problem
                chk2TONE.BackColor = SystemColors.Control;
                chk2TONE.Checked = false;
            }
            else
            {
                chk2TONE.BackColor = SystemColors.Control;
            }

            setupTuneDriveSlider(); // MW0LGE_22b
        }

        private void ucQuickRecallPad_ButtonClicked(object sender, EventArgs e)
        {
            // removes focus from any quickrecall button
            btnHidden.Focus();
        }

        private void lblBandStack_Click(object sender, EventArgs e)
        {
            //MW0LGE_21d band stack 2
            showBandStack();
        }

        //MW0LGE_21d3
        private string m_sOverControlName = "";
        private void getControl(Control cc, Point p, string sub)
        {
            Control c = cc.GetChildAtPoint(p);

            if (c == null) {
                m_sOverControlName = "";
                return;
            }

            if (c.GetType() == typeof(PanelTS) || c.GetType() == typeof(GroupBoxTS) || c.GetType() == typeof(ucQuickRecall))
            {
                if (!string.IsNullOrEmpty(sub))
                {
                    getControl(c, new Point(p.X - c.Location.X, p.Y - c.Location.Y), sub + " > " + c.Name + " (" + c.Size.Width.ToString() + " x " + c.Size.Height.ToString() + ")");
                }
                else
                {
                    getControl(c, new Point(p.X - c.Location.X, p.Y - c.Location.Y), c.Name + " (" + c.Size.Width.ToString() + " x " + c.Size.Height.ToString() + ")");
                }
            }
            else
            {
                if (!string.IsNullOrEmpty(sub))
                {
                    m_sOverControlName = sub + " > " + c.Name + " (" + c.Size.Width.ToString() + " x " + c.Size.Height.ToString() + ")";
                }
                else
                {
                    m_sOverControlName = c.Name + " (" + c.Size.Width.ToString() + " x " + c.Size.Height.ToString() + ")";
                }
            }
        }
        private void gmh_MouseMove(object sender, MouseEventArgs e)
        {
            if (EnableControlDebug)
            {
                string sTmp = m_sOverControlName;
                getControl(this, this.PointToClient(e.Location), "");
                if (m_sOverControlName != sTmp) Display.DebugText = m_sOverControlName;
            }
        }
        private bool m_bEnableControlDebug = false;
        public bool EnableControlDebug
        {
            get { return m_bEnableControlDebug; }
            set {
                if (!value) Display.DebugText = "";
                m_bEnableControlDebug = value;

                ////for power xmeter config
                //nudPwrTemp.Visible = m_bEnableControlDebug;
                //nudPwrTemp2.Visible = m_bEnableControlDebug;
            }
        }
        private bool m_bEnableDisplayDebug = false;
        public bool EnableDisplayDebug
        {
            get { return m_bEnableDisplayDebug; }
            set
            {
                if (!value) Display.DebugText = "";
                m_bEnableDisplayDebug = value;
            }
        }

        #region NewDelegateSystem
        //-------------------------------
        // MW0LGE_21b A move towards delegate/event based system
        public delegate void BandPreChange(int rx, Band band);
        public delegate void BandNoChange(int rx, Band band);
        public delegate void BandChanged(int rx, Band oldBand, Band newBand);
        public delegate void ModeChanged(int rx, DSPMode oldMode, DSPMode newMode, Band oldBand, Band newBand);
        public delegate void VFOAFrequencyChanged(Band oldBand, Band newBand, DSPMode oldMode, DSPMode newMode, Filter oldFilter, Filter newFilter, double oldFreq, double newFreq, double oldCentreF, double newCentreF, bool oldCTUN, bool newCTUN, int oldZoomSlider, int newZoomSlider, double offset, int rx);
        public delegate void VFOBFrequencyChanged(Band oldBand, Band newBand, DSPMode oldMode, DSPMode newMode, Filter oldFilter, Filter newFilter, double oldFreq, double newFreq, double oldCentreF, double newCentreF, bool oldCTUN, bool newCTUN, int oldZoomSlider, int newZoomSlider, double offset, int rx);
        public delegate void VFOASubFrequencyChanged(Band oldBand, Band newBand, DSPMode newMode, Filter newFilter, double oldFreq, double newFreq, double newCentreF, bool newCTUN, int newZoomSlider, double offset, int rx);
        public delegate void MoxChanged(int rx, bool oldMox, bool newMox);
        public delegate void MoxPreChanged(int rx, bool currentMox, bool expectedMox);
        public delegate void SetBandChanged(int rx, Band oldBand, Band newBand, DSPMode oldMode, DSPMode newMode, Filter oldFilter, Filter newFilter, double oldFreq, double newFreq, double oldCentreF, double newCentreF, bool oldCTUN, bool newCTUN, int oldZoomSlider, int newZoomSlider);
        public delegate void PowerChanged(bool oldPower, bool newPower);

        public delegate void CentreFrequencyChanged(int rx, double oldFreq, double newFreq, Band band, double offset);
        public delegate void CTUNChanged(int rx, bool oldCTUN, bool newCTUN, Band band);
        public delegate void FilterChanged(int rx, Filter oldFilter, Filter newFilter, Band band, int low, int high, string sName);
        public delegate void ZoomFactorChanged(double oldZoomFactor, double newZoomFactor, int sliderValue);

        public delegate void AttenuatorDataChanged(int rx, int oldAtt, int newAtt);
        public delegate void PreampModeChanged(int rx, PreampMode oldMode, PreampMode newMode);

        public delegate void FilterEdgesChanged(int rx, Filter filter, Band band, int low, int high, string sName);
        public delegate void SplitChanged(int rx, bool oldSplit, bool newSplit);
        public delegate void TuneChanged(int rx, bool oldTune, bool newTune);
        public delegate void DrivePowerChanged(int rx, int newPower, bool tune);
        public delegate void SampleRateChanged(int rx, int oldSampleRate, int newSampleRate);
        public delegate void ThetisFocusChanged(bool focus);
        public delegate void RX2EnabledChanged(bool enabled);
        public delegate void RX2EnabledPreChanged(bool enabled); // before the change
        public delegate void SpotClicked(string callsign, long frequencyHz, int rx = -1, bool vfoB = false);
        public delegate void MultiRxChanged(bool newState, bool oldState, double vfoASubFrequency, Band band, bool rx2Enabled);

        public delegate void VFOTXChanged(bool vfoB, bool oldState, bool newState);
        public delegate void TXBandChanged(Band oldBand, Band newBand, double tx_frequency);

        public delegate void TCPIPcatClientConnected();
        public delegate void TCPIPcatClientDisconnected();
        public delegate void TCPIPcatClientError(SocketException se);
        public delegate void TCPIPcatServerError(SocketException se);

        public delegate void MeterReadings(int rx, bool tx, ref Dictionary<Reading, float> readings);

        public delegate void AlexPresentChanged(bool oldSetting, bool newSetting);
        public delegate void PAPresentChanged(bool oldSetting, bool newSetting);
        public delegate void ApolloPresentChanged(bool oldSetting, bool newSetting);
        public delegate void CurrentModelChanged(HPSDRModel oldModel, HPSDRModel newModel);
        public delegate void TransverterIndexChanged(int oldIndex, int newIndex);

        public delegate void TXInhibitChanged(bool oldState, bool newState);

        public delegate void MuteChanged(int rx, bool oldState, bool newState);
        public delegate void MONChanged(bool oldState, bool newState);
        public delegate void MONVolumeChanged(int oldVolume, int newVolume);

        public delegate void EQChanged(bool oldState, bool newState);
        public delegate void LevelerChanged(bool oldState, bool newState);
        public delegate void CFCChanged(bool oldState, bool newState);
        public delegate void CompandChanged(bool oldState, bool newState);

        public delegate void QuickSplitChanged(bool oldState, bool newState);

        public delegate void WindowStateChanged(FormWindowState state);

        public delegate void BandPanelChanged(int rx, bool gen, bool hf, bool vhf);
        public delegate void VHFChanged(int idx, bool old_state, bool new_state, string old_text, string new_text);
        public delegate void FilterNameChanged(int rx, Filter f, string old_name, string new_name);

        public delegate void AntennaRXChanged(Band b, int antenna, bool old_state, bool new_state);
        public delegate void AntennaTXChanged(Band b, int antenna, bool old_state, bool new_state);
        public delegate void AntennaAuxChanged(Band b, int antenna, bool old_state, bool new_state, string button_text);
        public delegate void AntennaDoNotTXChanged(int antenna, bool old_state, bool new_state);
        public delegate void AntennaRxTxChanged(bool old_state, bool new_state);

        public delegate void TXFrequncyChanged(double old_frequency, double new_frequency, Band old_band, Band new_band);

        public delegate void VfoALockChanged(int rx, bool old_state, bool new_state);
        public delegate void VfoBLockChanged(int rx, bool old_state, bool new_state);

        public delegate void VFOSyncChanged(int rx, bool old_state, bool new_state);

        public delegate void TuneStepIndexChanged(int rx, int old_index, int new_index);

        public delegate void PAProfileNameChanged(string old_profile_name, string new_profile_name);

        public BandPreChange BandPreChangeHandlers; // when someone clicks a band button, before a change is made
        public BandNoChange BandNoChangeHandlers;
        public BandChanged BandChangeHandlers;
        public ModeChanged ModeChangeHandlers;
        public VFOAFrequencyChanged VFOAFrequencyChangeHandlers;
        public VFOBFrequencyChanged VFOBFrequencyChangeHandlers;
        public VFOASubFrequencyChanged VFOASubFrequencyChangeHandlers;
        public MoxChanged MoxChangeHandlers;
        public MoxPreChanged MoxPreChangeHandlers;
        public SetBandChanged SetBandChangeHanders;
        public PowerChanged PowerChangeHanders;

        public CentreFrequencyChanged CentreFrequencyHandlers;
        public CTUNChanged CTUNChangedHandlers;
        public FilterChanged FilterChangedHandlers;
        public ZoomFactorChanged ZoomFactorChangedHandlers;

        public AttenuatorDataChanged AttenuatorDataChangedHandlers;
        public PreampModeChanged PreampModeChangedHandlers;

        public FilterEdgesChanged FilterEdgesChangedHandlers;
        public SplitChanged SplitChangedHandlers;
        public TuneChanged TuneChangedHandlers;
        public DrivePowerChanged DrivePowerChangedHandlers;
        public SampleRateChanged SampleRateChangedHandlers;
        public ThetisFocusChanged ThetisFocusChangedHandlers;
        public RX2EnabledChanged RX2EnabledChangedHandlers;
        public RX2EnabledPreChanged RX2EnabledPreChangedHandlers;
        public SpotClicked SpotClickedHandlers;
        public MultiRxChanged MultiRxHandlers;

        public VFOTXChanged VFOTXChangedHandlers;
        public TXBandChanged TXBandChangeHandlers;

        public MeterReadings MeterReadingsChangedHandlers;

        public AlexPresentChanged AlexPresentChangedHandlers;
        public PAPresentChanged PAPresentChangedHandlers;
        public ApolloPresentChanged ApolloPresentChangedHandlers;
        public CurrentModelChanged CurrentModelChangedHandlers;
        public TransverterIndexChanged TransverterIndexChangedHandlers;

        public TXInhibitChanged TXInhibitChangedHandlers;

        public MuteChanged MuteChangedHandlers;
        public MONChanged MONChangedHandlers;
        public MONVolumeChanged MONVolumeChangedHandlers;

        public EQChanged EQChangedHandlers;
        public LevelerChanged LevelerChangedHandlers;
        public CFCChanged CFCChangedHandlers;
        public CompandChanged CompandChangedHandlers;

        public QuickSplitChanged QuickSplitChangedHandlers;

        public WindowStateChanged WindowStateChangedHandlers;

        public BandPanelChanged BandPanelChangeHandlers;
        public VHFChanged VHFDetailsChangedHandlers;
        //public FilterNameChanged FilterNameChangedHandlers;

        public AntennaRXChanged AntennaRXChangedHandlers;
        public AntennaTXChanged AntennaTXChangedHandlers;
        public AntennaAuxChanged AntennaAuxChangedHandlers;
        public AntennaDoNotTXChanged AntennaDoNotTXHandlers;
        public AntennaRxTxChanged AntennaRxTxHandlers;

        public TXFrequncyChanged TXFrequncyChangedHandlers;

        public VfoALockChanged VfoALockChangedHandlers;
        public VfoBLockChanged VfoBLockChangedHandlers;

        public VFOSyncChanged VFOSyncChangedHandlers;

        public TuneStepIndexChanged TuneStepIndexChangedHandlers;

        public PAProfileNameChanged PAProfileNameChangedHandlers;

        private bool m_bIgnoreFrequencyDupes = false;               // if an update is to be made, but the frequency is already in the filter, ignore it
        private bool m_bHideBandstackWindowOnSelect = false;        // hide the window if an entry is selected
        private bool m_bShowBandStackOverlays = false;                     // show bandstack entries on the spectrum
        private bool m_bBandStackOverlayClicked = false;        // we have clicked an overlay
        private void addDelegates()
        {
            // note: all commented handlers are not used in console, but here as a record
            m_frmNotchPopup.NotchDeleteEvent += onNotchDelete;
            m_frmNotchPopup.NotchBWChangedEvent += onBWChanged;
            m_frmNotchPopup.NotchActiveChangedEvent += onActiveChanged;
            m_frmSeqLog.ClearButtonEvent += onClearButton;
            BandPreChangeHandlers += OnBandBeforeChangeHandler;            // just a band button is pressed
            BandChangeHandlers += OnBandChangeHandler;                  // band was changed
            ModeChangeHandlers += OnModeChangeHandler;                  // mode was changed
            VFOAFrequencyChangeHandlers += OnVFOAFrequencyChangeHandler;    //VFOA changed
            VFOBFrequencyChangeHandlers += OnVFOBFrequencyChangeHandler;    //VFOB changed
            MoxChangeHandlers += OnMoxChangeHandler;                    // mox changed
            SetBandChangeHanders += OnSetBandChangeHander;              // SetBand completed
            PowerChangeHanders += OnPowerChangeHander;                  // power state changed
            CentreFrequencyHandlers += OnCentreFrequencyChanged;        // centrefreq's changed
            CTUNChangedHandlers += OnCTUNChanged;                       // CTUN state changed
            FilterChangedHandlers += OnFilterChanged;                   // filters changed
            ZoomFactorChangedHandlers += OnZoomChanged;                 // zoom changed
            PreampModeChangedHandlers += OnPreampModeChanged;                 // preamp mode change
            VFOTXChangedHandlers += OnVFOTXChanged;
            TXInhibitChangedHandlers += OnTXInhibitChanged;

            Display.SetupDelegates();
            
            TimeOutTimerManager.SetCallback(timeOutTimer);
        }
        private void removeDelegates()
        {
            m_frmNotchPopup.NotchDeleteEvent -= onNotchDelete;
            m_frmNotchPopup.NotchBWChangedEvent -= onBWChanged;
            m_frmNotchPopup.NotchActiveChangedEvent -= onActiveChanged;
            m_frmSeqLog.ClearButtonEvent -= onClearButton;
            BandPreChangeHandlers -= OnBandBeforeChangeHandler;
            BandChangeHandlers -= OnBandChangeHandler;
            ModeChangeHandlers -= OnModeChangeHandler;
            VFOAFrequencyChangeHandlers -= OnVFOAFrequencyChangeHandler;
            VFOBFrequencyChangeHandlers -= OnVFOBFrequencyChangeHandler;
            MoxChangeHandlers -= OnMoxChangeHandler;
            SetBandChangeHanders -= OnSetBandChangeHander;
            CentreFrequencyHandlers -= OnCentreFrequencyChanged;
            CTUNChangedHandlers -= OnCTUNChanged;
            FilterChangedHandlers -= OnFilterChanged;
            ZoomFactorChangedHandlers -= OnZoomChanged;
            PowerChangeHanders -= OnPowerChangeHander;
            PreampModeChangedHandlers -= OnPreampModeChanged;
            VFOTXChangedHandlers -= OnVFOTXChanged;
            TXInhibitChangedHandlers -= OnTXInhibitChanged;

            if (m_frmBandStack2 != null) // dont use the singleton accessor as we dont want to make one if one does not exist
            {
                BandStack2Form.EntrySelectedHandlers -= OnEntryClicked; // added in the forms Singleton function BandStack2Form
                BandStack2Form.EntryAddHandlers -= OnEntryAdd;
                BandStack2Form.EntryDeleteHandlers -= OnEntryDelete;
                BandStack2Form.EntryUpdateHandlers -= OnEntryUpdate;
                BandStack2Form.IgnoreDupeHandlers -= OnIgnoreDupes;
                BandStack2Form.HideOnSelectHandlers -= OnHideOnSelect;
                BandStack2Form.ShowInSpectrumHandlers -= OnShowInSpectrum;

                m_frmBandStack2.RemoveDelegates();
            }

            Display.RemoveDelegates();
            TimeOutTimerManager.RemoveCallback(timeOutTimer);
        }
        //
        private bool _stop_all_tx = false;
        public void StopAllTx(string msg = "")
        {
            if (MOX || manual_mox || chkTUN.Checked || chk2TONE.Checked)
            {
                _stop_all_tx = true;

                MOX = false;
                manual_mox = false;
                if (chkTUN.Checked)
                    chkTUN.Checked = false;
                if (chk2TONE.Checked)
                    chk2TONE.Checked = false;

                if (!string.IsNullOrEmpty(msg))
                {
                    infoBar.Warning(msg, false, 10000);
                }
            }
        }
        private void timeOutTimer(string msg)
        {
            if (MOX || manual_mox || chkTUN.Checked || chk2TONE.Checked)
            {
                //everything off !!
                StopAllTx(msg + " Time Out Timer");                
            }
        }

        private void OnTXInhibitChanged(bool oldState, bool newState)
        {
            TXInhibit = newState;
        }

        private void OnVFOTXChanged(bool vfoB, bool oldState, bool newState)
        {
            // cat broadcast for Kenwood AI
            if (KWAutoInformation)
                BroadcastVFOChange(vfoB ? "1" : "0");
        }
        private void OnIgnoreDupes(bool ignore)
        {
            m_bIgnoreFrequencyDupes = ignore;
        }
        private void OnHideOnSelect(bool hideOnSelect)
        {
            m_bHideBandstackWindowOnSelect = hideOnSelect;
        }
        private void OnShowInSpectrum(bool show)
        {
            m_bShowBandStackOverlays = show;
            Display.ShowBandStackOverlays = show;

            updateBandstackOverlay(1);
        }
       
        private void OnPreampModeChanged(int rx, PreampMode oldMode, PreampMode newMode)
        {

        }
        private void OnPowerChangeHander(bool oldPower, bool newPower)
        {
            if (newPower)
            {
                // reset meter pixel historory when powering up
                clearRXSignalPixels(1);
                if (RX2Enabled) clearRXSignalPixels(2);

                //MW0LGE_21g update title bar as we should now know FW
                this.Text = BasicTitleBar;
            }
        }
        private void handleChange(Band oldBand, Band newBand, DSPMode oldMode, DSPMode newMode, Filter oldFilter, Filter newFilter, double oldFreq, double newFreq, double oldCentreF, double newCentreF, bool oldCTUN, bool newCTUN, int oldZoomSlider, int newZoomSlider)
        {
            if (m_bSetBandRunning) return;

            BandStackFilter bsf = BandStackManager.GetFilter(oldBand);

            // the bands have changed
            if (bsf != null && oldBand != newBand)
            {
                //update last visited with this
                updateLastVisited(bsf, oldBand, oldMode, oldFilter, oldFreq, oldCentreF, oldCTUN, oldZoomSlider);

                // update the new band with where we are going
                bsf = BandStackManager.GetFilter(newBand);
                if (bsf != null)
                {
                    //update last visited if moving to the new band
                    updateLastVisited(bsf, newBand, newMode, newFilter, newFreq, newCentreF, newCTUN, newZoomSlider);
                }
            }

            // this only happens if bands the same, so we are cycling
            bsf = BandStackManager.GetFilter(newBand);
            if (bsf != null && oldBand == newBand)
            {
                //update last visited with this but only if cycling in the same band
                updateLastVisited(bsf, newBand, newMode, newFilter, newFreq, newCentreF, newCTUN, newZoomSlider);
            }

            if (bsf != null && newBand != oldBand)
            {
                BandStack2Form.InitBandStackFilter(bsf, true);
                updateStackNumberDisplay(bsf);
            }

            if(oldBand != newBand)
            {
                //MW0LGE_21h
                updateBandstackOverlay(1);
            }
        }
        private void updateLastVisited(BandStackFilter bsf, Band band, DSPMode mode, Filter filter, double freq, double centreF, bool cTUN, int zoomSlider)
        {
            if (bsf == null) return;
            bsf.LastVisited.Band = band;
            bsf.LastVisited.Mode = mode;
            bsf.LastVisited.Filter = filter;
            bsf.LastVisited.Frequency = freq;
            bsf.LastVisited.CentreFrequency = centreF;
            bsf.LastVisited.CTUNEnabled = cTUN;
            bsf.LastVisited.ZoomSlider = zoomSlider;
        }
        private void OnSetBandChangeHander(int rx, Band oldBand, Band newBand, DSPMode oldMode, DSPMode newMode, Filter oldFilter, Filter newFilter, double oldFreq, double newFreq, double oldCentreF, double newCentreF, bool oldCTUN, bool newCTUN, int oldZoomSlider, int newZoomSlider)
        {
            if (rx != 1) return;
            handleChange(oldBand, newBand, oldMode, newMode, oldFilter, newFilter, oldFreq, newFreq, oldCentreF, newCentreF, oldCTUN, newCTUN, oldZoomSlider, newZoomSlider);
        }
        private void OnEntryAdd(BandStackFilter bsf)
        {
            if (!BandStackManager.Ready) return;
            BandStackEntry bse = bsf.LastVisited.Copy(true);// take copy of the last visited data, with a new guid

            if (m_bIgnoreFrequencyDupes && bsf.FindEntriesForFrequency(bse.Frequency).Count > 0) return; // ignore if we have this frequency already

            BandStackManager.AddEntry(bse);
            bsf.GenerateFilteredList(false);

            bsf.IndexOfCurrent = bsf.IndexFromGUID(bse.GUID);

            BandStack2Form.InitBandStackFilter(bsf, true);

            updateStackNumberDisplay(bsf);

            //MW0LGE_21h
            updateBandstackOverlay(1);
        }
        private void OnEntryUpdate(BandStackFilter bsf, BandStackEntry bse)
        {
            if (!BandStackManager.Ready) return;

            bool bRet = bsf.UpdateCurrentWithLastVisitedData(m_bIgnoreFrequencyDupes);

            if (bRet)
            {
                bsf.GenerateFilteredList(false);
                bsf.IndexOfCurrent = bsf.IndexFromGUID(bse.GUID);
                BandStack2Form.InitBandStackFilter(bsf); // rebuild list as we might be moving off one that has now been updated
                updateStackNumberDisplay(bsf);

                //MW0LGE_21h
                updateBandstackOverlay(1);
            }
        }
        private void OnEntryDelete(BandStackFilter bsf, BandStackEntry bse)
        {
            if (!BandStackManager.Ready) return;
            BandStackManager.DeleteEntry(bse);

            bsf.GenerateFilteredList(true);
            bsf.SelectInitial();

            BandStack2Form.InitBandStackFilter(bsf, true);
            updateStackNumberDisplay(bsf);

            //MW0LGE_21d3 select the now highlighted one
            BandStackEntry bse2 = bsf.Current();
            if (bse2 != null) OnEntryClicked(bsf, bse2, true, false);

            //MW0LGE_21h
            updateBandstackOverlay(1);
        }
        private void OnCentreFrequencyChanged(int rx, double oldFreq, double newFreq, Band band, double offset)
        {
            //MW0LGE_21h
            if (rx == 1) Display.CentreFreqRX1 = newFreq;
            else if (rx == 2) Display.CentreFreqRX2 = newFreq;

            //MW0LGE_21d N1MM
            N1MM.Resize(rx);
            //MW0LGE_21h
            if (rx == 1) updateBandstackOverlay(rx);

            if (m_bSetBandRunning) return;
            if (rx != 1) return;
            if (!BandStackManager.Ready) return;
            BandStackFilter bsf = BandStackManager.GetFilter(band, false);
            if (bsf != null) bsf.LastVisited.CentreFrequency = newFreq;
        }
        private void OnCTUNChanged(int rx, bool oldCTUN, bool newCTUN, Band band)
        {
            if (m_bSetBandRunning) return;
            if (rx != 1) return;
            if (!BandStackManager.Ready) return;
            BandStackFilter bsf = BandStackManager.GetFilter(band, false);
            if (bsf != null) bsf.LastVisited.CTUNEnabled = newCTUN;
        }
        private void OnFilterChanged(int rx, Filter oldFilter, Filter newFilter, Band band, int low, int high, string sName)
        {
            if (m_bSetBandRunning) return;
            if (rx != 1) return;
            if (!BandStackManager.Ready) return;
            BandStackFilter bsf = BandStackManager.GetFilter(band, false);
            if (bsf != null) bsf.LastVisited.Filter = newFilter;

            //MW0LGE_21h
            updateBandstackOverlay(1);
        }
        private void updateBandstackOverlay(int rx)
        {
            if (!BandStackManager.Ready || rx != 1 || !m_bShowBandStackOverlays) return;

            BandStackFilter bsf = BandStackManager.GetFilter(RX1Band, false); // todo user defined here as well
            if(bsf != null)
            {
                // use the display versions of everything
                double bandWidth = rx == 1 ? Display.RXDisplayHigh - Display.RXDisplayLow : Display.RX2DisplayHigh - Display.RX2DisplayLow;
                double centreFrequency = rx == 1 ? Display.CentreFreqRX1 : Display.CentreFreqRX2;

                double dL = Math.Round(centreFrequency - ((bandWidth / 2) * 1e-6), 6);
                double dH = Math.Round(centreFrequency + ((bandWidth / 2) * 1e-6), 6);

                // extend out to max filter, prevents overlays dropping off until they have moved off the display
                dL -= max_filter_width * 1e-6;
                dH += max_filter_width * 1e-6;
                //

                BandStackEntry[] bsesArray = bsf.FindForFrequencyRange(dL, dH).ToArray();

                for(int n = 0;n< bsesArray.Length; n++)
                {
                    bsesArray[n].LowFilter = rx1_filters[(int)bsesArray[n].Mode].GetLow(bsesArray[n].Filter);
                    bsesArray[n].HighFilter = rx1_filters[(int)bsesArray[n].Mode].GetHigh(bsesArray[n].Filter);
                }

                Display.BandStackOverlays = bsesArray;
            }
        }
        private void OnZoomChanged(double oldZoomFactor, double newZoomFactor, int sliderValue)
        {
            //MW0LGE_21d N1MM
            N1MM.Resize(1);
            if (RX2Enabled) N1MM.Resize(2);
            //MW0LGE_21h
            updateBandstackOverlay(1);

            if (m_bSetBandRunning) return;
            if (!BandStackManager.Ready) return;
            BandStackFilter bsf = BandStackManager.GetFilter(RX1Band, false);
            if (bsf != null)
            {
                bsf.LastVisited.ZoomFactor = newZoomFactor;
                bsf.LastVisited.ZoomSlider = sliderValue;
            }
        }
        private void OnEntryClicked(BandStackFilter bsf, BandStackEntry bse, bool updateLastVisited = true, bool obeyHide = true)
        {
            if (m_bSetBandRunning) return;
            if (!BandStackManager.Ready) return;
            
            bool bRet = false;
            if (updateLastVisited)
            {
                bRet = bsf.UpdateCurrentWithLastVisitedData(m_bIgnoreFrequencyDupes); // store everything into current on current band filter // may return false if current is locked
            }

            if (bRet)
            {
                bsf.GenerateFilteredList(false);
                bsf.IndexOfCurrent = bsf.IndexFromGUID(bse.GUID);
                BandStack2Form.InitBandStackFilter(bsf); // rebuild list as we might be moving off one that has now been updated
            }
            else
            {
                bsf.IndexOfCurrent = bsf.IndexFromGUID(bse.GUID);
                BandStack2Form.UpdateSelected();
            }

            if (m_bHideBandstackWindowOnSelect && obeyHide) this.Invoke(new MethodInvoker(BandStack2Form.HideClose));

            setRX1BandFromBandStackEntry(bse);
            updateStackNumberDisplay(bsf);
        }
        private void OnBandBeforeChangeHandler(int rx, Band band)
        {
            //[2.10.3.6]MW0LGE no band change on TX fix
            if (MOX && rx == 1 && (VFOATX || (!rx2_enabled && VFOBTX))) return;
            if (MOX && rx == 2 && VFOBTX) return;

            if (m_bSetBandRunning) return;
            if (rx != 1) return; // only used for RX1, RX2 uses SetupRX2Band
            if (!BandStackManager.Ready) return;

            #region BS_CodeStore
            //////CODESTORE here for future ref
            //////if (RX1IsIn60m() && !RX1IsOn60mChannel() && current_region == FRSRegion.US)
            //////{
            //////    // jump to nearest 60m band
            //////    double jump_freq = 0;
            //////    double min_delta = double.MaxValue;
            //////    double offset = ModeFreqOffset(rx1_dsp_mode);
            //////    int index = 0;
            //////    int min_index = 0;
            //////    foreach (Channel c in Channels60m)
            //////    {
            //////        double freq = c.Freq + offset;
            //////        double delta = Math.Abs(freq - VFOAFreq);
            //////        if (delta < min_delta)
            //////        {
            //////            min_delta = delta;
            //////            jump_freq = freq;
            //////            min_index = index;
            //////        }
            //////        index++;
            //////    }
            //////int xvtr_index = Int32.Parse(new_band.Substring(3));
            //////double start_freq = XVTRForm.GetBegin(xvtr_index);
            //////double end_freq = XVTRForm.GetEnd(xvtr_index);
            #endregion

            BandStackFilter bsf = BandStackManager.GetFilter(band, false);  // get the non-user band stack filter
            if (bsf != null)
            {
                BandStackEntry bse;
                if (RX1Band == band) // already on the band
                {
                    if (Common.CtrlKeyDown)
                    {
                        // add new
                        OnEntryAdd(bsf);
                        return;
                    }

                    bsf.UpdateCurrentWithLastVisitedData(m_bIgnoreFrequencyDupes); // store everything into current on current band filter                    

                    if (Common.ShiftKeyDown)
                        bse = bsf.Previous();
                    else
                        bse = bsf.Next();

                    bsf.GenerateFilteredList(true); // this is done as current is updated above, this may cause that last entry to move ahead of where you area
                    BandStack2Form.InitBandStackFilter(bsf, false);
                }
                else
                {
                    // store old which is RX1Band
                    BandStackFilter bsfOld = BandStackManager.GetFilter(RX1Band);
                    if (bsfOld != null)
                    {
                        bsfOld.UpdateCurrentWithLastVisitedData(m_bIgnoreFrequencyDupes);
                        bsfOld.GenerateFilteredList(true);
                    }

                    BandStack2Form.InitBandStackFilter(bsf, false);
                    bse = bsf.SelectInitial();
                }

                if (bse == null)
                {
                    bse = bsf.LastVisited.Copy(); // in case of nothing in the filter (ie deleted everything, or no entries)
                    // at least set it to the band we want
                    bse.Band = band;
                    List<BandFrequencyData> bfd = BandStackManager.GetFrequencyRangesForBand(band, this.Extended, CurrentRegion);
                    if (bfd.Count > 0)
                    {
                        bse.CentreFrequency = bfd.First<BandFrequencyData>().low + ((bfd.First<BandFrequencyData>().high - bfd.First<BandFrequencyData>().low) / 2);
                        bse.Frequency = bse.CentreFrequency;
                    }
                    else
                    {
                        if(band >= Band.VHF0 && band <= Band.VHF13)
                        {
                            // attempt to get freq ranges from xvtr form
                            int index = band - Band.VHF0;
                            bse.CentreFrequency = XVTRForm.GetBegin(index) + ((XVTRForm.GetEnd(index) - XVTRForm.GetBegin(index)) / 2);
                            bse.Frequency = bse.CentreFrequency;
                        }
                    }
                }

                BandStack2Form.UpdateSelected();

                setRX1BandFromBandStackEntry(bse);
            }
            updateStackNumberDisplay(bsf);
        }
        private void setRX1BandFromBandStackEntry(in BandStackEntry bse)
        {
            //[2.10.3.6]MW0LGE no band change on TX fix
            if (MOX && (VFOATX || (!rx2_enabled && VFOBTX))) return;

            if (bse == null) return;

            NetworkIO.SendHighPriority(0);
            SetBand(bse.Mode.ToString(), bse.Filter.ToString(), bse.Frequency, bse.CTUNEnabled, bse.ZoomSlider, bse.CentreFrequency);
            UpdateWaterfallLevelValues();
            updateDisplayGridLevelValues();
            UpdateDiversityValues();
            NetworkIO.SendHighPriority(1);            
        }

        private void OnBandChangeHandler(int rx, Band oldBand, Band newBand)
        {
            if (rx == 1)
            {
                // set the panel rx1 only
                BandType bt = BandStackManager.GetBandTypeForFrequency(VFOAFreq);
                switch (bt)
                {
                    case BandType.GEN:
                        setBandPanelVisible(true, false, false);
                        break;
                    case BandType.HF:
                        setBandPanelVisible(false, true, false);
                        break;
                    case BandType.VHF:
                        setBandPanelVisible(false, false, true);
                        break;
                }
            }

            //reset smeter pixel history //MW0LGE_21a
            clearRXSignalPixels(rx);

            if (m_bSetBandRunning) return;
            if (!BandStackManager.Ready) return;
            if (rx != 1) return;

            BandStackFilter bsf = BandStackManager.GetFilter(oldBand, false);
            if (bsf != null) bsf.LastVisited.Band = oldBand;
            bsf = BandStackManager.GetFilter(newBand, false);
            if (bsf != null)
            {
                bsf.LastVisited.Band = newBand;
                BandStack2Form.InitBandStackFilter(bsf, false);
                bsf.SelectInitial();
                BandStack2Form.UpdateSelected();
                updateStackNumberDisplay(bsf);
            }
        }
        private void OnModeChangeHandler(int rx, DSPMode oldMode, DSPMode newMode, Band oldBand, Band newBand)
        {
            //reset smeter pixel history //MW0LGE_21a
            clearRXSignalPixels(rx);

            //recover the stepindex.
            updateStepIndexForMode(rx, newMode);

            if (m_bSetBandRunning) return;
            if (rx != 1) return;
            if (!BandStackManager.Ready) return;

            BandStackFilter bsf = BandStackManager.GetFilter(oldBand, false);
            if (bsf != null) bsf.LastVisited.Mode = oldMode;

            bsf = BandStackManager.GetFilter(newBand, false);
            if (bsf != null) bsf.LastVisited.Mode = newMode;

            //MW0LGE [2.9.0.7] resize after entering or leaving CW so that N1MM can use cwpitch offset
            if(newMode == DSPMode.CWL || newMode == DSPMode.CWU ||
                oldMode == DSPMode.CWL || oldMode == DSPMode.CWU)
                N1MM.Resize(rx);
        }
        private void OnVFOAFrequencyChangeHandler(Band oldBand, Band newBand, DSPMode oldMode, DSPMode newMode, Filter oldFilter, Filter newFilter, double oldFreq, double newFreq, double oldCentreF, double newCentreF, bool oldCTUN, bool newCTUN, int oldZoomSlider, int newZoomSlider, double offset, int rx)
        {
            if (rx == 1)
            {
                //used primarily to reset spectral peaks
                Display.CentreFreqRX1 = CentreFrequency;
            }

            //cat broadcast for kenwood AI
            if (KWAutoInformation)
                BroadcastFreqChange("A", newFreq);

            handleChange(oldBand, newBand, oldMode, newMode, oldFilter, newFilter, oldFreq, newFreq, oldCentreF, newCentreF, oldCTUN, newCTUN, oldZoomSlider, newZoomSlider);
        }
        private void OnVFOBFrequencyChangeHandler(Band oldBand, Band newBand, DSPMode oldMode, DSPMode newMode, Filter oldFilter, Filter newFilter, double oldFreq, double newFreq, double oldCentreF, double newCentreF, bool oldCTUN, bool newCTUN, int oldZoomSlider, int newZoomSlider, double offset, int rx)
        {
            if (rx == 2)
            {
                //used primarily to reset spectral peaks
                Display.CentreFreqRX2 = CentreRX2Frequency;
            }

            //cat broadcast for kenwood AI
            if (KWAutoInformation)
                BroadcastFreqChange("B", newFreq);
        }

        private void OnMoxChangeHandler(int rx, bool oldMox, bool newMox)
        {
            //MW0LGE_21k disable xPA if not permitted to hot switch
            if (newMox)
                chkExternalPA.Enabled = m_bHotSwitchOCTXPins;
            else
                chkExternalPA.Enabled = true;

            updateOCTXPins(newMox);

            //reset smeter pixel history //MW0LGE_21a
            clearRXSignalPixels(1);
            if (RX2Enabled) clearRXSignalPixels(2);
        }

        private void updateStackNumberDisplay(BandStackFilter bsf)
        {
            if (BandStackManager.Ready)
            {
                if (bsf != null)
                {
                    if (bsf.IndexOfCurrent == -1)
                    {
                        if (bsf.ReturnMode == BandStackFilter.FilterReturnMode.LastVisited) regBandStackCurrentEntry.Text = "L";
                        else regBandStackCurrentEntry.Text = "-";
                    }
                    else
                    {
                        regBandStackCurrentEntry.Text = (bsf.IndexOfCurrent + 1).ToString();
                    }
                    regBandStackTotalEntries.Text = bsf.NumberOfEntries.ToString();
                }
                else
                {
                    regBandStackCurrentEntry.Text = regBandStackTotalEntries.Text = "-";
                }
            }
        }
        //-------------------------------
        #endregion

        public void RepositionExternalPAButton(bool bShow)
        {
            if(bShow)
            {
                // move the quick play/rec buttons down
                ckQuickPlay.Top = ckQuickRec.Top = chkExternalPA.Top + 23;
            }
            else
            {
                // move the quick play/rec buttons up
                ckQuickPlay.Top = ckQuickRec.Top = chkExternalPA.Top;

                //disable it
                chkExternalPA.Checked = false;
            }
            chkExternalPA.Visible = bShow;
        }

        private void chkExternalPA_CheckedChanged(object sender, EventArgs e)
        {
            //wd5y
            if (SetupForm.chkAmpDRVLim.Checked == true & chkExternalPA.Checked == true)
            {
                int drvlimpwr = (int)(ptbPWR.Value / (float)(ptbPWR.Maximum - ptbPWR.Minimum) * SetupForm.GetPABandMaxPower(TXBand));
                int tunlimpwr = (int)(ptbTune.Value / (float)(ptbTune.Maximum - ptbTune.Minimum) * SetupForm.GetPABandMaxPower(TXBand));

                if (SetupForm.numUpDnDRVLim.Value < drvlimpwr & SetupForm.numUpDnTUNLim.Value < tunlimpwr)
                {
                    RXOnly = true;
                    chkExternalPA.Checked = false;
                    ptbPWR.Value = 0;
                    lblPWR.Text = "Drive: " + 0 + "w";
                    lblPWR2.Text = "Drive:" + 0 + "w";
                    ptbTune.Value = 0;
                    lblTune.Text = "Tune: " + 0 + "w";
                    lblTune2.Text = "Tune:" + 0 + "w";

                    MessageBox.Show("The Drive And/Or Tune Power Is Above The Maximum Limit.", "Release PTT And Reset Power.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    RXOnly = false;
                    chkExternalPA.Checked = true;
                    return;
                }
            }

            if (SetupForm.chkAmpDRVLim.Checked == true & chkExternalPA.Checked == true)
            {
                int drvlimpwr = (int)(ptbPWR.Value / (float)(ptbPWR.Maximum - ptbPWR.Minimum) * SetupForm.GetPABandMaxPower(TXBand));

                if (SetupForm.numUpDnDRVLim.Value < drvlimpwr)
                {
                    RXOnly = true;
                    chkExternalPA.Checked = false;
                    ptbPWR.Value = 0;
                    lblPWR.Text = "Drive: " + 0 + "w";
                    lblPWR2.Text = "Drive:" + 0 + "w";

                    MessageBox.Show("The Drive And/Or Tune Power Is Above The Maximum Limit.", "Release PTT And Reset Power.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    RXOnly = false;
                    chkExternalPA.Checked = true;
                    return;
                }
            }
            if (SetupForm.chkAmpDRVLim.Checked == true & chkExternalPA.Checked == true)
            {
                int tunlimpwr = (int)(ptbTune.Value / (float)(ptbTune.Maximum - ptbTune.Minimum) * SetupForm.GetPABandMaxPower(TXBand));

                if (SetupForm.numUpDnTUNLim.Value < tunlimpwr)
                {
                    RXOnly = true;
                    chkExternalPA.Checked = false;
                    ptbTune.Value = 0;
                    lblTune.Text = "Tune: " + 0 + "w";
                    lblTune2.Text = "Tune:" + 0 + "w";

                    MessageBox.Show("The Drive And/Or Tune Power Is Above The Maximum Limit.", "Release PTT And Reset Power.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    RXOnly = false;
                    chkExternalPA.Checked = true;
                    return;
                }
            }
            //wd5y

            //MW0LGE_21j
            if (!chkPower.Checked) return;

            Band lo_band = BandByFreq(XVTRForm.TranslateFreq(VFOAFreq), rx1_xvtr_index, current_region);
            Band lo_bandb = BandByFreq(XVTRForm.TranslateFreq(VFOBFreq), rx2_xvtr_index, current_region);

            if (penny_ext_ctrl_enabled) //MW0LGE_21k
            {
                int bits = Penny.getPenny().UpdateExtCtrl(lo_band, lo_bandb, _mox, tuning, SetupForm.TestIMD, chkExternalPA.Checked);
                if (!IsSetupFormNull) SetupForm.UpdateOCLedStrip(_mox, bits);
            }
        }
        public bool CATxPA
        {
            get
            {
                bool bRet = false;

                if (!IsSetupFormNull)
                {
                    bRet = chkExternalPA.Checked && SetupForm.CheckForAnyExternalPACheckBoxes();
                }

                return bRet;
            }
            set
            {
                if (!IsSetupFormNull && SetupForm.CheckForAnyExternalPACheckBoxes())
                {
                    chkExternalPA.Checked = value;
                }
                else
                    chkExternalPA.Checked = false;
            }
        }

        #region AutoAGC
        //
        private double m_dAutoAGCOffsetRX1 = 0.0;
        public double AutoAGCOffsetRX1
        {
            get { return m_dAutoAGCOffsetRX1; }
            set { m_dAutoAGCOffsetRX1 = value; }
        }
        private double m_dAutoAGCOffsetRX2 = 0.0;
        public double AutoAGCOffsetRX2
        {
            get { return m_dAutoAGCOffsetRX2; }
            set { m_dAutoAGCOffsetRX2 = value; }
        }
        //
        private bool m_bAutoAGCRX1 = false;
        public bool AutoAGCRX1
        {
            get { return m_bAutoAGCRX1; }
            set { 
                m_bAutoAGCRX1 = value;
                Display.AutoAGCRX1 = m_bAutoAGCRX1;
                ptbRF.GreenThumb = m_bAutoAGCRX1;
                if (!IsSetupFormNull) SetupForm.AutoAGCRX1 = m_bAutoAGCRX1;
            }
        }
        private bool m_bAutoAGCRX2 = false;
        public bool AutoAGCRX2
        {
            get { return m_bAutoAGCRX2; }
            set { 
                m_bAutoAGCRX2 = value;
                Display.AutoAGCRX2 = m_bAutoAGCRX2;
                ptbRX2RF.GreenThumb = m_bAutoAGCRX2;
                if (!IsSetupFormNull) SetupForm.AutoAGCRX2 = m_bAutoAGCRX2;
            }
        }
        //

        public void setAGCThresholdPoint(double agc_thresh_point, int rx)
        {
            float cal_offset = 0.0f;

            // MW0LGE_21k9d values are already offset as part of Display
            cal_offset = agcCalOffset(rx);

            //if (rx == 1)
            //{
            //    switch (RX1AGCMode)
            //    {
            //        case AGCMode.FIXD:
            //            cal_offset = 0.0f;
            //            break;
            //        default:
            //            cal_offset = 2.0f + (Display.RX1DisplayCalOffset +
            //                (Display.RX1PreampOffset - Display.AlexPreampOffset) + Display.RX1FFTSizeOffset); // note change in the sign for sizeoffset
            //            break;
            //    }
            //}
            //else
            //{
            //    switch (RX2AGCMode)
            //    {
            //        case AGCMode.FIXD:
            //            cal_offset = 0.0f;
            //            break;
            //        default:
            //            cal_offset = 2.0f + (Display.RX2DisplayCalOffset +
            //                (Display.RX2PreampOffset - Display.AlexPreampOffset) + Display.RX2FFTSizeOffset);
            //            break;
            //    }
            //}

            // offset applied before being called
            agc_thresh_point -= (double)cal_offset;
            if (agc_thresh_point > 2) agc_thresh_point = 2;
            if (agc_thresh_point < -160.0) agc_thresh_point = -160.0;

            double agc_top = 0.0;
            double size;
            if (rx == 1)
            {
                size = (double)specRX.GetSpecRX(0).FFTSize; // MW0LGE_21k7
                WDSP.SetRXAAGCThresh(WDSP.id(0, 0), agc_thresh_point, size, sample_rate_rx1);
                unsafe { WDSP.GetRXAAGCTop(WDSP.id(0, 0), &agc_top); }
            }
            else if (rx == 2)
            {
                size = (double)specRX.GetSpecRX(1).FFTSize;
                WDSP.SetRXAAGCThresh(WDSP.id(2, 0), agc_thresh_point, size, sample_rate_rx2);
                unsafe { WDSP.GetRXAAGCTop(WDSP.id(2, 0), &agc_top); }
            }

            agc_top = Math.Round(agc_top);
            if (agc_top > 120) agc_top = 120;
            if (agc_top < -20.0) agc_top = -20.0;

            AGCMode amode = rx == 1 ? RX1AGCMode : RX2AGCMode;
            switch (amode)
            {
                case AGCMode.FIXD:
                    if (!IsSetupFormNull) {
                        if (rx == 1) SetupForm.AGCFixedGain = (int)agc_top;
                        else if (rx == 2) SetupForm.AGCRX2FixedGain = (int)agc_top; 
                    }
                    break;
                default:
                    if (!IsSetupFormNull)
                    {
                        if (rx == 1) SetupForm.AGCMaxGain = (int)agc_top;
                        else if (rx == 2) SetupForm.AGCRX2MaxGain = (int)agc_top;
                    }
                    break;
            }
        }
        private bool _maintainNFAdjustDeltaRX1 = false;
        private bool _maintainNFAdjustDeltaRX2 = false;
        public bool MaintainNFAdjustDeltaRX1
        {
            get { return _maintainNFAdjustDeltaRX1; }
            set { _maintainNFAdjustDeltaRX1 = value; }
        }
        public bool MaintainNFAdjustDeltaRX2
        {
            get { return _maintainNFAdjustDeltaRX2; }
            set { _maintainNFAdjustDeltaRX2 = value; }
        }
        private float _lastRX1NoiseFloor = -200;
        private float _lastRX2NoiseFloor = -200;
        private bool _gridMinFollowsNFRX1 = false;
        private bool _gridMinFollowsNFRX2 = false;
        public bool GridMinFollowsNFRX1
        {
            get { return _gridMinFollowsNFRX1; }
            set { _gridMinFollowsNFRX1 = value; }
        }
        public bool GridMinFollowsNFRX2
        {
            get { return _gridMinFollowsNFRX2; }
            set { _gridMinFollowsNFRX2 = value; }
        }
        private float _RX1NFoffsetGridFollow = 5f;
        private float _RX2NFoffsetGridFollow = 5f;
        public float RX1NFoffsetGridFollow
        {
            get { return _RX1NFoffsetGridFollow; }
            set { _RX1NFoffsetGridFollow = value; }
        }
        public float RX2NFoffsetGridFollow
        {
            get { return _RX2NFoffsetGridFollow; }
            set { _RX2NFoffsetGridFollow = value; }
        }
        private bool _lastRX1NoiseFloorGood = false;
        private bool _lastRX2NoiseFloorGood = false;
        public float LastNFRX1
        {
            get { return _lastRX1NoiseFloor; }
        }
        public float LastNFRX2
        {
            get { return _lastRX2NoiseFloor; }
        }
        private void tmrAutoAGC_Tick(object sender, EventArgs e)
        {
            if (!chkPower.Checked || _mox) return;

            // every 500ms

            _lastRX1NoiseFloorGood = Display.IsNoiseFloorGoodRX1;
            _lastRX2NoiseFloorGood = Display.IsNoiseFloorGoodRX2;

            if (!_lastRX1NoiseFloorGood && !_lastRX2NoiseFloorGood) return;

            if (_lastRX1NoiseFloorGood) _lastRX1NoiseFloor = Display.NoiseFloorRX1; // these update noisefloorgoodrx, and 'use up' the readings
            if (_lastRX2NoiseFloorGood) _lastRX2NoiseFloor = Display.NoiseFloorRX2;

            //change the display grids if needed to follow NF
            if (!IsSetupFormNull)
            { 
                if (_lastRX1NoiseFloorGood && GridMinFollowsNFRX1 && (Display.CurrentDisplayMode == DisplayMode.PANADAPTER ||
                                            Display.CurrentDisplayMode == DisplayMode.SPECTRUM ||
                                            Display.CurrentDisplayMode == DisplayMode.PANAFALL ||
                                            Display.CurrentDisplayMode == DisplayMode.PANASCOPE ||
                                            Display.CurrentDisplayMode == DisplayMode.WATERFALL))
                {
                    float setPoint = _lastRX1NoiseFloor - _RX1NFoffsetGridFollow;
                    float fDelta = (float)Math.Abs(SetupForm.DisplayGridMax - SetupForm.DisplayGridMin); // abs incase MW0LGE [2.9.0.7]
                    if (Math.Abs(SetupForm.DisplayGridMin - setPoint) >= 2)
                    {
                        SetupForm.DisplayGridMin = setPoint;
                        if (_maintainNFAdjustDeltaRX1) SetupForm.DisplayGridMax = setPoint + fDelta;
                    }
                }

                if (_lastRX2NoiseFloorGood && RX2Enabled && GridMinFollowsNFRX2 &&
                                           (Display.CurrentDisplayModeBottom == DisplayMode.PANADAPTER ||
                                            Display.CurrentDisplayModeBottom == DisplayMode.SPECTRUM ||
                                            Display.CurrentDisplayModeBottom == DisplayMode.PANAFALL ||
                                            Display.CurrentDisplayModeBottom == DisplayMode.PANASCOPE ||
                                            Display.CurrentDisplayModeBottom == DisplayMode.WATERFALL))
                {
                    float setPoint = _lastRX2NoiseFloor - _RX2NFoffsetGridFollow;
                    float fDelta = (float)Math.Abs(SetupForm.RX2DisplayGridMax - SetupForm.RX2DisplayGridMin); // abs incase MW0LGE [2.9.0.7]
                    if (Math.Abs(SetupForm.RX2DisplayGridMin - setPoint) >= 2)
                    {
                        SetupForm.RX2DisplayGridMin = setPoint; // at least 2dB to move
                        if (_maintainNFAdjustDeltaRX2) SetupForm.RX2DisplayGridMax = setPoint + fDelta;
                    }
                }
            }
            //

            if (m_bAutoAGCRX1 && _lastRX1NoiseFloorGood)
            {
                setAGCThresholdPoint(_lastRX1NoiseFloor + m_dAutoAGCOffsetRX1, 1);
            }

            if (m_bAutoAGCRX2 && _lastRX2NoiseFloorGood)
            {
                setAGCThresholdPoint(_lastRX2NoiseFloor + m_dAutoAGCOffsetRX2, 2);
            }
        }
        #endregion

        private void radDisplayZoom05_Click(object sender, EventArgs e)
        {
        }

        private void radDisplayZoom1x_Click(object sender, EventArgs e)
        {
        }

        private void radDisplayZoom2x_Click(object sender, EventArgs e)
        {
        }

        private void radDisplayZoom4x_Click(object sender, EventArgs e)
        {
        }

        private void ptbRF_Click(object sender, EventArgs e)
        {
            if (IsRightButton((MouseEventArgs)e))
                AutoAGCRX1 = !AutoAGCRX1;

            //wd5y
            if (sliderForm != null)
            {
                sliderForm.chkAGCAut.Checked = AutoAGCRX1;
            }
            //wd5y
        }

        private void ptbRX2RF_Click(object sender, EventArgs e)
        {
            if (IsRightButton((MouseEventArgs)e))
                AutoAGCRX2 = !AutoAGCRX2;

            //wd5y
            if (sliderForm != null)
            {
                sliderForm.chkRX2AGCAut.Checked = AutoAGCRX2;
            }
            //wd5y
        }

        private void chkRXEQ_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) equalizerToolStripMenuItem_Click(null, EventArgs.Empty);
        }

        private void chkTXEQ_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) equalizerToolStripMenuItem_Click(null, EventArgs.Empty);
        }

        private void chkFWCATUBypass_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) linearityToolStripMenuItem_Click(null, EventArgs.Empty);            
        }

        private void chkTUN_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e) && !IsSetupFormNull) SetupForm.ShowSetupTab(Setup.SetupTab.Transmit_Tab);
        }

        private void chk2TONE_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e) && !IsSetupFormNull) SetupForm.ShowSetupTab(Setup.SetupTab.TEST_Tab);
        }

        private void chkExternalPA_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e) && !IsSetupFormNull) SetupForm.ShowSetupTab(Setup.SetupTab.OC_Tab);
        }

        private void ptbRF_MouseDown(object sender, MouseEventArgs e)
        {
            if(e.Button != MouseButtons.Right && AutoAGCRX1)
                AutoAGCRX1 = false;
        }

        private void ptbRX2RF_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Right && AutoAGCRX2)
                AutoAGCRX2 = false;
        }

        private void MouseWheelAGCRX1(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (AutoAGCRX1)
                AutoAGCRX1 = false;
        }
        private void MouseWheelAGCRX2(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (AutoAGCRX2)
                AutoAGCRX2 = false;
        }

        private bool m_bZTBstoreLock = false;
        public bool ZTBstoreLock
        {
            get { return m_bZTBstoreLock; }
            set
            { m_bZTBstoreLock = value; }
        }
        private bool m_bZTBisRecallStore = false;
        public bool ZTBisRecallStore
        {
            get { return m_bZTBisRecallStore; }
            set {
                m_bZTBisRecallStore = value;
                setupZTBButton();
            }
        }
        public void ZoomToBand(bool bStore)
        {
            int rx; // note, 0 indexed rx, rx1 = 0, rx2 = 1
            Band band;
            double centre;
            DSPMode dsp;
            bool bCTUN;

            if (RX2Enabled && Common.ShiftKeyDown)
            {
                rx = 1; //rx2
                band = RX2Band;
                centre = CentreRX2Frequency;                
            }
            else
            {
                rx = 0; //rx1
                band = RX1Band;
                centre = CentreFrequency;                                
            }

            // store recall ZTB
            if (bStore && !m_bZTBstoreLock)
            {
                // store
                ztb_data_by_band[rx][(int)band].CentreFrequency = centre;
                ztb_data_by_band[rx][(int)band].ZoomSliderPosition = ptbDisplayZoom.Value;
                ztb_data_by_band[rx][(int)band].PanSliderPosition = ptbDisplayPan.Value;
                ztb_data_by_band[rx][(int)band].Initalised = true;
                return;
            }

            if (rx == 1) { //rx2
                if (!chkX2TR.Checked) chkX2TR.Checked = true;
                dsp = RX2DSPMode;
                bCTUN = chkX2TR.Checked;
            }
            else //rx1
            {
                if (!chkFWCATU.Checked) chkFWCATU.Checked = true;
                dsp = RX1DSPMode;
                bCTUN = chkFWCATU.Checked;
            }

            if (m_bZTBisRecallStore)
            {
                ztb_data ztb = ztb_data_by_band[rx][(int)band];

                if (ztb.Initalised && bCTUN)
                {
                    centre = ztb_data_by_band[rx][(int)band].CentreFrequency;

                    if (dsp == DSPMode.CWL)
                        centre -= (double)cw_pitch * 0.0000010;
                    else if (dsp == DSPMode.CWU)
                        centre += (double)cw_pitch * 0.0000010;

                    m_bIgnoreLimitsForZTB = true;
                    if (Pan != ztb.PanSliderPosition) Pan = ztb.PanSliderPosition;
                    if (ptbDisplayZoom.Value != ztb.ZoomSliderPosition)
                    {
                        ptbDisplayZoom.Value = ztb.ZoomSliderPosition;
                        ptbDisplayZoom_Scroll(this, EventArgs.Empty);
                    }
                    if (rx == 0)
                    {
                        if (CentreFrequency != centre)
                        {
                            CentreFrequency = centre;
                            txtVFOAFreq_LostFocus(this, EventArgs.Empty);
                        }
                    }
                    else
                    {
                        if (CentreRX2Frequency != centre)
                        {
                            CentreRX2Frequency = centre;
                            txtVFOBFreq_LostFocus(this, EventArgs.Empty);
                        }
                    }
                    m_bIgnoreLimitsForZTB = false;
                }
            }
            else
            {
                //zoom to bandwidth mode
                if (bCTUN)
                {
                    // calculate zooms etc
                    if (rx == 0)
                        zoomToBandBandwidth(RX1Band, 1);
                    else //rx2
                        zoomToBandBandwidth(RX2Band, 2);
                }
            }
        }
        private void btnDisplayZTB_Click(object sender, EventArgs e)
        {
            MouseButtons mb = ((MouseEventArgs)e).Button;
            ZoomToBand(mb == MouseButtons.Right);
        }

        private void setupZTBButton()
        {
            if (m_bZTBisRecallStore)
                toolTip1.SetToolTip(btnDisplayZTB, "Recall/Store mode. Left click to recall, right to store Zoom/Pan/Center per band, per RX. Shift for RX2.");
            else
                toolTip1.SetToolTip(btnDisplayZTB, "Zoom to the band using Region band edges. Shift for RX2.");
        }

        private void btnDisplayZTB_MouseUp(object sender, MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Right) btnDisplayZTB_Click(sender, e);
        }

        private void Console_Activated(object sender, EventArgs e)
        {
            ThetisFocusChangedHandlers?.Invoke(true);
        }

        private void Console_Deactivate(object sender, EventArgs e)
        {
            ThetisFocusChangedHandlers?.Invoke(false);
        }

        //MW0LGE_21k9 to fix issues where some GPU drivers do not allow xor mono cursor on top of DirectX render target
        private bool _useOutlinedCrossCursor = false;
        public bool UseOutlinedCrossCursor
        {
            get { return _useOutlinedCrossCursor; }
            set { _useOutlinedCrossCursor = value; }
        }

        #region InfoBar
        private void infoBar_Button1Clicked(object sender, ucInfoBar.InfoBarAction e)
        {
            handleInfoBarButtonClick(e);
        }

        private void infoBar_Button2Clicked(object sender, ucInfoBar.InfoBarAction e)
        {
            handleInfoBarButtonClick(e);
        }

        private void handleInfoBarButtonClick(ucInfoBar.InfoBarAction e)
        {
            if (IsSetupFormNull) return;

            switch (e.Action)
            {
                case ucInfoBar.ActionTypes.ActivePeaks:
                    SetupForm.ActivePeakHoldsEnabled = e.ButtonState;
                    break;
                case ucInfoBar.ActionTypes.Blobs:
                    SetupForm.PeakBlobsEnabled = e.ButtonState;
                    break;
                case ucInfoBar.ActionTypes.CFC:
                    CFCEnabled = e.ButtonState;
                    break;
                case ucInfoBar.ActionTypes.CursorInfo:
                    SetupForm.ShowDisplayMHzCursorInfo = e.ButtonState;
                    break;
                case ucInfoBar.ActionTypes.Leveler:
                    SetupForm.TXLevelerOn = e.ButtonState;
                    break;
                case ucInfoBar.ActionTypes.CFCeq:
                    SetupForm.CFCPEQEnabled = e.ButtonState;
                    break;
                case ucInfoBar.ActionTypes.ShowSpots:
                    SetupForm.ShowTCISpots = e.ButtonState;
                    break;
                case ucInfoBar.ActionTypes.DisplayFill:
                    SetupForm.DisplayPanFill = e.ButtonState;
                    break;
            }
        }

        private void infoBar_Button1MouseDown(object sender, ucInfoBar.InfoBarAction e)
        {
            if (e.Button == MouseButtons.Right) showSetupFromInfoBar(e.Action);
        }

        private void infoBar_Button2MouseDown(object sender, ucInfoBar.InfoBarAction e)
        {
            if (e.Button == MouseButtons.Right) showSetupFromInfoBar(e.Action);
        }

        private void showSetupFromInfoBar(ucInfoBar.ActionTypes action)
        {
            if (IsSetupFormNull) return;

            switch (action)
            {
                case ucInfoBar.ActionTypes.Blobs:
                    SetupForm.ShowSetupTab(Setup.SetupTab.DISPGEN_Tab);
                    break;
                case ucInfoBar.ActionTypes.ActivePeaks:
                    SetupForm.ShowSetupTab(Setup.SetupTab.DISPRX1_Tab);
                    break;
                case ucInfoBar.ActionTypes.CFC:
                    SetupForm.ShowSetupTab(Setup.SetupTab.CFC_Tab);
                    break;
                case ucInfoBar.ActionTypes.CursorInfo:
                    SetupForm.ShowSetupTab(Setup.SetupTab.DISPGEN_Tab);
                    break;
                case ucInfoBar.ActionTypes.Leveler:
                    SetupForm.ShowSetupTab(Setup.SetupTab.ALCAGC_Tab);
                    break;
                case ucInfoBar.ActionTypes.DisplayFill:
                    SetupForm.ShowSetupTab(Setup.SetupTab.DISPGEN_Tab);                    
                    break;
                case ucInfoBar.ActionTypes.CFCeq:
                    SetupForm.ShowSetupTab(Setup.SetupTab.CFC_Tab);
                    break;
                case ucInfoBar.ActionTypes.ShowSpots:
                    SetupForm.ShowSetupTab(Setup.SetupTab.SpotTCI);                    
                    break;
            }
        }
        public bool HideFeebackLevel
        {
            get { return infoBar.HideFeedback; }
            set { infoBar.HideFeedback = value; }
        }
        public bool SwapRedBlue
        {
            get { return infoBar.SwapRedBlue; }
            set { infoBar.SwapRedBlue = value; }
        }
        private void infoBar_HideFeedbackChanged(object sender, EventArgs e)
        {
            if (!IsSetupFormNull) SetupForm.HideFeebbackChanged = infoBar.HideFeedback;
        }
        private void infoBar_SwapRedBlueChanged(object sender, EventArgs e)
        {
            if (!IsSetupFormNull) SetupForm.SwapRedBlueChanged();
        }
        #endregion
        private Color _limitSliderBarColor = Color.Red;
        public Color LimitSliderColor
        {
            get
            {
                return _limitSliderBarColor;
            }
            set
            {
                _limitSliderBarColor = value;
                ptbPWR.LimitBarColor = _limitSliderBarColor;
                ptbTune.LimitBarColor = _limitSliderBarColor;
            }
        }
        public void UpdateTuneLabel(bool bShowLimitValue, System.EventArgs e)
        {
            if (IsSetupFormNull) return;

            string sHeader = "Tu | 2T";
            if (_tuneDrivePowerSource == DrivePowerSource.TUNE_SLIDER && _2ToneDrivePowerSource != DrivePowerSource.TUNE_SLIDER) sHeader = "Tune";
            if (_tuneDrivePowerSource != DrivePowerSource.TUNE_SLIDER && _2ToneDrivePowerSource == DrivePowerSource.TUNE_SLIDER) sHeader = "2Tone";

            bool bUsePower = SetupForm.GetPABandUsesMaxPower(TXBand);

            int drv;
            if (bShowLimitValue) 
            {
                PrettyTrackBar.LimitConstraint lc = e as PrettyTrackBar.LimitConstraint;
                drv = lc.LimitValue;
                if (lc.MouseWheel)
                {
                    _bDelayUpdateTuneLabel = true;

                    if (_tmrTuneSliderUpdate == null)
                    {
                        _tmrTuneSliderUpdate = new System.Timers.Timer(500);
                        _tmrTuneSliderUpdate.Elapsed += OnTuneSliderUpdateTimerTick;
                        _tmrTuneSliderUpdate.AutoReset = false;
                        _tmrTuneSliderUpdate.Enabled = true;
                    }
                    else
                    {
                        _tmrTuneSliderUpdate.Stop();
                        _tmrTuneSliderUpdate.Start();
                    }
                }
            }
            else if (ptbTune.IsConstrained)
                drv = ptbTune.ConstrainedValue;
            else
                drv = ptbTune.Value;

            string sValue;
            if (bUsePower)
            {
                int nValue = (int)((drv / (float)(ptbTune.Maximum - ptbTune.Minimum)) * SetupForm.GetPABandMaxPower(TXBand));
                sValue = nValue.ToString();
            }
            else
            {
                sValue = drv.ToString();
            }

            if (!bShowLimitValue)
            {
                if (ptbTune.IsConstrained)
                    lblTune.Text = "Tune: (" + sValue + " w)";
                else
                    lblTune.Text = "Tune: " + sValue + " w";
            }
            else
            {
                lblTune.Text = "Limit: " + sValue + " w";
            }

            //wd5y
            lblTune2.Text = lblTune.Text;
            //wd5y
        }
        private double m_fTuneDrivePower = -1;
        private void ptbTune_Scroll(object sender, EventArgs e)
        {
            if (IsSetupFormNull)
                return; 
            
            PrettyTrackBar.LimitConstraint lc = e as PrettyTrackBar.LimitConstraint; // the event args will contain a LimitConstraint if we are using the right click/drag of a limit

            if (lc != null)
                    limitTunePower_by_band[(int)tx_band] = lc.LimitValue; // store the adjusted limit level

            int new_pwr = setPowerFromTuneSlider(out bool bUseConstrain, e != EventArgs.Empty);
            tunePower_by_band[(int)tx_band] = ptbTune.Value;

            UpdateTuneLabel(lc != null && bUseConstrain, e);

            if (sender.GetType() == typeof(PrettyTrackBar))
                ptbTune.Focus();

            if (m_fTuneDrivePower != new_pwr)  // MW0LGE_21k9d
            {
                m_fTuneDrivePower = new_pwr;
                DrivePowerChangedHandlers?.Invoke(1, new_pwr, true); // only rx1, and always tune
            }

            //wd5y
            if (SetupForm.chkAmpDRVLim.Checked == true & chkExternalPA.Checked == true)
            {
                int drvlimpwr = (int)(ptbPWR.Value / (float)(ptbPWR.Maximum - ptbPWR.Minimum) * SetupForm.GetPABandMaxPower(TXBand));
                int tunlimpwr = (int)(ptbTune.Value / (float)(ptbTune.Maximum - ptbTune.Minimum) * SetupForm.GetPABandMaxPower(TXBand));

                if (SetupForm.numUpDnDRVLim.Value < drvlimpwr & SetupForm.numUpDnTUNLim.Value < tunlimpwr)
                {
                    RXOnly = true;
                    chkExternalPA.Checked = false;
                    ptbPWR.Value = 0;
                    lblPWR.Text = "Drive: " + 0 + "w";
                    lblPWR2.Text = "Drive:" + 0 + "w";
                    ptbTune.Value = 0;
                    lblTune.Text = "Tune: " + 0 + "w";
                    lblTune2.Text = "Tune:" + 0 + "w";

                    MessageBox.Show("The Drive And/Or Tune Power Is Above The Maximum Limit.", "Release PTT And Reset Power.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    RXOnly = false;
                    chkExternalPA.Checked = true;
                    return;
                }
            }

            if (SetupForm.chkAmpDRVLim.Checked == true & chkExternalPA.Checked == true)
            {
                int tunlimpwr = (int)(ptbTune.Value / (float)(ptbTune.Maximum - ptbTune.Minimum) * SetupForm.GetPABandMaxPower(TXBand));

                if (SetupForm.numUpDnTUNLim.Value < tunlimpwr)
                {
                    RXOnly = true;
                    chkExternalPA.Checked = false;
                    ptbTune.Value = 0;
                    lblTune.Text = "Tune: " + 0 + "w";
                    lblTune2.Text = "Tune:" + 0 + "w";

                    MessageBox.Show("The Drive And/Or Tune Power Is Above The Maximum Limit.", "Release PTT And Reset Power.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    RXOnly = false;
                    chkExternalPA.Checked = true;
                    return;
                }
            }

            if (sliderForm != null)
            {
                sliderForm.tbTune.Value = ptbTune.Value;
                sliderForm.lblTNE.Text = lblTune.Text;
            }
            //wd5y
        }
        private DrivePowerSource _tuneDrivePowerSource = DrivePowerSource.DRIVE_SLIDER;
        private DrivePowerSource _2ToneDrivePowerSource = DrivePowerSource.DRIVE_SLIDER;
        public DrivePowerSource TuneDrivePowerOrigin
        {
            get { return _tuneDrivePowerSource; }
            set { 
                _tuneDrivePowerSource = value;
                switch (_tuneDrivePowerSource)
                {
                    case DrivePowerSource.DRIVE_SLIDER:
                        ptbPWR_Scroll(this, EventArgs.Empty);
                        break;
                    case DrivePowerSource.TUNE_SLIDER:
                        ptbTune_Scroll(this, EventArgs.Empty);
                        break;
                    case DrivePowerSource.FIXED:
                        ptbPWR_Scroll(this, EventArgs.Empty);
                        break;
                }

                setupTuneDriveSlider();
                UpdateTuneLabel(false, EventArgs.Empty);
            }
        }
        public DrivePowerSource TwoToneDrivePowerOrigin
        {
            get { return _2ToneDrivePowerSource; }
            set { 
                _2ToneDrivePowerSource = value;
                switch (_2ToneDrivePowerSource)
                {
                    case DrivePowerSource.DRIVE_SLIDER:
                        ptbPWR_Scroll(this, EventArgs.Empty);
                        break;
                    case DrivePowerSource.TUNE_SLIDER:
                        ptbTune_Scroll(this, EventArgs.Empty);
                        break;
                    case DrivePowerSource.FIXED:
                        ptbPWR_Scroll(this, EventArgs.Empty);
                        break;
                }

                setupTuneDriveSlider();
                UpdateTuneLabel(false, EventArgs.Empty);
            }
        }
        private void setupTuneDriveSlider()
        {
            if (_tuneDrivePowerSource != DrivePowerSource.TUNE_SLIDER && _2ToneDrivePowerSource != DrivePowerSource.TUNE_SLIDER)
            {
                // hide it
                ptbTune.Visible = false;
                lblTune.Visible = false;
            }
            else
            {
                ptbTune.Visible = true;
                lblTune.Visible = true;
            }

            if (chkTUN.Checked)
            {
                ptbPWR.Enabled = _tuneDrivePowerSource == DrivePowerSource.DRIVE_SLIDER;
                ptbTune.Enabled = _tuneDrivePowerSource == DrivePowerSource.TUNE_SLIDER;
            }
            else if (chk2TONE.Checked)
            {
                ptbPWR.Enabled = _2ToneDrivePowerSource == DrivePowerSource.DRIVE_SLIDER;
                ptbTune.Enabled = _2ToneDrivePowerSource == DrivePowerSource.TUNE_SLIDER;
            }
            else
            {
                ptbPWR.Enabled = true;
                ptbTune.Enabled = true;
            }

            lblPWR.Enabled = ptbPWR.Enabled;
            lblTune.Enabled = ptbTune.Enabled;
        }
        private int setPowerFromDriveSlider(out bool bConstrain, bool bAdjustedBySliderControl)
        {
            int nDrv;
            nDrv = SetPowerUsingTargetDBM(out bool bConstrainOut, out double targetdBm, true, false, false);
            bConstrain = bConstrainOut;
            return nDrv;
        }
        private int setPowerFromTuneSlider(out bool bConstrain, bool bAdjustedBySliderControl)
        {
            int nDrv;
            nDrv = SetPowerUsingTargetDBM(out bool bConstrainOut, out double targetdBm, true, true, chk2TONE.Checked);
            bConstrain = bConstrainOut;
            return nDrv;
        }
        public int SetPowerUsingTargetDBM(out bool bConstrain, out double targetdBm, bool bSetPower, bool bFromTune, bool bTwoTone)
        {
            PrettyTrackBar slider = ptbPWR;
            bConstrain = true;
            int new_pwr = 0;
            // tx mode
            int txMode = 0; // 0 normal, 1 tune, 2 2tone

            if (!MOX && !chkTUN.Checked && !chk2TONE.Checked)
            {
                if (bFromTune)
                {
                    if (!bTwoTone)
                        txMode = 1;
                    else
                        txMode = 2;
                }
            }
            else
            {
                if (chkTUN.Checked)
                    txMode = 1;
                else if (chk2TONE.Checked)
                    txMode = 2;
            }

            switch (txMode)
            {
                case 0: //normal
                    new_pwr = ptbPWR.Value;
                    power_by_band[(int)tx_band] = new_pwr;
                    break;
                case 1: //tune
                    switch (_tuneDrivePowerSource)
                    {
                        case DrivePowerSource.DRIVE_SLIDER:
                            new_pwr = ptbPWR.Value;
                            break;
                        case DrivePowerSource.TUNE_SLIDER:
                            slider = ptbTune;
                            new_pwr = ptbTune.Value;
                            break;
                        case DrivePowerSource.FIXED:
                            new_pwr = tune_power;
                            bConstrain = false;
                            break;
                    }
                    break;
                case 2: //2tone
                    switch (_2ToneDrivePowerSource)
                    {
                        case DrivePowerSource.DRIVE_SLIDER:
                            new_pwr = ptbPWR.Value;
                            break;
                        case DrivePowerSource.TUNE_SLIDER:
                            slider = ptbTune;
                            new_pwr = ptbTune.Value;
                            break;
                        case DrivePowerSource.FIXED:
                            new_pwr = twotone_tune_power;
                            bConstrain = false;
                            break;
                    }
                    break;
            }

            if ((!chkTUN.Checked || xvtr_tune_power) && tx_xvtr_index >= 0)
            {
                if (slider.Focused)
                    XVTRForm.SetPower(tx_xvtr_index, slider.Value);
                Band b = BandByFreq(XVTRForm.TranslateFreq(VFOAFreq), tx_xvtr_index, current_region);
            }

            //constrain power
            if(bConstrain) new_pwr = slider.ConstrainAValue(new_pwr);
            //

            double target_dbm = 10 * (double)Math.Log10((double)new_pwr * 1000);
            double gbb;
            if (tx_xvtr_index >= 0)
            {
                Band lo_band = BandByFreq(XVTRForm.TranslateFreq(VFOAFreq), tx_xvtr_index, current_region);
                gbb = GainByBand(lo_band, new_pwr);
            }
            else
            {
                gbb = GainByBand(TXBand, new_pwr);
            }
            target_dbm -= gbb;

            double target_volts = Math.Sqrt(Math.Pow(10, target_dbm * 0.1) * 0.05);		// E = Sqrt(P * R) 

            targetdBm = target_dbm;
            if (!bSetPower) return new_pwr;

            //[2.10.3.5]MW0LGE max tx attenuation when power is increased and PS is enabled
            if (new_pwr != _lastPower && chkFWCATUBypass.Checked && _forceATTwhenPowerChangesWhenPSAon)
            {
                if(new_pwr > _lastPower)
                    SetupForm.ATTOnTX = 31;

                _lastPower = new_pwr;
            }

            if (new_pwr == 0)
            {
                Audio.RadioVolume = 0.0;
                if (chkTUN.Checked)
                    radio.GetDSPTX(0).TXPostGenRun = 0;
            }
            else
            {
                if (chkTUN.Checked)
                    radio.GetDSPTX(0).TXPostGenRun = 1;
                Audio.RadioVolume = (double)Math.Min((target_volts / 0.8), 1.0);
            }

            return new_pwr;
        }

        private bool _bEnableAudioAmplifier = true;
        public bool EnableAudioAmplifier
        {
            get { return _bEnableAudioAmplifier; }
            set
            {
                _bEnableAudioAmplifier = value;
                if (!IsSetupFormNull)
                    SetupForm.DisableAudioAmplifier = !_bEnableAudioAmplifier;
                enableAudioAmplfier();
            }
        }
        private void enableAudioAmplfier()
        {
            if (NetworkIO.CurrentRadioProtocol == RadioProtocol.ETH && //only protocol 2
                (CurrentHPSDRModel == HPSDRModel.ANAN7000D || CurrentHPSDRModel == HPSDRModel.ANAN8000D
                || CurrentHPSDRModel == HPSDRModel.ANAN_G2 || current_hpsdr_model == HPSDRModel.ANAN_G2_1K))
            {
                NetworkIO.SetAudioAmpEnable(_bEnableAudioAmplifier);
            }
        }

        private void ptbTune_MouseUp(object sender, MouseEventArgs e)
        {
            UpdateTuneLabel(false, EventArgs.Empty);
        }

        public void ResetLevelCalibration(bool ignoreSet = false)
        {
            for (int i = 0; i < (int)HPSDRModel.LAST; i++)
            {
                switch ((HPSDRModel)i)
                {
                    case HPSDRModel.ANAN7000D:
                    case HPSDRModel.ANAN8000D:
                    case HPSDRModel.ORIONMKII:
                        rx_meter_cal_offset_by_radio[i] = 4.841644f;
                        rx_display_cal_offset_by_radio[i] = 5.259f;
                        break;
                    case HPSDRModel.ANAN_G2:
                    case HPSDRModel.ANAN_G2_1K:
                        rx_meter_cal_offset_by_radio[i] = -4.476f;
                        rx_display_cal_offset_by_radio[i] = -4.4005f;
                        break;
                    default:
                        rx_meter_cal_offset_by_radio[i] = 0.98f;
                        rx_display_cal_offset_by_radio[i] = -2.1f;
                        break;
                }
            }

            if (ignoreSet) return;

            rx1_meter_cal_offset = rx_meter_cal_offset_by_radio[(int)current_hpsdr_model];
            rx2_meter_cal_offset = rx_meter_cal_offset_by_radio[(int)current_hpsdr_model];

            RX1DisplayCalOffset = rx_display_cal_offset_by_radio[(int)current_hpsdr_model];
            RX2DisplayCalOffset = rx_display_cal_offset_by_radio[(int)current_hpsdr_model];

            UpdateRX1DisplayOffsets();
            UpdateRX2DisplayOffsets();
        }
        private async void MultiMeter2UpdateRX1()
        {
            HiPerfTimer meterDelay = new HiPerfTimer();
            while (chkPower.Checked)
            {
                meterDelay.Reset();

                bool updateRX = false;
                bool updateTX = false;

                if (!_mox || (_mox && RX2Enabled && VFOBTX))
                {
                    float offset = RXOffset(1);

                    // get all readings
                    if (MeterManager.RequiresUpdate(1, Reading.SIGNAL_STRENGTH)) _RX1MeterValues[Reading.SIGNAL_STRENGTH] = WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.SIGNAL_STRENGTH) + offset;
                    bool bNeedAvg = true;
                    if (MeterManager.RequiresUpdate(1, Reading.AVG_SIGNAL_STRENGTH))
                    {
                        _RX1MeterValues[Reading.AVG_SIGNAL_STRENGTH] = WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.AVG_SIGNAL_STRENGTH) + offset;
                        bNeedAvg = false;
                    }
                    if (MeterManager.RequiresUpdate(1, Reading.ADC_PK)) _RX1MeterValues[Reading.ADC_PK] = WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.ADC_REAL);
                    if (MeterManager.RequiresUpdate(1, Reading.ADC_AV)) _RX1MeterValues[Reading.ADC_AV] = WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.ADC_IMAG);

                    if (MeterManager.RequiresUpdate(1, Reading.AGC_PK)) _RX1MeterValues[Reading.AGC_PK] = WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.AGC_PK);
                    if (MeterManager.RequiresUpdate(1, Reading.AGC_AV)) _RX1MeterValues[Reading.AGC_AV] = WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.AGC_AV);
                    if (MeterManager.RequiresUpdate(1, Reading.AGC_GAIN)) _RX1MeterValues[Reading.AGC_GAIN] = 0 - WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.AGC_GAIN);

                    if (MeterManager.RequiresUpdate(1, Reading.ESTIMATED_PBSNR))
                    {
                        if (!Display.FastAttackNoiseFloorRX1 && _lastRX1NoiseFloorGood)
                        {
                            float avg = bNeedAvg ? WDSP.CalculateRXMeter(0, 0, WDSP.MeterType.AVG_SIGNAL_STRENGTH) + offset : _RX1MeterValues[Reading.AVG_SIGNAL_STRENGTH];
                            spectralCalculations(1, avg, out double bin_width, out double dRWB, out int passbandWidth, out double noise_floor_power_spectral_density, out double estimated_passband_noise_power, out double estimated_snr, out double rx_dBHz, out double rbw_dBHz);
                            _RX1MeterValues[Reading.ESTIMATED_PBSNR] = (float)estimated_snr;
                        }
                        else
                            _RX1MeterValues[Reading.ESTIMATED_PBSNR] = 0f;
                    }

                    updateRX = true;
                }
                else if (_mox && (!RX2Enabled || (RX2Enabled && VFOATX)))
                {
                    updateMetersReading(Reading.MIC, (float)Math.Max(-195.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.MIC)), 0);
                    updateMetersReading(Reading.MIC_PK, (float)Math.Max(-195.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.MIC_PK)), 0);
                    updateMetersReading(Reading.EQ, (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.EQ)), 0);
                    updateMetersReading(Reading.EQ_PK, (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.EQ_PK)), 0);
                    updateMetersReading(Reading.LEVELER, (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.LEVELER)), 0);
                    updateMetersReading(Reading.LEVELER_PK, (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.LEVELER_PK)), 0);
                    updateMetersReading(Reading.LVL_G, (float)Math.Max(0, WDSP.CalculateTXMeter(1, WDSP.MeterType.LVL_G)), 0);
                    updateMetersReading(Reading.CFC_G, (float)Math.Max(0, -WDSP.CalculateTXMeter(1, WDSP.MeterType.CFC_G)), 0);
                    updateMetersReading(Reading.CFC_PK, (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.CFC_PK)), 0);
                    updateMetersReading(Reading.CFC_AV, (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.CFC_AV)), 0);
                    updateMetersReading(Reading.COMP, (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.COMP)), 0);
                    updateMetersReading(Reading.COMP_PK, (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.COMP_PK)), 0);

                    updateMetersReading(Reading.ALC, (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC)), 0);
                    updateMetersReading(Reading.ALC_PK, (float)Math.Max(-195.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC_PK)), 0);
                    updateMetersReading(Reading.ALC_G, (float)Math.Max(-195.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC_G)), 0);

                    updateMetersReading(Reading.ALC_GROUP, (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC_PK)) + (float)Math.Max(0, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC_G)), 0);

                    updateMetersReading(Reading.PWR, (alexpresent || apollopresent) && current_hpsdr_model == HPSDRModel.ANAN8000D && tx_xvtr_index >= 0 ? drivepwr : calfwdpower, 0);
                    updateMetersReading(Reading.REVERSE_PWR, (alexpresent || apollopresent) ? alex_rev : -200f, 0);
                    updateMetersReading(Reading.SWR, alex_swr, 0);

                    updateMetersReading(Reading.DRIVE_FWD_ADC, average_drvadc, 0);
                    updateMetersReading(Reading.FWD_ADC, average_fwdadc, 0);
                    updateMetersReading(Reading.REV_ADC, average_revadc, 0);
                    updateMetersReading(Reading.DRIVE_PWR, average_drivepwr, 0);
                    updateMetersReading(Reading.PA_FWD_PWR, alex_fwd, 0);
                    updateMetersReading(Reading.PA_REV_PWR, alex_rev, 0);
                    updateMetersReading(Reading.CAL_FWD_PWR, calfwdpower, 0);

                    //// get all readings
                    //if (MeterManager.RequiresUpdate(1, Reading.MIC)) _RX1MeterValues[Reading.MIC] = (float)Math.Max(-195.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.MIC));
                    //if (MeterManager.RequiresUpdate(1, Reading.MIC_PK)) _RX1MeterValues[Reading.MIC_PK] = (float)Math.Max(-195.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.MIC_PK));
                    //if (MeterManager.RequiresUpdate(1, Reading.EQ)) _RX1MeterValues[Reading.EQ] = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.EQ));
                    //if (MeterManager.RequiresUpdate(1, Reading.EQ_PK)) _RX1MeterValues[Reading.EQ_PK] = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.EQ_PK));
                    //if (MeterManager.RequiresUpdate(1, Reading.LEVELER)) _RX1MeterValues[Reading.LEVELER] = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.LEVELER));
                    //if (MeterManager.RequiresUpdate(1, Reading.LEVELER_PK)) _RX1MeterValues[Reading.LEVELER_PK] = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.LEVELER_PK));
                    //if (MeterManager.RequiresUpdate(1, Reading.LVL_G)) _RX1MeterValues[Reading.LVL_G] = (float)Math.Max(0, WDSP.CalculateTXMeter(1, WDSP.MeterType.LVL_G));
                    //if (MeterManager.RequiresUpdate(1, Reading.CFC_G)) _RX1MeterValues[Reading.CFC_G] = (float)Math.Max(0, -WDSP.CalculateTXMeter(1, WDSP.MeterType.CFC_G));
                    //if (MeterManager.RequiresUpdate(1, Reading.CFC_PK)) _RX1MeterValues[Reading.CFC_PK] = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.CFC_PK));
                    //if (MeterManager.RequiresUpdate(1, Reading.CFC_AV)) _RX1MeterValues[Reading.CFC_AV] = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.CFC_AV));
                    //if (MeterManager.RequiresUpdate(1, Reading.COMP)) _RX1MeterValues[Reading.COMP] = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.COMP));
                    //if (MeterManager.RequiresUpdate(1, Reading.COMP_PK)) _RX1MeterValues[Reading.COMP_PK] = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.COMP_PK));

                    //if (MeterManager.RequiresUpdate(1, Reading.ALC)) _RX1MeterValues[Reading.ALC] = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC));
                    //if (MeterManager.RequiresUpdate(1, Reading.ALC_PK)) _RX1MeterValues[Reading.ALC_PK] = (float)Math.Max(-195.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC_PK));
                    //if (MeterManager.RequiresUpdate(1, Reading.ALC_G)) _RX1MeterValues[Reading.ALC_G] = (float)Math.Max(-195.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC_G));

                    //if (MeterManager.RequiresUpdate(1, Reading.ALC_GROUP)) _RX1MeterValues[Reading.ALC_GROUP] = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC_PK)) + (float)Math.Max(0, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC_G));

                    //if (MeterManager.RequiresUpdate(1, Reading.PWR)) _RX1MeterValues[Reading.PWR] = (alexpresent || apollopresent) && current_hpsdr_model == HPSDRModel.ANAN8000D && tx_xvtr_index >= 0 ? drivepwr : calfwdpower;
                    //if (MeterManager.RequiresUpdate(1, Reading.REVERSE_PWR)) _RX1MeterValues[Reading.REVERSE_PWR] = (alexpresent || apollopresent) ? alex_rev : -200f;
                    //if (MeterManager.RequiresUpdate(1, Reading.SWR)) _RX1MeterValues[Reading.SWR] = alex_swr;

                    ////test code, uses 2 number controls on main console
                    ////if (EnableControlDebug)
                    ////{
                    ////    _RX1MeterValues[Reading.PWR] = (float)nudPwrTemp.Value;
                    ////    _RX1MeterValues[Reading.REVERSE_PWR] = (float)nudPwrTemp2.Value;
                    ////    float vswr;
                    ////    if (_RX1MeterValues[Reading.PWR] == 0)
                    ////        vswr = 1;
                    ////    else
                    ////        vswr = (1 + (float)Math.Sqrt(_RX1MeterValues[Reading.REVERSE_PWR] / _RX1MeterValues[Reading.PWR])) / (1 - (float)Math.Sqrt(_RX1MeterValues[Reading.REVERSE_PWR] / _RX1MeterValues[Reading.PWR]));
                    ////    _RX1MeterValues[Reading.SWR] = vswr;
                    ////}

                    //// pa
                    //// note: there are others distributed around the console.cs, search for MeterManager.RequiresUpdate.
                    //if (MeterManager.RequiresUpdate(1, Reading.DRIVE_FWD_ADC)) _RX1MeterValues[Reading.DRIVE_FWD_ADC] = average_drvadc;
                    //if (MeterManager.RequiresUpdate(1, Reading.FWD_ADC)) _RX1MeterValues[Reading.FWD_ADC] = average_fwdadc;
                    //if (MeterManager.RequiresUpdate(1, Reading.REV_ADC)) _RX1MeterValues[Reading.REV_ADC] = average_revadc;
                    //if (MeterManager.RequiresUpdate(1, Reading.DRIVE_PWR)) _RX1MeterValues[Reading.DRIVE_PWR] = average_drivepwr;
                    //if (MeterManager.RequiresUpdate(1, Reading.PA_FWD_PWR)) _RX1MeterValues[Reading.PA_FWD_PWR] = alex_fwd;
                    //if (MeterManager.RequiresUpdate(1, Reading.PA_REV_PWR)) _RX1MeterValues[Reading.PA_REV_PWR] = alex_rev;
                    //if (MeterManager.RequiresUpdate(1, Reading.CAL_FWD_PWR)) _RX1MeterValues[Reading.CAL_FWD_PWR] = calfwdpower;
                    ////

                    updateTX = true;
                }

                bool bNeedVolts = MeterManager.RequiresUpdate(1, Reading.VOLTS);
                bool bNeedAmps = MeterManager.RequiresUpdate(1, Reading.AMPS);
                if (bNeedVolts || bNeedAmps) 
                {
                    //computeMKIIPAVoltsAmps(); // computed by timer_cpu_volts_meter_Tick

                    if (bNeedVolts) _RX1MeterValues[Reading.VOLTS] = _MKIIPAVolts;
                    if (bNeedAmps) _RX1MeterValues[Reading.AMPS] = _MKIIPAAmps;

                    updateRX = true;
                }

                //MeterReadingsChangedHandlers?.Invoke(1, _mox && (!RX2Enabled || (RX2Enabled && VFOATX)), ref _RX1MeterValues);
                if (updateRX) MeterReadingsChangedHandlers?.Invoke(1, false, ref _RX1MeterValues);
                if (updateTX)
                {
                    MeterReadingsChangedHandlers?.Invoke(1, true, ref _RX1MeterValues);
                    MeterReadingsChangedHandlers?.Invoke(2, true, ref _RX2MeterValues); // also for rx2 as data is the same for tx
                }

                meterDelay.Stop();

                // get quickest updating meter from MeterManager
                int delayMS = MeterManager.QuickestUpdateInterval(1, _mox) - (int)meterDelay.DurationMsec;
                if (delayMS < 1) delayMS = 1;
                await Task.Delay(delayMS);
            }
        }
        private async void MultiMeter2UpdateRX2()
        {
            HiPerfTimer meterDelay = new HiPerfTimer();

            while (chkPower.Checked && rx2_enabled)
            {
                meterDelay.Reset();

                bool updateRX = false;
                bool updateTX = false;

                if (!_mox || (_mox && RX2Enabled && VFOATX))
                {
                    float offset = RXOffset(2);

                    // get all readings
                    if (MeterManager.RequiresUpdate(2, Reading.SIGNAL_STRENGTH)) _RX2MeterValues[Reading.SIGNAL_STRENGTH] = WDSP.CalculateRXMeter(2, 0, WDSP.MeterType.SIGNAL_STRENGTH) + offset;
                    bool bNeedAvg = true;
                    if (MeterManager.RequiresUpdate(2, Reading.AVG_SIGNAL_STRENGTH))
                    {
                        _RX2MeterValues[Reading.AVG_SIGNAL_STRENGTH] = WDSP.CalculateRXMeter(2, 0, WDSP.MeterType.AVG_SIGNAL_STRENGTH) + offset;
                        bNeedAvg = false;
                    }
                    if (MeterManager.RequiresUpdate(2, Reading.ADC_PK)) _RX2MeterValues[Reading.ADC_PK] = WDSP.CalculateRXMeter(2, 0, WDSP.MeterType.ADC_REAL);
                    if (MeterManager.RequiresUpdate(2, Reading.ADC_AV)) _RX2MeterValues[Reading.ADC_AV] = WDSP.CalculateRXMeter(2, 0, WDSP.MeterType.ADC_IMAG);

                    if (MeterManager.RequiresUpdate(2, Reading.AGC_PK)) _RX2MeterValues[Reading.AGC_PK] = WDSP.CalculateRXMeter(2, 0, WDSP.MeterType.AGC_PK);
                    if (MeterManager.RequiresUpdate(2, Reading.AGC_AV)) _RX2MeterValues[Reading.AGC_AV] = WDSP.CalculateRXMeter(2, 0, WDSP.MeterType.AGC_AV);
                    if (MeterManager.RequiresUpdate(2, Reading.AGC_GAIN)) _RX2MeterValues[Reading.AGC_GAIN] = 0 - WDSP.CalculateRXMeter(2, 0, WDSP.MeterType.AGC_GAIN);

                    if (MeterManager.RequiresUpdate(2, Reading.ESTIMATED_PBSNR))
                    {
                        if (!Display.FastAttackNoiseFloorRX2 && _lastRX2NoiseFloorGood)
                        {
                            float avg = bNeedAvg ? WDSP.CalculateRXMeter(2, 0, WDSP.MeterType.AVG_SIGNAL_STRENGTH) + offset : _RX2MeterValues[Reading.AVG_SIGNAL_STRENGTH];
                            spectralCalculations(2, avg, out double bin_width, out double dRWB, out int passbandWidth, out double noise_floor_power_spectral_density, out double estimated_passband_noise_power, out double estimated_snr, out double rx_dBHz, out double rbw_dBHz);
                            _RX2MeterValues[Reading.ESTIMATED_PBSNR] = (float)estimated_snr;
                        }
                        else
                            _RX2MeterValues[Reading.ESTIMATED_PBSNR] = 0f;
                    }

                    updateRX = true;
                }
                else if(_mox && RX2Enabled && VFOBTX)
                {
                    updateMetersReading(Reading.MIC, (float)Math.Max(-195.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.MIC)), 0);
                    updateMetersReading(Reading.MIC_PK, (float)Math.Max(-195.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.MIC_PK)), 0);
                    updateMetersReading(Reading.EQ, (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.EQ)), 0);
                    updateMetersReading(Reading.EQ_PK, (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.EQ_PK)), 0);
                    updateMetersReading(Reading.LEVELER, (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.LEVELER)), 0);
                    updateMetersReading(Reading.LEVELER_PK, (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.LEVELER_PK)), 0);
                    updateMetersReading(Reading.LVL_G, (float)Math.Max(0, WDSP.CalculateTXMeter(1, WDSP.MeterType.LVL_G)), 0);
                    updateMetersReading(Reading.CFC_G, (float)Math.Max(0, -WDSP.CalculateTXMeter(1, WDSP.MeterType.CFC_G)), 0);
                    updateMetersReading(Reading.CFC_PK, (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.CFC_PK)), 0);
                    updateMetersReading(Reading.CFC_AV, (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.CFC_AV)), 0);
                    updateMetersReading(Reading.COMP, (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.COMP)), 2);
                    updateMetersReading(Reading.COMP_PK, (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.COMP_PK)), 0);

                    updateMetersReading(Reading.ALC, (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC)), 0);
                    updateMetersReading(Reading.ALC_PK, (float)Math.Max(-195.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC_PK)), 0);
                    updateMetersReading(Reading.ALC_G, (float)Math.Max(-195.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC_G)), 0);

                    updateMetersReading(Reading.ALC_GROUP, (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC_PK)) + (float)Math.Max(0, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC_G)), 0);

                    updateMetersReading(Reading.PWR, (alexpresent || apollopresent) && current_hpsdr_model == HPSDRModel.ANAN8000D && tx_xvtr_index >= 0 ? drivepwr : calfwdpower, 0);
                    updateMetersReading(Reading.REVERSE_PWR, (alexpresent || apollopresent) ? alex_rev : -200f, 0);
                    updateMetersReading(Reading.SWR, alex_swr, 0);

                    updateMetersReading(Reading.DRIVE_FWD_ADC, average_drvadc, 0);
                    updateMetersReading(Reading.FWD_ADC, average_fwdadc, 0);
                    updateMetersReading(Reading.REV_ADC, average_revadc, 0);
                    updateMetersReading(Reading.DRIVE_PWR, average_drivepwr, 0);
                    updateMetersReading(Reading.PA_FWD_PWR, alex_fwd, 0);
                    updateMetersReading(Reading.PA_REV_PWR, alex_rev, 0);
                    updateMetersReading(Reading.CAL_FWD_PWR, calfwdpower, 0);

                    //// get all readings
                    //if (MeterManager.RequiresUpdate(2, Reading.MIC)) _RX2MeterValues[Reading.MIC] = (float)Math.Max(-195.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.MIC));
                    //if (MeterManager.RequiresUpdate(2, Reading.MIC_PK)) _RX2MeterValues[Reading.MIC_PK] = (float)Math.Max(-195.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.MIC_PK));
                    //if (MeterManager.RequiresUpdate(2, Reading.EQ)) _RX2MeterValues[Reading.EQ] = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.EQ));
                    //if (MeterManager.RequiresUpdate(2, Reading.EQ_PK)) _RX2MeterValues[Reading.EQ_PK] = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.EQ_PK));
                    //if (MeterManager.RequiresUpdate(2, Reading.LEVELER)) _RX2MeterValues[Reading.LEVELER] = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.LEVELER));
                    //if (MeterManager.RequiresUpdate(2, Reading.LEVELER_PK)) _RX2MeterValues[Reading.LEVELER_PK] = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.LEVELER_PK));
                    //if (MeterManager.RequiresUpdate(2, Reading.LVL_G)) _RX2MeterValues[Reading.LVL_G] = (float)Math.Max(0, WDSP.CalculateTXMeter(1, WDSP.MeterType.LVL_G));
                    //if (MeterManager.RequiresUpdate(2, Reading.CFC_G)) _RX2MeterValues[Reading.CFC_G] = (float)Math.Max(0, -WDSP.CalculateTXMeter(1, WDSP.MeterType.CFC_G));
                    //if (MeterManager.RequiresUpdate(2, Reading.CFC_PK)) _RX2MeterValues[Reading.CFC_PK] = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.CFC_PK));
                    //if (MeterManager.RequiresUpdate(2, Reading.CFC_AV)) _RX2MeterValues[Reading.CFC_AV] = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.CFC_AV));
                    //if (MeterManager.RequiresUpdate(2, Reading.COMP)) _RX2MeterValues[Reading.COMP] = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.COMP));//peak_tx_meter ? (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.CPDR_PK)) : (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.CPDR));
                    //if (MeterManager.RequiresUpdate(2, Reading.COMP_PK)) _RX2MeterValues[Reading.COMP_PK] = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.COMP_PK));

                    //if (MeterManager.RequiresUpdate(2, Reading.ALC)) _RX2MeterValues[Reading.ALC] = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC));//peak_tx_meter ? (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC)) : (float)Math.Max(-195.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC));
                    //if (MeterManager.RequiresUpdate(2, Reading.ALC_PK)) _RX2MeterValues[Reading.ALC_PK] = (float)Math.Max(-195.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC_PK));
                    //if (MeterManager.RequiresUpdate(2, Reading.ALC_G)) _RX2MeterValues[Reading.ALC_G] = (float)Math.Max(-195.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC_G));

                    //if (MeterManager.RequiresUpdate(2, Reading.ALC_GROUP)) _RX2MeterValues[Reading.ALC_GROUP] = (float)Math.Max(-30.0f, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC_PK)) + (float)Math.Max(0, -WDSP.CalculateTXMeter(1, WDSP.MeterType.ALC_G));

                    //if (MeterManager.RequiresUpdate(2, Reading.PWR)) _RX2MeterValues[Reading.PWR] = (alexpresent || apollopresent) && current_hpsdr_model == HPSDRModel.ANAN8000D && tx_xvtr_index >= 0 ? drivepwr : calfwdpower;
                    //if (MeterManager.RequiresUpdate(2, Reading.REVERSE_PWR)) _RX2MeterValues[Reading.REVERSE_PWR] = (alexpresent || apollopresent) ? alex_rev : -200f;
                    //if (MeterManager.RequiresUpdate(2, Reading.SWR)) _RX2MeterValues[Reading.SWR] = alex_swr;

                    //// pa
                    //// note: there are others distributed around the console.cs, search for MeterManager.RequiresUpdate.
                    //if (MeterManager.RequiresUpdate(2, Reading.DRIVE_FWD_ADC)) _RX2MeterValues[Reading.DRIVE_FWD_ADC] = average_drvadc;
                    //if (MeterManager.RequiresUpdate(2, Reading.FWD_ADC)) _RX2MeterValues[Reading.FWD_ADC] = average_fwdadc;
                    //if (MeterManager.RequiresUpdate(2, Reading.REV_ADC)) _RX2MeterValues[Reading.REV_ADC] = average_revadc;
                    //if (MeterManager.RequiresUpdate(2, Reading.DRIVE_PWR)) _RX2MeterValues[Reading.DRIVE_PWR] = average_drivepwr;
                    //if (MeterManager.RequiresUpdate(2, Reading.PA_FWD_PWR)) _RX2MeterValues[Reading.PA_FWD_PWR] = alex_fwd;
                    //if (MeterManager.RequiresUpdate(2, Reading.PA_REV_PWR)) _RX2MeterValues[Reading.PA_REV_PWR] = alex_rev;
                    //if (MeterManager.RequiresUpdate(2, Reading.CAL_FWD_PWR)) _RX2MeterValues[Reading.CAL_FWD_PWR] = calfwdpower;
                    ////

                    updateTX = true;
                }

                bool bNeedVolts = MeterManager.RequiresUpdate(1, Reading.VOLTS);
                bool bNeedAmps = MeterManager.RequiresUpdate(1, Reading.AMPS);
                if (bNeedVolts || bNeedAmps)
                {
                    //computeMKIIPAVoltsAmps(); // computed by timer_cpu_volts_meter_Tick

                    if (bNeedVolts) _RX2MeterValues[Reading.VOLTS] = _MKIIPAVolts;
                    if (bNeedAmps) _RX2MeterValues[Reading.AMPS] = _MKIIPAAmps;

                    updateRX = true;
                }

                //MeterReadingsChangedHandlers?.Invoke(2, _mox && RX2Enabled && VFOBTX, ref _RX2MeterValues);
                if (updateRX) MeterReadingsChangedHandlers?.Invoke(2, false, ref _RX2MeterValues);
                if (updateTX)
                {
                    MeterReadingsChangedHandlers?.Invoke(2, true, ref _RX2MeterValues);
                    MeterReadingsChangedHandlers?.Invoke(1, true, ref _RX1MeterValues); // also for rx1 as data is the same
                }

                meterDelay.Stop();

                // get quickest RX updating meter from MeterManager
                int delayMS = MeterManager.QuickestUpdateInterval(2, false) - (int)meterDelay.DurationMsec;
                if (delayMS < 1) delayMS = 1;
                await Task.Delay(delayMS);
            }
        }
        private void updateMetersReading(Reading reading, float value, int rx)
        {
            if ((rx == 0 || rx == 1) && MeterManager.RequiresUpdate(1, reading)) _RX1MeterValues[reading] = value;
            if ((rx == 0 || rx == 2) && MeterManager.RequiresUpdate(2, reading)) _RX2MeterValues[reading] = value;
        }
        private void picMultiMeterDigital_Click(object sender, EventArgs e)
        {
        }

        private void picRX2Meter_Click(object sender, EventArgs e)
        {
        }

        private void ucVAC1UnderOver_ClearIssuesClick(object sender, EventArgs e)
        {
            ivac.resetIVACdiags(0, 0);
            ivac.resetIVACdiags(0, 1);
        }

        private void ucVAC2UnderOver_ClearIssuesClick(object sender, EventArgs e)
        {
            ivac.resetIVACdiags(1, 0);
            ivac.resetIVACdiags(1, 1);
        }

        private float[] getPassbandSpectrum(int rx, int fft_size, double[,] spectrum_data)
        {
            int lo_cut_hz;
            int hi_cut_hz;
            double hz_per_bucket;
            int zero_hz_bucket = fft_size / 2;
            int nExpand = 0;

            if (rx == 1)
            {
                hz_per_bucket = sample_rate_rx1 / (double)fft_size;
                lo_cut_hz = RX1FilterLow - nExpand;
                hi_cut_hz = RX1FilterHigh + nExpand;
            }
            else
            {
                hz_per_bucket = sample_rate_rx2 / (double)fft_size;
                lo_cut_hz = RX2FilterLow - nExpand;
                hi_cut_hz = RX2FilterHigh + nExpand;
            }

            bool bIgnoreCtun;
            if (rx == 1)
            {
                bIgnoreCtun = Display.CurrentDisplayMode == DisplayMode.SPECTRUM ||
                            Display.CurrentDisplayMode == DisplayMode.SPECTRASCOPE ||
                            Display.CurrentDisplayMode == DisplayMode.HISTOGRAM;
            }
            else
            {
                bIgnoreCtun = Display.CurrentDisplayModeBottom == DisplayMode.SPECTRUM ||
                            Display.CurrentDisplayModeBottom == DisplayMode.SPECTRASCOPE ||
                            Display.CurrentDisplayModeBottom == DisplayMode.HISTOGRAM;

            }
            if (!bIgnoreCtun && click_tune_display) //MW0LGE_21d
            {
                // need to calc zero hz bucket point for freq as it wont be in the middle of FFT as above
                double dBucketOffset;
                if (rx == 1)
                    dBucketOffset = ((VFOAFreq - CentreFrequency) * 1e6) / hz_per_bucket;
                else
                    dBucketOffset = ((VFOBFreq - CentreRX2Frequency) * 1e6) / hz_per_bucket;

                zero_hz_bucket += (int)dBucketOffset;
            }

            int lo_bucket = (int)(lo_cut_hz / hz_per_bucket) + zero_hz_bucket;
            int hi_bucket = (int)(hi_cut_hz / hz_per_bucket) + zero_hz_bucket;

            if (lo_bucket < 0 || hi_bucket > fft_size - 1)
            {
                return null;
            }

            double mag_sqr;
            float[] dbm = new float[hi_bucket - lo_bucket + 1];
            double pow2fft = Math.Pow(fft_size, 2);

            // all the offsets, use display
            float fOffset;
            if (rx == 1)
                fOffset = Display.RX1Offset;
            else
                fOffset = Display.RX2Offset;

            for (int i = lo_bucket; i <= hi_bucket; i++)
            {
                mag_sqr = spectrum_data[i, 0] * spectrum_data[i, 0] + spectrum_data[i, 1] * spectrum_data[i, 1];
                dbm[i - lo_bucket] = (float)(10.0f * Math.Log10(mag_sqr / pow2fft)) + fOffset;
            }

            return dbm;
        }
        private bool _bIgnoreSqlUpdate = false;// used by chkSquelch_CheckStateChanged
        private void ptbSquelch_Scroll(object sender, System.EventArgs e)
        {
            if (_bIgnoreSqlUpdate) return; // used by chkSquelch_CheckStateChanged

            int nValue;

            switch (chkSquelch.CheckState)
            {
                case CheckState.Unchecked:
                    // off //NOTE: no break here so that the sql threshold values are set, ready for us clicking the sql button

                    //wd5y
                    chkSquelch.Text = "SQL-OFF";
                    if (sliderForm != null)
                    {
                        sliderForm.lblRX1sql.Text = chkSquelch.Text;
                        sliderForm.chkRX1Sql.Text = "SQL OFF";
                    }
                    break;
                //wd5y

                case CheckState.Checked:
                    // sql
                    if (rx1_dsp_mode == DSPMode.FM) //FM Squelch
                    {
                        //nValue = ptbSquelch.Value; // 0-100
                        //[2.10.3.5]MW0LGE convert to a 0-100 scale from a -160 to 0 scale
                        nValue = (int)(((ptbSquelch.Value + 160) / 160f) * 100f);

                        rx1_fm_squelch_threshold_scroll = ptbSquelch.Value;

                        radio.GetDSPRX(0, 0).FMSquelchThreshold = (float)Math.Pow(10.0, -2.0 * nValue / 100.0);
                        radio.GetDSPRX(0, 1).FMSquelchThreshold = (float)Math.Pow(10.0, -2.0 * nValue / 100.0);
                    }
                    else
                    {
                        rx1_squelch_threshold_scroll = ptbSquelch.Value;

                        //[2.10.3.5]MW0LGE reverted back to a -160 to 0 scale
                        nValue = ptbSquelch.Value;                        

                        radio.GetDSPRX(0, 0).RXSquelchThreshold = (float)nValue -
                          rx1_preamp_offset[(int)rx1_preamp_mode] -
                          rx1_meter_cal_offset -
                          (-alex_preamp_offset);

                        radio.GetDSPRX(0, 1).RXSquelchThreshold = (float)nValue -
                            rx1_preamp_offset[(int)rx1_preamp_mode] -
                            rx1_meter_cal_offset -
                            (-alex_preamp_offset);
                    }

                    chkSquelch.Text = "SQL:  " + nValue.ToString();

                    //wd5y
                    if (sliderForm != null)
                    {
                        sliderForm.lblRX1sql.Text = chkSquelch.Text;
                        sliderForm.chkRX1Sql.Text = "SQL";
                    }
                    //wd5y
                    break;
                case CheckState.Indeterminate:
                    // vsq
                    //[2.10.3.5]MW0LGE convert to a 0-100 scale from a -160 to 0 scale
                    nValue = (int)(((ptbSquelch.Value + 160) / 160f) * 100f);

                    rx1_voice_squelch_threshold_scroll = ptbSquelch.Value;

                    radio.GetDSPRX(0, 0).SSqlThreshold = nValue / 100f;
                    radio.GetDSPRX(0, 1).SSqlThreshold = nValue / 100f;

                    chkSquelch.Text = "VSQL: " + nValue.ToString();

                    //wd5y
                    if (sliderForm != null)
                    {
                        sliderForm.lblRX1sql.Text = chkSquelch.Text;
                        sliderForm.chkRX1Sql.Text = "VSQL";
                    }
                    //wd5y
                    break;
            }

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbSquelch.Focus();
            }
            if (sliderForm != null)
                //[2.10.3.5]MW0LGE
                sliderForm.RX1Squelch = ptbSquelch.Value;
        }
        private bool _bIgnoreSqlStateChange = false;// used by handleSqlFM
        private void chkSquelch_CheckStateChanged(object sender, EventArgs e)
        {
            if (initializing || _bIgnoreSqlStateChange) return;

            bool bShowLevelBar = !collapsedDisplay;
            int nValue = 0;

            switch (chkSquelch.CheckState)
            {
                case CheckState.Unchecked:
                    // all off
                    radio.GetDSPRX(0, 0).RXFMSquelchOn = false;
                    radio.GetDSPRX(0, 1).RXFMSquelchOn = false;
                    radio.GetDSPRX(0, 0).RXAMSquelchOn = false;
                    radio.GetDSPRX(0, 1).RXAMSquelchOn = false;
                    radio.GetDSPRX(0, 0).SSqlOn = false;
                    radio.GetDSPRX(0, 1).SSqlOn = false;
                    if (rx1_dsp_mode == DSPMode.FM)
                    {
                        rx1_fm_squelch_state = SquelchState.OFF;
                        bShowLevelBar = false;
                        nValue = rx1_fm_squelch_threshold_scroll;
                    }
                    else
                    {
                        rx1_squelch_state = SquelchState.OFF;
                        nValue = rx1_squelch_threshold_scroll;
                    }
                    break;
                case CheckState.Checked:
                    // sql
                    switch (rx1_dsp_mode)
                    {
                        case DSPMode.FM:
                            radio.GetDSPRX(0, 0).RXAMSquelchOn = false;
                            radio.GetDSPRX(0, 1).RXAMSquelchOn = false;
                            radio.GetDSPRX(0, 0).SSqlOn = false;
                            radio.GetDSPRX(0, 1).SSqlOn = false;
                            radio.GetDSPRX(0, 0).RXFMSquelchOn = true;
                            radio.GetDSPRX(0, 1).RXFMSquelchOn = true;
                            rx1_fm_squelch_state = SquelchState.SQL;
                            bShowLevelBar = false;
                            nValue = rx1_fm_squelch_threshold_scroll;
                            break;
                        default:
                            radio.GetDSPRX(0, 0).RXFMSquelchOn = false;
                            radio.GetDSPRX(0, 1).RXFMSquelchOn = false;
                            radio.GetDSPRX(0, 0).SSqlOn = false;
                            radio.GetDSPRX(0, 1).SSqlOn = false;
                            radio.GetDSPRX(0, 0).RXAMSquelchOn = true;
                            radio.GetDSPRX(0, 1).RXAMSquelchOn = true;
                            rx1_squelch_state = SquelchState.SQL;
                            nValue = rx1_squelch_threshold_scroll;
                            break;
                    }
                    break;
                case CheckState.Indeterminate:
                    // vsq
                    radio.GetDSPRX(0, 0).RXFMSquelchOn = false;
                    radio.GetDSPRX(0, 1).RXFMSquelchOn = false;
                    radio.GetDSPRX(0, 0).RXAMSquelchOn = false;
                    radio.GetDSPRX(0, 1).RXAMSquelchOn = false;
                    radio.GetDSPRX(0, 0).SSqlOn = true;
                    radio.GetDSPRX(0, 1).SSqlOn = true;
                    if (rx1_dsp_mode == DSPMode.FM)
                    {
                        rx1_fm_squelch_state = SquelchState.VSQL;
                    }
                    else
                    {
                        rx1_squelch_state = SquelchState.VSQL;
                    }
                    bShowLevelBar = false;
                    nValue = rx1_voice_squelch_threshold_scroll;
                    break;
            }

            //SQL

            if (sliderForm != null)
                sliderForm.RX1SquelchState = chkSquelch.CheckState; //[2.10.3.5]MW0LGE
            AndromedaIndicatorCheck(EIndicatorActions.eINSquelch, true, chkSquelch.Checked);

            //update
            picSquelch.Visible = bShowLevelBar;

            _bIgnoreSqlUpdate = true;
            ptbSquelch.Value = nValue;
            _bIgnoreSqlUpdate = false;

            ptbSquelch_Scroll(this, EventArgs.Empty);
        }
        private void handleSqlFM(int rx, bool bFM)
        {
            // rx 1,2
            // bFM - true is starting fm
            _bIgnoreSqlStateChange = true; // previent the assignment of state from running code in chkSquelch_CheckStateChanged
                                           // as chkSquelch_CheckStateChanged is already called in SetRX1Mode where this function is used

            if (rx == 1)
            {                
                if (bFM)
                {
                    // entering FM
                    switch (rx1_fm_squelch_state)
                    {
                        case SquelchState.OFF:
                            chkSquelch.CheckState = CheckState.Unchecked;
                            break;
                        case SquelchState.SQL:
                            chkSquelch.CheckState = CheckState.Checked;
                            break;
                        case SquelchState.VSQL:
                            chkSquelch.CheckState = CheckState.Indeterminate;
                            break;
                    }
                }
                else
                {
                    // exiting FM
                    switch (rx1_squelch_state)
                    {
                        case SquelchState.OFF:
                            chkSquelch.CheckState = CheckState.Unchecked;
                            break;
                        case SquelchState.SQL:
                            chkSquelch.CheckState = CheckState.Checked;
                            break;
                        case SquelchState.VSQL:
                            chkSquelch.CheckState = CheckState.Indeterminate;
                            break;
                    }
                }
            }
            else if (rx == 2)
            {
                if (bFM)
                {
                    // entering FM
                    switch (rx2_fm_squelch_state)
                    {
                        case SquelchState.OFF:
                            chkRX2Squelch.CheckState = CheckState.Unchecked;
                            break;
                        case SquelchState.SQL:
                            chkRX2Squelch.CheckState = CheckState.Checked;
                            break;
                        case SquelchState.VSQL:
                            chkRX2Squelch.CheckState = CheckState.Indeterminate;
                            break;
                    }
                }
                else
                {
                    // exiting FM
                    switch (rx2_squelch_state)
                    {
                        case SquelchState.OFF:
                            chkRX2Squelch.CheckState = CheckState.Unchecked;
                            break;
                        case SquelchState.SQL:
                            chkRX2Squelch.CheckState = CheckState.Checked;
                            break;
                        case SquelchState.VSQL:
                            chkRX2Squelch.CheckState = CheckState.Indeterminate;
                            break;
                    }
                }
            }

            _bIgnoreSqlStateChange = false;
        }

        private void chkRX2Squelch_CheckStateChanged(object sender, EventArgs e)
        {
            if (initializing || _bIgnoreSqlStateChange) return;

            bool bShowLevelBar = !collapsedDisplay;
            int nValue = 0;

            switch (chkRX2Squelch.CheckState)
            {
                case CheckState.Unchecked:
                    // all off
                    radio.GetDSPRX(1, 0).RXFMSquelchOn = false;
                    radio.GetDSPRX(1, 1).RXFMSquelchOn = false;
                    radio.GetDSPRX(1, 0).RXAMSquelchOn = false;
                    radio.GetDSPRX(1, 1).RXAMSquelchOn = false;
                    radio.GetDSPRX(1, 0).SSqlOn = false;
                    radio.GetDSPRX(1, 1).SSqlOn = false;
                    if (rx2_dsp_mode == DSPMode.FM)
                    {
                        rx2_fm_squelch_state = SquelchState.OFF;
                        bShowLevelBar = false;
                        nValue = rx2_fm_squelch_threshold_scroll;
                    }
                    else
                    {
                        rx2_squelch_state = SquelchState.OFF;
                        nValue = rx2_squelch_threshold_scroll;
                    }
                    break;
                case CheckState.Checked:
                    // sql
                    switch (rx2_dsp_mode)
                    {
                        case DSPMode.FM:
                            radio.GetDSPRX(1, 0).RXAMSquelchOn = false;
                            radio.GetDSPRX(1, 1).RXAMSquelchOn = false;
                            radio.GetDSPRX(1, 0).SSqlOn = false;
                            radio.GetDSPRX(1, 1).SSqlOn = false;
                            radio.GetDSPRX(1, 0).RXFMSquelchOn = true;
                            radio.GetDSPRX(1, 1).RXFMSquelchOn = true;
                            rx2_fm_squelch_state = SquelchState.SQL;
                            bShowLevelBar = false;
                            nValue = rx2_fm_squelch_threshold_scroll;
                            break;
                        default:
                            radio.GetDSPRX(1, 0).RXFMSquelchOn = false;
                            radio.GetDSPRX(1, 1).RXFMSquelchOn = false;
                            radio.GetDSPRX(1, 0).SSqlOn = false;
                            radio.GetDSPRX(1, 1).SSqlOn = false;
                            radio.GetDSPRX(1, 0).RXAMSquelchOn = true;
                            radio.GetDSPRX(1, 1).RXAMSquelchOn = true;
                            rx2_squelch_state = SquelchState.SQL;
                            nValue = rx2_squelch_threshold_scroll;
                            break;
                    }
                    break;
                case CheckState.Indeterminate:
                    // vsq
                    radio.GetDSPRX(1, 0).RXFMSquelchOn = false;
                    radio.GetDSPRX(1, 1).RXFMSquelchOn = false;
                    radio.GetDSPRX(1, 0).RXAMSquelchOn = false;
                    radio.GetDSPRX(1, 1).RXAMSquelchOn = false;
                    radio.GetDSPRX(1, 0).SSqlOn = true;
                    radio.GetDSPRX(1, 1).SSqlOn = true;
                    if (rx2_dsp_mode == DSPMode.FM)
                    {
                        rx2_fm_squelch_state = SquelchState.VSQL;
                    }
                    else
                    {
                        rx2_squelch_state = SquelchState.VSQL;
                    }
                    bShowLevelBar = false;
                    nValue = rx2_voice_squelch_threshold_scroll;
                    break;
            }

            if (sliderForm != null)
                sliderForm.RX2SquelchState = chkRX2Squelch.CheckState; //[2.10.3.5]MW0LGE
            AndromedaIndicatorCheck(EIndicatorActions.eINSquelch, true, chkRX2Squelch.Checked);

            //update
            picRX2Squelch.Visible = bShowLevelBar;

            _bIgnoreSqlUpdate = true;
            ptbRX2Squelch.Value = nValue;
            _bIgnoreSqlUpdate = false;

            ptbRX2Squelch_Scroll(this, EventArgs.Empty);
        }

        private void ptbRX2Squelch_Scroll(object sender, System.EventArgs e)
        {            
            if (_bIgnoreSqlUpdate) return; // used by chkRX2Squelch_CheckStateChanged

            int nValue;

            switch (chkRX2Squelch.CheckState)
            {
                case CheckState.Unchecked:
                    // off

                    //wd5y
                    chkRX2Squelch.Text = "SQL-OFF";
                    if (sliderForm != null)
                    {
                        sliderForm.lblRX2sql.Text = chkRX2Squelch.Text;
                        sliderForm.chkRX2Sql.Text = "SQL OFF";
                    }
                    break;
                //wd5y

                case CheckState.Checked:
                    // sql
                    if (rx2_dsp_mode == DSPMode.FM) //FM Squelch
                    {
                        //[2.10.3.5]MW0LGE convert to a 0-100 scale from a -160 to 0 scale
                        nValue = (int)(((ptbRX2Squelch.Value + 160) / 160f) * 100f);

                        rx2_fm_squelch_threshold_scroll = ptbRX2Squelch.Value;

                        radio.GetDSPRX(1, 0).FMSquelchThreshold = (float)Math.Pow(10.0, -2.0 * nValue / 100.0);
                        radio.GetDSPRX(1, 1).FMSquelchThreshold = (float)Math.Pow(10.0, -2.0 * nValue / 100.0);
                    }
                    else
                    {
                        rx2_squelch_threshold_scroll = ptbRX2Squelch.Value; // 0-100

                        //[2.10.3.5]MW0LGE reverted back to a -160 to 0 scale
                        nValue = ptbRX2Squelch.Value;

                        radio.GetDSPRX(1, 0).RXSquelchThreshold = (float)nValue -
                          rx2_preamp_offset[(int)rx2_preamp_mode] -
                          rx2_meter_cal_offset -
                          rx2_path_offset;

                        radio.GetDSPRX(1, 1).RXSquelchThreshold = (float)nValue -
                            rx2_preamp_offset[(int)rx2_preamp_mode] -
                            rx2_meter_cal_offset -
                            rx2_path_offset;
                    }

                    chkRX2Squelch.Text = "SQL:  " + nValue.ToString();

                    //wd5y
                    if (sliderForm != null)
                    {
                        sliderForm.lblRX2sql.Text = chkRX2Squelch.Text;
                        sliderForm.chkRX2Sql.Text = "SQL";
                    }
                    //wd5y
                    break;
                case CheckState.Indeterminate:
                    // vsq
                    //[2.10.3.5]MW0LGE convert to a 0-100 scale from a -160 to 0 scale
                    nValue = (int)(((ptbRX2Squelch.Value + 160) / 160f) * 100f);

                    rx2_voice_squelch_threshold_scroll = ptbRX2Squelch.Value;

                    radio.GetDSPRX(1, 0).SSqlThreshold = nValue / 100f;
                    radio.GetDSPRX(1, 1).SSqlThreshold = nValue / 100f;

                    chkRX2Squelch.Text = "VSQL: " + nValue.ToString();

                    //wd5y
                    if (sliderForm != null)
                    {
                        sliderForm.lblRX2sql.Text = chkRX2Squelch.Text;
                        sliderForm.chkRX2Sql.Text = "VSQL";
                    }
                    //wd5y
                    break;
            }

            if (sender.GetType() == typeof(PrettyTrackBar))
            {
                ptbRX2Squelch.Focus();
            }
            if (sliderForm != null)
                //[2.10.3.5]MW0LGE
                sliderForm.RX2Squelch = ptbRX2Squelch.Value;
        }

        private void chkSquelch_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.AM_Tab);
        }

        private void chkRX2Squelch_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.AM_Tab);
        }

        private void chkVFOSplit_MouseClick(object sender, MouseEventArgs e)
        {
            //[2.10.1.0] MW0LGE
            // this control has AutoCheck turned off, and is now handled here
            // so that QSPLIT can be enabled/disabled by shift left clicking SPLT button
            if (e.Button == MouseButtons.Left && Keyboard.IsKeyDown(Keys.LShiftKey))
            {
                if (!IsSetupFormNull && !RX2Enabled) SetupForm.QuickSplitEnabled = !SetupForm.QuickSplitEnabled;
            }
            else
            {
                chkVFOSplit.Checked = !chkVFOSplit.Checked;
            }
        }

        private void chkVFOSplit_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.OPTIONS2_Tab);
        }

        private void lblPAProfile_MouseDown(object sender, MouseEventArgs e)
        {
            if (IsRightButton(e)) SetupForm.ShowSetupTab(Setup.SetupTab.PA_Tab);
        }

        public bool IsExpandedView
        {
            get { return _isexpanded; }
        }
        public bool IsCollapsedView
        {
            get { return _iscollapsed; }
        }
        private bool _useLegacyMeters = true;
        public bool UseLegacyMeters
        {
            get { return _useLegacyMeters; }
            set { 
                _useLegacyMeters = value;

                //start threads if needed, if previously running thread loops will terminate if _useLegacyMeters becomes false
                if (_useLegacyMeters)
                {
                    setupLegacyMeterThreads(1);
                    setupLegacyMeterThreads(2);
                }

                updateLegacyMeterControls(_isexpanded && !_iscollapsed);

                LegacyItemController.HideMeters = !_useLegacyMeters;
            }
        }

        //wd5y
        private void updateLegacyMeterControls(bool expanded)
        {
            //note: code lines commented with //LM in other functions are now performed here
            if (expanded)
            {
                grpMultimeter.Visible = _useLegacyMeters;
                grpRX2Meter.Visible = _useLegacyMeters;
                grpMultimeterMenus.Visible = _useLegacyMeters;
                comboMeterRXMode.Visible = _useLegacyMeters;
                comboRX2MeterMode.Visible = _useLegacyMeters;
                comboMeterTXMode.Visible = _useLegacyMeters;
            }
            else
            {
                grpMultimeter.Visible = false;
                grpRX2Meter.Visible = false;
                grpMultimeterMenus.Visible = false;
                comboMeterRXMode.Visible = false;
                comboRX2MeterMode.Visible = false;
                comboMeterTXMode.Visible = false;
                panelMeterLabels.Visible = false;

                if (_showAndromedaTopControls)
                {
                    picMultiMeterDigital.Visible = _useLegacyMeters && ShowRX1;
                    txtMultiText.Visible = _useLegacyMeters && ShowRX1;
                    picRX2Meter.Visible = _useLegacyMeters && ShowRX2;
                    txtRX2Meter.Visible = _useLegacyMeters && ShowRX2;
                    panelMeterLabels.Visible = _useLegacyMeters;
                    comboMeterRXMode.Visible = _useLegacyMeters && ShowRX1;
                    comboRX2MeterMode.Visible = _useLegacyMeters && ShowRX2;
                    comboMeterTXMode.Visible = _useLegacyMeters;
                    if (_useLegacyMeters)
                    {
                        this.MinimumSize = new Size(1622, 760);
                    }
                    else
                    {
                        this.MinimumSize = new Size(1142, 760);
                    }
                }
                else
                {
                    panelMeterLabels.Visible = false;
                    comboMeterRXMode.Visible = false;
                    comboRX2MeterMode.Visible = false;
                    comboMeterTXMode.Visible = false;
                    picMultiMeterDigital.Visible = false;
                    txtMultiText.Visible = false;
                    picRX2Meter.Visible = false;
                    txtRX2Meter.Visible = false;
                }                             
            }
            //wd5y
        }

        //[2.10.1.0] MW0LGE code/idea from WD5Y
        private bool _spacebar_vfobtx = false;
        public bool SpaceBarVFOBTX
        {
            get { return _spacebar_vfobtx; }
            set { _spacebar_vfobtx = value; }
        }

        public float RX1FFTFillTime
        {
            get { return _fft_fill_timeRX1; }
        }
        public float RX2FFTFillTime
        {
            get { return _fft_fill_timeRX2; }
        }
        private float _fft_fill_timeRX1 = 0f;
        private float _fft_fill_timeRX2 = 0f;
        public void InitFFTFillTime(int rx)
        {
            //https://community.apache-labs.com/viewtopic.php?f=9&t=4382&p=22287
            //https://github.com/ramdor/Thetis/issues/204
            //issue #204
            int fft_size;
            int sample_rate;
            if (rx == 1)
            {
                fft_size = specRX.GetSpecRX(0).FFTSize;
                sample_rate = specRX.GetSpecRX(0).SampleRate;
            }
            else if (rx == 2)
            {
                fft_size = specRX.GetSpecRX(1).FFTSize;
                sample_rate = specRX.GetSpecRX(1).SampleRate;
            }
            else return;

            float bin_width = sample_rate / (float)fft_size;
            float length = (float)Math.Round(sample_rate / bin_width);
            int power2length = Common.FindNextPowerOf2((int)length);
            float milliseconds = (power2length / (float)sample_rate) * 1000f;

            if (rx == 1)
            {
                _fft_fill_timeRX1 = milliseconds;
                Display.RX1FFTFillTime = _fft_fill_timeRX1;
            }
            else
            {
                _fft_fill_timeRX2 = milliseconds;
                Display.RX2FFTFillTime = _fft_fill_timeRX2;
            }
        }

        private void finderMenuItem_Click(object sender, EventArgs e)
        {
            if (_frmFinder == null) return; // InitContonsole creates this
            if (_frmFinder.InvokeRequired)
            {
                _frmFinder.Invoke(new MethodInvoker(() =>
                {
                    _frmFinder.TopMost = true;
                    _frmFinder.Show();
                }));
            }
            else
            {
                _frmFinder.TopMost = true;
                _frmFinder.Show();
            }
        }

        private void setupCMasioStatusBar()
        {
            int state = cmaster.GetCMAstate();

            switch (state)
            {
                case 0:
                    // not in use
                    toolStripStatusLabel_CMstatus.Visible = false;
                    break;
                case 1:
                    // in use, all ok
                    toolStripStatusLabel_CMstatus.Image = Properties.Resources.cm_green;
                    toolStripStatusLabel_CMstatus.ToolTipText = "CM ASIO is in use. The driver being used will not be available to VAC.\n" +
                                                                "Also, speaker/microphone jacks on the radio will be inoperable.";
                    toolStripStatusLabel_CMstatus.Visible = true;
                    break;
                default:
                    // otherwise error
                    toolStripStatusLabel_CMstatus.Image = Properties.Resources.cm_red;
                    toolStripStatusLabel_CMstatus.ToolTipText = "Issue starting CM ASIO. Check driver name in registry.";
                    toolStripStatusLabel_CMstatus.Visible = true;
                    break;
            }
        }

        private void setupSerialCatStatusBar()
        {
            if (IsSetupFormNull) return;

            int[] catState = SetupForm.SerialCatState();

            // check if anything in use
            int nTot = 0;
            for(int n = 0;n< catState.Length; n++)
                nTot += catState[n];
            if (nTot == 0)
            {
                toolStripStatusLabel_CatSerial.Visible = false;
                return;
            }
            //

            //replace colours in cat_serial_status image, red, green, blue and black to show state for cat1-4
            Bitmap modifiedImage = new Bitmap(Properties.Resources.cat_serial_status);

            for (int x = 0; x < modifiedImage.Width; x++)
            {
                for (int y = 0; y < modifiedImage.Height; y++)
                {
                    Color pixelColor = modifiedImage.GetPixel(x, y);

                    if (pixelColor.A == 255 && pixelColor.R == 255 && pixelColor.G == 0 && pixelColor.B == 0) // Check for red  cat 1
                    {
                        Color c = catState[0] == 0 ? Color.Transparent : catState[0] == 1 ? Color.FromArgb(255, 255, 0, 0) : Color.FromArgb(255, 0, 255, 0);
                        modifiedImage.SetPixel(x, y, c);
                    }
                    else if (pixelColor.A == 255 && pixelColor.R == 0 && pixelColor.G == 255 && pixelColor.B == 0) // Check for green  cat 2
                    {
                        Color c = catState[1] == 0 ? Color.Transparent : catState[1] == 1 ? Color.FromArgb(255, 255, 0, 0) : Color.FromArgb(255, 0, 255, 0);
                        modifiedImage.SetPixel(x, y, c);
                    }
                    else if (pixelColor.A == 255 && pixelColor.R == 0 && pixelColor.G == 0 && pixelColor.B == 255) // Check for blue  cat 3
                    {
                        Color c = catState[2] == 0 ? Color.Transparent : catState[2] == 1 ? Color.FromArgb(255, 255, 0, 0) : Color.FromArgb(255, 0, 255, 0);
                        modifiedImage.SetPixel(x, y, c);
                    }
                    else if (pixelColor.A == 255 && pixelColor.R == 0 && pixelColor.G == 0 && pixelColor.B == 0) // Check for black  cat 4
                    {
                        Color c = catState[3] == 0 ? Color.Transparent : catState[3] == 1 ? Color.FromArgb(255, 255, 0, 0) : Color.FromArgb(255,0,255,0);
                        modifiedImage.SetPixel(x, y, c);
                    }
                }
            }

            string sToolTip = "Serial : ";
            for (int n = 0; n < catState.Length; n++)
            {
                if (catState[n] == 1)
                {
                    sToolTip += $"CAT{n+1} disabled, ";
                }
                else if (catState[n] == 2)
                {
                    sToolTip += $"CAT{n+1} enabled, ";
                }
            }

            if (sToolTip.Right(2) == ", ") sToolTip = sToolTip.Left(sToolTip.Length - 2);

            toolStripStatusLabel_CatSerial.Image = modifiedImage;
            toolStripStatusLabel_CatSerial.ToolTipText = sToolTip;
            toolStripStatusLabel_CatSerial.Visible = true;
        }
        public void UpdateStatusBarStatusIcons(StatusBarIconGroup iconGroup)
        {
            // 0 = all

            if(iconGroup == StatusBarIconGroup.All || iconGroup == StatusBarIconGroup.CMAsio) //cmasio
                setupCMasioStatusBar();

            if(iconGroup == StatusBarIconGroup.All || iconGroup == StatusBarIconGroup.N1MM) //n1mm
                toolStripStatusLabel_N1MM.Visible = N1MM.IsStarted && (N1MM.IsEnabled(1) || N1MM.IsEnabled(2));

            if (iconGroup == StatusBarIconGroup.All || iconGroup == StatusBarIconGroup.TCPIPCat) //tcp/ip cat
                toolStripStatusLabel_CatTCPip.Visible = m_tcpCATServer != null ? m_tcpCATServer.IsServerRunning : false;

            if (iconGroup == StatusBarIconGroup.All || iconGroup == StatusBarIconGroup.SerialCat) //serial cat
                setupSerialCatStatusBar();

            if (iconGroup == StatusBarIconGroup.All || iconGroup == StatusBarIconGroup.TCI) //tci
                toolStripStatusLabel_TCI.Visible = m_tcpTCIServer != null ? m_tcpTCIServer.IsServerRunning : false;
        }

        private bool m_bAutoPowerOn = false;
        public bool AutoPowerOn
        {
            get { return m_bAutoPowerOn; }
            set { m_bAutoPowerOn = value; }
        }

        private ToolTip m_statusBarToolTip = null;
        private void addStatusStripToolTipHandlers()
        {
            toolStripStatusLabel_CMstatus.MouseHover += toolTipItemMouseHover;
            toolStripStatusLabel_N1MM.MouseHover += toolTipItemMouseHover;
            toolStripStatusLabel_CatTCPip.MouseHover += toolTipItemMouseHover;
            toolStripStatusLabel_CatSerial.MouseHover += toolTipItemMouseHover;
            toolStripStatusLabel_TCI.MouseHover += toolTipItemMouseHover;

            toolStripStatusLabel_CMstatus.MouseLeave += toolTipItemMouseLeave;
            toolStripStatusLabel_N1MM.MouseLeave += toolTipItemMouseLeave;
            toolStripStatusLabel_CatTCPip.MouseLeave += toolTipItemMouseLeave;
            toolStripStatusLabel_CatSerial.MouseLeave += toolTipItemMouseLeave;
            toolStripStatusLabel_TCI.MouseLeave += toolTipItemMouseLeave;
        }

        private void toolTipItemMouseHover(object sender, EventArgs e)
        {
            if (m_statusBarToolTip != null)
            {
                // nuke it, seemed to be the only reliable way of getting them to .show
                m_statusBarToolTip.Hide(statusStripMain);
                m_statusBarToolTip.Dispose();
                m_statusBarToolTip = null;
            }
                
            string sToolTip;
            int x;
            if (sender is ToolStripDropDownButton tsddb)
            {
                sToolTip = tsddb.ToolTipText;
                x = tsddb.Bounds.X;
            }
            else if (sender is ToolStripStatusLabel tssl)
            {
                sToolTip = tssl.ToolTipText;
                x = tssl.Bounds.X;
            }
            else return;

            if (string.IsNullOrEmpty(sToolTip)) return;

            Point pt = new Point(x, statusStripMain.Height * 2);

            // a new one every time
            m_statusBarToolTip = new ToolTip();              
            m_statusBarToolTip.Show(sToolTip, statusStripMain, pt);
        }
        private void toolTipItemMouseLeave(object sender, EventArgs e)
        {
            if (m_statusBarToolTip != null)
                m_statusBarToolTip.Hide(statusStripMain);
        }

        //wd5y
        private void chkMNU_CheckedChanged(object sender, EventArgs e)
        {
            if (chkMNU.Checked)
            {
                menuStrip1.Hide();
            }
            else
            {
                menuStrip1.Show();
            }
        }
        //wd5y

        #region -help text
        [DllImport("kernel32.dll")]
        private static extern bool AttachConsole(int dwProcessId);
        //[DllImport("kernel32.dll")]
        //private static extern bool AllocConsole();
        [DllImport("kernel32.dll")]
        private static extern bool FreeConsole();
        //[DllImport("kernel32.dll")]
        //private static extern IntPtr GetConsoleWindow();
        //[DllImport("kernel32.dll")]
        //private static extern bool GenerateConsoleCtrlEvent(int dwCtrlEvent, int dwProcessGroupId);
        //[DllImport("user32.dll")]
        //private static extern int SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

        //private const int WM_KEYDOWN = 0x0100;
        //private const int WM_KEYUP = 0x0101;
        //private const int WM_CHAR = 0x0102;
        //private const int VK_ENTER = 0x0D;
        private const int ATTACH_PARENT_PROCESS = -1;

        private void showHelpInfo()
        {
            //from https://community.apache-labs.com/viewtopic.php?f=9&t=4047

            bool bOk = AttachConsole(ATTACH_PARENT_PROCESS);

            if (bOk)
            {
                string s = "\nThetis command line help :\n\n";

                s += "  -help   this help\n";
                s += "  -logshutdown    generate shutdown_log.txt when closing down\n";
                s += "  -autostart      attempt to power on radio at start up\n\n";

                s += "  -datapath:c:\\thetisdatafolder\\    use this data folder for everything\n";
                s += "  -datapath:c:\\thetisdatafolder\\ -autostart     as above, with autostart\n";
                s += "  \"-datapath:c:\\test with spaces\\\"   use this data folder for everything, but with spaces in the path\n";
                s += "  \"-datapath:c:\\test with spaces\\\" -autostart   as above, with autostart\n\n";

                s += "  -dbid:xyz    keep the active database unique to the install run via this shortcut\n";
                s += "  -dbid:HL2    another example to keep the active database unique to the install run via this shortcut\n";
                s += "  -dbid:G2    another example to keep the active database unique to the install run via this shortcut\n";
                s += "  -cmasioconfig    show the cmASIO setup tab in audio setup\n\n\n";
                s += "  Press Enter...";
                //s += "  -dbfilename:c:\\folder\\database.xml    use this database instead\n";
                //s += "  \"-dbfilename:c:\\folder\\database.xml\"    use this database instead, but with spaces in the path\n";

                //System.Console.Write(s);
                using (Stream st = System.Console.OpenStandardOutput())
                {
                    StreamWriter sw = new StreamWriter(st);
                    sw.AutoFlush = true;
                    sw.Write(s);
                    sw.Close();
                }

                //the following does not seem to work, needs investigating.
                //cw does obtain the attached console window, tested with beep
                //unsure how to resolve this atm

                //// hack to fix problem where enter needs to be hit to return cmd prompt
                //IntPtr cw = GetConsoleWindow();
                //if (cw != IntPtr.Zero)
                //{
                //    SendMessage(cw, WM_KEYDOWN, (IntPtr)VK_ENTER, IntPtr.Zero);
                //    SendMessage(cw, WM_KEYUP, (IntPtr)VK_ENTER, IntPtr.Zero);
                //    SendMessage(cw, WM_CHAR, (IntPtr)VK_ENTER, IntPtr.Zero);
                //}

                FreeConsole();
            }
        }
        #endregion

        #region StepAttenuator data
        //[2.10.3.6]MW0LGE moved all this to functions to make it easier to diagnose issues
        private int getRX1stepAttenuatorForBand(Band b)
        {
            if (b <= Band.FIRST || b >= Band.LAST) return 0;
            int nAtt = rx1_step_attenuator_by_band[(int)b];
            //Debug.Print("getRX1StepAttForBand " + b.ToString() + " " + nAtt.ToString());
            return nAtt;
        }
        private void setRX1stepAttenuatorForBand(Band b, int att)
        {
            if (b <= Band.FIRST || b >= Band.LAST) return;
            //Debug.Print("setRX1StepAttForBand " + b.ToString() + " " + att.ToString());
            rx1_step_attenuator_by_band[(int)b] = att;
        }
        private int getRX2stepAttenuatorForBand(Band b)
        {
            if (b <= Band.FIRST || b >= Band.LAST) return 0;
            int nAtt = rx2_step_attenuator_by_band[(int)b];
            //Debug.Print("getRX2StepAttForBand " + b.ToString() + " " + nAtt.ToString());
            return nAtt;
        }
        private void setRX2stepAttenuatorForBand(Band b, int att)
        {
            if (b <= Band.FIRST || b >= Band.LAST) return;
            //Debug.Print("setRX2StepAttForBand " + b.ToString() + " " + att.ToString());
            rx2_step_attenuator_by_band[(int)b] = att;
        }
        private int getTXstepAttenuatorForBand(Band b)
        {
            if (b <= Band.FIRST || b >= Band.LAST) return 31;
            int nAtt = tx_step_attenuator_by_band[(int)b];
            //Debug.Print("getTXStepAttForBand " + b.ToString() + " " + nAtt.ToString());
            return nAtt;
        }
        private void setTXstepAttenuatorForBand(Band b, int att)
        {
            if (b <= Band.FIRST || b >= Band.LAST) return;
            //Debug.Print("setTXStepAttForBand " + b.ToString() + " " + att.ToString());
            tx_step_attenuator_by_band[(int)b] = att;
        }
        #endregion

        private void udTXStepAttData_ValueChanged(object sender, EventArgs e)
        {
            //always update it
            SetupForm.ATTOnTX = (int)udTXStepAttData.Value;            
            UpdateRX1DisplayOffsets();
            UpdateRX2DisplayOffsets();
        }

        private double _s9Frequency = 30.0;
        public double S9Frequency //[2.10.3.6]MW0LGE implements #418
        {
            get { return _s9Frequency; }
            set {
                _s9Frequency = value;
                MeterManager.UpdateS9();
            }
        }
        #region AutoStartCode
        //autostart_code
        //https://github.com/ramdor/Thetis/issues/286
        //store all this in a dictionary, much easier
        private Dictionary<string, bool> _auto_start_form_settings = new Dictionary<string, bool>();
        public void SetAutoFormStartSetting(string form, bool show)
        {
            string lowForm = form.ToLower();
            if(!_auto_start_form_settings.ContainsKey(lowForm))
            {
                _auto_start_form_settings.Add(lowForm, show);
            }
            else
            {
                _auto_start_form_settings[lowForm] = show;
            }
        }
        public bool GetAutoFormStartSetting(string form)
        {
            bool bRet;
            string lowForm = form.ToLower();
            if (_auto_start_form_settings.ContainsKey(lowForm))
            {
                bRet = _auto_start_form_settings[lowForm];
            }
            else
            {
                bRet = false;
            }
            return bRet;
        }
        private string getAutoStartData()
        {
            string sTmp = "";
            foreach (KeyValuePair<string, bool> kvp in _auto_start_form_settings)
            {
                string sKey = kvp.Key;
                bool bVal = kvp.Value;

                sTmp += sKey + "|" + bVal.ToString().ToLower() + "|";
            }
            if (sTmp.EndsWith("|")) sTmp = sTmp.Substring(0, sTmp.Length - 1);
            return sTmp.ToLower();
        }
        private void setAutoStartData(string data)
        {
            string[] sSplit = (data.ToLower()).Split('|');
            if (sSplit.Length % 2 != 0) return;

            //they are in pairs
            for (int i = 0; i < sSplit.Length; i += 2)
            {
                string sForm = sSplit[i];
                //bool bVal = bool.Parse(sSplit[i + 1]);
                bool ok = bool.TryParse(sSplit[i + 1], out bool bVal);
                if(ok)
                    SetAutoFormStartSetting(sForm, bVal);
            }
            if (!IsSetupFormNull) SetupForm.UpdateAutoStartForms();
        }
        Dictionary<string, bool> _autoFormLoadingDuplicate = new Dictionary<string, bool>();
        private System.Windows.Forms.Timer _autoLoadFormTimerFormTimer; // need timer for UI thread issues
        private void handleShowOnStartWindowsForms()
        {
            _autoFormLoadingDuplicate.Clear();
            foreach(KeyValuePair<string, bool> kvp in _auto_start_form_settings)
            {
                _autoFormLoadingDuplicate.Add(kvp.Key, kvp.Value);
            }
            if (_autoFormLoadingDuplicate.Count > 0)
            {
                _autoLoadFormTimerFormTimer = new System.Windows.Forms.Timer();
                _autoLoadFormTimerFormTimer.Tick += new EventHandler(OnOpenWindowsFormsTimerEvent);
                _autoLoadFormTimerFormTimer.Interval = 250;
                _autoLoadFormTimerFormTimer.Start();
            }
        }
        private void OnOpenWindowsFormsTimerEvent(Object source, EventArgs e)
        {
            //slowly open each window, every 250ms
            _autoLoadFormTimerFormTimer.Stop();
            if (_autoFormLoadingDuplicate.Count == 0) return;
            KeyValuePair<string, bool> kvp = _autoFormLoadingDuplicate.First();
            string form = kvp.Key;
            bool show = kvp.Value;
            _autoFormLoadingDuplicate.Remove(form);
            if(show) showOnStartup(form);
            if (_autoFormLoadingDuplicate.Count > 0)
                _autoLoadFormTimerFormTimer.Start();
        }
        private void showOnStartup(string form)
        {
            EventArgs e = EventArgs.Empty;

            switch (form)
            {
                case "setup": /*setupToolStripMenuItem_Click(this, e);*/ setupToolStripMenuItem1_Click(this, EventArgs.Empty); break;
                case "memory": memoryToolStripMenuItem_Click(this, e); break;
                case "wave": waveToolStripMenuItem_Click(this, e); break;
                case "equaliser": equalizerToolStripMenuItem_Click(this, e); break;
                case "xvtr": xVTRsToolStripMenuItem_Click(this, e); break;
                case "cwx": cWXToolStripMenuItem_Click(this, e); break;
                case "linearity":
                    if (psform != null)
                    {
                        if (psform.InvokeRequired)
                        {
                            psform.Invoke(new MethodInvoker(() =>
                            {
                                psform.ShowAtStartup_LinearityForm();
                            }));
                        }
                        else
                        {
                            psform.ShowAtStartup_LinearityForm();
                        }
                    }
                    break;
                case "ampview":
                    if (psform != null)
                    {
                        if (psform.InvokeRequired)
                        {
                            psform.Invoke(new MethodInvoker(() =>
                            {
                                psform.ShowAtStartup_AmpViewForm();
                            }));
                        }
                        else
                        {
                            psform.ShowAtStartup_AmpViewForm();
                        }
                    }
                    break;
                case "diversity": eSCToolStripMenuItem_Click(this, e); break;
                case "spot": spotterMenu_Click(this, e); break;
                case "ra": RAtoolStripMenuItem_Click(this, e); break;
                case "wb": wBToolStripMenuItem_Click(this, e); break;
                case "finder": finderMenuItem_Click(this, e); break;
                case "bandstack": lblBandStack_Click(this, e); break;
            }
        }
        private List<Process> _started_processes = new List<Process>();
        private void handleLaunchOnStartUp()
        {
            if (IsSetupFormNull) return;
            string[] files = SetupForm.GetAutoLaunchFiles();
            foreach (string file in files)
            {
                string lower = file.ToLower();
                int extensionPosExe = lower.IndexOf(".exe");
                int extensionPosCmd = lower.IndexOf(".cmd");
                int extensionPosBat = lower.IndexOf(".bat");
                int[] positions = { extensionPosExe, extensionPosCmd, extensionPosBat };
                int extensionPos = int.MaxValue;
                foreach (int pos in positions)
                {
                    if (pos != -1 && pos < extensionPos)
                    {
                        extensionPos = pos;
                    }
                }

                if (extensionPos != int.MaxValue)
                {
                    string arguments = file.Substring(extensionPos + 4).Trim();
                    string fileOnly = file.Substring(0, extensionPos + 4).Trim();
                    if (File.Exists(fileOnly))
                    {
                        try
                        {
                            string processName = Path.GetFileNameWithoutExtension(fileOnly);
                            if (!SetupForm.AutoLaunchNoStartIfRunning || (SetupForm.AutoLaunchNoStartIfRunning && !IsProcessRunning(processName)))
                            {
                                string extension = Path.GetExtension(fileOnly).ToLower();
                                if (extension == ".exe" || extension == ".cmd" || extension == ".bat")
                                {
                                    ProcessWindowStyle pws = extension == ".exe" ? ProcessWindowStyle.Normal : ProcessWindowStyle.Hidden;
                                    ProcessStartInfo startInfo = new ProcessStartInfo(fileOnly)
                                    {
                                        //LoadUserProfile = true,
                                        WindowStyle = pws,
                                        UseShellExecute = true,
                                        CreateNoWindow = true,
                                        Arguments = arguments,
                                        WorkingDirectory = Path.GetDirectoryName(fileOnly)                                        
                                    };

                                    Process p = Process.Start(startInfo);                                    
                                    //if(!p.HasExited) 
                                        _started_processes.Add(p);
                                }
                            }
                        }
                        catch
                        { }
                    }
                }
            }
        }

        private bool IsProcessRunning(string processName)
        {
            return Process.GetProcessesByName(processName).Length > 0;
        }
        private static List<IntPtr> FindAllWindowHandlesByProcessId(int processId)
        {
            List<IntPtr> handles = new List<IntPtr>();
            EnumWindows((hWnd, lParam) =>
            {
                GetWindowThreadProcessId(hWnd, out uint windowProcessId);
                if (windowProcessId == processId)
                    handles.Add(hWnd);
                return true;
            }, IntPtr.Zero);
            return handles;
        }

        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
        [DllImport("user32.dll", SetLastError = true)]
        private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
        [DllImport("user32.dll")]
        private static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        private const int WM_CLOSE = 0x0010;
        private const int WM_QUIT = 0x0012;
        private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);

        private void autoLaunchTryToClose()
        {
            if (IsSetupFormNull) return;
            if (!SetupForm.AutoLaunchTryToClose) return;

            //commented if(!p.HasExited) as not sure state is 100% accurate. Try/catch will handle any issue
            foreach (Process p in _started_processes)
            {
                try
                {
                    PostMessage(p.MainWindowHandle, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);                    
                }
                catch
                {
                }
            }
            if (_started_processes.Count > 0) Thread.Sleep(50);
            foreach (Process p in _started_processes)
            {
                try
                {
                    PostMessage(p.MainWindowHandle, WM_QUIT, IntPtr.Zero, IntPtr.Zero);
                }
                catch
                {
                }
            }
            if (_started_processes.Count > 0) Thread.Sleep(50);

            foreach (Process p in _started_processes)
            {
                try
                {
                    List<IntPtr> handles = FindAllWindowHandlesByProcessId(p.Id);
                    foreach (IntPtr handle in handles)
                    {
                        try
                        {
                            PostMessage(handle, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
                        }
                        catch { }
                    }
                }
                catch
                {
                }
            }
            if (_started_processes.Count > 0) Thread.Sleep(50);
            foreach (Process p in _started_processes)
            {
                try
                {
                    List<IntPtr> handles = FindAllWindowHandlesByProcessId(p.Id);
                    foreach (IntPtr handle in handles)
                    {
                        try
                        {
                            PostMessage(handle, WM_QUIT, IntPtr.Zero, IntPtr.Zero);
                        }
                        catch { }
                    }
                }
                catch
                {
                }
            }
            if (_started_processes.Count > 0) Thread.Sleep(50);
            foreach (Process p in _started_processes)
            {
                try
                {
                    p.CloseMainWindow();
                }
                catch
                {
                }
            }
            if (_started_processes.Count > 0) Thread.Sleep(50);
            foreach (Process p in _started_processes)
            {
                try
                {
                    p.Close();
                }
                catch
                {
                }
                finally
                {
                    try
                    {
                        p.Dispose();
                    }
                    catch { }
                }
            }
        }
        //
        #endregion

        private void databaseManagerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (IsSetupFormNull) return;
            DBMan.ShowDBMan();
        }

        private void setupToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (IsSetupFormNull) return;            
            if (SetupForm.InvokeRequired)
            {
                SetupForm.Invoke(new MethodInvoker(() =>
                {
                    SetupForm.Show();
                    SetupForm.Focus();
                    SetFocusMaster(false);
                }));
            }
            else
            {
                SetupForm.Show();
                SetupForm.Focus();
                SetFocusMaster(false);
            }
        }

        public void ToggleRxTxAnt()
        {
            chkRxAnt.Checked = !chkRxAnt.Checked;
        }
        public void PopupFilterContextMenu(int rx, MouseEventArgs e)
        {
            if (rx == 1)
                contextMenuStripFilterRX1.Show(MousePosition);
            else if(rx == 2)
                contextMenuStripFilterRX2.Show(MousePosition);
        }
        public void PopupBandstack(int rx, Band b, bool is_on_top)
        {
            if (rx == 2) return;  // no bandstack for rx2 yet

            // used by multimeters
            BandStackFilter bsf = BandStackManager.GetFilter(b);

            if (bsf != null)
            {
                BandStack2Form.InitBandStackFilter(bsf, true);
            }

            BandStack2Form.Show(true, MousePosition, is_on_top);
        }
        private void showBandStack()
        {
            // for console to use, so that we will always use rx1 band the stack for vfoa band
            BandStackFilter bsf = BandStackManager.GetFilter(RX1Band);

            if (bsf != null)
            {
                BandStack2Form.InitBandStackFilter(bsf, true);
                updateStackNumberDisplay(bsf);
            }

            if (InvokeRequired)
            {
                Invoke(new MethodInvoker(() =>
                {
                    btnHidden.Focus();
                    BandStack2Form.Show();
                }));
            }
            else
            {
                btnHidden.Focus();
                BandStack2Form.Show();
            }
        }

        private void miAbout_Click(object sender, EventArgs e)
        {
            if (IsSetupFormNull) return;

            string sFW;
            string sProto;
            string sModel;
            string sSupportedProtocol;

            if (NetworkIO.getHaveSync() == 1)
            {
                sModel = current_hpsdr_model.ToString();

                if (NetworkIO.CurrentRadioProtocol == RadioProtocol.ETH)
                {
                    sFW = NetworkIO.FWCodeVersion.ToString("0\\.0") + "." + NetworkIO.BetaVersion.ToString();
                    sProto = "2";
                    sSupportedProtocol = NetworkIO.ProtocolSupported.ToString("0\\.0");
                }
                else
                {
                    sFW = NetworkIO.FWCodeVersion.ToString("0\\.0");
                    sProto = "1";
                    sSupportedProtocol = "";
                }
            }
            else
            {
                sFW = "? (not connected)";
                sProto = "? (not connected)";
                sSupportedProtocol = "";
                sModel = current_hpsdr_model.ToString() + " (not connected)";
            }

            string version = Common.GetVerNum(true, false);

            int nPAVersion = PA19.PA_GetVersion();
            int major = (nPAVersion >> 16) & 0xFF;
            int minor = (nPAVersion >> 8) & 0xFF;
            int subminor = nPAVersion & 0xFF;
            nPAVersion = major * 100 + minor * 10 + subminor;
            string sPortAudio = major.ToString() + "." + minor.ToString() + "." + subminor.ToString();

            string sOriginalAndromG2Verson = SetupForm.AndromedaVersionNumber;
            string sAndromG2Verson = sOriginalAndromG2Verson;
            sAndromG2Verson = sAndromG2Verson.Replace("Andromeda: ", "");
            sAndromG2Verson = sAndromG2Verson.Replace("G2 panel: ", "");
            sAndromG2Verson = sAndromG2Verson.Replace("h/w=", "h=");
            sAndromG2Verson = sAndromG2Verson.Replace("  s/w=", " s=");
            if (!string.IsNullOrEmpty(sAndromG2Verson))
            {
                sAndromG2Verson = sOriginalAndromG2Verson.Contains("G2") ? "G2 Panel Version: " + sAndromG2Verson : "Andromeda Panel Version: " + sAndromG2Verson;
            }

            int dx_version = Display.DXVersion();
            string sdxversion;
            if (dx_version != -1)
                sdxversion = (dx_version / 10f).ToString("f1");
            else
                sdxversion = "";

            _frmAbout.InitVersions(version, TitleBar.BUILD_NAME, DB.VersionNumber.ToString(), sdxversion, sModel, sFW, sProto, sSupportedProtocol,
                    (WDSP.GetWDSPVersion() / 100f).ToString("f2"), (cmaster.GetCMVersion() / 1000f).ToString("f2"),
                    (cmaster.GetCMasioVersion() / 1000f).ToString("f2"), sPortAudio, sAndromG2Verson);

            _frmAbout.ShowDialog(this);
        }

        private Image _cached_background_image = null;
        private Size _background_image_size = Size.Empty;
        public Image CachedBackgroundImage
        {
            get { return _cached_background_image; }
            set
            {
                // no dispose here as we dont want to free up the cache in skins
                _cached_background_image = value;
                _background_image_size = Size.Empty;
                resizeBackgroundImage();
            }
        }
        private void resizeBackgroundImage()
        {
            // fixes issue where if the background image skin is larger than the client size of the window
            // then there would be very slow redraw/updates. So instead of the form resizing it, we do it ourseves                
            if (this.ClientSize == _background_image_size) return;
            if (this.ClientSize.Width == 0 || this.ClientSize.Height == 0) return;

            Graphics graphics = null;
            _background_image_size = this.ClientSize;

            if (this.BackgroundImage != null)
            {
                this.BackgroundImage.Dispose();
                this.BackgroundImage = null;
            }

            if (_cached_background_image == null) return;
            try
            {
                Image resized_image = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);

                graphics = Graphics.FromImage(resized_image);
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.DrawImage(_cached_background_image, 0, 0, resized_image.Width, resized_image.Height);

                this.BackgroundImageLayout = ImageLayout.None;
                this.BackgroundImage = resized_image;
            }
            catch (Exception e)
            {
                if (this.BackgroundImage == null)
                {
                    // issue resizing it, just use the original and turn on stretch mode
                    this.BackgroundImageLayout = ImageLayout.Stretch;
                    this.BackgroundImage = _cached_background_image;
                }
            }
            finally
            {
                if (graphics != null) graphics.Dispose();
            }
        }

        private void setupToolStripMenuItem_MouseUp(object sender, MouseEventArgs e)
        {
            //[2.10.3.6]MW0LGE now in submenu, however do this if shift held,
            //because so many people moan about 1 more mouse click
            if (Common.ShiftKeyDown)
            {
                if (IsSetupFormNull) return;
                if (SetupForm.InvokeRequired)
                {
                    SetupForm.Invoke(new MethodInvoker(() =>
                    {
                        SetupForm.Show();
                        SetupForm.Focus();
                        SetFocusMaster(false);
                    }));
                }
                else
                {
                    SetupForm.Show();
                    SetupForm.Focus();
                    SetFocusMaster(false);
                }
            }
            else if (!setupToolStripMenuItem.DropDown.Visible) setupToolStripMenuItem.ShowDropDown();
            //[2.10.3.7]MW0LGE show dropdown above fixes issue where the popup does not show if the window
            //does not have focus and setup is clicked. Note, also needs to be in MouseUp
        }
        //wd5y
        private void TopControlstoolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetupForm.chkShowAndromedaTop.Checked = !SetupForm.chkShowAndromedaTop.Checked;
        }

        private void bandToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetupForm.chkShowBandControls.Checked = !SetupForm.chkShowBandControls.Checked;
        }

        private void modeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetupForm.chkShowModeControls.Checked = !SetupForm.chkShowModeControls.Checked;
        }
        
        private void BtnBartoolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetupForm.chkShowAndromedaBar.Checked = !SetupForm.chkShowAndromedaBar.Checked;
        }

        private void RXTXGainToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (sliderForm == null || sliderForm.IsDisposed) sliderForm = new SliderSettingsForm(this);
            Skin.Restore(CurrentSkin, AppDataPath, sliderForm);
            Invoke(new MethodInvoker(sliderForm.Show));
        }
        //wd5y
    }

    public class DigiMode
    {
        public DigiMode()
        {

        }
        public enum DigiModeSettingState
        {
            dmssTurnOffSettings = 0,
            dmssStore,
            dmssRecall
        }

        public bool DEXP { get; set; }
        public bool TXEQ { get; set; }
        public bool LEVELER { get; set; }
        public bool COMPRESSOR { get; set; }
        public bool RXEQ { get; set; }
        public bool ANF { get; set; }
        public bool CESSB { get; set; }
        public CheckState NR { get; set; }
        public bool CFCEnabled { get; set; }
        public bool PhaseRotEnabled { get; set; }
        public DigiModeSettingState Mode { get; set; }
    }

    public class AsyncLock : IDisposable
    {
        private SemaphoreSlim _semaphoreSlim = new SemaphoreSlim(1, 1);

        public async Task<AsyncLock> LockAsync()
        {
            await _semaphoreSlim.WaitAsync();
            return this;
        }

        public void Dispose()
        {
            _semaphoreSlim.Release();
        }
    }
}
