LCOV - code coverage report
Current view: top level - AP_Proximity - AP_Proximity_TeraRangerTowerEvo.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 80 0.0 %
Date: 2026-09-09 11:02:08 Functions: 0 7 0.0 %

          Line data    Source code
       1             : /*
       2             :    This program is free software: you can redistribute it and/or modify
       3             :    it under the terms of the GNU General Public License as published by
       4             :    the Free Software Foundation, either version 3 of the License, or
       5             :    (at your option) any later version.
       6             : 
       7             :    This program is distributed in the hope that it will be useful,
       8             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
       9             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      10             :    GNU General Public License for more details.
      11             : 
      12             :    You should have received a copy of the GNU General Public License
      13             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      14             :  */
      15             : 
      16             : #include "AP_Proximity_config.h"
      17             : 
      18             : #if AP_PROXIMITY_TERARANGERTOWEREVO_ENABLED
      19             : 
      20             : #include <AP_HAL/AP_HAL.h>
      21             : #include "AP_Proximity_TeraRangerTowerEvo.h"
      22             : 
      23             : #include <AP_Math/crc.h>
      24             : #include <ctype.h>
      25             : #include <stdio.h>
      26             : 
      27             : extern const AP_HAL::HAL& hal;
      28             : 
      29             : // update the state of the sensor
      30           0 : void AP_Proximity_TeraRangerTowerEvo::update(void)
      31             : {
      32           0 :     if (_uart == nullptr) {
      33           0 :         return;
      34             :     }
      35           0 :     if (_last_request_sent_ms == 0) {
      36           0 :         _last_request_sent_ms = AP_HAL::millis();
      37             :     }
      38             :     //initialize the sensor
      39           0 :     if(_current_init_state != InitState::InitState_Finished)
      40             :     {
      41           0 :         initialise_modes();
      42             :     }
      43             : 
      44             :     // process incoming messages
      45           0 :     read_sensor_data();
      46             : 
      47             :     // check for timeout and set health status
      48           0 :     if ((_last_distance_received_ms == 0) || (AP_HAL::millis() - _last_distance_received_ms > PROXIMITY_TRTOWER_TIMEOUT_MS)) {
      49           0 :         set_status(AP_Proximity::Status::NoData);
      50             :     } else {
      51           0 :         set_status(AP_Proximity::Status::Good);
      52             :     }
      53             : }
      54             : 
      55             : // get maximum and minimum distances (in meters) of primary sensor
      56           0 : float AP_Proximity_TeraRangerTowerEvo::distance_max_m() const
      57             : {
      58           0 :     return 60.0f;
      59             : }
      60           0 : float AP_Proximity_TeraRangerTowerEvo::distance_min_m() const
      61             : {
      62           0 :     return 0.50f;
      63             : }
      64             : 
      65           0 : void AP_Proximity_TeraRangerTowerEvo::initialise_modes()
      66             : {
      67           0 :     if((AP_HAL::millis() - _last_request_sent_ms) < _mode_request_delay) {
      68           0 :         return;
      69             :     }
      70             : 
      71           0 :     if (_current_init_state == InitState_Printout) {
      72           0 :         set_mode(BINARY_MODE, 4);
      73           0 :     } else if (_current_init_state == InitState_Sequence) {
      74             :         //set tower mode - 4 sensors are triggered at once with 90 deg angle between each sensor
      75           0 :         set_mode(TOWER_MODE, 4);
      76           0 :     } else if (_current_init_state == InitState_Rate) {
      77             :         //set update rate of the sensor.
      78           0 :         set_mode(REFRESH_100_HZ, 5);
      79           0 :     } else if (_current_init_state == InitState_StreamStart) {
      80           0 :         set_mode(ACTIVATE_STREAM, 5);
      81             :     }
      82             : }
      83             : 
      84           0 : void AP_Proximity_TeraRangerTowerEvo::set_mode(const uint8_t *c, int length)
      85             : {
      86           0 :     _uart->write(c, length);
      87           0 :     _last_request_sent_ms = AP_HAL::millis();
      88           0 : }
      89             : 
      90             : // check for replies from sensor, returns true if at least one message was processed
      91           0 : bool AP_Proximity_TeraRangerTowerEvo::read_sensor_data()
      92             : {
      93           0 :     if (_uart == nullptr) {
      94           0 :         return false;
      95             :     }
      96             : 
      97           0 :     uint16_t message_count = 0;
      98           0 :     int16_t nbytes = _uart->available();
      99             : 
     100           0 :     if(_current_init_state != InitState_Finished && nbytes == 4) {
     101             : 
     102             :         //Increment _current_init_state only when we receive 4 ack bytes
     103           0 :         switch (_current_init_state) {
     104           0 :             case InitState_Printout:
     105           0 :                 _current_init_state = InitState_Sequence;
     106           0 :                 break;
     107           0 :             case InitState_Sequence:
     108           0 :                 _current_init_state = InitState_Rate;
     109           0 :                 break;
     110           0 :             case InitState_Rate:
     111           0 :                 _current_init_state = InitState_StreamStart;
     112           0 :                 break;
     113           0 :             case InitState_StreamStart:
     114           0 :                 _current_init_state = InitState_Finished;
     115           0 :                 break;
     116           0 :             case InitState_Finished:
     117           0 :                 break;
     118             :         }
     119             :     }
     120             : 
     121           0 :     while (nbytes-- > 0) {
     122           0 :         int16_t c = _uart->read();
     123           0 :         if (c==-1) {
     124           0 :             return false;
     125             :         }
     126           0 :         if (char(c) == 'T' ) {
     127           0 :             buffer_count = 0;
     128             :         }
     129           0 :         buffer[buffer_count++] = c;
     130             : 
     131             :         // we should always read 19 bytes THxxxxxxxxxxxxxxxxMC
     132           0 :         if (buffer_count >= 20){
     133           0 :             buffer_count = 0;
     134             : 
     135             :             //check if message has right CRC
     136           0 :             if (crc_crc8(buffer, 19) == buffer[19]){
     137           0 :                 update_sector_data(0,   UINT16_VALUE(buffer[2],  buffer[3]));   // d1
     138           0 :                 update_sector_data(45,  UINT16_VALUE(buffer[4],  buffer[5]));   // d2
     139           0 :                 update_sector_data(90,  UINT16_VALUE(buffer[6],  buffer[7]));   // d3
     140           0 :                 update_sector_data(135, UINT16_VALUE(buffer[8],  buffer[9]));   // d4
     141           0 :                 update_sector_data(180, UINT16_VALUE(buffer[10], buffer[11]));  // d5
     142           0 :                 update_sector_data(225, UINT16_VALUE(buffer[12], buffer[13]));  // d6
     143           0 :                 update_sector_data(270, UINT16_VALUE(buffer[14], buffer[15]));  // d7
     144           0 :                 update_sector_data(315, UINT16_VALUE(buffer[16], buffer[17]));  // d8
     145             : 
     146           0 :                 message_count++;
     147             :             }
     148             :         }
     149             :     }
     150           0 :     return (message_count > 0);
     151             : }
     152             : 
     153             : // process reply
     154           0 : void AP_Proximity_TeraRangerTowerEvo::update_sector_data(int16_t angle_deg, uint16_t distance_mm)
     155             : {
     156             :     // Get location on 3-D boundary based on angle to the object
     157           0 :     const AP_Proximity_Boundary_3D::Face face = frontend.boundary.get_face(angle_deg);
     158             :     //check for target too far, target too close and sensor not connected
     159           0 :     const bool valid = (distance_mm != 0xffff) && (distance_mm > 0x0001);
     160           0 :     if (valid && !ignore_reading(angle_deg, distance_mm * 0.001f, false)) {
     161           0 :         frontend.boundary.set_face_attributes(face, angle_deg, ((float) distance_mm) / 1000, state.instance);
     162             :         // update OA database
     163           0 :         database_push(angle_deg, ((float) distance_mm) / 1000);
     164             :     } else {
     165           0 :         frontend.boundary.reset_face(face, state.instance);
     166             :     }
     167           0 :     _last_distance_received_ms = AP_HAL::millis();
     168           0 : }
     169             : 
     170             : #endif // AP_PROXIMITY_TERARANGERTOWEREVO_ENABLED

Generated by: LCOV version 1.14