/*! * @section LICENSE * * (C) Copyright 2011~2014 Bosch Sensortec GmbH All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *------------------------------------------------------------------------------ * Disclaimer * * Common: Bosch Sensortec products are developed for the consumer goods * industry. They may only be used within the parameters of the respective valid * product data sheet. Bosch Sensortec products are provided with the express * understanding that there is no warranty of fitness for a particular purpose. * They are not fit for use in life-sustaining, safety or security sensitive * systems or any system or device that may lead to bodily harm or property * damage if the system or device malfunctions. In addition, Bosch Sensortec * products are not fit for use in products which interact with motor vehicle * systems. The resale and/or use of products are at the purchaser's own risk * and his own responsibility. The examination of fitness for the intended use * is the sole responsibility of the Purchaser. * * The purchaser shall indemnify Bosch Sensortec from all third party claims, * including any claims for incidental, or consequential damages, arising from * any product use not covered by the parameters of the respective valid product * data sheet or not approved by Bosch Sensortec and reimburse Bosch Sensortec * for all costs in connection with such claims. * * The purchaser must monitor the market for the purchased products, * particularly with regard to product safety and inform Bosch Sensortec without * delay of all security relevant incidents. * * Engineering Samples are marked with an asterisk (*) or (e). Samples may vary * from the valid technical specifications of the product series. They are * therefore not intended or fit for resale to third parties or for use in end * products. Their sole purpose is internal client testing. The testing of an * engineering sample may in no way replace the testing of a product series. * Bosch Sensortec assumes no liability for the use of engineering samples. By * accepting the engineering samples, the Purchaser agrees to indemnify Bosch * Sensortec from all claims arising from the use of engineering samples. * * Special: This software module (hereinafter called "Software") and any * information on application-sheets (hereinafter called "Information") is * provided free of charge for the sole purpose to support your application * work. The Software and Information is subject to the following terms and * conditions: * * The Software is specifically designed for the exclusive use for Bosch * Sensortec products by personnel who have special experience and training. Do * not use this Software if you do not have the proper experience or training. * * This Software package is provided `` as is `` and without any expressed or * implied warranties, including without limitation, the implied warranties of * merchantability and fitness for a particular purpose. * * Bosch Sensortec and their representatives and agents deny any liability for * the functional impairment of this Software in terms of fitness, performance * and safety. Bosch Sensortec and their representatives and agents shall not be * liable for any direct or indirect damages or injury, except as otherwise * stipulated in mandatory applicable law. * * The Information provided is believed to be accurate and reliable. Bosch * Sensortec assumes no responsibility for the consequences of use of such * Information nor for any infringement of patents or other rights of third * parties which may result from its use. * * @file algo_adapter.c * @date "Tue Aug 27 15:51:32 2013 +0800" * @commit "24cb7fe" * * @brief * * @detail * */ #include #include #define LOG_TAG_MODULE "" #include "sensord.h" #include "hw_def.h" extern void fusion_arbitrate_dr(); extern struct algo_product *fusion_get_product(uint32_t type); static uint32_t g_simulute_ts; typedef struct sample_intval_type { BS_U16 intval; BS_U8 acc_dr; BS_U8 gyro_dr; } sample_intval_t; /* The sequence matches with definitions of BSX_DATARATE_XHZ in * BsxLibraryConstances.h */ static const sample_intval_t sample_intval[ALGO_NUM_DR] = { {1000, HW_A_BW_8, HW_G_BW_47}, { 200, HW_A_BW_8, HW_G_BW_47}, { 100, HW_A_BW_8, HW_G_BW_47}, { 50, HW_A_BW_16, HW_G_BW_47}, { 40, HW_A_BW_16, HW_G_BW_47}, { 25, HW_A_BW_31, HW_G_BW_47}, { 20, HW_A_BW_31, HW_G_BW_47}, { 10, HW_A_BW_63, HW_G_BW_47}, { 8, HW_A_BW_63, HW_G_BW_47}, { 5, HW_A_BW_125, HW_G_BW_47} }; static BS_U16 g_tab_hz[ALGO_NUM_DR] = {}; /* record the count of sensors which require hw gyro sensor present */ static uint32_t g_active_gyro_aps_cnt = 0; static uint32_t g_active_aps = 0; static hw_dep_set_t g_active_hws = 0; static hw_dep_set_t g_hws_dep = 0; #define HW_IS_ACTIVE(hws, id) (hws & (1 << SENSOR_HW_TYPE_##id)) static struct sensor_hw_a *g_p_hw_a = NULL; static struct sensor_hw_m *g_p_hw_m = NULL; static struct sensor_hw_g *g_p_hw_g = NULL; static struct algo_work_mode *g_curr_work_mode = NULL; #ifdef CFG_USE_DATA_LOG static int g_fd_log_data_x = -1; #endif #define WM_IS_FUSION(wm) (((1<cap)\ && (1<cap) /* mask only one individual capability */ #define WM_MASK_CAP(wm, type) (wm->mask |= (1<<(type))) #define WM_UNMASK_CAP(wm, type) (wm->mask &= ~(1<<(type))) #define WM_MASK_FUSION_CAPS(wm)\ do {\ WM_MASK_CAP(wm, SENSOR_TYPE_O);\ WM_MASK_CAP(wm, SENSOR_TYPE_VRV);\ } while (0) static struct algo_work_mode g_algo_work_modes[] = { { name:"WM_S", mode:{opMode:BSX_WORKINGMODE_SLEEP}, cap:0, available:1, }, { name:"WM_A", mode:{opMode:BSX_WORKINGMODE_ACCONLY}, cap:((1<= __SENSORS_DEVICE_API_VERSION_1_0__ | (1<= __SENSORS_DEVICE_API_VERSION_1_0__ | (1<= __SENSORS_DEVICE_API_VERSION_1_0__ | (1<= __SENSORS_DEVICE_API_VERSION_1_0__ | (1<= __SENSORS_DEVICE_API_VERSION_1_0__ | (1<= __SENSORS_DEVICE_API_VERSION_1_1__ | (1<= __SENSORS_DEVICE_API_VERSION_1_0__ | (1<= __SENSORS_DEVICE_API_VERSION_1_1__ | (1<= __SENSORS_DEVICE_API_VERSION_1_0__ | (1<= __SENSORS_DEVICE_API_VERSION_1_1__ | (1<= __SENSORS_DEVICE_API_VERSION_1_0__ | (1<= __SENSORS_DEVICE_API_VERSION_1_1__ | (1<= __SENSORS_DEVICE_API_VERSION_1_0__ | (1<available) { continue; } aps = wm->cap; aps &= g_active_aps; if (aps & wm->mask) { PDEBUG("wm: %s has mask for caps: %x", wm->name, wm->mask); } aps &= ~wm->mask; if (aps == g_active_aps) { if (NULL == wm_new) { wm_new = wm; cap_num_new = get_num_set_bits_u32(wm_new->cap); } else { /* this is a simple way to determine * which work mode has a lighter overhead * it is not perfect but it works */ cap_num = get_num_set_bits_u32(wm->cap); if (cap_num < cap_num_new) { PDEBUG("select wm:%s -> %s", wm_new->name, wm->name); wm_new = wm; cap_num_new = cap_num; } } } } if (NULL == wm_new) { PWARN("no work mode is suitable"); } else { PINFO("work mode: %s selected", wm_new->name); } return wm_new; } static void algo_check_new_hw_dep() { ts_HWsensorSwitchList hw; hw_dep_set_t dep_hw = 0; hw_dep_set_t dep_hw_change = 0; bsx_get_hwdependency(g_curr_work_mode->mode, &hw); if (hw.acc) { dep_hw |= (1 << SENSOR_HW_TYPE_A); } if (hw.mag) { dep_hw |= (1 << SENSOR_HW_TYPE_M); } if (hw.gyro) { dep_hw |= (1 << SENSOR_HW_TYPE_G); } dep_hw_change = dep_hw ^ g_active_hws; if (dep_hw_change & (1 << SENSOR_HW_TYPE_A)) { if (dep_hw & (1 << SENSOR_HW_TYPE_A)) { algo_load_calib_profile(SENSOR_MAGIC_A); } } if (dep_hw_change & (1 << SENSOR_HW_TYPE_M)) { if (dep_hw & (1 << SENSOR_HW_TYPE_M)) { algo_load_calib_profile(SENSOR_MAGIC_M); } } if (dep_hw_change & (1 << SENSOR_HW_TYPE_G)) { if (dep_hw & (1 << SENSOR_HW_TYPE_G)) { algo_load_calib_profile(SENSOR_MAGIC_G); } } g_hws_dep = dep_hw; } static void algo_mode_transit() { struct algo_work_mode *wm_new = NULL; wm_new = algo_get_matching_mode(); #if __HAL_VER__ >= __SENSORS_DEVICE_API_VERSION_1_1__ #ifdef __USECASE_TYPE_NDOF__ struct algo_product *ap; ap = fusion_get_product(SENSOR_TYPE_GEOM_RV); if ((NULL != wm_new) && ap->enable) { if (g_active_gyro_aps_cnt != 0) #ifdef __FMC_OFF__ wm_new = g_algo_work_modes + ALGO_WORKING_MODE_NDOF_FMC_OFF; #else wm_new = g_algo_work_modes + ALGO_WORKING_MODE_NDOF; #endif else wm_new = g_algo_work_modes + ALGO_WORKING_MODE_COMPASS; } else #endif #endif { if ((NULL == wm_new) || (wm_new == g_curr_work_mode)) { PWARN("working mode not changed"); return; } } #ifdef CFG_USE_DATA_LOG #ifdef __RAM_DATA_LOG_SUPPORT__ // write sensor data buffer to file when sensor mode transmit if (-1 != g_fd_log_data_x) { if (data_log_level & DATA_LOG_USING_RAM_BUFFER) { g_trig_flag_log_data_x = 1; } } #endif #endif if (NULL != g_curr_work_mode) { if (NULL != g_curr_work_mode->exit) { g_curr_work_mode->exit(); } } if (HW_IS_ACTIVE(g_active_hws, A)) { algo_save_calib_profile(SENSOR_MAGIC_A); } if (HW_IS_ACTIVE(g_active_hws, M)) { algo_save_calib_profile(SENSOR_MAGIC_M); } if (HW_IS_ACTIVE(g_active_hws, G)) { algo_save_calib_profile(SENSOR_MAGIC_G); } bsx_set_workingmode(&wm_new->mode); if (NULL != wm_new->entry) { wm_new->entry(); } PINFO("work mode transit %s ---> %s", g_curr_work_mode ? g_curr_work_mode->name : "unknown", wm_new->name); g_curr_work_mode = wm_new; algo_check_new_hw_dep(); } static void algo_resolve_internal_state() { if ((g_curr_work_mode->min_dr_a != ALGO_DR_INVALID) && (g_dr_a < g_curr_work_mode->min_dr_a)) { g_dr_a = g_curr_work_mode->min_dr_a; } if ((g_curr_work_mode->max_dr_a != ALGO_DR_INVALID) && (g_dr_a > g_curr_work_mode->max_dr_a)) { g_dr_a = g_curr_work_mode->max_dr_a; } if ((g_curr_work_mode->min_dr_m != ALGO_DR_INVALID) && (g_dr_m < g_curr_work_mode->min_dr_m)) { g_dr_m = g_curr_work_mode->min_dr_m; } if ((g_curr_work_mode->max_dr_m != ALGO_DR_INVALID) && (g_dr_m > g_curr_work_mode->max_dr_m)) { g_dr_m = g_curr_work_mode->max_dr_m; } if ((g_curr_work_mode->min_dr_g != ALGO_DR_INVALID) && (g_dr_g < g_curr_work_mode->min_dr_g)) { g_dr_g = g_curr_work_mode->min_dr_g; } if ((g_curr_work_mode->max_dr_g != ALGO_DR_INVALID) && (g_dr_g > g_curr_work_mode->max_dr_g)) { g_dr_g = g_curr_work_mode->max_dr_g; } PINFO("end dr: %d %d %d", g_dr_a, g_dr_m, g_dr_g); if (g_curr_work_mode->min_dr_a != ALGO_DR_INVALID) { bsx_set_accdatarate(g_dr_a); #ifdef __DEBUG_TIMING_ACCURACY__ init_timing_tolerance(SENSOR_HW_TYPE_A, sample_intval[g_dr_a].intval); #endif } if (g_curr_work_mode->min_dr_m != ALGO_DR_INVALID) { bsx_set_magdatarate(g_dr_m); #ifdef __DEBUG_TIMING_ACCURACY__ init_timing_tolerance(SENSOR_HW_TYPE_M, sample_intval[g_dr_m].intval); #endif } if (g_curr_work_mode->min_dr_g != ALGO_DR_INVALID) { bsx_set_gyrodatarate(g_dr_g); #ifdef __DEBUG_TIMING_ACCURACY__ init_timing_tolerance(SENSOR_HW_TYPE_G, sample_intval[g_dr_g].intval); #endif } } static void algo_do_rearrange_workmode() { struct algo_work_mode *wm = NULL; int i = 0; BSX_U32 mode = 0; int usecase; usecase = algo_get_current_usecase(); switch (usecase) { case ALGO_FUSION_MODE_IMU: mode = BSX_WORKINGMODE_IMUPLUS; break; case ALGO_FUSION_MODE_9DOF: #ifdef __FMC_OFF__ mode = BSX_WORKINGMODE_NDOF_FMC_OFF; #else mode = BSX_WORKINGMODE_NDOF; #endif break; case ALGO_FUSION_MODE_COMPASS: mode = BSX_WORKINGMODE_COMPASS; break; case ALGO_FUSION_MODE_M4G: mode = BSX_WORKINGMODE_M4G; break; default: break; } for (i = 0; i < ARRAY_SIZE(g_algo_work_modes); i++) { wm = g_algo_work_modes + i; /* disable gyro if m4g mode */ if (mode == BSX_WORKINGMODE_M4G) { WM_MASK_CAP(wm, SENSOR_TYPE_G); } /* enable working mode for the use case */ if (wm->mode.opMode == mode) { PINFO("fusion workmode enabled: %s", wm->name); wm->available = 1; /* enable virtual gyro for m4g working mode */ if (mode == BSX_WORKINGMODE_M4G) { WM_UNMASK_CAP(wm, SENSOR_TYPE_G); } } } } void algo_adapter_init() { int i; struct sensor_hw *hw; #ifdef CFG_USE_DATA_LOG char buf[512]; #endif for (i = 0; i < ALGO_NUM_DR; i++) { g_tab_hz[i] = 1000 / sample_intval[i].intval; } hw = hw_get_hw_by_id(SENSOR_HW_TYPE_A); if (hw) { g_p_hw_a = CONTAINER_OF(hw, struct sensor_hw_a, hw); } hw = hw_get_hw_by_id(SENSOR_HW_TYPE_M); if (hw) { g_p_hw_m = CONTAINER_OF(hw, struct sensor_hw_m, hw); } hw = hw_get_hw_by_id(SENSOR_HW_TYPE_G); if (hw) { g_p_hw_g = CONTAINER_OF(hw, struct sensor_hw_g, hw); } algo_do_rearrange_workmode(); algo_mode_transit(); #ifdef CFG_USE_DATA_LOG sprintf(buf, "/data/misc/sensor/sensor_data_bsx.log", get_build_date()); g_fd_log_data_x = open(buf, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (-1 != g_fd_log_data_x) { write_version(g_fd_log_data_x); sprintf(buf, "\n%s", "scheduling timestamp\ta.x\ta.y\ta.z\ttimestamp acc\t" "m.x\tm.y\tm.z\ttimestamp mag\t" "g.x\tg.y\tg.z\ttimestampe gyro\t" "gfs.status\tgfs.x\tgfs.y\tgfs.z\t\n"); write(g_fd_log_data_x, buf, strlen(buf)); } #endif } static int algo_is_data_invalid(sensordata_t *p_data) { int zero_times = 0; /* how many zeros in axis */ if(p_data->data.x == 0) { zero_times ++; } if (p_data->data.y == 0) { zero_times ++; } if (p_data->data.z == 0) { zero_times ++; } if (zero_times >= 2) { return 0;//-EINVAL; } return 0; } #ifdef __DEBUG_TIMING_ACCURACY__ const char *hw_sensor_names[] = { "acc", "gyro", "mag" }; timeing_accuracy_t sensor_dbg_timing_status[SENSOR_HW_TYPE_MAX]; void init_timing_tolerance(int type, uint32_t interval) { interval *= 1000; sensor_dbg_timing_status[type].biggest = interval * 2; sensor_dbg_timing_status[type].tolerance_high = (interval * 105) / 100; sensor_dbg_timing_status[type].tolerance_low = (interval * 95) / 100; PWARN("biggest :%d\n", sensor_dbg_timing_status[type].biggest); PWARN("tolerance high :%d\n", sensor_dbg_timing_status[type].tolerance_high); PWARN("tolerance_low :%d\n", sensor_dbg_timing_status[type].tolerance_low); } void print_timing_accuracy(void) { int i = 0; for (i = 0; i < SENSOR_HW_TYPE_MAX; i ++) { PWARN("timing accuracy info for %s:\n", hw_sensor_names[i]); PWARN("total :%d\n", sensor_dbg_timing_status[i].num_total); PWARN("level1(over 5percent):%d\n", sensor_dbg_timing_status[i].num_overlap_lvl1); PWARN("level2(over 100percent):%d\n", sensor_dbg_timing_status[i].num_overlap_lvl2); } } #endif /*! * @brief this function update a sensor data with time stampe * * @param p_sensor[i] an instance of sensor_hw * @param ts[i] schedule time stamp for trigging read data from * driver * @param dr_index[i] data rate index relative to the table sample_intvl * @param p_data[o] out put xyz data and time stamp * * @return 0 success, or none zero failed * @retval -EBUSY timestamp have not reached sample duration * @retval 0 success */ static int algo_update_sensor_data(struct sensor_hw *p_sensor, uint32_t ts, BS_U8 dr_index, sensordata_t *p_data) { int err = 0; sensor_data_ival_t val; uint32_t current_ts = 0; uint32_t ts_diff = 0; uint32_t expected_interval; /* get time duration and add a time tolerance */ current_ts = ts; ts_diff = current_ts - p_sensor->ts_last_update; ts_diff += 200; expected_interval = sample_intval[dr_index].intval * 1000; /* period too short */ if (ts_diff < expected_interval) { return 0; } err = p_sensor->get_data_nb(&val); if (!err) { /* use scheduling or calibrated scheduling timestamp as sensor timestamp */ #ifndef __SENSOR_TIMESTAMP_SCHEDULING__ current_ts = get_current_timestamp(); #endif /*p_data->time_stamp = current_ts;*/ p_data->time_stamp = g_simulute_ts; p_data->data.x = (BS_S16) val.x; p_data->data.y = (BS_S16) val.y; p_data->data.z = (BS_S16) val.z; } #ifdef __DEBUG_TIMING_ACCURACY__ if (p_sensor->ts_last_update) { timeing_accuracy_t *p_timing_dbg = &sensor_dbg_timing_status[p_sensor->type]; uint32_t elapse; p_timing_dbg->num_total ++; elapse = current_ts - p_sensor->ts_last_update; if (elapse > p_timing_dbg->biggest) { p_timing_dbg->num_overlap_lvl2++; } else if ((elapse < p_timing_dbg->tolerance_low) || (elapse > p_timing_dbg->tolerance_high)) { p_timing_dbg->num_overlap_lvl1++; } } #endif p_sensor->ts_last_update = ts; return err; } /*! * @brief This function update all sensors' data periodically * * @param ts[i] schedule time stamp for trigging read data from * driver * * @return 0 success, or none zero failed * @retval -EBUSY timestamp have not reached sample duration * @retval 0 success */ static int algo_update_sensor_all(uint32_t ts, libraryinput_t *p_sensor_data) { int ret = 0; if (HW_IS_ACTIVE(g_active_hws, A) || HW_IS_ACTIVE(g_active_hws, G)) g_simulute_ts += sample_intval[g_dr_a].intval * 1000; else g_simulute_ts += sample_intval[g_dr_m].intval * 1000; /* update magnetic first if magnetic will just use 'ts' directly without query realtime timestamp */ if (HW_IS_ACTIVE(g_active_hws, M)) { ret = algo_update_sensor_data(&g_p_hw_m->hw, ts, g_dr_m, &p_sensor_data->mag); if (ret && (-ETIME != ret)) { PERR("read mag data failed:%d\n", ret); return ret; } ret = algo_is_data_invalid(&p_sensor_data->acc); if (ret) { PERR("acc data is invalid %d\n", ret); return ret; } } if (HW_IS_ACTIVE(g_active_hws, A)) { ret = algo_update_sensor_data(&g_p_hw_a->hw, ts, g_dr_a, &p_sensor_data->acc); if (ret && (-ETIME != ret)) { PERR("read acc data failed:%d\n", ret); return ret; } ret = algo_is_data_invalid(&p_sensor_data->acc); if (ret) { PERR("acc data is invalid %d\n", ret); return ret; } } if (HW_IS_ACTIVE(g_active_hws, G)) { ret = algo_update_sensor_data(&g_p_hw_g->hw, ts, g_dr_g, &p_sensor_data->gyro); if (ret && (-ETIME != ret)) { PERR("read gyro data failed:%d\n", ret); return ret; } } return ret; } static int algo_hz2data_rate(int hz) { int dr = 0; int i; for (i = 0; i < ALGO_NUM_DR; i++) { if (hz <= g_tab_hz[i]) { dr = i; break; } } if (i >= ALGO_NUM_DR) { dr = ALGO_NUM_DR - 1; } return dr; } int algo_enable_product(struct algo_product *ap, int enable) { int err = 0; #if __HAL_VER__ >= __SENSORS_DEVICE_API_VERSION_1_1__ #ifdef __USECASE_TYPE_NDOF__ if ((ap->type == SENSOR_TYPE_G) || (ap->type == SENSOR_TYPE_GYU) || (ap->type == SENSOR_TYPE_O)|| (ap->type == SENSOR_TYPE_VRV) || (ap->type == SENSOR_TYPE_GRV)) { if (enable) { g_active_gyro_aps_cnt++; } else { if (g_active_gyro_aps_cnt > 0) g_active_gyro_aps_cnt--; else g_active_gyro_aps_cnt = 0; } } #endif #endif PDEBUG("g_active_gyro_aps_cnt = %d", g_active_gyro_aps_cnt); enable = !!enable; g_active_aps = SET_VALUE_BITS(g_active_aps, enable, ap->type, 1); algo_mode_transit(); fusion_arbitrate_dr(); algo_resolve_internal_state(); return err; } int algo_update_sample_rate(void) { int ret = 0; if (HW_IS_ACTIVE(g_active_hws, A)) { if (g_p_hw_a && g_p_hw_a->set_bw) { ret = g_p_hw_a->set_bw(g_p_hw_a, sample_intval[g_dr_a].acc_dr); } } if (ret) { PERR("failed to change bandwidth for acc:%d\n", g_dr_a); return ret; } if (HW_IS_ACTIVE(g_active_hws, G)) { if (g_p_hw_g && g_p_hw_g->set_bw) { ret = g_p_hw_g->set_bw(g_p_hw_g, sample_intval[g_dr_g].gyro_dr); } } if (ret) { PERR("failed to change bandwidth for gyro:%d\n", g_dr_g); } return ret; } void algo_on_interval_changed(struct algo_product *ap, int *itvl) { int hz; int dr; int interval = *itvl; if (interval <= 0) { return; } interval = get_nearest_divisible_int(1000, interval); *itvl = interval; hz = 1000 / interval; dr = algo_hz2data_rate(hz); PINFO("type: %d interval: %d new hz: %d dr: %d", ap->type, interval, hz, dr); ap->dr_a = dr; ap->dr_m = dr; ap->dr_g = dr; fusion_arbitrate_dr(); algo_resolve_internal_state(); algo_update_sample_rate(); } void algo_get_curr_hw_dep(hw_dep_set_t *dep) { *dep = g_hws_dep; } int algo_on_hw_dep_checked(const hw_dep_set_t *dep) { g_active_hws = *dep; return algo_update_sample_rate(); } int algo_get_hint_interval() { int ret = 0; int intv_a = sample_intval[g_dr_a].intval; int intv_m = sample_intval[g_dr_m].intval; int intv_g = sample_intval[g_dr_g].intval; ret = 1000; if (HW_IS_ACTIVE(g_active_hws, A)) { ret = get_max_comm_div(ret, intv_a); } if (HW_IS_ACTIVE(g_active_hws, M)) { ret = get_max_comm_div(ret, intv_m); } if (HW_IS_ACTIVE(g_active_hws, G)) { ret = get_max_comm_div(ret, intv_g); } return ret; } static int algo_read_calib_profile(char magic, void *profile) { int err = 0; char *filename; switch (magic) { case SENSOR_MAGIC_A: filename = SENSOR_CFG_FILE_SYS_PROFILE_CALIB_A; break; case SENSOR_MAGIC_M: filename = SENSOR_CFG_FILE_SYS_PROFILE_CALIB_M; break; case SENSOR_MAGIC_G: filename = SENSOR_CFG_FILE_SYS_PROFILE_CALIB_G; break; default: PWARN("unknown sensor"); return -1; } // err = util_fs_read_file(filename, profile, sizeof(ts_calibprofile)); err = util_fs_read_file(filename, profile, sizeof(calibprofile_crc_t)); return err; } void algo_load_calib_profile(char magic) { #if 1 calibprofile_crc_t profile; ts_calibprofile* profile_p = (ts_calibprofile*)&profile; BSX_U8* profile_pu8; BSX_U8 crc = 0; int i; int err; /* reading calibration profile */ err = algo_read_calib_profile(magic, &profile); if (err != 10) { PERR("failed on reading calibration profile:%c\n", magic); return; } /* Do CRC check */ profile_pu8 = &profile; for (i = 0; i < sizeof(calibprofile_crc_t); i++) { crc += profile_pu8[i]; } if (crc != 0) { PERR("profile <%c> CRC check failed!", magic); return; } /* set profile to bsx */ switch (magic) { case SENSOR_MAGIC_A: if (profile.accuracy == SENSOR_ACCURACY_HIGH) { bsx_set_acccalibprofile(profile_p); } break; case SENSOR_MAGIC_M: if (profile.accuracy == SENSOR_ACCURACY_HIGH) { bsx_set_magcalibprofile(profile_p); } break; case SENSOR_MAGIC_G: if (profile.accuracy == SENSOR_ACCURACY_HIGH) { bsx_set_gyrocalibprofile(profile_p); } break; default: PWARN("unknown sensor"); return; } if (SENSOR_ACCURACY_HIGH == profile.accuracy) { PINFO("profile <%c> is loaded: %d %d %d %d %d", magic, (int)profile.calibParam.offset.x, (int)profile.calibParam.offset.y, (int)profile.calibParam.offset.z, (int)profile.calibParam.radius, (int)profile.accuracy ); } #else ts_calibprofile profile; int err; /* reading calibration profile */ err = algo_read_calib_profile(magic, &profile); PERR("read calib return err %d", err); if (err == -1) { PERR("failed on reading calibration profile:%c\n", magic); return; } /* set profile to bsx */ switch (magic) { case SENSOR_MAGIC_A: if (profile.accuracy == SENSOR_ACCURACY_HIGH) { bsx_set_acccalibprofile(&profile); } break; case SENSOR_MAGIC_M: if (profile.accuracy == SENSOR_ACCURACY_HIGH) { bsx_set_magcalibprofile(&profile); } break; case SENSOR_MAGIC_G: if (profile.accuracy == SENSOR_ACCURACY_HIGH) { bsx_set_gyrocalibprofile(&profile); } break; default: PWARN("unknown sensor"); return; } if (SENSOR_ACCURACY_HIGH == profile.accuracy) { PINFO("profile <%c> is loaded: %d %d %d %d %d", magic, (int)profile.calibParam.offset.x, (int)profile.calibParam.offset.y, (int)profile.calibParam.offset.z, (int)profile.calibParam.radius, (int)profile.accuracy ); } #endif } void algo_save_calib_profile(char magic) { #if 1 calibprofile_crc_t profile; ts_calibprofile* profile_p = (ts_calibprofile*)&profile; char *filename = NULL; int ret; BSX_U8* profile_pu8; int i; switch (magic) { case SENSOR_MAGIC_A: bsx_get_acccalibprofile(profile_p); filename = SENSOR_CFG_FILE_SYS_PROFILE_CALIB_A; break; case SENSOR_MAGIC_M: bsx_get_magcalibprofile(profile_p); filename = SENSOR_CFG_FILE_SYS_PROFILE_CALIB_M; break; case SENSOR_MAGIC_G: bsx_get_gyrocalibprofile(profile_p); filename = SENSOR_CFG_FILE_SYS_PROFILE_CALIB_G; break; default: PWARN("unknown sensor"); return; } if (profile.accuracy != SENSOR_ACCURACY_HIGH) { return; } /* Calculate CRC for profile */ profile.crc = 0; profile_pu8 = &profile; for (i = 0; i < sizeof(calibprofile_crc_t)-1; i++) { profile.crc -= profile_pu8[i]; } ret = util_fs_write_file(filename, &profile, sizeof(calibprofile_crc_t)); if (ret == -1) { PERR("save caliration file failed:%s\n", filename); } #else ts_calibprofile profile; char *filename = NULL; int ret; switch (magic) { case SENSOR_MAGIC_A: bsx_get_acccalibprofile(&profile); filename = SENSOR_CFG_FILE_SYS_PROFILE_CALIB_A; break; case SENSOR_MAGIC_M: bsx_get_magcalibprofile(&profile); filename = SENSOR_CFG_FILE_SYS_PROFILE_CALIB_M; break; case SENSOR_MAGIC_G: bsx_get_gyrocalibprofile(&profile); filename = SENSOR_CFG_FILE_SYS_PROFILE_CALIB_G; PERR("check offset before save: offset xyz %d %d %d", profile.calibParam.offset.x, profile.calibParam.offset.y, profile.calibParam.offset.z); break; default: PWARN("unknown sensor"); return; } if (profile.accuracy != SENSOR_ACCURACY_HIGH) { return; } ret = util_fs_write_file(filename, &profile, sizeof(profile)); if (ret == -1) { PERR("save caliration file failed:%s\n", filename); } #endif } BS_S32 algo_proc_data(uint32_t ts) { int err = 0; int ret = 0; #ifdef CFG_USE_DATA_LOG char line[256] = ""; #endif static libraryinput_t all_sensor_data; /* read all sensor data */ ret = algo_update_sensor_all(ts, &all_sensor_data); if (ret != 0) { PERR("update sensor data failed:%d\n", ret); return ret; } /* record data in log file */ #ifdef CFG_USE_DATA_LOG if (-1 != g_fd_log_data_x) { ret = snprintf(line, ARRAY_SIZE(line) - 1, "%11u,%6d,%6d,%6d,%11u,", ts, all_sensor_data.acc.data.x, all_sensor_data.acc.data.y, all_sensor_data.acc.data.z, all_sensor_data.acc.time_stamp); if (ret > 0) { write(g_fd_log_data_x, line, ret); } ret = snprintf(line, ARRAY_SIZE(line) - 1, "%6d,%6d,%6d,%11u,", all_sensor_data.mag.data.x, all_sensor_data.mag.data.y, all_sensor_data.mag.data.z, all_sensor_data.mag.time_stamp); if (ret > 0) { write(g_fd_log_data_x, line, ret); } ret = snprintf(line, ARRAY_SIZE(line) - 1, "%6d,%6d,%6d,%11u", all_sensor_data.gyro.data.x, all_sensor_data.gyro.data.y, all_sensor_data.gyro.data.z, all_sensor_data.gyro.time_stamp); if (ret > 0) { write(g_fd_log_data_x, line, ret); } } #endif bsx_dostep(&all_sensor_data); return err; } int algo_set_opmode(int32_t sensor_type, int32_t opmode) { int ret = 0; switch (sensor_type) { case SENSOR_TYPE_GEST_FLIP: bsx_set_flipgesture_detecttime(1000); bsx_set_flipgesture_angle(FLIP_FACE_UP, FLIP_FACE_DOWN); if (opmode) { bsx_set_flipgesture_opmode(BSX_FLIP_GESTURE_MODE_REGULAR); } else { bsx_set_flipgesture_opmode(BSX_FLIP_GESTURE_MODE_SLEEP); } break; case SENSOR_TYPE_SW_SIGNIFICANT_MOTION: if (opmode) { bsx_set_significantmotiondetectionopmode(1); } else { bsx_set_significantmotiondetectionopmode(0); } break; case SENSOR_TYPE_STC: case SENSOR_TYPE_STD: if (opmode) { uint8_t mode = 0; bsx_get_stepdetectionopmode(&mode); if (mode == 0) { bsx_set_stepdetectionopmode(1); } } else { bsx_set_stepdetectionopmode(0); } break; default: PERR(" sensor type %d not find", sensor_type); break; } return ret; } int algo_get_proc_data_a(sensor_data_t *pdata) { int err = 0; BS_U8 status = 0; err = bsx_get_acccordata((ts_dataxyzf32*)&pdata->acceleration); bsx_get_acccalibaccuracy(&status); #ifdef __DEBUG_DATALOG_WITH_ACCURACY__ if(BSX_THREE != status) { char line[64]; int ret; if (-1 != g_fd_log_data_x) { ret = snprintf(line, ARRAY_SIZE(line) - 1, "\t\twarning! acc accuracy status :%d\n", status); write(g_fd_log_data_x, line, ret); } } #endif pdata->status = status; return err; } int algo_get_proc_data_m(sensor_data_t *pdata) { int err = 0; BS_U8 status = 0; err = bsx_get_magfiltdata1((ts_dataxyzf32*)&pdata->magnetic); bsx_get_magcalibaccuracy(&status); #ifdef __DEBUG_DATALOG_WITH_ACCURACY__ if(BSX_THREE != status) { char line[64]; int ret; if (-1 != g_fd_log_data_x) { ret = snprintf(line, ARRAY_SIZE(line) - 1, "\t\twarning! mag accuracy status :%d \n", status); write(g_fd_log_data_x, line, ret); } } #endif pdata->status = status; return err; } int algo_get_proc_data_o(sensor_data_t *pdata) { int err = 0; BS_U8 status = 0; err = bsx_get_orientdata_euler_deg((ts_dataeulerf32*)&pdata->orientation); bsx_get_orient_datastatus(&status); pdata->status = status; #ifdef __DEBUG_DATALOG_WITH_ACCURACY__ if(BSX_THREE != status) { char line[64]; int ret; if (-1 != g_fd_log_data_x) { ret = snprintf(line, ARRAY_SIZE(line) - 1, "\t\twarning!orientation mag accuracy status :%d \n", status); if (ret > 0) { write(g_fd_log_data_x, line, ret); } } } #endif #ifdef CFG_USE_DATA_LOG if (data_log_level & DATA_LOG_LEVEL_OUTPUT_VIRTUAL_SENSOR) data_log_output(g_fd_log_data_o, pdata); #endif return err; } int algo_get_proc_data_g(sensor_data_t *pdata) { int err = 0; ts_dataxyzf32 data; BS_U8 status = 0; err = bsx_get_gyrocordata_dps((ts_dataxyzf32*)&data); pdata->gyro.x = (float) data.x / (180 / PI); pdata->gyro.y = (float) data.y / (180 / PI); pdata->gyro.z = (float) data.z / (180 / PI); bsx_get_gyrocalibaccuracy(&status); #ifdef __DEBUG_DATALOG_WITH_ACCURACY__ if(BSX_THREE != status) { char line[256]; int ret; if (-1 != g_fd_log_data_x) { ret = snprintf(line, ARRAY_SIZE(line) - 1, "%d,%f,%f,%f\n", status, pdata->gyro.x, pdata->gyro.y, pdata->gyro.z); if (ret > 0) { write(g_fd_log_data_x, line, ret);} } } #endif pdata->status = status; #ifdef CFG_USE_DATA_LOG if (data_log_level & DATA_LOG_LEVEL_OUTPUT_AMG) data_log_output(g_fd_log_data_g, pdata); #endif return err; } int algo_get_proc_data_vg(sensor_data_t *pdata) { bsx_get_gravity((ts_dataxyzf32*)&pdata->data); #ifdef CFG_USE_DATA_LOG if (data_log_level & DATA_LOG_LEVEL_OUTPUT_VIRTUAL_SENSOR) data_log_output(g_fd_log_data_vg, pdata); #endif return 0; } int algo_get_proc_data_vla(sensor_data_t *pdata) { bsx_get_linearacceleration((ts_dataxyzf32*)&pdata->data); #ifdef CFG_USE_DATA_LOG if (data_log_level & DATA_LOG_LEVEL_OUTPUT_VIRTUAL_SENSOR) data_log_output(g_fd_log_data_vla, pdata); #endif return 0; } int algo_get_proc_data_vrv(sensor_data_t *pdata) { int err = 0; ts_dataquatf32 quat; err = bsx_get_orientdata_quat((ts_dataquatf32*)&quat); #ifdef ALGO_FIX_QUAT_SIGN quat.x = 0 - quat.x; quat.y = 0 - quat.y; quat.z = 0 - quat.z; #endif if (quat.w < 0) { quat.w = 0 - quat.w; quat.x = 0 - quat.x; quat.y = 0 - quat.y; quat.z = 0 - quat.z; } pdata->data[0] = quat.x; pdata->data[1] = quat.y; pdata->data[2] = quat.z; #if __HAL_VER__ >= __SENSORS_DEVICE_API_VERSION_1_0__ pdata->data[3] = quat.w; bsx_get_headingaccuracy_rad( &(pdata->data[4])); #else pdata->data[3] = 0; #endif #ifdef CFG_USE_DATA_LOG if (data_log_level & DATA_LOG_LEVEL_OUTPUT_VIRTUAL_SENSOR) data_log_output_vrv(g_fd_log_data_vrv, pdata); #endif return err; } #ifdef __UNCALIBRATED_VIRTUAL_SENSOR_SUPPORT__ int algo_get_proc_data_grv(sensor_data_t *pdata) { int err = 0; ts_dataquatf32 quat; err = bsx_get_imuorientdata_quat((ts_dataquatf32*)&quat); if (quat.w < 0) { quat.w = 0 - quat.w; quat.x = 0 - quat.x; quat.y = 0 - quat.y; quat.z = 0 - quat.z; } pdata->data[0] = quat.x; pdata->data[1] = quat.y; pdata->data[2] = quat.z; pdata->data[3] = 0; pdata->data[4] = 0; #ifdef CFG_USE_DATA_LOG if (data_log_level & DATA_LOG_LEVEL_OUTPUT_VIRTUAL_SENSOR) data_log_output_vrv(g_fd_log_data_grv, pdata); #endif return err; } int algo_get_proc_data_gu(sensor_data_t *pdata) { int err = 0; ts_dataxyzf32 data; BS_U8 status = 0; bsx_get_gyrorawdata_dps((ts_dataxyzf32*)&data); pdata->uncalibrated_gyro.x_uncalib = (float) data.x / (180 / PI); pdata->uncalibrated_gyro.y_uncalib = (float) data.y / (180 / PI); pdata->uncalibrated_gyro.z_uncalib = (float) data.z / (180 / PI); bsx_get_gyrooffset_dps((ts_dataxyzf32*)&data); pdata->uncalibrated_gyro.x_bias = (float) data.x / (180 / PI); pdata->uncalibrated_gyro.y_bias = (float) data.y / (180 / PI); pdata->uncalibrated_gyro.z_bias = (float) data.z / (180 / PI); bsx_get_gyrocalibaccuracy(&status); pdata->status = status; #ifdef CFG_USE_DATA_LOG if (data_log_level & DATA_LOG_LEVEL_OUTPUT_MU_GU) data_log_output_gu(g_fd_log_data_gu, pdata); #endif return err; } int algo_get_proc_data_mu(sensor_data_t *pdata) { int err = 0; BS_U8 status = 0; ts_dataxyzf32 data; bsx_get_magsoftironcorrecteddata((ts_dataxyzf32*)&pdata->uncalibrated_magnetic); bsx_get_magoffsets((ts_dataxyzf32*)&data); pdata->uncalibrated_magnetic.x_bias = (float) data.x; pdata->uncalibrated_magnetic.y_bias = (float) data.y; pdata->uncalibrated_magnetic.z_bias = (float) data.z; bsx_get_magcalibaccuracy(&status); pdata->status = status; #ifdef CFG_USE_DATA_LOG if (data_log_level & DATA_LOG_LEVEL_OUTPUT_MU_GU) data_log_output_mu(g_fd_log_data_mu, pdata); #endif return err; } #endif int algo_get_proc_data_gest_flip(sensor_data_t * pdata) { uint8_t flip_status; static uint8_t flip_status_back = SENSOR_GEST_FLIP_VAL_UNKNOWN; (void)bsx_get_flipgesture_status(&flip_status); if (flip_status_back != flip_status) { pdata->data[0] = flip_status; pdata->data[1] = 0; pdata->data[2] = 0; flip_status_back = flip_status; return 1; } return 0; } #if __HAL_VER__ >= __SENSORS_DEVICE_API_VERSION_1_0__ int algo_get_proc_data_sgm(sensor_data_t *pdata) { uint16_t sgm_status; static uint8_t smg_status_prev = 0; bsx_get_significantmotiondetectionstatus(&sgm_status); if (smg_status_prev != sgm_status) { /* if not a valid status value, then won't report*/ if (sgm_status == 0) { smg_status_prev = sgm_status; return 0; } pdata->data[0] = sgm_status; pdata->data[1] = 0; pdata->data[2] = 0; smg_status_prev = sgm_status; return 1; } return 0; } int algo_get_proc_data_stc(sensor_data_t *pdata) { int ret = 0; uint64_t steps = 0; static uint64_t pre_steps = 0; bsx_get_stepcount(&steps); if (pre_steps != steps) { pdata->step_counter = steps; pre_steps = steps; ret = 1; PINFO("get step counter %lld pre_steps %lld", pdata->step_counter, pre_steps); } return ret; } int algo_get_proc_data_std(sensor_data_t *pdata) { int ret = 0; uint8_t step_status = 0; static uint8_t pre_step_status = 0; (void)bsx_get_stepdetectionstatus(&step_status); if (pre_step_status != step_status) { /* if not a valid status then won't report it as a step detector event*/ if (step_status == 0) { pre_step_status = step_status; return 0; } pdata->data[0] = step_status; pdata->data[1] = 0; pdata->data[2] = 0; pre_step_status = step_status; ret = 1; } return ret; } #endif #if __HAL_VER__ >= __SENSORS_DEVICE_API_VERSION_1_1__ int algo_get_proc_data_geom_rv(sensor_data_t *pdata) { int err = 0; ts_dataquatf32 quat; err = bsx_get_orientdata_quat((ts_dataquatf32*)&quat); if (quat.w < 0) { quat.w = 0 - quat.w; quat.x = 0 - quat.x; quat.y = 0 - quat.y; quat.z = 0 - quat.z; } pdata->data[0] = quat.x; pdata->data[1] = quat.y; pdata->data[2] = quat.z; pdata->data[3] = quat.w; bsx_get_headingaccuracy_rad( &(pdata->data[4])); PINFO("get geom data %f %f %f %f %f", quat.x, quat.y, quat.z, quat.w, pdata->data[4]); #ifdef CFG_USE_DATA_LOG if (data_log_level & DATA_LOG_LEVEL_OUTPUT_VIRTUAL_SENSOR) data_log_output_vrv(g_fd_log_data_grv, pdata); #endif return err; } #endif #ifdef CFG_USE_DATA_LOG /* data log functions*/ void data_log_init() { /* read file to decide the level of data log */ int fd; int count; char buf[512] = ""; char *pline = NULL; int i; fd = open(SENSOR_CFG_FILE_DATA_LOG_LEVEL, O_RDONLY); if (fd < 0) { PINFO("data log level file does not exist, no data log"); return; } count = read(fd, buf, ARRAY_SIZE(buf) - 1); close(fd); for (i=15; i= '0') && (buf[i] <= '9')) data_log_level = buf[i] - '0'; else if ((buf[i] >= 'a') && (buf[i] <= 'f')) data_log_level = buf[i] + 10 - 'a'; else if ((buf[i] >= 'A') && (buf[i] <= 'F')) data_log_level = buf[i] + 10 - 'A'; else return; if ((buf[i+1] >= '0') && (buf[i+1] <= '9')) data_log_level = data_log_level *16 + buf[i+1] - '0'; else if ((buf[i+1] >= 'a') && (buf[i+1] <= 'f')) data_log_level = data_log_level *16 + buf[i+1] + 10 - 'a'; else if ((buf[i+1] >= 'A') && (buf[16] <= 'F')) data_log_level = data_log_level *16 + buf[i+1] + 10 - 'A'; PINFO("data log level = %d", data_log_level); if ((data_log_level & DATA_LOG_LEVEL_INPUT)||(data_log_level & DATA_LOG_USING_RAM_BUFFER)) { sprintf(buf, "/data/misc/sensor/sensor_data_bsx.log"); g_fd_log_data_x = open(buf, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (-1 != g_fd_log_data_x) { #ifdef __RAM_DATA_LOG_SUPPORT__ if (data_log_level & DATA_LOG_USING_RAM_BUFFER) { g_buf_ptr_log_data_x[0] = malloc(DATA_LOG_BUF_SIZE_X * sizeof(char)); g_buf_ptr_log_data_x[1] = malloc(DATA_LOG_BUF_SIZE_X * sizeof(char)); if ( (NULL == g_buf_ptr_log_data_x[0]) || (NULL == g_buf_ptr_log_data_x[1])) { PERR("malloc memory fail for sensor_data_bsx.log"); close(g_fd_log_data_x); g_fd_log_data_x = -1; if (NULL != g_buf_ptr_log_data_x[0]) free(g_buf_ptr_log_data_x[0]); if (NULL != g_buf_ptr_log_data_x[1]) free(g_buf_ptr_log_data_x[1]); return; } g_fill_ptr_log_data_x[0] = g_buf_ptr_log_data_x[0]; g_fill_ptr_log_data_x[1] = g_buf_ptr_log_data_x[1]; } #endif write_version(g_fd_log_data_x); sprintf(buf, "\n%s", "scheduling_timestamp,\ta.x,a.y,a.z,timestamp_acc,\t" "m.x,m.y,m.z,timestamp_mag,\t" "g.x,g.y,g.z,timestampe_gyro\n"); write(g_fd_log_data_x, buf, strlen(buf)); } } if (data_log_level & DATA_LOG_LEVEL_OUTPUT_AMG) { g_fd_log_data_a = open("/data/misc/sensor/sensor_data_a.log", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (-1 != g_fd_log_data_a) { pline = "a.x, a.y, a.z, timestamp acc\n"; write(g_fd_log_data_a, pline, strlen(pline)); } g_fd_log_data_m = open("/data/misc/sensor/sensor_data_m.log", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (-1 != g_fd_log_data_m) { pline = "m.x, m.y, m.z, timestamp mag\n"; write(g_fd_log_data_m, pline, strlen(pline)); } g_fd_log_data_g = open("/data/misc/sensor/sensor_data_g.log", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (-1 != g_fd_log_data_g) { pline = "g.x, g.y, g.z, timestampe gyro\n"; write(g_fd_log_data_g, pline, strlen(pline)); } } if (data_log_level & DATA_LOG_LEVEL_OUTPUT_VIRTUAL_SENSOR) { g_fd_log_data_vrv = open("/data/misc/sensor/sensor_data_vrv.log", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (-1 != g_fd_log_data_vrv) { pline = "vrv.x, vrv.y, vrv.z, vrv.data3, vrv.data4, timestamp vrv\n"; write(g_fd_log_data_vrv, pline, strlen(pline)); } g_fd_log_data_o = open("/data/misc/sensor/sensor_data_o.log", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (-1 != g_fd_log_data_o) { pline = "o.h, o.p, o.r, timestamp o, accuracy\n"; write(g_fd_log_data_o, pline, strlen(pline)); } g_fd_log_data_vg = open("/data/misc/sensor/sensor_data_vg.log", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (-1 != g_fd_log_data_vg) { pline = "vg.x, vg.y, vg.z, timestamp vg\n"; write(g_fd_log_data_vg, pline, strlen(pline)); } g_fd_log_data_vla = open("/data/misc/sensor/sensor_data_vla.log", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (-1 != g_fd_log_data_vla) { pline = "vla.x, vla.y, vla.z, timestamp vla\n"; write(g_fd_log_data_vla, pline, strlen(pline)); } #if __HAL_VER__ >= __SENSORS_DEVICE_API_VERSION_1_0__ g_fd_log_data_stc = open("/data/misc/sensor/sensor_data_stc.log", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (-1 != g_fd_log_data_stc) { pline = "step counter, time now\n"; write(g_fd_log_data_stc, pline, strlen(pline)); } g_fd_log_data_std = open("/data/misc/sensor/sensor_data_std.log", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (-1 != g_fd_log_data_std) { pline = "step detector, time now\n"; write(g_fd_log_data_std, pline, strlen(pline)); } #endif } #ifdef __UNCALIBRATED_VIRTUAL_SENSOR_SUPPORT__ if (data_log_level & DATA_LOG_LEVEL_OUTPUT_VIRTUAL_SENSOR) { g_fd_log_data_grv = open("/data/misc/sensor/sensor_data_grv.log", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (-1 != g_fd_log_data_grv) { pline = "grv.x, grv.y, grv.z, grv.data3, grv.data4, timestamp grv\n"; write(g_fd_log_data_grv, pline, strlen(pline)); } } if (data_log_level & DATA_LOG_LEVEL_OUTPUT_MU_GU) { g_fd_log_data_gu = open("/data/misc/sensor/sensor_data_gu.log", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (-1 != g_fd_log_data_gu) { pline = ("gu.x, gu.y, gu.z, gu.x_bias, gu.y_bias, gu.z_bias, " "g.x, g.y, g.z, g_filt.x, g_filt.y, g_filt.z, accuracy, timestamp gu\n"); write(g_fd_log_data_gu, pline, strlen(pline)); } g_fd_log_data_mu = open("/data/misc/sensor/sensor_data_mu.log", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (-1 != g_fd_log_data_mu) { pline = ("mu.x, mu.y, mu,z, mu.x_bias, mu.y_bias, mu.z_bias, " "m.x, m.y, m.z, accuracy, timestamp mu\n"); write(g_fd_log_data_mu, pline, strlen(pline)); } } #endif } void data_log_input_to_algo(libraryinput_t all_sensor_data, BS_U32 ts) { int ret = 0; if (-1 != g_fd_log_data_x) { #ifdef __RAM_DATA_LOG_SUPPORT__ if (data_log_level & DATA_LOG_USING_RAM_BUFFER) { ret = snprintf(g_fill_ptr_log_data_x[g_buf_index_log_data_x], 250, "%11u,%d,%d,%d,%11u,%d,%d,%d,%11u,%d,%d,%d,%11u ;\n", ts, all_sensor_data.acc.data.x, all_sensor_data.acc.data.y, all_sensor_data.acc.data.z, all_sensor_data.acc.time_stamp, all_sensor_data.mag.data.x, all_sensor_data.mag.data.y, all_sensor_data.mag.data.z, all_sensor_data.mag.time_stamp, all_sensor_data.gyro.data.x, all_sensor_data.gyro.data.y, all_sensor_data.gyro.data.z, all_sensor_data.gyro.time_stamp ); if (ret > 0) { g_fill_ptr_log_data_x[g_buf_index_log_data_x] += strlen(g_fill_ptr_log_data_x[g_buf_index_log_data_x]); } else { PERR("print string overflow"); } if ( ((g_fill_ptr_log_data_x[g_buf_index_log_data_x] - g_buf_ptr_log_data_x[g_buf_index_log_data_x]) > DATA_LOG_BUF_OVER_LIMIT_X) || (ts > last_data_log_time_x+DATA_LOG_TIMEOUT_X) || g_trig_flag_log_data_x) { g_trig_flag_log_data_x = 0; g_fill_ptr_log_data_x[g_buf_index_log_data_x] = '\0'; write(g_fd_log_data_x, g_buf_ptr_log_data_x[g_buf_index_log_data_x], strlen(g_buf_ptr_log_data_x[g_buf_index_log_data_x])); last_data_log_time_x = ts; g_fill_ptr_log_data_x[g_buf_index_log_data_x] = g_buf_ptr_log_data_x[g_buf_index_log_data_x]; g_buf_index_log_data_x = !g_buf_index_log_data_x; } } else #endif { char line[256] = ""; ret = snprintf(line, ARRAY_SIZE(line) - 1, "%11u,%6d,%6d,%6d,%11u,%6d,%6d,%6d,%11u,%6d,%6d,%6d,%11u\n", ts, all_sensor_data.acc.data.x, all_sensor_data.acc.data.y, all_sensor_data.acc.data.z, all_sensor_data.acc.time_stamp, all_sensor_data.mag.data.x, all_sensor_data.mag.data.y, all_sensor_data.mag.data.z, all_sensor_data.mag.time_stamp, all_sensor_data.gyro.data.x, all_sensor_data.gyro.data.y, all_sensor_data.gyro.data.z, all_sensor_data.gyro.time_stamp ); if (ret > 0) { write(g_fd_log_data_x, line, ret); } } } } /* data log function for sensors with only x,y,z data */ void data_log_output(int fd, sensor_data_t *pdata) { char line[256] = ""; int ret; if (-1 != fd) { struct timeval time_now; gettimeofday (&time_now, NULL); ret = snprintf(line, ARRAY_SIZE(line) - 1, "%f, %f, %f, %lu, %d\n", pdata->data[0],pdata->data[1], pdata->data[2], time_now.tv_sec*1000 + time_now.tv_usec/1000, pdata->status); if (ret > 0) { write(fd, line, ret); } } } /* vrv and grv sensor need to log 5 data */ void data_log_output_vrv(int fd, sensor_data_t *pdata) { char line[256] = ""; int ret; if (-1 != fd) { struct timeval time_now; gettimeofday (&time_now, NULL); ret = snprintf(line, ARRAY_SIZE(line) - 1, "%f, %f, %f, %f, %f, %lu ms\n", pdata->data[0],pdata->data[1], pdata->data[2], pdata->data[3], pdata->data[4], time_now.tv_sec*1000 + time_now.tv_usec/1000); if (ret > 0) { write(fd, line, ret); } } } #ifdef __UNCALIBRATED_VIRTUAL_SENSOR_SUPPORT__ void data_log_output_gu(int fd, sensor_data_t *pdata) { char line[256] = ""; int ret; ts_dataxyzf32 data; BS_U8 status = 0; if (-1 != fd) { struct timeval time_now; gettimeofday (&time_now, NULL); bsx_get_gyrocordata_dps((ts_dataxyzf32*)&data); ret = snprintf(line, ARRAY_SIZE(line) - 1, "%f, %f, %f, %f, %f, %f, %f, %f, %f, ", pdata->uncalibrated_gyro.x_uncalib,pdata->uncalibrated_gyro.y_uncalib,pdata->uncalibrated_gyro.z_uncalib, pdata->uncalibrated_gyro.x_bias, pdata->uncalibrated_gyro.y_bias,pdata->uncalibrated_gyro.z_bias, (float) data.x / (180 / PI),(float) data.y / (180 / PI),(float) data.z / (180 / PI) ); if (ret > 0) { write(fd, line, ret); } bsx_get_gyrofiltdata1_dps((ts_dataxyzf32*)&data); bsx_get_gyrocalibaccuracy(&status); ret = snprintf(line, ARRAY_SIZE(line) - 1, "%f, %f, %f, %d, %lu ms\n", (float) data.x / (180 / PI),(float) data.y / (180 / PI),(float) data.z / (180 / PI), status, time_now.tv_sec*1000 + time_now.tv_usec/1000); if (ret > 0) { write(fd, line, ret); } } } void data_log_output_mu(int fd, sensor_data_t *pdata) { BS_U8 status = 0; ts_dataxyzf32 data; char line[256] = ""; int ret; if (-1 != fd) { struct timeval time_now; gettimeofday (&time_now, NULL); ret = snprintf(line, ARRAY_SIZE(line) - 1, "%f, %f, %f, %f, %f, %f, ", pdata->uncalibrated_magnetic.x_uncalib,pdata->uncalibrated_magnetic.y_uncalib,pdata->uncalibrated_magnetic.z_uncalib, pdata->uncalibrated_magnetic.x_bias, pdata->uncalibrated_magnetic.y_bias,pdata->uncalibrated_magnetic.z_bias); if (ret > 0) { write(fd, line, ret); } bsx_get_magfiltdata1((ts_dataxyzf32*)&data); bsx_get_magcalibaccuracy(&status); ret = snprintf(line, ARRAY_SIZE(line) - 1, "%f, %f, %f, %d, %lu ms\n", data.x,data.y,data.z, status, time_now.tv_sec*1000 + time_now.tv_usec/1000); if (ret > 0) { write(fd, line, ret); } } } #endif #if __HAL_VER__ >= __SENSORS_DEVICE_API_VERSION_1_0__ void data_log_output_step_detect(int fd, uint64_t value) { char line[256] = ""; int ret; if (-1 != fd) { time_t now = time(NULL); struct tm timenow = {0}; char strTmp[50] = {0}; localtime_r(&now, &timenow); strftime(strTmp, 50, "%H:%M:%S", &timenow); ret = snprintf(line, ARRAY_SIZE(line) - 1, "%lld, %s \n", value, strTmp); if (ret > 0) { write(fd, line, ret); } } } #endif #endif