#include "AP_Proximity_Cygbot_D1.h" #if HAL_PROXIMITY_ENABLED && AP_PROXIMITY_CYGBOT_ENABLED // update the state of the sensor void AP_Proximity_Cygbot_D1::update() { if (!_initialized) { send_sensor_start(); _temp_boundary.reset(); _initialized = true; _last_init_ms = AP_HAL::millis(); } if ((AP_HAL::millis() - _last_init_ms) < CYGBOT_INIT_TIMEOUT_MS) { // just initialized set_status(AP_Proximity::Status::NoData); return; } // read data read_sensor_data(); if (AP_HAL::millis() - _last_distance_received_ms < CYGBOT_TIMEOUT_MS) { set_status(AP_Proximity::Status::Good); } else { // long time since we received any valid sensor data // try sending the sensor the "send data" message _initialized = false; set_status(AP_Proximity::Status::NoData); } } // send message to the sensor to start streaming 2-D data void AP_Proximity_Cygbot_D1::send_sensor_start() { // this message corresponds to "start message" const uint8_t packet_start_2d[8] = { CYGBOT_PACKET_HEADER_0, CYGBOT_PACKET_HEADER_1, CYGBOT_PACKET_HEADER_2, 0x02, 0x00, 0x01, 0x00, 0x03 }; _uart->write(packet_start_2d, 8); } void AP_Proximity_Cygbot_D1::read_sensor_data() { uint32_t nbytes = _uart->available(); while (nbytes-- > 0) { uint8_t byte = _uart->read(); if (!parse_byte(byte)) { // reset reset(); } } } // parse one byte from the sensor. Return false on error. // Message format is: header1 + header2 + header3 + length1 + length2 + PayloadCommand + checksum bool AP_Proximity_Cygbot_D1::parse_byte(uint8_t data) { switch (_parse_state) { case Header1: if (data == CYGBOT_PACKET_HEADER_0) { _parse_state = Header2; return true; } return false; case Header2: if (data == CYGBOT_PACKET_HEADER_1) { _parse_state = Header3; return true; } return false; case Header3: if (data == CYGBOT_PACKET_HEADER_2) { _parse_state = Length1; return true; } return false; case Length1: _msg.payload_len_flags_low = data; _parse_state = Length2; return true; case Length2: _msg.payload_len_flags_high = data; _msg.payload_len = UINT16_VALUE(data, _msg.payload_len_flags_low); if (_msg.payload_len > CYGBOT_MAX_MSG_SIZE) { return false; } _parse_state = Payload_Header; return true; case Payload_Header: if (data == CYGBOT_PAYLOAD_HEADER) { _parse_state = Payload_Data; _msg.payload_counter = 1; _msg.payload[_msg.payload_counter] = data; return true; } return false; case Payload_Data: if (_msg.payload_counter < (_msg.payload_len)) { _msg.payload_counter++; _msg.payload[_msg.payload_counter] = data; return true; } _parse_state = CheckSum; FALLTHROUGH; case CheckSum: { const uint8_t checksum_num = calc_checksum(_msg.payload, _msg.payload_len); if (data != checksum_num) { return false; } // checksum is valid, parse payload _last_distance_received_ms = AP_HAL::millis(); parse_payload(); _temp_boundary.update_3D_boundary(boundary); reset(); return true; } break; default: return false; } return false; } // parse payload, to pick out distances, and feed them to the correct faces void AP_Proximity_Cygbot_D1::parse_payload() { // current horizontal angle in the payload float sampled_angle = CYGBOT_2D_START_ANGLE; // start from second byte as first byte is part of the header for (uint16_t i = 2; i < _msg.payload_len; i += 2) { const uint16_t distance_mm = UINT16_VALUE(_msg.payload[i], _msg.payload[i+1]); float distance_m = distance_mm * 0.001f; if (distance_m > distance_min() && distance_m < distance_max()) { if (ignore_reading(sampled_angle, distance_m)) { // ignore this angle sampled_angle += CYGBOT_2D_ANGLE_STEP; continue; } // convert angle to face const AP_Proximity_Boundary_3D::Face face = boundary.get_face(sampled_angle); // push face to temp boundary _temp_boundary.add_distance(face, sampled_angle, distance_m); // push to OA_DB database_push(sampled_angle, distance_m); } // increment sampled angle sampled_angle += CYGBOT_2D_ANGLE_STEP; } } // Checksum uint8_t AP_Proximity_Cygbot_D1::calc_checksum(uint8_t *buff, int buffSize) { uint8_t check_sum_num = 0; check_sum_num ^= _msg.payload_len_flags_high; check_sum_num ^= _msg.payload_len_flags_low; for (uint16_t i = 0; i <= buffSize; i++) { check_sum_num ^= buff[i]; } return check_sum_num; } // reset all variables and flags void AP_Proximity_Cygbot_D1::reset() { _parse_state = Header1; _msg.payload_counter = 0; _msg.payload_len = 0; _temp_boundary.reset(); } #endif // HAL_PROXIMITY_ENABLED