LCOV - code coverage report
Current view: top level - SITL - SIM_TFS20L.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 35 43 81.4 %
Date: 2026-09-09 11:02:08 Functions: 2 2 100.0 %

          Line data    Source code
       1             : #include "SIM_TFS20L.h"
       2             : #include "SITL/SIM_Aircraft.h"
       3             : #include <AP_HAL/AP_HAL.h>
       4             : #include <AP_Math/AP_Math.h>
       5             : #include <cmath>
       6             : 
       7             : #if AP_SIM_TFS20L_ENABLED
       8             : 
       9             : using namespace SITL;
      10             : 
      11             : // Register addresses matching real sensor
      12             : static const uint8_t REG_DIST_LOW = 0x00;
      13             : static const uint8_t REG_DIST_HIGH = 0x01;
      14             : static const uint8_t REG_AMP_LOW = 0x02;
      15             : static const uint8_t REG_AMP_HIGH = 0x03;
      16             : static const uint8_t REG_VERSION_MAJOR = 0x0C;
      17             : 
      18             : // Limits matching real sensor
      19             : static const uint16_t MAX_DIST_CM = 2000;  // 20m
      20             : static const uint16_t MIN_DIST_CM = 1;     // 1cm
      21             : static const uint16_t UPDATE_RATE_HZ = 20; // Sensor update rate
      22             : 
      23   178759942 : void TFS20L::update(const class Aircraft &aircraft)  
      24             : {
      25             :     // Rate limit updates to match real sensor (20Hz)
      26   178759942 :     const uint32_t now_ms = AP_HAL::millis();
      27   178759942 :     if (now_ms - last_update_ms < (1000U / UPDATE_RATE_HZ)) {
      28   175783114 :         return;
      29             :     }
      30     2976828 :     last_update_ms = now_ms;
      31             : 
      32             :     // Get range and convert to cm for checking limits
      33     2976828 :     rangefinder_range = aircraft.rangefinder_range();
      34             :     
      35             :     // Check for invalid readings first (infinite or negative)
      36             :     // Also check before casting to uint16_t to avoid overflow (>655m would wrap)
      37     2976828 :     if (rangefinder_range <= 0 || rangefinder_range > (MAX_DIST_CM * 0.01f)) {
      38     1433666 :         rangefinder_range = 0;  // Will trigger out of range
      39     1433666 :         strength = 0;          // Low strength for invalid reading
      40     1433666 :         return;
      41             :     }
      42             :     
      43     1543162 :     const uint16_t range_cm = rangefinder_range * 100.0f;
      44             :     
      45             :     // Apply real sensor limits (should always be in range due to check above)
      46     1543162 :     if (range_cm < MIN_DIST_CM) {
      47       72992 :         rangefinder_range = 0;  // Will trigger out of range
      48       72992 :         strength = 0;          // Low strength for invalid reading
      49             :     } else {
      50             :         // Simulate decreasing signal strength with distance
      51     1470170 :         const uint32_t str = 65535 - (range_cm * 20);
      52     1470170 :         strength = str < MIN_STRENGTH ? MIN_STRENGTH : (str > 65535 ? 65535 : str);
      53             :     }
      54             : }
      55             : 
      56        1399 : int TFS20L::rdwr(I2C::i2c_rdwr_ioctl_data *&data)
      57             : {
      58        1399 :     if (data->nmsgs == 1) {
      59             :         // Register selection
      60           0 :         reg = data->msgs[0].buf[0];
      61           0 :         return 0;
      62             :     }
      63             : 
      64        1399 :     if ((data->nmsgs != 2) || !(data->msgs[1].flags & I2C_M_RD)) {
      65           0 :         return -1;
      66             :     }
      67             : 
      68        1399 :     const uint16_t dist_cm = rangefinder_range * 100.0f;
      69             : 
      70             :     // Handle register reads
      71        1399 :     switch (reg) {
      72        1399 :         case REG_DIST_LOW:
      73             :         case REG_DIST_HIGH:
      74             :         case REG_AMP_LOW:
      75             :         case REG_AMP_HIGH: {
      76        1399 :             const uint8_t count = data->msgs[1].len;
      77        1399 :             if (reg + count > REG_AMP_HIGH + 1) {
      78           0 :                 return -1;
      79             :             }
      80             :             // Fill in sequential registers starting at reg
      81        6994 :             for (uint8_t i = 0; i < count; i++) {
      82        5595 :                 const uint8_t curr_reg = reg + i;
      83        5595 :                 if (curr_reg == REG_DIST_LOW) {
      84        1399 :                     data->msgs[1].buf[i] = dist_cm & 0xFF;
      85        4196 :                 } else if (curr_reg == REG_DIST_HIGH) {
      86        1399 :                     data->msgs[1].buf[i] = (dist_cm >> 8) & 0xFF;
      87        2797 :                 } else if (curr_reg == REG_AMP_LOW) {
      88        1399 :                     data->msgs[1].buf[i] = strength & 0xFF;
      89        1398 :                 } else if (curr_reg == REG_AMP_HIGH) {
      90        1398 :                     data->msgs[1].buf[i] = (strength >> 8) & 0xFF;
      91             :                 }
      92             :             }
      93        1399 :             return 0;
      94             :         }
      95           0 :         case REG_VERSION_MAJOR:
      96             :             // Return version 1.0.0
      97           0 :             data->msgs[1].buf[0] = 1;
      98           0 :             return 0;
      99             :     }
     100           0 :     return -1;
     101             : }
     102             : 
     103             : #endif // AP_SIM_TFS20L_ENABLED

Generated by: LCOV version 1.14