/*
*********************************************************************************************************
*                                       IAR Development Kits
*                                              on the
*
*                                    Nano130
*
* Filename      : spi_flash.c
* Version       : V1.00
* Programmer(s) : Qian Xianghong
*********************************************************************************************************
*/

#include  "includes.h"

// 片选
#define LIS2DH12_CS_LOW()	LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_12)
#define LIS2DH12_CS_HIGH()	LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_12)

// 加速度计ID
uint8_t Accelero_ID = 0;
// 运动状态（默认为1，万一加速度计有问题）
volatile uint8_t Motion_Status = 1;
// 运动检测：第一次需要定位
volatile uint8_t Motion_Detected = 1;

typedef unsigned char  uchar;
typedef unsigned short ushort;
typedef unsigned int   uint;

//****************************************
// 定义LIS2DH12内部地址
//****************************************
#define	CTRL_REG1		0x20
#define	CTRL_REG2		0x21
#define	CTRL_REG3		0x22
#define	CTRL_REG4		0x23
#define	CTRL_REG5		0x24
#define	CTRL_REG6		0x25
#define ACT_THS			0x3E
#define ACT_DUR			0x3F
#define	WHO_AM_I		0x0F	//地址寄存器(默认数值0x33，只读)

uchar Single_WriteSPI(uchar REG_Address,uchar REG_data)
{
	LIS2DH12_CS_LOW();

	// Write Address
	*(__IO uint8_t *)&SPI2->DR = (REG_Address & 0x3F);
	while(!(SPI2->SR & SPI_SR_RXNE));
	*(__IO uint8_t *)&SPI2->DR;

	// Write data
	*(__IO uint8_t *)&SPI2->DR = REG_data;
	while(!(SPI2->SR & SPI_SR_RXNE));
	*(__IO uint8_t *)&SPI2->DR;
	
	LIS2DH12_CS_HIGH();

	return 1;
}

uchar Single_ReadSPI(uchar REG_Address,	uchar *REG_data)
{
	LIS2DH12_CS_LOW();

	// Read Address
	*(__IO uint8_t *)&SPI2->DR = ((REG_Address & 0x3F) | 0x80);
	while(!(SPI2->SR & SPI_SR_RXNE));
	*(__IO uint8_t *)&SPI2->DR;

	// 提供Clock
	*(__IO uint8_t *)&SPI2->DR = 0;
	while(!(SPI2->SR & SPI_SR_RXNE));
	*REG_data = *(__IO uint8_t *)&SPI2->DR;

	LIS2DH12_CS_HIGH();

	return 1;
}

// 读取运动状态
void Accelero_ReadStatus(uint8_t int2_pin)
{
	// 当前运动状态
	Motion_Status = !int2_pin;	// Active low
	PRINTF("\r\nHard Motion status = %d\r\n", Motion_Status);
	// 检测到了运动（需要重新定位）
	if(Motion_Status)
		Motion_Detected = 1;
}

/**
  * @brief  EXTI line detection callback.
  * @param  GPIO_Pin: Specifies the port pin connected to corresponding EXTI line.
  * @retval None
  */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin == LL_EXTI_LINE_10)
	{
		if(Wakeup_Sleeping)
		{
			SysTick->CTRL |= (SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk);	
			delay_ms(10);
			
			Vcc_Enable();
			delay_ms(40);
			Wakeup_Sleeping = 0;
			
			printf("\nWakeup by Accelero ...\n");
		}

		// 读取运动状态
		Accelero_ReadStatus(LL_GPIO_IsInputPinSet(GPIOD, LL_GPIO_PIN_10));
	}
}

// 加速度中断处理，本函数被【key.c】模块中【GPDEF_IRQHandler】函数调用
void Accelero_Init()
{
  LL_EXTI_InitTypeDef EXTI_InitStruct = {0};
  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
  /**SPI2 GPIO Configuration  
  PB13   ------> SPI2_SCK
  PB14   ------> SPI2_MISO
  PB15   ------> SPI2_MOSI 
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_13|LL_GPIO_PIN_14|LL_GPIO_PIN_15;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
  LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /**/
  LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_12);

  /**/
  GPIO_InitStruct.Pin = LL_GPIO_PIN_12;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  LL_GPIO_Init(GPIOB, &GPIO_InitStruct);  

  LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOD);

  /**/
  LL_SYSCFG_SetEXTISource(LL_SYSCFG_EXTI_PORTD, LL_SYSCFG_EXTI_LINE10);

  /**/
  EXTI_InitStruct.Line_0_31 = LL_EXTI_LINE_10;
  EXTI_InitStruct.Line_32_63 = LL_EXTI_LINE_NONE;
  EXTI_InitStruct.LineCommand = ENABLE;
  EXTI_InitStruct.Mode = LL_EXTI_MODE_IT;
  EXTI_InitStruct.Trigger = LL_EXTI_TRIGGER_RISING_FALLING;
  LL_EXTI_Init(&EXTI_InitStruct);

  /**/
  LL_GPIO_SetPinPull(GPIOD, LL_GPIO_PIN_10, LL_GPIO_PULL_UP);

  /**/
  LL_GPIO_SetPinMode(GPIOD, LL_GPIO_PIN_10, LL_GPIO_MODE_INPUT);  
}

// 初始化LIS2DH12
void Accelero_Open()
{
  LL_SPI_InitTypeDef SPI_InitStruct = {0};
  LL_EXTI_InitTypeDef EXTI_InitStruct = {0};

  /* Peripheral clock enable */
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
  
  /* SPI2 parameter configuration*/
  SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
  SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
  SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
  SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
  SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;
  SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
  SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2;
  SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
  SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
  SPI_InitStruct.CRCPoly = 7;
  LL_SPI_Init(SPI2, &SPI_InitStruct);
  LL_SPI_SetStandard(SPI2, LL_SPI_PROTOCOL_MOTOROLA);
  LL_SPI_DisableNSSPulseMgt(SPI2);	
  
	LL_SPI_SetRxFIFOThreshold(SPI2, LL_SPI_RX_FIFO_TH_QUARTER);
	LL_SPI_Enable(SPI2);
	
	Single_WriteSPI(CTRL_REG1, 0x5F);		//控制寄存器，（100Hz， Low-power mode，Enable XYZ）
	Single_WriteSPI(CTRL_REG2, 0x00);		//控制寄存器，（High-pass filter disabled）
	Single_WriteSPI(CTRL_REG3, 0x00);		//控制寄存器
	Single_WriteSPI(CTRL_REG4, 0x00);		//控制寄存器，（4-wire SPI，Self-test disabled, HR=0, FS= ±2g）
	Single_WriteSPI(CTRL_REG5, 0x00);		//控制寄存器，（FIFO disabled）
	Single_WriteSPI(CTRL_REG6, 0x08);		//控制寄存器，（Enable activity interrupt on INT2 pin）

	// Activate/Inactivate: 门限寄存器，（x 4g/250 mg）
	if(dcBuff.configDisplay.op_SEND_GPS_DATA)				// 槽车最灵敏，只在行驶过程中判断
		Single_WriteSPI(ACT_THS, 4);
	else if(dcBuff.configDisplay.op_USE_CAPACITY_SENSOR)	// 杜瓦瓶最不灵敏（电池容量低）
		Single_WriteSPI(ACT_THS, 40);
	else													// 罐箱
		Single_WriteSPI(ACT_THS, 20);
	// Activate/Inactivate: 持续时间寄存器	
	Single_WriteSPI(ACT_DUR, 40);			

	// 读出ID：测试通信是否正常
	Accelero_CheckID();
	// 非罐箱或槽车版，禁止加速度中断
	if(!(dcBuff.configDisplay.op_BOX_VER || dcBuff.configDisplay.op_SEND_GPS_DATA))
	{
		EXTI_InitStruct.Line_0_31 = LL_EXTI_LINE_10;
		EXTI_InitStruct.Line_32_63 = LL_EXTI_LINE_NONE;
		EXTI_InitStruct.LineCommand = DISABLE;
		EXTI_InitStruct.Mode = LL_EXTI_MODE_IT;
		EXTI_InitStruct.Trigger = LL_EXTI_TRIGGER_RISING_FALLING;
		LL_EXTI_Init(&EXTI_InitStruct);
	}
	
	NVIC_SetPriority(EXTI15_10_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0));
	NVIC_EnableIRQ(EXTI15_10_IRQn);	
}

// 读出ID放在Accelero_ID(检查加速度计是否正常）
void Accelero_CheckID()
{
	// 读出ID：测试通信是否正常
	Single_ReadSPI(WHO_AM_I, &Accelero_ID);
	PRINTF("\r\nAccelero ID = 0x%02X\r\n", Accelero_ID);

	if(Accelero_ID == ACCELERO_ID)
	{
		Motion_Status = !LL_GPIO_IsInputPinSet(GPIOD, LL_GPIO_PIN_10);
		PRINTF("\r\nInit Motion status = %d\r\n", Motion_Status);
	}
}
