/*
 * ________________________________________________________________________________________________________
 * Copyright (c) 2016-2016 InvenSense Inc. All rights reserved.
 *
 * This software, related documentation and any modifications thereto (collectively “Software”) is subject
 * to InvenSense and its licensors' intellectual property rights under U.S. and international copyright
 * and other intellectual property rights laws.
 *
 * InvenSense and its licensors retain all intellectual property and proprietary rights in and to the Software
 * and any use, reproduction, disclosure or distribution of the Software without an express license agreement
 * from InvenSense is strictly prohibited.
 *
 * EXCEPT AS OTHERWISE PROVIDED IN A LICENSE AGREEMENT BETWEEN THE PARTIES, THE SOFTWARE IS
 * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
 * EXCEPT AS OTHERWISE PROVIDED IN A LICENSE AGREEMENT BETWEEN THE PARTIES, IN NO EVENT SHALL
 * INVENSENSE BE LIABLE FOR ANY DIRECT, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY
 * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
 * OF THE SOFTWARE.
 * ________________________________________________________________________________________________________
 */
#ifndef _EXAMPLE_FREEFALL_DETECTION_H_
#define _EXAMPLE_FREEFALL_DETECTION_H_

#include <stdint.h>
#include "imu/inv_imu_transport.h"
#include "imu/inv_imu_defs.h"
#include "imu/inv_imu_driver.h"
#include "imu/inv_imu_apex.h"

/*** Example configuration ***/

/* 
 * Select communication link between Smartmotion board and IMU 
 */
#define SERIF_TYPE UI_SPI4
// #define SERIF_TYPE                    UI_I2C

/*
 * Freefall frequency
 * Use type APEX_CONFIG1_DMP_ODR_t to define DMP frequency
 * These types are defined in inv_imu_defs.h.
 *
 * \note The frequency modes to run the Freefall are :
 * APEX_CONFIG1_DMP_ODR_25Hz  (Low Power mode),
 * APEX_CONFIG1_DMP_ODR_50Hz  (Low Power mode),
 * APEX_CONFIG1_DMP_ODR_100Hz  (Normal mode)
 * APEX_CONFIG1_DMP_ODR_400Hz  (High perf)
 */
#define FREEFALL_FREQUENCY_MODE APEX_CONFIG1_DMP_ODR_400Hz

/*
 * Duration(us) during which LowG and HighG events are not considered after an HighG event.
 * Use type APEX_CONFIG9_FF_DEBOUNCE_DURATION_t to define debounce duration
 * These types are defined in inv_imu_defs.h.
 */
#define FF_DEBOUNCE_DURATION APEX_CONFIG9_FF_DEBOUNCE_DURATION_2000_MS

/*
 * Distance (cm) max crossed by the device after a LowG event, below which the detection of an HighG event triggers a freefall interrupt. 
 * Use type APEX_CONFIG12_FF_MAX_DURATION_t to define ff_max_duration
 * These types are defined in inv_imu_defs.h.
 */
#define FF_MAX_DURATION APEX_CONFIG12_FF_MAX_DURATION_204_CM

/*
 * Distance (cm) min crossed by the device after a LowG event, above which the detection of an HighG event triggers a freefall interrupt.
 * Use type APEX_CONFIG12_FF_MIN_DURATION_t to define ff_min_duration
 * These types are defined in inv_imu_defs.h.
 */
#define FF_MIN_DURATION APEX_CONFIG12_FF_MIN_DURATION_10_CM

/*
 * Absolute low peak threshold to detect when it falls below on any of the accelerometer axis. 
 * Use type APEX_CONFIG10_LOWG_PEAK_TH_t to define lowG peak threshold
 * These types are defined in inv_imu_defs.h.
 */
#define LOWG_PEAK_THRESHOLD APEX_CONFIG10_LOWG_PEAK_TH_563_MG

/*
 * Hysteresis low peak threshold (mg) subtracted to the threshold after the initial threshold is met.
 * Use type APEX_CONFIG5_LOWG_PEAK_TH_HYST_t to define lowG peak hysteresis
 * These types are defined in inv_imu_defs.h.
 */
#define LOWG_PEAK_HYSTERESIS APEX_CONFIG5_LOWG_PEAK_TH_HYST_156_MG

/*
 * Time in number of samples to stay below the threshold before triggering the event
 * Use type APEX_CONFIG10_LOWG_TIME_TH_SAMPLES_t to define lowG peak hysteresis
 * These types are defined in inv_imu_defs.h.
 */
#define LOWG_TIME_SAMPLES_THRESHOLD APEX_CONFIG10_LOWG_TIME_TH_5_SAMPLES

/*
 * Absolute high peak threshold (mg) to detect when it goes above on any of the accelerometer axis. 
 * Use type APEX_CONFIG11_HIGHG_PEAK_TH_t to define highG time threshold
 * These types are defined in inv_imu_defs.h.
 */
#define HIGHG_PEAK_THRESHOLD APEX_CONFIG11_HIGHG_PEAK_TH_2500_MG

/*
 * Hysteresis high peak threshold (mg) added to the threshold after the initial threshold is met.
 * Use type APEX_CONFIG5_HIGHG_PEAK_TH_HYST_t to define highG peak hysteresis
 * These types are defined in inv_imu_defs.h.
 */
#define HIGHG_PEAK_HYSTERESIS APEX_CONFIG5_HIGHG_PEAK_TH_HYST_156_MG

/*
 * Time in number of samples to stay above the threshold before triggering the event
 * Use type APEX_CONFIG11_HIGHG_TIME_TH_SAMPLES_t to define highG time threshold
 * These types are defined in inv_imu_defs.h.
 */
#define HIGHG_TIME_SAMPLES_THRESHOLD APEX_CONFIG11_HIGHG_TIME_TH_1_SAMPLE

/**
 * \brief This function is in charge of reseting and initializing IMU device. It should
 * be successfully executed before any access to IMU device.
 * 
 * \param[in] icm_serif : Serial interface object.
 * \return 0 on success, negative value on error.
 */
int setup_imu_device(const struct inv_imu_serif *icm_serif);

/**
 * \brief This function configures the device for Freefall detection.
 *
 * This includes configuring accel frequency as well as setting all parameters.
 * \return 0 on success, negative value on error.
 */
int configure_imu_device();

/**
 * \brief This function extracts data from the IMU FIFO.
 *
 * \return 0 on success, negative value on error.
 */
int get_imu_data(void);

/**
 * \brief This function converts the free fall duration from number of sample to cm.
 *
 * \return Freefall duration in cm.
 */
float convert_ff_duration_sample_to_cm(uint16_t ff_duration_samples);

#endif /* !_EXAMPLE_FREEFALL_DETECTION_H_ */
