123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- #include "AP_RangeFinder_PulsedLightLRF.h"
- #include <utility>
- #include <stdio.h>
- #include <AP_HAL/AP_HAL.h>
- #include <AP_HAL/utility/sparse-endian.h>
- extern const AP_HAL::HAL& hal;
- #define LL40LS_MEASURE_REG 0x00
- #define LL40LS_SIG_COUNT_VAL 0x02
- #define LL40LS_DISTHIGH_REG 0x0F
- #define LL40LS_COUNT 0x11
- #define LL40LS_HW_VERSION 0x41
- #define LL40LS_INTERVAL 0x45
- #define LL40LS_SW_VERSION 0x4f
- #define LL40LS_MSRREG_RESET 0x00
- #define LL40LS_AUTO_INCREMENT 0x80
- #define LL40LS_COUNT_CONTINUOUS 0xff
- #define LL40LS_MSRREG_ACQUIRE 0x04
- #define LL40LS_ADDR 0x62
- AP_RangeFinder_PulsedLightLRF::AP_RangeFinder_PulsedLightLRF(uint8_t bus,
- RangeFinder::RangeFinder_State &_state,
- AP_RangeFinder_Params &_params,
- RangeFinder::RangeFinder_Type _rftype)
- : AP_RangeFinder_Backend(_state, _params)
- , _dev(hal.i2c_mgr->get_device(bus, LL40LS_ADDR))
- , rftype(_rftype)
- {
- }
- AP_RangeFinder_Backend *AP_RangeFinder_PulsedLightLRF::detect(uint8_t bus,
- RangeFinder::RangeFinder_State &_state,
- AP_RangeFinder_Params &_params,
- RangeFinder::RangeFinder_Type rftype)
- {
- AP_RangeFinder_PulsedLightLRF *sensor
- = new AP_RangeFinder_PulsedLightLRF(bus, _state, _params, rftype);
- if (!sensor ||
- !sensor->init()) {
- delete sensor;
- return nullptr;
- }
- return sensor;
- }
- void AP_RangeFinder_PulsedLightLRF::timer(void)
- {
- if (check_reg_counter++ == 10) {
- check_reg_counter = 0;
- if (!_dev->check_next_register()) {
-
-
- _dev->write_register(LL40LS_MEASURE_REG, LL40LS_MSRREG_ACQUIRE);
- }
- }
- switch (phase) {
- case PHASE_COLLECT: {
- be16_t val;
-
- if (_dev->read_registers(LL40LS_DISTHIGH_REG | LL40LS_AUTO_INCREMENT, (uint8_t*)&val, sizeof(val))) {
- uint16_t _distance_cm = be16toh(val);
-
- if (abs(_distance_cm - last_distance_cm) < 100) {
- state.distance_cm = _distance_cm;
- state.last_reading_ms = AP_HAL::millis();
- update_status();
- }
- last_distance_cm = _distance_cm;
- } else {
- set_status(RangeFinder::RangeFinder_NoData);
- }
- if (!v2_hardware) {
-
- phase = PHASE_MEASURE;
- }
- if (!v3hp_hardware) {
-
- break;
- }
- }
- FALLTHROUGH;
- case PHASE_MEASURE:
- if (_dev->write_register(LL40LS_MEASURE_REG, LL40LS_MSRREG_ACQUIRE)) {
- phase = PHASE_COLLECT;
- }
- break;
- }
- }
- struct settings_table {
- uint8_t reg;
- uint8_t value;
- };
- static const struct settings_table settings_v1[] = {
- { LL40LS_MEASURE_REG, LL40LS_MSRREG_RESET },
- };
- static const struct settings_table settings_v2[] = {
- { LL40LS_INTERVAL, 0x28 },
- { LL40LS_COUNT, LL40LS_COUNT_CONTINUOUS },
- { LL40LS_MEASURE_REG, LL40LS_MSRREG_ACQUIRE },
- };
- static const struct settings_table settings_v3hp[] = {
- { LL40LS_SIG_COUNT_VAL, 0x80 },
- };
- bool AP_RangeFinder_PulsedLightLRF::init(void)
- {
- if (!_dev || !_dev->get_semaphore()->take(HAL_SEMAPHORE_BLOCK_FOREVER)) {
- return false;
- }
- _dev->set_retries(3);
-
- _dev->set_split_transfers(true);
- if (rftype == RangeFinder::RangeFinder_TYPE_PLI2CV3) {
- v2_hardware = true;
- } else if (rftype == RangeFinder::RangeFinder_TYPE_PLI2CV3HP) {
- v3hp_hardware = true;
- } else {
-
- if (!(_dev->read_registers(LL40LS_HW_VERSION, &hw_version, 1) &&
- hw_version > 0 &&
- _dev->read_registers(LL40LS_SW_VERSION, &sw_version, 1) &&
- sw_version > 0)) {
- printf("PulsedLightI2C: bad version 0x%02x 0x%02x\n", (unsigned)hw_version, (unsigned)sw_version);
-
- goto failed;
- }
- v2_hardware = (hw_version >= 0x15);
- }
-
- const struct settings_table *table;
- uint8_t num_settings;
- if (v2_hardware) {
- table = settings_v2;
- num_settings = sizeof(settings_v2) / sizeof(settings_table);
- phase = PHASE_COLLECT;
- } else if (v3hp_hardware) {
- table = settings_v3hp;
- num_settings = sizeof(settings_v3hp) / sizeof(settings_table);
- phase = PHASE_MEASURE;
- } else {
- table = settings_v1;
- num_settings = sizeof(settings_v1) / sizeof(settings_table);
- phase = PHASE_MEASURE;
- }
- _dev->setup_checked_registers(num_settings);
- for (uint8_t i = 0; i < num_settings; i++) {
- if (!_dev->write_register(table[i].reg, table[i].value, true)) {
- goto failed;
- }
- }
- printf("Found LidarLite device=0x%x v2=%d v3hp=%d\n", _dev->get_bus_id(), (int)v2_hardware, (int)v3hp_hardware);
-
- _dev->get_semaphore()->give();
- _dev->register_periodic_callback(20000,
- FUNCTOR_BIND_MEMBER(&AP_RangeFinder_PulsedLightLRF::timer, void));
- return true;
- failed:
- _dev->get_semaphore()->give();
- return false;
- }
|