text: /**
    ******************************************************************************
    * @file    lis3dsh.c
    * @author  MCD Application Team
    * @version V1.0.2
    * @date    02-December-2014
    * @brief   This file provides a set of functions needed to manage the LIS3DSH
    *          MEMS Accelerometer.
    ******************************************************************************
    * @attention
    *
    * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
    *
    * Redistribution and use in source and binary forms, with or without modification,
    * are permitted provided that the following conditions are met:
    *   1. Redistributions of source code must retain the above copyright notice,
    *      this list of conditions and the following disclaimer.
    *   2. Redistributions in binary form must reproduce the above copyright notice,
    *      this list of conditions and the following disclaimer in the documentation
    *      and/or other materials provided with the distribution.
    *   3. Neither the name of STMicroelectronics nor the names of its contributors
    *      may be used to endorse or promote products derived from this software
    *      without specific prior written permission.
    *
    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
    * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    *
    ******************************************************************************
    */
  
  /* Includes ------------------------------------------------------------------*/
  #include "lis3dsh.h"
  
  /** @addtogroup BSP
    * @{
    */ 
  
  /** @addtogroup Components
    * @{
    */ 
  
  /** @addtogroup LIS3DSH
    * @brief  This file includes the motion sensor driver for LIS3DSH motion sensor 
    *         devices.
    * @{
    */
  
  /** @defgroup LIS3DSH_Private_TypesDefinitions
    * @{
    */
  
  /**
    * @}
    */
  
  /** @defgroup LIS3DSH_Private_Defines
    * @{
    */
  
  /**
    * @}
    */
  
  /** @defgroup LIS3DSH_Private_Macros
    * @{
    */
  
  /**
    * @}
    */ 
    
  /** @defgroup LIS3DSH_Private_Variables
    * @{
    */
  ACCELERO_DrvTypeDef Lis3dshDrv =
  {
    LIS3DSH_Init,
    LIS3DSH_ReadID,
    LIS3DSH_RebootCmd,
    LIS3DSH_Click_IntConfig,
    0,
    0,
    0,
    0,
    0,
    0,
    LIS3DSH_ReadACC,
  };
  
  /**
    * @}
    */
  
  /** @defgroup LIS3DSH_Private_FunctionPrototypes
    * @{
    */
    
  /**
    * @}
    */
  
  /** @defgroup LIS3DSH_Private_Functions
    * @{
    */
  
  /**
    * @brief  Set LIS3DSH Initialization.
    * @param  InitStruct: contains mask of different init parameters
    * @retval None
    */
  void LIS3DSH_Init(uint16_t InitStruct)
  {
    uint8_t ctrl = 0x00;
    
    /* Configure the low level interface */
    ACCELERO_IO_Init();
  
    /* Configure MEMS: power mode(ODR) and axes enable */
    ctrl = (uint8_t) (InitStruct);
    
    /* Write value to MEMS CTRL_REG4 register */
    ACCELERO_IO_Write(&ctrl, LIS3DSH_CTRL_REG4_ADDR, 1);
    
    /* Configure MEMS: full scale and self test */
    ctrl = (uint8_t) (InitStruct >> 8);
    
    /* Write value to MEMS CTRL_REG5 register */
    ACCELERO_IO_Write(&ctrl, LIS3DSH_CTRL_REG5_ADDR, 1);
  }
  
  /**
    * @brief  Read LIS3DSH device ID.
    * @param  None
    * @retval The Device ID (two bytes).
    */
  uint8_t LIS3DSH_ReadID(void)
  {
    uint8_t tmp = 0;
  
    /* Configure the low level interface */
    ACCELERO_IO_Init();
  
    /* Read WHO_AM_I register */
    ACCELERO_IO_Read(&tmp, LIS3DSH_WHO_AM_I_ADDR, 1);
    
    /* Return the ID */
    return (uint16_t)tmp;
  }
  
  /**
    * @brief  Set LIS3DSH Interrupt configuration
    * @param  LIS3DSH_InterruptConfig_TypeDef: pointer to a LIS3DSH_InterruptConfig_TypeDef 
    *         structure that contains the configuration setting for the LIS3DSH Interrupt.
    * @retval None
    */
  void LIS3DSH_InterruptConfig(LIS3DSH_InterruptConfigTypeDef *LIS3DSH_IntConfigStruct)
  {
    uint8_t ctrl = 0x00;
    
    /* Configure Interrupt Selection , Request and Signal */                   
    ctrl = (uint8_t)(LIS3DSH_IntConfigStruct->Interrupt_Selection_Enable | \
                     LIS3DSH_IntConfigStruct->Interrupt_Request | \
                     LIS3DSH_IntConfigStruct->Interrupt_Signal);
    
    /* Write value to MEMS CTRL_REG3 register */
    ACCELERO_IO_Write(&ctrl, LIS3DSH_CTRL_REG3_ADDR, 1);
    
    /* Configure State Machine 1 */                   
    ctrl = (uint8_t)(LIS3DSH_IntConfigStruct->State_Machine1_Enable | \
                     LIS3DSH_IntConfigStruct->State_Machine1_Interrupt);
    
    /* Write value to MEMS CTRL_REG1 register */
    ACCELERO_IO_Write(&ctrl, LIS3DSH_CTRL_REG1_ADDR, 1);
    
    /* Configure State Machine 2 */                   
    ctrl = (uint8_t)(LIS3DSH_IntConfigStruct->State_Machine2_Enable | \
                     LIS3DSH_IntConfigStruct->State_Machine2_Interrupt);
    
    /* Write value to MEMS CTRL_REG2 register */
    ACCELERO_IO_Write(&ctrl, LIS3DSH_CTRL_REG2_ADDR, 1);
  }
  
  /**
    * @brief  Set LIS3DSH for click detection
    * @param  None
    * @retval None
    */
  void LIS3DSH_Click_IntConfig(void)
  {
    uint8_t ctrl = 0x00;
    LIS3DSH_InterruptConfigTypeDef   LIS3DSH_InterruptStruct; 
  
    ACCELERO_IO_ITConfig();
  
    /* Set LIS3DSH Interrupt configuration */
    LIS3DSH_InterruptStruct.Interrupt_Selection_Enable = LIS3DSH_INTERRUPT_2_ENABLE;
    LIS3DSH_InterruptStruct.Interrupt_Request = LIS3DSH_INTERRUPT_REQUEST_LATCHED;
    LIS3DSH_InterruptStruct.Interrupt_Signal = LIS3DSH_INTERRUPT_SIGNAL_HIGH;
    LIS3DSH_InterruptStruct.State_Machine1_Enable = LIS3DSH_SM_DISABLE;
    LIS3DSH_InterruptStruct.State_Machine2_Enable = LIS3DSH_SM_ENABLE;
    LIS3DSH_InterruptStruct.State_Machine2_Interrupt = LIS3DSH_SM_INT1;
    LIS3DSH_InterruptConfig(&LIS3DSH_InterruptStruct);
      
    /* Set LIS3DSH State Machines configuration */
    ctrl=0x03; 
    ACCELERO_IO_Write(&ctrl, LIS3DSH_TIM2_1_L_ADDR,1);
    ctrl=0xC8; 
    ACCELERO_IO_Write(&ctrl, LIS3DSH_TIM1_1_L_ADDR,1);
    ctrl=0x45; 
    ACCELERO_IO_Write(&ctrl, LIS3DSH_THRS2_1_ADDR,1);
    ctrl=0xFC; 
    ACCELERO_IO_Write(&ctrl, LIS3DSH_MASK1_A_ADDR,1);
    ctrl=0xA1; 
    ACCELERO_IO_Write(&ctrl, LIS3DSH_SETT1_ADDR,1);
    ctrl=0x01; 
    ACCELERO_IO_Write(&ctrl, LIS3DSH_PR1_ADDR,1);
  
    ACCELERO_IO_Write(&ctrl, LIS3DSH_SETT2_ADDR,1);
    
    /* Configure State Machine 2 to detect single click */
    ACCELERO_IO_Write(&ctrl, LIS3DSH_ST2_1_ADDR,1);
    ctrl=0x06; 
    ACCELERO_IO_Write(&ctrl, LIS3DSH_ST2_2_ADDR,1);
    ctrl=0x28; 
    ACCELERO_IO_Write(&ctrl, LIS3DSH_ST2_3_ADDR,1);
    ctrl=0x11; 
    ACCELERO_IO_Write(&ctrl, LIS3DSH_ST2_4_ADDR,1);
  }
  
  /**
    * @brief  Change the lowpower mode for LIS3DSH.
    * @param  LowPowerMode: new state for the lowpower mode.
    *   This parameter can be one of the following values:
    *     @arg LIS3DSH_DATARATE_POWERDOWN: Power down mode
    *     @arg LIS3DSH_DATARATE_3_125: Normal mode. ODR: 3.125 Hz
    *     @arg LIS3DSH_DATARATE_6_25: Normal mode. ODR: 6.25 Hz
    *     @arg LIS3DSH_DATARATE_12_5: Normal mode. ODR: 12.5 Hz
    *     @arg LIS3DSH_DATARATE_25: Normal mode. ODR: 25 Hz
    *     @arg LIS3DSH_DATARATE_50: Normal mode. ODR: 50 Hz
    *     @arg LIS3DSH_DATARATE_100: Normal mode. ODR: 100 Hz
    *     @arg LIS3DSH_DATARATE_400: Normal mode. ODR: 400 Hz
    *     @arg LIS3DSH_DATARATE_800: Normal mode. ODR: 800 Hz
    *     @arg LIS3DSH_DATARATE_1600: Normal mode. ODR: 1600 Hz
    * @retval None
    */
  void LIS3DSH_ODR_LowpowerCmd(uint8_t ODR_LowPowerMode)
  {
    uint8_t tmpreg;
    
    /* Read CTRL_REG4 register */
    ACCELERO_IO_Read(&tmpreg, LIS3DSH_CTRL_REG4_ADDR, 1);
    
    /* Set new low power mode configuration */
    tmpreg &= (uint8_t)~LIS3DSH_DATARATE_100;
    tmpreg |= ODR_LowPowerMode;
    
    /* Write value to MEMS CTRL_REG4 register */
    ACCELERO_IO_Write(&tmpreg, LIS3DSH_CTRL_REG4_ADDR, 1);
  }
  
  /**
    * @brief  Data Rate command. 
    * @param  DataRateValue: Data rate value.
    *   This parameter can be one of the following values:
    *     @arg LIS3DSH_DATARATE_3_125: 3.125 Hz output data rate 
    *     @arg LIS3DSH_DATARATE_6_25: 6.25 Hz output data rate
    *     @arg LIS3DSH_DATARATE_12_5: 12.5  Hz output data rate
    *     @arg LIS3DSH_DATARATE_25: 25 Hz output data rate
    *     @arg LIS3DSH_DATARATE_50: 50 Hz output data rate 
    *     @arg LIS3DSH_DATARATE_100: 100 Hz output data rate
    *     @arg LIS3DSH_DATARATE_400: 400 Hz output data rate 
    *     @arg LIS3DSH_DATARATE_800: 800 Hz output data rate
    *     @arg LIS3DSH_DATARATE_1600: 1600 Hz output data rate
    * @retval None
    */
  void LIS3DSH_DataRateCmd(uint8_t DataRateValue)
  {
    uint8_t tmpreg;
    
    /* Read CTRL_REG4 register */
    ACCELERO_IO_Read(&tmpreg, LIS3DSH_CTRL_REG4_ADDR, 1);
    
    /* Set new data rate configuration from 100 to 400Hz */
    tmpreg &= (uint8_t)~LIS3DSH_DATARATE_400; 
    tmpreg |= DataRateValue;
    
    /* Write value to MEMS CTRL_REG4 register */
    ACCELERO_IO_Write(&tmpreg, LIS3DSH_CTRL_REG4_ADDR, 1);
  }
  
  /**
    * @brief  Change the Full Scale of LIS3DSH.
    * @param  FS_value: new full scale value. 
    *   This parameter can be one of the following values:
    *     @arg LIS3DSH_FULLSCALE_2: +-2g
    *     @arg LIS3DSH_FULLSCALE_4: +-4g
    *     @arg LIS3DSH_FULLSCALE_6: +-6g
    *     @arg LIS3DSH_FULLSCALE_8: +-8g
    *     @arg LIS3DSH_FULLSCALE_16: +-16g
    * @retval None
    */
  void LIS3DSH_FullScaleCmd(uint8_t FS_value)
  {
    uint8_t tmpreg;
    
    /* Read CTRL_REG5 register */
    ACCELERO_IO_Read(&tmpreg, LIS3DSH_CTRL_REG5_ADDR, 1);
    
    /* Set new full scale configuration */
    tmpreg &= (uint8_t)~LIS3DSH_FULLSCALE_16;
    tmpreg |= FS_value;
    
    /* Write value to MEMS CTRL_REG5 register */
    ACCELERO_IO_Write(&tmpreg, LIS3DSH_CTRL_REG5_ADDR, 1);
  }
  
  /**
    * @brief  Reboot memory content of LIS3DSH.
    * @param  None
    * @retval None
    */
  void LIS3DSH_RebootCmd(void)
  {
    uint8_t tmpreg;
    /* Read CTRL_REG6 register */
    ACCELERO_IO_Read(&tmpreg, LIS3DSH_CTRL_REG6_ADDR, 1);
    
    /* Enable or Disable the reboot memory */
    tmpreg |= LIS3DSH_BOOT_FORCED;
    
    /* Write value to MEMS CTRL_REG6 register */
    ACCELERO_IO_Write(&tmpreg, LIS3DSH_CTRL_REG6_ADDR, 1);
  }
  
  /**
    * @brief  Read LIS3DSH output register, and calculate the acceleration 
    *         ACC[mg]=SENSITIVITY* (out_h*256+out_l)/16 (12 bit representation).
    * @param  pointer on floating buffer.
    * @retval None
    */
  void LIS3DSH_ReadACC(int16_t *pData)
  {
    int8_t buffer[6];
    uint8_t crtl, i = 0x00;
    float sensitivity = LIS3DSH_SENSITIVITY_0_06G;
    float valueinfloat = 0;
    
    ACCELERO_IO_Read(&crtl, LIS3DSH_CTRL_REG5_ADDR, 1);  
    ACCELERO_IO_Read((uint8_t*)&buffer[0], LIS3DSH_OUT_X_L_ADDR, 1);
    ACCELERO_IO_Read((uint8_t*)&buffer[1], LIS3DSH_OUT_X_H_ADDR, 1);
    ACCELERO_IO_Read((uint8_t*)&buffer[2], LIS3DSH_OUT_Y_L_ADDR, 1);
    ACCELERO_IO_Read((uint8_t*)&buffer[3], LIS3DSH_OUT_Y_H_ADDR, 1);
    ACCELERO_IO_Read((uint8_t*)&buffer[4], LIS3DSH_OUT_Z_L_ADDR, 1);
    ACCELERO_IO_Read((uint8_t*)&buffer[5], LIS3DSH_OUT_Z_H_ADDR, 1);
    
    switch(crtl & LIS3DSH__FULLSCALE_SELECTION) 
    {
      /* FS bit = 000 ==> Sensitivity typical value = 0.06milligals/digit */ 
    case LIS3DSH_FULLSCALE_2:
      sensitivity = LIS3DSH_SENSITIVITY_0_06G;
      break;
      
      /* FS bit = 001 ==> Sensitivity typical value = 0.12milligals/digit */ 
    case LIS3DSH_FULLSCALE_4:
      sensitivity = LIS3DSH_SENSITIVITY_0_12G;
      break;
      
      /* FS bit = 010 ==> Sensitivity typical value = 0.18milligals/digit */ 
    case LIS3DSH_FULLSCALE_6:
      sensitivity = LIS3DSH_SENSITIVITY_0_18G;
      break;
      
      /* FS bit = 011 ==> Sensitivity typical value = 0.24milligals/digit */ 
    case LIS3DSH_FULLSCALE_8:
      sensitivity = LIS3DSH_SENSITIVITY_0_24G;
      break;
      
      /* FS bit = 100 ==> Sensitivity typical value = 0.73milligals/digit */ 
    case LIS3DSH_FULLSCALE_16:
      sensitivity = LIS3DSH_SENSITIVITY_0_73G;
      break;
      
    default:
      break;
    }
    
    /* Obtain the mg value for the three axis */
    for(i=0; i<3; i++)
    {
      valueinfloat = ((buffer[2*i+1] << 8) + buffer[2*i]) * sensitivity;
      pData[i] = (int16_t)valueinfloat;
    }
  }
  
  /**
    * @}
    */ 
  
  /**
    * @}
    */ 
    
  /**
    * @}
    */ 
  
  /**
    * @}
    */ 
  
  /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
  