int BMA180::init() { int ret = ERROR; /* do SPI init (and probe) first */ if (SPI::init() != OK) goto out; /* allocate basic report buffers */ _reports = new RingBuffer(2, sizeof(accel_report)); if (_reports == nullptr) goto out; /* advertise sensor topic */ struct accel_report zero_report; memset(&zero_report, 0, sizeof(zero_report)); _accel_topic = orb_advertise(ORB_ID(sensor_accel), &zero_report); /* perform soft reset (p48) */ write_reg(ADDR_RESET, SOFT_RESET); /* wait 10 ms (datasheet incorrectly lists 10 us on page 49) */ usleep(10000); /* enable writing to chip config */ modify_reg(ADDR_CTRL_REG0, 0, REG0_WRITE_ENABLE); /* disable I2C interface */ modify_reg(ADDR_HIGH_DUR, HIGH_DUR_DIS_I2C, 0); /* switch to low-noise mode */ modify_reg(ADDR_TCO_Z, TCO_Z_MODE_MASK, 0); /* disable 12-bit mode */ modify_reg(ADDR_OFFSET_T, OFFSET_T_READOUT_12BIT, 0); /* disable shadow-disable mode */ modify_reg(ADDR_GAIN_Y, GAIN_Y_SHADOW_DIS, 0); /* disable writing to chip config */ modify_reg(ADDR_CTRL_REG0, REG0_WRITE_ENABLE, 0); if (set_range(4)) warnx("Failed setting range"); if (set_lowpass(75)) warnx("Failed setting lowpass"); if (read_reg(ADDR_CHIP_ID) == CHIP_ID) { ret = OK; } else { ret = ERROR; } out: return ret; }
int BMA180::ioctl(struct file *filp, int cmd, unsigned long arg) { switch (cmd) { case SENSORIOCSPOLLRATE: { switch (arg) { /* switching to manual polling */ case SENSOR_POLLRATE_MANUAL: stop(); _call_interval = 0; return OK; /* external signalling not supported */ case SENSOR_POLLRATE_EXTERNAL: /* zero would be bad */ case 0: return -EINVAL; /* set default/max polling rate */ case SENSOR_POLLRATE_MAX: case SENSOR_POLLRATE_DEFAULT: /* XXX 500Hz is just a wild guess */ return ioctl(filp, SENSORIOCSPOLLRATE, 500); /* adjust to a legal polling interval in Hz */ default: { /* do we need to start internal polling? */ bool want_start = (_call_interval == 0); /* convert hz to hrt interval via microseconds */ unsigned ticks = 1000000 / arg; /* check against maximum sane rate */ if (ticks < 1000) return -EINVAL; /* update interval for next measurement */ /* XXX this is a bit shady, but no other way to adjust... */ _call.period = _call_interval = ticks; /* if we need to start the poll state machine, do it */ if (want_start) start(); return OK; } } } case SENSORIOCGPOLLRATE: if (_call_interval == 0) return SENSOR_POLLRATE_MANUAL; return 1000000 / _call_interval; case SENSORIOCSQUEUEDEPTH: { /* account for sentinel in the ring */ arg++; /* lower bound is mandatory, upper bound is a sanity check */ if ((arg < 2) || (arg > 100)) return -EINVAL; /* allocate new buffer */ struct accel_report *buf = new struct accel_report[arg]; if (nullptr == buf) return -ENOMEM; /* reset the measurement state machine with the new buffer, free the old */ stop(); delete[] _reports; _num_reports = arg; _reports = buf; start(); return OK; } case SENSORIOCGQUEUEDEPTH: return _num_reports -1; case SENSORIOCRESET: /* XXX implement */ return -EINVAL; case ACCELIOCSSAMPLERATE: /* sensor sample rate is not (really) adjustable */ return -EINVAL; case ACCELIOCGSAMPLERATE: return 1200; /* always operating in low-noise mode */ case ACCELIOCSLOWPASS: return set_lowpass(arg); case ACCELIOCGLOWPASS: return _current_lowpass; case ACCELIOCSSCALE: /* copy scale in */ memcpy(&_accel_scale, (struct accel_scale*) arg, sizeof(_accel_scale)); return OK; case ACCELIOCGSCALE: /* copy scale out */ memcpy((struct accel_scale*) arg, &_accel_scale, sizeof(_accel_scale)); return OK; case ACCELIOCSRANGE: return set_range(arg); case ACCELIOCGRANGE: return _current_range; default: /* give it to the superclass */ return SPI::ioctl(filp, cmd, arg); } }
int BMA180::ioctl(struct file *filp, int cmd, unsigned long arg) { switch (cmd) { case SENSORIOCSPOLLRATE: { switch (arg) { /* switching to manual polling */ case SENSOR_POLLRATE_MANUAL: stop(); _call_interval = 0; return OK; /* external signalling not supported */ case SENSOR_POLLRATE_EXTERNAL: /* zero would be bad */ case 0: return -EINVAL; /* set default/max polling rate */ case SENSOR_POLLRATE_MAX: case SENSOR_POLLRATE_DEFAULT: /* With internal low pass filters enabled, 250 Hz is sufficient */ return ioctl(filp, SENSORIOCSPOLLRATE, 250); /* adjust to a legal polling interval in Hz */ default: { /* do we need to start internal polling? */ bool want_start = (_call_interval == 0); /* convert hz to hrt interval via microseconds */ unsigned ticks = 1000000 / arg; /* check against maximum sane rate */ if (ticks < 1000) { return -EINVAL; } /* update interval for next measurement */ /* XXX this is a bit shady, but no other way to adjust... */ _call.period = _call_interval = ticks; /* if we need to start the poll state machine, do it */ if (want_start) { start(); } return OK; } } } case SENSORIOCGPOLLRATE: if (_call_interval == 0) { return SENSOR_POLLRATE_MANUAL; } return 1000000 / _call_interval; case SENSORIOCSQUEUEDEPTH: { /* lower bound is mandatory, upper bound is a sanity check */ if ((arg < 2) || (arg > 100)) { return -EINVAL; } irqstate_t flags = px4_enter_critical_section(); if (!_reports->resize(arg)) { px4_leave_critical_section(flags); return -ENOMEM; } px4_leave_critical_section(flags); return OK; } case SENSORIOCGQUEUEDEPTH: return _reports->size(); case SENSORIOCRESET: /* XXX implement */ return -EINVAL; case ACCELIOCSSAMPLERATE: /* sensor sample rate is not (really) adjustable */ return -EINVAL; case ACCELIOCGSAMPLERATE: return 1200; /* always operating in low-noise mode */ case ACCELIOCSLOWPASS: return set_lowpass(arg); case ACCELIOCGLOWPASS: return _current_lowpass; case ACCELIOCSSCALE: /* copy scale in */ memcpy(&_accel_scale, (struct accel_calibration_s *) arg, sizeof(_accel_scale)); return OK; case ACCELIOCGSCALE: /* copy scale out */ memcpy((struct accel_calibration_s *) arg, &_accel_scale, sizeof(_accel_scale)); return OK; case ACCELIOCSRANGE: return set_range(arg); case ACCELIOCGRANGE: return _current_range; default: /* give it to the superclass */ return SPI::ioctl(filp, cmd, arg); } }
int BMA180::init() { int ret = PX4_ERROR; /* do SPI init (and probe) first */ if (SPI::init() != OK) { goto out; } /* allocate basic report buffers */ _reports = new ringbuffer::RingBuffer(2, sizeof(accel_report)); if (_reports == nullptr) { goto out; } /* perform soft reset (p48) */ write_reg(ADDR_RESET, SOFT_RESET); /* wait 10 ms (datasheet incorrectly lists 10 us on page 49) */ usleep(10000); /* enable writing to chip config */ modify_reg(ADDR_CTRL_REG0, 0, REG0_WRITE_ENABLE); /* disable I2C interface */ modify_reg(ADDR_HIGH_DUR, HIGH_DUR_DIS_I2C, 0); /* switch to low-noise mode */ modify_reg(ADDR_TCO_Z, TCO_Z_MODE_MASK, 0); /* disable 12-bit mode */ modify_reg(ADDR_OFFSET_T, OFFSET_T_READOUT_12BIT, 0); /* disable shadow-disable mode */ modify_reg(ADDR_GAIN_Y, GAIN_Y_SHADOW_DIS, 0); /* disable writing to chip config */ modify_reg(ADDR_CTRL_REG0, REG0_WRITE_ENABLE, 0); if (set_range(4)) { warnx("Failed setting range"); } if (set_lowpass(75)) { warnx("Failed setting lowpass"); } if (read_reg(ADDR_CHIP_ID) == CHIP_ID) { ret = OK; } else { ret = PX4_ERROR; } _class_instance = register_class_devname(ACCEL_DEVICE_PATH); /* advertise sensor topic, measure manually to initialize valid report */ measure(); if (_class_instance == CLASS_DEVICE_PRIMARY) { struct accel_report arp; _reports->get(&arp); /* measurement will have generated a report, publish */ _accel_topic = orb_advertise(ORB_ID(sensor_accel), &arp); } out: return ret; }