LCOV - code coverage report
Current view: top level - AP_RangeFinder - AP_RangeFinder_JRE_Serial.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 71 0.0 %
Date: 2026-09-09 11:02:08 Functions: 0 2 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_RangeFinder_config.h"
      17             : 
      18             : #if AP_RANGEFINDER_JRE_SERIAL_ENABLED
      19             : 
      20             : #include "AP_RangeFinder_JRE_Serial.h"
      21             : #include <AP_Math/AP_Math.h>
      22             : 
      23             : #define FRAME_HEADER_1    'R'    // 0x52
      24             : #define FRAME_HEADER_2_A  'A'    // 0x41
      25             : #define FRAME_HEADER_2_B  'B'    // 0x42
      26             : #define FRAME_HEADER_2_C  'C'    // 0x43
      27             : 
      28             : #define DIST_MAX 50.00
      29             : #define OUT_OF_RANGE_ADD   1.0  // metres
      30             : 
      31           0 : void AP_RangeFinder_JRE_Serial::move_preamble_in_buffer(uint8_t search_start_pos)
      32             : {
      33             :     uint8_t i;
      34           0 :     for (i=search_start_pos; i<data_buff_ofs; i++) {
      35           0 :         if (data_buff[i] == FRAME_HEADER_1) {
      36           0 :             break;
      37             :         }
      38             :     }
      39           0 :     if (i == 0) {
      40           0 :         return;
      41             :     }
      42           0 :     memmove(data_buff, &data_buff[i], data_buff_ofs-i);
      43           0 :     data_buff_ofs = data_buff_ofs - i;
      44             : }
      45             : 
      46           0 : bool AP_RangeFinder_JRE_Serial::get_reading(float &reading_m)
      47             : {
      48             :     // uart instance check
      49           0 :     if (uart == nullptr) {
      50           0 :         return false;  // not update
      51             :     }
      52             : 
      53           0 :     uint16_t valid_count = 0;   // number of valid readings
      54           0 :     uint16_t invalid_count = 0; // number of invalid readings
      55           0 :     float sum = 0.0f;
      56             : 
      57           0 :     float fft_value = 0.0f;
      58           0 :     float sum_fft_value = 0.0f;
      59             :     uint16_t sq_pct;
      60             : 
      61             :     // read a maximum of 8192 bytes per call to this function:
      62           0 :     uint16_t bytes_available = MIN(uart->available(), 8192U);
      63             : 
      64           0 :     while (bytes_available > 0) {
      65             :         // fill buffer
      66           0 :         const auto num_bytes_to_read = MIN(bytes_available, ARRAY_SIZE(data_buff) - data_buff_ofs);
      67           0 :         const auto num_bytes_read = uart->read(&data_buff[data_buff_ofs], num_bytes_to_read);
      68           0 :         if (num_bytes_read == 0) {
      69           0 :             break;
      70             :         }
      71           0 :         if (bytes_available < num_bytes_read) {
      72             :             // this is a bug in the uart call.
      73           0 :             break;
      74             :         }
      75           0 :         bytes_available -= num_bytes_read;
      76           0 :         data_buff_ofs += num_bytes_read;
      77             : 
      78             :         // move header frame header in buffer
      79           0 :         move_preamble_in_buffer(0);
      80             : 
      81             :         // ensure we have a packet type:
      82           0 :         if (data_buff_ofs < 2) {
      83           0 :             continue;
      84             :         }
      85             : 
      86             :         // determine packet length for incoming packet:
      87             :         uint8_t packet_length;
      88           0 :         switch (data_buff[1]) {
      89           0 :         case FRAME_HEADER_2_A:
      90           0 :             packet_length = 16;
      91           0 :             break;
      92           0 :         case FRAME_HEADER_2_B:
      93           0 :             packet_length = 32;
      94           0 :             break;
      95           0 :         case FRAME_HEADER_2_C:
      96           0 :             packet_length = 48;
      97           0 :             break;
      98           0 :         default:
      99           0 :             move_preamble_in_buffer(1);
     100           0 :             continue;
     101             :         }
     102             : 
     103             :         // check there are enough bytes for message type
     104           0 :         if (data_buff_ofs < packet_length) {
     105           0 :             continue;
     106             :         }
     107             : 
     108             :         // check the checksum
     109           0 :         const uint16_t crc = crc16_ccitt_r(data_buff, packet_length - 2, 0xffff, 0xffff);
     110           0 :         if (crc != ((data_buff[packet_length-1] << 8) | data_buff[packet_length-2])) {
     111             :             // CRC failure
     112           0 :             move_preamble_in_buffer(1);
     113           0 :             continue;
     114             :         }
     115             : 
     116             :         // check random bit to for magic value:
     117           0 :         if (data_buff[packet_length-3] & 0x02) { // NTRK
     118           0 :             invalid_count++;
     119             :             // discard entire packet:
     120           0 :             move_preamble_in_buffer(packet_length);
     121           0 :             continue;
     122             :         }
     123             : 
     124             :         // good message, extract rangefinder reading:
     125           0 :         reading_m = (data_buff[4] * 256 + data_buff[5]) * 0.01f;
     126           0 :         sum += reading_m;
     127           0 :         fft_value = (data_buff[10] * 256 + data_buff[11]);
     128           0 :         sum_fft_value += fft_value;
     129           0 :         valid_count++;
     130           0 :         move_preamble_in_buffer(packet_length);
     131             :     }
     132             : 
     133             :     // return average of all valid readings
     134           0 :     if (valid_count > 0) {
     135           0 :         no_signal = false;
     136           0 :         reading_m = sum / valid_count;
     137           0 :         sq_pct = (uint16_t)((sum_fft_value / valid_count) * (100.0f / 512.0f) + 0.5f);
     138           0 :         if (sq_pct >= 100) {
     139           0 :             signal_quality_pct = 100;
     140             :         } else {
     141           0 :             signal_quality_pct = (int8_t)sq_pct;
     142             :         }
     143           0 :         return true;
     144             :     }
     145             : 
     146             :     // all readings were invalid so return out-of-range-high value
     147           0 :     if (invalid_count > 0) {
     148           0 :         no_signal = true;
     149           0 :         reading_m = MAX(DIST_MAX, max_distance() + OUT_OF_RANGE_ADD);
     150           0 :         return true;
     151             :     }
     152             : 
     153           0 :     return false;
     154             : }
     155             : #endif  // AP_RANGEFINDER_JRE_SERIAL_ENABLED

Generated by: LCOV version 1.14