
#include "LIS302DL_SPI1.h"

static uint8_t x, y, z;

// Accelerometer initialization
static void LIS302DL_INITIALIZATION(void);
// write one byte to accelerometer via SPI1
static uint8_t WRITE_BYTE_TO_SPI1(uint8_t data);
// read x-axes from accelerometer
static void READ_X_AXES(void);
// read y-axes from accelerometer
static void READ_Y_AXES(void);
// read z-axes from accelerometer
static void READ_Z_AXES(void);

// Initialization SPI1 and LIS302DL accelerometer
void LIS302DL_SPI1_INIT(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	SPI_InitTypeDef SPI_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,  ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);

	GPIO_StructInit(&GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
	GPIO_InitStructure.GPIO_Pin   = spi1_cs;
	GPIO_Init(gpio_cs, &GPIO_InitStructure);
	GPIO_SetBits(gpio_cs, spi1_cs);

	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
	GPIO_InitStructure.GPIO_Pin   = spi1_mosi | spi1_miso | spi1_sck;
	GPIO_Init(gpio_spi1, &GPIO_InitStructure);
	
	GPIO_PinAFConfig(gpio_spi1, GPIO_PinSource7, GPIO_AF_SPI1);
	GPIO_PinAFConfig(gpio_spi1, GPIO_PinSource5, GPIO_AF_SPI1);
	GPIO_PinAFConfig(gpio_spi1, GPIO_PinSource6, GPIO_AF_SPI1);

	SPI_StructInit(&SPI_InitStructure);
	SPI_InitStructure.SPI_Direction         = SPI_Direction_2Lines_FullDuplex; 
	SPI_InitStructure.SPI_DataSize          = SPI_DataSize_8b; 
	SPI_InitStructure.SPI_CPOL              = SPI_CPOL_Low; 
	SPI_InitStructure.SPI_CPHA              = SPI_CPHA_1Edge; 
	SPI_InitStructure.SPI_NSS               = SPI_NSS_Soft | SPI_NSSInternalSoft_Set;
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; 
	SPI_InitStructure.SPI_FirstBit          = SPI_FirstBit_MSB; 
	SPI_InitStructure.SPI_Mode              = SPI_Mode_Master;
	SPI_Init(SPI1, &SPI_InitStructure); 
	SPI_Cmd(SPI1, ENABLE); 

	SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Set);
	
	LIS302DL_INITIALIZATION();
}

// read data from accelerometer
void LIS302DL_READ_AXES_EVERY_SECOND(void)
{
	READ_X_AXES();
	READ_Y_AXES();
	READ_Z_AXES();
	
	#ifdef WRITE_TO_UART3
		USART3_SendData(x);
		USART3_SendData(y);
		USART3_SendData(z);
		_delay_ms(1000);
	#endif
}

// read x-axes from accelerometer
static void READ_X_AXES(void)
{
	GPIO_ResetBits(gpio_cs, spi1_cs);
	_delay_us(5);
	WRITE_BYTE_TO_SPI1(OutX | READ); 
	x = WRITE_BYTE_TO_SPI1(0x00); 
	GPIO_SetBits(gpio_cs, spi1_cs);
	_delay_us(5);
}

// read y-axes from accelerometer
static void READ_Y_AXES(void)
{
	GPIO_ResetBits(gpio_cs, spi1_cs);
	_delay_us(5);
	WRITE_BYTE_TO_SPI1(OutY | READ); 
	y = WRITE_BYTE_TO_SPI1(0x00); 
	GPIO_SetBits(gpio_cs, spi1_cs);
	_delay_us(5);
}

// read z-axes from accelerometer
static void READ_Z_AXES(void)
{
	GPIO_ResetBits(gpio_cs, spi1_cs);
	_delay_us(5);
	WRITE_BYTE_TO_SPI1(OutZ | READ); 
	z = WRITE_BYTE_TO_SPI1(0x00); 
	GPIO_SetBits(gpio_cs, spi1_cs);
	_delay_us(5);
}

// Accelerometer initialization
static void LIS302DL_INITIALIZATION(void)
{
	GPIO_ResetBits(gpio_cs, spi1_cs);
	_delay_us(5);
	WRITE_BYTE_TO_SPI1(Who_Am_I | READ);
	WRITE_BYTE_TO_SPI1(0x00);
	GPIO_SetBits(gpio_cs, spi1_cs);
	_delay_ms(10);
	GPIO_ResetBits(gpio_cs, spi1_cs);
	_delay_us(5);
	WRITE_BYTE_TO_SPI1(Ctrl_Reg1 | WRITE); 
	WRITE_BYTE_TO_SPI1(0x47); 
	WRITE_BYTE_TO_SPI1(Ctrl_Reg2 | WRITE);
	WRITE_BYTE_TO_SPI1(0x00);
	GPIO_SetBits(gpio_cs, spi1_cs);
	_delay_us(5);
}

// write one byte to accelerometer via SPI1
static uint8_t WRITE_BYTE_TO_SPI1(uint8_t data)
{
	while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET) ; // SPI1 is busy
    SPI_I2S_SendData(SPI1, data);
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET) ;
    return SPI_I2S_ReceiveData(SPI1);
}
