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_NoopLoop.h" 17 : 18 : #if AP_RANGEFINDER_NOOPLOOP_ENABLED 19 : 20 : #include <AP_HAL/AP_HAL.h> 21 : #include <AP_HAL/utility/sparse-endian.h> 22 : 23 : #include <ctype.h> 24 : 25 : extern const AP_HAL::HAL& hal; 26 : 27 : #define NOOPLOOP_FRAME_HEADER 0x57 28 : #define NOOPLOOP_FRAME_HEADER_1 0x00 29 : #define NOOPLOOP_FRAME_LENGTH 16 30 : #define NOOPLOOP_DIST_MAX_MM 8000 31 : 32 : // format of serial packets received from NoopLoop TOF Sense P and F lidar 33 : // 34 : // Data Bit Definition Description 35 : // ----------------------------------------------------------------------- 36 : // byte 0 Frame header 0x57 37 : // byte 1 Function Mark 0x00 38 : // byte 2 (Reserved) 39 : // byte 3 Id id 40 : // byte 4-7 System time System time in ms 41 : // byte 8-10 Distance*1000 42 : // byte 11 Status Strength high 8 bits 43 : // byte 12-13 Signal Strength 44 : // byte 14 (Reserved) 45 : // byte 15 Checksum 46 : 47 : // distance returned in reading_m 48 1361 : bool AP_RangeFinder_NoopLoop::get_reading(float &reading_m) 49 : { 50 1361 : if (uart == nullptr) { 51 0 : return false; 52 : } 53 : 54 : // read any available lines from the lidar 55 1361 : uint32_t nbytes = uart->available(); 56 6491 : while (nbytes-- > 0) { 57 : uint8_t c; 58 5472 : if (!uart->read(c)) { 59 0 : break; 60 : } 61 : // if buffer is empty and this byte is 0x57, add to buffer 62 5472 : if (linebuf_len == 0) { 63 342 : if (c == NOOPLOOP_FRAME_HEADER) { 64 342 : linebuf[linebuf_len++] = c; 65 : } 66 5130 : } else if (linebuf_len == 1) { 67 : // if buffer has 1 element and this byte is 0x00, add it to buffer 68 : // if not clear the buffer 69 342 : if (c == NOOPLOOP_FRAME_HEADER_1) { 70 342 : linebuf[linebuf_len++] = c; 71 : } else { 72 0 : linebuf_len = 0; 73 : } 74 : } else { 75 : // add character to buffer 76 4788 : linebuf[linebuf_len++] = c; 77 : // if buffer now has 16 items try to decode it 78 4788 : if (linebuf_len == NOOPLOOP_FRAME_LENGTH) { 79 : // calculate checksum 80 342 : uint8_t checksum = 0; 81 5472 : for (uint8_t i=0; i<NOOPLOOP_FRAME_LENGTH-1; i++) { 82 5130 : checksum += linebuf[i]; 83 : } 84 : // if checksum matches extract contents 85 342 : if (checksum == linebuf[NOOPLOOP_FRAME_LENGTH-1]) { 86 : // calculate distance 87 342 : const int32_t dist = (int32_t)(linebuf[8] << 8 | linebuf[9] << 16 | linebuf[10] << 24) / 256; 88 342 : const uint8_t valid = (linebuf[11]); 89 342 : if (dist > 0 && reading_m < NOOPLOOP_DIST_MAX_MM && valid < 255) { 90 342 : reading_m = dist * 0.001f; 91 342 : linebuf_len = 0; 92 342 : uart->discard_input(); 93 342 : return true; 94 : } 95 : } 96 : // clear buffer 97 0 : linebuf_len = 0; 98 0 : uart->discard_input(); 99 : } 100 : } 101 : } 102 : 103 : // no readings so return false 104 1019 : return false; 105 : } 106 : 107 : #endif // AP_RANGEFINDER_NOOPLOOP_ENABLED