/*
 * Copyright (C) 2013 Thomas M. Alldread
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package va7ta.app.nimblesigsweepgen;



import va7ta.app.nimblesigsweepgen.R;
import android.app.ActionBar;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

	public class SweepControl extends Activity {
	    private static final String TAG = "SweepControl";
	    private static final boolean D = true;// false true

	    public final int BT_NEW_RX_DATA_ATTACHED=1;
		protected SweepDraw drawView;
		
		//global variables
		protected int g_displayX=100;
		protected int g_displayY=100;
		protected int g_yPxSpan=444;
		protected int g_xPxSpan=1006;
		protected int g_yPxTopMargin=100;
		protected int g_xPxLeftMargin=100;		
    	private int g_xAxisPxSteps[]= new int[2048];
    	private int g_xAxisFrqSteps[]= new int[2048];
    	private int g_stepPwrCalibration[]= new int[2048];
    	private int g_NextSweepStep=0;
    	private int g_swallowReplies = 2;

    	private float g_NormalizeValues[]=new float[2048];
		
	    private boolean g_LevelPending_b=false;
	    private boolean g_NewLvlReady_b=false;
	    private boolean g_LevelDataProcessed_b=false;
	    private boolean g_NormalizeCalCycle_b=false;
	    private boolean g_NormalizeReady_b=false;
	    private boolean g_sweepReStart_b = false;
	    private boolean g_reStartPending_b = false;
	    private boolean g_SwallowEnabled_b=false;


		// Action BAR constants
		protected final int MEASURE_RF_LEVEL = 1;
		protected final int SET_CENTER_FREQ = 2;
		protected final int SET_SWEEP_SPANWIDTH = 3;
		
	    // Name of the bluetooth connected device
	    protected String mConnectedDeviceName = null;
	    // Array adapter for the conversation thread
	    protected ArrayAdapter<String> mConversationArrayAdapter;
	    // Local Bluetooth adapter
	    protected BluetoothAdapter mBluetoothAdapter = null;
	    // Member object for the chat services
//	    private int nsigApp.g_BT_RXD_BfrPtr = 0;//sync relationship with BluetoothChatService.bfr2InPtr
	    private int g_ReplyStkPtr = 0;
	    protected String[] g_ReplyStackStr={"","","","","","","","","",""}; // 10 string stack
	    private String g_LevelValueStr="";
	    // Message types sent from the BluetoothChatService Handler
	    protected static final int MESSAGE_STATE_CHANGE = 1;
	    protected static final int MESSAGE_READ = 2;
	    protected static final int MESSAGE_WRITE = 3;
	    protected static final int MESSAGE_DEVICE_NAME = 4;
	    protected static final int MESSAGE_TOAST = 5;

	    // Key names received from the BluetoothChatService Handler
	    protected static final String DEVICE_NAME = "device_name";
	    protected static final String TOAST = "toast";

	    // onActivityResults Return Codes
	    private static final int REQUEST_CONNECT_DEVICE_SECURE = 1;
	    private static final int REQUEST_CONNECT_DEVICE_INSECURE = 2;    
	    private static final int REQUEST_ENABLE_BT = 3;
	    private static final int PHASE_OFFSET_UPDATE_GEN_A = 4;
	    private static final int PHASE_OFFSET_UPDATE_GEN_B = 5;
	    private static final int OUTPUT_LEVEL_UPDATE_GEN_A = 6;
	    private static final int OUTPUT_LEVEL_UPDATE_GEN_B = 7;
	    private static final int AM_MOD_INDEX_UPDATE_GEN_A = 8;
	    private static final int AM_MOD_INDEX_UPDATE_GEN_B = 9;
	    private static final int FM_DEV_UPDATE_GEN_A = 10;
	    private static final int FM_DEV_UPDATE_GEN_B = 11;
	    private static final int MOD_FREQ_HZ_UPDATE = 12;
	    private static final int SWEEP_GEN_RESULTS= 13;
	    private static final int SWEEP_GEN_NEW_SETUP= 14;
	    private static final int SWEEP_GEN_SET_CNTR_FREQ_HZ=15;
	 	    
	    @Override
	    public void onCreate(Bundle savedInstanceState) {
	        super.onCreate(savedInstanceState);
	        if(D) Log.e(TAG, "+ ON CREATE +");      
	        // Set full screen view
	        mConnectedDeviceName=NS3_App.mConnectedDeviceName;
	        drawView = new SweepDraw(this);
        	NS3_App.getInstance();
        	NS3_App.gs_SweepGenMode_b = true;
        	NS3_App.spectrumDisplayHandler=mHandler;
//            IntentFilter intentFilter = new IntentFilter();
//            intentFilter.addAction(Intent.ACTION_ATTACH_DATA);
//            registerReceiver(bluetoothReplyRcvr, intentFilter);
        	sweepFreqValsIni(NS3_App.sg_SweepCenterFreqHz, NS3_App.sg_SweepSpanFreqHz);

	        WindowManager.LayoutParams params = getWindow().getAttributes();	        
	        params.height = WindowManager.LayoutParams.FLAG_FULLSCREEN;
	        params.width = WindowManager.LayoutParams.FLAG_FULLSCREEN;
	        getWindow().setAttributes((android.view.WindowManager.LayoutParams) params);	        

	           params.x = 0;  
	           params.y = 0;  
	           params.height = 700;  
	           params.width = 1200; 
	           restoreSweepSetup();
 
	              
//	        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
//	                                         WindowManager.LayoutParams.FLAG_FULLSCREEN);
//	        requestWindowFeature(Window.FEATURE_ACTION_BAR);

	        drawView = new SweepDraw(this);
//		    setContentView(R.layout.activity_spectrum_display);     

	        setContentView(drawView);
	        drawView.requestFocus();
	        drawView.bringToFront();
	        drawView.setEnabled(true);
	        drawView.setBackgroundColor(0xFFFFFFFF);

	    }// End onCreate
	    
	    @Override
	    protected void onResume(){
	    	super.onResume();
	        if(D) Log.e(TAG, "+ ON RESUME +");      
        	NS3_App.gs_SweepGenMode_b = true;
        	restoreSweepSetup();
	    }
	     
	    @Override
	    protected void onPause(){
	        super.onPause();
	        saveSweepSetup();
	        NS3_App.sg_SweepActivated = false;
	        if(D) Log.e(TAG, "+ ON PAUSE +"); 
	    }

	    @Override
	    protected void onStop(){
	        super.onStop();
	        if(D) Log.e(TAG, "+ ON STOP +");      
        	NS3_App.sg_SweepActivated=false;
        	NS3_App.gs_SweepGenMode_b = false;
	    }
	    
	    @Override
	    protected void onDestroy() {
	        super.onDestroy();
	        // Stop the Bluetooth chat services
	        if(D) Log.e(TAG, "--- ON DESTROY ---");
	    }//onDestroy ================================================================================

	  //ActionBar Code============================================
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.action_bar_menu_spectrum_display, menu);
            return true;
        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            Intent serverIntent = null;
            switch (item.getItemId()) {
            case R.id.measure_power_item:
/*
            	// display speed test code
            	NS3_App.sg_SweepStartNew=false;
            	int y=100;
            	boolean j=false;
            	for(int x=100;x<1100;x++){
	    	        drawView.drawTrace(x,y);
	    	        if(!j)y +=10;
	    	        if(y>500)j=true;
	    	        if(j) y -= 10;
	    	        if(y<200)j=false;
            	}
            	// END display speed test code
*/            	
            	NS3_App.sg_SweepActivated=true;
            	sendMessage("la50");
                return true;
            case R.id.sweep_setup_item:
            	Intent startSetCenterFreq=new Intent(getApplicationContext(), SweepSetup.class);
            	startSetCenterFreq.putExtra("centerFreqHz",NS3_App.sg_SweepCenterFreqHz);
            	startSetCenterFreq.putExtra("sweepSpanHz",NS3_App.sg_SweepSpanFreqHz);            	
            	startActivityForResult(startSetCenterFreq,SWEEP_GEN_NEW_SETUP);
                return true;
            case R.id.sweep_normalize_item:
            	if(NS3_App.sg_Scale_dB_Div_Int == 10){
	            	g_NormalizeCalCycle_b=true;
	            	NS3_App.sg_NormalizeMode_b=false;
	            	sweepStart();
            	}else{
                    Toast.makeText(this, "Normalize only for 10dB/div mode", Toast.LENGTH_LONG).show();
                   	final ToneGenerator tg = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 100);
                   	tg.startTone(ToneGenerator.TONE_CDMA_CALLDROP_LITE);             		
            	}
                return true;
            case R.id.prev_normalize_item:
            	if(NS3_App.sg_Scale_dB_Div_Int == 10){
	            	NS3_App.sg_NormalizeMode_b=true;
	            	sweepStart();
            	}else{
                    Toast.makeText(this, "Normalize only for 10dB/div mode", Toast.LENGTH_LONG).show();
                   	final ToneGenerator tg = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 100);
                   	tg.startTone(ToneGenerator.TONE_CDMA_CALLDROP_LITE);             		            		
            	}
                return true;
            case R.id.sweep_start_item:
            	NS3_App.sg_NormalizeMode_b=false;
            	/*if(NS3_App.sg_SweepActivated){
            		g_sweepReStart_b=true;
            		g_reStartPending_b=true;
            	}else{
            		NS3_App.sg_refreshScreen=true;
            		sweepStart();
            	}*/
        		sweepStart();//trial statement
                return true;
            case R.id.sweep_stop_item:
            	NS3_App.sg_SweepActivated=false;
            	finish();
                return true;
            case R.id.sweep_refresh_item:
            	NS3_App.sg_refreshScreen=true;
            	g_sweepReStart_b=true;
                return true;
            }
            return false;
        }
        // End ActionBar Code================================
        // SweepGenerater Code================================
        
	    private void sweepFreqValsIni(int centerFreqHz, int spanHz){
	    	NS3_App.sg_SweepCenterFreqHz=centerFreqHz;
	    	NS3_App.sg_SweepCenterFreqHz_Str=spaceDelimiter(NS3_App.sg_SweepCenterFreqHz) + " Hz.";
	    	NS3_App.sg_SweepSpanFreqHz = spanHz;
	    	NS3_App.sg_SweepSpanFreqHz_Str=spaceDelimiter(spanHz) + " Hz.";
	    	NS3_App.sg_SweepStartFreqHz=NS3_App.sg_SweepCenterFreqHz-(NS3_App.sg_SweepSpanFreqHz/2);
	    	NS3_App.sg_SweepStartFreqHz_Str=spaceDelimiter(NS3_App.sg_SweepStartFreqHz) + " Hz.";
	    	NS3_App.sg_SweepStopFreqHz=NS3_App.sg_SweepCenterFreqHz+(NS3_App.sg_SweepSpanFreqHz/2);
	    	NS3_App.sg_SweepStopFreqHz_Str=String.valueOf(NS3_App.sg_SweepStopFreqHz) + " Hz.";
	    	NS3_App.sg_SweepStopFreqHz_Str=spaceDelimiter(NS3_App.sg_SweepStopFreqHz) + " Hz.";
	    	NS3_App.sg_HzPerDiv_Int=NS3_App.sg_SweepSpanFreqHz/10;
	    	NS3_App.sg_HzPerDiv_Int_Str=spaceDelimiter(NS3_App.sg_HzPerDiv_Int) + " Hz.";
	    }
	    
	    // convert int to string and add space delimiters for GUI display
	    private String spaceDelimiter(int freq_Int){
	    	String freqDelimited_Str = String.valueOf(freq_Int);
	        char tempChr[]=freqDelimited_Str.toCharArray();
	        int l=freqDelimited_Str.length();
	        int space1=l-4;
	        int space2=l-7;
	        String tempStr="";
	        for(int i=0;i<l;i++){
	        	tempStr+=String.valueOf(tempChr[i]);
	        	if((i==space1)|(i==space2))tempStr+=' ';
	        }     	
	    	return tempStr;
	    }
	    
	    public void onActivityResult(int requestCode, int resultCode, Intent data) {
	        if(D) Log.d(TAG, "onActivityResult " + resultCode);  
	        switch (requestCode) {
	        case SWEEP_GEN_NEW_SETUP:
	            // When DeviceListActivity returns with a device to connect
	            if (resultCode == Activity.RESULT_OK) {
	    	        saveSweepSetup();
	            	NS3_App.sg_refreshScreen=true;
	            	sweepStart();            		        
	            }
	            break;
	        }
	    }
	    
	    protected void saveSweepSetup(){    	
	        SharedPreferences mSweepPrefs = getPreferences(Context.MODE_PRIVATE);
	        SharedPreferences.Editor editor = mSweepPrefs.edit();
	        editor.putInt("p_SweepCenterFreqHz", NS3_App.sg_SweepCenterFreqHz);
	        editor.putInt("p_SweepSpanFreqHz", NS3_App.sg_SweepSpanFreqHz);
	        editor.putInt("p_SweepStartFreqHz", NS3_App.sg_SweepStartFreqHz);
	        editor.putInt("p_SweepStopFreqHz", NS3_App.sg_SweepStopFreqHz);
	        editor.putInt("p_SweepTime_mS_Int", NS3_App.sg_SweepTime_mS_Int);
	        editor.putInt("p_2dB_DivRefLvl_Int", NS3_App.sg_2dB_DivRefLvl_Int);
	        editor.putInt("p_Yaxis_RefLevel_dBm_Int", NS3_App.sg_Yaxis_RefLevel_dBm_Int);
	        editor.putInt("p_HzPerDiv_Int", NS3_App.sg_HzPerDiv_Int);
	        editor.putInt("p_HzPerStep_Int", NS3_App.sg_HzPerStep_Int);
	        editor.putFloat("p_HzPerPixel_Flt", NS3_App.sg_HzPerPixel_Flt);
	        editor.putFloat("p_dB_PerPixel_Flt", NS3_App.sg_dB_PerPixel_Flt);	        
	        editor.putInt("p_Yaxis_DynamicRange_dB_Int", NS3_App.sg_Yaxis_DynamicRange_dB_Int);
	        editor.putInt("p_Scale_dB_Div_Int", NS3_App.sg_Scale_dB_Div_Int);
	        editor.putInt("p_StepsPerSweep", NS3_App.sg_StepsPerSweep);
	        for (int i = 0; i < NS3_App.sg_StepsPerSweep; i++){
	        	editor.putFloat("p_NormalizeVals"+String.valueOf(i), g_NormalizeValues[i]);
	        }
	        editor.commit();
	        if(D) Log.d(TAG, "saveSweepSetup - SweepGen Settings Saved");                
	    }

	    public void restoreSweepSetup(){ //restore GUI view values
	        SharedPreferences mSweepPrefs = getPreferences(Context.MODE_PRIVATE);
	        NS3_App.sg_SweepCenterFreqHz = mSweepPrefs.getInt("p_SweepCenterFreqHz", 50000000);
	        NS3_App.sg_SweepSpanFreqHz = mSweepPrefs.getInt("p_SweepSpanFreqHz", 20000000);
	        NS3_App.sg_SweepStartFreqHz = mSweepPrefs.getInt("p_SweepStartFreqHz", 40000000);
	        NS3_App.sg_SweepStopFreqHz = mSweepPrefs.getInt("p_SweepStopFreqHz", 60000000);
	        NS3_App.sg_SweepTime_mS_Int = mSweepPrefs.getInt("p_SweepTime_mS_Int", 1);
	        NS3_App.sg_2dB_DivRefLvl_Int = mSweepPrefs.getInt("p_2dB_DivRefLvl_Int", -10);
	        NS3_App.sg_Yaxis_RefLevel_dBm_Int = mSweepPrefs.getInt("p_Yaxis_RefLevel_dBm_Int", 20);
	        NS3_App.sg_HzPerDiv_Int = mSweepPrefs.getInt("p_HzPerDiv_Int", 2000000);
	        NS3_App.sg_HzPerStep_Int = mSweepPrefs.getInt("p_HzPerStep_Int", 40000);
//	        NS3_App.sg_HzPerPixel_Flt  = mSweepPrefs.getFloat("p_HzPerPixel_Flt", (float)1);
//	        NS3_App.sg_dB_PerPixel_Flt  = mSweepPrefs.getFloat("p_dB_PerPixel_Flt", (float)1);
	        NS3_App.sg_Yaxis_DynamicRange_dB_Int =  mSweepPrefs.getInt("p_Yaxis_DynamicRange_dB_Int", 100);
	        NS3_App.sg_Scale_dB_Div_Int = mSweepPrefs.getInt("p_Scale_dB_Div_Int", 10);
	        NS3_App.sg_StepsPerSweep = mSweepPrefs.getInt("p_StepsPerSweep", 200);
	        for (int i = 0; i < NS3_App.sg_StepsPerSweep; i++){
	        	g_NormalizeValues[i]=mSweepPrefs.getFloat("p_NormalizeVals"+String.valueOf(i), -10);
	        }
	        if(NS3_App.sg_Scale_dB_Div_Int !=10)NS3_App.sg_10dB_Div_Yaxis_b=false;
	    }

	    
	    @Override
	    public void onSaveInstanceState(Bundle savedInstanceState){
	    	super.onSaveInstanceState(savedInstanceState);
	        savedInstanceState.putInt("p_sg_SweepCenterFreqHz_Int", NS3_App.sg_SweepCenterFreqHz);        
	        savedInstanceState.putInt("p_sg_SweepSpanFreqHz", NS3_App.sg_SweepSpanFreqHz);        
	        savedInstanceState.putBoolean("p_sg_NormalizeMode_b", NS3_App.sg_NormalizeMode_b);        
	        savedInstanceState.putBoolean("sg_10dB_Div_Yaxis_b", NS3_App.sg_10dB_Div_Yaxis_b);    
	        savedInstanceState.putInt("p_sg_Yaxis_DynamicRange_dB_Int", NS3_App.sg_Yaxis_DynamicRange_dB_Int);        
	        savedInstanceState.putInt("p_sg_Yaxis_RefLevel_dBm_Int", NS3_App.sg_Yaxis_RefLevel_dBm_Int);        
	        savedInstanceState.putInt("p_sg_SweepTime_mS_Int", NS3_App.sg_SweepTime_mS_Int);        
	        savedInstanceState.putInt("p_sg_Scale_dB_Div_Int", NS3_App.sg_Scale_dB_Div_Int);        
	        savedInstanceState.putInt("p_sg_2dB_DivRefLvl_Int", NS3_App.sg_2dB_DivRefLvl_Int);        
	        savedInstanceState.putInt("p_sg_Scale_dB_Div_Int", NS3_App.sg_Scale_dB_Div_Int);        
	        savedInstanceState.putInt("p_sg_HzPerStep_Int", NS3_App.sg_HzPerStep_Int);        
	        savedInstanceState.putInt("p_sg_HzPerDiv_Int", NS3_App.sg_HzPerDiv_Int);        
	        savedInstanceState.putInt("p_sg_StepsPerSweep", NS3_App.sg_StepsPerSweep);        
	        savedInstanceState.putInt("p_sg_SweepStopFreqHz", NS3_App.sg_SweepStopFreqHz);        
	        savedInstanceState.putInt("p_sg_SweepStartFreqHz", NS3_App.sg_SweepStartFreqHz);         
	        savedInstanceState.putString("p_sMeasuredRFLevel_dBm_Str", NS3_App.sMeasuredRFLevel_dBm_Str); 
	        savedInstanceState.putString("p_sg_HzPerDiv_Int_Str", NS3_App.sg_HzPerDiv_Int_Str); 
	        for (int i = 0; i < NS3_App.sg_StepsPerSweep; i++){
	        	savedInstanceState.putFloat("p_NormalizeVals"+String.valueOf(i), g_NormalizeValues[i]);
	        }
	    }
	        
	    @Override
	    public void onRestoreInstanceState(Bundle savedInstanceState){
	        super.onRestoreInstanceState(savedInstanceState);
	        Toast.makeText(this, savedInstanceState .getString("Previous Instance Data Restored"), Toast.LENGTH_LONG).show();	        
		    NS3_App.sg_SweepCenterFreqHz = savedInstanceState.getInt("p_sg_SweepCenterFreqHz_Int");
	    	NS3_App.sg_SweepSpanFreqHz = savedInstanceState.getInt("p_sg_SweepSpanFreqHz");
	    	NS3_App.sg_NormalizeMode_b = savedInstanceState.getBoolean("p_sg_NormalizeMode_b");
	    	NS3_App.sg_10dB_Div_Yaxis_b = savedInstanceState.getBoolean("sg_10dB_Div_Yaxis_b");
	    	NS3_App.sg_Yaxis_DynamicRange_dB_Int = savedInstanceState.getInt("p_sg_Yaxis_DynamicRange_dB_Int");
	    	NS3_App.sg_Yaxis_RefLevel_dBm_Int = savedInstanceState.getInt("p_sg_Yaxis_RefLevel_dBm_Int");
	    	NS3_App.sg_SweepTime_mS_Int = savedInstanceState.getInt("p_sg_SweepTime_mS_Int");
	    	NS3_App.sg_Scale_dB_Div_Int = savedInstanceState.getInt("p_sg_Scale_dB_Div_Int");
	    	NS3_App.sg_2dB_DivRefLvl_Int = savedInstanceState.getInt("p_sg_2dB_DivRefLvl_Int");
	    	NS3_App.sg_Scale_dB_Div_Int = savedInstanceState.getInt("p_sg_Scale_dB_Div_Int");
	    	NS3_App.sg_HzPerStep_Int = savedInstanceState.getInt("p_sg_HzPerStep_Int");
	    	NS3_App.sg_HzPerDiv_Int = savedInstanceState.getInt("p_sg_HzPerDiv_Int");
	    	NS3_App.sg_StepsPerSweep = savedInstanceState.getInt("p_sg_StepsPerSweep");
	    	NS3_App.sg_SweepStopFreqHz = savedInstanceState.getInt("p_sg_SweepStopFreqHz");
	    	NS3_App.sg_SweepStartFreqHz = savedInstanceState.getInt("p_sg_SweepStartFreqHz");
	    	NS3_App.sMeasuredRFLevel_dBm_Str = savedInstanceState.getString("p_sMeasuredRFLevel_dBm_Str");
	    	NS3_App.sg_HzPerDiv_Int_Str = savedInstanceState.getString("p_sg_HzPerDiv_Int_Str");
	        for (int i = 0; i < NS3_App.sg_StepsPerSweep; i++){
	        	g_NormalizeValues[i]=savedInstanceState.getFloat("p_NormalizeVals"+String.valueOf(i), -10);
	        }
	        if(NS3_App.sg_Scale_dB_Div_Int !=10)NS3_App.sg_10dB_Div_Yaxis_b=false;
	    }
	    
	    // End SweepGenerater Code================================

        // bluetooth Link related=============================
        
        public void enableBT(){
		    Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
		    startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
        }

        protected void connectDevice(Intent data, boolean secure) {
            // Get the device MAC address
            String address = data.getExtras()
                .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
            // Get the BluetoothDevice object
            BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
            // Attempt to connect to the device
            NS3_App nsigApp = (NS3_App)getApplication();
            nsigApp.mChatService.connect(device, secure);
        }

        public void ensureDiscoverable() {
            if(D) Log.d(TAG, "ensure discoverable");
            if (mBluetoothAdapter.getScanMode() !=
                BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
                Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
                discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
                startActivity(discoverableIntent);
            }
        }

        public void sendMessage(String message) {
	        if(D) Log.e(TAG, "sendMessage() Entered");              	
            // Check that we're actually connected before trying anything
        	
            NS3_App nsigApp = (NS3_App)getApplication();
        	int chatServiceState = nsigApp.mChatService.getState();
            if (chatServiceState != BluetoothChatService.STATE_CONNECTED) {
                Toast.makeText(this, R.string.not_connected, Toast.LENGTH_LONG).show();
//                blueToothConnectionNeeded();
                return;
            }
	        if(D) Log.e(TAG, "sendMessage() connection confirmed!");              	
            // Check that there's actually something to send
            if (message.length() > 0) {
                // Get the message bytes and tell the BluetoothChatService to write
            	message += '\r';
                byte[] send = message.getBytes();
                nsigApp.mChatService.write(send);
    	        if(D) Log.e(TAG, "sendMessage() NS cmd sent to ChatSvc");              	
                // Reset out string buffer to zero // and clear the edit text field
                nsigApp.mOutStringBuffer.setLength(0);
//                mNSig_CmdEditor =(EditText) findViewById(R.id.edit_text_out);
//                mNSig_CmdEditor.setText(mOutStringBuffer);
             }
	        if(D) Log.e(TAG, "sendMessage() exit");              	
        }

        private void blueToothConnectionNeeded(){
//           	final ToneGenerator tg = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 100);
//           	tg.startTone(ToneGenerator.TONE_CDMA_CALLDROP_LITE); 
            Toast.makeText(this, "Bluetooth is not connected", Toast.LENGTH_LONG).show();
//            BluetoothChatService test = NS3_App.getConnectedThread();
        }

        // The Handler that gets information back from the BluetoothChatService
        protected final Handler mHandler = new Handler(){
        	        	            	


        	@Override
        	public void handleMessage(Message msg) {
//            	Intent ctsIntent = new Intent(Intent.ACTION_SEND);
//            	ctsIntent.setType("cts");
            	NS3_App.spectrumDisplayHandler=mHandler;
    	        if(D) Log.e(TAG, "SpectDisp mHandler entered");
    		    if(!NS3_App.sg_SweepActivated){
        	        if(D) Log.e(TAG, "SpectDisp mHandler EJECTION ");    		    	
    		    	return;
    		    }

            	switch (msg.what) {
                case MESSAGE_STATE_CHANGE:
                    if(D) Log.i(TAG, "handleMessage MESSAGE_STATE_CHANGE: " + msg.arg1);
                    switch (msg.arg1) {
                    case BluetoothChatService.STATE_LISTEN:
                    case BluetoothChatService.STATE_NONE:
                        setStatus(R.string.title_not_connected);
                        break;
                    case BluetoothChatService.STATE_CONNECTED:
                    	String subTitle_Str = getString(R.string.title_connected_to, mConnectedDeviceName);
                        setStatus(subTitle_Str);
                        mConversationArrayAdapter.clear();
           	            TextView nsReplyTxt = (TextView) findViewById(R.id.nsReply);
           	            nsReplyTxt.setText("\nNimbleSig CONNECTED !!!");
           	            nimbleSigConnected();
           	            break;
                    case BluetoothChatService.STATE_CONNECTING:
                        setStatus(R.string.title_connecting);
                        break;
                    }
                    break;
                case MESSAGE_WRITE:
        	        if(D) Log.e(TAG, "handleMessage MESSAGE_WRITE +");              	
                    byte[] writeBuf = (byte[]) msg.obj;
                    // construct a string from the buffer
//                    String writeMessage = new String(writeBuf);
//                    mConversationArrayAdapter.add("Me:  " + writeMessage);
                    break;
                case MESSAGE_READ:
        	        if(D) Log.e(TAG, "handleMessage MESSAGE_READ Entered");              	
                    byte[] readBuf = (byte[]) msg.obj;
                    byte[] buffer2 = new byte[2048];
                    String replyScrolled;                   

                    // insert the characters into the second buffer
                    NS3_App nsigApp = (NS3_App)getApplication();
                    for(int i=0;i<msg.arg1;i++){
                    	buffer2[i]=readBuf[nsigApp.g_BT_RXD_BfrPtr++];
                    	if(nsigApp.g_BT_RXD_BfrPtr>2047)nsigApp.g_BT_RXD_BfrPtr=0;
                    }
                    // construct a string from the valid bytes in the buffer
                    String readMsgStr = new String(buffer2, 0, msg.arg1);//arg1 = byte count
                    g_ReplyStackStr[g_ReplyStkPtr]=readMsgStr;//add the latest message to the stack     	        
                    if(++g_ReplyStkPtr>3)g_ReplyStkPtr=0;//limit number of lines sent to the display
                    replyScrolled="";
                    for(int i=0;i<4;i++){
                    	replyScrolled+=g_ReplyStackStr[g_ReplyStkPtr++];
                        if(g_ReplyStkPtr>3)g_ReplyStkPtr=0;
                    }
//                    final TextView nsReply = (TextView)findViewById(R.id.nsReply);
//                    nsReply.setText(replyScrolled);
//                    setStatus(getString(R.string.title_connected_to, mConnectedDeviceName));
                    
                    int i = readMsgStr.indexOf( '-');// if '-' in msg then a level reading to follow
                    if(i > -1){
                    	g_LevelPending_b=true;
                    	g_LevelValueStr="-";
                    }
                	if(g_LevelPending_b){
                    	int l = readMsgStr.length();
                    	i++;               	
                    	while(l>i){
                    		char c = (readMsgStr.charAt(i++));
                    		if(c=='.')g_LevelValueStr+=c;
                    		else if ((c>='0')&&(c<='9'))g_LevelValueStr+=c;
                    		else if((c == '\r')&&(g_LevelValueStr.length()>2)&&(g_LevelValueStr.contains("."))){
                    			g_LevelPending_b = false;
                    			g_NewLvlReady_b = true;
                    			// write new level reading to GUI
//                    	        mPowerLevel_Btn = (Button) findViewById(R.id.RFLevelBtn);
//                    	        mPowerLevel_Btn.setText(g_LevelValueStr + " dBm");
                    			break;
                    		}
                    	}
/*                    	
    	    	    	if((g_sweepReStart_b)&&(g_NewLvlReady_b)){//sweep renew or sweep re-start re-sync
    	    	    		g_NewLvlReady_b=false;
    	    	    		g_sweepReStart_b = false;
    	    	    		g_NextSweepStep=0;
    	    	    		g_swallowReplies=0;
    	            		g_reStartPending_b=true;
        	    			try{Thread.sleep(100);}catch (InterruptedException e) {}// wait 100mS
        	    	    	sweepStep(g_NextSweepStep);
    	    	    	}
    	    	    	
    	    	    	if((g_SwallowEnabled_b)&&(g_NewLvlReady_b)){//swallow replies at beginning of sweep for NS3 synchronisation
    	    	    		g_NewLvlReady_b=false;
	    	    			g_swallowReplies++;
    	    	    		if(g_swallowReplies > 1){
        	    	    		g_SwallowEnabled_b = false;
    	    	    		}
    	    	    		g_NextSweepStep=0;
        	    			try{Thread.sleep(100);}catch (InterruptedException e) {}// wait 100mS
        	    	    	sweepStep(g_NextSweepStep);
    	    	    	}
    	    	    	if((g_reStartPending_b)&&(g_NewLvlReady_b)){
    	    	    		g_NewLvlReady_b=false;
    	    	    		g_swallowReplies++;
    	    	    		if(g_swallowReplies > 2){
    	    	    			g_reStartPending_b=false;
    	    	    			g_swallowReplies = 0;
    	    	    		}
    	    	    		g_NextSweepStep=0;
        	    			try{Thread.sleep(100);}catch (InterruptedException e) {}// wait 100mS
        	    	    	sweepStep(g_NextSweepStep);
    	    	    	}
 */   	    	    	
                    	if(g_NewLvlReady_b){
                			g_NewLvlReady_b = false;
                        	try{
    	                    	NS3_App.sMeasuredRFLevel_dBm_Str=g_LevelValueStr;
    	                    	float floatLevel_dBm = Float.valueOf(g_LevelValueStr); 
    	                    	if(g_NormalizeCalCycle_b){//save normalization offset for current step
    	                    		g_NormalizeValues[g_NextSweepStep]=floatLevel_dBm;
    	                    	}
    	                    	if((NS3_App.sg_NormalizeMode_b)&&(NS3_App.sg_10dB_Div_Yaxis_b)){//add normalize offset
    	                    		floatLevel_dBm -= g_NormalizeValues[g_NextSweepStep];
    	                    	}
    	                    	floatLevel_dBm = -floatLevel_dBm;
    	                    	if(NS3_App.sg_Scale_dB_Div_Int != 2){
    	                    		NS3_App.sg_Yaxis_DynamicRange_dB_Int=100;
    	                    		floatLevel_dBm += NS3_App.sg_Yaxis_RefLevel_dBm_Int;  //add 10dB/div top of scale reference +20 dBm
    	                    	}else{
    	                    		NS3_App.sg_Yaxis_DynamicRange_dB_Int=20;
    	                    		floatLevel_dBm += NS3_App.sg_2dB_DivRefLvl_Int;  //add 2dB/div top of scale reference level   	                    		
    	                    	}
    	                    	float Y_Flt = ((float)g_yPxSpan*(floatLevel_dBm/NS3_App.sg_Yaxis_DynamicRange_dB_Int)+
    	                    			NS3_App.sg_Y_TopBorder);
    	                    	g_displayY=(int)(Y_Flt+0.5); 
    	                    	if(g_NextSweepStep == 0){
    	                    		int test = g_displayY;
    	                    		
    	                    	}
    	                    	if(g_displayY < NS3_App.sg_Y_TopBorder){
    	                    		g_displayY=NS3_App.sg_Y_TopBorder;//limit swing to top of scale
    	                    	}
    	                    	if(g_displayY > NS3_App.sg_Y_BtmBorder){
    	                    		g_displayY=NS3_App.sg_Y_BtmBorder;//limit swing to bottom of scale
    	                    	}
    	        	    	    drawView.drawTrace(g_displayX,g_displayY);//draw trace segment on spectrum view
    	        	    	    if(NS3_App.sg_SweepActivated){
    	        	    	    	g_NextSweepStep++;
    	        	    	    	if(g_NextSweepStep > (NS3_App.sg_StepsPerSweep)){
    	        	    	    		g_NextSweepStep=0;
    	        	    	    		g_SwallowEnabled_b=true;
    	        	    	    		if(g_NormalizeCalCycle_b)NS3_App.sg_NormalizeMode_b=true;
    	        	    	    		g_NormalizeCalCycle_b=false;
    	        	    	    	}
    	        	    	    	sweepStep(g_NextSweepStep);
    	        	    	    }
                        	}catch (Exception e) {
                        		int forDebugging = 0;
                        		forDebugging++;
                        	} 
                	        if(D) Log.e(TAG, "handleMessage MESSAGE_READ Exit");              	
                    	}
                	}               	            	
    				break;
                case MESSAGE_DEVICE_NAME:
        	        if(D) Log.e(TAG, "handleMessage MESSAGE_DEVICE_NAME +");              	
                    // save the connected device's name
                    mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
                    Toast.makeText(getApplicationContext(), "Connected to "
                                   + mConnectedDeviceName, Toast.LENGTH_LONG).show();
                    break;
                case MESSAGE_TOAST:
        	        if(D) Log.e(TAG, "handleMessage MESSAGE_TOAST +");              	
                    Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST),
                                   Toast.LENGTH_LONG).show();
                    break;
                }
            }
        };

        private void sweepStep(int step){ //generate freq for new step and measure the level
	        if(NS3_App.sg_SweepActivated){
		        if(D) Log.e(TAG, "sweepStep Entered");
		        String stepFreqCmdStr = "fah" + String.valueOf(g_xAxisFrqSteps[step]);
		        sendMessage(stepFreqCmdStr); //generate frequency for next step
		        NS3_App.sg_SweepCurrentFreqHz_Str=spaceDelimiter(g_xAxisFrqSteps[step]);
//		        if(D) Log.e(TAG, "sweepStep new freq cmd sent");
		        int pwrMeterCalMHz=g_stepPwrCalibration[step];
		        if(pwrMeterCalMHz<1)pwrMeterCalMHz=1;
		        String pwrMeterCalMHz_Str = String.valueOf(pwrMeterCalMHz);
		        sendMessage("ll" + pwrMeterCalMHz_Str);//measure the level
//		        if(D) Log.e(TAG, "sweepStep getLevel cmd sent");
		        g_displayX = g_xAxisPxSteps[step];
		        if(step==0){
		        	NS3_App.sg_SweepStartNew=true;
//	    			try{Thread.sleep(100);}catch (InterruptedException e) {}// wait 100mS
		        }
//		        if(D) Log.e(TAG, "sweepStep exit");
	        }else{
		        if(D) Log.e(TAG, "SweepStep - Sweep DeActivated");	        	
	        }
        }

        protected void sweepStart(){
        	NS3_App.sg_SweepActivated=false;
			try{Thread.sleep(100);}catch (InterruptedException e) {}// wait 100mS to let previous level request complete
	        sendMessage("EX");//disable human interface echos
	        g_NextSweepStep=0;
	        NS3_App.sg_SweepStart=true;
        	NS3_App.sg_SweepActivated=true;
        	NS3_App.sg_DrawGrid=true;
    	    g_LevelPending_b=false;
    	    g_NewLvlReady_b=false;
    	    g_LevelDataProcessed_b=false;
			try{Thread.sleep(100);}catch (InterruptedException e) {}// wait 100mS to let previous level request complete
            sweepFreqValsIni(NS3_App.sg_SweepCenterFreqHz,NS3_App.sg_SweepSpanFreqHz);	                    	
        	sweepControl(NS3_App.sg_SweepStartFreqHz, NS3_App.sg_SweepStopFreqHz, NS3_App.sg_StepsPerSweep);        	
        }
        protected void sweepControl(int startFreqHz, int stopFreqHz, int steps){//calculate the x axis step positions and pwr meter cal values        	
        	g_yPxSpan = NS3_App.sg_Y_BtmBorder - NS3_App.sg_Y_TopBorder;
        	g_xPxSpan = NS3_App.sg_X_RightBorder - NS3_App.sg_X_LeftBorder;
        	float sweepBW_Hz=NS3_App.sg_SweepSpanFreqHz;
        	NS3_App.sg_HzPerPixel_Flt=sweepBW_Hz/g_xPxSpan;
        	NS3_App.sg_dB_PerPixel_Flt= (float)NS3_App.sg_Yaxis_DynamicRange_dB_Int/g_yPxSpan;
        	NS3_App.sg_stepSizeHz_Flt=(float)sweepBW_Hz/steps;
        	float pixelsPerStep=(float)g_xPxSpan/steps;
        	for(int i=0;i<(steps+1);i++){
        		g_xAxisFrqSteps[i]=(int)((float)NS3_App.sg_stepSizeHz_Flt    * i + startFreqHz + 0.5);
        		g_xAxisPxSteps[i] =(int)((float)pixelsPerStep * i + NS3_App.sg_X_LeftBorder +0.5);
        		g_stepPwrCalibration[i] = (int)((float)g_xAxisFrqSteps[i]/1000000+0.5);
        	}
        	NS3_App.sg_HzPerDiv_Int=(int)((float)steps/10*NS3_App.sg_stepSizeHz_Flt+.5);
        	g_NextSweepStep=0;
        	sweepStep(g_NextSweepStep);
        }

        private final void setStatus(int resId) {
            final ActionBar actionBar = getActionBar();
            actionBar.setSubtitle(resId);
        }

        private final void setStatus(CharSequence subTitle) {
            final ActionBar actionBar = getActionBar();
            actionBar.setSubtitle(subTitle);
        }
        
        private void nimbleSigConnected(){
            Toast.makeText(this, R.string.NS_Connected, Toast.LENGTH_LONG).show();    	
//            final ToneGenerator tg = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 100);
//            tg.startTone(ToneGenerator.TONE_CDMA_ALERT_AUTOREDIAL_LITE); 
        }

        private void blueToothNotConnected(){
           	TextView nsReplyTxt = (TextView) findViewById(R.id.nsReply);
           	nsReplyTxt.append("\nNimbleSig NOT-CONNECTED !!!"); 
//           	final ToneGenerator tg = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 100);
//           	tg.startTone(ToneGenerator.TONE_CDMA_CALLDROP_LITE); 
        }

        private BroadcastReceiver bluetoothReplyRcvr= new BroadcastReceiver(){
        	public void onReceive(Context context, Intent intent){
        		if(intent.getAction().equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)){
        			
        		}
        	}
        };
        
        // END Bluetooth Link Section  ======================================================= 

	
	}
