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_RPM_config.h" 17 : 18 : #if AP_RPM_DRONECAN_ENABLED 19 : 20 : #include "RPM_DroneCAN.h" 21 : #include <AP_BoardConfig/AP_BoardConfig.h> 22 : 23 : AP_RPM_DroneCAN* AP_RPM_DroneCAN::_drivers[]; 24 : uint8_t AP_RPM_DroneCAN::_driver_instance; 25 : HAL_Semaphore AP_RPM_DroneCAN::_driver_sem; 26 : 27 0 : AP_RPM_DroneCAN::AP_RPM_DroneCAN(AP_RPM &_ap_rpm, uint8_t instance, AP_RPM::RPM_State &_state) : 28 0 : AP_RPM_Backend(_ap_rpm, instance, _state) 29 : { 30 : // Register self in static driver list 31 0 : WITH_SEMAPHORE(_driver_sem); 32 0 : _drivers[_driver_instance] = this; 33 0 : _driver_instance++; 34 0 : } 35 : 36 : // Subscribe to incoming rpm messages 37 5 : bool AP_RPM_DroneCAN::subscribe_msgs(AP_DroneCAN* ap_dronecan) 38 : { 39 5 : const auto driver_index = ap_dronecan->get_driver_index(); 40 : 41 5 : return (Canard::allocate_sub_arg_callback(ap_dronecan, &handle_rpm, driver_index) != nullptr); 42 : } 43 : 44 : // Receive new CAN message 45 0 : void AP_RPM_DroneCAN::handle_rpm(AP_DroneCAN *ap_dronecan, const CanardRxTransfer& transfer, const dronecan_sensors_rpm_RPM &msg) 46 : { 47 0 : WITH_SEMAPHORE(_driver_sem); 48 : 49 0 : for (uint8_t i = 0; i < _driver_instance; i++) { 50 0 : if (_drivers[i] == nullptr) { 51 0 : continue; 52 : } 53 : // Find params for this instance 54 0 : const uint8_t instance = _drivers[i]->state.instance; 55 0 : const AP_RPM_Params& params = _drivers[i]->ap_rpm._params[instance]; 56 : 57 0 : if (params.dronecan_sensor_id == msg.sensor_id) { 58 : // Driver loaded and looking for this ID, add reading 59 0 : _drivers[i]->last_reading_ms = AP_HAL::millis(); 60 0 : _drivers[i]->rpm = msg.rpm * params.scaling; 61 : 62 0 : const bool heathy = (msg.flags & DRONECAN_SENSORS_RPM_RPM_FLAGS_UNHEALTHY) == 0; 63 0 : _drivers[i]->signal_quality = heathy ? 0.5 : 0.0; 64 : } 65 : } 66 0 : } 67 : 68 0 : void AP_RPM_DroneCAN::update(void) 69 : { 70 0 : WITH_SEMAPHORE(_driver_sem); 71 : 72 : // Update state from temporay variables 73 0 : state.last_reading_ms = last_reading_ms; 74 0 : state.signal_quality = signal_quality; 75 0 : state.rate_rpm = rpm; 76 : 77 : // assume we get readings at at least 1Hz, otherwise reset quality to zero 78 0 : if ((AP_HAL::millis() - state.last_reading_ms) > 1000) { 79 0 : state.signal_quality = 0; 80 0 : state.rate_rpm = 0; 81 : } 82 0 : } 83 : 84 : #endif // AP_RPM_DRONECAN_ENABLED