void Sample_XTalkCalibrate(void) { VL6180xDev_t myDev; VL6180x_RangeData_t Range; int XTalkRate; int i, status; /* init device */ MyDev_Init(myDev); status = Sample_Init(myDev); if( status <0 ){ HandleError("Sample_Init fail"); } /* run calibration */ XTalkRate = Sample_XTalkRunCalibration(myDev); /*TODO when possible reset re-init device else set back required scaling/filter*/ VL6180x_FilterSetState(myDev, 1); // turn on wrap around filter again VL6180x_UpscaleSetScaling(myDev, 3); // set scaling /* apply cross talk */ status = VL6180x_SetXTalkCompensationRate(myDev, XTalkRate); if( status<0 ){ /* ignore warning but not error */ HandleError("VL6180x_WrWord fail"); } for( i=0; i< 10; i++){ status = VL6180x_RangePollMeasurement(myDev, &Range); MyDev_ShowRange(myDev, Range.range_mm); } }
static int stmvl6180_start(struct stmvl6180_data *data, uint8_t scaling, init_mode_e mode) { int rc = 0; vl6180_dbgmsg("Enter\n"); /* Power up */ rc = data->pmodule_func_tbl->power_up(&data->client_object, &data->reset); if (rc) { vl6180_errmsg("%d,error rc %d\n", __LINE__, rc); return rc; } /* init */ rc = stmvl6180_init_client(data); if (rc) { vl6180_errmsg("%d, error rc %d\n", __LINE__, rc); data->pmodule_func_tbl->power_down(&data->client_object); return -EINVAL; } /* prepare */ VL6180x_Prepare(vl6180x_dev); VL6180x_UpscaleSetScaling(vl6180x_dev, scaling); /* check mode */ if (mode != NORMAL_MODE) { #if VL6180x_WRAP_AROUND_FILTER_SUPPORT /* turn off wrap around filter */ VL6180x_FilterSetState(vl6180x_dev, 0); #endif VL6180x_SetXTalkCompensationRate(vl6180x_dev, 0); VL6180x_UpdateByte(vl6180x_dev, SYSRANGE_RANGE_CHECK_ENABLES, ~RANGE_CHECK_RANGE_ENABLE_MASK, 0); } if (mode == OFFSETCALIB_MODE) VL6180x_SetOffsetCalibrationData(vl6180x_dev, 0); /* start - single shot mode */ VL6180x_RangeSetSystemMode(vl6180x_dev, MODE_START_STOP|MODE_SINGLESHOT); data->ps_is_singleshot = 1; data->enable_ps_sensor = 1; /* enable work handler */ stmvl6180_schedule_handler(data); vl6180_dbgmsg("End\n"); return rc; }
/* * misc device file operation functions */ static int stmvl6180_ioctl_handler(struct file *file, unsigned int cmd, unsigned long arg, void __user *p) { int rc = 0; unsigned int xtalkint = 0; int8_t offsetint = 0; struct stmvl6180_data *data = gp_vl6180_data; struct stmvl6180_register reg; if (!data) return -EINVAL; vl6180_dbgmsg("Enter enable_ps_sensor:%d\n", data->enable_ps_sensor); switch (cmd) { /* enable */ case VL6180_IOCTL_INIT: pr_err("%s: VL6180_IOCTL_INIT\n", __func__); /* turn on tof sensor only if it's not enabled by other client */ if (data->enable_ps_sensor == 0) { /* to start */ stmvl6180_start(data, 3, NORMAL_MODE); } else rc = -EINVAL; break; /* crosstalk calibration */ case VL6180_IOCTL_XTALKCALB: vl6180_dbgmsg("VL6180_IOCTL_XTALKCALB\n"); /* turn on tof sensor only if it's not enabled by other client */ if (data->enable_ps_sensor == 0) { /* to start */ stmvl6180_start(data, 3, XTALKCALIB_MODE); } else rc = -EINVAL; break; /* set up Xtalk value */ case VL6180_IOCTL_SETXTALK: vl6180_dbgmsg("VL6180_IOCTL_SETXTALK\n"); if (copy_from_user(&xtalkint, (unsigned int *)p, sizeof(unsigned int))) { vl6180_errmsg("%d, fail\n", __LINE__); return -EFAULT; } vl6180_dbgmsg("SETXTALK as 0x%x\n", xtalkint); #ifdef CALIBRATION_FILE xtalk_calib = xtalkint; stmvl6180_write_xtalk_calibration_file(); #endif VL6180x_SetXTalkCompensationRate(vl6180x_dev, xtalkint); break; /* offset calibration */ case VL6180_IOCTL_OFFCALB: vl6180_dbgmsg("VL6180_IOCTL_OFFCALB\n"); if (data->enable_ps_sensor == 0) { /* to start */ stmvl6180_start(data, 3, OFFSETCALIB_MODE); } else rc = -EINVAL; break; /* set up offset value */ case VL6180_IOCTL_SETOFFSET: vl6180_dbgmsg("VL6180_IOCTL_SETOFFSET\n"); if (copy_from_user(&offsetint, (int8_t *)p, sizeof(int8_t))) { vl6180_errmsg("%d, fail\n", __LINE__); return -EFAULT; } vl6180_dbgmsg("SETOFFSET as %d\n", offsetint); #ifdef CALIBRATION_FILE offset_calib = offsetint; stmvl6180_write_offset_calibration_file(); #endif VL6180x_SetOffsetCalibrationData(vl6180x_dev, offsetint); break; /* disable */ case VL6180_IOCTL_STOP: vl6180_errmsg("VL6180_IOCTL_STOP\n"); /* turn off tof sensor only if it's enabled by other client */ if (data->enable_ps_sensor == 1) { data->enable_ps_sensor = 0; /* to stop */ stmvl6180_stop(data); } break; /* Get all range data */ case VL6180_IOCTL_GETDATAS: vl6180_dbgmsg("VL6180_IOCTL_GETDATAS\n"); if (copy_to_user((VL6180x_RangeData_t *)p, &(data->rangeData), sizeof(VL6180x_RangeData_t))) { vl6180_errmsg("%d, fail\n", __LINE__); return -EFAULT; } break; case VL6180_IOCTL_REGISTER: vl6180_dbgmsg("VL6180_IOCTL_REGISTER\n"); if (copy_from_user(®, (struct stmvl6180_register *)p, sizeof(struct stmvl6180_register))) { vl6180_errmsg("%d, fail\n", __LINE__); return -EFAULT; } reg.status = 0; switch (reg.reg_bytes) { case(4): if (reg.is_read) reg.status = VL6180x_RdDWord(vl6180x_dev, (uint16_t)reg.reg_index, ®.reg_data); else reg.status = VL6180x_WrDWord(vl6180x_dev, (uint16_t)reg.reg_index, reg.reg_data); break; case(2): if (reg.is_read) reg.status = VL6180x_RdWord(vl6180x_dev, (uint16_t)reg.reg_index, (uint16_t *)®.reg_data); else reg.status = VL6180x_WrWord(vl6180x_dev, (uint16_t)reg.reg_index, (uint16_t)reg.reg_data); break; case(1): if (reg.is_read) reg.status = VL6180x_RdByte(vl6180x_dev, (uint16_t)reg.reg_index, (uint8_t *)®.reg_data); else reg.status = VL6180x_WrByte(vl6180x_dev, (uint16_t)reg.reg_index, (uint8_t)reg.reg_data); break; default: reg.status = -1; } if (copy_to_user((struct stmvl6180_register *)p, ®, sizeof(struct stmvl6180_register))) { vl6180_errmsg("%d, fail\n", __LINE__); return -EFAULT; } break; default: rc = -EINVAL; break; } return rc; }
static void stmvl6180_read_calibration_file(void) { struct file *f; char buf[8]; mm_segment_t fs; int i, is_sign = 0; if(gp_vl6180_data->offset_buf.file_opened == true) { vl6180_dbgmsg("offset_calib as %d\n", gp_vl6180_data->offset_buf.value); VL6180x_SetOffsetCalibrationData(vl6180x_dev, gp_vl6180_data->offset_buf.value); } else { f = filp_open("/persist/calibration/offset", O_RDONLY, 0); if (f != NULL && !IS_ERR(f) && f->f_dentry != NULL) { fs = get_fs(); set_fs(get_ds()); /* init the buffer with 0 */ for (i = 0; i < 8; i++) buf[i] = 0; f->f_op->read(f, buf, 8, &f->f_pos); set_fs(fs); vl6180_dbgmsg("offset as:%s, buf[0]:%c\n", buf, buf[0]); offset_calib = 0; for (i = 0; i < 8; i++) { if (i == 0 && buf[0] == '-') is_sign = 1; else if (buf[i] >= '0' && buf[i] <= '9') offset_calib = offset_calib * 10 + (buf[i] - '0'); else break; } if (is_sign == 1) offset_calib = -1 * offset_calib; vl6180_dbgmsg("file open offset_calib as %d\n", offset_calib); gp_vl6180_data->offset_buf.file_opened = true; gp_vl6180_data->offset_buf.value = offset_calib; VL6180x_SetOffsetCalibrationData(vl6180x_dev, offset_calib); filp_close(f, NULL); } else { gp_vl6180_data->offset_buf.file_opened = true; gp_vl6180_data->offset_buf.value = 0; vl6180_errmsg("no offset calibration file exist!\n"); } } is_sign = 0; if(gp_vl6180_data->xtalk_buf.file_opened == true) { vl6180_dbgmsg("xtalk_calib as %d\n", gp_vl6180_data->xtalk_buf.value); /* set up threshold ignore */ if ((gp_vl6180_data->xtalk_buf.value+13) < 64 ) VL6180x_WrWord(vl6180x_dev, SYSRANGE_RANGE_IGNORE_THRESHOLD, 64); /* 0.5Mcps */ else VL6180x_WrWord(vl6180x_dev, SYSRANGE_RANGE_IGNORE_THRESHOLD, (gp_vl6180_data->xtalk_buf.value+13)); /* +0.1Mcps */ VL6180x_WrByte(vl6180x_dev, SYSRANGE_RANGE_IGNORE_VALID_HEIGHT, 100); VL6180x_UpdateByte(vl6180x_dev, SYSRANGE_RANGE_CHECK_ENABLES, ~RANGE_CHECK_RANGE_ENABLE_MASK, RANGE_CHECK_RANGE_ENABLE_MASK); /* setup xtalk compensation rate */ VL6180x_SetXTalkCompensationRate(vl6180x_dev, gp_vl6180_data->xtalk_buf.value); } else { f = filp_open("/persist/calibration/xtalk", O_RDONLY, 0); if (f != NULL && !IS_ERR(f) && f->f_dentry != NULL) { fs = get_fs(); set_fs(get_ds()); /* init the buffer with 0 */ for (i = 0; i < 8; i++) buf[i] = 0; f->f_op->read(f, buf, 8, &f->f_pos); set_fs(fs); vl6180_dbgmsg("xtalk as:%s, buf[0]:%c\n", buf, buf[0]); xtalk_calib = 0; for (i = 0; i < 8; i++) { if (i == 0 && buf[0] == '-') is_sign = 1; else if (buf[i] >= '0' && buf[i] <= '9') xtalk_calib = xtalk_calib * 10 + (buf[i] - '0'); else break; } if (is_sign == 1) xtalk_calib = -1 * xtalk_calib; vl6180_dbgmsg("file open xtalk_calib as %d\n", xtalk_calib); gp_vl6180_data->xtalk_buf.file_opened = true; gp_vl6180_data->xtalk_buf.value = xtalk_calib; /* set up threshold ignore */ if ((xtalk_calib+13) < 64 ) VL6180x_WrWord(vl6180x_dev, SYSRANGE_RANGE_IGNORE_THRESHOLD, 64); /* 0.5Mcps */ else VL6180x_WrWord(vl6180x_dev, SYSRANGE_RANGE_IGNORE_THRESHOLD, (xtalk_calib+13)); /* +0.1Mcps */ VL6180x_WrByte(vl6180x_dev, SYSRANGE_RANGE_IGNORE_VALID_HEIGHT, 100); VL6180x_UpdateByte(vl6180x_dev, SYSRANGE_RANGE_CHECK_ENABLES, ~RANGE_CHECK_RANGE_ENABLE_MASK, RANGE_CHECK_RANGE_ENABLE_MASK); /* setup xtalk compensation rate */ VL6180x_SetXTalkCompensationRate(vl6180x_dev, xtalk_calib); filp_close(f, NULL); } else { gp_vl6180_data->xtalk_buf.file_opened = true; gp_vl6180_data->xtalk_buf.value = XTALK_CALIBRATION_DEFAULT; vl6180_errmsg("no xtalk calibration file exist!\n"); } } return; }