//#include <stdio.h>
#include "math.h"
#include "tc_vars.h"
#include "hardware_t.h"
#include "flash_t.h"
#include "display_t.h"
#include "floatstr_t.h"
#include "signal_t.h"
#include "commif_t.h"
#include "userif_t.h"

//#define _Debug_
//#define _Debug_IRQ_
//#define _Debug_QM_
//#define _Debug_FindZero_
//#define _Debug_AutoScale_
//#define _Debug_FindVoltage_
//#define _Debug_FindTimebase_
//#define _Debug_ZeroLevel_
//#define _Debug_Cursor_
//#define _Debug_Roll_Mode_
//#define _Debug_Memory_
//#define _Debug_USB_
//#define _Debug_FFT_


// Class Hardware

void Hardware::Init(void)						// Hardware Init Routine
{
	unsigned long ChannelSign = 0;

	printf("- Hardware initialization\r");

	na_data_adr->np_piodata = 0x01;
	na_mode->np_piodata 	= 0x01;		//reset CH3 & CH4
	na_mode->np_piodata 	= 0x00;

	//printf("Get number of channels\r\n");
	na_data_adr->np_piodata = 0x01;
	ChannelSign = READADC(3);

	if ((ChannelSign & 0xFFFF0000) == 0x12480000)
	{ NumberOfChannels = 4;	}
	else
	{ NumberOfChannels = 2;	}
	
	data_adr->np_piodata = 0x00;

	//printf("Setup hardware\r");
	Setup_Hardware();	
	//printf("Setup hardware 				- done\r\n");

	Read_Version();	
	//printf("HW Version : %x  Channels : %d\r\n", tc_hw_version, NumberOfChannels);

	LED_FunctionTest(0);				// perform LED quick test
	
	//printf("Setup vars\r");
	Setup_Vars();
	//printf("Setup vars 				- done\r\n");

	
	//printf("Read protected config from flash\r");
	AMDFlash::Read_Protected_Flash();
	//printf("Read protected config from flash	- done\r\n");

	//Setup_Interrupts();					//enable all interupts

//	key_reset->np_piodata = 0;				//reset keyboard
//	nr_delay(1);
//	key_reset->np_piodata = 1;	

//	key_int->np_pioedgecapture = 0;				// clear IRQ conditions		

	serdata->np_piodata = ext_trg_val_reg;			// initialize external trigger
	serstartpwm->np_piodata = 1;
	serstartpwm->np_piodata = 0;

	Hardware::Set_Vars_Default();

	AMDFlash::Read_Config_Flash();

	if (config_loaded == false){ Reset_To_Default(); config_changed = 2;return;}	// emergency exit


	printf("- Hardware initialization               - done\r\n");


}

void Hardware::Reset_the_Watchdog(void)					//Resets the WatchDog
{
	reset_watchdog->np_piodata = 0x00;			// Reset WatchDog
	reset_watchdog->np_piodata = 0x01;	
}
//#####################################################################################################################################
void Hardware::Start_Record(void)						
{

	if(acq_ready->np_piodata == 0x01)
	{
		la_pulse->np_piodata = 0x01;			//stop record Port On
		la_pulse->np_piodata = 0x00;			//stop record Port Off	

//		for(unsigned int timeout = 0;acq_ready->np_piodata == 0x01 && timeout < 0x8FFFFFFF;timeout++){}		//wait until acquisition has terminated
//		{ if (timeout > 0xFFFFFFF0 || UI_request){ ADC_Data_Available = 1; return; } }
	}
na_data_adr->np_piodata = 0x01;	
	READADC(1);

	if (NumberOfChannels == 4)   				// JK
	{ READADC(3); }              				// JK
na_data_adr->np_piodata = 0x00;

	ADC_Data_Available = 0;
	adc_started = true;

	start_acq->np_piodata = 0x01;				//start record Port On
	start_acq->np_piodata = 0x00;				//start record Port Off	
 	//printf("Start Record\r\n");
}
//#####################################################################################################################################
void Hardware::Stop_Record()							
{
	adc_started = false;
	la_pulse->np_piodata = 0x01;				//stop record Port On
	la_pulse->np_piodata = 0x00;				//stop record Port Off	
/*
	if (adc_started)
	{
		while (acq_ready->np_piodata == 0x01)
		{}
		adc_started = false;
	}
*/

//    READADC(1);
 //printf("Stop Record\r\n");

}
//#####################################################################################################################################
void Hardware::Read_Version(void)					//Read the hardware version
{
    la_gate->np_piodata = 0x01;
    tc_hw_version = (unsigned long) la_data->np_piodata;
    la_gate->np_piodata = 0x00;
}
//#####################################################################################################################################
void Hardware::Setup_Vars(void)						// Set standard values for variables
{
	short ix, ix2, ix3;
    	int cnt;
	
	for (ix = 0;ix < 480;ix++)
	    Display_Line_Adresses[ix] = ix * 20;	//BF used in  Display::PIXELP() and in Screenshot()

	// BF -> changed Stefans initialization to 1 dimensional array
	for (cnt = 0; cnt < 1024; cnt++)
	SIGNAL_Histo[cnt] = 0;
	

	// delete signals
	for (cnt = 0; cnt < 0x4000; cnt++) {
		SIGNAL1[cnt] = ADC_ZERO;
		SIGNAL2[cnt] = ADC_ZERO;
		SIGNAL3[cnt] = ADC_ZERO;
		SIGNAL4[cnt] = ADC_ZERO;
	        SIGNALM[cnt] = ADC_ZERO;
	}	

	MenuStored  = 0;
	MenuChanged = 0;
		
	IsPopuped   = 0;
	
    	Cursor_Enabled = false;
	
	Cursor_Both_Selected_Old = 0;	
    	Cursor_Both_Selected = 0;	
	
	SelectedCursor = 0;
	SelectedCursorOld = 0;	
	
	CursorChanged = 0;
	
	Cursor_Horizontal_Active = 0;
	Cursor_Horizontal_Active_Old = 0; 	

	Cursor_Horizontal_Position_Real1 = 103;
	Cursor_Horizontal_Position_Real2 = 203;	

	Cursor_Horizontal_Position1_Old = 103;
	Cursor_Horizontal_Position2_Old = 203;	

	Cursor_Vertical_Active = 0;
	Cursor_Vertical_Active_Old = 0;	

	Cursor_Vertical_Position_TY_1 = 100;	
	Cursor_Vertical_Position_TY_2 = 400;	

	Cursor_Vertical_Position_XY_1 = 100;
	Cursor_Vertical_Position_XY_2 = 300;

	Cursor_Vertical_Position_FFT_1 = 125;
	Cursor_Vertical_Position_FFT_2 = 475;

	Cursor_Vertical_Position1_Old = 0;
	Cursor_Vertical_Position2_Old = 0;	
/*
	Cursor_Vertical_Position_Real_XY_1 = 103;
	Cursor_Vertical_Position_Real_XY_2 = 203;	

	Cursor_Vertical_Position_XY_1_Old = 103;
	Cursor_Vertical_Position_XY_2_Old = 203;
*/	
    	QM_Enabled = false;
	QM_Changed[0] = 0;
	QM_Changed[1] = 0;
	QM_Changed[2] = 0;
	
	QM_Type[0] = 0;
	QM_Type[1] = 0;
	QM_Type[2] = 0;

	QM_Type_Old[0] = 0;
	QM_Type_Old[1] = 0;
	QM_Type_Old[2] = 0;
	
	QM_Channel[0] = 1;
	QM_Channel[1] = 1;
	QM_Channel[2] = 1;	
    	
	QM_Horizontal_Active = 3;
	QM_Horizontal_Active_Old = 3; 	

	QM_Horizontal_Position_Real1 = 103;
	QM_Horizontal_Position_Real2 = 203;	

	QM_Horizontal_Position1_Old = 103;
	QM_Horizontal_Position2_Old = 203;	

	QM_Vertical_Active = 3;
	QM_Vertical_Active_Old = 3;	

	QM_Vertical_Position_Real1 = 103;
	QM_Vertical_Position_Real2 = 203;	

	QM_Vertical_Position1_Old = 103;
	QM_Vertical_Position2_Old = 203;		

    	Quick_Measure_Threshold_btn_select = 1;

	Selected_Trigger_Source     = 1;
	Selected_Trigger_Source_Old = 1;
	
	MainTimebase = 4;
	
	DelayedTimebase = 0;
	dmode_Window_Offset_Pos = 0;
	
	TriggerWay = TRIG_EDGE;

	Selected_Voltage_CH1 = 9;
	Selected_Voltage_CH2 = 9;
	Selected_Voltage_CH3 = 9;
	Selected_Voltage_CH4 = 9;
	Selected_TB = 0;	
	
	SwitchesCH1 = 0x00D5;
	SwitchesCH2 = 0x00D5;
	SwitchesCH3 = 0x00D5;
	SwitchesCH4 = 0x00D5;	
	SwitchesTB  = 0x0000;		

/*
	SwitchesCH1Old = 0x0000;
	SwitchesCH2Old = 0x0000;
	SwitchesCH3Old = 0x0000;
	SwitchesCH4Old = 0x0000;		
	SwitchesTBOld  = 0x0001;
*/
	ScreenShotActive = 0;	
	
	USB_Data_Trans  = 0;
	USB_SendAllData = 0;
	USB_OnlyTrigger = 0;
	Run       	= 1;
	SingleShot      = 0;	
	//Single_Restart  = 0;
	
	ADC_Debug_Mode = false;
	Debug_Mode     = false;
	Command_Mode   = false;
	//Calc_Mode      = false;
	ExtraTrg_Mode  = false;
	
	adc_started    = false;
	
	ctrl_reg     = 0x00A3;
	adc_ctrl_reg = 0x01C0;
	
	adc_del_reg = 0;
	pre_reg = 0x0000;
	//trg_val_reg = 0x00A0;
	//trg_hyst_reg = 0x0090;
	ext_trg_val_reg = 125;	// JK 0x80;
	triggering = 0x00;
	trig_range_reg = 0;
	trig_width_reg = 0x0001;
	
	trg_val_CHI_reg   = 0x00A0;
	trg_val_CHII_reg  = 0x00A0;
	trg_val_CHIII_reg = 0x00A0;
	trg_val_CHIV_reg  = 0x00A0;
	
	trig_holdoff_reg = 0x00000000;

//	ram_adress_reg = 0;
//	test_port_reg = 0;
	
	CH1_DAC_Offset = DAC_MIDSCALE;
	CH2_DAC_Offset = DAC_MIDSCALE;
	CH3_DAC_Offset = DAC_MIDSCALE;
	CH4_DAC_Offset = DAC_MIDSCALE;

	VSync_Needed = 0;		// BF what for?????????????????
	
	ClearPlane  = 0x00;
	DrawPlane   = 0x00;
	RemovePlane = 0x00;
	ClearPhase  = true;		// BF what for?????????????????

	// Display settings
	GridColorArrayPos         = 1;                                          		// Normal Grid 33 %
	GridColor_Val             = GridColorArray[ColorPalette][GridColorArrayPos];     	// Grid Color
	
	Rotary_Direction           = 0;
	Rotary_Direction_mem_pulse = 1;
	Rotary_Switch              = 0;
	Rotary_Steps               = 1;
	
	Keyboard_mem     = 0;
	Keyboard_Changed = 0;
	
	ADC_Data_Available = 0;

	USB_Data_Trans  = false;
	USB_SendAllData = false;
	USB_OnlyTrigger = false;
	
	//ButtonChanged = false;
	//RoteryChanged = false;

	PopUpPosition    = 0;
	IsPopuped        = false;
	PopupTimeCounter = 0;
	
	TriggerLevelChanged = 1;								// Was Triggerlevel changed
	TriggerModeChanged  = 1;								// Was Triggermode changed
	TriggerWayChanged   = 1;								// Was Triggerway changed
	TimebaseChanged     = 1;								// Was Timebase changed
	TimeOffsetChanged   = 1;								// Was Time_Offset changed
//BF del	SIGNALFaktorChanged = 1;								// Was SIGNALFaktor changed
	
	TriggerLevelActive = 0;								    	// Is Triggerlevel selected ?
	TimeOffsetActive   = 0;									// Is Time_Offset selected ?
	
	StatusBtnRemove  = 0;									// remove button
	ZeroPopupChanged  = 0;									// When 1 then is changed
	MenuPopupChanged  = 0;									// When 1 then is changed
	MenuPopupActive   = -1;									// Stores the actual Menupopup
	VoltageChangedCh1 = 1;									// Was Voltage changed
	VoltageChangedCh2 = 1;									// Was Voltage changed
	VoltageChangedCh3 = 1;									// Was Voltage changed
	VoltageChangedCh4 = 1;									// Was Voltage changed
	MenuPopupChanged2 = 0;									// Was MenuPopup changed
	MenuOnlyChanged  = 0;									// When 1 then is changed

	MenuItemPushed[0] = 0;				                    // When Menuitem is pushed drawed
	MenuItemPushed[1] = 0;				                    // When Menuitem is pushed drawed
	MenuItemPushed[2] = 0;				                    // When Menuitem is pushed drawed
	MenuItemPushed[3] = 0;				                    // When Menuitem is pushed drawed
	MenuItemPushed[4] = 0;				                    // When Menuitem is pushed drawed
	MenuItemPushed[5] = 0;				                    // When Menuitem is pushed drawed
	
	//MenuStatusChanged = 0;									// When switching on/off a menu holds menunr
	
	VS_ZeroLevelChanged = 0;								// zero changed
	VS_TrigLevelChanged = 0;								// triggerlevel change
	
	MenuPopupX = 0;
	MenuPopupY = 0;
	MenuPopupSizeX = 0;
	MenuPopupSizeY = 0;
	
	MenuStored      = 0;
	MenuChanged     = true;
	MenuTimeCounter = 0;										// Counter for Menu Pulldown
	
	MenuItemCount    = 0;										// Store the count of the Menuitems
	MenuOldItemCount = 0;										// Store the count of the old Menuitems
	
	New_Menu     = -1;
	Active_Menu  = -1;
	Menu_Changed = -1;
	
	//Memory_Position = 0;

	UI_request = 0;	


/*BF del not used
	//clear buffers
	for (cnt = 0; cnt < 32; cnt++)
	  LogicData[cnt] = 0;
*/	

}
//#####################################################################################################################################
void Hardware::Setup_Hardware(void)					// Setup the Hardware
{
	dma->np_piointerruptmask = 0x00;							// disable all IRQs
	dma->np_piodirection = 0x01;								// set all bits to output
	dma->np_piodata = 0x00;									// Set to 0

	serstartled->np_piointerruptmask = 0x00;						// disable all IRQs
	serstartled->np_piodirection = 0x01;							// set all bits to output
	serstartled->np_piodata = 0x00;								// Set to 0

	serstartsw->np_piointerruptmask = 0x00;							// disable all IRQs
	serstartsw->np_piodirection = 0x01;							// set all bits to output
	serstartsw->np_piodata = 0x00;								// Set to 0

	serstartdac->np_piointerruptmask = 0x00;						// disable all IRQs
	serstartdac->np_piodirection = 0x01;							// set all bits to output
	serstartdac->np_piodata = 0x00;								// Set to 0

	serdata->np_piointerruptmask = 0x00;							// disable all IRQs
	serdata->np_piodirection = 0xFF;							// set all bits to output
	serdata->np_piodata = 0x00;								// Set to 0

	key_reset->np_piointerruptmask = 0x00;							// disable all IRQs
	key_reset->np_piodirection = 0x01;							// set all bits to output
	key_reset->np_piodata = 0x01;								// Set to 1

	key_int->np_piointerruptmask = 0x00;							// disable all IRQs
	key_int->np_piodirection = 0x00;							// set all bits to input
	key_int->np_piodata = 0x00;								// Set to 0

	key->np_piointerruptmask = 0x00;							// disable all IRQs
	key->np_piodirection = 0x00;								// set all bits to input
	key->np_piodata = 0x00;									// Set to 0

	rot_speed_read->np_piointerruptmask = 0x00;						// disable all IRQs
	rot_speed_read->np_piodirection = 0x01;							// set all bits to output
	rot_speed_read->np_piodata = 0x00;							// Set to 0

	data_adr->np_piointerruptmask = 0x00;							// disable all IRQs
	data_adr->np_piodirection = 0x01;							// set all bits to output
	data_adr->np_piodata = 0x00;								// Set to 0
	
	mode->np_piointerruptmask = 0x00;							// disable all IRQs
	mode->np_piodirection = 0x01;								// set all bits to output
	mode->np_piodata = 0x00;								// Set to 0
	
	start_acq->np_piointerruptmask = 0x00;							// disable all IRQs
	start_acq->np_piodirection = 0x01;							// set all bits to output
	start_acq->np_piodata = 0x00;								// Set to 0

	acq_ready->np_piointerruptmask = 0x00;							// disable all IRQs
	acq_ready->np_piodirection = 0x00;							// set all bits to input
	acq_ready->np_piodata = 0x00;								// Set to 0

	reset_watchdog->np_piointerruptmask = 0x00;						// disable all IRQs
	reset_watchdog->np_piodirection = 0x01;							// set all bits to output
	reset_watchdog->np_piodata = 0x00;							// Set to 0

	la_data->np_piointerruptmask = 0x00;							// disable all IRQs
	la_data->np_piodirection = 0x00;							// set all bits to input
	la_data->np_piodata = 0x00;								// Set to 0

	la_interrupt->np_piointerruptmask = 0x00;						// disable all IRQs
	la_interrupt->np_piodirection = 0x00;							// set all bits to input
	la_interrupt->np_piodata = 0x00;							// Set to 0

	la_gate->np_piointerruptmask = 0x00;							// disable all IRQs
	la_gate->np_piodirection = 0x01;							// set all bits to output
	la_gate->np_piodata = 0x00;									// Set to 0

	la_pulse->np_piointerruptmask = 0x00;							// disable all IRQs
	la_pulse->np_piodirection = 0x01;							// set all bits to output
	la_pulse->np_piodata = 0x00;								// Set to 0

	//out_test->np_pioedgecapture = 0x00; 							// clear all existing IRQ conditions
	//out_test->np_piodirection = 0x01;								// set all bits to output
	//out_test->np_piodata = 0x08;

	boot_reset_key->np_piointerruptmask = 0x00;						// disable all IRQs
	boot_reset_key->np_piodirection = 0x00;							// set all bits to input
	boot_reset_key->np_piodata = 0x00;							// Set to 0

	power_on_boot_key->np_piointerruptmask = 0x00;						// disable all IRQs
	power_on_boot_key->np_piodirection = 0x00;						// set all bits to input
	power_on_boot_key->np_piodata = 0x00;							// Set to 0
	
	//key_test->np_piointerruptmask = 0x00;							// disable all IRQs
	//key_test->np_piodirection = 0x00;							// set all bits to input
	//key_test->np_piodata = 0x00;			

    if ((boot_reset_key->np_piodata == 0x00) && (power_on_boot_key->np_piodata == 0x00)) {
        printf("No Keyboard found\r\n");
        keyboard_found = 1;
    } 
	else if ((boot_reset_key->np_piodata == 0x01) && (power_on_boot_key->np_piodata == 0x00)) {
        printf("Power on Boot Pressed\r\n");
        keyboard_found = 2;
    } 
	else if ((boot_reset_key->np_piodata == 0x00) && (power_on_boot_key->np_piodata == 0x01)) {
        printf("Reset on Boot Pressed\r\n");
        keyboard_found = 3;
    } else {
        //printf("Keyboard found\r\n");
        keyboard_found = 4;
    }

	triggering = 0;
}
//#####################################################################################################################################
void Hardware::Setup_Interrupts(void)					// Setup the Interrupts
{
	if (keyboard_found == 4)
	{
		DoEnableKeyInterrupt();
		DoEnableRotInterrupt();

		//key_reset->np_piodata = 0;				//reset keyboard
		//nr_delay(1);
		//key_reset->np_piodata = 1;	
	
		//key_int->np_pioedgecapture = 0;				// clear IRQ conditions		
	}
	
	DoEnableUARTInterrupt();
	DoEnableUART2Interrupt();
	DoEnableADCInterrupt();	
	//DoEnableReadVSyncInterrupt();
	//    DoEnableLogicAnalyserInterrupt();
	DoEnableTimer1Interrupt();
	DoEnableTimer2Interrupt();
	DoEnableTimer3Interrupt();	
}
//#####################################################################################################################################
//BF #010
void Hardware::Disable_All_Interrupts(void)					// Disable the Interrupts
{
	if (keyboard_found == 4)
	{
		DoDisableKeyInterrupt();
		DoDisableRotInterrupt();
	}
	
	DoDisableUARTInterrupt();
	DoDisableUART2Interrupt();
	DoDisableADCInterrupt();	
	DoDisableReadVSyncInterrupt();
	//    DoDisableLogicAnalyserInterrupt();
	DoDisableTimer1Interrupt();
	DoDisableTimer2Interrupt();
	DoDisableTimer3Interrupt();	
}
//#####################################################################################################################################
void Hardware::Set_Vars_Default(void)					//Resets all vars to standard values
{
	int cnt;
	
	// Main/Delayed - Timebase
	MenuStatus[MENU_TIMEBASE][0] = BTN_ON;				// Main
	MenuStatus[MENU_TIMEBASE][1] = BTN_OFF;				// Delayed
	MenuStatus[MENU_TIMEBASE][2] = BTN_OFF;				// XY-Mode
	MenuStatus[MENU_TIMEBASE][3] = BTN_OFF;				// FFT-Mode
	MenuStatus[MENU_TIMEBASE][4] = BTN_OFF;				// Timebase - Browse off
	Memory_Window_visible = 0;

	MenuStatus[MENU_USTB][0] = USTB_ROLL;                     	// Roll-Mode 
	MenuStatus[MENU_USTB][1] = USTB_PERM;				// Display -> permanent
	MenuStatus[MENU_USTB][2] = USTB_16KB;				// Buffer size 16KB


	XY_Mode       = 0;						// Normal Mode - No XY-Mode
	USTB_Mode     = USTB_OFF;					// ultra slow timebase off	
	USTB_Mode_bak = USTB_ROLL;

	UI_request  = 0;						//BF flag for user interface activity
	QP_request  = 0;						//BF flag Quick Print requested
	ZL_changed  = 0;						//BF OnZero Channel -> only draw signal with changed zerolevel
	AS_request  = 0;						//BF auto scale requested
	RC_request  = 0;						//BF signal recall requested
	RC_overlay  = 0;

	test_signal = 0;						//BF test signal generator
	CRS_Delta   = 1;						//BF delta cursor on/off

	UART_NewData = 0;
	UART_RXData  = -1;
	
//BF ins	
	//Trig_Pos_Mem             = 300; 
	Trig_Pos_Display           = 300;
	Trig_Pos_Display_dmode     = 300;
	Trig_Pos_Mem               = 300;
	Trig_Pos_Mem_old           = 300;	
	Trig_Pos_Display_old       = 300;
	Trig_Pos_Display_dmode_old = 300;	
	MemWinStart                = 0;
	MemWinStart_old            = -300;

// BF end
	
	dmode_Window_Offset_Pos = 0;

	SwitchesTB         = 0;                                         // timebase switches
	MainTimebase       = 4;                                        	// Displayed timebase is 50 ns
	VirtualTimebase	   = 0;

	DelayedTimebase = 0;                                    // delayed timebase is 20 ns
	Timebase_Ratio = 0;                                             // factor for delayed windows cursor calculation
	
	Cursor_Delayed_1    = 180;                                      // Delayed windows cursor position 1
	Cursor_Delayed_2    = 420;                                      // Delayed windows cursor position 2
	Cursor_Delayed_Size = 240;                                      // Delayed windows size
	

	// Trigger
	// Trigger Mode
	MenuStatus[MENU_TRIGGERMODE][0] = TRIG_AUTO;                                   // Triggering - Auto
	MenuStatus[MENU_TRIGGERMODE][1] = 95;                                         // Triggering - Coupling DC
	MenuStatus[MENU_TRIGGERMODE][4] = 104;                                        // Triggering - External Probe 1:1
	
//BF del #020	MenuPopupStatus[9][0] = 3;
//BF del #020	MenuPopupStatus[9][1] = 2;
		
	EdgeToggle = 1;                                                 		// Holdoff deaktive - probe button active
	
	// Trigger Edge
	MenuStatus[MENU_TRIGGEREDGE][0] = 2;                                          // Triggering - positive edge
	MenuStatus[MENU_TRIGGEREDGE][1] = 137;                                        // Triggering - Source = channel 1 #019
	MenuStatus[MENU_TRIGGEREDGE][2] = 246;                                        // Triggering - no externel triggering #019
	MenuStatus[MENU_TRIGGEREDGE][3] = 246;                                        // Triggering - no externel TV triggering #019
	Display::MenuPopupInit(28, MENU_TRIGGEREDGE, 137);	
	//init extern trigger menu #019
	MenuPopupStatus[8][0] = 3;
	MenuPopupStatus[8][1] = 2;
	MenuPopupStatus[8][2] = 2;
	//init TV trigger menu #019
	MenuPopupStatus[11][0] = 3;
	MenuPopupStatus[11][1] = 2;



	// Trigger Pulse
	MenuStatus[MENU_PULSEWIDTH][0] = 137;                                        // Triggering - Source Channel 1
	//MenuStatus[MENU_PULSEWIDTH][1] = 2;                                          // Triggering - Negative Pulse
	MenuStatus[MENU_PULSEWIDTH][2] = 3;                                          // Triggering - bigger - smaller - then
	
	Selected_Trigger_Source = 1;                                    	// Selected Trigger Source is Channel 1
//BF not used	SelectedEdgeExtern = 0;                                         // Trigger Edge by extern triggering


	CalSet = 0;
	MenuStatus[MENU_UTILITY][3] = 264;					// calibration set standard
	Display::MenuPopupInit(19, MENU_UTILITY, 264);	

			
	//BF set zero levels to default
	if (NumberOfChannels == 2)
	{
		ZeroLevelCH1 = (int)(GRID_HEIGHT / 4);		// 1/4 grid height
		ZeroLevelCH2 = (int)((GRID_HEIGHT / 4) * 3);	// 3/4 grid height
		ZeroLevelCH3 = (int)(GRID_HEIGHT >> 1);	
		ZeroLevelCH4 = (int)(GRID_HEIGHT >> 1);
	}
	else
	{
		//ZeroLevelCH1 = (int)(GRID_HEIGHT / 5.333);			//10% line
		ZeroLevelCH1 = (int)(GRID_HEIGHT / 8);				// first div
		ZeroLevelCH2 = (int)((GRID_HEIGHT / 8) * 3);			//third div
		ZeroLevelCH3 = (int)((GRID_HEIGHT / 8) * 5);			//fifth div
		ZeroLevelCH4 = (int)((GRID_HEIGHT / 8) * 7);			// last div
		//ZeroLevelCH4 = (int)(GRID_HEIGHT - (GRID_HEIGHT / 5.333));	//90% line
	}

	ZeroLevelCH1_Old = ZeroLevelCH1;
	ZeroLevelCH2_Old = ZeroLevelCH2;
	ZeroLevelCH3_Old = ZeroLevelCH3;
	ZeroLevelCH4_Old = ZeroLevelCH4;

	Virtual_ZeroLevelCH1 = ZeroLevelCH1 - (GRID_HEIGHT / 2);	//Virtual zeroes are related to 1/2 grid height,
	Virtual_ZeroLevelCH2 = ZeroLevelCH2 - (GRID_HEIGHT / 2);	//means that VZero = 0 is the middle of the grid
	Virtual_ZeroLevelCH3 = ZeroLevelCH3 - (GRID_HEIGHT / 2);	
	Virtual_ZeroLevelCH4 = ZeroLevelCH4 - (GRID_HEIGHT / 2);
	
	Virtual_ZeroLevelXYCH1 = 0;	// 0 = middle of the grid
	Virtual_ZeroLevelXYCH2 = 0;	// 0 = middle of the grid
	Virtual_ZeroLevelXYCH3 = 0;	// 0 = middle of the grid	
	Virtual_ZeroLevelXYCH4 = 0;	// 0 = middle of the grid


	//BF set trigger levels
	Trigger_Pos_CH1 = ZeroLevelCH1;					// Trigger Level Channel 1
	Trigger_Pos_CH2 = ZeroLevelCH2;					// Trigger Level Channel 2
	Trigger_Pos_CH3 = ZeroLevelCH3;					// Trigger Level Channel 3
	Trigger_Pos_CH4 = ZeroLevelCH4;					// Trigger Level Channel 4
	Trigger_Pos_CHE = 61;						// Trigger Level Extern Trigger Source JK old 56
	
	Trigger_Pos_CH1_Old = ZeroLevelCH1;
	Trigger_Pos_CH2_Old = ZeroLevelCH2;
	Trigger_Pos_CH3_Old = ZeroLevelCH3;
	Trigger_Pos_CH4_Old = ZeroLevelCH4;
	Trigger_Pos_CHE_Old = 61;		// JK 56

	//trg_val_reg = 0xB1;                                       	// Trigger Value
	//trg_hyst_reg = 0xA9;                                		// Trigger Hysterese
	trg_val_CHI_reg   = 0x00A0;                                     // Trigger Level Register Channel 1
	trg_val_CHII_reg  = 0x00A0;                                     // Trigger Level Register Channel 2
	trg_val_CHIII_reg = 0x00A0;                                     // Trigger Level Register Channel 3
	trg_val_CHIV_reg  = 0x00A0;                                     // Trigger Level Register Channel 4
	ext_trg_val_reg   = 125;	// JK 0x80;                             		// Triggr Level Register Extern Trigger (0.00V)
	
	trig_range_reg   = 0;                                  		// Trigger Range
	trig_holdoff_reg = 0;                  				// Trigger Holdoff
	trig_width_reg   = 0;                                   	// Trigger Width
	pre_reg          = 0x6C;    					// PreTrigger Value

	ACQ_ManTrigg = 0;						// manual trigger off

//--------------------------------------------------------------------------------------------------------------------------------
	ctrl_reg         = 0x0007;                                        // Control register
	adc_ctrl_reg     = 0x81C0;		                          // ADC Control register - Auto Slope detect off

//BF ???	ctrl_reg     = 0x00A3;
//BF ???	adc_ctrl_reg = 0x01C0;
//------------------------------------------------------------------------------------------------------------------------------
	triggering = 1;                                                 // Triggering - Free Run
	TriggerWay = TRIG_EDGE;                                         // Edge
	Run  = 1;                                                 	// Running
	
	HoldOff_Value = 0;
	HoldOff_Expo  = 1;   //ns
	HoldOff_Steps = 8;   //40;
	
	Pulse11_Value = 16;
	Pulse11_Expo  = 1;   //ns
	Pulse11_Steps = 8;
	
	Pulse12_Value = 8;
	Pulse12_Expo  = 1;   //ns
	Pulse12_Steps = 8;
	
	Pulse21_Value = 16;
	Pulse21_Expo  = 1;   //ns
	Pulse21_Steps = 8;
	
	Pulse22_Value = 16;
	Pulse22_Expo  = 1;   //ns
	Pulse22_Steps = 8;

	math_scale     = 11;	//BF added -> 5V default
	math_mul_scale = 177;	//BF -> 5V
	math_sub_scale = 161;	//BF -> 5V 
	math_add_scale = 161;	//BF -> 5V
	
	//BF added for new offset calculation
	Math_Offset     = 0;
	Math_Mul_Offset = 0;
	Math_Sub_Offset = 0;
	Math_Add_Offset = 0;
	
	Math_Offset_mul.Init(0.000001, 0.000001, 1000, 0.000001, 2, 3, "", "", "V");
	Math_Offset_mul.RenderText();
	Math_Offset_add.Init(0.001, 0.001, 1000, 0.001, 2, 3, "", "", "V");
	Math_Offset_add.RenderText();
	Math_Offset_sub.Init(0.001, 0.001, 1000, 0.001, 2, 3, "", "", "V");
	Math_Offset_sub.RenderText();

	// Channel 1
	Channel_1_Active = 1;                                           // Channel 1 active
//BF del	Channel_1_Active_Old = 0;                                       // Channel 1 old must be 0
	Channel_1_Active_bak = 1;                                       // Channel 1 backup
	MenuStatus[MENU_CHANNEL1][0] = 8;                               // Channel 1 - Coupling AC
	MenuStatus[MENU_CHANNEL1][1] = BTN_OFF;                             // Channel 1 - BW Limit off
	MenuStatus[MENU_CHANNEL1][2] = BTN_OFF;                             // Channel 1 - Invert off
	MenuStatus[MENU_CHANNEL1][3] = 104;                             // Channel 1 - Probe 1.0 : 1
	
	MenuPopupStatus[13][0] = 2;                                     // Popup Coupling = DC
	MenuPopupStatus[13][1] = 2;
	MenuPopupStatus[13][2] = 3;
	
	SwitchesCH1 = MenuStatus[MENU_HARDWARE][1] == ADD_ON ? 0x0F3A : 0x0F1A;            // Switches for Channel 1 and for the other the AC bit
 	SwitchesLMH[0] = 0x040A; // LMH6518 default config: aux amp disabled, no filter, low gain, max. attenuation
	//SwitchesCH1 = 0x0F1A;                                           // Switches for Channel 1 and for the other the AC bit
	
	Selected_Voltage_CH1 = 11;                                      // Voltage 5V
	
	// Channel2
	Channel_2_Active = 1;                                           // Channel 2 active
//BF del	Channel_2_Active_Old = 0;                                       // Channel 2 old must be 0
	Channel_2_Active_bak = 1;                                       // Channel 2 backup
	MenuStatus[MENU_CHANNEL2][0] = 8;                               // Channel 2 - Coupling AC
	MenuStatus[MENU_CHANNEL2][1] = BTN_OFF;                             // Channel 2 - BW Limit off
	MenuStatus[MENU_CHANNEL2][2] = BTN_OFF;                             // Channel 2 - Invert off
	MenuStatus[MENU_CHANNEL2][3] = 104;                             // Channel 2 - Probe 1.0 : 1
	
	MenuPopupStatus[14][0] = 2;                                     // Popup Coupling = DC
	MenuPopupStatus[14][1] = 2;
	MenuPopupStatus[14][2] = 3;

	SwitchesCH2 = MenuStatus[MENU_HARDWARE][1] == ADD_ON ? 0x003A : 0x001A;            // Switches for Channel 2
	SwitchesLMH[1] = 0x040A; // LMH6518 default config: aux amp disabled, no filter, low gain, max. attenuation
	//SwitchesCH2 = 0x001A;                                           // Switches for Channel 2
	Selected_Voltage_CH2 = 11;                                      // Voltage 5V
	
	if (NumberOfChannels == 4)
	{
		// Channel 3
		Channel_3_Active = 1;                                           // Channel 3 active
//BF del		Channel_3_Active_Old = 0;                                       // Channel 3 old must be 0
		Channel_3_Active_bak = 1;                                       // Channel 3 backup
		MenuStatus[MENU_CHANNEL3][0] = 8;                               // Channel 3 - Coupling AC
		MenuStatus[MENU_CHANNEL3][1] = BTN_OFF;                             // Channel 3 - BW Limit off
		MenuStatus[MENU_CHANNEL3][2] = BTN_OFF;                             // Channel 3 - Invert off
		MenuStatus[MENU_CHANNEL3][3] = 104;                             // Channel 3 - Probe 1.0 : 1
	
		MenuPopupStatus[15][0] = 2;                                     // Popup Coupling = DC
		MenuPopupStatus[15][1] = 2;
		MenuPopupStatus[15][2] = 3;

		SwitchesCH3 = MenuStatus[MENU_HARDWARE][1] == ADD_ON ? 0x003A : 0x001A;            // Switches for Channel 3
		SwitchesLMH[2] = 0x040A; // LMH6518 default config: aux amp disabled, no filter, low gain, max. attenuation
		//SwitchesCH3 = 0x001A;                                           // Switches for Channel 3
		Selected_Voltage_CH3 = 11;                                      // Voltage 5V
	
		// Channel 4
		Channel_4_Active = 1;                                           // Channel 4 active
//BF del		Channel_4_Active_Old = 0;                                       // Channel 4 old must be 0
		Channel_4_Active_bak = 1;                                       // Channel 4 backup
		MenuStatus[MENU_CHANNEL4][0] = 8;                           	// Channel 4 - Coupling AC
		MenuStatus[MENU_CHANNEL4][1] = BTN_OFF;                         	// Channel 4 - BW Limit off
		MenuStatus[MENU_CHANNEL4][2] = BTN_OFF;                         	// Channel 4 - Invert off
		MenuStatus[MENU_CHANNEL4][3] = 104;                         	// Channel 4 - Probe 1.0 : 1
	
		MenuPopupStatus[16][0] = 2;                                     // Popup Coupling = DC
		MenuPopupStatus[16][1] = 2;
		MenuPopupStatus[16][2] = 3;
	
		SwitchesCH4 = MenuStatus[MENU_HARDWARE][1] == ADD_ON ? 0x003A : 0x001A;            // Switches for Channel 4
		SwitchesLMH[3] = 0x040A; // LMH6518 default config: aux amp disabled, no filter, low gain, max. attenuation
		//SwitchesCH4 = 0x001A;                                           // Switches for Channel 4
		Selected_Voltage_CH4 = 11;                                      // Voltage 5V
	}
	else
	{
		// Channel 3
		Channel_3_Active = 0;                                           // Channel 3 inactive
		Channel_3_Active_bak = 0;
//BF del		Channel_3_Active_Old = 0;                                       // Channel 3 old must be 0

		// Channel 4
		Channel_4_Active = 0;                                           // Channel 4 inactive
		Channel_4_Active_bak = 0;
//BF del		Channel_4_Active_Old = 0;                                       // Channel 4 old must be 0
	}

	Channels_Active = NumberOfChannels;

	Channel_Math_Active = 0;                                       		// Math channel off
	//MenuStatus[MENU_MATH][1] = BTN_OFF;    				// not used 
	MenuStatus[MENU_MATH][2] = BTN_OFF;					// math 1*2 off
	MenuStatus[MENU_MATH][3] = BTN_ON;					// math 1-2 on
	MenuStatus[MENU_MATH][4] = BTN_OFF;					// math 1+2 off

	math_mul_scale = 177;							//5V	math scaling default setting
	math_sub_scale = 161;							//5V	math scaling default setting
	math_add_scale = 161;							//5V	math scaling default setting
 
	MenuStatus[MENU_FFT][0] = 137;                                          // source = channel 1
	MenuStatus[MENU_FFT][1] = 193;                                          // window = rectangle
	MenuStatus[MENU_FFT][2] = 66;                                          	// mode   = linear
	MenuStatus[MENU_FFT][3] = 83;                                          	// length = 512
	
	FFT_Mode    = FFT_OFF;							// FFT off
	FFT_NewData = 0;
	FFT_Length  = FFT_512;
	FFT_Level   = 9;							// FFT_Level = ld(FFT_Length)
	FFT_Windex  = -1;							// FFT window index default is rect
//BF not needed anymore	FFT_Scale   = 2;
	
	GainIdx = MenuStatus[MENU_HARDWARE][1] - 230;				//BF #004 set gain of input stage

	SavePointer = 1;

	// Cursors
	MenuStatus[MENU_CURSOR][0] = 27;                                         // Cursor source = channel 1
	
	Cursor_Enabled = false;
	Cursor_Both_Selected = 0;	
	SelectedCursor = 0;
	Cursor_Horizontal_Active = 0;
	Cursor_Horizontal_Position_Real1 = 103;
	Cursor_Horizontal_Position_Real2 = 203;	
	Cursor_Vertical_Active = 0;

	Cursor_Vertical_Position_TY_1 = 100;	
	Cursor_Vertical_Position_TY_2 = 400;	

	Cursor_Vertical_Position_XY_1 = 100;
	Cursor_Vertical_Position_XY_2 = 300;

	Cursor_Vertical_Position_FFT_1 = 125;
	Cursor_Vertical_Position_FFT_2 = 475;


    	// Quick Measure
	QM_Enabled = false;
	
	QM_Type[0] = 5;
	QM_Type[1] = 8;
	QM_Type[2] = 0;
	
	QM_Channel[0] = 1;
	QM_Channel[1] = 1;
	QM_Channel[2] = 1;	
    	
	QM_Horizontal_Active = 0;
	QM_Horizontal_Position_Real1 = 103;
	QM_Horizontal_Position_Real2 = 203;	

	QM_Vertical_Active = 0;
	QM_Vertical_Position_Real1 = 103;
	QM_Vertical_Position_Real2 = 203;	

	Quick_Measure_Threshold_btn_select = 1;
	
	MenuStatus[MENU_QUICKMEASURE][0] = 27;	
	MenuStatus[MENU_QUICKMEASURE][1] = 52;
	MenuStatus[MENU_QUICKMEASURE][2] = 52;
	MenuStatus[MENU_QUICKMEASURE][4] = 244;			// gray out button

	MenuStatus[MENU_QMDELAY][0] = 27;
	MenuStatus[MENU_QMDELAY][1] = 2;
	MenuStatus[MENU_QMDELAY][2] = 28;
	MenuStatus[MENU_QMDELAY][3] = 2;
	MenuStatus[MENU_QMPHASE][0] = 27;
	MenuStatus[MENU_QMPHASE][2] = 28;

	MenuStatus[MENU_QMTHRESHOLDS][0] = 27;
	MenuStatus[MENU_QMTHRESHOLDS][1] = 49;


	for (int i=0;i<5;i++)
	{
		thres_low[i] = 10;						// QM thresholds -> 10%
		thres_mdl[i] = 50;						// QM thresholds -> 50%
		thres_up[i]  = 90;						// QM thresholds -> 90%
		thres_type[i] = 49;						// QM thresholds -> percent
	}

	// Display settings
	//ColorPalette      = 0;						// standard colors
	GridColorArrayPos = 1;                                          	// Normal Grid 33 %
	GridColor_Val     = GridColorArray[ColorPalette][GridColorArrayPos];    // Grid Color

	//BF not used GridColorArrayPos_Delayed = 1;                           	// Delayed Grid 33 %
	//BF not used GridColor_Val_Delayed     = 0x15;                        	// GridColore Gray

 	MenuStatus[MENU_DISPLAY][0] = BTN_OFF;                                  // Display - Persist off
	MenuStatus[MENU_DISPLAY][2] = GridColorArrayPos + 133;                  // Display - Grid 33%
	MenuStatus[MENU_DISPL_FFT][2] = GridColorArrayPos + 133;                // Display - Grid 33%
	MenuStatus[MENU_DISPLAY][4] = DRAW_FAST;				// Display - Draw Mode

	MenuStatus[MENU_DISPLAY][3] = 320;					// no display -> all channels off
	for(int i=0;i<4;i++)NoDisplay[i] = 0;					// no display -> all channels off

	if ( MenuStatus[MENU_DISPL_SETUP][3] != BTN_ON && MenuStatus[MENU_DISPL_SETUP][3] != BTN_OFF)
	MenuStatus[MENU_DISPL_SETUP][3] = BTN_OFF;

	// Aquire
	MenuStatus[MENU_ACQUIRE][0] = LOGA_OFF;					// Acquire - Logic		-> Off
	MenuStatus[MENU_ACQUIRE][1] = AVRG_OFF;					// Acquire - Average		-> Off
	MenuStatus[MENU_ACQUIRE][2] = FILT_OFF;					// Acquire - Noise Filter 	-> Off
	MenuStatus[MENU_ACQUIRE][3] = 42;					// Acquire - Interpolation	-> Linear
	ACQ_Average = 0;
	LA_active = 0;
	FilterType = PRO;


	// LEDs
	LED_ON[0] = 1;			                                        // Select Channel 1
	LED_ON[1] = 1;			                                        // Select Channel 2
	LED_ON[2] = 1;			                                        // Select Channel 3
	LED_ON[3] = 1;			                                        // Select Channel 4
	LED_ON[4] = 0;			                                        // Select Channel Math
	LED_ON[5] = 1;			                                        // General
	LED_ON[6] = 0;			                                        // Cursor
	LED_ON[7] = 0;			                                        // Quick Measure
	LED_ON[8] = 1;			                                        // Edge
	LED_ON[9] = 0;			                                        // Pattern - Not Used
	LED_ON[10] = 0;			                                        // Pulse Width
	LED_ON[11] = 0;			                                        // More - Not Used
	LED_ON[12] = 1;			                                        // Run/Stop Green
	LED_ON[13] = 0;			                                        // Run/Stop Red
	LED_ON[14] = 0;			                                        // Single Red
//	LED_ON[15] = 0;			                                        // Single Green

	if (MenuStatus[MENU_TRIGGERSUB][3] == 126)
	LED_ON[15] = 1;
	else
	LED_ON[15] = 0;

	S1Ptr = SIGNAL1;	// pointer to signal 1
	S2Ptr = SIGNAL2;	// pointer to signal 2
	S3Ptr = SIGNAL3;	// pointer to signal 3
	S4Ptr = SIGNAL4;	// pointer to signal 4
	SMPtr = SIGNALM;	// pointer to signal math

	RemovePlane |= 0x1F;
	
	ClearPlanes();
		
}
//#####################################################################################################################################
/* BF del not used anymore
char Hardware::SearchZero(char channel, char level, int *DAC_Offset, int *ZeroSign)
{
	
	int lcnt = 0;
	//BF del int lcnt2 = 0;
	unsigned long buflong = 0, buflong1 = 0;//, buflong2 = 0;
	//char is_running = 1;

	
	lcnt = 0;
	DAC_Offset[0] = 0x2000;		//DAC_Center
	//is_running = 1;
	
	SetDacOffset(channel);
	SetSwitches(channel, level);
	
	triggering = 0;								
	ctrl_reg = 0x0083;							        // Trigger_Master / Trigger_INT / Free Run  / Zero Line search bit
	if (NumberOfChannels == 2) adc_ctrl_reg = 0x00C0;				// Disable Trigger sources and remove the master bits
	else  adc_ctrl_reg = 0x0000;						        // Remove the master bits
	
	switch (channel)
	{
		case 1 : adc_ctrl_reg |= 0x0100; break;                     // Set channel 1 Master bit
		case 2 : adc_ctrl_reg |= 0x0200; break;                     // Set channel 2 Master bit
		case 3 : adc_ctrl_reg |= 0x0400; break;                     // Set channel 3 Master bit
		case 4 : adc_ctrl_reg |= 0x0800; break;                     // Set channel 4 Master bit
	}

	SetupADC();
	
	nr_delay(100);
	
	ctrl_reg = 0x0183;                                               // Add zero_line_adj
	
	SetupADC();

	buflong = 0x00000000;
	if (channel < 3)	// Channel 1 & 2
	{
		
		while (1 == 1)
		{
			data_adr->np_piodata = 0x01;
			
			buflong = READADC(1);
			//printf("buflong %8x %d\n", buflong, buflong);
			if ((buflong & 0x00008000) == 0x00008000)
			{
			
				buflong1 = READADC(1) & 0x3FFF;
							
				ZeroSign[0] = (int) (buflong1 - DAC_Center);		// Wertübergabe an NIOS
			
		//          printf("buflong_ch1 %8x %d\n", buflong, buflong);
		          	//printf("buflong1 %8x %d\n", buflong1, buflong1);
				printf("Channel %d ZeroSign %d\n\r", channel, ZeroSign[0]);	
				break;
			}
			
			data_adr->np_piodata = 0x00;
			lcnt++;
			
			if (lcnt == 50000) break;
		}
	}
	else	// Channel 3 & 4
	{
		lcnt = 0;
		while (1 == 1)		
		{
			data_adr->np_piodata = 0x01;

			buflong = READADC(3);

			buflong = READADC(1);	
			
			if ((buflong & 0x00008000) == 0x00008000)
			{
				buflong1 = READADC(3) & 0x3FFF;
								
				ZeroSign[0] = (int)buflong1 ;	//(buflong1 - DAC_Center);//BF test
				
				printf("Channel %d ZeroSign %d\n\r", channel, ZeroSign[0]);	
				break;
			}
			
			data_adr->np_piodata = 0x00;
			lcnt++;
			if (lcnt == 50000) break;
		}
	}
	lcnt = 0;
	data_adr->np_piodata = 0x00;

	ctrl_reg = 0x0083;	// Trigger_Master / Trigger_INT / FreeRun bit  /
	SetupADC();


	return 0;
}
*/
//#####################################################################################################################################
/* BF del not used anymore
char Hardware::SearchZeros(void)
{
	char IsSearching = true;
	int searchcnt = 0;
	char lChannel_1_bak, lChannel_2_bak, lChannel_3_bak, lChannel_4_bak;
	
	if ((Search_Mode == false) && (Search_Auto == false)) return 0;

	Stop_Record();
	AutoTimerOff = true;
	
	//reset_watchdog->np_piodata = 0x00;						// Disable WatchDog
	#ifdef _Debug_FindZero_
	printf("We start searching\n");
	#endif
		
	DoDisableUARTInterrupt();
	DoDisableADCInterrupt();
	
	//    if (Search_Auto == false)
	//    {
		Display::DRAWROUNDBUTTON(230, 180, 180, 80, 0, 0);
		Display::TEXTOUTxvbig("Searching zero lines.", 247, 192, 1, UI_Plane2);
		Display::TEXTOUTxvbig("Remove all inputs.", 247, 212, 1, UI_Plane2);
		Display::TEXTOUTxvbig("Can take up to 1 min.", 247, 232, 1, UI_Plane2);
	//    }
	
	// Backup old vars
	lChannel_1_bak = Channel_1_Active;
	lChannel_2_bak = Channel_2_Active;
	lChannel_3_bak = Channel_3_Active;
	lChannel_4_bak = Channel_4_Active;
	
	RealTimebase_bak  = RealTimebase;
	SIGNALFaktor_idx_bak   = SIGNALFaktor_idx;
	SIGNAL_StartFr_idx_bak = SIGNAL_StartFr_idx;
	timebase_reg_bak       = timebase_reg;
	MainTimebase_bak       = MainTimebase;
	Run_bak                = Run;
	SingleShot_bak         = SingleShot;
	
	triggering_bak   = triggering;
	ctrl_reg_bak     = ctrl_reg;
	adc_ctrl_reg_bak = adc_ctrl_reg;
	
	// backup settings
	CH1_DAC_Offset_bak = CH1_DAC_Offset;
	CH2_DAC_Offset_bak = CH2_DAC_Offset;
	CH3_DAC_Offset_bak = CH3_DAC_Offset;
	CH4_DAC_Offset_bak = CH4_DAC_Offset;
	
	CH1_DAC_Offset = DAC_Center;	//Range middle
	CH2_DAC_Offset = DAC_Center;
	CH3_DAC_Offset = DAC_Center;
	CH4_DAC_Offset = DAC_Center;
	
	
	Channel_1_Active = true;
	Channel_2_Active = true;
	
	if (NumberOfChannels > 2)
	{
		Channel_3_Active = true;
		Channel_4_Active = true;
	}
	
	Run = 0;
	//   SingleShot = 1;
	
	if (adc_started)
	{
		while (acq_ready->np_piodata == 0x01)
		{}
		adc_started = false;
	}
	
	RealTimebase = 4;                                          // 50 nS
	SIGNALFaktor_idx = 0;                                           // zoom factor 0
	SIGNAL_StartFr_idx = 0;                                         // running. so 0
	
	timebase_reg = 0xFFFFFFFF;                                      // real timebase 50ns (1GSa/s)
	MainTimebase = 4;                                           // Displayed timebase is 50ns
	
	// start condition made -> start searching

	searchcnt = 0;
	IsSearching = true;
	while (IsSearching)
	{
		searchcnt++;
		if (searchcnt == 3) break;
	
		IsSearching = SearchZero(1, 9, &CH1_DAC_Offset, &DAC_Correction[0][0]);	//channel 1 correction for 1er Ranges
	}
	searchcnt = 0;
	IsSearching = true;
	while (IsSearching)
	{
		searchcnt++;
		if (searchcnt == 3) break;
		IsSearching = SearchZero(1, 10, &CH1_DAC_Offset, &DAC_Correction[0][1]);//channel 1 correction for 2er Ranges
	}
	searchcnt = 0;
	IsSearching = true;
	while (IsSearching)
	{
		searchcnt++;
		if (searchcnt == 3) break;
		IsSearching = SearchZero(1, 11, &CH1_DAC_Offset, &DAC_Correction[0][2]);//channel 1 correction for 5er Ranges
	}
	searchcnt = 0;
	IsSearching = true;
	while (IsSearching)
	{
		searchcnt++;
		if (searchcnt == 3) break;
		IsSearching = SearchZero(2, 9, &CH2_DAC_Offset, &DAC_Correction[1][0]);	//channel 2 correction for 1er Ranges
	}
	searchcnt = 0;
	IsSearching = true;
	while (IsSearching)
	{
		searchcnt++;
		if (searchcnt == 3) break;
		IsSearching = SearchZero(2, 10, &CH2_DAC_Offset, &DAC_Correction[1][1]);//channel 2 correction for 2er Ranges
	}
	searchcnt = 0;
	IsSearching = true;
	while (IsSearching)
	{
		searchcnt++;
		if (searchcnt == 3) break;
		IsSearching = SearchZero(2, 11, &CH2_DAC_Offset, &DAC_Correction[1][2]);//channel 2 correction for 5er Ranges
	}
	
	if (NumberOfChannels > 2)
	{
		searchcnt = 0;
		IsSearching = true;
		while (IsSearching)
		{
			searchcnt++;
			if (searchcnt == 3) break;
			IsSearching = SearchZero(3, 9, &CH3_DAC_Offset, &DAC_Correction[2][0]);//channel 3 correction for 1er Ranges
		}
		searchcnt = 0;
		IsSearching = true;
		while (IsSearching)
		{
			searchcnt++;
			if (searchcnt == 3) break;
			IsSearching = SearchZero(3, 10, &CH3_DAC_Offset, &DAC_Correction[2][1]);//channel 3 correction for 2er Ranges
		}
		searchcnt = 0;
		IsSearching = true;
		while (IsSearching)
		{
			searchcnt++;
			if (searchcnt == 3) break;
			IsSearching = SearchZero(3, 11, &CH3_DAC_Offset, &DAC_Correction[2][2]);//channel 3 correction for 5er Ranges
		}
		searchcnt = 0;
		IsSearching = true;
		while (IsSearching)
		{
			searchcnt++;
			if (searchcnt == 3) break;
			IsSearching = SearchZero(4, 9, &CH4_DAC_Offset, &DAC_Correction[3][0]);//channel 4 correction for 1er Ranges
		}
		searchcnt = 0;
		IsSearching = true;
		while (IsSearching)
		{
			searchcnt++;
			if (searchcnt == 3) break;
			IsSearching = SearchZero(4, 10, &CH4_DAC_Offset, &DAC_Correction[3][1]);//channel 4 correction for 2er Ranges
		}
		searchcnt = 0;
		IsSearching = true;
		while (IsSearching)
		{
			searchcnt++;
			if (searchcnt == 3) break;
			IsSearching = SearchZero(4, 11, &CH4_DAC_Offset, &DAC_Correction[3][2]);//channel 4 correction for 5er Ranges
		}
	}
		
	//restore settings
	Channel_1_Active = lChannel_1_bak;
	Channel_2_Active = lChannel_2_bak;
	Channel_3_Active = lChannel_3_bak;
	Channel_4_Active = lChannel_4_bak;
	
	RealTimebase  = RealTimebase_bak;
	SIGNALFaktor_idx   = SIGNALFaktor_idx_bak;
	SIGNAL_StartFr_idx = SIGNAL_StartFr_idx_bak;
	timebase_reg       = timebase_reg_bak;
	MainTimebase   = MainTimebase_bak;
	Run               = Run_bak;
	SingleShot         = SingleShot_bak;
	
	triggering   = triggering_bak;
	ctrl_reg     = ctrl_reg_bak;
	adc_ctrl_reg = adc_ctrl_reg_bak;
	
	CH1_DAC_Offset = CH1_DAC_Offset_bak;
	CH2_DAC_Offset = CH2_DAC_Offset_bak;
	CH3_DAC_Offset = CH3_DAC_Offset_bak;
	CH4_DAC_Offset = CH4_DAC_Offset_bak;
	
	
	Rotary_Steps = 0;
	UserIF::UserIF::ON_Zero_Channel_1();
	Rotary_Steps = 0;
	UserIF::UserIF::ON_Zero_Channel_2();
	
	
	SetSwitches(1, Selected_Voltage_CH1);
	SetSwitches(2, Selected_Voltage_CH2);
	
	SetDacOffset(1);
	SetDacOffset(2);
	
	//4 channel version
	if (NumberOfChannels == 4)
	{
		Rotary_Steps = 0;
		UserIF::UserIF::ON_Zero_Channel_3();
		Rotary_Steps = 0;
		UserIF::UserIF::ON_Zero_Channel_4();
	
		SetSwitches(3, Selected_Voltage_CH3);
		SetSwitches(4, Selected_Voltage_CH4);

		SetDacOffset(3);
		SetDacOffset(4);
	}
	
	SetupADC();
	
	SingleShot = 0;
	Run = 1;
	

   	config_changed = true;

	Display::DRAWROUNDBUTTON(230, 180, 180, 80, 0, 1);
	Display::TEXTOUTxvbig("Searching zero lines.", 247, 192, 0, UI_Plane2);
	Display::TEXTOUTxvbig("Remove all inputs.", 247, 212, 0, UI_Plane2);
	Display::TEXTOUTxvbig("Can take up to 1 min.", 247, 232, 0, UI_Plane2);

	
	AutoTimerOff = false;
	
	DoEnableADCInterrupt();
	DoEnableUARTInterrupt();
	
	acq_ready->np_pioedgecapture = 0;
	Start_Record();
	
	//reset_watchdog->np_piodata = 0x01;						// Enable WatchDog
	
	return 0;
}
*/
//#####################################################################################################################################

void Hardware::DoEnableKeyInterrupt(void)							// Enable Keyboard service routine
{
	key_int->np_pioedgecapture = 0x00; 							// clear all existing IRQ conditions
	key_int->np_piodirection = 0x00;							// set all bits to input
	key_int->np_piointerruptmask = 0x01;							// enable Keyboard IRQ

	key_reset->np_piodata = 0;								// Reset Keyboard
	nr_delay(2);
	key_reset->np_piodata = 1;
	
	key_int->np_pioedgecapture = 0x00; 							// clear all existing IRQ conditions	

	nr_installuserisr(na_key_interrupt_irq,ISR_KEY,(int)key_int);	// Install ISR for Keyboard
#ifdef _Debug_IRQ_
	if (Debug_Mode) printf("\nKEY interrupt enabled.\n"); 							// print on console
#endif
}
//#####################################################################################################################################

void Hardware::DoDisableKeyInterrupt(void)							// Disable Keyboard I/O service routine
{
	nr_installuserisr(na_key_interrupt_irq,0,0); 					// Install empty routine for Keyboard irq
	key_int->np_piointerruptmask = 0x00;							// disable all IRQs
}
//#####################################################################################################################################

void Hardware::ISR_KEY(int context)									// Keyboard Interrupt subroutine
{
	int KeyData = key->np_piodata;									// Get interrupt Keyboad data

	key_reset->np_piodata = 0;									// Reset Keyboard
	nr_delay(2);
	key_reset->np_piodata = 1;
	key_int->np_pioedgecapture = 0;									// clear IRQ conditions	
	
	Keyboard_mem = KeyData;
	Keyboard_Changed = 1;

	UI_request = 1;	

	//printf("\r\nKEY interrupt occured %x(%d).\r\n",KeyData,KeyData ); 				// print on console
}
//#####################################################################################################################################
//BF register docu by JK
/*
	MSB	adc_ctrl_reg		  		MSB		ctrl_reg
	---------------------------			-----------------------------------------
	8 - ?						8 - ?
	4 - ?						4 - ?
	2 - ?						2 - 1 = Holdoff enable
	1 - ?						1 - 1 = Pulswidth enable
	---------------------------			-----------------------------------------
	8 - 1 = Ch 4 Masterbit				8 - 1 = Pulsewidth Range
	4 - 1 = Ch 3 Masterbit				4 - 1 = Pulsewidth less than
	2 - 1 = Ch 2 Masterbit				2 - 1 = Pulsewidth greater than
	1 - 1 = Ch 1 Masterbit				1 - ? Zero adjust?
	---------------------------			-----------------------------------------
	8 - 2 Ch = 1 / 4 Ch = 0				8 - 1 = Trigger Master enable
	4 - 2 Ch = 1 / 4 Ch = 0				4 - 0 = Normal / 1 = Auto
	2 - ?						2 - ?
	1 - ?						1 - ?
	---------------------------			-----------------------------------------
	8 - 1 = Triggersource Ch 4			8 - ?
	4 - 1 = Triggersource Ch 3			4 - 0 = falling / 1 = rising edge
	2 - 1 = Triggersource Ch 2			2 - 0 = external / 1 = internal trigger
	1 - 1 = Triggersource Ch 1			1 - 1 ? search zero bit?
	---------------------------			-----------------------------------------
	LSB						LSB

*/
void Hardware::SetupTrigger(void)
{


	//---------------------------------------------------
	//		Initialization
	//---------------------------------------------------

	Selected_Trigger_Source_Old = Selected_Trigger_Source;

	if (NumberOfChannels == 4)
	adc_ctrl_reg &= 0xFF00;
	else	
	adc_ctrl_reg &= 0xFFC0;		//0xFFF0;


    //ctrl_reg &= 0xC17F;  // remove holdoff and pulse bits
    	ctrl_reg &= 0xC17D;  // remove holdoff and pulse bits and internal bit


	//BF switch off trigger for USTB
	if (USTB_Mode != USTB_OFF)// || FFT_Mode != FFT_OFF)
	{
		adc_ctrl_reg |= 0x0001;
		ctrl_reg |= 0x0040;
		triggering = 0;
		//timebase_reg = 0xFFFFFFFF;      //set real timebase 50ns (1GSa/s) -> only for USTB not for FFT
		SetupADC();
		return;
	}

	//---------------------------------------------------
	//		Holdoff
	//---------------------------------------------------
	if (HoldOff_Value > 0)
	{
		//trig_holdoff_reg = (unsigned long) (HoldOff.Read_Value() / (float) 0.000000008);
		trig_holdoff_reg = (unsigned long) (HoldOff.Read_Value() * 125000000);
		ctrl_reg |= 0x2000;
	}
	else
	trig_holdoff_reg = 0x00000000;



	//---------------------------------------------------
	//		Edge Triggering
	//---------------------------------------------------

	if (TriggerWay == TRIG_EDGE)	//BF own logic for Edge / Pulse Width
    	{

		if (MenuStatus[MENU_TRIGGEREDGE][1] == 137)	//Source = channel 1
		{
			triggering = 1;
			ctrl_reg |= 0x0002;
			adc_ctrl_reg |= 0x0001;
			
			if (Trigger_Pos_CH1 < GRID_HEIGHT && Trigger_Pos_CH1 > 0)
			{	
				trg_val_CHI_reg = (int)((float)(Trigger_Pos_CH1 - (GRID_HEIGHT/2)) / ScaleFactor[Selected_Voltage_CH1][GainIdx]) + ADC_ZERO;	//Stefan
				trg_val_CHI_reg	= 255 - trg_val_CHI_reg;
			}	
	
			if (MenuStatus[MENU_TRIGGEREDGE][0] == 2)	//rising
			{ 	
				ctrl_reg |= 0x0004;
				if (Trigger_Pos_CH1 > ZeroLevelCH1)	//BF correction
				trg_val_CHI_reg += 10;			//BF correction
			}
			else if (MenuStatus[MENU_TRIGGEREDGE][0] == 3)	//falling
			{ 	
				ctrl_reg &= 0xFFFB;

				if (Trigger_Pos_CH1 < ZeroLevelCH1)	//BF correction
				trg_val_CHI_reg -= 15;			//BF correction
				else
				trg_val_CHI_reg -= 5;			//BF correction
			}
		}
		else if (MenuStatus[MENU_TRIGGEREDGE][1] == 138)	//Source = channel 2
		{
			triggering = 2;
			ctrl_reg |= 0x0002;
			adc_ctrl_reg |= 0x0002;
						
			if (Trigger_Pos_CH2 < GRID_HEIGHT && Trigger_Pos_CH2 > 0)
			{	
				trg_val_CHII_reg = (int)((float)(Trigger_Pos_CH2 - (GRID_HEIGHT/2)) / ScaleFactor[Selected_Voltage_CH2][GainIdx]) + ADC_ZERO;	//Stefan
				trg_val_CHII_reg = 255 - trg_val_CHII_reg;
			}
			
			if (MenuStatus[MENU_TRIGGEREDGE][0] == 2)	//rising
			{ 
				ctrl_reg |= 0x0004;
				if (Trigger_Pos_CH2 > ZeroLevelCH2)	//BF correction
				trg_val_CHII_reg += 10;			//BF correction
 			}
			else if (MenuStatus[MENU_TRIGGEREDGE][0] == 3)	//falling
			{ 
				ctrl_reg &= 0xFFFB;
				if (Trigger_Pos_CH2 < ZeroLevelCH2)	//BF correction
				trg_val_CHII_reg -= 15;			//BF correction
				else
				trg_val_CHII_reg -= 5;			//BF correction
			 }
		}
		else if (MenuStatus[MENU_TRIGGEREDGE][1] == 139)	//Source = channel 3
		{
			triggering = 3;
			ctrl_reg |= 0x0002;
			adc_ctrl_reg |= 0x0004;
					
			if (Trigger_Pos_CH3 < GRID_HEIGHT && Trigger_Pos_CH3 > 0)
			{	
				trg_val_CHIII_reg = (int)((float)(Trigger_Pos_CH3 - (GRID_HEIGHT/2)) / ScaleFactor[Selected_Voltage_CH3][GainIdx]) + ADC_ZERO;	//Stefan
				trg_val_CHIII_reg = 255 - trg_val_CHIII_reg;
			}	
			
			if (MenuStatus[MENU_TRIGGEREDGE][0] == 2)	//rising
			{ 
				ctrl_reg |= 0x0004;
				if (Trigger_Pos_CH3 > ZeroLevelCH3)	//BF correction
				trg_val_CHIII_reg += 10;		//BF correction
			}
			else if (MenuStatus[MENU_TRIGGEREDGE][0] == 3)	//falling
			{ 
				ctrl_reg &= 0xFFFB;
				if (Trigger_Pos_CH3 < ZeroLevelCH3)	//BF correction
				trg_val_CHIII_reg -= 15;		//BF correction
				else
				trg_val_CHIII_reg -= 5;			//BF correction
			}
		}
		else if (MenuStatus[MENU_TRIGGEREDGE][1] == 140)	//Source = channel 4
		{
			triggering = 4;
			ctrl_reg |= 0x0002;
			adc_ctrl_reg |= 0x0008;
					
			if (Trigger_Pos_CH4 < GRID_HEIGHT && Trigger_Pos_CH4 > 0)
			{	
				trg_val_CHIV_reg = (int)((float)(Trigger_Pos_CH4 - (GRID_HEIGHT/2)) / ScaleFactor[Selected_Voltage_CH4][GainIdx]) + ADC_ZERO;	//Stefan
				trg_val_CHIV_reg = 255 - trg_val_CHIV_reg;
			}

			if (MenuStatus[MENU_TRIGGEREDGE][0] == 2)	//rising
			{
			 	ctrl_reg |= 0x0004;
				if (Trigger_Pos_CH4 > ZeroLevelCH4)	//BF correction
				trg_val_CHIV_reg += 10;			//BF correction
 			}
			else if (MenuStatus[MENU_TRIGGEREDGE][0] == 3)	//falling
			{
				ctrl_reg &= 0xFFFB; 
				if (Trigger_Pos_CH4 < ZeroLevelCH4)	//BF correction
				trg_val_CHIV_reg -= 15;			//BF correction
				else
				trg_val_CHIV_reg -= 5;			//BF correction
			}
		}

//BF del		if (MenuStatus[MENU_TRIGGEREDGE][2] == 1)	//Source = extern
		else if (MenuStatus[MENU_TRIGGEREDGE][1] == 141)	//Source = extern #019
		{
			triggering = 5;
						
			ctrl_reg &= 0xFFFD;
			adc_ctrl_reg &= 0xFFF0;
		
			if (MenuStatus[MENU_TRIGGEREDGE][0] == 2) ctrl_reg |= 0x0004;		//rising
			else if (MenuStatus[MENU_TRIGGEREDGE][0] == 3) ctrl_reg &= 0xFFFB;	//falling
		
			SwitchesTB = 0x00;
/*BF test
			if (MenuPopupStatus[8][0] == 3) SwitchesTB = 0x40;		//LF Reject 
			else if (MenuPopupStatus[8][1] == 3) SwitchesTB = 0xC0;		//HF Reject
			else if (MenuPopupStatus[8][2] == 3) SwitchesTB = 0x80;		//Line
*/	
/*BF del 09.08.2011 
			//BF changed due to Juergens recherche	
			if (MenuPopupStatus[8][0] == 3) SwitchesTB = 0xC0;		//LF Reject 
			else if (MenuPopupStatus[8][1] == 3) SwitchesTB = 0x80;		//HF Reject
			else if (MenuPopupStatus[8][2] == 3) SwitchesTB = 0x40;		//Line


			if (MenuStatus[MENU_TRIGGERMODE][1] == 95) SwitchesTB |= 0x04;	//AC/DC
			else SwitchesTB &= 0xFB;
										
			SetSwitches(5, SwitchesTB);

			if (MenuPopupStatus[8][2] == 3)					//Line
			ext_trg_val_reg = 0x80;						//BF set to zero
			else
			ext_trg_val_reg = ExtTriggerLevel[Trigger_Pos_CHE];
*/
// BF new coding from JK -> not tested!!!
			//BF changed due to Juergens recherche	; new 05.09.11
			if (MenuPopupStatus[8][0] == 3) SwitchesTB = 0x80;		//LF Reject 
			else if (MenuPopupStatus[8][1] == 3) SwitchesTB = 0xC0;		//HF Reject
			else if (MenuPopupStatus[8][2] == 3) SwitchesTB = 0x40;		//Line


			if (MenuStatus[MENU_TRIGGERMODE][1] == 95) SwitchesTB |= 0x04;	//AC/DC
			else SwitchesTB &= 0xFB;
										
			SetSwitches(5, SwitchesTB);

			if (MenuPopupStatus[8][2] == 3)					//Line
			{
				//ext_trg_val_reg = 125;				//BF set to zero , JK 61 + 0x40
				ext_trg_val_reg = 128;					// JK 61 + 3 * ca.39mV + 0x40 = +115mV an U6/4 11.9.11
				ctrl_reg |= 0x0004;					// JK forced to rising edge for stable triggering
			}
			else
			ext_trg_val_reg = Trigger_Pos_CHE + 0x40;

			//printf("Trigger_Pos_CHE %d\n\r", Trigger_Pos_CHE);
			//printf("trigger extern level %d \n\r", ext_trg_val_reg);

			serdata->np_piodata = ext_trg_val_reg;
			serstartpwm->np_piodata = 1;
			serstartpwm->np_piodata = 0;
		}
        
//BF del		if (MenuStatus[MENU_TRIGGEREDGE][3] == 1)			//TV Ch1
		else if (MenuStatus[MENU_TRIGGEREDGE][1] == 142)		//TV Ch1 #019
		{
			triggering = 5;
						
			ctrl_reg &= 0xFFFD;
			adc_ctrl_reg &= 0xFFF0;
		
			if (MenuStatus[MENU_TRIGGEREDGE][0] == 2) ctrl_reg |= 0x0004;		//rising/falling
			else if (MenuStatus[MENU_TRIGGEREDGE][0] == 3) ctrl_reg &= 0xFFFB;	//rising/falling
		
			SwitchesTB = 0x00;
			
			if (MenuPopupStatus[11][0] == 3) SwitchesTB = 0x01;		//BF vertical sync
			else if (MenuPopupStatus[11][1] == 3) SwitchesTB = 0x02;	//BF composit sync
		
			if (MenuStatus[MENU_TRIGGERMODE][1] == 95) SwitchesTB |= 0x04;		//coupling
			else SwitchesTB &= 0xFB;
										
			SetSwitches(5, SwitchesTB);
			//ext_trg_val_reg = ExtTriggerLevel[Trigger_Pos_CHE];
			ext_trg_val_reg = Trigger_Pos_CHE + 0x40;			// JK
		
			serdata->np_piodata = ext_trg_val_reg;
			serstartpwm->np_piodata = 1;
			serstartpwm->np_piodata = 0;
		}
    	}


	//---------------------------------------------------
	//		Pulse Width Triggering
	//---------------------------------------------------

	if (TriggerWay == TRIG_PULS)	//BF pulse width triggering #021
	{
		//printf("\r\npulse width triggering active\r\n");

		adc_ctrl_reg &= 0xFFF0;
		ctrl_reg &= 0xC000;	//0xC130	
	
		//ctrl_reg |= 0x0080;	//set master bit???
		ctrl_reg |= 0x1000;	//enable pulsewidth
		ctrl_reg |= 0x0002;	//internal

		//BF set source
		if (MenuStatus[MENU_PULSEWIDTH][0] == 137) 					//Channel 1 
		{ 	triggering = 1; adc_ctrl_reg |= 0x0001;      				// JK
			if (Trigger_Pos_CH1 < GRID_HEIGHT && Trigger_Pos_CH1 > 0)        	// added JK 01.09.11
			{	
				trg_val_CHI_reg = (int)((float)(Trigger_Pos_CH1 - (GRID_HEIGHT/2)) / ScaleFactor[Selected_Voltage_CH1][GainIdx]) + ADC_ZERO;	//Stefan
				trg_val_CHI_reg	= 255 - trg_val_CHI_reg;
			}	
		}  
		else if (MenuStatus[MENU_PULSEWIDTH][0] == 138)  				//Channel 2 
		{ 	triggering = 2; adc_ctrl_reg |= 0x0002; 
			if (Trigger_Pos_CH2 < GRID_HEIGHT && Trigger_Pos_CH2 > 0)		// added JK 01.09.11
			{	
				trg_val_CHII_reg = (int)((float)(Trigger_Pos_CH2 - (GRID_HEIGHT/2)) / ScaleFactor[Selected_Voltage_CH2][GainIdx]) + ADC_ZERO;	//Stefan
				trg_val_CHII_reg = 255 - trg_val_CHII_reg;
			}
		}
		else if (MenuStatus[MENU_PULSEWIDTH][0] == 139)  				//Channel 3 
		{ 	triggering = 3; adc_ctrl_reg |= 0x0004;
			if (Trigger_Pos_CH3 < GRID_HEIGHT && Trigger_Pos_CH3 > 0)		// added JK 01.09.11
			{	
				trg_val_CHIII_reg = (int)((float)(Trigger_Pos_CH3 - (GRID_HEIGHT/2)) / ScaleFactor[Selected_Voltage_CH3][GainIdx]) + ADC_ZERO;	//Stefan
				trg_val_CHIII_reg = 255 - trg_val_CHIII_reg;
			}	
		}
		else if (MenuStatus[MENU_PULSEWIDTH][0] == 140) 				//Channel 4 
		{ 	triggering = 4; adc_ctrl_reg |= 0x0008;
			if (Trigger_Pos_CH4 < GRID_HEIGHT && Trigger_Pos_CH4 > 0)		// added JK 01.09.11
			{	
				trg_val_CHIV_reg = (int)((float)(Trigger_Pos_CH4 - (GRID_HEIGHT/2)) / ScaleFactor[Selected_Voltage_CH4][GainIdx]) + ADC_ZERO;	//Stefan
				trg_val_CHIV_reg = 255 - trg_val_CHIV_reg;
			}
		}
	//BF does not work correct! Works as edge triggering!		
		else if (MenuStatus[MENU_PULSEWIDTH][0] == 141)  				//external 
		{
			triggering = 5; 
			
			ctrl_reg &= 0xFFFD; 							// delete internal bit
		/*
			//SwitchesTB = 0x00;
			SwitchesTB = 0xC0;
	
			if (MenuStatus[MENU_TRIGGERMODE][1] == 95) SwitchesTB |= 0x04;		//coupling
			else SwitchesTB &= 0xFB;
										
			SetSwitches(5, SwitchesTB);
	
			serdata->np_piodata = 0x80;	//BF level 0
	
			serstartpwm->np_piodata = 1;
			serstartpwm->np_piodata = 0;
		*/
		}  // JK ? add. menu item "source extern" necessary??
	
		//BF calculate upper pulse width threshold for width range (> <)
		if (MenuStatus[MENU_PULSEWIDTH][2] == 3)
		{ trig_range_reg -= trig_width_reg;}
		else
		{ trig_range_reg = 0; }
		
	
		// JK set kind of pulse width
		if (MenuStatus[MENU_PULSEWIDTH][2] == 1) ctrl_reg |= 0x0200;			//less than
		else if (MenuStatus[MENU_PULSEWIDTH][2] == 2) ctrl_reg |= 0x0400;		//greater than
		else if (MenuStatus[MENU_PULSEWIDTH][2] == 3) ctrl_reg |= 0x0800;		//range between
	
	}
	


	//--------------------------------------------
	//		Trigger Mode
	//--------------------------------------------


	// set trigger mode
	if ((MenuStatus[MENU_TRIGGERMODE][0] == TRIG_AUTO) && (TriggerWay == TRIG_EDGE))	// auto mode
	{ ctrl_reg |= 0x0040; }	
	else if((MenuStatus[MENU_TRIGGERMODE][0] == TRIG_COMB) && (TriggerWay == TRIG_EDGE))   //combi-trigger by Stefan
	{
		if (MainTimebase<22)	//enable normal mode for timebase < 50ms
		{
			ctrl_reg &= 0xFFBF;
			noTriggerTime      = 0;	//reset time-measurement
			CombiTriggerStatus = 0;	//Starten im Normal-Modus
		}
		else
		{ ctrl_reg |= 0x0040; }		//Zeitbasis zu groß->immer Auto-Modus
		
	}
	else									// normal mode
	{ ctrl_reg &= 0xFFBF; }


	Selected_Trigger_Source = triggering;

	SetupADC();
}
//#####################################################################################################################################
// switch single LED on and send LED array to serial port
void Hardware::Set_LED(int LED)
{
	LED_ON[LED] = 1;
	Send_LED();
}

// switch single LED off and send LED array to serial port
void Hardware::Reset_LED(int LED)
{
	LED_ON[LED] = 0;
	Send_LED();
}
/*
void Hardware::Clear_LED(void)
{
	int ct;
	
	for (ct = 0; ct < 13;ct++) LED_ON[ct] = 0;
}
*/
// send LED array to serial port
void Hardware::Send_LED(void)
{
	int led_value = 0xFFFF;
	
	if (LED_ON[0] == 1) led_value = led_value & 0xBFFF;		// Select Channel 1
	if (LED_ON[1] == 1) led_value = led_value & 0xEFFF;		// Select Channel 2
 	if (LED_ON[2] == 1) led_value = led_value & 0xFEFF;		// Select Channel 3
	if (LED_ON[3] == 1) led_value = led_value & 0x7FFF;		// Select Channel 4

	if (LED_ON[4] == 1) led_value = led_value & 0xDFFF;		// Select Channel Math
	if (LED_ON[5] == 1) led_value = led_value & 0xFDFF;		// General
	if (LED_ON[6] == 1) led_value = led_value & 0xFBFF;		// Cursor						
	if (LED_ON[7] == 1) led_value = led_value & 0xF7FF;		// Quick Measure
	if (LED_ON[8] == 1) led_value = led_value & 0xFFBF;		// Edge
	if (LED_ON[9] == 1) led_value = led_value & 0xFFFD;		// Trigger waiting
	if (LED_ON[10] == 1) led_value = led_value & 0xFF7F;		// Pulse Width
	if (LED_ON[11] == 1) led_value = led_value & 0xFFFE;		// Trigger event occured 
	if (LED_ON[12] == 1) led_value = led_value & 0xFFDF;		// Run/Stop Green
	if (LED_ON[13] == 1) led_value = led_value & 0xFFEF;		// Run/Stop Red
	if (LED_ON[14] == 1) led_value = led_value & 0xFFF7;		// Single Red					
	if (LED_ON[15] == 1) led_value = led_value & 0xFFFB;		// Single Green
	
	serdata->np_piodata = led_value;
	serstartled->np_piodata = 0x01;
	serstartled->np_piodata = 0x00;	
#ifdef _Debug_	
	if (Debug_Mode) printf("LED VAL : %x \n", led_value);
#endif
}
//##########################################################################################################################################

void Hardware::DoEnableRotInterrupt(void)						// Enable service routine
{
	rot_int->np_pioedgecapture = 0x00; 						// clear all existing IRQ conditions
	rot_int->np_piodirection = 0x00;						// set all bits to input
	rot_int->np_piointerruptmask = 0x01;						// enable rotary IRQ

	key_reset->np_piodata = 0;
	nr_delay(2);
	key_reset->np_piodata = 1;

	rot_int->np_pioedgecapture = 0x00; 						// clear all existing IRQ conditions
	
	nr_installuserisr(na_rot_interrupt_irq,ISR_ROT,(int)rot_int);			// Install ISR for parallel I/Os

	Rotary_Steps = 0;								// BF reset rotary buffer

#ifdef _Debug_IRQ_
	if (Debug_Mode) printf("\nRot interrupt enabled.\n");  				// print on console
#endif	
}
//##########################################################################################################################################

void Hardware::DoDisableRotInterrupt(void)						// Disable parallel I/O service routine
{
	nr_installuserisr(na_rot_interrupt_irq,0,0); 					// Install empty routine for pio irq
	rot_int->np_piointerruptmask = 0x00;						// disable all IRQs
}
//##########################################################################################################################################

void Hardware::ISR_ROT(int context)							// Parallel I/O Interrupt subroutine
{
	int ct;
	int KeyData = key->np_piodata;								// Get interrupt data to asign respective ISR
	int Rot_Dir = KeyData & 0x000FFF;							// Get interrupt data to asign respective ISR

	Rotary_Switch = (KeyData & 0xFFF000) >> 12;

	//BF only draw signal with changed zerolevel
	if (((Rotary_Switch & 0x00000080) == 0x00000080) && Channel_1_Active) { ZL_changed = 1; }
	else if (((Rotary_Switch & 0x00000010) == 0x00000010) && Channel_2_Active) { ZL_changed = 2; }
	else if (((Rotary_Switch & 0x00000800) == 0x00000800) && Channel_3_Active) { ZL_changed = 3; }
	else if (((Rotary_Switch & 0x00000100) == 0x00000100) && Channel_4_Active) { ZL_changed = 4; }

//BF -> del	for (ct = 0; ct < 100; ct++){};
	
	rot_speed_read->np_piodata = 1;
	Rotary_Steps += (key->np_piodata & 0x000FFF);						// Get interrupt data to assign respective ISR
	rot_speed_read->np_piodata = 0;

	//printf("\nkeydata : %3x RotSW %3x RotDir %i RotaryDirec %i RotDirMem %i RotSpe : %i \n\n", key->np_piodata, Rotary_Switch, Rot_Dir, Rotary_Direction, Rotary_Direction_mem, Rotary_Steps);	

	key_reset->np_piodata = 0;
	for (ct = 0; ct < 100; ct++){};
	key_reset->np_piodata = 1;

	;
	//Rotary_Changed = 1;

	rot_int->np_pioedgecapture = 0;								// clear IRQ conditions		

	if (Rotary_Switch == Rot_Dir)
	Rotary_Direction = 1;
	else
	Rotary_Direction = 0;

/*BF del -> causes problems with QM cursor drawing
	ResetTimer3(TimerRotPeriod);
	//BF handle TB and voltage directly for better reaction
	if ((Rotary_Switch & 0x00000008) == 0x00000008) { UserIF::ON_Timebase(); RC_user_if = 1; Rotary_Steps = 0; }
	else if ((Rotary_Switch & 0x00000020) == 0x00000020 && Run) { UserIF::ON_Voltage_Channel_2(); Rotary_Steps = 0; }
	else if ((Rotary_Switch & 0x00000040) == 0x00000040 && Run) { UserIF::ON_Voltage_Channel_1(); Rotary_Steps = 0; }
	else if ((Rotary_Switch & 0x00000200) == 0x00000200 && Run) { UserIF::ON_Voltage_Channel_4(); Rotary_Steps = 0; }
	else if ((Rotary_Switch & 0x00000400) == 0x00000400 && Run) { UserIF::ON_Voltage_Channel_3(); Rotary_Steps = 0; }
	else { UI_request = 1; }
*/

	UI_request = 1;

//#ifdef _Debug_IRQ_
//    if (Debug_Mode) printf("RotSW %3x RotDir %i RotaryDirec %i RotDirMem %i RotSpe : %i \n", Rotary_Switch, Rot_Dir, Rotary_Direction, Rotary_Direction_mem, Rotary_Steps);	
//#endif
//UserIF::Rotary_Interface();

}
//##########################################################################################################################################
void Hardware::Zero_Levels_Center(void)	 
{
	char CH1_bak, CH2_bak, CH3_bak, CH4_bak;

	//if(Run) Hardware::Stop_Record();

	//backup channel status
	CH1_bak = Channel_1_Active;
	CH2_bak = Channel_2_Active;
	CH3_bak = Channel_3_Active;
	CH4_bak = Channel_4_Active;

	//backup zerolevels
	ZeroLevelCH1_bak = ZeroLevelCH1;
	ZeroLevelCH2_bak = ZeroLevelCH2;
	ZeroLevelCH3_bak = ZeroLevelCH3;
	ZeroLevelCH4_bak = ZeroLevelCH4;

	Virtual_ZeroLevelCH1_bak = Virtual_ZeroLevelCH1;
	Virtual_ZeroLevelCH2_bak = Virtual_ZeroLevelCH2;
	Virtual_ZeroLevelCH3_bak = Virtual_ZeroLevelCH3;
	Virtual_ZeroLevelCH4_bak = Virtual_ZeroLevelCH4;

	//backup triggerlevels
	Trigger_Pos_CH1_Old = Trigger_Pos_CH1;
	Trigger_Pos_CH2_Old = Trigger_Pos_CH2;
	Trigger_Pos_CH3_Old = Trigger_Pos_CH3;
	Trigger_Pos_CH4_Old = Trigger_Pos_CH4;


	//set zerolevels to the middle of the grid
	ZeroLevelCH1 = GRID_HEIGHT / 2;
	ZeroLevelCH2 = GRID_HEIGHT / 2;
	ZeroLevelCH3 = GRID_HEIGHT / 2;
	ZeroLevelCH4 = GRID_HEIGHT / 2;

	Virtual_ZeroLevelCH1 = 0;
	Virtual_ZeroLevelCH2 = 0;
	Virtual_ZeroLevelCH3 = 0;
	Virtual_ZeroLevelCH4 = 0;

	//channel have to be active to activate new settings
	Channel_1_Active = 1;
	Channel_2_Active = 1;

	//activate new settings
	Rotary_Steps = 0;
	UserIF::ON_Zero_Channel_1();
	Rotary_Steps = 0;
	UserIF::ON_Zero_Channel_2();

	Trigger_Pos_CH1    = GRID_HEIGHT/2;	
	Trigger_Pos_CH2    = GRID_HEIGHT/2;	


	if (NumberOfChannels == 4)	// 4 channel version
	{	
		Channel_3_Active = 1;
		Channel_4_Active = 1;

		//activate new settings
		Rotary_Steps = 0;
		UserIF::ON_Zero_Channel_3();
		Rotary_Steps = 0;
		UserIF::ON_Zero_Channel_4();

		Trigger_Pos_CH3    = GRID_HEIGHT/2;	
		Trigger_Pos_CH4    = GRID_HEIGHT/2;	
	}

	Hardware::SetupTrigger();

	//restore channel status
	Channel_1_Active = CH1_bak;
	Channel_2_Active = CH2_bak;
	Channel_3_Active = CH3_bak;
	Channel_4_Active = CH4_bak;

	nr_delay(200);

	if(!Run && !RC_request) SingleShot = 1;
	
	Hardware::Start_Record();

}
//##########################################################################################################################################
void Hardware::Zero_Levels_Restore(void)							// 
{
	char CH1_bak, CH2_bak, CH3_bak, CH4_bak;

	//if(Run) Hardware::Stop_Record();

	//backup channel status
	CH1_bak = Channel_1_Active;
	CH2_bak = Channel_2_Active;
	CH3_bak = Channel_3_Active;
	CH4_bak = Channel_4_Active;

	//restore zerolevels
	ZeroLevelCH1 = ZeroLevelCH1_bak;
	ZeroLevelCH2 = ZeroLevelCH2_bak;
	ZeroLevelCH3 = ZeroLevelCH3_bak;
	ZeroLevelCH4 = ZeroLevelCH4_bak;

	Virtual_ZeroLevelCH1 = Virtual_ZeroLevelCH1_bak;
	Virtual_ZeroLevelCH2 = Virtual_ZeroLevelCH2_bak;
	Virtual_ZeroLevelCH3 = Virtual_ZeroLevelCH3_bak;
	Virtual_ZeroLevelCH4 = Virtual_ZeroLevelCH4_bak;

	Trigger_Pos_CH1 = Trigger_Pos_CH1_Old;
	Trigger_Pos_CH2 = Trigger_Pos_CH2_Old;
	Trigger_Pos_CH3 = Trigger_Pos_CH3_Old;
	Trigger_Pos_CH4 = Trigger_Pos_CH4_Old;


	//channel have to be active to activate new settings
	Channel_1_Active = 1;
	Channel_2_Active = 1;

	//activate new settings
	Rotary_Steps = 0;
	UserIF::ON_Zero_Channel_1();
	Rotary_Steps = 0;
	UserIF::ON_Zero_Channel_2();

	if (NumberOfChannels > 2)	// 4 channel version
	{	
		Channel_3_Active = 1;
		Channel_4_Active = 1;

		//activate new settings
		Rotary_Steps = 0;
		UserIF::ON_Zero_Channel_3();
		Rotary_Steps = 0;
		UserIF::ON_Zero_Channel_4();
	}

	Hardware::SetupTrigger();

	//restore channel status
	Channel_1_Active = CH1_bak;
	Channel_2_Active = CH2_bak;
	Channel_3_Active = CH3_bak;
	Channel_4_Active = CH4_bak;

	nr_delay(200);

	if(!Run && !RC_request)SingleShot = 1;
	
	Hardware::Start_Record();

}
//###########################################################################################################################################
void Hardware::DoEnableUARTInterrupt(void)						// Enable service routine
{
	nr_installuserisr(na_uart1_irq, ISR_UART, (int)puart);				// Install ISR for UART

	puart->np_uartcontrol = np_uartcontrol_irrdy_mask;				// Enable Control Bits
#ifdef _Debug_IRQ_	
	if (Debug_Mode) printf("\nUART interrupt enabled.\n"); 				// print on console
#endif	
}
	
void Hardware::DoDisableUARTInterrupt(void)						// Disable service routine
{
	puart->np_uartcontrol = 0;							// Disable Control Bits
	nr_installuserisr(na_uart1_irq, 0, 0); 						// Install empty routine for uart irq
}
//###########################################################################################################################################
//BF cleaned ISR from useless overhead and transferred buttonhandler to keyboard interface

/********************************************************************
/ Added state machine for GUI-commands.
/ On reception of STX (0x02) eight Bytes are read into a buffer.
/ When buffer is full, UartRxGuiCmd is set to 1
*********************************************************************/
void Hardware::ISR_UART(int context)                            // UART Interrupt subroutine for RS232 interface
{
#define	debug 0
    char rxchar;
    int status;
    static unsigned char state=0,rxbufcnt=0;

    status = puart->np_uartstatus;
    rxchar = puart->np_uartrxdata;

    puart->np_uartstatus = 0;				//clear interrupt condition

    UART_RXFlag = 1;   					//KB new uart data received for Quick Print export function

    if (status & np_uartstatus_rrdy_mask)
    {
        switch (state) {
            case 0:
                if (rxchar != STX) {        //Standard handling
                    UART_RXData  = rxchar;
                    UART_NewData = 1;
                    UI_request   = 1;
                }
                else state=1;
            break;
            case 1:
                if (rxchar == 'E') {        //Extended CMD from GUI
					if (debug) printf("E->2\n\r");
                    state=2; }
                else {                      //This is a screenshot-request
                    UartRxGuiCmd=rxchar;    //This setting is caught in PC-comms.cpp
					UART_NewData=1;
					if (debug) printf("Extended Part invalid: %.2X\n\r",rxchar);
                    state=0; }
            break;
            case 2:
					if (debug) printf("Extended Part: %.2X\n\r",rxchar);
                    UartRxGuiBuf[rxbufcnt++]=rxchar;    //Store to buffer
                    if (rxbufcnt==UARTRXGUISIZE) {      //If buffer is full
						if (debug) printf("Is Last Extended Part: %.2X\n\r",rxchar);
                        UartRxGuiCmd='E';               //Mark UartRxGuiCmd
                    	UART_NewData = 1;
                        rxbufcnt=0;                     //Reset counter
                        state=0; }                      //and state
            break;
        }
    }
}

//###########################################################################################################################################

void Hardware::DoEnableUART2Interrupt(void)						// Enable service routine
{
	UART2_rx_cnt = 0;
	
	nr_installuserisr(na_uart_usb_irq, ISR_UART2, (int)puart2);			// Install ISR for UART2

	puart2->np_uartcontrol = np_uartcontrol_irrdy_mask;				// Enable Control Bits
#ifdef _Debug_IRQ_	
	if (Debug_Mode) printf("\nUART USB interrupt enabled.\n"); 			// print on console
#endif	
}
//###########################################################################################################################################
	
void Hardware::DoDisableUART2Interrupt(void)						// Disable service routine
{
	puart2->np_uartcontrol = 0;							// Disable Control Bits
	nr_installuserisr(na_uart_usb_irq, 0, 0); 					// Install empty routine for uart2 irq
}
//###########################################################################################################################################
// BF new designed USB function #017
void Hardware::ISR_UART2(int context)							// UART Interrupt subroutine for USB interface
{
	char rxchar = -1;
	int status;
	int x;
		

		
	status = puart2->np_uartstatus;									// get UART status
	rxchar = puart2->np_uartrxdata;									// get transferred byte
	
	//puart2->np_uartstatus = 0;									// Clear Interrupt condition
	   	
	if (status & np_uartstatus_rrdy_mask)
	{
		UART2_rx_buffer[UART2_rx_cnt] = rxchar;							// save byte to buffer
			
		UART2_rx_cnt++;										// increase byte counter
	}	

	if ((UART2_rx_buffer[0] != 64) && (UART2_rx_buffer[0] != 8) && (UART2_rx_buffer[0] != 37))	// check for block start indicator
	UART2_rx_cnt = 0;
													// first byte contains block size

	if ((UART2_rx_cnt == UART2_rx_buffer[0]) && (UART2_rx_cnt > 0))								// Check if data block is complete (64 byte)
	{		
		printf("USB Interface: Received data block with %d bytes\n\r",UART2_rx_cnt);

		if(UART2_rx_buffer[0] == 37) CommIF::InterpretUART(&UART2_rx_buffer[0]);		//WELEC USB handler
	
		if(UART2_rx_buffer[0] == 64) CommIF::ON_UART2DataBlock(&UART2_rx_buffer[0]);		//new USB handler by BF

		if(UART2_rx_buffer[0] == 8) CommIF::ON_UART2DataBlock(&UART2_rx_buffer[0]);		//new USB handler by BF

		UART2_rx_cnt = 0;									// reset byte counter
	}
	
	puart2->np_uartstatus = 0;									// Clear Interrupt condition

}

//##############################################################################################################################################
// BF new implemented
// timer 1 service routines for combi-trigger
void Hardware::DoEnableTimer1Interrupt(void)									// Enable service routine
{	
	nr_installuserisr(na_timer1_irq,ISR_TIMER1,(int)timer1); 						// Install timer isr
	
	timer1->np_timerperiodh = (nasys_clock_freq/1000)>>16;;
	timer1->np_timerperiodl = (nasys_clock_freq/1000)&0x0000ffff;	
	
	timer1->np_timercontrol = timer1->np_timercontrol | np_timercontrol_ito_mask | np_timercontrol_start_mask | np_timercontrol_cont_mask;
#ifdef _Debug_IRQ_	
	if (Debug_Mode) printf("\nTimer1 interrupt enabled.\n"); 						// print on console
#endif	
}
//##############################################################################################################################################

void Hardware::DoDisableTimer1Interrupt(void)									// Disable service routine
{
	nr_installuserisr(na_timer1_irq,0,0); 									// Install empty routine for timer irq
	timer1->np_timercontrol = timer1->np_timercontrol & ~np_timercontrol_ito_mask; 				// Disable timer interrupt
}
//##############################################################################################################################################

void Hardware::Start_Timer1(void)
{
	timer1->np_timerperiodh = timer_reload_high;
	timer1->np_timerperiodl = timer_reload_low;	
	
	timer1->np_timercontrol = ((timer1->np_timercontrol & 3) + np_timercontrol_start_mask);	// Start Timer
}
//##############################################################################################################################################

void Hardware::Stop_Timer1(void)
{
   	 timer1->np_timercontrol = ((timer1->np_timercontrol & 3) + np_timercontrol_stop_mask);	// Stop Timer
}
//##############################################################################################################################################

void Hardware::ISR_TIMER1(int context)										// Menu Timer service subroutine
{
	timer1->np_timerstatus  = 0;										// clear the status register
	timingcounter++;
	noTriggerTime++; 											//needed for combi-trigger
	
	//BF added for Stefans combi-trigger
	if (MenuStatus[MENU_TRIGGERMODE][0] == TRIG_COMB  && noTriggerTime > 500  && CombiTriggerStatus == 0 && USTB_Mode == USTB_OFF) //change trigger to auto-trigger
	{
		//combi-trigger,  no Trigger for 500ms, trigger still in normal-mode
		if((MainTimebase < 22) || (!(ctrl_reg & 0x0040)))
		{
			//timebase<=20ms,
			CombiTriggerStatus = 1;//change trigger to auto-trigger
			ctrl_reg |= 0x0040;
			SetupADC();
			// printf("Set to Auto\n");
		}
	}
	

//	printf("We got a timer1 irq  AFR %d  AST %d tcv %d tcm %d irq %d\n", AutoFreeRun, AutoSearchTrigger, timer_counter_value, timer_counter_max, acq_ready->np_piodata);

}
//##############################################################################################################################################
// BF new implemented
// Enable timer 2 interrupt for rollmode
void Hardware::DoEnableTimer2Interrupt(void)									// Enable service routine
{	

	//timer2->np_timercontrol = np_timercontrol_stop_mask;							// Stop Timer
	timer2->np_timercontrol = 0x0008;									// Stop Timer, disable interrupt
	//timer2->np_timerperiodh = (short)((USTB_timer_value[RealTimebase - 23] >> 16) & 0x0000ffff);	// Set High Register of Timer
	//timer2->np_timerperiodl = (short)(USTB_timer_value[RealTimebase - 23] & 0x0000ffff);		// Set Low Register of Timer
	timer2->np_timerstatus = 0;										// write anything to clear the ISR

	nr_installuserisr(na_timer2_irq,ISR_TIMER2,(int)timer2); 						// Install timer isr
	timer2->np_timercontrol = 0x0001;									// enable interrupt

	//printf("\nTimer2 interrupt enabled.\n");

}
//##############################################################################################################################################
// BF new implemented
// disable timer 2 interrupt for rollmode
void Hardware::DoDisableTimer2Interrupt(void)									// Disable service routine
{
	
	timer2->np_timercontrol = np_timercontrol_stop_mask;							// Stop Timer
	nr_installuserisr(na_timer2_irq,0,0); 									// Install empty routine for timer irq
    	timer2->np_timerstatus = 0;

	//printf("\nTimer2 interrupt disabled.\n");	

}
//##############################################################################################################################################
// BF new implemented
void Hardware::Start_Timer2(void)
{
	//timer2->np_timerperiodh = (short)((USTB_timer_value[RealTimebase - 23] >> 16) & 0x0000ffff);	// Set High Register of Timer
	//timer2->np_timerperiodl = (short)(USTB_timer_value[RealTimebase - 23] & 0x0000ffff);		// Set Low Register of Timer
	//timer2->np_timerstatus = 0;										// clear the ISR

	//timer2->np_timercontrol = np_timercontrol_start_mask;							// Start Timer
	//timer2->np_timercontrol = np_timercontrol_start_mask + np_timercontrol_ito_mask;			// Start Timer and enable Interrupt
	timer2->np_timercontrol = 0x0005;									// Start Timer and enable Interrupt
	printf("\nTimer2 started.\n");
}
//##############################################################################################################################################
// BF new implemented
void Hardware::Stop_Timer2(void)
{
	//timer2->np_timercontrol = np_timercontrol_stop_mask;							// Stop Timer
	//timer2->np_timercontrol = 0x0009;									// Stop Timer
	timer2->np_timercontrol = 0x0008;									// Stop Timer, disable interrupt
	timer2->np_timerstatus  = 0;										// clear the ISR

	//printf("\nTimer2 stopped.\n");
}
//##############################################################################################################################################
// BF new implemented
void Hardware::Reset_Timer2(void)
{
	unsigned long int lTimerValue = USTB_timer_value[MainTimebase - 25];

	timer2->np_timerperiodh = (short)((lTimerValue >> 16) & 0x0000ffff);					// set high register of timer
	timer2->np_timerperiodl = (short)(lTimerValue & 0x0000ffff);						// set low register of timer
	timer2->np_timerstatus = 0;										// clear the ISR
	
	timer2->np_timercontrol = 0x0007; 									// set timer to continious running and start


	//timer2->np_timercontrol = np_timercontrol_start_mask;							// start timer
	//timer2->np_timercontrol = np_timercontrol_start_mask + np_timercontrol_ito_mask;			// start timer and enable interrupt
	//timer2->np_timercontrol = 0x0005;									// start timer and enable interrupt

//	printf("\r\nReset Timer2 -> counter value = %d\r\n", USTB_timer_value[RealTimebase - 23]);

}
//##############################################################################################################################################
// timer 2 interrupt service routine for rollmode
// BF new implemented
void Hardware::ISR_TIMER2(int context)										// Menu Timer service subroutine
{

	if (context != (int)timer2) return;

	//if (Run == false) return;

	timer2->np_timerstatus  = 0;										// clear the status register
	//Stop_Timer2();

	Start_Record();

//printf("Timer 2 interrupt   ");	
//	printf("Timer 2 interrupt occured - new record started\n\r");

}
//##############################################################################################################################################
/* BF -> not needed
// copy/shift routine for rollmode
void Hardware::Copy_in_asm(int cnt, unsigned char *DataArray_in, unsigned char *DataArray_out)
{
    asm("
            ;MOV	%l0, %i0

            ;MOV	%l1, %i1
            ;SUB	%l1, %i0

            ;MOV	%l2, %i2
            ;SUB	%l2, %i0

        copy_asm1 :
            LD      	%r0, [%i1]	; save old value
            EXT8D   	%r0, %i1 	; extract byte

            FILL8	%r0, %r0
            ST8D	[%i2], %r0

            ADDI   	%i1, 1    	; Add Address Counter
            ADDI   	%i2, 1 		; Add Address Counter
                        	
            SUBI   	%i0, 1   	; Decrement Line Counter
            SKPS   	cc_z
            BR     	copy_asm1	
            NOP

        ");

}
*/
//##############################################################################################################################################
// enable timer 3 interupt for rotary interface
void Hardware::DoEnableTimer3Interrupt(void)										// Enable service routine
{					
	timer_rotary_busy->np_timerperiodh = TimerRotPeriod >> 16;							// Set High Register of Timer
	timer_rotary_busy->np_timerperiodl = TimerRotPeriod & 0xffff;							// Set Low Register of Timer
    	timer_rotary_busy->np_timerstatus = 0;										// write anything to clear the IRQ

	nr_installuserisr(na_timer3_irq,ISR_TIMER3,(int)timer_rotary_busy); 						// Install timer isr

	timer_rotary_busy->np_timercontrol = timer_rotary_busy->np_timercontrol | np_timercontrol_ito_mask;  		// Enable timer interrupt
	
	//if (Debug_Mode) printf("Timer3 interrupt enabled & started.\n"); 						// print on console

}
//##############################################################################################################################################
// disable timer 3 interupt for rotary interface
void Hardware::DoDisableTimer3Interrupt(void)										// Disable service routine
{
	nr_installuserisr(na_timer3_irq,0,0); 										// Install empty routine for timer irq
	timer_rotary_busy->np_timercontrol = timer_rotary_busy->np_timercontrol & ~np_timercontrol_ito_mask; 		// Disable timer interrupt
}
//##############################################################################################################################################
// timer 3 interrupt service routine for rotary interface and popup menus
// Menu Timer service subroutine
void Hardware::ISR_TIMER3(int context)				
{
	timer_rotary_busy->np_timerstatus = 0;						// write anything to clear the IRQ

	TriggerLevelActive = 0;

	//if (Splash_drawed) return;

	if(QP_request) return;

/*BF del
	// unpush buttons
	for (int cnt = 0; cnt < 6; cnt++)
	{
		if (MenuItemPushed[cnt] == 0) continue;
		if (MenuItemDef[Active_Menu][cnt] != 0)		//only if button is active in this menu (after menu change)
		{
			//Display::ClearMenuItemTextAsm(cnt, 35040, 32);
			Display::ClearMenuItemAsm(cnt, 34560, 44);	// -> only for deleting old lines -> better in button routine!
			Display::DrawMenuItemButton(cnt, 0);
			Display::DrawMenuItem(New_Menu, cnt, MenuAktive, 1);
		}
		MenuItemPushed[cnt] = 0;
	} 
*/

	if (MenuPopupActive == 46)							// change Status Layout
	{ Display::DrawInitialScreen(); MenuPopupActive = -1; MenuPopupChanged = 0; }
	else if (MenuPopupActive == 44)							// change Grid Layout
	{ Display::DRAWMENUPOPDOWN(); Display::RefreshScreen(); }
	else if (MenuPopupActive == 31)							// change FFT mode
	{ Display::DRAWMENUPOPDOWN(); Display::RefreshScreen(); }
	else if (MenuPopupActive > -1)							// menu popup active?
    	{ Display::DRAWMENUPOPDOWN(); }							// close popup due to timeout

	// Bf changed for new menu structure 
	if ((Memory_Window_visible) && (MenuStatus[MENU_TIMEBASE][4] == BTN_OFF)) 	// if memory window is visible and browse function
    	{ Display::DRAWMEMORY(1, 0, 0); }						// is not active close memory window for timeout

	ButtonChanged = 0;
	if(!AS_request)config_changed = 1;						// write config

   	//BF del acq_ready->np_pioedgecapture = 0;	#018

}
//##############################################################################################################################################
// Reset timer 3  -> reset and start timer for timeout event (popup menus, trigger line etc.)
void Hardware::ResetTimer3(int period)	// Reset Timer
{
	//long timerVal;
	//long timerPeriod;

	timer_rotary_busy->np_timercontrol = ((timer_rotary_busy->np_timercontrol & 3) + np_timercontrol_stop_mask);// & ~np_timercontrol_cont_mask;	// Stop Timer
	timer_rotary_busy->np_timerstatus = 0;									// write anything to clear the IRQ
		
	timer_rotary_busy->np_timerperiodh = period >> 16;						// Set High Register of Timer
	timer_rotary_busy->np_timerperiodl = period & 0xffff;						// Set Low Register of Timer

	timer_rotary_busy->np_timercontrol = ((timer_rotary_busy->np_timercontrol & 3) + np_timercontrol_start_mask);// | np_timercontrol_cont_mask;	// Start Timer

}
//##############################################################################################################################################
// set hardware switches on the mainboard for voltage range
void Hardware::SetSwitches(char channel, int voltage)
{

	if (MenuStatus[MENU_HARDWARE][1] == ADD_ON && channel < 5)
	{
		// support for new input stage 
		ADDON_SetSwitches(channel, voltage);
		return;
	}


	bool DoNothing = 0;
	short dat_buf = 0;
	short CalcBufInt = 0;	
	long adr_buf = 0x00000000;
	long outbuf = 0x00000000;
	


	//Bit0 and Bit1: 01: 1st Voltage divider 1/10, Bit2 and 3: 2nd Voltage divider 1/10
	//Bit4: 0: OPA656N: ampl. by 1.25, 1: ampl. by 1.
	//Bit5: BW-Limit
	//Bit6: 1st AD8131 x1/x2
	//Bit7: 2nd AD8131 x1/x2
	//Bits8-11: AC Channel (Bit8..Bit11) -> only at address 0x70000000
	//Bit28-30: hardware address of the channels Bit28: channel 3  Bit28 + 29: channel 4  Bit28 + 30: channel 2  Bit28 + 29 + 20: channel 1

	
	switch(voltage)
	{
		case -1 :
		{
			switch(channel)
			{
				case 1 : dat_buf = SwitchesCH1;break;
				case 2 : dat_buf = SwitchesCH2;break;
				case 3 : dat_buf = SwitchesCH3;break;
				case 4 : dat_buf = SwitchesCH4;break;
				case 5 : dat_buf = SwitchesTB;break;				
			}	
			break;		
		}			
							// amplification 1.25
		//case 0 : dat_buf = 0x	  ; break;	//0x		//1mV		not supported
		//case 1 : dat_buf = 0x   ; break;	//0x		//2mV		not supported
		//case 2 : dat_buf = 0x   ; break;	//0x		//5mV		not supported
		case 3 : dat_buf = 0x0015; break;	//0x0005	//10mV	00010101
		case 4 : dat_buf = 0x0055; break;	//0x0045	//20mV	01010101
		case 5 : dat_buf = 0x00C5; break;	//0x00D5	//50mV	11000101
		case 6 : dat_buf = 0x0019; break;	//0x0009	//100mV	00011001
		case 7 : dat_buf = 0x0059; break;	//0x0049	//200mV	01011001
		case 8 : dat_buf = 0x00C9; break;	//0x00D9	//500mV	11001001
		case 9 : dat_buf = 0x001A; break;	//0x000A	//1V	00011010
		case 10 : dat_buf = 0x005A; break;	//0x004A	//2V	01011010
		case 11 : dat_buf = 0x00CA; break;	//0x00DA	//5V	11001010
	}

	if(GainIdx > 0) dat_buf &= 0xFFEF;							//delete bit 4 set amplification to 1.25

	switch(channel)
	{
		case 1:
		{
			adr_buf = 0x70000000;							// channel 1 address

			dat_buf = dat_buf & 0xF0DF;						// delete bits 5 and 8 - 11

			if (MenuStatus[MENU_CHANNEL1][0] == 8) dat_buf = dat_buf | 0x0100;	// set DC Bit 8
			if (MenuStatus[MENU_CHANNEL2][0] == 8) dat_buf = dat_buf | 0x0200;	// set DC Bit 9
			if (MenuStatus[MENU_CHANNEL3][0] == 8) dat_buf = dat_buf | 0x0400;	// set DC Bit 10
			if (MenuStatus[MENU_CHANNEL4][0] == 8) dat_buf = dat_buf | 0x0800;	// set DC Bit 11

			if (MenuStatus[MENU_CHANNEL1][1] == 241) dat_buf = dat_buf | 0x0020;	// BW Limit Bit 5

			SwitchesCH1 = dat_buf;
			
			VoltageChangedCh1 = 1;
		
			break;	
		}
		case 2:
		{
			adr_buf = 0x50000000;							// channel 2 address
			
			dat_buf = dat_buf & 0xFFDF;						// delete Bit 5

			if (MenuStatus[MENU_CHANNEL2][1] == 241) dat_buf = dat_buf | 0x0020;	// BW Limit Bit 5
			
			SwitchesCH2 = dat_buf;
	
			VoltageChangedCh2 = 1;

			break;	
		}
		case 3:
		{
			adr_buf = 0x10000000;							// channel 3 address
			
			dat_buf = dat_buf & 0xFFDF;						// delete Bit 5
			
			if (MenuStatus[MENU_CHANNEL3][1] == 241) dat_buf = dat_buf | 0x0020;	// BW Limit Bit 5
			
			SwitchesCH3 = dat_buf;

			VoltageChangedCh3 = 1;

			break;	
		}
		case 4:
		{
			adr_buf = 0x30000000;							// channel 4 address
			
            		dat_buf = dat_buf & 0xFFDF;						// delete Bit 5
			
			if (MenuStatus[MENU_CHANNEL4][1] == 241) dat_buf = dat_buf | 0x0020;	// BW Limit Bit 5
			
			SwitchesCH4 = dat_buf;

			VoltageChangedCh4 = 1;

			break;	
		}		
		case 5:
		{
			adr_buf = 0x20000000;							// trigger channel address
			SwitchesTB = voltage;

			break;	
		}				
	}

	switch(channel)
	{
		case 1: outbuf = adr_buf | SwitchesCH1; break;
		case 2: outbuf = adr_buf | SwitchesCH2; break;
		case 3: outbuf = adr_buf | SwitchesCH3; break;
		case 4: outbuf = adr_buf | SwitchesCH4; break;
		case 5: outbuf = adr_buf | SwitchesTB; break;		
		case 6: outbuf = 0xFFFFFFFF; break;		
		case 7: outbuf = 0x00000000; break;				
	}	

    	//printf("outbuf1 : %x\n", outbuf);

    	serdata->np_piodata = outbuf;
	
	serstartsw->np_piodata = 1;
	serstartsw->np_piodata = 0;	
		
	nr_delay(30);

	//Clear Bits0..3 and send again to shut off driver transistors for voltage divider-relais
	switch(channel)
	{
		case 1: outbuf = (adr_buf | SwitchesCH1) & 0xFFFFFFF0; break;
		case 2: outbuf = (adr_buf | SwitchesCH2) & 0xFFFFFFF0; break;
		case 3: outbuf = (adr_buf | SwitchesCH3) & 0xFFFFFFF0; break;
		case 4: outbuf = (adr_buf | SwitchesCH4) & 0xFFFFFFF0; break;
	}		
	//printf("outbuf2 : %x\n", outbuf);

	if ((channel > 0) && (channel < 5))
	{
		serdata->np_piodata = outbuf;
		
		serstartsw->np_piodata = 1;
		serstartsw->np_piodata = 0;	
	
		nr_delay(30);
	}

/*
	switch(channel)
	{	
		case 1: printf("Switches : %x , erg : %x\r\n", SwitchesCH1, (adr_buf | SwitchesCH1) & 0xFFFFFFF0); break;
		case 2: printf("Switches : %x , erg : %x\r\n", SwitchesCH2, (adr_buf | SwitchesCH2) & 0xFFFFFFF0); break;
		case 3: printf("Switches : %x , erg : %x\r\n", SwitchesCH3, (adr_buf | SwitchesCH3) & 0xFFFFFFF0); break;
		case 4: printf("Switches : %x , erg : %x\r\n", SwitchesCH4, (adr_buf | SwitchesCH4) & 0xFFFFFFF0); break;
		case 5: printf("Switches : %x , erg : %x\r\n", SwitchesTB, (adr_buf | SwitchesTB) & 0xFFFFFFFF); break;
	}
*/



}

//##############################################################################################################################################
// support for the new input stage -> addon PCB written by Jörg
// set hardware switches on the mainboard and the add-on pcb for voltage range
void Hardware::ADDON_SetSwitches(char channel, int voltage)
{
	unsigned short dat_buf = 0;
	unsigned long lmh_buf = 0x00040A; // LMH6518 default config: aux amp disabled, no filter, low gain, max. attenuation
	unsigned long adr_buf = 0x00000000;
	unsigned long outbuf = 0x00000000;


	//Bit0 and Bit1: 01: 1st Voltage divider 1/10, Bit2 and 3: 2nd Voltage divider 1/10
	//Bit4: /CS of LMH6518, 1 if not accessing it
	//Bit5: unused, should be 1
	//Bit6: unused, should be 0
	//Bit7: unused, must be 0
	//Bits8-11: AC Channel (Bit8..Bit11)
			
	switch(voltage)
	{
		default: // no change
		{
			switch(channel)
			{
				case 1 : dat_buf = SwitchesCH1; lmh_buf = (unsigned long)SwitchesLMH[0]; break;
				case 2 : dat_buf = SwitchesCH2; lmh_buf = (unsigned long)SwitchesLMH[1]; break;
				case 3 : dat_buf = SwitchesCH3; lmh_buf = (unsigned long)SwitchesLMH[2]; break;
				case 4 : dat_buf = SwitchesCH4; lmh_buf = (unsigned long)SwitchesLMH[3]; break;
			}	
			break;		
		}			

		case 0  : dat_buf = 0x0035; lmh_buf = 0x000410; break;	//1mV	10110101, pre-amp
		case 1  : dat_buf = 0x0035; lmh_buf = 0x000413; break;	//2mV	10110101, pre-amp
		case 2  : dat_buf = 0x0035; lmh_buf = 0x000417; break;	//5mV	10110101, pre-amp
		case 3  : dat_buf = 0x0035; lmh_buf = 0x000400; break;	//10mV	10110101
		case 4  : dat_buf = 0x0035; lmh_buf = 0x000403; break;	//20mV	10110101
		case 5  : dat_buf = 0x0035; lmh_buf = 0x000407; break;	//50mV	10110101
		case 6  : dat_buf = 0x0039; lmh_buf = 0x000400; break;	//100mV	10111001
		case 7  : dat_buf = 0x0039; lmh_buf = 0x000403; break;	//200mV	10111001
		case 8  : dat_buf = 0x0039; lmh_buf = 0x000407; break;	//500mV	10111001
		case 9  : dat_buf = 0x003A; lmh_buf = 0x000400; break;	//1V	10111010
		case 10 : dat_buf = 0x003A; lmh_buf = 0x000403; break;	//2V	10111010
		case 11 : dat_buf = 0x003A; lmh_buf = 0x000407; break;	//5V	10111010
	}

	switch(channel)
	{
		case 1:
		{
			adr_buf = 0x70000000;		// channel 1 = address 7 (hardware)

			// Set AC Bits
			dat_buf = dat_buf & 0xF0DF;

			if (MenuStatus[MENU_CHANNEL1][0] == 8) dat_buf = dat_buf | 0x0100;
			if (MenuStatus[MENU_CHANNEL2][0] == 8) dat_buf = dat_buf | 0x0200;
			if (MenuStatus[MENU_CHANNEL3][0] == 8) dat_buf = dat_buf | 0x0400;
			if (MenuStatus[MENU_CHANNEL4][0] == 8) dat_buf = dat_buf | 0x0800;	
		
			// BW Limit
			if (MenuStatus[MENU_CHANNEL1][1] == 241) lmh_buf |= 0x0040; // 20 MHz

			SwitchesCH1 = dat_buf;
			
			VoltageChangedCh1 = 1;
			//printf("Switches : %x , erg : %x \n", SwitchesCH1, (adr_buf | SwitchesCH1));
		
			break;	
		}
		case 2:
		{
			adr_buf = 0x50000000;		// channel 2 = address 5 (hardware)
			
			// Set AC Bit
			dat_buf = dat_buf & 0xFFDF;
			//dat_buf = dat_buf & 0xF0DF;	
			//if (MenuStatus[MENU_CHANNEL2][0] == 8) dat_buf = dat_buf | 0x0200;	//BF add
			// BW Limit
			if (MenuStatus[MENU_CHANNEL2][1] == 241) lmh_buf |= 0x0040; // 20 MHz
			
			SwitchesCH2 = dat_buf;
	
			VoltageChangedCh2 = 1;

			//printf("Switches : %x , erg : %x \n", SwitchesCH2, (adr_buf | SwitchesCH2));

			break;	
		}
		case 3:
		{
			adr_buf = 0x10000000;		// channel 3 = address 4 (hardware)
			
			// Set AC Bit		
			dat_buf = dat_buf & 0xFFDF;
			//dat_buf = dat_buf & 0xF0DF;
			//if (MenuStatus[MENU_CHANNEL3][0] == 8) dat_buf = dat_buf | 0x0400;	//BF add
			// BW Limit
			if (MenuStatus[MENU_CHANNEL3][1] == 241) lmh_buf |= 0x0040; // 20 MHz
			
			SwitchesCH3 = dat_buf;

			VoltageChangedCh3 = 1;
			//printf("Switches : %x , erg : %x \n", SwitchesCH3, (adr_buf | SwitchesCH3));

			break;	
		}
		case 4:
		{
			adr_buf = 0x30000000;		// channel 4 = address 3 (hardware)
			
			// Set AC Bit	
            		dat_buf = dat_buf & 0xFFDF;
			//dat_buf = dat_buf & 0xF0DF;
			//if (MenuStatus[MENU_CHANNEL4][0] == 8) dat_buf = dat_buf | 0x0800;
			// BW Limit
			if (MenuStatus[MENU_CHANNEL4][1] == 241) lmh_buf |= 0x0040; // 20 MHz
			
			SwitchesCH4 = dat_buf;

			VoltageChangedCh4 = 1;

			//printf("Switches : %x , erg : %x \n", SwitchesCH4, (adr_buf | SwitchesCH4));

			break;	
		}		
	}

	SwitchesLMH[channel-1] = (unsigned short) lmh_buf; // save for later restore with voltage = -1

	outbuf = adr_buf | dat_buf;
    //printf("outbuf1: %x\r\n", outbuf);
	serdata->np_piodata = outbuf;//TurnBits(outbuf);
	serstartsw->np_piodata = 1;
	serstartsw->np_piodata = 0;	
	Sleep_us(SPI_DELAY16); // delay >130us while FPGA shifts it out
		
	// while the relays are settling, program the LMH

	// clear /CS, assert it (this could have been done above already, 
	// only do it here because it may be first time and the line not idle high)
	outbuf = adr_buf | (dat_buf & 0xFFEF); 
    //printf("outbuf2: %x\r\n", outbuf);
    	serdata->np_piodata = outbuf;
	serstartsw->np_piodata = 1;
	serstartsw->np_piodata = 0;	
	Sleep_us(SPI_DELAY16); // delay >130us while FPGA shifts it out
	
	unsigned long mask = 1L << 23; // with leading 0x00 command byte, send 24 bits, MSB first
	outbuf = 0x70000000 | (SwitchesCH1 & ~0x9000); // clock and data low

	// test: send more bits -> not working, valid transfer is 24 bits only
	// mask <<= 8; 
	// outbuf <<= 8; // left aligned, shift the data, too -> not working

	//printf("outbuf3: %x\r\n", outbuf);
	//printf("lmh=%x\r\n", lmh_buf);
	while (mask)
	{
		outbuf &= ~0x9000L; // clock low, data low and t.b.d.
		// set data line to bit value
		if (lmh_buf & mask)
		{
			outbuf |= 0x1000L; // set data bit
		}

		serdata->np_piodata = outbuf;
		serstartsw->np_piodata = 1;
		serstartsw->np_piodata = 0;
		Sleep_us(SPI_DELAY16); // delay >130us while FPGA shifts it out

		// clock high
		outbuf |= 0x8000L;
		serdata->np_piodata = outbuf;
		serstartsw->np_piodata = 1;
		serstartsw->np_piodata = 0;	
		Sleep_us(SPI_DELAY16); // delay >130us while FPGA shifts it out

		mask >>= 1; // next lower bit
	}
	
	outbuf &= ~0x9000L; // clock and data low
	serdata->np_piodata = outbuf;
	serstartsw->np_piodata = 1;
	serstartsw->np_piodata = 0;	
	//printf("\r\noutbuf4: %x\r\n", outbuf);
	
	if ((15000-49*SPI_DELAY16) > SPI_DELAY16) // if there's still more time to kill than the shift time
	{
		Sleep_us(15000-49*SPI_DELAY16); // wait for SPI shifting it out, plus remaining relay settling time
	}
	else // minimum time
	{
		Sleep_us(SPI_DELAY16); // wait for SPI shifting it out
	} 


	//Clear Bits0..3 and send again to shut off driver transistors for voltage divider-relais
	// this also de-assert /CS of the LMH
	outbuf = adr_buf | (dat_buf & 0xFFF0);
	printf("outbuf5: %x\r\n\r\n", outbuf);

	serdata->np_piodata = outbuf;//TurnBits(outbuf);	
	
	serstartsw->np_piodata = 1;
	serstartsw->np_piodata = 0;	
	Sleep_us(SPI_DELAY16); // wait for SPI shifting it out



}
//##############################################################################################################################################
// busy wait with microsecond resolution -> written by Jörg
void Hardware::Sleep_us(unsigned long us)
{
	// as it currently compiles, one loop iteration takes ~2 us
	// note that this is rather inaccurate, not precisely timed
	for (volatile unsigned long i=us/2; i>0; i--);
}

//##############################################################################################################################################
// BF added 16 Bit DAC support
void Hardware::SetDacOffset(char channel)
{
	//long CalcBufInt = 0;	
	long BufInt = 0;
	long BufInt2 = 0;	
	long outbuf = 0x00000000;		

/* 	BF Serial interface (SDI) specification for LTC2602/LTC2612 DAC family.
	The 4-bit command, C3-C0, is loaded first; then the 4-bit DAC address, A3-A0; and finally the 16-bit data word. The
	data word comprises the 16-, 14- or 12-bit input code, ordered MSB-to-LSB, followed by 0, 2 or 4 don’t-care bits
	(LTC2602, LTC2612 and LTC2622 respectively). 

	Data can only be transferred to the device when the CS/LD signal is low.The rising edge of CS/LD ends the data transfer and
	causes the device to carry out the action specified in the 24-bit input word.

	Command:							Address:
	C3  C2  C1  C0							A3  A2  A1  A0
	-----------------------------------------------------		-------------------------
	0   0   0   0	write to input register n			0   0   0   0	DAC A
	-----------------------------------------------------		-------------------------
	0   0   0   1	update (power up) register n			0   0   0   1	DAC B
	-----------------------------------------------------		-------------------------
	0   0   1   0	write to input register n, update all		1   1   1   1	All DACs
	-----------------------------------------------------		-------------------------
	0   0   1   1	write to and update n
	-----------------------------------------------------
	0   1   0   0	Power down n
	-----------------------------------------------------
	1   1   1   1	No operation
	-----------------------------------------------------


	Input word LTC2602:

	<C3 C2 C1 C0|A3 A2 A1 A0|D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0> 


	Input word LTC2612:

	<C3 C2 C1 C0|A3 A2 A1 A0|D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 X X> 

	The input word structure is software compatible. The DAC versions can be changed
	without changing the firmware if the format is implemented in 16 bit.
*/

	switch(channel)
	{
		case 1 :	
		{			
			BufInt = CH1_DAC_Offset & 0xFFFF;
			
			BufInt2 = 0x00310000 | BufInt;			// write and update register DAC 1-B

			outbuf = 0x60000000 | BufInt2;			// set DAC 1 base address
			
			serdata->np_piodata = outbuf;

			serstartsw->np_piodata = 1;
			serstartsw->np_piodata = 0;	
							
			nr_delay(10);	
						
			break;	
		}			
		case 2 :	
		{
			BufInt = CH2_DAC_Offset & 0xFFFF;
			
			BufInt2 = 0x00300000 | BufInt;			//write and update register DAC 1-A

			outbuf = 0x60000000 | BufInt2;			// set DAC 1 base address
			
			serdata->np_piodata = outbuf;
			
			serstartsw->np_piodata = 1;
			serstartsw->np_piodata = 0;	
							
			nr_delay(10);

			break;		
		}	
		case 3 :
		{			
			BufInt = CH3_DAC_Offset & 0xFFFF;

			BufInt2 = 0x00310000 | BufInt;			//write and update register DAC 2-B

			outbuf = 0x40000000 | BufInt2;			// set DAC 2 base address	
			
			serdata->np_piodata = outbuf;

			serstartsw->np_piodata = 1;
			serstartsw->np_piodata = 0;	
							
			nr_delay(10);	
						
			break;	
		}			
		case 4 :
		{
			BufInt = CH4_DAC_Offset & 0xFFFF;
			
			BufInt2 = 0x00300000 | BufInt;			//write and update register DAC 2-A

			outbuf = 0x40000000 | BufInt2;			// set DAC 2 base address
			
			serdata->np_piodata = outbuf;
			
			serstartsw->np_piodata = 1;
			serstartsw->np_piodata = 0;	
							
			nr_delay(10);

			break;		
		}
	}	

}
//##############################################################################################################################################
//BF usage unclear -> check if needed!!
/*
void Hardware::SetCHDacOffset(char channel)
{
	switch(channel)
	{
		case 1 :
		{		
 			// channel 1 DAC 1
			serdata->np_piodata = 0x80000000 | 0 | 0x0600;

			serstartsw->np_piodata = 1;
			serstartsw->np_piodata = 0;	

			nr_delay(1);
					
 			// channel 1 DAC 2
			serdata->np_piodata = 0x80000000 | 0 | 0x1600; //0x0E00;

			serstartsw->np_piodata = 1;
			serstartsw->np_piodata = 0;	
			
			nr_delay(1);

 			// channel 1 DAC 3
			serdata->np_piodata = 0x80000000 | 0 | 0x1E00; //0x1600;

			serstartsw->np_piodata = 1;
			serstartsw->np_piodata = 0;	
			
			nr_delay(1);

 			// channel 1 DAC 4
			serdata->np_piodata = 0x80000000 | 0 | 0x2600; //0x1E00;

			serstartsw->np_piodata = 1;
			serstartsw->np_piodata = 0;	
			
			nr_delay(1);	
					
			break;	
		}
															
		case 2 : 
		{
			// channel 2 DAC 1
			serdata->np_piodata = 0x80000000 | 0 | 0x0E00; //0x2600;

			serstartsw->np_piodata = 1;
			serstartsw->np_piodata = 0;	
			
			nr_delay(1);

			// channel 2 DAC 2
			serdata->np_piodata = 0x80000000 | 0 | 0x3E00; //0x2E00;

			serstartsw->np_piodata = 1;
			serstartsw->np_piodata = 0;	
			
			nr_delay(1);

			// channel 2 DAC 3
			serdata->np_piodata = 0x80000000 | 0 | 0x3600;

			serstartsw->np_piodata = 1;
			serstartsw->np_piodata = 0;	
			
			nr_delay(1);

			// channel 2 DAC 4
			serdata->np_piodata = 0x80000000 | 0 | 0x2E00; //0x3E00;

			serstartsw->np_piodata = 1;
			serstartsw->np_piodata = 0;	
			
			nr_delay(1);
										
			break;
		}

		case 3 : 
		{
			// channel 3 DAC 1
			serdata->np_piodata = 0x90000000 | 0 | 0x0600;

			serstartsw->np_piodata = 1;
			serstartsw->np_piodata = 0;	

			nr_delay(1);		

			// channel 3 DAC 2
			serdata->np_piodata = 0x90000000 | 0 | 0x0E00;

			serstartsw->np_piodata = 1;
			serstartsw->np_piodata = 0;	
			
			nr_delay(1);

			// channel 3 DAC 3
			serdata->np_piodata = 0x90000000 | 0 | 0x1600;

			serstartsw->np_piodata = 1;
			serstartsw->np_piodata = 0;	
			
			nr_delay(1);

			// channel 3 DAC 4
			serdata->np_piodata = 0x90000000 | 0 | 0x1E00;

			serstartsw->np_piodata = 1;
			serstartsw->np_piodata = 0;	
			
			nr_delay(1);	

			break;		
		}												
															
		case 4 : 
		{
			// channel 4 DAC 1
			serdata->np_piodata = 0x90000000 | 0 | 0x2600;

			serstartsw->np_piodata = 1;
			serstartsw->np_piodata = 0;	
			
			nr_delay(1);	

			// channel 4 DAC 2
			serdata->np_piodata = 0x90000000 | 0 | 0x2E00;

			serstartsw->np_piodata = 1;
			serstartsw->np_piodata = 0;	
			
			nr_delay(1);

			// channel 4 DAC 3
			serdata->np_piodata = 0x90000000 | 0 | 0x3600;

			serstartsw->np_piodata = 1;
			serstartsw->np_piodata = 0;	
			
			nr_delay(1);

			// channel 4 DAC 4
			serdata->np_piodata = 0x90000000 | 0 | 0x3E00;

			serstartsw->np_piodata = 1;
			serstartsw->np_piodata = 0;	
			
			nr_delay(1);

			break;					
		}			
	}	
}
*/
//#####################################################################################################################################################
//BF set ADC depending registers for triggering and acquisition
void Hardware::SetupADC(void)
{
	
	mode->np_piodata = 0x01;
		
	if (triggering == 0)	// trigger off
	{ 
		adc_ctrl_reg &= 0xFFF1;
		ctrl_reg &= 0xC17D;  // remove holdoff and pulse bits and internal bit

		adc_ctrl_reg |= 0x0001;
		ctrl_reg |= 0x0041;
		trig_holdoff_reg = 0x00000000;

		WRITEADC(1, ctrl_reg + (adc_ctrl_reg << 16));
	}	
	else if(triggering == 1) WRITEADC(1, ctrl_reg + (adc_ctrl_reg << 16));
	else WRITEADC(1, (ctrl_reg & 0xFFFE) + (adc_ctrl_reg << 16));		

	WRITEADC(1, tb_value[MainTimebase]);	// set timebase register

	WRITEADC(1, pre_reg + (channel_Adr_add12 << 16));
    	
	WRITEADC(1, trg_val_CHI_reg + (trg_val_CHII_reg << 8) + (trig_range_reg << 16));
	WRITEADC(1, (0xFFFFFFFF - trig_holdoff_reg));

	//BF set the grid color and pulse width
	WRITEADC(1, trig_width_reg + (GridColor_Val << 26));	// ->GridColorArray[4] = {0x00, 0x15, 0x2A, 0x3F};
	
	WRITEADC(1, adc_change12_reg);
	
	WRITEADC(1, adc_ctr12_reg);

	mode->np_piodata = 0x00;

	nr_delay(20);

	if (NumberOfChannels == 4)
	{
		mode->np_piodata = 0x01;
		if(triggering == 0 || triggering == 3) WRITEADC(3, ctrl_reg + (adc_ctrl_reg << 16));
		else WRITEADC(3, (ctrl_reg & 0xFFFE) + (adc_ctrl_reg << 16));
	
		WRITEADC(3, tb_value[MainTimebase]);	// set timebase register
		
		WRITEADC(3, pre_reg + (channel_Adr_add34 << 16));		//BF add
//		WRITEADC(3, pre_reg + (channel_Adr_add2 << 16));

		WRITEADC(3, trg_val_CHIII_reg + (trg_val_CHIV_reg << 8) + (trig_range_reg << 16));	
		WRITEADC(3, (0xFFFFFFFF - trig_holdoff_reg));
	
		WRITEADC(3, trig_width_reg + (GridColor_Val << 26));	// ->GridColorArray[4] = {0x00, 0x15, 0x2A, 0x3F};
	
		WRITEADC(3, adc_change34_reg);	//BF changed
		WRITEADC(3, adc_ctr34_reg);
	
		mode->np_piodata = 0x00;
    	}

	//mode->np_piodata = 0x00;

}
//#####################################################################################################################################################
void Hardware::WRITEADC(unsigned char which, unsigned long value)
{	
	switch(which)
	{
		case 1 :
				asm("		
						MOV		%r0,%i1					; Address of Buffer
						PFX		%hi(0x00A00000)
						MOVI	%l0,%lo(0x00A00000)
						PFX		%xhi(0x00A00000)
						MOVHI	%l0,%xlo(0x00A00000)				
			
						ST		[%l0], %r0		
					");	
				break;
		case 2 :
				asm("		
						MOV		%r0,%i1					; Address of Buffer
						PFX		%hi(0x00A00010)
						MOVI	%l0,%lo(0x00A00010)
						PFX		%xhi(0x00A00010)
						MOVHI	%l0,%xlo(0x00A00010)				
			
						ST		[%l0], %r0		
					");	
				break;
		case 3 :
				asm("		
						MOV		%r0,%i1					; Address of Buffer
						PFX		%hi(0x00A00020)
						MOVI	%l0,%lo(0x00A00020)
						PFX		%xhi(0x00A00020)
						MOVHI	%l0,%xlo(0x00A00020)				
			
						ST		[%l0], %r0		
					");	
				break;
		case 4 :
				asm("		
						MOV		%r0,%i1					; Address of Buffer
						PFX		%hi(0x00A00030)
						MOVI	%l0,%lo(0x00A00030)
						PFX		%xhi(0x00A00030)
						MOVHI	%l0,%xlo(0x00A00030)				
			
						ST		[%l0], %r0		
					");	
				break;
	}
}
//#####################################################################################################################################################
unsigned long Hardware::READADC(unsigned char which)
{

	switch(which)
	{
		case 1 :
				asm("		
						PFX		%hi(0x00A00000)
						MOVI	%l0,%lo(0x00A00000)
						PFX		%xhi(0x00A00000)
						MOVHI	%l0,%xlo(0x00A00000)				
		
						LD		%r0,[%l0]	
		
						MOV		%i0, %r0
					");	
				break;
		case 2 :
				asm("		
						PFX		%hi(0x00A00010)
						MOVI	%l0,%lo(0x00A00010)
						PFX		%xhi(0x00A00010)
						MOVHI	%l0,%xlo(0x00A00010)				
		
						LD		%r0,[%l0]	
		
						MOV		%i0, %r0	
					");	
				break;
		case 3 :
				asm("		
						PFX		%hi(0x00A00020)
						MOVI	%l0,%lo(0x00A00020)
						PFX		%xhi(0x00A00020)
						MOVHI	%l0,%xlo(0x00A00020)				
		
						LD		%r0,[%l0]	
		
						MOV		%i0, %r0	
					");	
				break;
		case 4 :
				asm("		
						PFX		%hi(0x00A00030)
						MOVI	%l0,%lo(0x00A00030)
						PFX		%xhi(0x00A00030)
						MOVHI	%l0,%xlo(0x00A00030)				
		
						LD		%r0,[%l0]	
		
						MOV		%i0, %r0	
					");	
				break;
	}
}	
//#####################################################################################################################################################
//BF set registers for ADC reading with correction values and value count -> Assembler
void Hardware::PREPARE_READADC(unsigned char correct1, unsigned char correct2, unsigned char correct3, unsigned char correct4, unsigned int count)
{
    asm("
            MOV		%r3, %i0
            MOV		%r4, %i1
            MOV		%r5, %i2
            MOV		%r6, %i3
            MOV		%r7, %i4
        ");
}
//#####################################################################################################################################################
//BF sort, correct and recalculate ADC-values -> Assembler
//BF changed by Stefan to avoid correction error in inverting and averaging mode
//BF complete redesigned, deleted average and invertion parts, chopped unused parameters for average and invertion
void Hardware::READADC_ALL(unsigned char which, unsigned char *DataArray1, unsigned char highspeed)
{

    asm("
           ;PFX	    %hi(0xFEFEFEFE)            	; Set MASK -> BF delete
           ;MOVI    %r10,%lo(0xFEFEFEFE)
           ;PFX	    %xhi(0xFEFEFEFE)
           ;MOVHI   %r10,%xlo(0xFEFEFEFE)

            MOV	    %l1, %r7               	; set address offset memory 2

            IFRZ    %i2                        	; highspeeed timebases?
            BR      lpr_slow                   	; jump to slow tb configuration
            NOP	

            MOV	    %l4, %i1               	; set address offset memory 2
            PFX     %hi(0x0001)
            ADDI    %l4, %lo(0x0001);
						
            MOV	    %l5, %i1               	; set address offset memory 3
            PFX     %hi(0x0002)
            ADDI    %l5, %lo(0x0002);
						
            MOV	    %l6, %i1               	; set address offset memory 4
            PFX     %hi(0x0003)
            ADDI    %l6, %lo(0x0003);

            BR      lpr_channel
            NOP

        lpr_slow:
            MOV	    %l4, %i1               	; set address offset memory 2
            PFX     %hi(0x1000)
            ADDI    %l4, %lo(0x1000);
							
            MOV		%l5, %i1               	; set address offset memory 3
            PFX     %hi(0x2000)
            ADDI    %l5, %lo(0x2000);
						
            MOV		%l6, %i1               	; set address offset memory 4
            PFX     %hi(0x3000)
            ADDI    %l6, %lo(0x3000);

      lpr_channel:


            PFX     %hi(0x008F4C00)    		; load address channel
            MOVI    %l0,%lo(0x008F4C00)
            PFX	    %xhi(0x008F4C00)
            MOVHI   %l0,%xlo(0x008F4C00)

	
        lpr1:				       	;main loop start
            LD	    %l2, [%l0]
            NOT     %l2	
            				       	; start mem 1			
            MOV	    %r0, %l2  			
            EXT8S   %r0, 0
	
	    SUB     %r0, %r3			; Offsetadjustment (Stefan) -> ADC1-correction

            IFS     cc_n
            PFX     %hi(0)
            MOVI    %r0, %lo(0)	
;--------------------------------------------------------------------------------------------------

        lpr1e:							
            FILL8   %r0, %r0
            ST8D    [%i1], %r0
            					; start mem 2		
            MOV	    %r0, %l2  
            EXT8S   %r0, 1
	
	    SUB     %r0, %r4			; offsetadjustment(Stefan) -> ADC2-correction
			
            IFS     cc_n
            PFX     %hi(0)
            MOVI    %r0, %lo(0)		
;-----------------------------------------------------------------------------------------------

        lpr2e:							
            FILL8   %r0, %r0
            ST8D    [%l4], %r0
						; start mem 3	
            MOV     %r0, %l2 
            EXT8S   %r0, 2

	    SUB     %r0, %r5			; offsetadjustment(Stefan) -> ADC3-correction

            IFS     cc_n
            PFX     %hi(0)
            MOVI    %r0, %lo(0)	
;-------------------------------------------------------------------

        lpr3e:
            FILL8   %r0, %r0
            ST8D    [%l5], %r0
						; start mem 4								
            MOV     %r0, %l2 
            EXT8S   %r0, 3
			
	    SUB     %r0, %r6			; offsetadjustment (Stefan) -> ADC4-correction
			
            IFS     cc_n
            PFX     %hi(0)
            MOVI    %r0, %lo(0)	
;-----------------------------------------------------------------------------------

        lpr4e:	
            FILL8   %r0, %r0
            ST8D    [%l6], %r0

            ADDI    %l0, 4 			; Add Address Counter

            IFRZ    %i2				; highspeeed timebases?
            BR      lpr_slow_ac			; jump to slow address calculation
            NOP
						
            					; calc new adresses
            ADDI   %i1, 4 			; Add Address Counter
            ADDI   %l4, 4			; Add Address Counter
            ADDI   %l5, 4			; Add Address Counter
            ADDI   %l6, 4			; Add Address Counter
	
            SUBI   %l1, 1			; Decrement Line Counter
            SKPS   cc_z
            BR     lpr1	
            NOP	

            BR     lprend
            NOP	


        lpr_slow_ac:
            					; calc new adresses
            ADDI   %i1, 1			; Add Address Counter
            ADDI   %l4, 1			; Add Address Counter
            ADDI   %l5, 1			; Add Address Counter
            ADDI   %l6, 1			; Add Address Counter

            SUBI   %l1, 1			; Decrement Line Counter
            SKPS   cc_z
            BR     lpr1	
            NOP

        lprend:		
    ");

}
//#####################################################################################################################################################
//BF -> get data from ADC  -  Assembler routine 
void Hardware::READADC_ALL2(unsigned char which, unsigned long *DataArray1, unsigned int count)
{

    asm("
            CMPI    %i0, 0x01               ; Is it channel 1
            IFS     cc_z
            BR      lpr1ch1n
            NOP

            CMPI    %i0, 0x02               ; Is it channel 2
            IFS     cc_z
            BR      lpr1ch2n
            NOP

            CMPI    %i0, 0x03               ; Is it channel 3
            IFS     cc_z
            BR      lpr1ch3n
            NOP

            CMPI    %i0, 0x04               ; Is it channel 4
            IFS     cc_z
            BR      lpr1ch4n
            NOP

        lpr1ch1n:
            PFX     %hi(0x00A00000)         ; load address channel 1
            MOVI	%l0,%lo(0x00A00000)
            PFX		%xhi(0x00A00000)
            MOVHI	%l0,%xlo(0x00A00000)
            BR      lpr1n
            NOP

        lpr1ch2n:
            PFX     %hi(0x00A00010)         ; load address channel 2
            MOVI	%l0,%lo(0x00A00010)
            PFX		%xhi(0x00A00010)
            MOVHI	%l0,%xlo(0x00A00010)
            BR      lpr1n
            NOP

        lpr1ch3n:
            PFX     %hi(0x00A00020)         ; load address channel 3
            MOVI	%l0,%lo(0x00A00020)
            PFX		%xhi(0x00A00020)
            MOVHI	%l0,%xlo(0x00A00020)
            BR      lpr1n
            NOP

        lpr1ch4n:
            PFX     %hi(0x00A00030)         ; load address channel 4
            MOVI	%l0,%lo(0x00A00030)
            PFX		%xhi(0x00A00030)
            MOVHI	%l0,%xlo(0x00A00030)
	
        lpr1n:
            LD		%l2, [%l0]
	
            MOV		%r0, %l2  	

            ST  	[%i1], %r0
						
           					 ; calc new adresses
            ADDI   %i1, 4                            ; Add Address Counter

            SUBI   %i2, 1                            ; Decrement Line Counter
            SKPS   cc_z
            BR     lpr1n	
            NOP
    ");

}
//#####################################################################################################################################################
//BF -> get data from ADC
//BF new C-coded hardware routine as replacement for READADC_ALL2()
void Hardware::ADC_ReadData(unsigned char which, unsigned long *DataArray1, unsigned int count)
{

		//coded by Guido

		unsigned long *source=0;
		
			
		switch (which)
		{
			case  	1:
				source = ((unsigned long*)(0x00A00000)); 	//load address channel 1
				break;
				
			case	2:
				source = ((unsigned long*)(0x00A00010));	//load address channel 2
				break;
				
			case	3:
				source = ((unsigned long*)(0x00A00020));	//load address channel 3
				break;
				
			case	4:
				source = ((unsigned long*)(0x00A00030)); 	//load address channel 4
				break;
		}	
		for (unsigned int i = 0; i < count; i++)
		{
			DataArray1[i] = *source;
		}

}
//#####################################################################################################################################################
//BF sort, correct and recalculate ADC-values
//BF new C-coded hardware routine as replacement for READADC_ALL()
void Hardware::ADC_ProcessData(unsigned char which, unsigned char *DataArray1, unsigned char inverse, unsigned int zero, unsigned char averageval, unsigned char highspeed)
{
	//coded by Guido

	static unsigned long mask = 0xFEFEFEFE;  	//set MASK (but never use it???)
	static unsigned int lw_count = 4096;		//number of longwords to work on, should be a parameter
	static unsigned char *chan_addr;		//input-buffer			
	static unsigned int loop, i;			//control
	static unsigned char byte_data; 		//byte to work on
	static unsigned char temp_byte;	
	static int temp_int;		
	static unsigned char correct[4];		//channeldependend correctionvalues	
	static unsigned char *DataArray2;
	static unsigned int zero2;
		
	DataArray2 = DataArray1;		
	zero2 = zero << 1;
	
	chan_addr = readout_sigbuf_char; // ((unsigned char*)(0x008F0C00)); //channel_address = readout_sigbuf, READADC_ALL2 filled this buffer	
	if (highspeed == 1)	//timebase < 7
/*	//Guido: testing:
	{
		for (loop = 0; loop < 4096; loop++)
		{
			byte_data = *(chan_addr);
			byte_data = ~byte_data;
			*(DataArray2) = byte_data;;	
			*(DataArray2 + 1) = byte_data;;	
			//byte_data = *(chan_addr + 2);
			//byte_data = ~byte_data;					
			*(DataArray2 + 2) = byte_data;;	
			*(DataArray2 + 3) = byte_data;;		
			DataArray2 += 4;
			chan_addr += 4;
		}	
	}
*/
	{
		// this was done bei PREPARE_READADC (now obsolete): load the channel's correctionvalues
		for (i = 0; i < 4; i++) correct[i] = ADC_Offset[(which - 1)][i];

		for (loop = 0; loop < lw_count; loop++)		
		{	
			byte_data = *(chan_addr);	//load first byte
			byte_data = ~byte_data;		//invert it bitwise			
			if (byte_data > correct[0]) byte_data -= correct[0];	//offsetadjustment (stefan put it here)
			else byte_data = 0;

/* BF is calculated in signal processing

			if (inverse == 1)
			{			
				temp_int = zero2 - byte_data;
				if (temp_int < 0) temp_int = 0;		//limit to byte
				else if (temp_int > 255) temp_int = 255;	
				byte_data = temp_int;				
			}	
			if (averageval != 0) //then start averaging				
			{
				temp_byte = *(DataArray2);		//load old value as byte
				byte_data = (unsigned char)(((unsigned short)byte_data + (unsigned short)temp_byte) >> 1);
			}
*/
			*(DataArray2) = byte_data;	//store result	
			
			byte_data = *(chan_addr);	//load second byte
			byte_data = ~byte_data;		//invert it bitwise			
			if (byte_data > correct[1]) byte_data -= correct[1];	//offsetadjustment (stefan put it here)
			else byte_data = 0;

/* BF is calculated in signal processing

			if (inverse == 1)
			{			
				temp_int = zero2 - byte_data;
				if (temp_int < 0) temp_int = 0;		//limit to byte
				else if (temp_int > 255) temp_int = 255;	
				byte_data = temp_int;				
			}	
			if (averageval != 0) //then start averaging				
			{
				temp_byte = *(DataArray2 + 1);		//load old value as byte
				byte_data = (unsigned char)(((unsigned short)byte_data + (unsigned short)temp_byte) >> 1);
			}
*/
			*(DataArray2 + 1) = byte_data;	//store result	
			
			byte_data = *(chan_addr);	//load third byte
			byte_data = ~byte_data;		//invert it bitwise			
			if (byte_data > correct[2]) byte_data -= correct[2];	//offsetadjustment (stefan put it here)
			else byte_data = 0;
/* BF is calculated in signal processing

			if (inverse == 1)
			{			
				temp_int = zero2 - byte_data;
				if (temp_int < 0) temp_int = 0;		//limit to byte
				else if (temp_int > 255) temp_int = 255;	
				byte_data = temp_int;				
			}	
			if (averageval != 0) //then start averaging				
			{
				temp_byte = *(DataArray2 + 2);		//load old value as byte
				byte_data = (unsigned char)(((unsigned short)byte_data + (unsigned short)temp_byte) >> 1);
			}
*/
			*(DataArray2 + 2) = byte_data;	//store result	
			
			byte_data = *(chan_addr);	//load last byte
			byte_data = ~byte_data;		//invert it bitwise			
			if (byte_data > correct[3]) byte_data -= correct[3];	//offsetadjustment (stefan put it here)
			else byte_data = 0;

/* BF is calculated in signal processing
			if (inverse == 1)
			{			
				temp_int = zero2 - byte_data;
				if (temp_int < 0) temp_int = 0;		//limit to byte
				else if (temp_int > 255) temp_int = 255;	
				byte_data = temp_int;				
			}	
			if (averageval != 0) //then start averaging				
			{
				temp_byte = *(DataArray2 + 3);		//load old value as byte
				byte_data = (unsigned char)(((unsigned short)byte_data + (unsigned short)temp_byte) >> 1);
			}
*/
			*(DataArray2 + 3) = byte_data;	//store result	
			DataArray2 += 4;
			chan_addr += 4;
		}	
	}	
	else	//timebase > 6: only use ADC0
	{
		for (loop = 0; loop < lw_count; loop++)		
		{	
			byte_data = *(chan_addr);	//load one byte
			byte_data = ~byte_data;		//invert it bitwise	
			// nothing to correct as only one ADC is used		
			//if (byte_data > correct[0]) byte_data -= correct[0];	//offsetadjustment (stefan put it here)
			//else byte_data = 0;

/* BF is calculated in signal processing
			if (inverse == 1)
			{			
				temp_int = zero2 - byte_data;
				if (temp_int < 0) temp_int = 0;		//limit to byte
				else if (temp_int > 255) temp_int = 255;	
				byte_data = temp_int;				
			}	
			if (averageval != 0) //then start averaging				
			{
				temp_byte = *(DataArray2);		//load old value as byte
				byte_data = (unsigned char)(((unsigned short)byte_data + (unsigned short)temp_byte) >> 1);
			}
*/
			*(DataArray2) = byte_data;	//store result	
			DataArray2 += 1;
			chan_addr += 4;		
		}
	}

}
//#####################################################################################################################################################
void Hardware::DoEnableADCInterrupt(void)							// Enable ADC service routine
{
	acq_ready->np_pioedgecapture = 0x00; 							// clear existing IRQ conditions
	acq_ready->np_piodirection = 0;								// set bit to input
	acq_ready->np_piointerruptmask = 0x01;							// enable interrupt

	nr_installuserisr(na_data_acq_interrupt_irq,ISR_ADC_INT,(int)acq_ready);		// Install ISR for ADC
#ifdef _Debug_IRQ_
	if (Debug_Mode) printf("\nADC interrupt enabled.\n"); 							// print on console
#endif
}
//#####################################################################################################################################################
void Hardware::DoDisableADCInterrupt(void)							// Disable ADC service routine
{
	
	nr_installuserisr(na_data_acq_interrupt_irq,0,0); 				// Install empty routine for adc irq
	acq_ready->np_piointerruptmask = 0x00;							// disable all IRQs
	
#ifdef _Debug_IRQ_
	if (Debug_Mode) printf("\nADC interrupt disabled.\n"); 							// print on console
#endif	
}
//#####################################################################################################################################################
	//--------------------------------------------------------------------------------------
	//        	 ultra slow timebase mode (roll mode / shift mode)
	//--------------------------------------------------------------------------------------
	//  				USTB-engine V2.1
	//--------------------------------------------------------------------------------------
inline void Handle_USTB(void)						// ADC handler for ultra slow TB
{

	//if (UI_request && !ZL_changed)	return;			// BF add  don't handle ADC if user interface must be handled first except zero level adjustment

	//if (RC_request)	return;					// BF signal recall is requested -> don't handle ADC

	if (MenuStatus[MENU_TRIGGERSUB][1] > 119)			//acquisition event occured
	{
		if(MenuStatus[MENU_TRIGGERSUB][2] == BTN_ON)
		{ LED_ON[3] = 1; }					//Channel 4 LED on
		else 
		{ LED_ON[11] = 1; }					//right LED (red) on 
		Hardware::Send_LED();
	}


	data_adr->np_piodata = 0x01;

	//BF set buffer start address
	Hardware::WRITEADC(1, 0);	
	Hardware::WRITEADC(2, 0);
	
	if (NumberOfChannels == 4)
	{				
		Hardware::WRITEADC(3, 0);
		Hardware::WRITEADC(4, 0);
	}

	data_adr->np_piodata = 0x00;


	//-------------------------------------------------------
	//		Signal Acquisition
	//-------------------------------------------------------
	if (Channel_1_Active)
	{ Hardware::ReadOut_Signal(1); }
	
	if (Channel_2_Active)
	{ Hardware::ReadOut_Signal(2); }	
	
	if (NumberOfChannels == 4)
	{	
		if (Channel_3_Active == 1)
		{ Hardware::ReadOut_Signal(3); }
	
		if (Channel_4_Active == 1)
		{ Hardware::ReadOut_Signal(4); }
	}	

	//printf("Acquisition ready!\r\n");

	//printf("MemStartOffs: %d  MemoryEnd: %d  MemWinStart: %d  USTB_idx: %d\r",MemStartOffs, MemoryEnd, MemWinStart, USTB_idx);

	//-------------------------------------------------------
	//		Math calculation
	//-------------------------------------------------------
	if (Channel_Math_Active)
	{
		if (Channel_1_Active && Channel_2_Active)
		{
			//---------------------------------------------
			//         MATH function multiply
			//---------------------------------------------
			if (MenuStatus[MENU_MATH][2] == BTN_ON)      		// multiply 
			{	
				//set global math scaling and offset for drawing routine
				math_scale = math_mul_scale - 166;
				Math_Offset = Math_Mul_Offset;
				
				//calculate main math signal
				Signal::calcMathMul(USTB_idx, USTB_idx+1, draw_factor, S1Ptr, S2Ptr, SMPtr);
			}	//multiply end
	
			//---------------------------------------------
			//         MATH function subtract
			//---------------------------------------------
			else if (MenuStatus[MENU_MATH][3] == BTN_ON)           	// subtract
			{	
				//set global math scaling and offset for drawing routine
				math_scale = math_sub_scale - 150;
				Math_Offset = Math_Sub_Offset;

				//calculate main math signal
				Signal::calcMathSub(USTB_idx, USTB_idx+1, draw_factor, S1Ptr, S2Ptr, SMPtr);
			}	//subtract end
	
			//---------------------------------------------
			//         MATH function add
			//---------------------------------------------
			else if (MenuStatus[MENU_MATH][4] == BTN_ON)           	// add
			{
				//set global math scaling and offset for drawing routine
				math_scale = math_add_scale - 150;
				Math_Offset = Math_Add_Offset;
				
				//calculate main math signal
				Signal::calcMathAdd(USTB_idx, USTB_idx+1, draw_factor, S1Ptr, S2Ptr, SMPtr);
			}	//add end
		}
		else if ((!Channel_1_Active && Channel_2_Active) || (!Channel_2_Active && Channel_1_Active))
		{ SMPtr[USTB_idx] = ADC_ZERO;	 }
	}

	//-------------------------------------------------------
	//		Time parameter control
	//-------------------------------------------------------

	// set time pointer to new position
	if (USTB_Dir == USTB_FORWARD)								// direction = forward
	{
		if (USTB_Mode == USTB_ROLL)							// roll mode
		{	
			if(USTB_idx >= MemoryEnd)						// check for time pointer overflow
			{ 
				USTB_idx = MemStartOffs; MemWinStart = MemStartOffs+1;   	// jump to start for circular buffering (roll mode)

				if (SingleShot)
				{ UserIF::Buttonhandler(BTN_STOP); }				// set to stop mode
			}
			else
			{ USTB_idx ++;}								//increment time pointer

			if (USTB_Disp == USTB_PERM && MemWinStart+GRID_WIDTH == USTB_idx-1)	// adjust memory window -> shift window right
			{ MemWinStart += draw_factor;}	
			else if (USTB_Disp == USTB_STEP && MemWinStart+GRID_WIDTH == USTB_idx-1)
			{ MemWinStart += (GRID_WIDTH * draw_factor); }
	
			if (MemWinStart > MemoryEnd-GRID_WIDTH) MemWinStart = MemoryEnd-GRID_WIDTH;	// limiter

			Trig_Pos_Mem = USTB_idx;						// adjust pre trigger sign to actual USTB index position	
		}
		else										// shift mode
		{
			USTB_EOSignal++;

			if (USTB_EOSignal >= MemoryEnd)						// end of 16k reached?
			{
//printf("end of 16k signal reached\n\r");	
				USTB_EOSignal = MemStartOffs;
				if (SingleShot)							// check single mode
				{ UserIF::Buttonhandler(BTN_STOP); }				// set to stop mode
			}

			S1Ptr--; S2Ptr--; S3Ptr--; S4Ptr--; SMPtr--;				// increment memory pointer

			if(S1Ptr <= SHIFT_OFFS1)						// check for memory pointer overflow
			{ Signal::USTB_resetShiftBuffer(); }					// reset buffers and pointers
			

		}

		//printf("MemStartOffs: %d  MemoryEnd: %d  MemWinStart: %d  USTB_idx: %d   ",MemStartOffs, MemoryEnd, MemWinStart, USTB_idx);

	}
	else											// direction = reverse
	{
		if (USTB_Mode == USTB_ROLL)							// roll mode
		{
			if(USTB_idx <= MemStartOffs)						// check for time pointer overflow
			{ 
				USTB_idx = MemoryEnd; MemWinStart = MemoryEnd - GRID_WIDTH; 	// jump to end for circular buffering (roll mode)
				if (SingleShot)
				{ UserIF::Buttonhandler(BTN_STOP); }				// set to stop mode
			}
			else
			{ USTB_idx --;}								//decrement time pointer

			if (USTB_Disp == USTB_PERM && MemWinStart == USTB_idx+1)		// adjust memory window -> shift window left
			{ MemWinStart -= draw_factor;}	
			else if (USTB_Disp == USTB_STEP && MemWinStart == USTB_idx+1)
			{ MemWinStart -= (GRID_WIDTH * draw_factor); }
	
			if (MemWinStart < MemStartOffs) MemWinStart = MemStartOffs;		// limiter

			Trig_Pos_Mem = USTB_idx;						// adjust pre trigger sign to actual USTB index position
		}
		else										// shift mode
		{
			USTB_EOSignal--;

			if (USTB_EOSignal <= MemStartOffs)					// end of 16k reached?
			{
//printf("end of 16k signal reached\n\r");	
				USTB_EOSignal = MemoryEnd;
				if (SingleShot)							// check single mode
				{ UserIF::Buttonhandler(BTN_STOP); }				// set to stop mode
			}

			S1Ptr++; S2Ptr++; S3Ptr++; S4Ptr++; SMPtr++;				// increment memory pointer

			if(S1Ptr >= SIGNAL1)							// check for memory pointer overflow
			{ Signal::USTB_resetShiftBuffer(); }					// reset buffers and pointers
		}


	}
	Trig_Pos_Display = (int) ((float)(Trig_Pos_Mem - MemWinStart) / ZoomFactor);
	//Trig_Pos_Display_dmode = (int) (((float)(Trig_Pos_Mem - MemWinStart) / ZoomFactorDel) - ((float) Cursor_Delayed_1 * (ZoomFactor / ZoomFactorDel)));


	LED_ON[11] = 0;										//right LED (red) off -> data acquisition ready
	if(MenuStatus[MENU_TRIGGERSUB][2] == BTN_ON){ LED_ON[3] = 0; }				//Channel 4 LED off
	Hardware::Send_LED();

	//FFT_NewData = 1; 		//new data for FFT available

	ACQ_NewData = 1;		//New signal data acquired
	ADC_Data_Available = 0;

//printf("Acquisition ready\r\n");
 
}
//#####################################################################################################################################################
void Hardware::ISR_ADC_INT(int context)						// ADC interrupt subroutine
{
	adc_started = false;
	
	acq_ready->np_pioedgecapture = 0;
	
	ADC_Data_Available = 1;
//printf("ADC ready   ");
	
	if (USTB_Mode != USTB_OFF)
	Handle_USTB();
}
//#####################################################################################################################################################
int Hardware::Read_IRQ(void)
{
    return acq_ready->np_piodata;
}
//#####################################################################################################################################################
void Hardware::Handle_ADC(void)						// ADC handler
{
	volatile long buffer_addr = 0;	
	volatile long buffer_written = 0;	


	if (UI_request && !ZL_changed)	return;		// BF add  don't handle ADC if user interface must be handled first except zero level adjustment

	if (RC_request)	return;				// BF signal recall is requested -> don't handle ADC

 	if (USTB_Mode != USTB_OFF) return;

	if(test_signal)		// generate test signals
	{ Signal::generateTestSignal(); FFT_NewData = 1; ACQ_NewData = 1; ADC_Data_Available = 0; return;}
	
//printf("ADC_Data_Available = %d\r\n",ADC_Data_Available );
	if (ADC_Data_Available == 0) return;		// if no new data is available return

	ADC_Data_Available = 0;				// reset availability flag	

//printf("ADC Handler -> ADC data available\n\r");
//printf("ADC Handler\r\n");
	data_adr->np_piodata = 0x01;

	LED_ON[9] = 0;								//left LED 1 (green) off -> Trigger is not armed 
	if (MenuStatus[MENU_TRIGGERSUB][2] == BTN_ON){ LED_ON[2] = 0; }		//mapped channel 3 LED off


	//-------------------------------------------------------
	//		(Pre) Trigger Control
	//-------------------------------------------------------
	AutoFreeRun = false;

	//BF get start address of readout buffer
	if ((Selected_Trigger_Source == 3) || (Selected_Trigger_Source == 4))	
	{ buffer_addr = READADC(3); if ((buffer_addr & 0x0000FFFF) == 0x00000000) { AutoFreeRun = true; }}
	else 
	{ buffer_addr = READADC(1); if ((buffer_addr & 0x00001000) == 0x00001000) { AutoFreeRun = true; }}

	//printf("buffer_addr =  %x & 0x00001000 = %x \r", buffer_addr, buffer_addr & 0x00001000);	

	//BF calc buffer address with pretrigger offset
	if (AutoFreeRun == true)	//BF no trigger event occured
	{
		if ((buffer_addr & 0x00000FFF) == 0x00000000)
		{
			if (MainTimebase < 11) buffer_written = (buffer_addr & 0x00000FFF) + ((pre_reg - 8) >> 1); 	// 16Kbyte
			else buffer_written = (buffer_addr & 0x00000FFF) + (pre_reg - 8);				//  4Kbyte
		}
		else
		{	
			if (MainTimebase < 11) buffer_written = pre_reg >> 1;	// 16Kbyte
			else buffer_written = pre_reg;				//  4Kbyte
		}
	
		LED_ON[11] = 0;							//right LED (red) off -> no triggerevent 
		if(MenuStatus[MENU_TRIGGERSUB][2] == BTN_ON){ LED_ON[3] = 0; }	//Channel 4 LED off
	}
	else if (MainTimebase < 11)	//BF trigger event occured -> 16Kbyte
	{ 
		buffer_written = ((buffer_addr & 0x0FFF) - (pre_reg >> 1)) & 0x00000FFF;

		if (MenuStatus[MENU_TRIGGERSUB][1] == 121)			//triggerevent on
		{
			if(MenuStatus[MENU_TRIGGERSUB][2] == BTN_ON)
			{ LED_ON[3] = 1; }					//Channel 4 LED on
			else 
			{ LED_ON[11] = 1; }					//right LED (red) on -> triggerevent 
			Send_LED();
		}
	}	
	else	//low speed -> 4KB memory
	{ 
		buffer_written = ((buffer_addr & 0x0FFF) - pre_reg) & 0x00000FFF;

		if (MenuStatus[MENU_TRIGGERSUB][1] == 121)			//triggerevent on
		{
			if(MenuStatus[MENU_TRIGGERSUB][2] == BTN_ON)
			{ LED_ON[3] = 1; }					//Channel 4 LED on
			else 
			{ LED_ON[11] = 1; }					//right LED (red) on -> triggerevent 
			Send_LED();
		}
	}				//BF trigger event occured


	//BF set buffer start address
	WRITEADC(1, buffer_written);	
	WRITEADC(2, buffer_written);
	
	if (NumberOfChannels == 4)
	{				
		WRITEADC(3, buffer_written);
		WRITEADC(4, buffer_written);
	}

	data_adr->np_piodata = 0x00;

	if (ACQ_ManTrigg)	//manual trigger
	{
		ACQ_ManTrigg = 0;					//reset trigger flag

		if (MenuStatus[MENU_TRIGGERSUB][1] > 119)
		{
			if(MenuStatus[MENU_TRIGGERSUB][2] == BTN_ON)
			{ LED_ON[3] = 1; }				//Channel 4 LED on
			else 
			{ LED_ON[11] = 1; }				//right LED (red) on -> triggered
		}

		// Single green 
		LED_ON[14] = 0;
		LED_ON[15] = 1;

		//reset trigger to previous setting
		Hardware::SetupTrigger();
	}


	if (SingleShot == 1)							// handle stop/single mode
	{
		//printf("Single event occured\r\n"); 
		//SingleShot = 0;	-> reset of single flag in signal processing
		nr_delay(10);

		// Run/Stop LED red
		LED_ON[12] = 0;
		LED_ON[13] = 1;			
		
		// Single Mode LED green
		LED_ON[14] = 0;
		LED_ON[15] = 1;	
	}
	else if(!Run)								// BF add don't read the new data when stop mode is active and no single shot is done 
	{
		if (AutoFreeRun == false)
		{
			nr_delay(10);
			LED_ON[11] = 0;							//right LED (red) off -> triggerevent passed 
			if(MenuStatus[MENU_TRIGGERSUB][2] == BTN_ON){ LED_ON[3] = 0; }	//Channel 4 LED	
			Send_LED();
			//data_adr->np_piodata = 0x00;
	
			//printf("Trigger event while Stop mode\r\n"); 
		}
		Start_Record();
		return;
	}
	
	if (MenuStatus[MENU_TRIGGERSUB][1] == 120 && AutoFreeRun == false)	//triggered on
	{
		if(MenuStatus[MENU_TRIGGERSUB][2] == BTN_ON)
		{ LED_ON[3] = 1; }						//Channel 4 LED on
		else 
		{ LED_ON[11] = 1; }						//right LED (red) on -> triggered
	}
	Send_LED();

	//-------------------------------------------------------
	//		Signal Acquisition
	//-------------------------------------------------------
	if (Channel_1_Active)
	{ ReadOut_Signal(1); }
	
	if (Channel_2_Active)
	{ ReadOut_Signal(2); }	
	
	if (NumberOfChannels == 4)
	{	
		if (Channel_3_Active == 1)
		{ ReadOut_Signal(3); }
	
		if (Channel_4_Active == 1)
		{ ReadOut_Signal(4); }
	}	

	//printf("Acquisition ready!\r\n");

	//----------------------------------------------------------------------------------
	//				Pretrigger Compensation
	//----------------------------------------------------------------------------------
	if (Selected_Trigger_Source > 4)//external
	{ PreTrigComp = ExtTrigOffset[MainTimebase]; }	//BF #022
	else if (AutoFreeRun == false)
	{ PreTrigComp = TriggerCorrection(Selected_Trigger_Source, MenuStatus[MENU_TRIGGEREDGE][0] - 2, Trig_Pos_Mem); }
	else											//no trigger event occured -> set offset to zero
	{ PreTrigComp = 0; }


	//added by Stefan for combi-trigger	
	if (MenuStatus[MENU_TRIGGERMODE][0] == TRIG_COMB && CombiTriggerStatus >= 1)		//combi-trigger -> auto-mode enabled
	{
		//search for signal crossing triggervalue - calc borders
		unsigned char min=0,max=0;
		static unsigned char oldMin=0,oldMax=0;
		unsigned char *pSignal=0;
		unsigned char tvalue=0;
		
		if (CombiTriggerStatus == 1)							//if first time triggered by auto after switching to auto, reset oldMin,oldMax
		{
			oldMin=255;
			oldMax=0;
			CombiTriggerStatus=2;
		}
		
		//calc border for searching min and max in signal
		short start = (short) MemWinStart + PreTrigComp;
		if (start < 0) start = 0;
		
		short stop = start + ((GRID_WIDTH + 30) * draw_factor);
		if (stop > TrigPosMax){stop = TrigPosMax;}

		switch (Selected_Trigger_Source)
		{
			case 1:
			pSignal=SIGNAL1;
			tvalue = (int)((float)(Trigger_Pos_CH1-GRID_HEIGHT/2)/ScaleFactor[Selected_Voltage_CH1][GainIdx])+ADC_ZERO;
			break;
			case 2:
			pSignal=SIGNAL2;
			tvalue = (int)((float)(Trigger_Pos_CH2-GRID_HEIGHT/2)/ScaleFactor[Selected_Voltage_CH2][GainIdx])+ADC_ZERO;
			break;
			case 3:
			pSignal=SIGNAL3;
			tvalue = (int)((float)(Trigger_Pos_CH3-GRID_HEIGHT/2)/ScaleFactor[Selected_Voltage_CH3][GainIdx])+ADC_ZERO;
			break;
			case 4:
			pSignal=SIGNAL4;
			tvalue = (int)((float)(Trigger_Pos_CH4-GRID_HEIGHT/2)/ScaleFactor[Selected_Voltage_CH4][GainIdx])+ADC_ZERO;
			break;
		}

		Signal::calcMinMax(start,stop,1,pSignal,&min,&max);	
		
		if (((oldMin<tvalue) && (max>tvalue)) || ((oldMax>tvalue) && (min<tvalue)) || (min<tvalue && max>tvalue))
		{
			//triggervalue crossed--> enable normal-mode
			ctrl_reg &= 0xFFBF;		//activate normal-mode
			noTriggerTime      = 0;		//reset time-measurement
			CombiTriggerStatus = 0;		//reset co-trigger-status to normal-mode
			SetupADC();
		}
		oldMax=max;
		oldMin=min;
		
	}
	else	//combi-trigger -> normal-mode
	{ noTriggerTime = 0; }//reset time, because trigger-event occured within 500ms

	Start_Record();

	if (MenuStatus[MENU_TRIGGERSUB][0] == 115 && Run)			//trigger wait on
	{
		if(MenuStatus[MENU_TRIGGERSUB][2] == BTN_ON)
		{ LED_ON[2] = 1; }						//Channel 3 LED on
		else 
		{ LED_ON[9] = 1; }						//left LED (green) on -> Trigger is armed 
	}

	LED_ON[11] = 0;								//right LED (red) off -> no triggerevent 
	if(MenuStatus[MENU_TRIGGERSUB][2] == BTN_ON){ LED_ON[3] = 0; }		//Channel 4 LED

	Send_LED();


	FFT_NewData = 1; 		//new data for FFT available

	ACQ_NewData = 1;		//New signal data acquired

}
//#####################################################################################################################################################
// BF deleted unused parameters
void Hardware::ReadOut_Signal(char channel)
{
	int ix, ix2, ix3, enddata;
	int chk_calc     = 0;
	//BF del long buffer_long = 0;
	unsigned int read_out_count;


	if (USTB_Mode != USTB_OFF)	// ultra slow tb mode?
	  read_out_count = 32;//128;
	else if (MainTimebase < 11)	// 16Kbyte
 	  read_out_count = 4096;
	else				// 4Kbyte
	  read_out_count = 5004;



	switch(channel)
	{	
		//--------------------------------------------------
		//                   Channel 1
		//--------------------------------------------------
		case 1 :	
		{
			SIGNAL1 = (unsigned char *) 0x0091CC00; // set buffer to base address

			//channel coupling = ground -> set all values to zero		BF -> new ground function 
			if (MenuStatus[MENU_CHANNEL1][0] == 6) //GND-coupling
			{ 
				if (USTB_Mode == USTB_OFF) for(int i=0;i<0x4000;i++) SIGNAL1[i] = ADC_VirtualZero_CH1;
				else
				{
					for(int i=0;i<128;i++) SIGNAL1_USTB[i] = ADC_VirtualZero_CH1;
					Signal::USTB_insertSample(MenuStatus[MENU_CHANNEL1][2] - BTN_OFF, ADC_VirtualZero_CH1, SIGNAL1_USTB, S1Ptr);
				}
			}
			else
			{
				//BF del buffer_long = READADC(1);    // Read correction
				//BF del buffer_long = READADC(1);

/*BF test coding 		
				if(test_sw1)	//BF -> new C-routines for testing
				{
					ADC_ReadData(1, &readout_sigbuf[0], read_out_count);
					 					
					if (RealTimebase < 7 || USTB_Mode != USTB_OFF) //Highspeed
					{
						if (MenuStatus[MENU_ACQUIRE][1] == 241)
						{ ADC_ProcessData(1, &SIGNAL1[0], MenuStatus[MENU_CHANNEL1][2] - 240, Virtual_Zero, 1, 1); }	
						else
						{ ADC_ProcessData(1, &SIGNAL1[0], MenuStatus[MENU_CHANNEL1][2] - 240, Virtual_Zero, 0, 1); }	
				
					}
					else	//Lowspeed
					{
						if (MenuStatus[MENU_ACQUIRE][1] == 241)
						{ ADC_ProcessData(1, &SIGNAL1[0], MenuStatus[MENU_CHANNEL1][2] - 240, Virtual_Zero, 1, 0); }	
						else
						{ ADC_ProcessData(1, &SIGNAL1[0], MenuStatus[MENU_CHANNEL1][2] - 240, Virtual_Zero, 0, 0); }	
					}
				}
//BF test end	
				else	//BF -> Assembler routines as standard
*/				{
					READADC_ALL2(1, readout_sigbuf, read_out_count);
					PREPARE_READADC(ADC_Offset[0][0],ADC_Offset[0][1],ADC_Offset[0][2],ADC_Offset[0][3], read_out_count);	
					
					if (MainTimebase < 11)						//Highspeed  -> 16KB memory
					{ READADC_ALL(1, SIGNAL1, 1); }
					else if (USTB_Mode != USTB_OFF) 				//Highspeed  -> 128 byte USTB-buffer
					{ READADC_ALL(1, SIGNAL1_USTB, 1); Signal::USTB_insertSample(MenuStatus[MENU_CHANNEL1][2] - BTN_OFF, ADC_VirtualZero_CH1, SIGNAL1_USTB, S1Ptr); }
					else								//Lowspeed   -> 4KB memory
					{ READADC_ALL(1, SIGNAL1, 0); }
				}

				//BF #001 set buffer to corrected address if delay correction is active (buffer shift)
				if(MainTimebase < 5)
				{SIGNAL1 = &SIGNAL1[-CH1_Del_Correct];}
//printf("Ch1 readout\r\n");
			}

			break;
		}
		//--------------------------------------------------
		//                   Channel 2
		//--------------------------------------------------
		case 2 :
		{
			SIGNAL2 = (unsigned char *) 0x00920C00;		// set buffer to base address

			//channel coupling = ground -> set all values to zero
			if (MenuStatus[MENU_CHANNEL2][0] == 6) 
			{ 
				if (USTB_Mode == USTB_OFF) for(int i=0;i<0x4000;i++) SIGNAL2[i] = ADC_VirtualZero_CH2;
				else
				{
					for(int i=0;i<128;i++) SIGNAL2_USTB[i] = ADC_VirtualZero_CH2;
					Signal::USTB_insertSample(MenuStatus[MENU_CHANNEL2][2] - BTN_OFF, ADC_VirtualZero_CH2, SIGNAL2_USTB, S2Ptr);
				}
			}
			else
			{
				//BF del buffer_long = READADC(2);    // Read correction
				//BF del buffer_long = READADC(2);
					
				READADC_ALL2(2, readout_sigbuf, read_out_count);
				PREPARE_READADC(ADC_Offset[1][0],ADC_Offset[1][1],ADC_Offset[1][2],ADC_Offset[1][3], read_out_count);
		
				if (MainTimebase < 11)						//Highspeed  -> 16KB memory
				{ READADC_ALL(2, SIGNAL2, 1); }
				else if (USTB_Mode != USTB_OFF) 				//Highspeed  -> 128 byte
				{ READADC_ALL(2, SIGNAL2_USTB, 1); Signal::USTB_insertSample(MenuStatus[MENU_CHANNEL2][2] - BTN_OFF, ADC_VirtualZero_CH2, SIGNAL2_USTB, S2Ptr); }
				else								//Lowspeed   -> 4KB memory
				{ READADC_ALL(2, SIGNAL2, 0); }
	

				//BF #001 set buffer to corrected address if correction is active (buffer shift)
				if(MainTimebase < 5)
				{SIGNAL2 = &SIGNAL2[-CH2_Del_Correct];}

			}
            		break;
        	}
		//--------------------------------------------------
		//                   Channel 3
		//--------------------------------------------------
		case 3 :
		{
			SIGNAL3 = (unsigned char *) 0x00924C00;		// set buffer to base address

			//channel coupling = ground -> set all values to zero		BF -> new ground function 
			if (MenuStatus[MENU_CHANNEL3][0] == 6) 
			{ 
				if (USTB_Mode == USTB_OFF) for(int i=0;i<0x4000;i++) SIGNAL3[i] = ADC_VirtualZero_CH3;
				else
				{
					for(int i=0;i<128;i++) SIGNAL3_USTB[i] = ADC_VirtualZero_CH3;
					Signal::USTB_insertSample(MenuStatus[MENU_CHANNEL3][2] - BTN_OFF, ADC_VirtualZero_CH3, SIGNAL3_USTB, S3Ptr);
				}
			}
			else
			{
				//BF del buffer_long = READADC(3);    // Read correction
				//BF del buffer_long = READADC(3);
//BF test del				buffer_long = READADC(3);    // Read correction
				
				// Get new Signal Data
				READADC_ALL2(3, readout_sigbuf, read_out_count);
				PREPARE_READADC(ADC_Offset[2][0],ADC_Offset[2][1],ADC_Offset[2][2],ADC_Offset[2][3], read_out_count);
			
				if (MainTimebase < 11)						//Highspeed  -> 16KB memory
				{ READADC_ALL(3, SIGNAL3, 1); }
				else if (USTB_Mode != USTB_OFF) 				//Highspeed  -> 128 byte
				{ READADC_ALL(3, SIGNAL3_USTB, 1); Signal::USTB_insertSample(MenuStatus[MENU_CHANNEL3][2] - BTN_OFF, ADC_VirtualZero_CH3, SIGNAL3_USTB, S3Ptr); }
				else								//Lowspeed   -> 4KB memory
				{ READADC_ALL(3, SIGNAL3, 0); }

				//BF #001 set buffer to corrected address if delay correction is active (buffer shift)
				if(MainTimebase < 5)
				{SIGNAL3 = &SIGNAL3[-CH3_Del_Correct];}

			}
			break;
		}
		//--------------------------------------------------
		//                   Channel 4
		//--------------------------------------------------
		case 4 :	
		{
			SIGNAL4 = (unsigned char *) 0x00928C00;		// set buffer to base address
	
			//channel coupling = ground -> set all values to zero		BF -> new ground function 
			if (MenuStatus[MENU_CHANNEL4][0] == 6) 
			{ 
				if (USTB_Mode == USTB_OFF) for(int i=0;i<0x4000;i++) SIGNAL4[i] = ADC_VirtualZero_CH4;
				else
				{
					for(int i=0;i<128;i++) SIGNAL4_USTB[i] = ADC_VirtualZero_CH4;
					Signal::USTB_insertSample(MenuStatus[MENU_CHANNEL4][2] - BTN_OFF, ADC_VirtualZero_CH4, SIGNAL4_USTB, S4Ptr);
				}
			}
			else
			{
				//BF del buffer_long = READADC(4);    // Read correction
				//BF del buffer_long = READADC(4);
//BF test del				buffer_long = READADC(4);
				
				// Get new Signal Data
				READADC_ALL2(4, readout_sigbuf, read_out_count);
				PREPARE_READADC(ADC_Offset[3][0],ADC_Offset[3][1],ADC_Offset[3][2],ADC_Offset[3][3], read_out_count);
	
				if (MainTimebase < 11)						//Highspeed  -> 16KB memory
				{ READADC_ALL(4, SIGNAL4, 1); }
				else if (USTB_Mode != USTB_OFF) 				//Highspeed  -> 128 byte
				{ READADC_ALL(4, SIGNAL4_USTB, 1); Signal::USTB_insertSample(MenuStatus[MENU_CHANNEL4][2] - BTN_OFF, ADC_VirtualZero_CH4, SIGNAL4_USTB, S4Ptr); }
				else								//Lowspeed   -> 4KB memory
				{ READADC_ALL(4, SIGNAL4, 0); }

				//BF #001 set buffer to corrected address if correction is active (buffer shift)
				if(MainTimebase < 5)
				{SIGNAL4 = &SIGNAL4[-CH4_Del_Correct];}
//printf("Ch4, ");
			}
			break;

		}

	}//Ende switch channel
}
//#####################################################################################################################################################
//BF new fix for trigger calculating by Stefan
//BF ->  The pretrigger has an time offset of 70 at high speed TB and 40 at low speed TB. This routine calculates the correction dynamically.
int Hardware::TriggerCorrection(unsigned char channel, unsigned char negativ, int TriggerPos)
{
	int ix, foundat = 0, start, range;
	int tl_buf = 0;

	switch(channel)
	{
		case 1 : tl_buf = (int)((float)(Trigger_Pos_CH1-GRID_HEIGHT/2)/ScaleFactor[Selected_Voltage_CH1][GainIdx])+ADC_ZERO; break;//Stefan
		case 2 : tl_buf = (int)((float)(Trigger_Pos_CH2-GRID_HEIGHT/2)/ScaleFactor[Selected_Voltage_CH2][GainIdx])+ADC_ZERO; break;
		case 3 : tl_buf = (int)((float)(Trigger_Pos_CH3-GRID_HEIGHT/2)/ScaleFactor[Selected_Voltage_CH3][GainIdx])+ADC_ZERO; break;
		case 4 : tl_buf = (int)((float)(Trigger_Pos_CH4-GRID_HEIGHT/2)/ScaleFactor[Selected_Voltage_CH4][GainIdx])+ADC_ZERO; break;
	}
	
	if (MainTimebase < 11)	//memory length is 16K
	{
		start = TriggerPos + 50;	// set start point near to the real triggerevent
		foundat = TriggerPos + 70;	// default correction
	}
	else	// 4K
	{ 
		start = TriggerPos + 25;	// set start point near to the real triggerevent
		foundat = TriggerPos + 40;	// default correction
	}

//return foundat - TriggerPos;	//Test without dynamic stabilizing


	range = TriggerPos + 300;
	if (range > TrigPosMax) range = TrigPosMax;

	//start searching for the next edge in range
	if (negativ)	//falling edge
	{
		switch(channel)
		{
			case 1 :
			{
				for (ix = start; ix < range; ix++)
				{
					if (SIGNAL1[ix] > tl_buf)
					{
						foundat = ix;
						break;
					}
				}
				break;
			}
			case 2 :
			{
				for (ix = start; ix < range; ix++)
				{
					if (SIGNAL2[ix] > tl_buf)
					{
						foundat = ix;
						break;
					}
				}
				break;
			}
			case 3 :
			{
				for (ix = start; ix < range; ix++)
				{
					if (SIGNAL3[ix] > tl_buf)
					{
						foundat = ix;
						break;
					}
				}
				break;
			}
			case 4 :
			{
				for (ix = start; ix < range; ix++)
				{
					if (SIGNAL4[ix] > tl_buf)
					{
						foundat = ix;
						break;
					}
				}
				break;
			}
		}

	}
	else	//rising edge
	{
		switch(channel)
		{
			case 1 :
			{
				for (ix = start; ix < range; ix++)
				{
					if (SIGNAL1[ix] < tl_buf)
					{
						foundat = ix;
						break;
					}
				}
				break;
			}
			case 2 :
			{
				for (ix = start; ix < range; ix++)
				{
					if (SIGNAL2[ix] < tl_buf)
					{
						foundat = ix;
						break;
					}
				}
				break;
			}
			case 3 :
			{
				for (ix = start; ix < range; ix++)
				{
					if (SIGNAL3[ix] < tl_buf)
					{
						foundat = ix;
						break;
					}
				}
				break;
			}
			case 4 :
			{
				for (ix = start; ix < range; ix++)
				{
					if (SIGNAL4[ix] < tl_buf)
					{
						foundat = ix;
						break;
					}
				}
				break;
			}
		}

	}
		
	return foundat - TriggerPos;


}
//#####################################################################################################################################################
//Auto scale
int Hardware::AutoScale(char slow_tb)
{
	int subrc1 = 0, subrc2=0, subrc3=0, subrc4=0;
	unsigned char lGainIdx_bak;
	char Trigger_Source_bak;

	//Run_bak        = Run;
	//SingleShot_bak = SingleShot;
	lGainIdx_bak   = GainIdx;

	Run = 1;
	SingleShot = 0;
	//GainIdx    = 1;			//force pre amp to 1.25
	//AS_request = 1;
	
	LED_ON[12] = 1;	// Run/Stop green
	LED_ON[13] = 0; // single off

	// show popup with message and progress indicator
	Display::DRAWROUNDBUTTON(190, 180, 260, 80, 0, 0);	// draw popup
	if (slow_tb) Display::TEXTOUTxvbig("Autoscale TB range 500ms - 10&s", 200, 192, 1, UI_Plane2);
	else Display::TEXTOUTxvbig("Autoscale TB range 2ms - 2ns", 200, 192, 1, UI_Plane2);
	Display::Rect(200, 220, 240, 20, 1, UI_Plane1);		// draw white box
	Display::Rect(200, 220, 20, 20, 1, UI_Plane2);		// draw black box as progress indicator

	//Stop_Record();			
	//for(int timeout=0;(timeout < 500) && acq_ready->np_piodata == 0x01;timeout++)
	//nr_delay(5);
	
	if (USTB_Mode != USTB_OFF)	//was USTB mode active?
	{
		Hardware::Stop_Timer2();

		//deactivate roll/shift mode and backup setting in menu
		USTB_Mode_bak = USTB_Mode;
		USTB_Mode = USTB_OFF;					//switch off USTB mode
	}

	DoDisableUARTInterrupt();
	DoDisableADCInterrupt();
	DoDisableKeyInterrupt();
	DoDisableRotInterrupt();
	
	ADC_Data_Available = 0;
	acq_ready->np_pioedgecapture = 0;

	//switch trigger to Auto
	MenuStatus[MENU_TRIGGERMODE][0] = TRIG_COMB;  	//set trigger combi mode
	Display::MenuPopupInit(9, MENU_TRIGGERMODE, 92);
	HoldOff.Write_Value(0.0);			// holdoff off
	HoldOff_Value = 0;
	MenuStatus[MENU_TRIGGEREDGE][0] = 2;		// rising
	TriggerWay = TRIG_EDGE;				// trigger edge
	LED_ON[8] = 1;					// edge on
	LED_ON[10] = 0;					// puls off

	Send_LED();

	Trigger_Source_bak      = Selected_Trigger_Source;

	MenuStatus[MENU_CHANNEL1][0] = 7;	// AC
	MenuStatus[MENU_CHANNEL2][0] = 7;	// AC
	MenuStatus[MENU_CHANNEL3][0] = 7;	// AC
	MenuStatus[MENU_CHANNEL4][0] = 7;	// AC

	MenuStatus[MENU_CHANNEL1][1] = BTN_OFF;	// BW
	MenuStatus[MENU_CHANNEL2][1] = BTN_OFF;	// BW
	MenuStatus[MENU_CHANNEL3][1] = BTN_OFF;	// BW
	MenuStatus[MENU_CHANNEL4][1] = BTN_OFF;	// BW

	SetSwitches(1, -1);			// set coupling

	if (slow_tb) MainTimebase = 20;	
	else MainTimebase = 14;	

	// find matching voltage ranges
	if (Channel_1_Active) FindVoltage(1);
	Display::Rect(220, 220, 40, 20, 1, UI_Plane2);		// draw black box as progress indicator

	if (Channel_2_Active) FindVoltage(2);
	Display::Rect(260, 220, 40, 20, 1, UI_Plane2);		// draw black box as progress indicator

	if (Channel_3_Active) FindVoltage(3);
	Display::Rect(300, 220, 40, 20, 1, UI_Plane2);		// draw black box as progress indicator

	if (Channel_4_Active) FindVoltage(4);
	Display::Rect(340, 220, 40, 20, 1, UI_Plane2);		// draw black box as progress indicator

	// find matching timebase
	if (MenuStatus[MENU_AUTOSCALE][3]==280) 					//search at trigger source
	{
		FindTimebase(Trigger_Source_bak,slow_tb);
		subrc1 = 1; subrc2 = 1; subrc3 = 1; subrc4 = 1;
	}
	else										// search in channel order for new trigger source
	{
		// find matching timebase
		if (Channel_1_Active) subrc1 = FindTimebase(1,slow_tb);
		if ((Channel_2_Active && subrc1==-1) || (Channel_2_Active && !Channel_1_Active)) subrc2 = FindTimebase(2,slow_tb);
		if ((Channel_3_Active && subrc2==-1) || (Channel_3_Active && !Channel_2_Active)) subrc3 = FindTimebase(3,slow_tb);
		if ((Channel_4_Active && subrc3==-1) || (Channel_4_Active && !Channel_3_Active)) subrc4 = FindTimebase(4,slow_tb);
	}

	//if no signal is found anywhere -> reset to old triggersource
	if (((subrc1<1) && (subrc2<1) && (subrc3<1) && (subrc4<1)) || Selected_Trigger_Source == 0 )
	{
		Selected_Trigger_Source = Trigger_Source_bak;
		TriggerWay = TRIG_EDGE;							// edge triggering
		MenuStatus[MENU_TRIGGEREDGE][1] = 136 + Selected_Trigger_Source;	// source menu
		Display::MenuPopupInit(28, MENU_TRIGGEREDGE, 137);
	}

	Display::Rect(380, 220, 60, 20, 1, UI_Plane2);

	Display::RecalcTimeParameters();

	acq_ready->np_pioedgecapture = 0;

	MenuStatus[MENU_CHANNEL1][0] = 8;	// DC
	MenuStatus[MENU_CHANNEL2][0] = 8;	// DC
	MenuStatus[MENU_CHANNEL3][0] = 8;	// DC
	MenuStatus[MENU_CHANNEL4][0] = 8;	// DC

	SetSwitches(1, -1);			// set coupling
	nr_delay(100);

	Display::DRAWROUNDBUTTON(190, 180, 260, 80, 0, 1);				// delete popup
	Display::Rect(200, 220, 240, 20, 0, UI_Plane1);					// remove white box
	Display::Rect(200, 190, 240, 52, 0, UI_Plane2);					// remove indicator and text
	//for (int i=Display_Line_Adresses[190]; i < Display_Line_Adresses[241]; i++)	// delete progress indicator and text
	//{ UI_Plane2[i] = 0; UI_Plane1[i] = 0;}	

	DispatchTraces();

	TRIG_AutoPretrigger();

	DoEnableRotInterrupt();
	DoEnableKeyInterrupt();
	DoEnableADCInterrupt();
	DoEnableUARTInterrupt();

	nr_delay(50);
	//SetupTrigger();
	
	TimebaseChanged = 1;
	TimeOffsetChanged = 1;
	TriggerLevelChanged = 1;
	TriggerModeChanged = 1;
	TriggerWayChanged = 1;
	VoltageChangedCh1 = 1;	
	VoltageChangedCh2 = 1;	
	VoltageChangedCh3 = 1;	
	VoltageChangedCh4 = 1;	
	
	GainIdx = lGainIdx_bak;
		
	Display::StatusUpdate();

	Display::MenuInit();

	if (Memory_Window_visible)
        Display::DRAWMEMORY(1, 0, 0);		//close memory window

	if (Cursor_Enabled)
	{
		Display::CALCCURSORDATA();
		Menu_Changed = 1;
		CursorChanged = 4;
	}
	
	if (QM_Enabled)
	{
		Display::CALCQMDATA();
		Menu_Changed = 1;
	}

	if (Selected_Trigger_Source > 0 && Selected_Trigger_Source < 5)
	{
		//start_acq->np_piodata = 0x01;				//start record Port On
		//start_acq->np_piodata = 0x00;				//start record Port Off
		Start_Record();

		//wait for ADC
		//for(short timeout=0;(timeout < 200) && acq_ready->np_piodata == 0x01;timeout++)
		for(short timeout=0;(timeout < 200) && ADC_Data_Available == 0;timeout++)
		nr_delay((MainTimebase+1)*2);

		data_adr->np_piodata = 0x01;
		
		//READADC(Selected_Trigger_Source);	
		//WRITEADC(Selected_Trigger_Source, 0);
		READADC(1);	
		WRITEADC(1, 0);
		WRITEADC(2, 0);
	
		if (NumberOfChannels > 2)
		{
			READADC(3);
			WRITEADC(3, 0);
			WRITEADC(4, 0);
		}

		data_adr->np_piodata = 0x00;
		ReadOut_Signal(Selected_Trigger_Source);
	
		TRIG_AutoLevel();
		timer_rotary_busy->np_timercontrol = ((timer_rotary_busy->np_timercontrol & 3) + np_timercontrol_stop_mask);	// Stop Timer, disable interrupt
		timer_rotary_busy->np_timerstatus  = 0;										// clear the ISR
	}
	
	Display::DRAW_ALL_CURSOR();

	Start_Record();

	config_changed = 0;
	AS_request = 0;
	TriggerLevelActive = 0;

    	return 0;
}
//#####################################################################################################################################################
int Hardware::FindTimebase(char channel, char slow_tb)
{
	int ix, edges=0, max_cnt, cnt = 0, cnt2 = 0;
	int lIntFactor;
	int max_tb = 25;	//500ms
	
	unsigned char buf_min;
	unsigned char buf_max;
	unsigned char buf_byte;
	unsigned char avrg = 0;

	unsigned char *lPtrSignal = NULL;
	
	char lVoltage=0;


	if (slow_tb)
	printf("\r\nStart searching slow timebase channel %d\r\n", channel);
	else
	printf("\r\nStart searching timebase channel %d\r\n", channel);

	
	switch(channel)
	{
		case 1: lPtrSignal = SIGNAL1; lVoltage = Selected_Voltage_CH1 - 3; break;
		case 2: lPtrSignal = SIGNAL2; lVoltage = Selected_Voltage_CH2 - 3;break; 
		case 3: lPtrSignal = SIGNAL3; lVoltage = Selected_Voltage_CH3 - 3;break;
		case 4: lPtrSignal = SIGNAL4; lVoltage = Selected_Voltage_CH4 - 3;break;
	}

	if(lVoltage < 3) lVoltage = 3;

	// set voltage range
	SetSwitches(channel, lVoltage);
	nr_delay(200);	//wait for capacitor

	max_cnt = 0;
	
	// slow TB?
	if (slow_tb){ max_tb = 25; MainTimebase = 21; }			// start with 20ms -> range is 500ms - 10µs	
	else{ max_tb = 18; MainTimebase = 8; }//11; }				// start with 10µs -> range is 2ms - 2ns

//	timebase_reg = tb_value[MainTimebase];

	triggering = 0;		// switch off trigger
			
	for(;;)
	{
		max_cnt++;

		if (MainTimebase <= 8) // 1GSa/s
		{ pre_reg = 0x002D; }
		else if (MainTimebase == 9)
		{ pre_reg = 0x003C; }
		else if (MainTimebase == 10)
		{ pre_reg = 0x0055; }
		else if (MainTimebase == 11)
		{ pre_reg = 0x0120; }
		else if (MainTimebase == 12)
		{ pre_reg = 0x0120; }
		else if (MainTimebase > 12 && MainTimebase < 25)
		{ pre_reg = 0x0110; }

		SetupADC();						//set pre trigger and timebase registers
		nr_delay(50);

		start_acq->np_piodata = 0x01;				//start record Port On
		start_acq->np_piodata = 0x00;				//start record Port Off
	
		//wait for ADC
		int timeout;
		for(timeout=0;(timeout < 200) && acq_ready->np_piodata == 0x01;timeout++)
		nr_delay((MainTimebase+1)*2);
	
		if (timeout >= 200 ){ printf("Timeout\r\n"); continue; }

		data_adr->np_piodata = 0x01;
	
		READADC(1);	
		WRITEADC(1, 0);
		WRITEADC(2, 0);
	
		if (NumberOfChannels > 2)
		{
			READADC(3);
			WRITEADC(3, 0);
			WRITEADC(4, 0);
		}
		
		data_adr->np_piodata = 0x00;

		switch(channel)
		{
			case 1 : ReadOut_Signal(1); break;
			case 2 : ReadOut_Signal(2); break;
			case 3 : ReadOut_Signal(3); break;
			case 4 : ReadOut_Signal(4); break;
		}

		buf_byte = 0;
	
		// draw factor
		lIntFactor = (int) ZoomFactorTable[MainTimebase];
		if (lIntFactor <= 0) lIntFactor = 1;

		// get minima and maxima
		buf_min = 255;
		buf_max = 0;

		for (ix=150, cnt=0; cnt < 600; cnt++, ix+=lIntFactor)
		{
			buf_byte = lPtrSignal[ix];
			buf_arr[cnt] = buf_byte;
			if (buf_min > buf_byte) buf_min = buf_byte;
			if (buf_max < buf_byte) buf_max = buf_byte;
		}
		
		edges = 0;	
	
		// signal found?
		if ( (buf_max - buf_min) > 10 )
		{
			// calculate average
			avrg = (unsigned char) (((int) buf_min + (int) buf_max) >> 1);
	
			// search signal edges
			for (ix=3; ix < 597; ix++)
			{
				//printf("buf_arr[%d] %d",ix, buf_arr[ix]);
				if ((buf_arr[ix - 3] > avrg + 1) && (buf_arr[ix + 3] < avrg - 1)) { printf("rising edge->%d\r\n",ix); edges++; ix+=10;  }	// rising edge
				if ((buf_arr[ix - 3] < avrg - 1) && (buf_arr[ix + 3] > avrg + 1)) { printf("falling edge->%d\r\n",ix); edges++; ix+=10;  } 	// falling edge
				//printf("\r\n");
			}
		}	

		printf("TimeBase %d Zoom %d Edges %d avrg %d bmin %d bmax %d\r\n", MainTimebase, lIntFactor, edges, avrg, buf_min, buf_max);

		if ((edges < 3 && !slow_tb) || (edges < 4 && slow_tb))//4		// go to next slower TB if less than 1 period is on the screen
		{
			MainTimebase++;
//			timebase_reg = tb_value[MainTimebase];

			SetupADC();
		}
		else if (MainTimebase == 4 && edges > 8)//6			// check if interpolation is needed for very high frequencies
		{
			if (edges > 40)
			{
				printf("\r\nStarting HF search\r\n");

				// search HF signal edges
				for (ix=3, edges=0; ix < 597; ix++)
				{
					//printf("buf_arr[%d] %d",ix, buf_arr[ix]);
					if ((buf_arr[ix - 2] > avrg + 1) && (buf_arr[ix + 2] < avrg - 1)) { printf("rising edge->%d\r\n",ix); edges++; ix+=4;  }	// rising edge
					if ((buf_arr[ix - 2] < avrg - 1) && (buf_arr[ix + 2] > avrg + 1)) { printf("falling edge->%d\r\n",ix); edges++; ix+=4;  } 	// falling edge
					//printf("\r\n");
				}

				if (edges > 100)
				{
					printf("\r\nStarting UHF search\r\n");
	
					// search HF signal edges
					for (ix=3, edges=0; ix < 597; ix++)
					{
						//printf("buf_arr[%d] %d",ix, buf_arr[ix]);
						if ((buf_arr[ix - 1] > avrg + 1) && (buf_arr[ix + 1] < avrg - 1)) { printf("rising edge->%d\r\n",ix); edges++; ix+=2;  }	// rising edge
						if ((buf_arr[ix - 1] < avrg - 1) && (buf_arr[ix + 1] > avrg + 1)) { printf("falling edge->%d\r\n",ix); edges++; ix+=2;  } 	// falling edge
						//printf("\r\n");
					}
				}
			}

			if (edges < 15)
			{ MainTimebase = 3; }
			else if (edges < 30)
			{ MainTimebase = 2; }
			else if (edges < 80)
			{ MainTimebase = 1; }
			else 
			{ MainTimebase = 0; }

			lIntFactor = 0;
			printf("TimeBase %d Zoom %d Edges %d avrg %d bmin %d bmax %d\r\n", MainTimebase, lIntFactor, edges, avrg, buf_min, buf_max);

			break;
		}
		else if (MainTimebase > 4 && edges > 8)				// go to next faster TB if more than 3 periods are on the screen
		{
			MainTimebase--;
//			timebase_reg = tb_value[MainTimebase];

			SetupADC();
		}
		else
		{ break;}

		if (MainTimebase == max_tb) { edges = -1; break; }	// no matching TB found

		if (max_cnt >= 10) { edges = -1; break; }		// no matching TB found
    	}

	// signal found?
	if ( edges < 0 && (buf_max - buf_min) < 15)	// nothing found
	{
		if (slow_tb)
		MainTimebase = 18;	// 200µs
		else
		MainTimebase = 4;	// 50ns

//		timebase_reg = tb_value[MainTimebase];
		edges = -1;
		printf("No Signal found -> ");
		lIntFactor = 1;
	}
	else						// search was successfull
	{
		// set triggersource
		Selected_Trigger_Source = channel;			// set new trigger source
		TriggerWay = TRIG_EDGE;					// edge triggering
		MenuStatus[MENU_TRIGGEREDGE][1] = 136 + channel;	// source menu
		Display::MenuPopupInit(28, MENU_TRIGGEREDGE, 137);
	}
	printf("Set Timebase %d Zoom %d channel %d\r\n", MainTimebase, lIntFactor, channel);


	// reset voltage range to previous setting
	switch(channel)
	{
		case 1: SetSwitches(channel, Selected_Voltage_CH1); break;
		case 2: SetSwitches(channel, Selected_Voltage_CH2); break;
		case 3: SetSwitches(channel, Selected_Voltage_CH3); break;
		case 4: SetSwitches(channel, Selected_Voltage_CH4); break;
	}	//5V

	return edges;
}
//#####################################################################################################################################################
//BF optimized 
int Hardware::FindVoltage(char channel)
{
	int ix, cnt, lIntFactor, volt = 12;
	short deltaV, maxV; //topV, bottomV;

	unsigned char buf_min = 0, buf_max = 0, buf_delta;
	unsigned char buf_byte = 0;

	short scr_max = 0, scr_min = 0, scr_delta = 0;

	unsigned char *lPtrSignal = NULL;

    	printf("\r\nStart searching range channel %d\r\n", channel);

	//Stop_Record();

	// thresholds due to the new DC offset adjusting -> now converted to screen values
	switch(Channels_Active)
	{
		case 1 : deltaV = 150; maxV = GRID_HEIGHT; break;
		case 2 : deltaV = 75; maxV = GRID_HEIGHT/2; break;
		case 3 : deltaV = 70; maxV = GRID_HEIGHT/3; break;
		default : deltaV = 50; maxV = GRID_HEIGHT/4;
	}


	//printf("Switch off triggering\r\n");
	triggering = 0;		// switch off trigger
	SetupADC();
	nr_delay(50);	

	for(;;)	//endless loop -> start with Volt = 11 -> 5V
	{
		if (volt > 3) { volt--; }//printf("decrement volt %d\n", volt); }
		else break;
	
		printf("Set switches to voltage range %d\r\n", volt);
		SetSwitches(channel, volt);				// set new voltage range

		//nr_delay(30);

		// adjust zero
		if( volt == 9 || volt == 6 || volt == 3 || volt == 0)//1 V
		{
			CH1_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][0][0];
			CH2_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][1][0];
			CH3_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][2][0];
			CH4_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][3][0];
		}
		else if( volt == 10 || volt == 7 || volt == 4 || volt == 1)//2 V
		{
			CH1_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][0][1];
			CH2_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][1][1];
			CH3_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][2][1];
			CH4_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][3][1];
		}
		else if( volt == 11 || volt == 8 || volt == 5 || volt == 2)//5 V
		{
			CH1_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][0][2];
			CH2_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][1][2];
			CH3_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][2][2];
			CH4_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][3][2];
		}

		SetDacOffset(channel);	

		nr_delay(100);	


		// start ADC
		//printf("Start ADC\r\n");
		start_acq->np_piodata = 0x01;				//start record Port On
		start_acq->np_piodata = 0x00;				//start record Port Off	
	
		//while (acq_ready->np_piodata == 0x01 && !ADC_Data_Available) {}
		//wait for ADC
		int timeout;
		for(timeout=0;(timeout < 200) && acq_ready->np_piodata == 0x01;timeout++)
		nr_delay((MainTimebase+1)*2);
	
		if (timeout >= 200 ){ printf("Timeout\r\n"); continue; }

		data_adr->np_piodata = 0x01;
	
		READADC(1);
		WRITEADC(1, 0);	
		WRITEADC(2, 0);	
	
		if (NumberOfChannels > 2)
		{
			READADC(3);
			WRITEADC(3, 0);	
			WRITEADC(4, 0);	
		}
		
		data_adr->np_piodata = 0x00;
	
		switch(channel)
		{
			case 1 : ReadOut_Signal(1); lPtrSignal = SIGNAL1; break;
			case 2 : ReadOut_Signal(2); lPtrSignal = SIGNAL2; break;
			case 3 : ReadOut_Signal(3); lPtrSignal = SIGNAL3; break;
			case 4 : ReadOut_Signal(4); lPtrSignal = SIGNAL4; break;
		}
	
		// draw factor
		lIntFactor = (int) ZoomFactorTable[MainTimebase];
		if (lIntFactor <= 0) lIntFactor = 1;
	
		buf_min = 255;
		buf_max = 0;

		// get minimum and maximum
		//printf("Get minima and maxima\r\n");
		for (ix=150, cnt=0; cnt < 600 ; cnt++, ix+=lIntFactor)
		{
			buf_byte = lPtrSignal[ix];

			if (buf_min > buf_byte)	{ buf_min = buf_byte; }
			if (buf_max < buf_byte)	{ buf_max = buf_byte; }
		}
		//if ((buf_min < topV) || (buf_max > bottomV) || (abs(buf_max - buf_min) > deltaV)) break;
		
		scr_max = ScaleLookupTable[buf_max][ScaleIndexTable[volt]];
		scr_min = ScaleLookupTable[buf_min][ScaleIndexTable[volt]];
		//scr_delta = (short)abs((int)(scr_max - scr_min));
		scr_delta = scr_max - scr_min;
		printf("Min %d  Max %d  Delta %d  Thrhld %d  Volt %d \r\n", scr_min, scr_max, scr_delta, deltaV, volt);

		if (scr_delta > deltaV) break;
	}

	// limiter -> check if range is too small	
	if (scr_delta > maxV && volt<11)
	{
		volt++; printf("Limiter -> switch back to volt %d\r\n",volt);

		SetSwitches(channel, volt);				// set new voltage range
		// adjust zero
		if( volt == 9 || volt == 6 || volt == 3 || volt == 0)//1 V
		{
			CH1_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][0][0];
			CH2_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][1][0];
			CH3_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][2][0];
			CH4_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][3][0];
		}
		else if( volt == 10 || volt == 7 || volt == 4 || volt == 1)//2 V
		{
			CH1_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][0][1];
			CH2_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][1][1];
			CH3_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][2][1];
			CH4_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][3][1];
		}
		else if( volt == 11 || volt == 8 || volt == 5 || volt == 2)//5 V
		{
			CH1_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][0][2];
			CH2_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][1][2];
			CH3_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][2][2];
			CH4_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][3][2];
		}

		SetDacOffset(channel);	

		nr_delay(50);	

	 }

	// if lowest voltage range is reached without finding a signal -> switch back to old range
	if ( volt == 3 && (buf_min > 115) && (buf_max < 140))
	{
		switch(channel)
		{
			case 1 : volt = Selected_Voltage_CH1; SetSwitches(1, Selected_Voltage_CH1); break;
			case 2 : volt = Selected_Voltage_CH2; SetSwitches(2, Selected_Voltage_CH2); break;	
			case 3 : volt = Selected_Voltage_CH3; SetSwitches(3, Selected_Voltage_CH3); break;
			case 4 : volt = Selected_Voltage_CH4; SetSwitches(4, Selected_Voltage_CH4); break;
		}
		printf("No Signal found -> set to old voltage range\r\n ");
	}	


	switch(channel)
	{
		case 1 : Selected_Voltage_CH1 = volt;  VoltageChangedCh1 = 1; Display::DRAWSTATUS(1, 0); break;	// Draw Voltage Channel 1
		case 2 : Selected_Voltage_CH2 = volt;  VoltageChangedCh2 = 1; Display::DRAWSTATUS(2, 0); break;	// Draw Voltage Channel 2
		case 3 : Selected_Voltage_CH3 = volt;  VoltageChangedCh3 = 1; Display::DRAWSTATUS(3, 0); break;	// Draw Voltage Channel 3
		case 4 : Selected_Voltage_CH4 = volt;  VoltageChangedCh4 = 1; Display::DRAWSTATUS(4, 0); break;	// Draw Voltage Channel 4
	}


}
//##########################################################################################################################################################
/* BF not used
void Hardware::FindSlope(void)
{
	long buf_long = 0, buf_long1 = 0;
	int cnt = 0;
	// Only two channels so far
	
    Hardware::DoDisableUARTInterrupt();
    Hardware::DoDisableADCInterrupt();
    Hardware::DoDisableKeyInterrupt();
    Hardware::DoDisableRotInterrupt();

    Stop_Record();


 	
//    Display::DRAWROUNDBUTTON(230, 180, 220, 80, 0, 0);
//    Display::TEXTOUTxvbig("For startup calibration", 247, 192, 1, UI_Plane2);
//    Display::TEXTOUTxvbig("remove all input lines.", 247, 212, 1, UI_Plane2);
//    Display::TEXTOUTxvbig("Press any key to continue.", 247, 232, 1, UI_Plane2);

  //  printf("Press a key\n");

//	key_reset->np_piodata = 0;										// Reset Keyboard
//	nr_delay(1);
//	key_reset->np_piodata = 1;
//	key_int->np_pioedgecapture = 0;									// clear IRQ conditions	

 //   while (key_int->np_pioedgecapture == 0) {};

//   printf("Yes, a key\n");
	
	// Backup old
    triggering_bak = triggering;
    ctrl_reg_bak = ctrl_reg;
    adc_ctrl_reg_bak = adc_ctrl_reg;
    adc_change12_reg_bak = adc_change12_reg;
    adc_change34_reg_bak = adc_change34_reg;

    RealTimebase_bak = RealTimebase;
    SIGNALFaktor_idx_bak = SIGNALFaktor_idx;
    SIGNAL_StartFr_idx_bak = SIGNAL_StartFr_idx;
    timebase_reg_bak = timebase_reg;
    MainTimebase_bak = MainTimebase;
    Run_bak = Run;
    SingleShot_bak = SingleShot;

    Selected_Voltage_CH1_bak = Selected_Voltage_CH1;
    Selected_Voltage_CH2_bak = Selected_Voltage_CH2;
    Selected_Voltage_CH3_bak = Selected_Voltage_CH3;
    Selected_Voltage_CH4_bak = Selected_Voltage_CH4;   	

    ZeroLevelCH1_bak = ZeroLevelCH1;
    ZeroLevelCH2_bak = ZeroLevelCH2;
    ZeroLevelCH3_bak = ZeroLevelCH3;
    ZeroLevelCH4_bak = ZeroLevelCH4;

    Virtual_ZeroLevelCH1_bak = Virtual_ZeroLevelCH1;
    Virtual_ZeroLevelCH2_bak = Virtual_ZeroLevelCH2;
    Virtual_ZeroLevelCH3_bak = Virtual_ZeroLevelCH3;
    Virtual_ZeroLevelCH4_bak = Virtual_ZeroLevelCH4;


    CH1_DAC_Correction_1_bak = CH1_DAC_Correction_1;	
    CH1_DAC_Correction_2_bak = CH1_DAC_Correction_2;
    CH1_DAC_Correction_3_bak = CH1_DAC_Correction_3;

    CH2_DAC_Correction_1_bak = CH2_DAC_Correction_1;	
    CH2_DAC_Correction_2_bak = CH2_DAC_Correction_2;
    CH2_DAC_Correction_3_bak = CH2_DAC_Correction_3;

    CH3_DAC_Correction_1_bak = CH3_DAC_Correction_1;	
    CH3_DAC_Correction_2_bak = CH3_DAC_Correction_2;
    CH3_DAC_Correction_3_bak = CH3_DAC_Correction_3;

    CH4_DAC_Correction_1_bak = CH4_DAC_Correction_1;	
    CH4_DAC_Correction_2_bak = CH4_DAC_Correction_2;
    CH4_DAC_Correction_3_bak = CH4_DAC_Correction_3;
	
	// set test data
	
    CH1_DAC_Correction_1 = 0;	
    CH1_DAC_Correction_2 = 0;
    CH1_DAC_Correction_3 = 0;

    CH2_DAC_Correction_1 = 0;	
    CH2_DAC_Correction_2 = 0;
    CH2_DAC_Correction_3 = 0;

    CH3_DAC_Correction_1 = 0;	
    CH3_DAC_Correction_2 = 0;
    CH3_DAC_Correction_3 = 0;

    CH4_DAC_Correction_1 = 0;	
    CH4_DAC_Correction_2 = 0;
    CH4_DAC_Correction_3 = 0;	

    ZeroLevelCH1 = GRID_HEIGHT / 2;
    Virtual_ZeroLevelCH1 = 0;                                 // Virtual ZeroLevel
    //BF del	CH1_Zero_Offset = 0;                                        // Shift offset when stopped

    ZeroLevelCH2 = GRID_HEIGHT / 2;
    Virtual_ZeroLevelCH2 = 0;                                 // Virtual ZeroLevel
    //BF del	CH2_Zero_Offset = 0;                                        // Shift offset when stopped

    Rotary_Steps = 0;
    Hardware::UserIF::ON_Zero_Channel_1();

    nr_delay(100);

    Rotary_Steps = 0;
    Hardware::UserIF::ON_Zero_Channel_2();

    Hardware::SetSwitches(1, 11);

    nr_delay(100);

    Hardware::SetSwitches(2, 11);    	

    nr_delay(100);

    RealTimebase  = 4;                                          //  50 nS
    SIGNALFaktor_idx   = 0;                                           // zoom factor 1 = 50 nS
    SIGNAL_StartFr_idx = 0;                                         // running. so 0

    timebase_reg = tb_value[RealTimebase];
    MainTimebase = 4;                                          // Displayed timebase is 50 ns

    HoldOff_Value = 0;
    triggering = 0;								
    //ctrl_reg &= 0xC0FF;							// Clear Pulse and HoldOff bits
    ctrl_reg = 0x0087;							                    // Trigger_Master / Trigger_INT / Free Run
    adc_ctrl_reg &= 0x0100;						                    // Disable Trigger sources
	                     	

    // test generator settings
    adc_change12_reg = 0x30000000;                //  Bit 28 - TestGenerator  - Filter
    adc_change34_reg = 0x10000000;                //  Bit 28 - TestGenerator
    SwitchesCH2 = 0x66DA;                       // TestCounter CH I - IV + 5V Channel II
					
    Hardware::SetSwitches(2, -1);


    la_pulse->np_piodata = 0x01;				//stop record Port On
    la_pulse->np_piodata = 0x00;				//stop record Port Off	
                             																						
    Hardware::SetupADC();
    nr_delay(100);
    Hardware::SetupADC();

    // Run as long not found


//    Hardware::READADC(1);

    acq_ready->np_pioedgecapture = 0;
    acq_ready->np_piodata = 0x00;

 //   while ((buf_long & 0x1000) == 0)
    {
        // first reag
        start_acq->np_piodata = 0x01;				//start record Port On
        start_acq->np_piodata = 0x00;				//start record Port Off

        //printf("slope started\n");	

        while (acq_ready->np_piodata == 0x01)
        {
//#ifdef _Debug_
            //printf("1\n");
            nr_delay(500);

//            Hardware::SetupADC();
//            start_acq->np_piodata = 0x01;				//start record Port On
//            start_acq->np_piodata = 0x00;				//start record Port Off	

            cnt++;
            if (cnt == 20)
            {
//                printf("Slope stoped");
                break;
            }
//#endif
        }


        data_adr->np_piodata = 0x01;

        buf_long  = Hardware::READADC(1);
        buf_long1 = Hardware::READADC(1);

        Hardware::WRITEADC(1, ram_adress_reg);
        Hardware::WRITEADC(2, ram_adress_reg);

        if (NumberOfChannels > 2)
        {
            Hardware::WRITEADC(3, ram_adress_reg);
            Hardware::WRITEADC(4, ram_adress_reg);
        }
    	
        data_adr->np_piodata = 0x00;

        ReadOut_Signal(1, buf_long, 0);
        ReadOut_Signal(2, buf_long, 0);
        if (NumberOfChannels > 2)
        {
            ReadOut_Signal(3, buf_long, 0);
            ReadOut_Signal(4, buf_long, 0);
        }
#ifdef _Debug_
        printf("bl %04x bl1 %08x\n", buf_long, buf_long1);
#endif
    }

    la_gate->np_piodata = 0x00;
    slope_value = la_data->np_piodata;


    // restore old
    triggering = triggering_bak;
    ctrl_reg = ctrl_reg_bak;
    adc_ctrl_reg = adc_ctrl_reg_bak;

    Run = Run_bak;
    SingleShot = SingleShot_bak;

    SwitchesCH2 &= 0x00FF;
    adc_change12_reg = adc_change12_reg_bak;
    adc_change34_reg = adc_change34_reg_bak;

    RealTimebase = RealTimebase_bak;
    SIGNALFaktor_idx = SIGNALFaktor_idx_bak;
    SIGNAL_StartFr_idx = SIGNAL_StartFr_idx_bak;
    timebase_reg = timebase_reg_bak;
    MainTimebase = MainTimebase_bak;

    Selected_Voltage_CH1 = Selected_Voltage_CH1_bak;
    Selected_Voltage_CH2 = Selected_Voltage_CH2_bak;
    Selected_Voltage_CH3 = Selected_Voltage_CH3_bak;
    Selected_Voltage_CH4 = Selected_Voltage_CH4_bak;   	

    ZeroLevelCH1 = ZeroLevelCH1_bak;
    ZeroLevelCH2 = ZeroLevelCH2_bak;
    ZeroLevelCH3 = ZeroLevelCH3_bak;
    ZeroLevelCH4 = ZeroLevelCH4_bak;

    Virtual_ZeroLevelCH1 = Virtual_ZeroLevelCH1_bak;
    Virtual_ZeroLevelCH2 = Virtual_ZeroLevelCH2_bak;
    Virtual_ZeroLevelCH3 = Virtual_ZeroLevelCH3_bak;
    Virtual_ZeroLevelCH4 = Virtual_ZeroLevelCH4_bak;

    CH1_DAC_Correction_1 = CH1_DAC_Correction_1_bak;	
    CH1_DAC_Correction_2 = CH1_DAC_Correction_2_bak;
    CH1_DAC_Correction_3 = CH1_DAC_Correction_3_bak;

    CH2_DAC_Correction_1 = CH2_DAC_Correction_1_bak;	
    CH2_DAC_Correction_2 = CH2_DAC_Correction_2_bak;
    CH2_DAC_Correction_3 = CH2_DAC_Correction_3_bak;

    CH3_DAC_Correction_1 = CH3_DAC_Correction_1_bak;	
    CH3_DAC_Correction_2 = CH3_DAC_Correction_2_bak;
    CH3_DAC_Correction_3 = CH3_DAC_Correction_3_bak;

    CH4_DAC_Correction_1 = CH4_DAC_Correction_1_bak;	
    CH4_DAC_Correction_2 = CH4_DAC_Correction_2_bak;
    CH4_DAC_Correction_3 = CH4_DAC_Correction_3_bak;

    Hardware::SetupTrigger(33);

    Rotary_Steps = 0;
    Hardware::UserIF::ON_Zero_Channel_1();
    Rotary_Steps = 0;
    Hardware::UserIF::ON_Zero_Channel_2();

    Hardware::SetSwitches(1, Selected_Voltage_CH1);
    Hardware::SetSwitches(2, Selected_Voltage_CH2);



//    Display::DRAWROUNDBUTTON(230, 180, 220, 80, 0, 1);
//    Display::TEXTOUTxvbig("For startup calibration", 247, 192, 0, UI_Plane2);
//    Display::TEXTOUTxvbig("remove all input lines.", 247, 212, 0, UI_Plane2);
//    Display::TEXTOUTxvbig("Press any key to continue.", 247, 232, 0, UI_Plane2);	


    Hardware::DoEnableRotInterrupt();
    Hardware::DoEnableKeyInterrupt();
    Hardware::DoEnableADCInterrupt();
    Hardware::DoEnableUARTInterrupt();	
#ifdef _Debug_
    printf("Slope : %x\n", slope_value);
#endif
}
*/

void Hardware::DoEnableReadVSyncInterrupt(void)							// Enable ReadVSync service routine
{

	read_vsync->np_pioedgecapture = 0x00; 							// clear existing IRQ conditions
	read_vsync->np_piodirection = 0;							// set bit to input
	read_vsync->np_piointerruptmask = 0x01;							// enable interrupt

	nr_installuserisr(na_read_vsync_irq,ISR_ReadVSync_INT,(int)read_vsync);			// Install ISR for ReadVSync
#ifdef _Debug_IRQ_
	if (Debug_Mode) printf("read_vsync interrupt enabled.\n"); 				// print on console
#endif	

}

void Hardware::DoDisableReadVSyncInterrupt(void)						// Disable ReadVSync service routine
{
	nr_installuserisr(na_read_vsync_irq,0,0); 						// Install empty routine for ReadVSync irq
	read_vsync->np_piointerruptmask = 0x00;							// disable all IRQs
}

void Hardware::ISR_ReadVSync_INT(int context)							// ReadVSync interrupt subroutine
{
    	tc_test_var2++;
	VSync_Needed = 1;	

	read_vsync->np_pioedgecapture = 0;							// clear IRQ conditions	
	//printf("read_vsync interrupt occured\r\n");
	printf("VSync counter: %d\r\n",tc_test_var2++);
}
//##########################################################################################################################################################
/* BF copy buffer planes to display planes (channel planes). 
   This is necessary, because direct writing and deleting in the channel planes causes
   a flickering signal. To avoid this the signal is written into the buffer plane first
   and then copied to the channel plane.
*/
void Hardware::TransferPlanes(void)
{
	int cnt;
	
	//if (VSync_Needed == 0) return;
	if (MenuPopupActive > -1) return;
	
	if (UpdateMarkerPlane)
	{
	 	TransferPlanes_asm_persistant(0x008CABE4, 0x009D9DF0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1);
		UpdateMarkerPlane = false;
	}
	
	if (UpdateMenuTextPlane)
	{
		if ((QM_Enabled == 1) || (Cursor_Enabled == 1))				//BF add by Guido
		{ TransferDataPlane_asm_persistant(0x008DBB24, 0x00970F30); }		//BF add by Guido	
		else
		{ TransferDataPlane_asm_persistant(0x008DC254, 0x00971660); }		//BF -> fixed by Guido 			

		UpdateMenuTextPlane = false;	
	}
	
	//if (Splash_drawed) return;
	
	if (MenuStatus[MENU_DISPLAY][0] == BTN_OFF)	//delete channel plane and copy buffer plane
	{
	
		switch(ClearPlane)
		{
			//only channel planes	-> offset from plane start address is 5F0
			case 0x01 : TransferPlanes_asm(0x0093A7F0, 0x0098EDF0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1); break;	//copy Buffer_Plane1 to Channel_Plane1
			case 0x02 : TransferPlanes_asm(0x00943DF0, 0x009983F0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1); break;	//copy Buffer_Plane2 to Channel_Plane2
			case 0x03 : TransferPlanes_asm(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x00000000, 0x00000000, 2); break;	//copy Buffer_1 to Channel_1 and Buffer_2 to Channel_2
			case 0x04 : TransferPlanes_asm(0x0094D3F0, 0x009A19F0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1); break;	//copy Buffer_Plane3 to Channel_Plane3
			case 0x05 : TransferPlanes_asm(0x0093A7F0, 0x0098EDF0, 0x0094D3F0, 0x009A19F0, 0x00000000, 0x00000000, 2); break;	//copy Buffer_1 to Channel_1 and Buffer_2 to Channel_2
			case 0x06 : TransferPlanes_asm(0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 0x00000000, 0x00000000, 2); break;	//copy Buffer_1 to Channel_1 and Buffer_3 to Channel_3	
			case 0x07 : TransferPlanes_asm(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 3); break;
			case 0x08 : TransferPlanes_asm(0x009569F0, 0x009AAFF0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1); break;	//copy Buffer_Plane4 to Channel_Plane4
			case 0x09 : TransferPlanes_asm(0x0093A7F0, 0x0098EDF0, 0x009569F0, 0x009AAFF0, 0x00000000, 0x00000000, 2); break;
			case 0x0A : TransferPlanes_asm(0x00943DF0, 0x009983F0, 0x009569F0, 0x009AAFF0, 0x00000000, 0x00000000, 2); break;	
			case 0x0B : TransferPlanes_asm(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x009569F0, 0x009AAFF0, 3); break;
			case 0x0C : TransferPlanes_asm(0x0094D3F0, 0x009A19F0, 0x009569F0, 0x009AAFF0, 0x00000000, 0x00000000, 2); break;	
			case 0x0D : TransferPlanes_asm(0x0093A7F0, 0x0098EDF0, 0x0094D3F0, 0x009A19F0, 0x009569F0, 0x009AAFF0, 3); break;
			case 0x0E : TransferPlanes_asm(0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 0x009569F0, 0x009AAFF0, 3); break;
		
			case 0x0F :
			{
				TransferPlane_Set_Buffer_Adr(0x009569F0, 0x009AAFF0, 0x00000000, 0x00000000);
				TransferPlanes_asm(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 4);			//copy to all channel planes
				break;
			}
		
			// additional math plane
			case 0x10 : TransferPlanes_asm(0x009311F0, 0x009B45F0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1); break;	//copy Buffer_PlaneM to Channel_Math_Plane	
			case 0x11 : TransferPlanes_asm(0x0093A7F0, 0x0098EDF0, 0x009311F0, 0x009B45F0, 0x00000000, 0x00000000, 2); break;
			case 0x12 : TransferPlanes_asm(0x00943DF0, 0x009983F0, 0x009311F0, 0x009B45F0, 0x00000000, 0x00000000, 2); break;	
			case 0x13 : TransferPlanes_asm(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x009311F0, 0x009B45F0, 3); break;	
			case 0x14 : TransferPlanes_asm(0x0094D3F0, 0x009A19F0, 0x009311F0, 0x009B45F0, 0x00000000, 0x00000000, 2); break;
			case 0x15 : TransferPlanes_asm(0x0093A7F0, 0x0098EDF0, 0x0094D3F0, 0x009A19F0, 0x009311F0, 0x009B45F0, 3); break;	
			case 0x16 : TransferPlanes_asm(0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 0x009311F0, 0x009B45F0, 3); break;
		
			case 0x17 :
			{
				TransferPlane_Set_Buffer_Adr(0x009311F0, 0x009B45F0, 0x00000000, 0x00000000);
				TransferPlanes_asm(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 4);			//copy to math plane and 3 channel planes
				break;
			}
		
			case 0x18 : TransferPlanes_asm(0x009569F0, 0x009AAFF0, 0x009311F0, 0x009B45F0, 0x00000000, 0x00000000, 2); break;		
			case 0x19 : TransferPlanes_asm(0x0093A7F0, 0x0098EDF0, 0x009569F0, 0x009AAFF0, 0x009311F0, 0x009B45F0, 3); break;		
			case 0x1A : TransferPlanes_asm(0x00943DF0, 0x009983F0, 0x009569F0, 0x009AAFF0, 0x009311F0, 0x009B45F0, 3); break;		
		
			case 0x1B :
			{
				TransferPlane_Set_Buffer_Adr(0x009311F0, 0x009B45F0, 0x00000000, 0x00000000);
				TransferPlanes_asm(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x009569F0, 0x009AAFF0, 4);
				break;
			}
		
			case 0x1C : TransferPlanes_asm(0x0094D3F0, 0x009A19F0, 0x009569F0, 0x009AAFF0, 0x009311F0, 0x009B45F0, 3); break;	
		
			case 0x1D :
			{
				TransferPlane_Set_Buffer_Adr(0x009311F0, 0x009B45F0, 0x00000000, 0x00000000);
				TransferPlanes_asm(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009A19F0, 0x009569F0, 0x009AAFF0, 4);
				break;
			}
		
			case 0x1E :
			{
				TransferPlane_Set_Buffer_Adr(0x009311F0, 0x009B45F0, 0x00000000, 0x00000000);
				TransferPlanes_asm(0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 0x009569F0, 0x009AAFF0, 4);
				break;
			}
		
			case 0x1F :
			{
				TransferPlane_Set_Buffer_Adr(0x009569F0, 0x009AAFF0, 0x009311F0, 0x009B45F0);
				TransferPlanes_asm(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 5);			//copy to math plane and all channel planes
				break;
			}  		
		} 
	}
	else	// copy buffer planes without deleting channel planes to keep the old trace
	{	
		switch(ClearPlane)
		{
			case 0x01 : TransferPlanes_asm_persistant(0x0093A7F0, 0x0098EDF0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1);break;	//copy Buffer_Plane1 to Channel_Plane1
			case 0x02 : TransferPlanes_asm_persistant(0x00943DF0, 0x009983F0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1);break;	//copy Buffer_Plane2 to Channel_Plane2
			case 0x03 : TransferPlanes_asm_persistant(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x00000000, 0x00000000, 2);break;	//copy Buffer_1 to Channel_1 and Buffer_2 to Channel_2
			case 0x04 : TransferPlanes_asm_persistant(0x0094D3F0, 0x009A19F0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1);break;	//copy Buffer_Plane3 to Channel_Plane3	
			case 0x05 : TransferPlanes_asm_persistant(0x0093A7F0, 0x0098EDF0, 0x0094D3F0, 0x009A19F0, 0x00000000, 0x00000000, 2);break;	//copy Buffer_1 to Channel_1 and Buffer_2 to Channel_2
			case 0x06 : TransferPlanes_asm_persistant(0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 0x00000000, 0x00000000, 2);break;	//copy Buffer_1 to Channel_1 and Buffer_3 to Channel_3	
			case 0x07 : TransferPlanes_asm_persistant(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 3);break;
			case 0x08 : TransferPlanes_asm_persistant(0x009569F0, 0x009AAFF0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1);break;	//copy Buffer_Plane4 to Channel_Plane4
			case 0x09 : TransferPlanes_asm_persistant(0x0093A7F0, 0x0098EDF0, 0x009569F0, 0x009AAFF0, 0x00000000, 0x00000000, 2);break;
			case 0x0A : TransferPlanes_asm_persistant(0x00943DF0, 0x009983F0, 0x009569F0, 0x009AAFF0, 0x00000000, 0x00000000, 2);break;
			case 0x0B : TransferPlanes_asm_persistant(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x009569F0, 0x009AAFF0, 3);break;
			case 0x0C : TransferPlanes_asm_persistant(0x0094D3F0, 0x009A19F0, 0x009569F0, 0x009AAFF0, 0x00000000, 0x00000000, 2);break;
			case 0x0D : TransferPlanes_asm_persistant(0x0093A7F0, 0x0098EDF0, 0x0094D3F0, 0x009A19F0, 0x009569F0, 0x009AAFF0, 3);break;
			case 0x0E : TransferPlanes_asm_persistant(0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 0x009569F0, 0x009AAFF0, 3);break;
		
			case 0x0F :
			{
				TransferPlane_Set_Buffer_Adr(0x009569F0, 0x009AAFF0, 0x00000000, 0x00000000);
				TransferPlanes_asm_persistant(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 4);
				break;
			}
		
			case 0x10 : TransferPlanes_asm_persistant(0x009311F0, 0x009B45F0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1);break;
			case 0x11 : TransferPlanes_asm_persistant(0x0093A7F0, 0x0098EDF0, 0x009311F0, 0x009B45F0, 0x00000000, 0x00000000, 2);break;
			case 0x12 : TransferPlanes_asm_persistant(0x00943DF0, 0x009983F0, 0x009311F0, 0x009B45F0, 0x00000000, 0x00000000, 2);break;
			case 0x13 : TransferPlanes_asm_persistant(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x009311F0, 0x009B45F0, 3);break;
			case 0x14 : TransferPlanes_asm_persistant(0x0094D3F0, 0x009A19F0, 0x009311F0, 0x009B45F0, 0x00000000, 0x00000000, 2);break;
			case 0x15 : TransferPlanes_asm_persistant(0x0093A7F0, 0x0098EDF0, 0x0094D3F0, 0x009A19F0, 0x009311F0, 0x009B45F0, 3);break;
			case 0x16 : TransferPlanes_asm_persistant(0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 0x009311F0, 0x009B45F0, 3);break;
		
			case 0x17 :
			{
				TransferPlane_Set_Buffer_Adr(0x009311F0, 0x009B45F0, 0x00000000, 0x00000000);
				TransferPlanes_asm_persistant(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 4);
				break;
			}
		
			case 0x18 : TransferPlanes_asm_persistant(0x009569F0, 0x009AAFF0, 0x009311F0, 0x009B45F0, 0x00000000, 0x00000000, 2);break;
			case 0x19 : TransferPlanes_asm_persistant(0x0093A7F0, 0x0098EDF0, 0x009569F0, 0x009AAFF0, 0x009311F0, 0x009B45F0, 3);break;
			case 0x1A : TransferPlanes_asm_persistant(0x00943DF0, 0x009983F0, 0x009569F0, 0x009AAFF0, 0x009311F0, 0x009B45F0, 3);break;
		
			case 0x1B :
			{
				TransferPlane_Set_Buffer_Adr(0x009311F0, 0x009B45F0, 0x00000000, 0x00000000);
				TransferPlanes_asm_persistant(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x009569F0, 0x009AAFF0, 4);
				break;
			}
		
			case 0x1C : TransferPlanes_asm_persistant(0x0094D3F0, 0x009A19F0, 0x009569F0, 0x009AAFF0, 0x009311F0, 0x009B45F0, 3);break;
		
			case 0x1D :
			{
				TransferPlane_Set_Buffer_Adr(0x009311F0, 0x009B45F0, 0x00000000, 0x00000000);
				TransferPlanes_asm_persistant(0x0093A7F0, 0x0098EDF0, 0x0094D3F0, 0x009A19F0, 0x009569F0, 0x009AAFF0, 4);
				break;
			}
		
			case 0x1E :
			{
				TransferPlane_Set_Buffer_Adr(0x009311F0, 0x009B45F0, 0x00000000, 0x00000000);
				TransferPlanes_asm_persistant(0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 0x009569F0, 0x009AAFF0, 4);
				break;
			}
		
			case 0x1F :
			{
				TransferPlane_Set_Buffer_Adr(0x009569F0, 0x009AAFF0, 0x009311F0, 0x009B45F0);
				TransferPlanes_asm_persistant(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 5);
				break;
			}
		}
	}


       	if (init_done){ Display::DRAWSIGNS(); }		// draw zero markers
       	if (Menu_Changed){ Display::UpdateMenu(); }	// redraw buttons


//BF test 	
	if(!UI_request)	ZL_changed = 0;
	
	VS_TrigLevelChanged = 0;	//reset triggerlevel change flag
	VS_ZeroLevelChanged = 0;	//reset zerolevel change flag
//test end

	//BF test ClearPlane &= 0xE0;
	ClearPlane = 0xE0;	
    	VSync_Needed = 0;
    	
	//reset_watchdog->np_piodata = 0x01;								// Enable WatchDog	

}
//##########################################################################################################################################################
void Hardware::ClearPlanes(void)
{
//	reset_watchdog->np_piodata = 0x00;								// Disable WatchDog
	
	if (Channel_1_Active == 1) DrawPlane |= 0x01;	
	if (Channel_2_Active == 1) DrawPlane |= 0x02;
	
	if (Channel_3_Active == 1) DrawPlane |= 0x04;
	if (Channel_4_Active == 1) DrawPlane |= 0x08;
	
	if (Channel_Math_Active == 1) DrawPlane |= 0x10;

	ClearPlane = DrawPlane | RemovePlane;
	DrawPlane = 0;
   	   	
	//printf("ClearPlane = %x\r\n");

	switch(ClearPlane)
	{
		case 0x01 :
		{ TransferPlanes_clear_asm(0x0093A7F0, 0x0098EDF0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1); break; }
		case 0x02 :
		{ TransferPlanes_clear_asm(0x00943DF0, 0x009983F0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1); break; }
		case 0x03 :
		{ TransferPlanes_clear_asm(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x00000000, 0x00000000, 2); break; }
		case 0x04 :
		{ TransferPlanes_clear_asm(0x0094D3F0, 0x009A19F0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1); break; }
		case 0x05 :
		{ TransferPlanes_clear_asm(0x0093A7F0, 0x0098EDF0, 0x0094D3F0, 0x009A19F0, 0x00000000, 0x00000000, 2); break; }
		case 0x06 :
		{ TransferPlanes_clear_asm(0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 0x00000000, 0x00000000, 2); break; }
		case 0x07 :
		{ TransferPlanes_clear_asm(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 3); break; }	
		case 0x08 :
	    	{ TransferPlanes_clear_asm(0x009569F0, 0x009AAFF0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1); break; }
        	case 0x09 :
	    	{ TransferPlanes_clear_asm(0x0093A7F0, 0x0098EDF0, 0x009569F0, 0x009AAFF0, 0x00000000, 0x00000000, 2); break; }
        	case 0x0A :
	    	{ TransferPlanes_clear_asm(0x00943DF0, 0x009983F0, 0x009569F0, 0x009AAFF0, 0x00000000, 0x00000000, 2); break; }
		case 0x0B :
		{
		TransferPlanes_clear_asm(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x009569F0, 0x009AAFF0, 3);
		break;
			}
		case 0x0C :
		{
		TransferPlanes_clear_asm(0x0094D3F0, 0x009A19F0, 0x009569F0, 0x009AAFF0, 0x00000000, 0x00000000, 2);
		break;	
			}
		case 0x0D :
		{
		TransferPlanes_clear_asm(0x0093A7F0, 0x0098EDF0, 0x0094D3F0, 0x009A19F0, 0x009569F0, 0x009AAFF0, 3);
		break;
			}
		case 0x0E :
		{
		TransferPlanes_clear_asm(0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 0x009569F0, 0x009AAFF0, 3);
		break;
			}
		case 0x0F :
		{
		TransferPlane_Set_Buffer_Adr(0x009569F0, 0x009AAFF0, 0x00000000, 0x00000000);
		TransferPlanes_clear_asm(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 4);
		break;
			}     	
		case 0x10 :
		{
		TransferPlanes_clear_asm(0x009311F0, 0x009B45F0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1);
		break;	
			}
		case 0x11 :
		{
		TransferPlanes_clear_asm(0x0093A7F0, 0x0098EDF0, 0x009311F0, 0x009B45F0, 0x00000000, 0x00000000, 2);
		break;
			}
		case 0x12 :
		{
		TransferPlanes_clear_asm(0x00943DF0, 0x009983F0, 0x009311F0, 0x009B45F0, 0x00000000, 0x00000000, 2);
		break;	
			}
		case 0x13 :
		{  	
		TransferPlanes_clear_asm(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x009311F0, 0x009B45F0, 3);
		break;	
			}
		case 0x14 :
		{
		TransferPlanes_clear_asm(0x0094D3F0, 0x009A19F0, 0x009311F0, 0x009B45F0, 0x00000000, 0x00000000, 2);
		break;
			}
		case 0x15 :
		{
		TransferPlanes_clear_asm(0x0093A7F0, 0x0098EDF0, 0x0094D3F0, 0x009A19F0, 0x009311F0, 0x009B45F0, 3);
		break;	
			}
		case 0x16 :
		{
		TransferPlanes_clear_asm(0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 0x009311F0, 0x009B45F0, 3);
		break;
			}
		case 0x17 :
		{
		TransferPlane_Set_Buffer_Adr(0x009311F0, 0x009B45F0, 0x00000000, 0x00000000);
		TransferPlanes_clear_asm(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 4);
		break;		
			}
		case 0x18 :
		{
		TransferPlanes_clear_asm(0x009569F0, 0x009AAFF0, 0x009311F0, 0x009B45F0, 0x00000000, 0x00000000, 2);
		break;		
			}                                        		
		case 0x19 :
		{
		TransferPlanes_clear_asm(0x0093A7F0, 0x0098EDF0, 0x009569F0, 0x009AAFF0, 0x009311F0, 0x009B45F0, 3);
		break;		
			}               		
		case 0x1A :
		{
		TransferPlanes_clear_asm(0x00943DF0, 0x009983F0, 0x009569F0, 0x009AAFF0, 0x009311F0, 0x009B45F0, 3);
		break;		
			}
		case 0x1B :
		{
		TransferPlane_Set_Buffer_Adr(0x009311F0, 0x009B45F0, 0x00000000, 0x00000000);	
		TransferPlanes_clear_asm(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x009569F0, 0x009AAFF0, 4);
		break;		
			}
		case 0x1C :
		{
		TransferPlanes_clear_asm(0x0094D3F0, 0x009A19F0, 0x009569F0, 0x009AAFF0, 0x009311F0, 0x009B45F0, 3);
		break;	
			}
		case 0x1D :
		{
		TransferPlane_Set_Buffer_Adr(0x009311F0, 0x009B45F0, 0x00000000, 0x00000000);
		TransferPlanes_clear_asm(0x0093A7F0, 0x0098EDF0, 0x0094D3F0, 0x009A19F0, 0x009569F0, 0x009AAFF0, 4);
		break;
			}
		case 0x1E :
		{
		TransferPlane_Set_Buffer_Adr(0x009311F0, 0x009B45F0, 0x00000000, 0x00000000);
		TransferPlanes_clear_asm(0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 0x009569F0, 0x009AAFF0, 4);
		break;	
			}           		
		case 0x1F :
		{
		TransferPlane_Set_Buffer_Adr(0x009569F0, 0x009AAFF0, 0x009311F0, 0x009B45F0);
		TransferPlanes_clear_asm(0x0093A7F0, 0x0098EDF0, 0x00943DF0, 0x009983F0, 0x0094D3F0, 0x009A19F0, 5);
		break;
			}		
	}	
	

	ClearPlane &= 0xE0;	
}
//##########################################################################################################################################################
//BF changed by Guido
void Hardware::TransferDataPlane_asm_persistant(unsigned long Buffer_Adr1, unsigned long Plane_Adr1)
{
	if ((QM_Enabled == 1) || (Cursor_Enabled == 1))
	{
		asm("
            		PFX	    %hi(1460)                	; //Set Counter 	BF-> 1460 for cursor data
            		MOVI	%l1,%lo(1460)			; 

            		loopmtpp1:
            		LD     %l0, [%i0]                  	; //Load Buffer Data to %r0 	
            		ST     [%i1], %l0                  	; //Store it to Plane

            		ADDI   %i0, 4               		; //Add Address Counter
            		ADDI   %i1, 4	
	
            		SUBI   %l1, 1              		; //Decrement Line Counter
            		SKPS   cc_z
            		BR     loopmtpp1
            		NOP 	
        		");
	}
	else
	{
		asm("
            		PFX	    %hi(1000)                	; //Set Counter 	BF-> change from 1460 to 1000 for new grid size to avoid pixel error
            		MOVI	%l1,%lo(1000)			; //BF-> new value calculated by Guido

            		loopmtpp1_a:
            		LD     %l0, [%i0]                  	; //Load Buffer Data to %r0 	
            		ST     [%i1], %l0                  	; //Store it to Plane

            		ADDI   %i0, 4               		; //Add Address Counter
            		ADDI   %i1, 4	
	
            		SUBI   %l1, 1              		; //Decrement Line Counter
            		SKPS   cc_z
            		BR     loopmtpp1_a
            		NOP 	
        		");
	}
}

void Hardware::TransferPlane_Set_Buffer_Adr(unsigned long Buffer_Adr1, unsigned long Plane_Adr1, unsigned long Buffer_Adr2, unsigned long Plane_Adr2)
{
    asm("
            MOV		%r4,%i0	
            MOV		%r5,%i1

            MOV		%r6,%i2
            MOV		%r7,%i3
        ");
}

void Hardware::TransferPlanes_asm(unsigned long Buffer_Adr1, unsigned long Plane_Adr1, unsigned long Buffer_Adr2, unsigned long Plane_Adr2, unsigned long Buffer_Adr3, unsigned long Plane_Adr3, unsigned char count)
{
	switch(count)
	{
	    case 1 :
	    {
	        asm("
                    PFX	    %hi(8060)                         ; Set Counter
                    MOVI	%l1,%lo(8060)

                    PFX	    %hi(0)                            ; Set Clear register
                    MOVI	%l2,%lo(0)
                    PFX	    %xhi(0)
                    MOVHI	%l2,%xlo(0)	
	
                    looptp1:
                    LD     %l0, [%i0]                        ; Load Buffer Data to %r0 	
                    ST     [%i1], %l0                        ; Store it to Plane
                    ST     [%i0], %l2                        ; Clear Buffer

                                                               	
                    ADDI   %i0, 4                            ; Add Address Counter
                    ADDI   %i1, 4	

	
                    SUBI   %l1, 1                            ; Decrement Line Counter
                    SKPS   cc_z
                    BR     looptp1
                    NOP 	
                ");
            break;
        }
	    case 2 :
	    {
	        asm("
                    PFX	    %hi(8060)                         ; Set Counter
                    MOVI	%l1,%lo(8060)

                    PFX	    %hi(0)                            ; Set Clear register
                    MOVI	%l2,%lo(0)
                    PFX	    %xhi(0)
                    MOVHI	%l2,%xlo(0)	
	
                    looptp2:
                    LD     %l0, [%i0]                        ; Load Buffer Data to %r0 	
                    ST     [%i1], %l0                        ; Store it to Plane
                    ST     [%i0], %l2                        ; Clear Buffer

                    LD     %l0, [%i2]                        ; Load Buffer Data to %r0
                    ST     [%i3], %l0                        ; Store it to Plane
                    ST     [%i2], %l2                        ; Clear Buffer
                                                              	
                    ADDI   %i0, 4                            ; Add Address Counter
                    ADDI   %i1, 4	

                    ADDI   %i2, 4
                    ADDI   %i3, 4	
	
                    SUBI   %l1, 1                            ; Decrement Line Counter
                    SKPS   cc_z
                    BR     looptp2
                    NOP 	
                ");
            break;
        }

	    case 3 :
	    {
	        asm("
                    PFX	    %hi(8060)                         ; Set Counter
                    MOVI	%l1,%lo(8060)

                    PFX	    %hi(0)                            ; Set Clear register
                    MOVI	%l2,%lo(0)
                    PFX	    %xhi(0)
                    MOVHI	%l2,%xlo(0)	
	
                    looptp3:
                    LD     %l0, [%i0]                        ; Load Buffer Data to %r0 	
                    ST     [%i1], %l0                        ; Store it to Plane
                    ST     [%i0], %l2                        ; Clear Buffer

                    LD     %l0, [%i2]                        ; Load Buffer Data to %r0
                    ST     [%i3], %l0                        ; Store it to Plane
                    ST     [%i2], %l2                        ; Clear Buffer

                    LD     %l0, [%i4]                        ; Load Buffer Data to %r0
                    ST     [%i5], %l0                        ; Store it to Plane
                    ST     [%i4], %l2                        ; Clear Buffer
                                                               	
                    ADDI   %i0, 4                            ; Add Address Counter
                    ADDI   %i1, 4	

                    ADDI   %i2, 4
                    ADDI   %i3, 4	

                    ADDI   %i4, 4
                    ADDI   %i5, 4	

                    SUBI   %l1, 1                            ; Decrement Line Counter
                    SKPS   cc_z
                    BR     looptp3
                    NOP 	
                ");
            break;
        }

	    case 4 :
	    {
	        asm("
                    PFX	    %hi(8060)                         ; Set Counter
                    MOVI	%l1,%lo(8060)

                    PFX	    %hi(0)                            ; Set Clear register
                    MOVI	%l2,%lo(0)
                    PFX	    %xhi(0)
                    MOVHI	%l2,%xlo(0)	
	
                    looptp4:
                    LD     %l0, [%i0]                        ; Load Buffer Data to %r0 	
                    ST     [%i1], %l0                        ; Store it to Plane
                    ST     [%i0], %l2                        ; Clear Buffer

                    LD     %l0, [%i2]                        ; Load Buffer Data to %r0
                    ST     [%i3], %l0                        ; Store it to Plane
                    ST     [%i2], %l2                        ; Clear Buffer

                    LD     %l0, [%i4]                        ; Load Buffer Data to %r0
                    ST     [%i5], %l0                        ; Store it to Plane
                    ST     [%i4], %l2                        ; Clear Buffer

                    LD     %l0, [%r4]                        ; Load Buffer Data to %r0
                    ST     [%r5], %l0                       ; Store it to Plane
                    ST     [%r4], %l2                        ; Clear Buffer
                          	
                    ADDI   %i0, 4                            ; Add Address Counter
                    ADDI   %i1, 4	

                    ADDI   %i2, 4
                    ADDI   %i3, 4	

                    ADDI   %i4, 4
                    ADDI   %i5, 4	

                    ADDI   %r4, 4
                    ADDI   %r5, 4	
	
                    SUBI   %l1, 1                            ; Decrement Line Counter
                    SKPS   cc_z
                    BR     looptp4
                    NOP 	
                ");
            break;
        }                        	
	    case 5 :
	    {
	        asm("
                    PFX	    %hi(8060)                         ; Set Counter
                    MOVI	%l1,%lo(8060)

                    PFX	    %hi(0)                            ; Set Clear register
                    MOVI	%l2,%lo(0)
                    PFX	    %xhi(0)
                    MOVHI	%l2,%xlo(0)	
	
                    looptp5:
                    LD     %l0, [%i0]                        ; Load Buffer Data to %r0 	
                    ST     [%i1], %l0                        ; Store it to Plane
                    ST     [%i0], %l2                        ; Clear Buffer

                    LD     %l0, [%i2]                        ; Load Buffer Data to %r0
                    ST     [%i3], %l0                        ; Store it to Plane
                    ST     [%i2], %l2                        ; Clear Buffer

                    LD     %l0, [%i4]                        ; Load Buffer Data to %r0
                    ST     [%i5], %l0                        ; Store it to Plane
                    ST     [%i4], %l2                        ; Clear Buffer

                    LD     %l0, [%r4]                        ; Load Buffer Data to %r0
                    ST     [%r5], %l0                       ; Store it to Plane
                    ST     [%r4], %l2                        ; Clear Buffer

                    LD     %l0, [%r6]                        ; Load Buffer Data to %r0
                    ST     [%r7], %l0                       ; Store it to Plane
                    ST     [%r6], %l2                        ; Clear Buffer
                                                               	
                    ADDI   %i0, 4                            ; Add Address Counter
                    ADDI   %i1, 4	

                    ADDI   %i2, 4
                    ADDI   %i3, 4	

                    ADDI   %i4, 4
                    ADDI   %i5, 4	

                    ADDI   %r4, 4
                    ADDI   %r5, 4	
	
                    ADDI   %r6, 4
                    ADDI   %r7, 4		
	
                    SUBI   %l1, 1                            ; Decrement Line Counter
                    SKPS   cc_z
                    BR     looptp5
                    NOP 	
                ");
            break;
        }
    }
}

void Hardware::TransferPlanes_asm_persistant(unsigned long Buffer_Adr1, unsigned long Plane_Adr1, unsigned long Buffer_Adr2, unsigned long Plane_Adr2, unsigned long Buffer_Adr3, unsigned long Plane_Adr3, unsigned char count)
{
	switch(count)
	{
	    case 1 :
	    {
	        asm("
                    PFX	    %hi(8060)                         ; Set Counter
                    MOVI	%l1,%lo(8060)

                    looptpp1:
                    LD     %l0, [%i0]                        ; Load Buffer Data to %r0 	
                    ST     [%i1], %l0                        ; Store it to Plane
                                                               	
                    ADDI   %i0, 4                            ; Add Address Counter
                    ADDI   %i1, 4	
	
                    SUBI   %l1, 1                            ; Decrement Line Counter
                    SKPS   cc_z
                    BR     looptpp1
                    NOP 	
                ");
            break;
        }
	    case 2 :
	    {
	        asm("
                    PFX	    %hi(8060)                         ; Set Counter
                    MOVI	%l1,%lo(8060)
	
                    looptpp2:
                    LD     %l0, [%i0]                        ; Load Buffer Data to %r0 	
                    ST     [%i1], %l0                        ; Store it to Plane

                    LD     %l0, [%i2]                        ; Load Buffer Data to %r0
                    ST     [%i3], %l0                        ; Store it to Plane
                                                              	
                    ADDI   %i0, 4                            ; Add Address Counter
                    ADDI   %i1, 4	

                    ADDI   %i2, 4
                    ADDI   %i3, 4	
	
                    SUBI   %l1, 1                            ; Decrement Line Counter
                    SKPS   cc_z
                    BR     looptpp2
                    NOP 	
                ");
            break;
        }

	    case 3 :
	    {
	        asm("
                    PFX	    %hi(8060)                         ; Set Counter
                    MOVI	%l1,%lo(8060)
	
                    looptpp3:
                    LD     %l0, [%i0]                        ; Load Buffer Data to %r0 	
                    ST     [%i1], %l0                        ; Store it to Plane

                    LD     %l0, [%i2]                        ; Load Buffer Data to %r0
                    ST     [%i3], %l0                        ; Store it to Plane

                    LD     %l0, [%i4]                        ; Load Buffer Data to %r0
                    ST     [%i5], %l0                        ; Store it to Plane
                                                               	
                    ADDI   %i0, 4                            ; Add Address Counter
                    ADDI   %i1, 4	

                    ADDI   %i2, 4
                    ADDI   %i3, 4	

                    ADDI   %i4, 4
                    ADDI   %i5, 4	

                    SUBI   %l1, 1                            ; Decrement Line Counter
                    SKPS   cc_z
                    BR     looptpp3
                    NOP 	
                ");
            break;
        }
	    case 4 :
	    {
	        asm("
                    PFX	    %hi(8060)                         ; Set Counter
                    MOVI	%l1,%lo(8060)

                    looptpp4:
                    LD     %l0, [%i0]                        ; Load Buffer Data to %r0 	
                    ST     [%i1], %l0                        ; Store it to Plane

                    LD     %l0, [%i2]                        ; Load Buffer Data to %r0
                    ST     [%i3], %l0                        ; Store it to Plane

                    LD     %l0, [%i4]                        ; Load Buffer Data to %r0
                    ST     [%i5], %l0                        ; Store it to Plane

                    LD     %l0, [%r4]                        ; Load Buffer Data to %r0
                    ST     [%r5], %l0                       ; Store it to Plane
                          	
                    ADDI   %i0, 4                            ; Add Address Counter
                    ADDI   %i1, 4	

                    ADDI   %i2, 4
                    ADDI   %i3, 4	

                    ADDI   %i4, 4
                    ADDI   %i5, 4	

                    ADDI   %r4, 4
                    ADDI   %r5, 4	
	
                    SUBI   %l1, 1                            ; Decrement Line Counter
                    SKPS   cc_z
                    BR     looptpp4
                    NOP 	
                ");
            break;
        }                        	
	    case 5 :
	    {
	        asm("
                    PFX	    %hi(8060)                         ; Set Counter
                    MOVI	%l1,%lo(8060)

                    looptpp5:
                    LD     %l0, [%i0]                        ; Load Buffer Data to %r0 	
                    ST     [%i1], %l0                        ; Store it to Plane

                    LD     %l0, [%i2]                        ; Load Buffer Data to %r0
                    ST     [%i3], %l0                        ; Store it to Plane

                    LD     %l0, [%i4]                        ; Load Buffer Data to %r0
                    ST     [%i5], %l0                        ; Store it to Plane

                    LD     %l0, [%r4]                        ; Load Buffer Data to %r0
                    ST     [%r5], %l0                       ; Store it to Plane

                    LD     %l0, [%r6]                        ; Load Buffer Data to %r0
                    ST     [%r7], %l0                       ; Store it to Plane
                                                               	
                    ADDI   %i0, 4                            ; Add Address Counter
                    ADDI   %i1, 4	

                    ADDI   %i2, 4
                    ADDI   %i3, 4	

                    ADDI   %i4, 4
                    ADDI   %i5, 4	

                    ADDI   %r4, 4
                    ADDI   %r5, 4	
	
                    ADDI   %r6, 4
                    ADDI   %r7, 4		
	
                    SUBI   %l1, 1                            ; Decrement Line Counter
                    SKPS   cc_z
                    BR     looptpp5
                    NOP 	
                ");
            break;
        }
    }
}

void Hardware::TransferPlanes_clear_asm(unsigned long Buffer_Adr1, unsigned long Plane_Adr1, unsigned long Buffer_Adr2, unsigned long Plane_Adr2, unsigned long Buffer_Adr3, unsigned long Plane_Adr3, unsigned char count)
{
	switch(count)
	{
	    case 1 :
	    {
	        asm("
                    PFX	    %hi(8060)                         ; Set Counter
                    MOVI	%l1,%lo(8060)

                    PFX	    %hi(0)                            ; Set Clear register
                    MOVI	%l2,%lo(0)
                    PFX	    %xhi(0)
                    MOVHI	%l2,%xlo(0)	
	
                    looptpc1:
                    ST     [%i0], %l2                        ; Clear Buffer
                    ST     [%i1], %l2                        ; Store it to Plane

                                                               	
                    ADDI   %i0, 4                            ; Add Address Counter
                    ADDI   %i1, 4	

	
                    SUBI   %l1, 1                            ; Decrement Line Counter
                    SKPS   cc_z
                    BR     looptpc1
                    NOP 	
                ");
            break;
        }
	    case 2 :
	    {
	        asm("
                    PFX	    %hi(8060)                         ; Set Counter
                    MOVI	%l1,%lo(8060)

                    PFX	    %hi(0)                            ; Set Clear register
                    MOVI	%l2,%lo(0)
                    PFX	    %xhi(0)
                    MOVHI	%l2,%xlo(0)	
	
                    looptpc2:
                    ST     [%i0], %l2                        ; Clear Buffer
                    ST     [%i1], %l2                        ; Store it to Plane

                    ST     [%i2], %l2                        ; Clear Buffer
                    ST     [%i3], %l2                        ; Store it to Plane
                                                              	
                    ADDI   %i0, 4                            ; Add Address Counter
                    ADDI   %i1, 4	

                    ADDI   %i2, 4
                    ADDI   %i3, 4	
	
                    SUBI   %l1, 1                            ; Decrement Line Counter
                    SKPS   cc_z
                    BR     looptpc2
                    NOP 	
                ");
            break;
        }

	    case 3 :
	    {
	        asm("
                    PFX	    %hi(8060)                         ; Set Counter
                    MOVI	%l1,%lo(8060)

                    PFX	    %hi(0)                            ; Set Clear register
                    MOVI	%l2,%lo(0)
                    PFX	    %xhi(0)
                    MOVHI	%l2,%xlo(0)	
	
                    looptpc3:
                    ST     [%i0], %l2                        ; Clear Buffer
                    ST     [%i1], %l2                        ; Store it to Plane

                    ST     [%i2], %l2                        ; Clear Buffer
                    ST     [%i3], %l2                        ; Store it to Plane

                    ST     [%i4], %l2                        ; Clear Buffer
                    ST     [%i5], %l2                        ; Store it to Plane
                                                               	
                    ADDI   %i0, 4                            ; Add Address Counter
                    ADDI   %i1, 4	

                    ADDI   %i2, 4
                    ADDI   %i3, 4	

                    ADDI   %i4, 4
                    ADDI   %i5, 4	

                    SUBI   %l1, 1                            ; Decrement Line Counter
                    SKPS   cc_z
                    BR     looptpc3
                    NOP 	
                ");
            break;
        }
	    case 4 :
	    {
	        asm("
                    PFX	    %hi(8060)                         ; Set Counter
                    MOVI	%l1,%lo(8060)

                    PFX	    %hi(0)                            ; Set Clear register
                    MOVI	%l2,%lo(0)
                    PFX	    %xhi(0)
                    MOVHI	%l2,%xlo(0)	
	
                    looptpc4:
                    ST     [%i0], %l2                        ; Clear Buffer
                    ST     [%i1], %l2                        ; Store it to Plane

                    ST     [%i2], %l2                        ; Clear Buffer
                    ST     [%i3], %l2                        ; Store it to Plane

                    ST     [%i4], %l2                        ; Clear Buffer
                    ST     [%i5], %l2                        ; Store it to Plane

                    ST     [%r4], %l2                        ; Clear Buffer
                    ST     [%r5], %l2                        ; Store it to Plane
                          	
                    ADDI   %i0, 4                            ; Add Address Counter
                    ADDI   %i1, 4	

                    ADDI   %i2, 4
                    ADDI   %i3, 4	

                    ADDI   %i4, 4
                    ADDI   %i5, 4	

                    ADDI   %r4, 4
                    ADDI   %r5, 4	
	
                    SUBI   %l1, 1                            ; Decrement Line Counter
                    SKPS   cc_z
                    BR     looptpc4
                    NOP 	
                ");
            break;
        }                        	
	    case 5 :
	    {
	        asm("
                    PFX	    %hi(8060)                         ; Set Counter
                    MOVI	%l1,%lo(8060)

                    PFX	    %hi(0)                            ; Set Clear register
                    MOVI	%l2,%lo(0)
                    PFX	    %xhi(0)
                    MOVHI	%l2,%xlo(0)	
	
                    looptpc5:
                    ST     [%i0], %l2                        ; Clear Buffer
                    ST     [%i1], %l2                        ; Store it to Plane

                    ST     [%i2], %l2                        ; Clear Buffer
                    ST     [%i3], %l2                        ; Store it to Plane

                    ST     [%i4], %l2                        ; Clear Buffer
                    ST     [%i5], %l2                        ; Store it to Plane

                    ST     [%r4], %l2                        ; Clear Buffer
                    ST     [%r5], %l2                        ; Store it to Plane

                    ST     [%r6], %l2                        ; Clear Buffer
                    ST     [%r7], %l2                        ; Store it to Plane

                                                               	
                    ADDI   %i0, 4                            ; Add Address Counter
                    ADDI   %i1, 4	

                    ADDI   %i2, 4
                    ADDI   %i3, 4	

                    ADDI   %i4, 4
                    ADDI   %i5, 4	

                    ADDI   %r4, 4
                    ADDI   %r5, 4	
	
                    ADDI   %r6, 4
                    ADDI   %r7, 4		
	
                    SUBI   %l1, 1                            ; Decrement Line Counter
                    SKPS   cc_z
                    BR     looptpc5
                    NOP 	
                ");
            break;
        }
    }
}

void Hardware::Planes_clear_asm(unsigned long Buffer_Adr1)
{
	asm("
            PFX	    %hi(8060)                         ; Set Counter
            MOVI	%l1,%lo(8060)

            PFX	    %hi(0)                            ; Set Clear register
            MOVI	%l2,%lo(0)
            PFX	    %xhi(0)
            MOVHI	%l2,%xlo(0)	
	
        looptpcc1:
            ST     [%i0], %l2                        ; Clear Buffer

            ADDI   %i0, 4                            ; Add Address Counter
	
            SUBI   %l1, 1                            ; Decrement Line Counter
            SKPS   cc_z
            BR     looptpcc1
            NOP 	
        ");
}

void Hardware::Planes_clear_asm_all(unsigned char count, unsigned long Buffer_Adr1, unsigned long Buffer_Adr2, unsigned long Buffer_Adr3, unsigned long Buffer_Adr4, unsigned long Buffer_Adr5)
{
    switch(count)
    {
        case 1 :
        {
	       asm("
                PFX	    %hi(8060)                         ; Set Counter
                MOVI	%l1,%lo(8060)

                PFX	    %hi(0)                            ; Set Clear register
                MOVI	%l2,%lo(0)
                PFX	    %xhi(0)
                MOVHI	%l2,%xlo(0)	
	
            looptpcc21:
                ST     [%i1], %l2                        ; Clear Buffer

                ADDI   %i1, 4                            ; Add Address Counter
            	
                SUBI   %l1, 1                            ; Decrement Line Counter
                SKPS   cc_z
                BR     looptpcc21
                NOP 	
            ");
            break;
        }
        case 2 :
        {
	       asm("
                PFX	    %hi(8060)                         ; Set Counter
                MOVI	%l1,%lo(8060)

                PFX	    %hi(0)                            ; Set Clear register
                MOVI	%l2,%lo(0)
                PFX	    %xhi(0)
                MOVHI	%l2,%xlo(0)	
	
            looptpcc22:
                ST     [%i1], %l2                        ; Clear Buffer
                ST     [%i2], %l2                        ; Clear Buffer

                ADDI   %i1, 4                            ; Add Address Counter
                ADDI   %i2, 4                            ; Add Address Counter
            	
                SUBI   %l1, 1                            ; Decrement Line Counter
                SKPS   cc_z
                BR     looptpcc22
                NOP 	
            ");
            break;
        }
        case 3 :
        {
	       asm("
                PFX	    %hi(8060)                         ; Set Counter
                MOVI	%l1,%lo(8060)

                PFX	    %hi(0)                            ; Set Clear register
                MOVI	%l2,%lo(0)
                PFX	    %xhi(0)
                MOVHI	%l2,%xlo(0)	
	
            looptpcc23:
                ST     [%i1], %l2                        ; Clear Buffer
                ST     [%i2], %l2                        ; Clear Buffer
                ST     [%i3], %l2                        ; Clear Buffer

                ADDI   %i1, 4                            ; Add Address Counter
                ADDI   %i2, 4                            ; Add Address Counter
                ADDI   %i3, 4                            ; Add Address Counter
            	
                SUBI   %l1, 1                            ; Decrement Line Counter
                SKPS   cc_z
                BR     looptpcc23
                NOP 	
            ");
            break;
        }
        case 4 :
        {
	       asm("
                PFX	    %hi(8060)                         ; Set Counter
                MOVI	%l1,%lo(8060)

                PFX	    %hi(0)                            ; Set Clear register
                MOVI	%l2,%lo(0)
                PFX	    %xhi(0)
                MOVHI	%l2,%xlo(0)	
	
            looptpcc24:
                ST     [%i1], %l2                        ; Clear Buffer
                ST     [%i2], %l2                        ; Clear Buffer
                ST     [%i3], %l2                        ; Clear Buffer
                ST     [%i4], %l2                        ; Clear Buffer

                ADDI   %i1, 4                            ; Add Address Counter
                ADDI   %i2, 4                            ; Add Address Counter
                ADDI   %i3, 4                            ; Add Address Counter
                ADDI   %i4, 4                            ; Add Address Counter
            	
                SUBI   %l1, 1                            ; Decrement Line Counter
                SKPS   cc_z
                BR     looptpcc24
                NOP 	
            ");
            break;
        }
        case 5 :
        {
	       asm("
                PFX	    %hi(8060)                         ; Set Counter
                MOVI	%l1,%lo(8060)

                PFX	    %hi(0)                            ; Set Clear register
                MOVI	%l2,%lo(0)
                PFX	    %xhi(0)
                MOVHI	%l2,%xlo(0)	
	
            looptpcc25:
                ST     [%i1], %l2                        ; Clear Buffer
                ST     [%i2], %l2                        ; Clear Buffer
                ST     [%i3], %l2                        ; Clear Buffer
                ST     [%i4], %l2                        ; Clear Buffer
                ST     [%i5], %l2                        ; Clear Buffer

                ADDI   %i1, 4                            ; Add Address Counter
                ADDI   %i2, 4                            ; Add Address Counter
                ADDI   %i3, 4                            ; Add Address Counter
                ADDI   %i4, 4                            ; Add Address Counter
                ADDI   %i5, 4                            ; Add Address Counter
            	
                SUBI   %l1, 1                            ; Decrement Line Counter
                SKPS   cc_z
                BR     looptpcc25
                NOP 	
            ");
            break;
        }
    }
}
/*BF not used	
void Hardware::DoEnableLogicAnalyserInterrupt(void)							// Enable service routine
{
	la_interrupt->np_pioedgecapture = 0x00; 							// clear all existing IRQ conditions
	la_interrupt->np_piodirection = 0x00;								// set all bits to input
	la_interrupt->np_piointerruptmask = 0x01;							// enable Button IRQs
	la_interrupt->np_piodata = 0;

	nr_installuserisr(na_la_interrupt_irq,ISR_LogicAnalyser,(int)la_interrupt);	// Install ISR for parallel I/Os

#ifdef _Debug_IRQ_
	if (Debug_Mode) printf("\nLogicAnalyser interrupt enabled.\n"); 						// print on console
#endif	
}
*/

/*BF not used	
void Hardware::DoDisableLogicAnalyserInterrupt(void)						// Disable parallel I/O service routine
{
	nr_installuserisr(na_la_interrupt_irq,0,0); 				// Install empty routine for pio irq
	la_interrupt->np_piointerruptmask = 0x00;						// disable all IRQs
}
*/

/*BF not used
void Hardware::ISR_LogicAnalyser(int context)
{
	char la_data_cnt;
	
	tc_test_var2++;

	la_gate->np_piodata = 0x01;
	
	for (la_data_cnt = 0; la_data_cnt < 32; la_data_cnt++)
	{
		la_pulse->np_piodata = 0x01;
		
		LogicData[la_data_cnt] = la_data-> np_piodata;
		
		la_pulse->np_piodata = 0x00;		
	}	
	
	la_gate->np_piodata = 0x00;
	
    la_interrupt->np_pioedgecapture = 0; 								// clear IRQ conditions		

	//if (USB_Data_Trans == 1)
	{
		send_buffer[0] = 3;						// Command Write Data
		send_buffer[1] = 20;
		send_buffer[2] = 1;
		
		CommIF::SendData(send_buffer);	
	}
#ifdef _Debug_IRQ_	
	if (Debug_Mode) printf("\nLogicAnalyser interrupt received\n");
#endif	
}
*/

//##########################################################################################################################################################
//BF added
// Calculate ADC offset for specified channel
void Hardware::Calc_ADC_Offset(int channel)
{
	long int ADC1 = 0, ADC2 = 0, ADC3 = 0, ADC4 = 0;
	int ix = 0, ref; 
	
	printf("\r\nChannel %d start calibrating ADC offsets\r\n", channel);

	switch(channel)
	{
		case 1:
		{
			//get sum of values separate for each of the four ADCs
			for (ix = 0; ix < 4000; ix+=4)
			{ ADC1 += SIGNAL1[ix];ADC2 += SIGNAL1[ix+1];ADC3 += SIGNAL1[ix+2];ADC4 += SIGNAL1[ix+3];}
			break;	
		}
		case 2:
		{
			//get sum of values separate for each of the four ADCs
			for (ix = 0; ix < 4000; ix+=4)
			{ ADC1 += SIGNAL2[ix];ADC2 += SIGNAL2[ix+1];ADC3 += SIGNAL2[ix+2];ADC4 += SIGNAL2[ix+3];}
			break;	
		}
		case 3:
		{
			//get sum of values separate for each of the four ADCs
			for (ix = 0; ix < 4000; ix+=4)
			{ ADC1 += SIGNAL3[ix];ADC2 += SIGNAL3[ix+1];ADC3 += SIGNAL3[ix+2];ADC4 += SIGNAL3[ix+3];}
			break;	
		}
		case 4:
		{
			//get sum of values separate for each of the four ADCs
			for (ix = 0; ix < 4000; ix+=4)
			{ ADC1 += SIGNAL4[ix];ADC2 += SIGNAL4[ix+1];ADC3 += SIGNAL4[ix+2];ADC4 += SIGNAL4[ix+3];}
			break;	
		}
	}

	//calculate average for each ADC	
	ix = ix >> 2;	

	ADC1 /= ix;
	ADC2 /= ix;
	ADC3 /= ix;
	ADC4 /= ix;

	//get ADC with smallest offset as  zero reference 
	ref = ADC1;
	if( ADC2 < ref ) ref = ADC2;
	if( ADC3 < ref ) ref = ADC3;
	if( ADC4 < ref ) ref = ADC4;
	
	//calculate offsets
        ADC_Offset[channel-1][0] = ADC1 - ref;
	ADC_Offset[channel-1][1] = ADC2 - ref;
	ADC_Offset[channel-1][2] = ADC3 - ref;
	ADC_Offset[channel-1][3] = ADC4 - ref;

	
	printf("ADC 1 Offset = %d\r\n",ADC_Offset[channel-1][0]);
	printf("ADC 2 Offset = %d\r\n",ADC_Offset[channel-1][1]);
	printf("ADC 3 Offset = %d\r\n",ADC_Offset[channel-1][2]);
	printf("ADC 4 Offset = %d\r\n",ADC_Offset[channel-1][3]);


}
//##########################################################################################################################################################
//BF added
//Calculate DAC offset correction for specified channel
int Hardware::Calc_DAC_Correction(int channel, int *Correction)
{

	//-------------------------------------------------------------------------------------------
	// BF new calibration	
	//------------------------------------------------------------------------------------------
//	printf("\r\nChannel %d start calibrating DAC zero\r\n", channel);
//	printf("DAC correction old  = %d\r\n", *Correction);

	long int ADC_sum = 0;
	int ADC_diff;
	int ix = 0, lvoltage_range = 0; 
	
	switch(channel)
	{
		case 0:	// channel 1
		{
			//get sum of values
			for (ix = 1000; ix < 1400; ix++)
			{ ADC_sum += SIGNAL1[ix]; }
			lvoltage_range = Selected_Voltage_CH1;
			break;	
		}
		case 1:	// channel 2
		{
			//get sum of values
			for (ix = 1000; ix < 1400; ix++)
			{ ADC_sum += SIGNAL2[ix]; }
			lvoltage_range = Selected_Voltage_CH2;	
			break;	
		}
		case 2:	// channel 3
		{
			//get sum of values
			for (ix = 1000; ix < 1400; ix++)
			{ ADC_sum += SIGNAL3[ix]; }
			lvoltage_range = Selected_Voltage_CH3;	
			break;	
		}
		case 3:	// channel 4
		{
			//get sum of values
			for (ix = 1000; ix < 1400; ix++)
			{ ADC_sum += SIGNAL4[ix]; }
			lvoltage_range = Selected_Voltage_CH4;	
			break;	
		}
	}

	//get average offset of each ADC-set
	ADC_sum /= 400;
	printf("Channel %d: ADC average value  = %d   ", channel+1, ADC_sum);

	//calculate offset from zero
	ADC_diff = ADC_sum - ADC_ZERO;
//	printf("ADC offset         = %d\r\n", ADC_diff);

	
	//approximate correction value
	switch(lvoltage_range)
	{
		/*case 0: *Correction -= ADC_diff * 6; break;//  1 mV
		case 1: *Correction -= ADC_diff * 14; break;//  2 mV
		case 2: *Correction -= ADC_diff * 27; break;//  5 mV
		case 3: *Correction -= ADC_diff * 6; break;// 10 mV
		case 4: *Correction -= ADC_diff * 14; break;// 20 mV
		case 5: *Correction -= ADC_diff * 27; break;// 50 mV
		case 6: *Correction -= ADC_diff * 6; break;//100 mV
		case 7: *Correction -= ADC_diff * 14; break;//200 mV
		case 8: *Correction -= ADC_diff * 27; break;//500 mV */
		case 9: *Correction -= ADC_diff * 6; break;// 1 V
		case 10: *Correction -= ADC_diff * 14; break;//2 V
		case 11: *Correction -= ADC_diff * 27; break;//5 V
	}

//	printf("DAC Correction new  = %d\r\n", Correction[0]);
printf("Diff  = %d\r\n", ADC_diff);
	return ADC_diff;

}
//##########################################################################################################################################################
//BF added
//Calibrate all ADCs
void Hardware::Calibrate_ADC_ZeroOffsets(void)
{

	char CH1_DelCorr_bak;
	char CH2_DelCorr_bak;
	char CH3_DelCorr_bak;
	char CH4_DelCorr_bak;
/*
	char lChannel_1_bak, lChannel_2_bak, lChannel_3_bak, lChannel_4_bak;
	//char lCH1_VR_bak,lCH2_VR_bak, lCH3_VR_bak, lCH4_VR_bak;
	long int lTB_reg_bak;


	Display::DRAWROUNDBUTTON(200, 180, 240, 80, 0, 0);
	Display::TEXTOUTxvbig("Calibrating ADC Offsets.", 217, 192, 1, UI_Plane2);
	Display::TEXTOUTxvbig("All inputs must be removed!", 217, 212, 1, UI_Plane2);
	Display::TEXTOUTxvbig("This may take some seconds...", 217, 232, 1, UI_Plane2);
*/

	//backup BF  #001 
	CH1_DelCorr_bak = CH1_Del_Correct;
	CH2_DelCorr_bak = CH2_Del_Correct;
	CH3_DelCorr_bak = CH3_Del_Correct;
	CH4_DelCorr_bak = CH4_Del_Correct;

//	Channel delay correction must be reset for correct ADC adjustment  BF  #001 
	CH1_Del_Correct = 0;
	CH2_Del_Correct = 0;
	CH3_Del_Correct = 0;
	CH4_Del_Correct = 0;
/*
	lCH1_VR_bak = Selected_Voltage_CH1;
	lCH2_VR_bak = Selected_Voltage_CH2;
	lCH3_VR_bak = Selected_Voltage_CH3;
	lCH4_VR_bak = Selected_Voltage_CH4;

	Selected_Voltage_CH1 = 11;	// 5V
	Selected_Voltage_CH2 = 11;	// 5V
	Selected_Voltage_CH3 = 11;	// 5V
	Selected_Voltage_CH4 = 11;	// 5V
*/
/*
	//backup settings and activate channels
	lChannel_1_bak = Channel_1_Active; Channel_1_Active = 1;
	lChannel_2_bak = Channel_2_Active; Channel_2_Active = 1;
	lChannel_3_bak = Channel_3_Active; Channel_3_Active = 1;
	lChannel_4_bak = Channel_4_Active; Channel_4_Active = 1;

	lTB_reg_bak  = timebase_reg;	//backup timebase
	timebase_reg = 0xFFFFFFFF;      //set real timebase 50ns (1GSa/s)
*/
	SetSwitches(1, 11);	// 5V
	SetSwitches(2, 11);	// 5V
	SetSwitches(3, 11);	// 5V
	SetSwitches(4, 11);	// 5V

	pre_reg = 0x002D;

	//disable triggersource and triggering
	triggering = 0;	

	SetupADC();	
	nr_delay(50);	

	start_acq->np_piodata = 0x01;				//start record Port On
	start_acq->np_piodata = 0x00;				//start record Port Off

	//wait for ADC
	int timeout;
	for(timeout=0;(timeout < 100) && acq_ready->np_piodata == 0x01;timeout++)
	nr_delay(30);

	if (timeout >= 100 ){ printf("Timeout\r\n"); }
	
	data_adr->np_piodata = 0x01;

	READADC(1);	
	WRITEADC(1, 0);
	WRITEADC(2, 0);

	if (NumberOfChannels > 2)
	{
		READADC(3);
		WRITEADC(3, 0);
		WRITEADC(4, 0);
	}
	
	data_adr->np_piodata = 0x00;
	
	//read signal and calibrate ADC-offsets
	//reset offsets
	ADC_Offset[0][0] = 0;
	ADC_Offset[0][1] = 0;
	ADC_Offset[0][2] = 0;
	ADC_Offset[0][3] = 0;
	ReadOut_Signal(1);
	Calc_ADC_Offset(1);
	
	//reset offsets
	ADC_Offset[1][0] = 0;
	ADC_Offset[1][1] = 0;
	ADC_Offset[1][2] = 0;
	ADC_Offset[1][3] = 0;
	ReadOut_Signal(2);
	Calc_ADC_Offset(2);

	if (NumberOfChannels == 4)
	{
		//reset offsets
		ADC_Offset[2][0] = 0;
		ADC_Offset[2][1] = 0;
		ADC_Offset[2][2] = 0;
		ADC_Offset[2][3] = 0;
		ReadOut_Signal(3);
		Calc_ADC_Offset(3);

		//reset offsets
		ADC_Offset[3][0] = 0;
		ADC_Offset[3][1] = 0;
		ADC_Offset[3][2] = 0;
		ADC_Offset[3][3] = 0;
		ReadOut_Signal(4);
		Calc_ADC_Offset(4);
	}	
/*
	//Save new values to flash
   	AMDFlash::Write_Protected_Flash();

	//restore settings
	Channel_1_Active = lChannel_1_bak;
	Channel_2_Active = lChannel_2_bak;
	Channel_3_Active = lChannel_3_bak;
	Channel_4_Active = lChannel_4_bak;
*/
/*
	Selected_Voltage_CH1 = lCH1_VR_bak;
	Selected_Voltage_CH2 = lCH2_VR_bak;
	Selected_Voltage_CH3 = lCH3_VR_bak;
	Selected_Voltage_CH4 = lCH4_VR_bak;
*/
/*
	//restore timebase settings
	timebase_reg = lTB_reg_bak; //tb_value[RealTimebase];

	SetSwitches(1, Selected_Voltage_CH1);
	SetSwitches(2, Selected_Voltage_CH2);
	SetSwitches(3, Selected_Voltage_CH3);
	SetSwitches(4, Selected_Voltage_CH4);

	SetupTrigger();	//setup ADC control registers
*/
	//restore BF  #001 
	CH1_Del_Correct = CH1_DelCorr_bak;
	CH2_Del_Correct = CH2_DelCorr_bak;
	CH3_Del_Correct = CH3_DelCorr_bak;
	CH4_Del_Correct = CH4_DelCorr_bak;

/*
	//wait a little bit
	nr_delay(100);	

	if(Run) Start_Record();
	else ADC_Data_Available = 0;

	//Delete popup
	Display::DRAWROUNDBUTTON(200, 180, 240, 80, 0, 1);
	Display::TEXTOUTxvbig("Calibrating ADC Offsets.", 217, 192, 0, UI_Plane2);
	Display::TEXTOUTxvbig("All inputs must be removed!", 217, 212, 0, UI_Plane2);
	Display::TEXTOUTxvbig("This may take some seconds...", 217, 232, 0, UI_Plane2);

*/


}
//##########################################################################################################################################################
//BF added
//Calibrate DACs for all channels and all voltage ranges
void Hardware::Calibrate_DAC_ZeroOffsets(void)
{
	char TB_bak;

	char lVoltRange;

	char lCH1_VR_bak,lCH2_VR_bak, lCH3_VR_bak, lCH4_VR_bak;

	char CH1_DelCorr_bak;
	char CH2_DelCorr_bak;
	char CH3_DelCorr_bak;
	char CH4_DelCorr_bak;

	char lChannel_1_bak, lChannel_2_bak, lChannel_3_bak, lChannel_4_bak;

	int lDiff[4][3];

	// initialize array
	for (int i=0;i<4;i++)
	{ for(int j=0;j<3;j++){ lDiff[i][j] = 0xFFFF; }}


	Display::DRAWROUNDBUTTON(200, 180, 240, 80, 0, 0);
	Display::TEXTOUTxvbig("Calibrating Offsets.", 217, 192, 1, UI_Plane2);
	Display::TEXTOUTxvbig("All inputs must be removed!", 217, 212, 1, UI_Plane2);
	Display::TEXTOUTxvbig("This may take some seconds...", 217, 232, 1, UI_Plane2);

	DoDisableUARTInterrupt();
	DoDisableADCInterrupt();
	DoDisableKeyInterrupt();
	DoDisableRotInterrupt();


	// Backup actual values

	//backup channel delay BF  #001 
	CH1_DelCorr_bak = CH1_Del_Correct;
	CH2_DelCorr_bak = CH2_Del_Correct;
	CH3_DelCorr_bak = CH3_Del_Correct;
	CH4_DelCorr_bak = CH4_Del_Correct;


//	Channel delay correction must be reset for correct ADC adjustment  BF  #001 
	CH1_Del_Correct = 0;
	CH2_Del_Correct = 0;
	CH3_Del_Correct = 0;
	CH4_Del_Correct = 0;

	lCH1_VR_bak = Selected_Voltage_CH1;
	lCH2_VR_bak = Selected_Voltage_CH2;
	lCH3_VR_bak = Selected_Voltage_CH3;
	lCH4_VR_bak = Selected_Voltage_CH4;

	lChannel_1_bak = Channel_1_Active;
	lChannel_2_bak = Channel_2_Active;
	lChannel_3_bak = Channel_3_Active;
	lChannel_4_bak = Channel_4_Active;

	Channel_1_Active = 1;
	Channel_2_Active = 1;

	//set DAC correction to default
	DAC_Correction[CalSet][0][0] = 400;
	DAC_Correction[CalSet][0][1] = 520;
	DAC_Correction[CalSet][0][2] = 400;
	
	DAC_Correction[CalSet][1][0] = 400;
	DAC_Correction[CalSet][1][1] = 520;
	DAC_Correction[CalSet][1][2] = 400;

	if (NumberOfChannels == 4)
	{
		Channel_3_Active = 1;
		Channel_4_Active = 1;

		DAC_Correction[CalSet][2][0] = 400;
		DAC_Correction[CalSet][2][1] = 520;
		DAC_Correction[CalSet][2][2] = 400;
		
		DAC_Correction[CalSet][3][0] = 400;
		DAC_Correction[CalSet][3][1] = 520;
		DAC_Correction[CalSet][3][2] = 400;
	}

	TB_bak  = MainTimebase;		//backup timebase
        MainTimebase = 4;   		//set timebase 50ns (1GSa/s)

	//pre_reg = 0x002D;
	
	//disable triggersource and triggering
	//triggering = 0;	

	//SetupADC(); 

	// calibrate ADC offsets first
	Calibrate_ADC_ZeroOffsets();

	// range loop for 1V / 2V / 5V
	for(lVoltRange = 9; lVoltRange <= 11; lVoltRange++)
	{
printf("\n\r**************** Voltage Range %d ********************\n\r",lVoltRange);
		
		Selected_Voltage_CH1 = lVoltRange;	//needed for calibration subroutine
		Selected_Voltage_CH2 = lVoltRange;	//needed for calibration subroutine
		
		Hardware::SetSwitches(1, lVoltRange);
		Hardware::SetSwitches(2, lVoltRange);

		if (NumberOfChannels == 4)
		{	
			Selected_Voltage_CH3 = lVoltRange;	//needed for calibration subroutine
			Selected_Voltage_CH4 = lVoltRange;	//needed for calibration subroutine
			
			Hardware::SetSwitches(3, lVoltRange);
			Hardware::SetSwitches(4, lVoltRange);
		}

		nr_delay(100);
		//SetupADC();
	
		//make several calibration runs to approximate zero
		for(int i=0; i<10; i++)
		{
			//check if calibration is done
			if(NumberOfChannels == 4)
			{ if(lDiff[0][lVoltRange-9] == 0 && lDiff[1][lVoltRange-9] == 0 && lDiff[2][lVoltRange-9] == 0 && lDiff[3][lVoltRange-9] == 0){printf("Range %d calibration complete\n\r",lVoltRange); break; }}
			else
			{ if(lDiff[0][lVoltRange-9] == 0 && lDiff[1][lVoltRange-9] == 0) {printf("Range %d calibration complete\n\r",lVoltRange); break; } }

			printf("Calibration run %d\n\r",i+1);

			// set DAC to scale middle and set default offset correction
			switch(lVoltRange)
			{
				case 9://1 V
				{
					CH1_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][0][0];
					CH2_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][1][0];
					CH3_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][2][0];
					CH4_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][3][0];
					//printf("\n\n\r*** Voltage Range 1V ***\n\r");
					break;
				}
				case 10://2 V
				{
					CH1_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][0][1];
					CH2_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][1][1];
					CH3_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][2][1];
					CH4_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][3][1];
					//printf("\n\n\r*** Voltage Range 2V ***\n\r");
					break;
				}
				case 11://5 V
				{
					CH1_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][0][2];
					CH2_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][1][2];
					CH3_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][2][2];
					CH4_DAC_Offset = DAC_MIDSCALE + DAC_Correction[CalSet][3][2];
					//printf("\n\n\r*** Voltage Range 5V ***\n\r");
					break;
				}
			}

			Hardware::SetDacOffset(1);	
			Hardware::SetDacOffset(2);	

			if (NumberOfChannels == 4)
			{				
				Hardware::SetDacOffset(3);	
				Hardware::SetDacOffset(4);	
			}

			nr_delay(50);	

			start_acq->np_piodata = 0x01;				//start record Port On
			start_acq->np_piodata = 0x00;				//start record Port Off
		
			//wait for ADC
			int timeout;
			for(timeout=0;(timeout < 100) && acq_ready->np_piodata == 0x01;timeout++)
			nr_delay(30);
		
			if (timeout >= 100 ){ printf("Timeout\r\n"); continue; }
		
			data_adr->np_piodata = 0x01;
		
			READADC(1);	
			WRITEADC(1, 0);
			WRITEADC(2, 0);
		
			if (NumberOfChannels > 2)
			{
				READADC(3);
				WRITEADC(3, 0);
				WRITEADC(4, 0);
			}
			
			data_adr->np_piodata = 0x00;
			
			// calibrate each channel
			for (int channel=0; channel < NumberOfChannels ; channel++)
			{
				if(lDiff[channel][lVoltRange-9] == 0) continue;

				//read signal and calibrate DAC-offsets
				ReadOut_Signal(channel+1);

				lDiff[channel][lVoltRange-9] = Calc_DAC_Correction(channel, &DAC_Correction[CalSet][channel][lVoltRange-9]);	
			}

		}	//for loop calbration runs end
	
	}	//for loop voltage ranges end


	//restore timebase
	MainTimebase = TB_bak;

	//restore voltage ranges
	Selected_Voltage_CH1 = lCH1_VR_bak;
	Selected_Voltage_CH2 = lCH2_VR_bak;
	Selected_Voltage_CH3 = lCH3_VR_bak;
	Selected_Voltage_CH4 = lCH4_VR_bak;

	SetSwitches(1, Selected_Voltage_CH1);
	SetSwitches(2, Selected_Voltage_CH2);
	SetSwitches(3, Selected_Voltage_CH3);
	SetSwitches(4, Selected_Voltage_CH4);

	//SetupTrigger();	//setup ADC control registers -> is done in zero handler

	//activate settings
	Rotary_Steps = 0;
	UserIF::ON_Zero_Channel_1();
	Rotary_Steps = 0;
	UserIF::ON_Zero_Channel_2();
	if (NumberOfChannels == 4)
	{	
		Rotary_Steps = 0;
		UserIF::ON_Zero_Channel_3();
	
		Rotary_Steps = 0;
		UserIF::ON_Zero_Channel_4();
	}


	Channel_1_Active = lChannel_1_bak;
	Channel_2_Active = lChannel_2_bak;
	Channel_3_Active = lChannel_3_bak;
	Channel_4_Active = lChannel_4_bak;

	//Save new values to flash
	AMDFlash::Write_Protected_Flash();

	//restore channel delay BF  #001 
	CH1_Del_Correct = CH1_DelCorr_bak;
	CH2_Del_Correct = CH2_DelCorr_bak;
	CH3_Del_Correct = CH3_DelCorr_bak;
	CH4_Del_Correct = CH4_DelCorr_bak;

	DoEnableRotInterrupt();
	DoEnableKeyInterrupt();
	DoEnableADCInterrupt();
	DoEnableUARTInterrupt();

	if(Run) Start_Record();
	else ADC_Data_Available = 0;


	//Delete popup
	Display::DRAWROUNDBUTTON(200, 180, 240, 80, 0, 1);
	Display::TEXTOUTxvbig("Calibrating Offsets.", 217, 192, 0, UI_Plane2);
	Display::TEXTOUTxvbig("All inputs must be removed!", 217, 212, 0, UI_Plane2);
	Display::TEXTOUTxvbig("This may take some seconds...", 217, 232, 0, UI_Plane2);


}
//##########################################################################################################################################################
void Hardware::FFT_Set_Channel(unsigned char backup)
{
	//Hardware::Stop_Record();

	if (backup)
	{
		//printf("- FFT Backup Channels\r\n");

		//Backup channel status
		Channel_Math_Active_bak = Channel_Math_Active;
		Channel_1_Active_bak = Channel_1_Active;
		Channel_2_Active_bak = Channel_2_Active;
		if(NumberOfChannels == 4)
		{
			Channel_3_Active_bak = Channel_3_Active;	
			Channel_4_Active_bak = Channel_4_Active;
		}
		else
		{
			Channel_3_Active_bak = Channel_3_Active = 0;	
			Channel_4_Active_bak = Channel_4_Active = 0;
		}

/*
		//Backup triggersetting and force auto mode	
		FFT_TriggerMode_bak = MenuStatus[MENU_TRIGGERMODE][0];	// remember the trigger setting
		MenuStatus[MENU_TRIGGERMODE][0] = 92;			//set trigger auto mode (or combi???)
		Display::MenuPopupInit(9, MENU_TRIGGERMODE, 92);	//BF #007
		TriggerLevelChanged = 1;
		TriggerModeChanged = 1;
		SetupTrigger();
*/	}

	// which channel has to be active?
	switch(MenuStatus[MENU_FFT][0])	//FFT source
	{
		case 137: Channel_1_Active = 1;	Channel_2_Active = 0; Channel_3_Active = 0; Channel_4_Active = 0;
				LED_ON[0] = 1; LED_ON[1] = 0; LED_ON[2] = 0; LED_ON[3] = 0; break;	
		case 138: Channel_1_Active = 0;	Channel_2_Active = 1; Channel_3_Active = 0; Channel_4_Active = 0;
				LED_ON[0] = 0; LED_ON[1] = 1; LED_ON[2] = 0; LED_ON[3] = 0; break;	
		case 139: Channel_1_Active = 0;	Channel_2_Active = 0; Channel_3_Active = 1; Channel_4_Active = 0;
				LED_ON[0] = 0; LED_ON[1] = 0; LED_ON[2] = 1; LED_ON[3] = 0; break;	
		case 140: Channel_1_Active = 0;	Channel_2_Active = 0; Channel_3_Active = 0; Channel_4_Active = 1;
				LED_ON[0] = 0; LED_ON[1] = 0; LED_ON[2] = 0; LED_ON[3] = 1; break;	
	}

	UserIF::UpdateChannel(1, Channel_1_Active);
	UserIF::UpdateChannel(2, Channel_2_Active);
	UserIF::UpdateChannel(3, Channel_3_Active);
	UserIF::UpdateChannel(4, Channel_4_Active);
	SetupTrigger();

	Channel_Math_Active = 0; 					//switch off math function	
	LED_ON[4] = 0;

	Send_LED();

	Display::MenuPopupInit(29, MENU_FFT, 137);			// 29 FFT Source

	config_changed = true;						//Save new values to flash

	Signal::FFT_buildScaleLookupTable();

	// Remove all Signals which where active before
	if(Channel_1_Active_bak)RemovePlane |= 0x01;
	if(Channel_2_Active_bak)RemovePlane |= 0x02;
	if(Channel_3_Active_bak)RemovePlane |= 0x04;
	if(Channel_4_Active_bak)RemovePlane |= 0x08;
	RemovePlane |= 0x1F;

	ClearPlanes();

	// force new output in statusbar
	VoltageChangedCh1 = 1;
	VoltageChangedCh2 = 1;
	VoltageChangedCh3 = 1;
	VoltageChangedCh4 = 1;

	Display::StatusUpdate();
	
	//if(!Run)SingleShot = 1;
	//Hardware::Start_Record();

}
//##########################################################################################################################################################
void Hardware::FFT_Restore_Channels(void)
{
	//printf("- FFT Restore Channels\r\n");

	//Hardware::Stop_Record();

	//restore channel setting
	Channel_Math_Active = Channel_Math_Active_bak;
	Channel_1_Active = Channel_1_Active_bak;
	Channel_2_Active = Channel_2_Active_bak;
	if(NumberOfChannels == 4)
	{
		Channel_3_Active = Channel_3_Active_bak;	
		Channel_4_Active = Channel_4_Active_bak;
	}
	else
	{
		Channel_3_Active_bak = Channel_3_Active = 0;	
		Channel_4_Active_bak = Channel_4_Active = 0;
	}


	// set LED
	if (Channel_1_Active) LED_ON[0] = 1;
	else LED_ON[0] = 0;

	// set LED
	if (Channel_2_Active) LED_ON[1] = 1;
	else LED_ON[1] = 0;

	// set LED
	if (Channel_3_Active) LED_ON[2] = 1;
	else LED_ON[2] = 0;

	// set LED
	if (Channel_4_Active) LED_ON[3] = 1;
	else LED_ON[3] = 0;

	// set LED
	if (Channel_Math_Active) LED_ON[4] = 1;
	else LED_ON[4] = 0;

	Send_LED();

	// Remove Signals of inactive channels
	if(!Channel_1_Active)RemovePlane |= 0x01;
	if(!Channel_2_Active)RemovePlane |= 0x02;
	if(!Channel_3_Active)RemovePlane |= 0x04;
	if(!Channel_4_Active)RemovePlane |= 0x08;

	ClearPlanes();

/*
	//restore triggermode
	MenuStatus[MENU_TRIGGERMODE][0] = FFT_TriggerMode_bak;	
	Display::MenuPopupInit(9, MENU_TRIGGERMODE, 92);	//BF #007
	TriggerLevelChanged = 1;
	TriggerModeChanged = 1;
	SetupTrigger();
*/

	UserIF::UpdateChannel(1, Channel_1_Active);
	UserIF::UpdateChannel(2, Channel_2_Active);
	UserIF::UpdateChannel(3, Channel_3_Active);
	UserIF::UpdateChannel(4, Channel_4_Active);
	SetupTrigger();


/*BF not needed, because it is done in RefreshScreen() 
	// force new output in statusbar
	VoltageChangedCh1 = 1;
	VoltageChangedCh2 = 1;
	VoltageChangedCh3 = 1;
	VoltageChangedCh4 = 1;
	
	Display::StatusUpdate();
*/



}
//##########################################################################################################################################################
void Hardware::Reset_To_Default(void)
{
	printf("- Reset to Default\r\n");

	//Hardware::Stop_Record();

	Hardware::Set_Vars_Default();

	Hardware::TRIG_AutoPretrigger();

   	Display::RecalcTimeParameters();

	Display::MenuInit();
	
	UserIF::UpdateChannel(1, 1);
	UserIF::UpdateChannel(2, 1);

	LED_ON[0] = 1;
	LED_ON[1] = 1;
	LED_ON[5] = 1;
	LED_ON[6] = 0;

	Rotary_Steps = 0;
	UserIF::ON_Zero_Channel_1();
	Rotary_Steps = 0;
	UserIF::ON_Zero_Channel_2();

	SetSwitches(1, Selected_Voltage_CH1);
	SetSwitches(2, Selected_Voltage_CH2);

	if (NumberOfChannels == 4)
	{

		UserIF::UpdateChannel(3, 1);
		UserIF::UpdateChannel(4, 1);

	
		LED_ON[2] = 1;
		LED_ON[3] = 1;
	
		Rotary_Steps = 0;
		UserIF::ON_Zero_Channel_3();
		Rotary_Steps = 0;
		UserIF::ON_Zero_Channel_4();

		SetSwitches(3, Selected_Voltage_CH3);
		SetSwitches(4, Selected_Voltage_CH4);

	}
/*	else
	{
		UserIF::UpdateChannel(3, 0);
		UserIF::UpdateChannel(4, 0);
	} 
*/
	UserIF::UpdateChannel(5, Channel_Math_Active);

	Send_LED();
	Display::CALCPRETRIGGER();
	SetupTrigger();
	
	Display::DrawInitialScreen();

	Display::DRAW_ALL_CURSOR();

	Signal::buildScaleLookupTable();

	Hardware::Start_Record();

}
//##########################################################################################################################################################
void Hardware::Restore_From_Flash(void)
{
	char CH1_bak, CH2_bak, CH3_bak, CH4_bak;
	unsigned char FFT_Mode_bak = FFT_Mode;

	printf("- Restore settings from flash\r");

	Set_Vars_Default();

	AMDFlash::Read_Config_Flash();

	if (config_loaded == false){ Reset_To_Default(); config_changed = 2; return;}	// emergency exit

	// set grid colour
	if (ColorPalette>9) ColorPalette = 0;

	//prepare FFT-mode
	if(FFT_Mode != FFT_OFF)
	{ Signal::FFT_buildTrigoTables(); Signal::FFT_buildScaleLookupTable();}

	Signal::buildScaleLookupTable();

	Send_LED();	

	TriggerLevelChanged = 1;
	TriggerModeChanged = 1;	
	TriggerWayChanged = 1;
	TimebaseChanged = 1;
	TimeOffsetChanged = 1;

	MenuAktive = 1;

	Cursor_Data_First_Draw = 0;
	Quick_Measure_First_Draw = 0;

	Display::RecalcTimeParameters();

	Display::CALCPRETRIGGER();
//BF add
	if (USTB_Mode == USTB_OFF)
	{
		S1Ptr = SIGNAL1;		// adjust signal pointer to 16k signal buffers
		S2Ptr = SIGNAL2;
		S3Ptr = SIGNAL3;
		S4Ptr = SIGNAL4;
		SMPtr = SIGNALM;
	}
	else					//prepare USTB-mode at start 
	{
		Signal::USTB_clearBuffer();	//clear all buffers and adjust pointer
		Reset_Timer2();
	}
//BF add

	//backup channel status
	CH1_bak = Channel_1_Active;
	CH2_bak = Channel_2_Active;
	CH3_bak = Channel_3_Active;
	CH4_bak = Channel_4_Active;

	FFT_Mode = FFT_OFF;								//FFT has to be switched off to process zero level handler

	//channels have to be active to activate new settings
	Channel_1_Active = 1;
	Channel_2_Active = 1;

	Rotary_Steps = 0;
	UserIF::ON_Zero_Channel_1();
	SetSwitches(1, Selected_Voltage_CH1);

	UserIF::ON_Zero_Channel_2();
	SetSwitches(2, Selected_Voltage_CH2);
	
	if (NumberOfChannels == 4)
	{
		Channel_3_Active = 1;
		Channel_4_Active = 1;

	      	UserIF::ON_Zero_Channel_3();
		SetSwitches(3, Selected_Voltage_CH3);

		UserIF::ON_Zero_Channel_4();
		SetSwitches(4, Selected_Voltage_CH4);
	}

	Hardware::SetupTrigger();							//set ADC depending registers

	//restore channel status
	Channel_1_Active = CH1_bak;
	Channel_2_Active = CH2_bak;
	Channel_3_Active = CH3_bak;
	Channel_4_Active = CH4_bak;

	FFT_Mode = FFT_Mode_bak;							// restore FFT mode

	Display::MenuInit();		//BF #005

	if (MenuStatus[MENU_ACQUIRE][2] == (FILT_OFF+1) || MenuStatus[MENU_ACQUIRE][2] == (FILT_OFF+2))
	{ FilterType = PRO; }
	else if (MenuStatus[MENU_ACQUIRE][2] > (FILT_OFF+2) && MenuStatus[MENU_ACQUIRE][2] < (FILT_OFF+6))
	{ FilterType = IIR; }
	else if (MenuStatus[MENU_ACQUIRE][2] > (FILT_OFF+5) && MenuStatus[MENU_ACQUIRE][2] < (FILT_OFF+9))
	{ FilterType = FIR; }


	//ON_Timebase();

	Memory_Window_visible = 0; 

	Display::DrawInitialScreen();

	Display::DRAW_ALL_CURSOR();

	Menu_Changed = 1;
	Menu_First_Draw = 1;
	//printf("setup trigger\r\n");
	//SetupTrigger();	// BF registers must be updated after all other actions!!!  -> wird aber schon in ON_Zerolevel gemacht! Löschen???
	
	printf("- Restore settings from flash           - done\r\n");


}
//##########################################################################################################################################################
//BF new Startup initialization
void Hardware::Start_Up(void)
{
	char CH1_bak, CH2_bak, CH3_bak, CH4_bak;
	unsigned char FFT_Mode_bak = FFT_Mode;

	printf("- Starting up\r");


	// color palette limiter
	if (ColorPalette>9) ColorPalette = 0;

	//prepare FFT-mode
	Signal::FFT_buildTrigoTables();

	//Signal::FFT_BuildScaleLookupTable();	-> is done in read config flash
	//Signal::Build_ScaleLookupTable();

	// create FIR lookup table
	Signal::FIR_buildNoiseFilterLookupTable();
	Signal::FIR_buildSincLookupTable();

	Setup_Interrupts();								//enable all interupts

 	//UserIF::UpdateChannel(1, Channel_1_Active);	->??

	// get number of active channels for global use -> Math channel has to be handled seperately
	Channels_Active = Channel_1_Active + Channel_2_Active + Channel_3_Active + Channel_4_Active;

	//backup channel status
	CH1_bak = Channel_1_Active;
	CH2_bak = Channel_2_Active;
	CH3_bak = Channel_3_Active;
	CH4_bak = Channel_4_Active;

	FFT_Mode = FFT_OFF;								//FFT has to be switched off to process zero level handler

	//channels have to be active to activate new settings
	Channel_1_Active = 1;
	Channel_2_Active = 1;

	Rotary_Steps = 0;
	UserIF::ON_Zero_Channel_1();
	SetSwitches(1, Selected_Voltage_CH1);

	UserIF::ON_Zero_Channel_2();
	SetSwitches(2, Selected_Voltage_CH2);
	
	if (NumberOfChannels == 4)
	{
		Channel_3_Active = 1;
		Channel_4_Active = 1;

	      	UserIF::ON_Zero_Channel_3();
		SetSwitches(3, Selected_Voltage_CH3);

		UserIF::ON_Zero_Channel_4();
		SetSwitches(4, Selected_Voltage_CH4);
	}

	//restore channel status
	Channel_1_Active = CH1_bak;
	Channel_2_Active = CH2_bak;
	Channel_3_Active = CH3_bak;
	Channel_4_Active = CH4_bak;

	FFT_Mode = FFT_Mode_bak;							// restore FFT mode

//	channel delay correction -> will be loaded from flash but may be damaged because of old values
//	check for correct value range - else set to default
	if(CH1_Del_Correct > 16 || CH1_Del_Correct < 0){CH1_Del_Correct = 0;}
	if(CH2_Del_Correct > 16 || CH2_Del_Correct < 0){CH2_Del_Correct = 0;}
	if(CH3_Del_Correct > 16 || CH3_Del_Correct < 0){CH3_Del_Correct = 0;}
	if(CH4_Del_Correct > 16 || CH4_Del_Correct < 0){CH4_Del_Correct = 0;}


	//--------------------------------------------------------------
	// 		preset flash
	//--------------------------------------------------------------
	//if(FlashPreset != (char)tc_dev_subversion)
	if(FlashPreset != 0x24)
	{
		printf("\nStart up: Presetting Flash\r\n");

		//FlashPreset = (char)tc_dev_subversion;
		FlashPreset = 0x24;

		//ADC registers to factory setting
		MenuStatus[MENU_HARDWARE][0] = 223;

		AMDFlash::ReadProtReg();

		//Pre Amp Gain to standard setting
		GainIdx = 1;
		MenuStatus[MENU_HARDWARE][1] = 231;		//BF #004
		
		//MenuStatus[MENU_HARDWARE][4] = 0;				// not used

		QP_mode = 0;					//BF #006
		MenuStatus[MENU_QUICKPRINT][5] = 185;		//BF-Version of Screenshot
		MenuStatus[MENU_QP_USB][5]     = 185;		//BF-Version of Screenshot

		FFT_grid = 0;
		DrawMono = 0;
		ColorPalette = 0;

	//	set channel delay to default
		CH1_Del_Correct = 0;
		CH2_Del_Correct = 0;
		CH3_Del_Correct = 0;
		CH4_Del_Correct = 0;

		CalSet = 0;
		MenuStatus[MENU_UTILITY][3] = 264;				// standard calibration set
	
	//      init extended utility menu
		MenuStatus[MENU_EXTUTILS][0] = 203;
		MenuStatus[MENU_EXTUTILS][1] = 203;
	
		if (NumberOfChannels == 4)
		{
			MenuStatus[MENU_EXTUTILS][2] = 203;
			MenuStatus[MENU_EXTUTILS][3] = 203;
		}
		else
		{
			MenuStatus[MENU_EXTUTILS][2] = INACTIVE;		// for 2 Channel version set inactive
			MenuStatus[MENU_EXTUTILS][3] = INACTIVE;		// for 2 Channel version set inactive
		}

		MenuStatus[MENU_TIMEBASE][0] = BTN_ON;				// Main
		MenuStatus[MENU_TIMEBASE][1] = BTN_OFF;				// Delayed
		MenuStatus[MENU_TIMEBASE][2] = BTN_OFF;				// XY-Mode
		MenuStatus[MENU_TIMEBASE][3] = BTN_OFF;
		MenuStatus[MENU_TIMEBASE][4] = BTN_OFF;
		MenuStatus[MENU_USTB][0] = USTB_ROLL;                     	// Roll-Mode forward
		MenuStatus[MENU_USTB][1] = USTB_PERM;				// Permanent window shift
		MenuStatus[MENU_USTB][2] = USTB_16KB;				// Buffer size 16KB
		MenuStatus[MENU_DISPLAY][2]  = 136;				// Display - Grid - 100%
		MenuStatus[MENU_DISPLAY][4]  = DRAW_FAST;			// Display - Draw Mode
		MenuStatus[MENU_DISPLAY][3] = 320;				// no display -> all channels off
		for(int i=0;i<4;i++)NoDisplay[i] = 0;				// no display -> all channels off

		MenuStatus[MENU_DISPL_SETUP][0]  = 300;				// grid color
		MenuStatus[MENU_DISPL_SETUP][1]  = 248;				// grid layout
		MenuStatus[MENU_DISPL_SETUP][2]  = 330;				// status layout
		MenuStatus[MENU_DISPL_SETUP][3]  = 240;				// no QM-cursors
		DrawMono = 0;

		USTB_Mode = USTB_OFF;
		USTB_Dir  = USTB_FORWARD;
		USTB_Disp = USTB_PERM;

		// Acquire
		MenuStatus[MENU_ACQUIRE][0] = LOGA_OFF;				// Acquire - Logic Processor 	-> off
		MenuStatus[MENU_ACQUIRE][1] = AVRG_OFF;				// Acquire - Average		-> off
		MenuStatus[MENU_ACQUIRE][2] = FILT_OFF;				// Acquire - Noise Filter 	-> off
		MenuStatus[MENU_ACQUIRE][3] = 42;				// Acquire - Interpolation	-> Linear
		ACQ_Average = 0;
		Display::MenuPopupInit(21, MENU_ACQUIRE, AVRG_OFF); 
		Display::MenuPopupInit(22, MENU_ACQUIRE, FILT_OFF); 
		Display::MenuPopupInit(23, MENU_ACQUIRE, 42); 
		Display::MenuPopupInit(47, MENU_ACQUIRE, LOGA_OFF); 

		MenuStatus[MENU_TRIGGERMODE][0] = TRIG_AUTO;			//set new trigger auto mode

		MenuStatus[MENU_TRIGGERSUB][0] = 114;				// LED 1
		MenuStatus[MENU_TRIGGERSUB][1] = 119;				// LED 2
		MenuStatus[MENU_TRIGGERSUB][2] = BTN_OFF;			// map LED to Ch 3/4
		MenuStatus[MENU_TRIGGERSUB][3] = 124;				// Single Trigger setting
		MenuStatus[MENU_TRIGGERSUB][4] = 272;				// Pre Trigger setting -> Left Edge

		MenuStatus[MENU_TRIGGEREDGE][1] = 137;				//trigger source is channel 1
		MenuStatus[MENU_TRIGGEREDGE][2] = INACTIVE;				//ext. trigger popup is inactive
		MenuStatus[MENU_TRIGGEREDGE][3] = INACTIVE;				//TV trigger popup is inactive

		MenuStatus[MENU_AUTOSCALE][3] = 281;				// Autoscale setup TB search -> all channels

		MenuStatus[MENU_QUICKMEASURE][0] = 27;	
		MenuStatus[MENU_QUICKMEASURE][1] = 52;
		MenuStatus[MENU_QUICKMEASURE][2] = 52;

		Channel_Math_Active = 0;                       			// Math channel off
		// not used MenuStatus[MENU_MATH][1] = BTN_OFF;                		// 
		MenuStatus[MENU_MATH][2] = BTN_OFF;                		// math 1*2 off
		MenuStatus[MENU_MATH][3] = BTN_ON;                		// math 1-2 on
		MenuStatus[MENU_MATH][4] = BTN_OFF;                		// math 1+2 off

		MenuPopupStatus[8][0] = 3;	              			//BF popup for external trigger
		MenuPopupStatus[8][1] = 2;
		MenuPopupStatus[8][2] = 2;

		MenuPopupStatus[11][0] = 3;              			//BF popup for TV trigger
		MenuPopupStatus[11][1] = 2;

		Cursor_Vertical_Position_TY_1 = 100;	
		Cursor_Vertical_Position_TY_2 = 400;	
	
		Cursor_Vertical_Position_XY_1 = 100;
		Cursor_Vertical_Position_XY_2 = 300;
	
		Cursor_Vertical_Position_FFT_1 = 125;
		Cursor_Vertical_Position_FFT_2 = 475;

		SavePointer = 1;

		ADC_Offset[0][0] = 0;
		ADC_Offset[0][1] = 0;
		ADC_Offset[0][2] = 0;
		ADC_Offset[0][3] = 0;	
		
		ADC_Offset[1][0] = 0;
		ADC_Offset[1][1] = 0;
		ADC_Offset[1][2] = 0;
		ADC_Offset[1][3] = 0;
	
		ADC_Offset[2][0] = 0;
		ADC_Offset[2][1] = 0;
		ADC_Offset[2][2] = 0;
		ADC_Offset[2][3] = 0;
	
		ADC_Offset[3][0] = 0;
		ADC_Offset[3][1] = 0;
		ADC_Offset[3][2] = 0;
		ADC_Offset[3][3] = 0;

		AMDFlash::Write_Protected_Flash();

		Signal::buildScaleLookupTable();

	} //preset end

	config_changed = 2;					// actualize backup config sector
	AMDFlash::Write_Config_Flash();

	MenuStatus[MENU_DISPL_FFT][2] = MenuStatus[MENU_DISPLAY][2];
	Display::MenuInit();					//BF #005

	Send_LED();	

	//MenuStatusChanged = 1;
	//MenuAktive = 1;
	Menu_Changed = 1;

	Display::DrawInitialScreen();

	// set filter type
	if (MenuStatus[MENU_ACQUIRE][2] == (FILT_OFF+1) || MenuStatus[MENU_ACQUIRE][2] == (FILT_OFF+2))
	{ FilterType = PRO; }
	else if (MenuStatus[MENU_ACQUIRE][2] > (FILT_OFF+2) && MenuStatus[MENU_ACQUIRE][2] < (FILT_OFF+6))
	{ FilterType = IIR; }
	else if (MenuStatus[MENU_ACQUIRE][2] > (FILT_OFF+5) && MenuStatus[MENU_ACQUIRE][2] < (FILT_OFF+9))
	{ FilterType = FIR; }

	SingleShot = 0;
	Run = 1;						//always start in run mode

	Display::RecalcTimeParameters();

	Display::CALCTRIGGER();

	if(FFT_Mode != FFT_OFF)
	Display::FFT_CalcCursorData();
	else
	Display::CALCCURSORDATA();

	Display::DRAW_ALL_CURSOR();

	Hardware::SetupTrigger();							//set ADC depending registers
	
	if(USTB_Mode == USTB_OFF)
	{
		Display::CALCPRETRIGGER();
		Hardware::Start_Record();						//start normal data acquistion
	}
	else										//if USTB is active, start timer controlled acquisition
	{ 
		Signal::USTB_clearBuffer();						//clear all buffers
		Hardware::Reset_Timer2();						//start USTB data acquistion
	}

	//Splash_drawed = false;

	if (MenuStatus[MENU_TIMEBASE][4] == BTN_OFF)
	Display::DRAWMEMORY(1, 0, 0);							//close memory window if browse is off

	//printf("- Startup preparation                   - done\r\n");
	printf("- Starting up                           - done\r\n\n");


	printf("----------------------------------------------\r\n");
	printf("Version : %1i.%1i.BF.%1i.%1i%s\r\n", tc_version, tc_subversion, tc_dev_version, tc_dev_subversion, tc_compilation);
	printf("Hardware: %X.%c%c\r\n", tc_hw_version, tc_production_lot1, tc_production_lot2);
	printf("Serial  : %06d%02d%1X%1X\r\n", tc_serial, ((tc_shipment_date & 0x0000FF00) >> 8), ((tc_shipment_date & 0x000000F0) >> 4), (tc_shipment_date & 0x0000000F));	
	printf("Model   : W%04dA / %d Channels \r\n", tc_model, NumberOfChannels);
	printf("----------------------------------------------\r\n\n");


	// check if logic processor has to be started
	LA_active = 0;

	if (MenuStatus[MENU_ACQUIRE][0] != LOGA_OFF)
	{
		// restore voltage ranges
		Selected_Voltage_CH1 = Selected_Voltage_CH1_bak;
		Selected_Voltage_CH2 = Selected_Voltage_CH2_bak;
		Selected_Voltage_CH3 = Selected_Voltage_CH3_bak;
		Selected_Voltage_CH4 = Selected_Voltage_CH4_bak;

		// restore trigger settings
		Trigger_Pos_CH1 = Trigger_Pos_CH1_bak;
		Trigger_Pos_CH2 = Trigger_Pos_CH2_bak;
		Trigger_Pos_CH3 = Trigger_Pos_CH3_bak;
		Trigger_Pos_CH4 = Trigger_Pos_CH4_bak;

		Signal::LOGA_LogicProcessor();
	}




//Hardware::Reset_To_Default();

}
//##########################################################################################################################################################
//BF test the LED for function
void Hardware::LED_FunctionTest(char tmode)
{
	unsigned char x;

	int led_bak[16];

	//printf("Testing LEDs\r");


	switch (tmode)
	{
		case 0: // quick test
		{
			for(x=0;x<16;x++)	//switch all LEDs on 	
			{ LED_ON[x] = 1; }
		
			Send_LED();
			break;
		}

		case 1: // extended LED test
		{
			for(x=0;x<16;x++)	//backup LED status and switch all LEDs off 	
			{ led_bak[x] = LED_ON[x]; LED_ON[x] = 0; }
		
			Send_LED();
			nr_delay(50);		//wait until shift registers are ready
		
			for(char i=0;i<4;i++)
			{
				for(x=0;x<16;x++)	//switch all LEDs on 	
				{ LED_ON[x] = 1; }
			
				Send_LED();
				nr_delay(500);		//let the LED shine a moment
			
			
				for(x=0;x<16;x++)	//switch all LEDs off	
				{ LED_ON[x] = 0; }
			
				Send_LED();
				nr_delay(500);		//wait a little moment
			}
		
			for(char i=0;i<4;i++)
			{
				LED_ON[12] = 1;		//Run/Stop green
				LED_ON[13] = 0;	
				LED_ON[14] = 1;		//Single red
				LED_ON[15] = 0;
				Send_LED();
				nr_delay(500);		//let the LED shine a moment
	
				LED_ON[12] = 0;	
				LED_ON[13] = 1;		//Run/Stop red
				LED_ON[14] = 0;		
				LED_ON[15] = 1;		//Single green
				Send_LED();
				nr_delay(500);		//let the LED shine a moment
			}


			for(x=0;x<16;x++)	// restore LED status
			{ LED_ON[x] = led_bak[x]; }
		
			Send_LED();
			nr_delay(50);		//wait until shift registers are ready

			break;
		}
	}

	//printf("Testing LEDs				- done\r\n");

}
//##########################################################################################################################################################
//BF 
void Hardware::CenterTrace(int channel)
{
	Rotary_Steps = 0;

	if (FFT_Mode != FFT_OFF) return;

	if(XY_Mode)
	{
		//set zerolevels to the middle of the grid
		switch(channel)
		{
			case 1:
			{
				Trigger_Pos_CH1 = Trigger_Pos_CH1 - Virtual_ZeroLevelXYCH1;		//keep triggerlevel
				ZeroLevelCH1 = GRID_HEIGHT / 2;
				ZeroLevelCH1_Old = ZeroLevelCH1;
				Virtual_ZeroLevelXYCH1 = 0;
				UserIF::ON_Zero_Channel_1();
				break;
			}
	
			case 2:
			{
				Trigger_Pos_CH2 = Trigger_Pos_CH2 - Virtual_ZeroLevelXYCH2;		//keep triggerlevel
				ZeroLevelCH2 = GRID_HEIGHT / 2;
				ZeroLevelCH2_Old = ZeroLevelCH2;
				Virtual_ZeroLevelXYCH2 = 0;
				UserIF::ON_Zero_Channel_2();
				break;
			}
	
			case 3:
			{
				Trigger_Pos_CH3 = Trigger_Pos_CH3 - Virtual_ZeroLevelXYCH3;		//keep triggerlevel
				ZeroLevelCH3 = GRID_HEIGHT / 2;
				ZeroLevelCH3_Old = ZeroLevelCH3;
				Virtual_ZeroLevelXYCH3 = 0;
				UserIF::ON_Zero_Channel_3();
				break;
			}
	
			case 4:
			{
				Trigger_Pos_CH4 = Trigger_Pos_CH4 - Virtual_ZeroLevelXYCH4;		//keep triggerlevel
				ZeroLevelCH4 = GRID_HEIGHT / 2;
				ZeroLevelCH4_Old = ZeroLevelCH4;
				Virtual_ZeroLevelXYCH4 = 0;
				UserIF::ON_Zero_Channel_4();
				break;
			}
		}

	}
	else
	{
		//set zerolevels to the middle of the grid
		switch(channel)
		{
			case 1:
			{
				Trigger_Pos_CH1 = Trigger_Pos_CH1 - Virtual_ZeroLevelCH1;		//keep triggerlevel
				ZeroLevelCH1 = GRID_HEIGHT / 2;
				ZeroLevelCH1_Old = ZeroLevelCH1;
				Virtual_ZeroLevelCH1 = 0;
				UserIF::ON_Zero_Channel_1();
				break;
			}
	
			case 2:
			{
				Trigger_Pos_CH2 = Trigger_Pos_CH2 - Virtual_ZeroLevelCH2;		//keep triggerlevel
				ZeroLevelCH2 = GRID_HEIGHT / 2;
				ZeroLevelCH2_Old = ZeroLevelCH2;
				Virtual_ZeroLevelCH2 = 0;
				UserIF::ON_Zero_Channel_2();
				break;
			}
	
			case 3:
			{
				Trigger_Pos_CH3 = Trigger_Pos_CH3 - Virtual_ZeroLevelCH3;		//keep triggerlevel
				ZeroLevelCH3 = GRID_HEIGHT / 2;
				ZeroLevelCH3_Old = ZeroLevelCH3;
				Virtual_ZeroLevelCH3 = 0;
				UserIF::ON_Zero_Channel_3();
				break;
			}
	
			case 4:
			{
				Trigger_Pos_CH4 = Trigger_Pos_CH4 - Virtual_ZeroLevelCH4;		//keep triggerlevel
				ZeroLevelCH4 = GRID_HEIGHT / 2;
				ZeroLevelCH4_Old = ZeroLevelCH4;
				Virtual_ZeroLevelCH4 = 0;
				UserIF::ON_Zero_Channel_4();
				break;
			}
		}
	}
	//Hardware::SetupTrigger();

}
//##########################################################################################################################################################
int GetDC_Offset(int channel)
{
	unsigned char *lPtrSignal = NULL;
	int ix;
	
	unsigned char buf_byte = 0, adc_min = 255 , adc_max = 0;
	unsigned char avrg = 0;
	unsigned char lADC_Zero=0;

	int offset=0, diff;
	int lVrange=0;

	switch(channel)
	{
		case 1: lPtrSignal = SIGNAL1; lADC_Zero = ADC_VirtualZero_CH1; lVrange = Selected_Voltage_CH1; break;
		case 2: lPtrSignal = SIGNAL2; lADC_Zero = ADC_VirtualZero_CH2; lVrange = Selected_Voltage_CH2;break;
		case 3: lPtrSignal = SIGNAL3; lADC_Zero = ADC_VirtualZero_CH3; lVrange = Selected_Voltage_CH3;break;
		case 4: lPtrSignal = SIGNAL4; lADC_Zero = ADC_VirtualZero_CH4; lVrange = Selected_Voltage_CH4;break;
	}

	for (ix=150; ix < 3800; ix++)
	{
		buf_byte = lPtrSignal[ix];
		if (adc_min > buf_byte) adc_min = buf_byte;
		if (adc_max < buf_byte) adc_max = buf_byte;
	}

	// calculate average
	avrg = (unsigned char) (((int) adc_min + (int) adc_max) >> 1);

	diff = avrg - lADC_Zero;

	// calculate offset
	if (avrg < lADC_Zero-15 || avrg > lADC_Zero+15){
	offset = (int)((float)(diff) * ScaleFactor[lVrange][GainIdx]);        //(diff-ADC_ZERO)
	}

	//printf("\r\nChannel %d ADCzero %d AVRG %d ADCmin %d ADCmax %d ->Offset %d", channel, lADC_Zero, avrg, adc_min, adc_max, offset);

	//if (offset == 0)printf("   -> no Offset", channel);

	//printf("\r\n");

/*
	// calculate offset
	if (avrg > lADC_Zero-5 &&  avrg < lADC_Zero+5)
	{ return 0; }						// no DC offset
	else if(adc_max > lADC_Zero-5)
	{ offset = -50; }					// shift zero level down
	else if(adc_min < lADC_Zero+5)
	{ offset = 50; }					// shift zero level up

	if(Channels_Active == 1)
	{ offset *= 3;}
	else if(Channels_Active == 2)
	{ offset = offset<<1;}
*/



	return offset;

}
//BF 
void Hardware::DispatchTraces(void)
{

	int  lTopPos = 0, lBotPos = 0;
	int lVZL1_Old,lVZL2_Old,lVZL3_Old,lVZL4_Old;

	int lDC_Offset1=0, lDC_Offset2=0, lDC_Offset3=0, lDC_Offset4=0;

	if (FFT_Mode != FFT_OFF) return;
	if (XY_Mode) return;


	ZeroLevelCH1_Old = ZeroLevelCH1;
	ZeroLevelCH2_Old = ZeroLevelCH2;
	ZeroLevelCH3_Old = ZeroLevelCH3;
	ZeroLevelCH4_Old = ZeroLevelCH4;

	lVZL1_Old = Virtual_ZeroLevelCH1;
	lVZL2_Old = Virtual_ZeroLevelCH2;
	lVZL3_Old = Virtual_ZeroLevelCH3;
	lVZL4_Old = Virtual_ZeroLevelCH4;

	if (Channel_Math_Active || (Channels_Active > 2))
	{
		//lTopPos = (int)(GRID_HEIGHT / 5.333);			//10% line
		lTopPos = (int)(GRID_HEIGHT / 8);			// first div line
		lBotPos = (int)((GRID_HEIGHT / 8) * 7);			// last div line
		//lBotPos = (int)(GRID_HEIGHT - (GRID_HEIGHT / 5.333));	//90% line
	}
	else
	{
		lTopPos = (int)(GRID_HEIGHT / 4);		// 1/4 grid height
		lBotPos = (int)((GRID_HEIGHT / 4) * 3);		// 3/4 grid height
	}
/*
	// check for DC offset like digital signals
	if (Channel_1_Active) lDC_Offset1 = GetDC_Offset(1);
	if (Channel_2_Active) lDC_Offset2 = GetDC_Offset(2);
	if (Channel_3_Active) lDC_Offset3 = GetDC_Offset(3);
	if (Channel_4_Active) lDC_Offset4 = GetDC_Offset(4);
*/
	switch(Channels_Active)
	{
		case 1:	// center trace with DC offset
		{
			if (Channel_1_Active)
			{
				Trigger_Pos_CH1 = Trigger_Pos_CH1 - Virtual_ZeroLevelCH1 - lDC_Offset1;		//keep triggerlevel
				ZeroLevelCH1 = GRID_HEIGHT / 2;
				ZeroLevelCH1_Old = ZeroLevelCH1;
				Virtual_ZeroLevelCH1 = -lDC_Offset1;
				UserIF::ON_Zero_Channel_1();
			}

			if (Channel_2_Active)
			{
				Trigger_Pos_CH2 = Trigger_Pos_CH2 - Virtual_ZeroLevelCH2 - lDC_Offset2;		//keep triggerlevel
				ZeroLevelCH2 = GRID_HEIGHT / 2;
				ZeroLevelCH2_Old = ZeroLevelCH2;
				Virtual_ZeroLevelCH2 = -lDC_Offset2;
				UserIF::ON_Zero_Channel_2();
			}

			if (Channel_3_Active)
			{
				Trigger_Pos_CH3 = Trigger_Pos_CH3 - Virtual_ZeroLevelCH3 - lDC_Offset3;		//keep triggerlevel
				ZeroLevelCH3 = GRID_HEIGHT / 2;
				ZeroLevelCH3_Old = ZeroLevelCH3;
				Virtual_ZeroLevelCH3 = -lDC_Offset3;
				UserIF::ON_Zero_Channel_3();
			}

			if (Channel_4_Active)
			{
				Trigger_Pos_CH4 = Trigger_Pos_CH4 - Virtual_ZeroLevelCH4 - lDC_Offset4;		//keep triggerlevel
				ZeroLevelCH4 = GRID_HEIGHT / 2;
				ZeroLevelCH4_Old = ZeroLevelCH4;
				Virtual_ZeroLevelCH4 = -lDC_Offset4;
				UserIF::ON_Zero_Channel_4();
			}


			return;
		}

		case 2:
		{
			if (Channel_1_Active && Channel_2_Active)
			{
				ZeroLevelCH1 = lTopPos;
				ZeroLevelCH2 = lBotPos;
				
				Virtual_ZeroLevelCH1 = ZeroLevelCH1 - (GRID_HEIGHT / 2) - lDC_Offset1;	//Virtual zeroes are related to 1/2 grid height,
				Virtual_ZeroLevelCH2 = ZeroLevelCH2 - (GRID_HEIGHT / 2) - lDC_Offset2;	//means that VZero = 0 is the middle of the grid

				Trigger_Pos_CH1 = Trigger_Pos_CH1 - lVZL1_Old + Virtual_ZeroLevelCH1;	//keep triggerlevel
				Trigger_Pos_CH2 = Trigger_Pos_CH2 - lVZL2_Old + Virtual_ZeroLevelCH2;	//keep triggerlevel
			}
			else if (Channel_1_Active && Channel_3_Active)
			{	
				ZeroLevelCH1 = lTopPos;
				ZeroLevelCH3 = lBotPos;
				
				Virtual_ZeroLevelCH1 = ZeroLevelCH1 - (GRID_HEIGHT / 2) - lDC_Offset1;	//Virtual zeroes are related to 1/2 grid height,
				Virtual_ZeroLevelCH3 = ZeroLevelCH3 - (GRID_HEIGHT / 2) - lDC_Offset3;	//means that VZero = 0 is the middle of the grid

				Trigger_Pos_CH1 = Trigger_Pos_CH1 - lVZL1_Old + Virtual_ZeroLevelCH1;	//keep triggerlevel
				Trigger_Pos_CH3 = Trigger_Pos_CH3 - lVZL3_Old + Virtual_ZeroLevelCH3;	//keep triggerlevel
			}
			else if (Channel_1_Active && Channel_4_Active)
			{	
				ZeroLevelCH1 = lTopPos;
				ZeroLevelCH4 = lBotPos;
				
				Virtual_ZeroLevelCH1 = ZeroLevelCH1 - (GRID_HEIGHT / 2) - lDC_Offset1;	//Virtual zeroes are related to 1/2 grid height,
				Virtual_ZeroLevelCH4 = ZeroLevelCH4 - (GRID_HEIGHT / 2) - lDC_Offset4;	//means that VZero = 0 is the middle of the grid

				Trigger_Pos_CH1 = Trigger_Pos_CH1 - lVZL1_Old + Virtual_ZeroLevelCH1;	//keep triggerlevel
				Trigger_Pos_CH4 = Trigger_Pos_CH4 - lVZL4_Old + Virtual_ZeroLevelCH4;	//keep triggerlevel
			}
			else if (Channel_2_Active && Channel_3_Active)
			{	
				ZeroLevelCH2 = lTopPos;
				ZeroLevelCH3 = lBotPos;
				
				Virtual_ZeroLevelCH2 = ZeroLevelCH2 - (GRID_HEIGHT / 2) - lDC_Offset2;	//Virtual zeroes are related to 1/2 grid height,
				Virtual_ZeroLevelCH3 = ZeroLevelCH3 - (GRID_HEIGHT / 2) - lDC_Offset3;	//means that VZero = 0 is the middle of the grid

				Trigger_Pos_CH2 = Trigger_Pos_CH2 - lVZL2_Old + Virtual_ZeroLevelCH2;	//keep triggerlevel
				Trigger_Pos_CH3 = Trigger_Pos_CH3 - lVZL3_Old + Virtual_ZeroLevelCH3;	//keep triggerlevel
			}
			else if (Channel_2_Active && Channel_4_Active)
			{	
				ZeroLevelCH2 = lTopPos;
				ZeroLevelCH4 = lBotPos;
				
				Virtual_ZeroLevelCH2 = ZeroLevelCH2 - (GRID_HEIGHT / 2) - lDC_Offset2;	//Virtual zeroes are related to 1/2 grid height,
				Virtual_ZeroLevelCH4 = ZeroLevelCH4 - (GRID_HEIGHT / 2) - lDC_Offset4;	//means that VZero = 0 is the middle of the grid

				Trigger_Pos_CH2 = Trigger_Pos_CH2 - lVZL2_Old + Virtual_ZeroLevelCH2;	//keep triggerlevel
				Trigger_Pos_CH4 = Trigger_Pos_CH4 - lVZL4_Old + Virtual_ZeroLevelCH4;	//keep triggerlevel
			}
			else if (Channel_3_Active && Channel_4_Active)
			{	
				ZeroLevelCH3 = lTopPos;
				ZeroLevelCH4 = lBotPos;
				
				Virtual_ZeroLevelCH3 = ZeroLevelCH3 - (GRID_HEIGHT / 2) - lDC_Offset3;	//Virtual zeroes are related to 1/2 grid height,
				Virtual_ZeroLevelCH4 = ZeroLevelCH4 - (GRID_HEIGHT / 2) - lDC_Offset4;	//means that VZero = 0 is the middle of the grid

				Trigger_Pos_CH3 = Trigger_Pos_CH3 - lVZL3_Old + Virtual_ZeroLevelCH3;	//keep triggerlevel
				Trigger_Pos_CH4 = Trigger_Pos_CH4 - lVZL4_Old + Virtual_ZeroLevelCH4;	//keep triggerlevel
			}


			break;
		}

		case 3:
		{
		
			if (Channel_Math_Active)
			{
				ZeroLevelCH1 = lTopPos;
				ZeroLevelCH2 = (int)((GRID_HEIGHT / 8) * 3);			//third div
				ZeroLevelCH3 = (int)((GRID_HEIGHT / 8) * 5);			//fifth div
				ZeroLevelCH4 = lBotPos;
	
				Virtual_ZeroLevelCH1 = ZeroLevelCH1 - (GRID_HEIGHT / 2) - lDC_Offset1;	//Virtual zeroes are related to 1/2 grid height,
				Virtual_ZeroLevelCH2 = ZeroLevelCH2 - (GRID_HEIGHT / 2) - lDC_Offset2;	//means that VZero = 0 is the middle of the grid
				Virtual_ZeroLevelCH3 = ZeroLevelCH3 - (GRID_HEIGHT / 2) - lDC_Offset3;	
				Virtual_ZeroLevelCH4 = ZeroLevelCH4 - (GRID_HEIGHT / 2) - lDC_Offset4;
	
				Trigger_Pos_CH1 = Trigger_Pos_CH1 - lVZL1_Old + Virtual_ZeroLevelCH1;	//keep triggerlevel
				Trigger_Pos_CH2 = Trigger_Pos_CH2 - lVZL2_Old + Virtual_ZeroLevelCH2;	//keep triggerlevel
				Trigger_Pos_CH3 = Trigger_Pos_CH3 - lVZL3_Old + Virtual_ZeroLevelCH3;	//keep triggerlevel
				Trigger_Pos_CH4 = Trigger_Pos_CH4 - lVZL4_Old + Virtual_ZeroLevelCH4;	//keep triggerlevel
			}	
			else if (!Channel_1_Active)
			{
				ZeroLevelCH2 = lTopPos;
				ZeroLevelCH4 = lBotPos;
				
				Virtual_ZeroLevelCH2 = ZeroLevelCH2 - (GRID_HEIGHT / 2) - lDC_Offset2;	//Virtual zeroes are related to 1/2 grid height,
				Virtual_ZeroLevelCH4 = ZeroLevelCH4 - (GRID_HEIGHT / 2) - lDC_Offset4;	//means that VZero = 0 is the middle of the grid

				Trigger_Pos_CH2 = Trigger_Pos_CH2 - lVZL2_Old + Virtual_ZeroLevelCH2;	//keep triggerlevel
				Trigger_Pos_CH4 = Trigger_Pos_CH4 - lVZL4_Old + Virtual_ZeroLevelCH4;	//keep triggerlevel

				UserIF::ON_Zero_Channel_2();
				UserIF::ON_Zero_Channel_4();

 				CenterTrace(3);
				return;
			}
			else if (!Channel_2_Active)
			{
				ZeroLevelCH1 = lTopPos;
				ZeroLevelCH4 = lBotPos;
				
				Virtual_ZeroLevelCH1 = ZeroLevelCH1 - (GRID_HEIGHT / 2) - lDC_Offset1;		//Virtual zeroes are related to 1/2 grid height,
				Virtual_ZeroLevelCH4 = ZeroLevelCH4 - (GRID_HEIGHT / 2) - lDC_Offset4;		//means that VZero = 0 is the middle of the grid

				Trigger_Pos_CH1 = Trigger_Pos_CH1 - lVZL1_Old + Virtual_ZeroLevelCH1;	//keep triggerlevel
				Trigger_Pos_CH4 = Trigger_Pos_CH4 - lVZL4_Old + Virtual_ZeroLevelCH4;	//keep triggerlevel

				UserIF::ON_Zero_Channel_1();
				UserIF::ON_Zero_Channel_4();

 				CenterTrace(3);
				return;
			}
			else if (!Channel_3_Active)
			{
				ZeroLevelCH1 = lTopPos;
				ZeroLevelCH4 = lBotPos;
				
				Virtual_ZeroLevelCH1 = ZeroLevelCH1 - (GRID_HEIGHT / 2);		//Virtual zeroes are related to 1/2 grid height,
				Virtual_ZeroLevelCH4 = ZeroLevelCH4 - (GRID_HEIGHT / 2);		//means that VZero = 0 is the middle of the grid

				Trigger_Pos_CH1 = Trigger_Pos_CH1 - lVZL1_Old + Virtual_ZeroLevelCH1 - lDC_Offset1;	//keep triggerlevel
				Trigger_Pos_CH4 = Trigger_Pos_CH4 - lVZL4_Old + Virtual_ZeroLevelCH4 - lDC_Offset4;	//keep triggerlevel

				UserIF::ON_Zero_Channel_1();
				UserIF::ON_Zero_Channel_4();

 				CenterTrace(2);
				return;
			}
			else if (!Channel_4_Active)
			{
				ZeroLevelCH1 = lTopPos;
				ZeroLevelCH3 = lBotPos;
				
				Virtual_ZeroLevelCH1 = ZeroLevelCH1 - (GRID_HEIGHT / 2) - lDC_Offset1;		//Virtual zeroes are related to 1/2 grid height,
				Virtual_ZeroLevelCH3 = ZeroLevelCH3 - (GRID_HEIGHT / 2) - lDC_Offset3;		//means that VZero = 0 is the middle of the grid

				Trigger_Pos_CH1 = Trigger_Pos_CH1 - lVZL1_Old + Virtual_ZeroLevelCH1;	//keep triggerlevel
				Trigger_Pos_CH3 = Trigger_Pos_CH3 - lVZL3_Old + Virtual_ZeroLevelCH3;	//keep triggerlevel

				UserIF::ON_Zero_Channel_1();
				UserIF::ON_Zero_Channel_3();

				CenterTrace(2);
				return;
			}
			
			break;

		}

		case 4:
		{
			ZeroLevelCH1 = lTopPos;
			ZeroLevelCH2 = (int)((GRID_HEIGHT / 8) * 3);			//third div
			ZeroLevelCH3 = (int)((GRID_HEIGHT / 8) * 5);			//fifth div
			ZeroLevelCH4 = lBotPos;

			Virtual_ZeroLevelCH1 = ZeroLevelCH1 - (GRID_HEIGHT / 2) - lDC_Offset1;	//Virtual zeroes are related to 1/2 grid height,
			Virtual_ZeroLevelCH2 = ZeroLevelCH2 - (GRID_HEIGHT / 2) - lDC_Offset2;	//means that VZero = 0 is the middle of the grid
			Virtual_ZeroLevelCH3 = ZeroLevelCH3 - (GRID_HEIGHT / 2) - lDC_Offset3;	
			Virtual_ZeroLevelCH4 = ZeroLevelCH4 - (GRID_HEIGHT / 2) - lDC_Offset4;

			Trigger_Pos_CH1 = Trigger_Pos_CH1 - lVZL1_Old + Virtual_ZeroLevelCH1;	//keep triggerlevel
			Trigger_Pos_CH2 = Trigger_Pos_CH2 - lVZL2_Old + Virtual_ZeroLevelCH2;	//keep triggerlevel
			Trigger_Pos_CH3 = Trigger_Pos_CH3 - lVZL3_Old + Virtual_ZeroLevelCH3;	//keep triggerlevel
			Trigger_Pos_CH4 = Trigger_Pos_CH4 - lVZL4_Old + Virtual_ZeroLevelCH4;	//keep triggerlevel

			break;

		}



	}

	if (Channel_1_Active) UserIF::ON_Zero_Channel_1();
	if (Channel_2_Active) UserIF::ON_Zero_Channel_2();
	if (Channel_3_Active) UserIF::ON_Zero_Channel_3();
	if (Channel_4_Active) UserIF::ON_Zero_Channel_4();

	//Hardware::SetupTrigger();




}
//##########################################################################################################################################################
//BF 
void Hardware::TRIG_AutoLevel(void)
{
	int lScaleIndex = 0;

	unsigned char lMaxValue = 0, lMinValue = 255;
	int lMeanValue =  ADC_ZERO;
	int lSignalEnd;


	if (MainTimebase < 11) lSignalEnd = 16000;	//16K
	else lSignalEnd = 4000;				// 4K


/*
	
	Start_Record();

	//wait for ADC
	for(int timeout = 0;(timeout < 100) && !ADC_Data_Available;timeout++)
	nr_delay(10);

	//if no new data is available send error message
	if (ADC_Data_Available == 0)
	{ printf("\r\nTimeout Error, no new Data available\r\n");  }

	//reset availability flag	
	ADC_Data_Available = 0;
*/

	// which channel is trigger source?
	switch(Selected_Trigger_Source)
	{
		case 1:
		{

			//read signal and calculate 50% trigger level
			//ReadOut_Signal(1);


			//find maxima and minima
			for (int i = 100; i<lSignalEnd ;i++)
			{
				if (SIGNAL1[i] > lMaxValue) lMaxValue = SIGNAL1[i];
				if (SIGNAL1[i] < lMinValue) lMinValue = SIGNAL1[i];
			}

			//calculate 50%
			lMeanValue = (int)(lMaxValue + lMinValue) >> 1;

			//printf("Mean %d = (Max %d + Min %d)/2\r\n",lMeanValue,lMaxValue,lMinValue);

			lScaleIndex = ScaleIndexTable[Selected_Voltage_CH1];

			if (MenuStatus[MENU_CHANNEL1][2] == BTN_ON)	//Inverted Signal	BF
			{ Trigger_Pos_CH1 = (GRID_HEIGHT / 2) + Virtual_ZeroLevelCH1 + (Virtual_ZeroLevelCH1 - ScaleLookupTable[lMeanValue][lScaleIndex]); }
			else
			{ Trigger_Pos_CH1 = (GRID_HEIGHT / 2) + ScaleLookupTable[lMeanValue][lScaleIndex]; }

			if (Trigger_Pos_CH1 > GRID_HEIGHT){ Trigger_Pos_CH1 = GRID_HEIGHT; }
			if (Trigger_Pos_CH1 < 0){ Trigger_Pos_CH1 = 0; }
			break;
		}

		case 2:
		{
			//find maxima and minima
			for (int i = 100; i<lSignalEnd ;i++)
			{
				if (SIGNAL2[i] > lMaxValue) lMaxValue = SIGNAL2[i];
				if (SIGNAL2[i] < lMinValue) lMinValue = SIGNAL2[i];
			}

			//calculate 50%
			lMeanValue = (int)(lMaxValue + lMinValue) >> 1;

			lScaleIndex = ScaleIndexTable[Selected_Voltage_CH2];

			if (MenuStatus[MENU_CHANNEL2][2] == BTN_ON)	//Inverted Signal	BF
			{ Trigger_Pos_CH2 = (GRID_HEIGHT / 2) + Virtual_ZeroLevelCH2 + (Virtual_ZeroLevelCH2 - ScaleLookupTable[lMeanValue][lScaleIndex]); }
			else
			{ Trigger_Pos_CH2 = (GRID_HEIGHT / 2) + ScaleLookupTable[lMeanValue][lScaleIndex]; }

			if (Trigger_Pos_CH2 > GRID_HEIGHT){ Trigger_Pos_CH2 = GRID_HEIGHT; } 
			if (Trigger_Pos_CH2 < 0){ Trigger_Pos_CH2 = 0; }

			break;
		}

		case 3:
		{
			//find maxima and minima
			for (int i = 100; i<lSignalEnd ;i++)
			{
				if (SIGNAL3[i] > lMaxValue) lMaxValue = SIGNAL3[i];
				if (SIGNAL3[i] < lMinValue) lMinValue = SIGNAL3[i];
			}

			//calculate 50%
			lMeanValue = (int)(lMaxValue + lMinValue) >> 1;

			lScaleIndex = ScaleIndexTable[Selected_Voltage_CH3];

			if (MenuStatus[MENU_CHANNEL3][2] == BTN_ON)	//Inverted Signal	BF
			{ Trigger_Pos_CH3 = (GRID_HEIGHT / 2) + Virtual_ZeroLevelCH3 + (Virtual_ZeroLevelCH3 - ScaleLookupTable[lMeanValue][lScaleIndex]); }
			else
			{ Trigger_Pos_CH3 = (GRID_HEIGHT / 2) + ScaleLookupTable[lMeanValue][lScaleIndex]; }

			if (Trigger_Pos_CH3 > GRID_HEIGHT){ Trigger_Pos_CH3 = GRID_HEIGHT; }  
			if (Trigger_Pos_CH3 < 0){ Trigger_Pos_CH3 = 0; }

			break;
		}

		case 4:
		{
			//find maxima and minima
			for (int i = 100; i<lSignalEnd ;i++)
			{
				if (SIGNAL4[i] > lMaxValue) lMaxValue = SIGNAL4[i];
				if (SIGNAL4[i] < lMinValue) lMinValue = SIGNAL4[i];
			}

			//calculate 50%
			lMeanValue = (int)(lMaxValue + lMinValue) >> 1;

			lScaleIndex = ScaleIndexTable[Selected_Voltage_CH4];

			if (MenuStatus[MENU_CHANNEL4][2] == BTN_ON)	//Inverted Signal	BF
			{ Trigger_Pos_CH4 = (GRID_HEIGHT / 2) + Virtual_ZeroLevelCH4 + (Virtual_ZeroLevelCH4 - ScaleLookupTable[lMeanValue][lScaleIndex]); }
			else
			{ Trigger_Pos_CH4 = (GRID_HEIGHT / 2) + ScaleLookupTable[lMeanValue][lScaleIndex]; }

			if (Trigger_Pos_CH4 > GRID_HEIGHT){ Trigger_Pos_CH4 = GRID_HEIGHT; }  
			if (Trigger_Pos_CH4 < 0){ Trigger_Pos_CH4 = 0; }

			break;
		}

		case 5:	{ return; }	// external

		case 6:	{ return; }	// TV

	}

	Hardware::SetupTrigger();

	Display::DRAWSTATUS(6, 1);			// Draw Trigger Level
	VS_TrigLevelChanged = Selected_Trigger_Source;
	
	Hardware::ResetTimer3(TimerRotPeriod);
	TriggerLevelActive = 1;

//	Start_Record();


}
//##########################################################################################################################################################
//BF 
void Hardware::TRIG_AutoPretrigger(void)
{

	if (MenuStatus[MENU_TRIGGERSUB][4] == 272)
	{
		MemWinStart  = MemStartOffs;				// memory window to start of memory
		Trig_Pos_Mem = MemWinStart;				// trigger to the left edge
	}
	else if (MenuStatus[MENU_TRIGGERSUB][4] == 273)
	{
		MemWinStart  = MemStartOffs;				// memory window to start of memory
		Trig_Pos_Mem = MemWinStart + (int)(50 * ZoomFactor);	// trigger to the first div
	}
	else if (MenuStatus[MENU_TRIGGERSUB][4] == 274)
	{
		MemWinStart  = MemStartOffs;				// memory window to start of memory
		Trig_Pos_Mem = MemWinStart + (SignalMemSize/2);		// center trigger
	}
	else if (MenuStatus[MENU_TRIGGERSUB][4] == 275)
	{
		MemWinStart = (MemoryEnd>>1) - (SignalMemSize>>1);	// center memory window
		Trig_Pos_Mem = MemWinStart + (SignalMemSize>>1);	// center trigger
	}
	else if (MenuStatus[MENU_TRIGGERSUB][4] == 276)
	{	MemWinStart = Trig_Pos_Mem - (SignalMemSize>>1); }	// keep time value and center the memory window

	// right edge limiter
	if ((MemWinStart + SignalMemSize) > MemoryEnd) { MemWinStart = MemoryEnd - SignalMemSize; }

	// left edge limiter
        if (MemWinStart < MemStartOffs) { MemWinStart  = MemStartOffs; }

	// right edge limiter
        if (Trig_Pos_Mem > TrigPosMax) { Trig_Pos_Mem = TrigPosMax; }


	// left edge limiter
        if (Trig_Pos_Mem < MemStartOffs) { Trig_Pos_Mem = MemStartOffs; }


	Display::RecalcTriggerPos();
	Hardware::SetupADC();

	Display::CALCPRETRIGGER();

}



