#include "userdef.h"
#include "hardware.h"
#include "lcd.h"
#include "memmanage.h"
#include "stdio.h"
#include "global.h"
#include "intrinsics.h"
#include "pccomm.h"
#include "memory.h"

#define ADC1_DR_Address    0x4001244C
#define SPI2_DR_Address    0x4000380C

#define CCR_ENABLE         ((u32)0x00000001)

extern vu16 g_arADCBuffer[10];

u8 g_PowerSource = POWER_BATTERY;

/*******************************************************************************
* Function Name  : void InitHardware(void)
* Description    : Inits the internal MCU hardware
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void InitHardware(void) {

	SPI_InitTypeDef *SPI_InitStructure;
	TIM_TimeBaseInitTypeDef  *TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  *TIM_OCInitStructure;
	NVIC_InitTypeDef *NVIC_InitStructure;
	DMA_InitTypeDef *DMA_InitStructure;
	ADC_InitTypeDef *ADC_InitStructure;
	
//Set flash latency to 1 wait states for 48Mhz system clock
	FLASH_SetLatency(FLASH_Latency_1);
//Enable HSE oscilator and PLL
	RCC_HSEConfig(RCC_HSE_ON);
	RCC_WaitForHSEStartUp();
	RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_6);
	RCC_PLLCmd(ENABLE);
	while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) != SET);
//Configure clocks
	RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);			//SYS = 48MHZ
	RCC_HCLKConfig(RCC_SYSCLK_Div1);					//AHB = 48MHZ
	RCC_PCLK1Config(RCC_HCLK_Div2);						//APB1 = 24MHZ
	RCC_PCLK2Config(RCC_HCLK_Div4);						//APB2 = 12MHZ
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2 | RCC_APB1Periph_TIM2 |
						   RCC_APB1Periph_TIM3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_AFIO |
						   RCC_APB2Periph_ADC1, ENABLE);
	
//Init Pins
	InitPins();

	//Init SPI
	SPI_InitStructure = my_malloc( sizeof(SPI_InitTypeDef) );
	
	SPI_InitStructure->SPI_Mode = SPI_Mode_Master;
	SPI_InitStructure->SPI_NSS = SPI_NSS_Soft; //SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;
	SPI_InitStructure->SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
	SPI_InitStructure->SPI_FirstBit = SPI_FirstBit_MSB;
  	SPI_InitStructure->SPI_CRCPolynomial = 7;
	//SPI2 - LCD
	SPI_InitStructure->SPI_CPOL = SPI_CPOL_High;
	SPI_InitStructure->SPI_CPHA = SPI_CPHA_2Edge;
	SPI_InitStructure->SPI_DataSize = SPI_DataSize_8b;
	SPI_InitStructure->SPI_Direction = SPI_Direction_1Line_Tx;
	SPI_Init(SPI2,SPI_InitStructure);
	SPI_I2S_DMACmd(SPI2,SPI_I2S_DMAReq_Tx,ENABLE);				//Enable DMA on SPI2 TX
	//SPI1- for DAC and DP
	SPI_InitStructure->SPI_CPOL = SPI_CPOL_Low;
	SPI_InitStructure->SPI_CPHA = SPI_CPHA_1Edge;
	SPI_InitStructure->SPI_Direction = SPI_Direction_2Lines_FullDuplex;
	SPI_InitStructure->SPI_DataSize = SPI_DataSize_16b;
	SPI_Init(SPI1,SPI_InitStructure);
 	SPI_NSSInternalSoftwareConfig(SPI1,SPI_NSSInternalSoft_Set); //SPI_SSOutputCmd(SPI1, ENABLE);
	SPI_NSSInternalSoftwareConfig(SPI2,SPI_NSSInternalSoft_Set); //SPI_SSOutputCmd(SPI2, ENABLE);

	free(SPI_InitStructure);
	
//Set DMA
	DMA_InitStructure = my_malloc( sizeof(DMA_InitTypeDef) );
	//Init DMA_CH5 for SPI LCD transfer
	DMA_InitStructure->DMA_PeripheralBaseAddr = SPI2_DR_Address;
	DMA_InitStructure->DMA_DIR = DMA_DIR_PeripheralDST;
	DMA_InitStructure->DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStructure->DMA_MemoryInc = DMA_MemoryInc_Enable;
	DMA_InitStructure->DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
	DMA_InitStructure->DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
	DMA_InitStructure->DMA_Mode = DMA_Mode_Normal;
	DMA_InitStructure->DMA_Priority = DMA_Priority_Medium;
	DMA_InitStructure->DMA_M2M = DMA_M2M_Disable;
	DMA_Init(DMA1_Channel5, DMA_InitStructure);

    //Init DMA_CH7 for M2M transfer
	DMA_InitStructure->DMA_DIR = DMA_DIR_PeripheralDST;
	DMA_InitStructure->DMA_PeripheralInc = DMA_PeripheralInc_Enable;
	DMA_InitStructure->DMA_MemoryInc = DMA_MemoryInc_Enable;
	DMA_InitStructure->DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
	DMA_InitStructure->DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
	DMA_InitStructure->DMA_Mode = DMA_Mode_Normal;
	DMA_InitStructure->DMA_Priority = DMA_Priority_Low;
	DMA_InitStructure->DMA_M2M = DMA_M2M_Enable;
	DMA_Init(DMA1_Channel7, DMA_InitStructure);
		
	free(DMA_InitStructure);

//Set ADC1
    ////one regular channel - battery voltage
	ADC_InitStructure = my_malloc( sizeof(ADC_InitStructure) );
	ADC_InitStructure->ADC_Mode = ADC_Mode_Independent;
  	ADC_InitStructure->ADC_ScanConvMode = ENABLE;
 	ADC_InitStructure->ADC_ContinuousConvMode = DISABLE;
  	ADC_InitStructure->ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure->ADC_NbrOfChannel = 1;
    ADC_InitStructure->ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO;
  	ADC_Init(ADC1, ADC_InitStructure);
    free(ADC_InitStructure);
	ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_71Cycles5);
	ADC_ExternalTrigConvCmd(ADC1, ENABLE);
		
    //two injected channels - Led level & PL signal
	ADC_InjectedSequencerLengthConfig(ADC1, 2);
	ADC_InjectedChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_71Cycles5);
  	ADC_InjectedChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_71Cycles5);
	ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_T2_CC1);
	ADC_ExternalTrigInjectedConvCmd(ADC1, ENABLE);
	
//Init Timers
	TIM_TimeBaseStructure = my_malloc( sizeof(TIM_TimeBaseInitTypeDef) );
	TIM_OCInitStructure = my_malloc( sizeof(TIM_OCInitTypeDef) );
	
	//Init Timer 2
	TIM_TimeBaseStructure->TIM_Period = 47999;						//Timer 2 freq = 500HZ
	TIM_TimeBaseStructure->TIM_Prescaler = 1;
	TIM_TimeBaseStructure->TIM_ClockDivision = 0;
 	TIM_TimeBaseStructure->TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM2, TIM_TimeBaseStructure);
	
	//Init PWM on output TMR2_CH3 (PB10)
	TIM_OCInitStructure->TIM_OCMode = TIM_OCMode_PWM2;
	TIM_OCInitStructure->TIM_OutputState = TIM_OutputState_Enable;
  	TIM_OCInitStructure->TIM_Pulse = 45600;							//Duty cycle = 1/20
  	TIM_OCInitStructure->TIM_OCPolarity = TIM_OCPolarity_Low;
  	TIM_OC3Init(TIM2, TIM_OCInitStructure);
  	TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);
	//Init PWM on output TMR2_CH4 (PB11)
	TIM_OCInitStructure->TIM_OCMode = TIM_OCMode_PWM2;
	TIM_OCInitStructure->TIM_OutputState = TIM_OutputState_Enable;
  	TIM_OCInitStructure->TIM_Pulse = 47520;							//Short pulse at the end = 20us
  	TIM_OCInitStructure->TIM_OCPolarity = TIM_OCPolarity_High;
  	TIM_OC4Init(TIM2, TIM_OCInitStructure);
  	TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable);
	
	//Init PWM on output TMR2_CH1 (used for ADC start)
	TIM_OCInitStructure->TIM_OCMode =  TIM_OCMode_PWM2;
	TIM_OCInitStructure->TIM_OutputState = TIM_OutputState_Enable;
  	TIM_OCInitStructure->TIM_Pulse = 47760;							//event on 80us after start
  	TIM_OCInitStructure->TIM_OCPolarity = TIM_OCPolarity_Low;
  	TIM_OC1Init(TIM2, TIM_OCInitStructure);
	TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);

	TIM_ARRPreloadConfig(TIM2, ENABLE);
	
    //Init Timer 3 - used for battery reading
    TIM_TimeBaseStructure->TIM_Period = 10000;						//Timer 2 freq = 10Hz
	TIM_TimeBaseStructure->TIM_Prescaler = 479;
	TIM_TimeBaseStructure->TIM_ClockDivision = 0;
 	TIM_TimeBaseStructure->TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM3, TIM_TimeBaseStructure);
    TIM_ARRPreloadConfig(TIM3, ENABLE);
#ifdef DEBUG_TEST_PIN_TOGGLE_ON_TMR3_UPDATE
	TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
#endif
	TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);	
	TIM_Cmd(TIM3, ENABLE);

	
	free(TIM_TimeBaseStructure); free(TIM_OCInitStructure);
	
//Set NVIC
	
#ifdef BOOTLOADER_REALOCATE
	/* Set the Vector Table base location at 0x3000 because of the DFU*/
  	NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x3000);
#else	
	NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0000);
#endif

	NVIC_InitStructure = my_malloc( sizeof(NVIC_InitTypeDef) );
	
	//Set ADC1 interrupt
	NVIC_InitStructure->NVIC_IRQChannel = ADC1_2_IRQChannel;
  	NVIC_InitStructure->NVIC_IRQChannelPreemptionPriority = 0;
  	NVIC_InitStructure->NVIC_IRQChannelSubPriority = 1;
  	NVIC_InitStructure->NVIC_IRQChannelCmd = ENABLE;
  	NVIC_Init(NVIC_InitStructure);
	
	//Set DMA1_CH5 interrupt
	NVIC_InitStructure->NVIC_IRQChannel = DMA1_Channel5_IRQChannel;
  	NVIC_InitStructure->NVIC_IRQChannelPreemptionPriority = 0;
  	NVIC_InitStructure->NVIC_IRQChannelSubPriority = 2;
  	NVIC_InitStructure->NVIC_IRQChannelCmd = ENABLE;
  	NVIC_Init(NVIC_InitStructure);

#ifdef DEBUG_TEST_PIN_TOGGLE_ON_TMR3_UPDATE
	//Set TMR3 interrupt
	NVIC_InitStructure->NVIC_IRQChannel = TIM3_IRQChannel;
  	NVIC_InitStructure->NVIC_IRQChannelPreemptionPriority = 0;
  	NVIC_InitStructure->NVIC_IRQChannelSubPriority = 3;
  	NVIC_InitStructure->NVIC_IRQChannelCmd = ENABLE;
  	NVIC_Init(NVIC_InitStructure);
#endif

	free(NVIC_InitStructure);	
	
//Set Systick timer to produce interrupt on 1ms	
	SysTick_SetReload(6000);						
	SysTick_ITConfig(ENABLE);
	SysTick_CounterCmd(SysTick_Counter_Enable);

	//Enable all used periferials	
	ADC_Cmd(ADC1, ENABLE);
	//Calibrate ADC1
	ADC_ResetCalibration(ADC1);
	while(ADC_GetResetCalibrationStatus(ADC1));
	ADC_StartCalibration(ADC1);
	while(ADC_GetCalibrationStatus(ADC1));
	SPI_Cmd(SPI2,ENABLE);
	SPI_Cmd(SPI1,ENABLE);

//Configure communication with PC
 	PCComm_ConfigureHardware();

//Set analog part of the schematics	
	WriteDP(TRUE, 10);
	WriteDP(FALSE,255);
}	

/*******************************************************************************
* Function Name  : void InitPins(void)
* Description    : Sets I/O in proper state
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void InitPins(void) {

  	GPIO_InitTypeDef GPIO_InitStructure;

  	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
                         RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD |
						 RCC_APB2Periph_GPIOE, ENABLE);
	
//All pins - analog inputs, except of JTAG
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
//PortA
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 |
  						GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 |
						GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
						GPIO_Pin_11 | GPIO_Pin_12;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
//PortB
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 |
  						GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 |
						GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 |
						GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
//PortC
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
	GPIO_Init(GPIOC, &GPIO_InitStructure);
	
//Configure correct direction and function for used I/Os
//Set outputs speed - slow
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;		
//PortA
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;			//GP Outputs
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_8;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;				//Alternative func
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;				//GP Inputs - input pull up
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

//PortB
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;			//GP Outputs
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_7
								| GPIO_Pin_12 | GPIO_Pin_14;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;				//GP Inputs - input pull up
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;				//Alternative func
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_15;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
//PortC
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;				//GP Inputs - input pull up
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
	GPIO_Init(GPIOC, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;			//Open drain outputs
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
	GPIO_Init(GPIOC, &GPIO_InitStructure);
	
//Remap timer 2	partial_2	
	GPIO_PinRemapConfig(GPIO_PartialRemap2_TIM2, ENABLE);

//Disable unused ports clock
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE, DISABLE);
	
//Set default level on GPIOs
	
	Clr_FASTCALM(); Clr_TP3(); Clr_LCDA0();					//Port A
	Set_nCSDP(); Clr_CSEE(); Set_POWERON(); Set_nLEDEN();	//Port B
	Clr_SHEN(); Set_nLCDCS(); Set_nLCDRST();				
	Set_nUSBDISCONN();										//Port C
}

/*******************************************************************************
* Function Name  : void EnableDataCollect(void)
* Description    : Enables timing functions for Data collect
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void EnableDataCollect(void) {
	
	g_PL_BufferWriteIndex = g_PL_BufferReadIndex = 0;
	
	TIM_Cmd(TIM2, ENABLE);
	ADC_ClearITPendingBit(ADC1, ADC_IT_JEOC);
	ADC_ITConfig(ADC1, ADC_IT_JEOC, ENABLE);
}

/*******************************************************************************
* Function Name  : void DisableDataCollect(void)
* Description    : Enables timing functions for Data collect
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void DisableDataCollect(void) {
	
	TIM_Cmd(TIM2, DISABLE);		
	ADC_ITConfig(ADC1, ADC_IT_JEOC, DISABLE);
}

/*******************************************************************************
* Function Name  : void WriteDP(bool bDPNumb, u8 Value )
* Description    : Writes Digital potentiometer
* Input          : Potentiometer number (0,1), 8 bit value
* Output         : None
* Return         : None
*******************************************************************************/
void WriteDP(bool bDPNumb, u8 Value ) {

	Clr_nCSDP();
	if(!bDPNumb)
		SPI1->DR = Value;
	else
		SPI1->DR = 0x1000 + Value;
	while( !(SPI1->SR & SPI_I2S_FLAG_TXE) );
	while(SPI1->SR & SPI_I2S_FLAG_BSY);
	Set_nCSDP();
}

/*******************************************************************************
* Function Name  : u8 GetKey(bool bWaitForButton)
* Description    : Reads the buttons
* Input          : TRUE - blocks till button is pressed
* Output         : Buttons state
* Return         : None
*******************************************************************************/
u8 GetKey(bool bWaitForButton) {

	u8 ReadKey;
	if(bWaitForButton)
		while(g_ButtonRegister == NO_BUTTONS_PRESSED);
	if(g_ButtonRegister != NO_BUTTONS_PRESSED) {
		__disable_interrupt();
		ReadKey = g_ButtonRegister;
		g_ButtonRegister = NO_BUTTONS_PRESSED;
		__enable_interrupt();
	}
	return ReadKey;
}

/*******************************************************************************
* Function Name  : void WaitToReleaseButtons(void)
* Description    : wait to release all button
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void WaitToReleaseButtons(void) {

	while( (GPIOB->IDR & (GPIO_Pin_5 | GPIO_Pin_6)) != (GPIO_Pin_5 | GPIO_Pin_6));
	g_ButtonRegister = NO_BUTTONS_PRESSED;
}

/*******************************************************************************
* Function Name  : void SwitchOff(void)
* Description    : Switch off device
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SwitchOff(void) {

	Memory_StoreSystemSettings();
	LCD_PowerOff();
	Clr_POWERON();
	while(1);
}

/***********************************************************************************************
* Function Name  : void DMAMemoryTransfer(u8 *Source, u8 *Destination, u8 Size)
* Description    : Transfer an amount of memory bytes via DMA
* Input          : Source & Destination pointers, Size of data, Wait to finish flag
* Output         : None.
* Return         : None.
* Note           : This function block until transfer completes. Use it for short data arrays
***********************************************************************************************/
void DMAMemoryTransfer(u8 *Source, u8 *Destination, u8 Size){

    DMA1_Channel7->CMAR = (u32)Source;
    DMA1_Channel7->CPAR = (u32)Destination;
    DMA1_Channel7->CNDTR = Size;
    DMA1_Channel7->CCR |= CCR_ENABLE;
    while(DMA1_Channel7->CNDTR != 0);
    DMA1_Channel7->CCR &= ~CCR_ENABLE;
}

/***********************************************************************************************
* Functions Names:  void EnableBatteryCheck(void)
*					void DisableBatteryCheck(void)
* Description    :  Enable/Disable Battery voltage verification
* Input          :  None.
* Output         :  None.
* Return         :  None.
***********************************************************************************************/
void EnableBatteryCheck(void) {

    ADC_AnalogWatchdogCmd(ADC1, ADC_AnalogWatchdog_SingleRegEnable);
    ADC_AnalogWatchdogThresholdsConfig(ADC1, 0x0FFF, BATTERY_LEVEL_LOW);
    ADC_AnalogWatchdogSingleChannelConfig(ADC1, ADC_Channel_2);
	ADC_ITConfig(ADC1, ADC_IT_AWD, ENABLE);
	g_PowerSource = POWER_BATTERY;
	g_bBatteryLow = FALSE;
}
void DisableBatteryCheck(void) {
	
	ADC_AnalogWatchdogCmd(ADC1, ADC_AnalogWatchdog_None);
	ADC_ITConfig(ADC1, ADC_IT_AWD, DISABLE);
	g_PowerSource = POWER_USB;
	g_bBatteryLow = FALSE;
}

/***********************************************************************************************
* Functions Names:  u8 GetPowerSource(void)
* Description    :  Returns the power source
* Input          :  None.
* Output         :  None.
* Return         :  Battery or USB power
***********************************************************************************************/
u8 GetPowerSource(void){
	return g_PowerSource;
}

/***********************************************************************************************
* Functions Names:  void CriticalError(u8 ErrorCode)
* Description    :  Critical error loop
* Input          :  Error code.
* Output         :  None.
* Return         :  None.
***********************************************************************************************/
void CriticalError(u8 ErrorCode){
	
	char strTemp[4];
	
	LCD_ClrScr();
	LCD_PrintStr(0,0,"Critical Error:", FALSE);
	sprintf(strTemp, "%d",ErrorCode);
	LCD_PrintStr(16*6,0,strTemp, FALSE);
	g_UserTimer = 0;
	while(g_UserTimer < 5000);
	SwitchOff();
}



