#include "boardcfg.h"
#include "hw_config.h"
#include "lcd.h"
#include "stm32f10x_adc.h"
#include "stm32f10x_spi.h"
#include "stm32f10x_dma.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_nvic.h"
#include "stm32f10x_usart.h"
#include "stm32f10x_pwr.h"
//#define USB_LP_CAN_RX0_IRQChannel    ((u8)0x14)  /* USB Low Priority or CAN RX0 Interrupts */

//#define ADC1_DR_Address    ((u32)0x4001244C)
vu16 ADCConvertedValue;

static vu32 TimingDelay = 0;
u8 Last_SPI_Config=255;
u16 Delay;

void SPI_Config(u8 Mode, u8 Datasize, u8 Baudrate) {
	SPI_InitTypeDef  SPI_InitStructure;
	GPIO_InitTypeDef  GPIO_InitStructure;
	
	if (Mode==Mode_OFF) {
		SPI_SelectDevice(0);
		SPI_I2S_DeInit(SPI1);
		SPI_Cmd(SPI1, DISABLE);
		/* All SPI-Pins to input with weak internal pull-downs */
		GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_SD_SCK | GPIO_Pin_SD_MISO | GPIO_Pin_SD_MOSI;
		GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPD;
		GPIO_Init(GPIO_SD_Port, &GPIO_InitStructure);
		GPIO_SD_Port->BRR = GPIO_Pin_SD_SCK | GPIO_Pin_SD_MISO | GPIO_Pin_SD_MOSI;
		
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, DISABLE);
	}
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
	
	/* Configure SPI pins: SCK and MOSI with default alternate function (not remapped) push-pull */
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_SD_SCK | GPIO_Pin_SD_MOSI;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
	GPIO_Init(GPIO_SD_Port, &GPIO_InitStructure);

	/* Configure MISO as Input with internal pull-up */
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_SD_MISO;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;
	GPIO_Init(GPIO_SD_Port, &GPIO_InitStructure);
	GPIO_SD_Port->BSRR = GPIO_Pin_SD_MISO;
		
	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
	switch (Mode) {
		case 0: 
			SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
			SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
			break;
		case 1: 
			SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
			SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
			break;
		case 2: 
			SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
			SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
			break;
		case 3: 
			SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
			SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
			break;
	}
	switch (Datasize) {
		case 8: SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; break;
		case 16: SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; break;
	}
	switch (Baudrate) {//72000kHz/256=281.25 kHz
		case 2: SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; break; //36 MHz
		case 4: SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; break; //18 MHz
		case 8: SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; break; //9 MHz
		case 16: SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; break; //4.5 MHz
		case 32: SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; break; //2.25 MHz
		case 64: SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; break; //1.125 MHz
		case 128: SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128; break; //562.5 KHz
		case 255: SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; break; //281.25 KHz
	}
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
	SPI_InitStructure.SPI_CRCPolynomial = 7;

	SPI_Init(SPI1, &SPI_InitStructure);
	SPI_CalculateCRC(SPI1, DISABLE);
	SPI_Cmd(SPI1, ENABLE);
	
	SPI_SSOutputCmd(SPI1, DISABLE);

	SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Set);
	
}
//1=SD 2=TP 3=FLASH
void SPI_SelectDevice(u8 Device) {
	if (Last_SPI_Config==Device) { return; }
	Last_SPI_Config=Device;
	
	TP_OFF; SD_OFF; F_OFF;
	switch(Device) {
		case 1: SPI_Config(Mode_0,Databit8,BaudScale_32); SD_ON;  break; //
		case 2: SPI_Config(Mode_0,Databit16,BaudScale_64); TP_ON;  break; //
		case 3: SPI_Config(Mode_0,Databit8,BaudScale_32); F_ON;  break;	//
		case 255: SPI_Config(Mode_OFF,0,0); break;
	}
}
u16 TP_SPI_RW(u16 c) {
	u16 MSB, LSB, data, Timeout;
	
	SPI_I2S_SendData(SPI1, c); Timeout=5000;
	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) { Timeout--; if	(Timeout==0) { return 0; } }
	MSB=SPI_I2S_ReceiveData(SPI1);
	
	SPI_I2S_SendData(SPI1, 0); Timeout=5000;
	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) { Timeout--; if	(Timeout==0) { return 0; } }
	LSB=SPI_I2S_ReceiveData(SPI1);
    data=(((MSB<<4)&0x0FF0)|((LSB>>12)&0x000F))<<1;
	//TP_Deselect();
	return data;
}
void TP_GetAdXY(vs16 *x,vs16 *y) {
	u32 X,Y;
	X=TP_SPI_RW(0x9400); X+=TP_SPI_RW(0x9400); X+=TP_SPI_RW(0x9400); X+=TP_SPI_RW(0x9400);
	Y=TP_SPI_RW(0xD400); Y+=TP_SPI_RW(0xD400); Y+=TP_SPI_RW(0xD400); Y+=TP_SPI_RW(0xD400);
	Y=Y/4; X=X/4;
	#ifdef Switch_TP_Axis
	*y=((4094-X-260)/14.895);
	*x=((Y-240)/11.312);
//	*y=((4094-TP_SPI_RW(0x9400)-260)/14.895);
//	*x=((TP_SPI_RW(0xD400)-240)/11.312);
	#else
	*x=((4094-X-530)/10.5);
	*y=((Y-370)/14.16);
//	*x=((4094-TP_SPI_RW(0x9400)-530)/10.5);
//	*y=((TP_SPI_RW(0xD400)-370)/14.16);
	#endif
}

void ADC_Configuration(void) {
	ADC_InitTypeDef ADC_InitStructure;
	DMA_InitTypeDef DMA_InitStructure;
	/* DMA1 channel1 configuration ----------------------------------------------*/
	DMA_DeInit(DMA1_Channel1);
	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)0x4001244C; //ADC1_DR_Address
	DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADCConvertedValue;
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
	DMA_InitStructure.DMA_BufferSize = 1;
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	DMA_Init(DMA1_Channel1, &DMA_InitStructure);
	DMA_Cmd(DMA1_Channel1, ENABLE);
	/* ADC1 Configuration ------------------------------------------------------*/
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	ADC_InitStructure.ADC_NbrOfChannel = 1;
	ADC_Init(ADC1, &ADC_InitStructure);
	
	//B0->Ain8
	ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_55Cycles5);//ADC_SampleTime_55Cycles5
	ADC_DMACmd(ADC1, ENABLE);
	ADC_Cmd(ADC1, ENABLE);
	
	ADC_ResetCalibration(ADC1);
	while(ADC_GetResetCalibrationStatus(ADC1));
	ADC_StartCalibration(ADC1);
	while(ADC_GetCalibrationStatus(ADC1));
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
u16 readADC1(u8 channel) {
	u16 Timeout=5000;
	ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_1Cycles5);//
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
	while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET) {Timeout--; if	(Timeout==0) { return 0; }};
	return ADC_GetConversionValue(ADC1);
}
void USB_Config(u8 State) {
	NVIC_InitTypeDef NVIC_InitStructure;
	if (State==DISABLE) {
		BOARD_USB_ENABLE_PORT->BSRR =  BOARD_USB_ENABLE_PIN; //OFF
	} else { //ENABLE
		USB_Init();
		/* Set the Vector Table base address at 0x08000000 */
		NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN_RX0_IRQChannel;
		NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
		NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
		NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
		NVIC_Init(&NVIC_InitStructure);
		//einschalten
		BOARD_USB_ENABLE_PORT->BRR =  BOARD_USB_ENABLE_PIN; //ON
		Last_SPI_Config=255;
		USB_Connect(TRUE);
	}
}
void StopMode(void) {
	ErrorStatus HSEStartUpStatus;
	//Ausschalten
	LED2_Off(); LED3_Off();
	LCD_Enable(0);
	USB_Config(DISABLE);
//	PWR_EnterSTANDBYMode(); //turn off
	PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFI);
	
	//Code wird nach External GPIO Interrupt ausgeführt
	//EXTI0 auf Pin A0 (button Key 1) ist als einziger aktiv
//	RCC_HSEConfig(RCC_HSE_ON);
//	HSEStartUpStatus = RCC_WaitForHSEStartUp();
//	if(HSEStartUpStatus == SET)	{
//		RCC_PLLCmd(ENABLE);
//		while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) { }
//		RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
//		while(RCC_GetSYSCLKSource() != 0x08) { }
//	}
	stm32_Init(); //STM32_Init.c
	System_Init(); //hw_config.c
}
void System_Init(void) {
	RCC_AHBPeriphClockCmd(BOARD_AHB_RCCs, ENABLE);
	RCC_APB1PeriphClockCmd(BOARD_APB1_RCCs, ENABLE);
	RCC_APB2PeriphClockCmd(BOARD_APB2_RCCs, ENABLE);
	
	PWR_WakeUpPinCmd(ENABLE);
	ADC_Configuration();
	USB_Config(ENABLE);
//	SPI_Config(Mode_0,Databit8,BaudScale_32);
	I2C_GPIO_Config();
	LCD_Initializtion();
}

//Usart und LCD Ausgabefunktionen #########################################################################
//#########################################################################################################
int fputc(int ch) {
	u16 Timeout=5000;
	//ohne diese funktion arbeitet printf nicht!
	USART_SendData(USART1, (u8) ch);
	while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {Timeout--; if	(Timeout==0) { return 0; }}
	return ch;
}
void UART_Print(char *p) {
	while (*p) {
		USART_SendData(USART1, *p++);
		while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {;}
	}
}
void UART_Print_DEC(char *info,int i) {
	char buf[15],*p;
	itoa(i, buf, 10);
	p=buf;
	while (*info) {
		USART_SendData(USART1, *info++);
		while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {;}
	}
	while (*p) {
		USART_SendData(USART1, *p++);
		while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {;}
	}
}
void UART_Print_FRESULT(char *info,int FRES) {
	const char *p;
	static char str[] =
		"OK\0" "NOT_READY\0" "NO_FILE\0" "FR_NO_PATH\0" "INVALID_NAME\0" "INVALID_DRIVE\0"
		"DENIED\0" "EXIST\0" "RW_ERROR\0" "WRITE_PROTECTED\0" "NOT_ENABLED\0"
		"NO_FILESYSTEM\0" "INVALID_OBJECT\0" "MKFS_ABORTED\0";
	u8 i=0;	
	for (p = str, i = 0; i != FRES && *p; i++) {
		while(*p++);
	}
	while (*info) {
		USART_SendData(USART1, *info++);
		while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {;}
	}
	while (*p) {
		USART_SendData(USART1, *p++);
		while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {;}
	}
}
void ff_LCD_FRESULT(u16 x, u16 y, char *info,int FRES) {
	char *p,*inf=info;
	static char str[] =
		"OK\0" "NOT_READY\0" "NO_FILE\0" "FR_NO_PATH\0" "INVALID_NAME\0" "INVALID_DRIVE\0"
		"DENIED\0" "EXIST\0" "RW_ERROR\0" "WRITE_PROTECTED\0" "NOT_ENABLED\0"
		"NO_FILESYSTEM\0" "INVALID_OBJECT\0" "MKFS_ABORTED\0";
	u8 i=0;	u8 len=0;
	for (p = str, i = 0; i != FRES && *p; i++) {
		while(*p++);
	}
	while (*inf++) { len++; }
	LCD_DrawText(x,y,info,LCD_White,LCD_Black,font_5x8);
	if (FRES==0) {
		LCD_DrawText(x+(len*5),y,p,LCD_Green,LCD_Black,font_5x8);
	} else {
		LCD_DrawText(x+(len*5),y,p,LCD_Red,LCD_Black,font_5x8);
	}
	//Usart ausgabe paralell dazu
	if (LCD_GetButtonstate(5)==BtnIsOn) { //switch Uart
		while (*info) {
			USART_SendData(USART1, *info++);
			while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {;}
		}
		while (*p) {
			USART_SendData(USART1, *p++);
			while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {;}
		}
	}
}
void ff_LCD_Text(u16 x, u16 y, char *info, char *text, u16 charColor) {
	char len=0,*inf=info;
	while (*inf++) { len++; }
	LCD_DrawText(x,y,info,LCD_White,LCD_Black,font_5x8);
	LCD_DrawText(x+(len*5),y,text,charColor,LCD_Black,font_5x8);
	//Usart ausgabe paralell dazu
	if (LCD_GetButtonstate(5)==BtnIsOn) { //switch Uart
		while (*info) {
			USART_SendData(USART1, *info++);
			while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {;}
		}
		while (*text) {
			USART_SendData(USART1, *text++);
			while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {;}
		}
	}
}
void Decrement_TimingDelay(void) { if (TimingDelay != 0x00) { TimingDelay--; } }
char *itoa(int n, char *s, int b) { //n=nummer,*s=buffer,b=basis (dec=10,hex=16)
	static char digits[] = "0123456789ABCDEFghijklmnopqrstuvwxyz";
	int i=0, sign;
	if ((sign = n) < 0)
		n = -n;
	do {
		s[i++] = digits[n % b];
	} while ((n /= b) > 0);
	if (sign < 0)
		s[i++] = '-';
	s[i] = '\0';
	return strrev(s);
}
char *strrev(char *str) {
	char *p1, *p2;
	if (!str || !*str) return str;
	for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2) {
		*p1 ^= *p2;
		*p2 ^= *p1;
		*p1 ^= *p2;
	}
	return str;
}
//I2C Funktionen ##########################################################################################
//#########################################################################################################
u8 I2C_Send(u8 adresse, u8 reg, u8 data) {
	I2C_SendStart();
	if(0==I2C_WriteByte(adresse<<1)) { I2C_SendStop(); return(0); }
  	if(0==I2C_WriteByte(reg)) { I2C_SendStop(); return(0); }
  	if(0==I2C_WriteByte(data)) { I2C_SendStop(); return(0); }
  	I2C_SendStop();
  	return(1);
}
u8 I2C_Read(u8 adresse, u8 reg, u8 *data) {
	I2C_SendStart();
	if(0==I2C_WriteByte(adresse<<1)) { I2C_SendStop(); return(0); }
	if(0==I2C_WriteByte(reg)) { I2C_SendStop(); return(0); }
	I2C_SendStart();
	if(0==I2C_WriteByte(adresse<<1|1)) { I2C_SendStop(); return(0); } //adresse + read Bit
  	*data=I2C_ReadByte();
	I2C_SendnoAck();
  	I2C_SendStop();
  	return(1);
}
//I2C Kernel
void I2C_SendStart() {
	I2C_DATA_H(); I2C_Delay_Long();
	I2C_SCL_H(); I2C_Delay_Long();
	I2C_DATA_L(); I2C_Delay_Long();
	I2C_SCL_L();
}
void I2C_SendStop() {
	I2C_SetDataPort_OUT();
	I2C_SCL_L(); I2C_Delay_Long();
    I2C_DATA_L(); I2C_Delay_Long();
	I2C_SCL_H(); I2C_Delay_Long();
	I2C_DATA_H();
}
void I2C_SendnoAck() {
	I2C_DATA_H(); I2C_Delay_Short();
	I2C_SCL_H(); I2C_Delay_Short();
	I2C_SCL_L(); I2C_Delay_Long();
	I2C_DATA_L();
}
u8 I2C_WriteByte(u8 m_data) {
	u8 j,tem;
	
	for(j=0;j<8;j++) {
		if((m_data<<j)&0x80) {
			I2C_DATA_H();	
		} else {
			I2C_DATA_L();	
		}
		I2C_Delay_Short();
		I2C_SCL_H();	
		I2C_Delay_Long();
		I2C_SCL_L();
	}
	I2C_SetDataPort_IN();
	I2C_SCL_H();
	I2C_Delay_Long();
	if(I2C_DATA_STATE) {tem=0;} else {tem=1;}
	I2C_SCL_L();
	while(!I2C_SCL_STATE) {;} //Clockstretching: w8 4 Slave
    I2C_SetDataPort_OUT();
	
	return (tem);  
}
u8 I2C_ReadByte(void) {
	u8 read=0,j; Delay=0;
	I2C_SetDataPort_IN();
	I2C_Delay_Long();
	for(j=8;j>0;j--) {
		I2C_SCL_H();
		I2C_Delay_Long();
		read=read<<1;
		if(I2C_DATA_STATE) { read++; }
		I2C_SCL_L();
		I2C_Delay_Long();
	}
	I2C_SetDataPort_OUT();
	return(read);
}

void I2C_SetDataPort_OUT(void) {
#ifdef IC2_DATA_MACRO_OUT
	IC2_DATA_MACRO_OUT; LED2_On();//
#else
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin =  I2C_PIN_DATA;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(I2C_PORT_DATA, &GPIO_InitStructure);
#endif
}
void I2C_SetDataPort_IN(void) {
#ifdef IC2_DATA_MACRO_IN
	IC2_DATA_MACRO_IN; LED2_Off();//
#else
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin =  I2C_PIN_DATA;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(I2C_PORT_DATA, &GPIO_InitStructure);
#endif
}
void I2C_GPIO_Config(void) {
	GPIO_InitTypeDef GPIO_InitStructure;
	I2C_SCL_H();
	I2C_DATA_H();
	GPIO_InitStructure.GPIO_Pin =  I2C_PIN_DATA;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
	GPIO_Init(I2C_PORT_DATA, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin =  I2C_PIN_SCL;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
	GPIO_Init(I2C_PORT_SCL, &GPIO_InitStructure);
	
}
/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
