LCOV - code coverage report
Current view: top level - AP_RangeFinder - AP_RangeFinder_Ainstein_LR_D1.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 11 11 100.0 %
Date: 2026-09-09 11:02:08 Functions: 6 6 100.0 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include "AP_RangeFinder_config.h"
       4             : 
       5             : /*
       6             :  questions:
       7             :  - bug on page 22 on malfunction codes
       8             :  - fixed length seems strange at 28 bytes
       9             :  - definition of snr field is missing in documentation
      10             :  - roll/pitch limits are in conflict, 3.2 vs 
      11             : */
      12             : #if AP_RANGEFINDER_AINSTEIN_LR_D1_ENABLED
      13             : 
      14             : #include "AP_RangeFinder.h"
      15             : #include "AP_RangeFinder_Backend_Serial.h"
      16             : 
      17             : class AP_RangeFinder_Ainstein_LR_D1 : public AP_RangeFinder_Backend_Serial
      18             : {
      19             : 
      20             : public:
      21             : 
      22           3 :     static AP_RangeFinder_Backend_Serial *create(
      23             :         RangeFinder::RangeFinder_State &_state,
      24             :         AP_RangeFinder_Params &_params) {
      25           3 :         return NEW_NOTHROW AP_RangeFinder_Ainstein_LR_D1(_state, _params);
      26             :     }
      27             : 
      28             : protected:
      29             : 
      30        1767 :     MAV_DISTANCE_SENSOR _get_mav_distance_sensor_type() const override {
      31        1767 :         return MAV_DISTANCE_SENSOR_RADAR;
      32             :     }
      33             : 
      34           3 :     uint32_t initial_baudrate(uint8_t serial_instance) const override {
      35           3 :         return 115200;
      36             :     }
      37             : 
      38             :     // make sure readings go out-of-range when necessary
      39      119488 :     float max_distance() const override  {
      40      119488 :         return MIN(AP_RangeFinder_Backend::max_distance(), 500);
      41             :     }
      42        3407 :     float min_distance() const override {
      43        3407 :         return MAX(AP_RangeFinder_Backend::min_distance(), 0.7);
      44             :     }
      45             : 
      46             : private:
      47             : 
      48             :     using AP_RangeFinder_Backend_Serial::AP_RangeFinder_Backend_Serial;
      49             : 
      50             :     // get_reading - read all samples, return last.  The device sends at
      51             :     // 40Hz, so there should only ever be one sample available.  Assuming
      52             :     // that something's gone wrong with scheduling, we will simply return
      53             :     // the last.
      54             :     bool get_reading(float &reading_m) override;
      55             : 
      56             :     // get a reading
      57             :     bool get_one_reading(float &reading_m);
      58             : 
      59             :     // 0 is no return value, 100 is perfect.  false means signal
      60             :     // quality is not available
      61        3536 :     int8_t get_signal_quality_pct() const override { return signal_quality_pct; };
      62             : 
      63             :     static void report_malfunction(const uint16_t _malfunction_alert_, const uint16_t _malfunction_alert_prev_);
      64             : 
      65             :     enum class MalfunctionAlert : uint8_t {
      66             :         Temperature       = (1U << 0),  // 0x01
      67             :         Voltage           = (1U << 1),  // 0x02
      68             :         IFSignalSaturation= (1U << 6),  // 0x40
      69             :         AltitudeReading   = (1U << 7),  // 0x80
      70             :     };
      71             :     // see page 25
      72             :     static void report_malfunction_v19000(const uint16_t malfunction_alert, const uint16_t malfunction_alert_prev);
      73             :     enum class MalfunctionAlert_v19000 : uint16_t {
      74             :         MCUTemperature         = (1U << 0),   // 0x0001
      75             :         MCUVoltage             = (1U << 1),   // 0x0002
      76             :         IFTemperature          = (1U << 4),   // 0x0010
      77             :         IFSignalSaturation     = (1U << 7),   // 0x0080
      78             :         Software               = (1U << 8),   // 0x0100
      79             :         AltitudeReadingOverflow= (1U << 10),  // 0x0400
      80             :         Voltage                = (1U << 15),  // 0x8000
      81             :     };
      82             : 
      83             :     // Ainstein LR-D1 firmware emits a single message with the same
      84             :     // header bytes, size, device_id and length, but different
      85             :     // meanings for some of the fields!  We differentiate between the
      86             :     // "original" packet and the new-style packet by looking at "byte
      87             :     // 12" (at offset 11).  If it is not 0xff then we consider the
      88             :     // packet to be of the "v19.0.0" format.  In this new format there
      89             :     // is no object count, there are 16 malfunction alert bits, "byte
      90             :     // 12" contains the unit's self-assessed height-valid information
      91             :     // and a lot of fields move from "other object readings" to
      92             :     // "reserved"
      93             :     union LRD1Union {
      94             :         struct PACKED LRD1Packet {
      95             :             uint8_t header_msb;
      96             :             uint8_t header_lsb;
      97             :             uint8_t device_id;
      98             :             uint8_t length;  // "fixed as 28 bytes"
      99             :             uint8_t malfunction_alert;
     100             :             uint8_t objects_number;  // "fixed as 1"
     101             :             uint16_t object1_alt;
     102             :             uint8_t object1_snr;
     103             :             uint16_t object1_velocity;
     104             :             uint8_t unused[20];
     105             :             uint8_t checksum;  // (data4+data5+…+data29+data31) bitwise-AND with 0xFF
     106             :         } packet;
     107             :         struct PACKED LRD1Packet_v19000 {
     108             :             uint8_t header_msb;
     109             :             uint8_t header_lsb;
     110             :             uint8_t device_id;
     111             :             uint8_t length;  // "fixed as 28 bytes"
     112             :             uint16_t malfunction_alert;
     113             :             uint16_t object1_alt;
     114             :             uint8_t object1_snr;
     115             :             uint16_t object1_velocity;
     116             :             uint8_t altitude_valid;
     117             :             uint8_t reserved[19];
     118             :             uint8_t checksum;  // (data4+data5+…+data29+data31) bitwise-AND with 0xFF
     119             :         } packet_v19000;
     120             :         uint8_t buffer[64];  // each packet is 32 bytes long
     121             : 
     122             :         // return checksum calculated from data in buffer
     123             :         uint8_t calculate_checksum() const;
     124             :     } u;
     125             :     uint8_t buffer_used;
     126             : 
     127             :     uint16_t malfunction_alert_prev;
     128             :     uint32_t malfunction_alert_last_send_ms;
     129             : 
     130             :     int8_t signal_quality_pct = RangeFinder::SIGNAL_QUALITY_UNKNOWN;    
     131             : 
     132             :     // ensures that there is a packet starting at offset 0 in the
     133             :     // buffer.  If that's not the case this returns false.  Search
     134             :     // starts at offset start in the buffer - if a packet header is
     135             :     // found at a non-zero offset then the data is moved to the start
     136             :     // of the buffer.
     137             :     bool move_signature_in_buffer(uint8_t start);
     138             : };
     139             : #endif  // AP_RANGEFINDER_AINSTEIN_LR_D1_ENABLED

Generated by: LCOV version 1.14