LCOV - code coverage report
Current view: top level - AP_VideoTX - AP_Tramp.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 12 248 4.8 %
Date: 2026-09-09 11:02:08 Functions: 3 14 21.4 %

          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             :    Code by Andy Piper, ported from betaflight vtx_tramp
      16             : */
      17             : 
      18             : #include "AP_Tramp.h"
      19             : #include <AP_Math/crc.h>
      20             : #include <GCS_MAVLink/GCS.h>
      21             : #include <AP_HAL/utility/sparse-endian.h>
      22             : #include <AP_SerialManager/AP_SerialManager.h>
      23             : 
      24             : #if AP_TRAMP_ENABLED
      25             : 
      26             : #define AP_TRAMP_UART_BAUD            9600
      27             : // request and response size is 16 bytes
      28             : #define AP_TRAMP_UART_BUFSIZE_RX      32
      29             : #define AP_TRAMP_UART_BUFSIZE_TX      32
      30             : 
      31             : // Define periods between requests
      32             : #define TRAMP_MIN_REQUEST_PERIOD_US (200 * 1000) // 200ms
      33             : #define TRAMP_STATUS_REQUEST_PERIOD_US (1000 * 1000) // 1s
      34             : 
      35             : //#define TRAMP_DEBUG
      36             : #ifdef TRAMP_DEBUG
      37             : # define debug(fmt, args...)    do { hal.console->printf("TRAMP: " fmt "\n", ##args); } while (0)
      38             : #else
      39             : # define debug(fmt, args...)    do {} while(0)
      40             : #endif
      41             : 
      42             : extern const AP_HAL::HAL &hal;
      43             : 
      44        2098 : AP_Tramp::AP_Tramp()
      45             : {
      46        2098 :     singleton = this;
      47        2098 : }
      48             : 
      49             : AP_Tramp *AP_Tramp::singleton;
      50             : 
      51             : // Calculate tramp protocol checksum of provided buffer
      52           0 : uint8_t AP_Tramp::checksum(uint8_t *buf)
      53             : {
      54           0 :     uint8_t cksum = 0;
      55             : 
      56           0 :     for (int i = 1 ; i < TRAMP_BUF_SIZE - 2; i++) {
      57           0 :         cksum += buf[i];
      58             :     }
      59             : 
      60           0 :     return cksum;
      61             : }
      62             : 
      63             : // Send tramp protocol frame to device
      64           0 : void AP_Tramp::send_command(uint8_t cmd, uint16_t param)
      65             : {
      66           0 :     if (port == nullptr) {
      67           0 :         return;
      68             :     }
      69             : 
      70           0 :     memset(request_buffer, 0, ARRAY_SIZE(request_buffer));
      71           0 :     request_buffer[0] = 0x0F;
      72           0 :     request_buffer[1] = cmd;
      73           0 :     request_buffer[2] = param & 0xFF;
      74           0 :     request_buffer[3] = (param >> 8) & 0xFF;
      75           0 :     request_buffer[14] = checksum(request_buffer);
      76             : 
      77           0 :     port->write(request_buffer, TRAMP_BUF_SIZE);
      78           0 :     port->flush();
      79             : 
      80           0 :     _packets_sent++;
      81             : 
      82             :     debug("send command '%c': %u", cmd, param);
      83             : }
      84             : 
      85             : // Process response and return code if valid else 0
      86           0 : char AP_Tramp::handle_response(void)
      87             : {
      88           0 :     _packets_rcvd++;
      89           0 :     _packets_sent = _packets_rcvd;
      90             : 
      91           0 :     const uint8_t respCode = response_buffer[1];
      92             : 
      93           0 :     switch (respCode) {
      94           0 :     case 'r': {
      95           0 :         const uint16_t min_freq = response_buffer[2]|(response_buffer[3] << 8);
      96             :         // Check we're not reading the request (indicated by freq zero)
      97           0 :         if (min_freq != 0) {
      98             :             // Got response, update device limits
      99           0 :             device_limits.rf_freq_min = min_freq;
     100           0 :             device_limits.rf_freq_max = response_buffer[4]|(response_buffer[5] << 8);
     101           0 :             device_limits.rf_power_max = response_buffer[6]|(response_buffer[7] << 8);
     102             :             debug("device limits: min freq: %u, max freq: %u, max power %u",
     103             :                 unsigned(device_limits.rf_freq_min), unsigned(device_limits.rf_freq_max), unsigned(device_limits.rf_power_max));
     104           0 :             return 'r';
     105             :         }
     106           0 :         break;
     107             :     }
     108           0 :     case 'v': {
     109           0 :         const uint16_t freq = response_buffer[2]|(response_buffer[3] << 8);
     110             :         // Check we're not reading the request (indicated by freq zero)
     111           0 :         if (freq != 0) {
     112             :             // Got response, update device status
     113           0 :             const uint16_t power = response_buffer[4]|(response_buffer[5] << 8);
     114           0 :             cur_control_mode = response_buffer[6]; // Currently only used for race lock
     115           0 :             const bool pit_mode = response_buffer[7];
     116           0 :             cur_act_power = response_buffer[8]|(response_buffer[9] << 8);
     117             : 
     118             :             // update the vtx
     119           0 :             AP_VideoTX& vtx = AP::vtx();
     120           0 :             bool update_pending = vtx.have_params_changed();
     121           0 :             vtx.set_frequency_mhz(freq);
     122             : 
     123             :             AP_VideoTX::VideoBand band;
     124             :             uint8_t channel;
     125           0 :             if (vtx.get_band_and_channel(freq, band, channel)) {
     126           0 :                 vtx.set_band(band);
     127           0 :                 vtx.set_channel(channel);
     128             :             }
     129             : 
     130           0 :             vtx.set_power_mw(power);
     131           0 :             vtx.set_actual_power_mw(cur_act_power);
     132             : 
     133             :             // VTX-reported rf_power_max is unreliable, so warn on the user cap instead
     134           0 :             if (!_act_power_warned && cur_act_power != 0) {
     135           0 :                 const uint16_t user_cap = vtx.get_max_power_mw();
     136           0 :                 const bool over_cap = (user_cap != 0 && cur_act_power > user_cap);
     137           0 :                 const bool over_request = (power != 0 && cur_act_power > power + (power / 2));
     138           0 :                 if (over_cap || over_request) {
     139           0 :                     GCS_SEND_TEXT(MAV_SEVERITY_WARNING,
     140             :                                   "VTX: requested %umW, actual %umW, cap %umW",
     141             :                                   unsigned(power), unsigned(cur_act_power), unsigned(user_cap));
     142           0 :                     _act_power_warned = true;
     143             :                 }
     144             :             }
     145             : 
     146           0 :             if (pit_mode) {
     147           0 :                 vtx.set_options(vtx.get_options() | uint8_t(AP_VideoTX::VideoOptions::VTX_PITMODE));
     148             :             } else {
     149           0 :                 vtx.set_options(vtx.get_options() & ~uint8_t(AP_VideoTX::VideoOptions::VTX_PITMODE));
     150             :             }
     151             : 
     152             :             // make sure the configured values now reflect reality
     153             :             // if they do then announce if there were changes
     154           0 :             if (!vtx.set_defaults() && update_pending && !vtx.have_params_changed()) {
     155           0 :                 vtx.announce_vtx_settings();
     156             :             }
     157             : 
     158             :             debug("device config: freq: %u, cfg pwr: %umw, act pwr: %umw, pitmode: %u, ctrl: 0x%02x",
     159             :                 unsigned(freq), unsigned(power), unsigned(cur_act_power),
     160             :                 unsigned(pit_mode), unsigned(cur_control_mode));
     161             : 
     162             :             // update the "_configuration_finished" flag, otherwise OSD item VTX_POWER blinks forever
     163           0 :             vtx.set_configuration_finished(!update_pending);
     164             : 
     165           0 :             return 'v';
     166             :         }
     167           0 :         break;
     168             :     }
     169           0 :     case 's': {
     170           0 :         const uint16_t temp = (int16_t)(response_buffer[6]|(response_buffer[7] << 8));
     171             :         // Check we're not reading the request (indicated by temp zero)
     172           0 :         if (temp != 0) {
     173             :             // Got response, update device status
     174           0 :             cur_temp = temp;
     175           0 :             return 's';
     176             :         }
     177           0 :         break;
     178             :     }
     179             :     }
     180             : 
     181             :     // Likely reading a request, return zero to indicate not accepted
     182           0 :     return 0;
     183             : }
     184             : 
     185             : // Reset receiver state machine
     186           0 : void AP_Tramp::reset_receiver(void)
     187             : {
     188           0 :     port->discard_input();
     189           0 :     receive_state = ReceiveState::S_WAIT_LEN;
     190           0 :     receive_pos = 0;
     191           0 : }
     192             : 
     193             : // returns completed response code or 0
     194           0 : char AP_Tramp::receive_response()
     195             : {
     196           0 :     if (port == nullptr) {
     197           0 :         return 0;
     198             :     }
     199             : 
     200             :     // wait for complete packet
     201           0 :     const uint16_t bytesNeeded = TRAMP_BUF_SIZE - receive_pos;
     202           0 :     if (port->available() < bytesNeeded) {
     203           0 :         return 0;
     204             :     }
     205             : 
     206             :     // sanity check
     207           0 :     if (bytesNeeded == 0) {
     208           0 :         reset_receiver();
     209           0 :         return 0;
     210             :     }
     211             : 
     212           0 :     for (uint16_t i = 0; i < bytesNeeded; i++) {
     213           0 :         const int16_t b = port->read();
     214           0 :         if (b < 0) {
     215             :             // uart claimed bytes available, but there were none
     216           0 :             return 0;
     217             :         }
     218           0 :         const uint8_t c = uint8_t(b);
     219           0 :         response_buffer[receive_pos++] = c;
     220             : 
     221           0 :         switch (receive_state) {
     222           0 :         case ReceiveState::S_WAIT_LEN: {
     223           0 :             if (c == 0x0F) {
     224             :                 // Found header byte, advance to wait for code
     225           0 :                 receive_state = ReceiveState::S_WAIT_CODE;
     226             :             } else {
     227             :                 // Unexpected header, reset state machine
     228           0 :                 reset_receiver();
     229             :             }
     230           0 :             break;
     231             :         }
     232           0 :         case ReceiveState::S_WAIT_CODE: {
     233           0 :             if (c == 'r' || c == 'v' || c == 's') {
     234             :                 // Code is for response is one we're interested in, advance to data
     235           0 :                 receive_state = ReceiveState::S_DATA;
     236             :             } else {
     237             :                 // Unexpected code, reset state machine
     238           0 :                 reset_receiver();
     239             :             }
     240           0 :             break;
     241             :         }
     242           0 :         case ReceiveState::S_DATA: {
     243           0 :             if (receive_pos == TRAMP_BUF_SIZE) {
     244             :                 // Buffer is full, calculate checksum
     245           0 :                 const uint8_t cksum = checksum(response_buffer);
     246             : 
     247             :                 // Reset state machine ready for next response
     248           0 :                 reset_receiver();
     249             : 
     250           0 :                 if ((response_buffer[TRAMP_BUF_SIZE-2] == cksum) && (response_buffer[TRAMP_BUF_SIZE-1] == 0)) {
     251             :                     // Checksum is correct, process response
     252           0 :                     const char r = handle_response();
     253             : 
     254             :                     // Check response valid else keep on reading
     255           0 :                     if (r != 0) {
     256           0 :                         return r;
     257             :                     }
     258             :                 }
     259             :             }
     260           0 :             break;
     261             :         }
     262           0 :         default:
     263             :             // Invalid state, reset state machine
     264           0 :             reset_receiver();
     265           0 :             break;
     266             :         }
     267             :     }
     268             : 
     269           0 :     return 0;
     270             : }
     271             : 
     272           0 : void AP_Tramp::send_query(uint8_t cmd)
     273             : {
     274             :     // Reset receive buffer and issue command
     275           0 :     reset_receiver();
     276           0 :     send_command(cmd, 0);
     277           0 : }
     278             : 
     279           0 : void AP_Tramp::set_status(TrampStatus _status)
     280             : {
     281           0 :     status = _status;
     282             : #ifdef TRAMP_DEBUG
     283             :     switch (status) {
     284             :         case TrampStatus::TRAMP_STATUS_OFFLINE:
     285             :             debug("status: OFFLINE");
     286             :             break;
     287             :         case TrampStatus::TRAMP_STATUS_INIT:
     288             :             debug("status: INIT");
     289             :             break;
     290             :         case TrampStatus::TRAMP_STATUS_ONLINE_MONITOR_FREQPWRPIT:
     291             :             debug("status: ONLINE_MONITOR_FREQPWRPIT");
     292             :             break;
     293             :         case TrampStatus::TRAMP_STATUS_ONLINE_MONITOR_TEMP:
     294             :             debug("status: ONLINE_MONITOR_TEMP");
     295             :             break;
     296             :         case TrampStatus::TRAMP_STATUS_ONLINE_CONFIG:
     297             :             debug("status: ONLINE_CONFIG");
     298             :             break;
     299             :     }
     300             : #endif
     301           0 : }
     302             : 
     303           0 : void AP_Tramp::process_requests()
     304             : {
     305           0 :     if (port == nullptr) {
     306           0 :         return;
     307             :     }
     308             : 
     309           0 :     bool configUpdateRequired = false;
     310             : 
     311             :     // Read response from device
     312           0 :     const char replyCode = receive_response();
     313           0 :     const uint32_t now = AP_HAL::micros();
     314             : 
     315             : #ifdef TRAMP_DEBUG
     316             :     if (replyCode != 0) {
     317             :         debug("receive response '%c'", replyCode);
     318             :     }
     319             : #endif
     320             : 
     321             :     // Act on state
     322           0 :     switch (status) {
     323           0 :     case TrampStatus::TRAMP_STATUS_OFFLINE: {
     324             :         // Offline, check for response
     325           0 :         if (replyCode == 'r') {
     326             :             // Device replied to reset? request, enter init
     327           0 :             set_status(TrampStatus::TRAMP_STATUS_INIT);
     328           0 :         } else if ((now - last_time_us) >= TRAMP_MIN_REQUEST_PERIOD_US) {
     329             :             // Min request period exceeded, issue another reset?
     330           0 :             send_query('r');
     331             : 
     332             :             // Update last time
     333           0 :             last_time_us = now;
     334             :         }
     335           0 :         break;
     336             :     }
     337           0 :     case TrampStatus::TRAMP_STATUS_INIT: {
     338             :         // Initializing, check for response
     339           0 :         if (replyCode == 'v') {
     340             :             // Device replied to freq / power / pit query, enter online
     341           0 :             set_status(TrampStatus::TRAMP_STATUS_ONLINE_MONITOR_FREQPWRPIT);
     342           0 :         } else if ((now - last_time_us) >= TRAMP_MIN_REQUEST_PERIOD_US) {
     343             : 
     344           0 :             update_baud_rate();
     345             : 
     346             :             // Min request period exceeded, issue another query
     347           0 :             send_query('v');
     348             : 
     349             :             // Update last time
     350           0 :             last_time_us = now;
     351             :         }
     352           0 :         break;
     353             :     }
     354           0 :     case TrampStatus::TRAMP_STATUS_ONLINE_MONITOR_FREQPWRPIT: {
     355             :         // Note after config a status update request is made, a new status
     356             :         // request is made, this request is handled above and should prevent
     357             :         // subsequent config updates if the config is now correct
     358           0 :         if (retry_count > 0 && ((now - last_time_us) >= TRAMP_MIN_REQUEST_PERIOD_US)) {
     359           0 :             AP_VideoTX& vtx = AP::vtx();
     360             :             // Config retries remain and min request period exceeded, check freq
     361           0 :             if (!is_race_lock_enabled() && vtx.update_frequency()) {
     362             :                 debug("Updating frequency to %uMhz", vtx.get_configured_frequency_mhz());
     363             :                 // Freq can be and needs to be updated, issue request
     364           0 :                 send_command('F', vtx.get_configured_frequency_mhz());
     365             : 
     366             :                 // Set flag
     367           0 :                 configUpdateRequired = true;
     368           0 :             } else if (!is_race_lock_enabled() && vtx.update_power()) {
     369             :                 debug("Updating power to %umw\n", vtx.get_configured_power_mw());
     370             :                 // Power can be and needs to be updated, issue request
     371           0 :                 send_command('P', vtx.get_configured_power_mw());
     372             : 
     373             :                 // Set flag
     374           0 :                 configUpdateRequired = true;
     375           0 :             } else if (vtx.update_options()) {
     376             :                 // Pit mode needs to be updated, issue request
     377           0 :                 send_command('I', vtx.has_option(AP_VideoTX::VideoOptions::VTX_PITMODE) ? 0 : 1);
     378             : 
     379             :                 // Set flag
     380           0 :                 configUpdateRequired = true;
     381             :             }
     382             : 
     383           0 :             if (configUpdateRequired) {
     384             :                 // Update required, decrement retry count
     385           0 :                 retry_count--;
     386             : 
     387             :                 // Update last time
     388           0 :                 last_time_us = now;
     389             : 
     390             :                 // Advance state
     391           0 :                 set_status(TrampStatus::TRAMP_STATUS_ONLINE_CONFIG);
     392             :             } else {
     393             :                 // No update required, reset retry count
     394           0 :                 retry_count = 0;
     395             :             }
     396             :         }
     397             : 
     398             :         /* Was a config update made? */
     399           0 :         if (!configUpdateRequired) {
     400             :             /* No, look to continue monitoring */
     401           0 :             if ((now - last_time_us) >= TRAMP_STATUS_REQUEST_PERIOD_US) {
     402             :                 // Request period exceeded, issue freq/power/pit query
     403           0 :                 send_query('v');
     404             : 
     405             :                 // Update last time
     406           0 :                 last_time_us = now;
     407           0 :             } else if (replyCode == 'v') {
     408             :                 // Got reply, issue temp query
     409           0 :                 send_query('s');
     410             : 
     411             :                 // Wait for reply
     412           0 :                 set_status(TrampStatus::TRAMP_STATUS_ONLINE_MONITOR_TEMP);
     413             : 
     414             :                 // Update last time
     415           0 :                 last_time_us = now;
     416             :             }
     417             :         }
     418             : 
     419           0 :         break;
     420             :     }
     421           0 :     case TrampStatus::TRAMP_STATUS_ONLINE_MONITOR_TEMP: {
     422             :         // Check request time
     423           0 :         if (replyCode == 's') {
     424             :             // Got reply, return to request freq/power/pit
     425           0 :             set_status(TrampStatus::TRAMP_STATUS_ONLINE_MONITOR_TEMP);
     426           0 :         } else if ((now - last_time_us) >= TRAMP_MIN_REQUEST_PERIOD_US) {
     427             :             // Timed out after min request period, return to request freq/power/pit query
     428           0 :             set_status(TrampStatus::TRAMP_STATUS_ONLINE_MONITOR_FREQPWRPIT);
     429             :         }
     430           0 :         break;
     431             :     }
     432           0 :     case TrampStatus::TRAMP_STATUS_ONLINE_CONFIG: {
     433             :         // Param should now be set, check time
     434           0 :         if ((now - last_time_us) >= TRAMP_MIN_REQUEST_PERIOD_US) {
     435             :             // Min request period exceeded, re-query
     436           0 :             send_query('v');
     437             : 
     438             :             // Advance state
     439           0 :             set_status(TrampStatus::TRAMP_STATUS_ONLINE_MONITOR_FREQPWRPIT);
     440             : 
     441             :             // Update last time
     442           0 :             last_time_us = now;
     443             :         }
     444           0 :         break;
     445             :     }
     446           0 :     default:
     447             :         // Invalid state, reset
     448           0 :         set_status(TrampStatus::TRAMP_STATUS_OFFLINE);
     449           0 :         break;
     450             :     }
     451             : }
     452             : 
     453           0 : bool AP_Tramp::is_device_ready()
     454             : {
     455           0 :     return status >= TrampStatus::TRAMP_STATUS_ONLINE_MONITOR_FREQPWRPIT;
     456             : }
     457             : 
     458           0 : void AP_Tramp::set_frequency(uint16_t freq)
     459             : {
     460             :     uint8_t freqValid;
     461             : 
     462             :     // Check frequency valid
     463           0 :     if (device_limits.rf_freq_min != 0 && device_limits.rf_freq_max != 0) {
     464           0 :         freqValid = (freq >= device_limits.rf_freq_min && freq <= device_limits.rf_freq_max);
     465             :     } else {
     466           0 :         freqValid = (freq >= VTX_TRAMP_MIN_FREQUENCY_MHZ && freq <= VTX_TRAMP_MAX_FREQUENCY_MHZ);
     467             :     }
     468             : 
     469             :     // Is frequency valid?
     470           0 :     if (freqValid) {
     471             :         // Requested freq changed, reset retry count
     472           0 :         retry_count = VTX_TRAMP_MAX_RETRIES;
     473             :     } else {
     474             :         debug("requested frequency %u is invalid", freq);
     475             :         // not valid reset to default
     476           0 :         AP::vtx().set_configured_frequency_mhz(AP::vtx().get_frequency_mhz());
     477             :     }
     478           0 : }
     479             : 
     480     7525129 : void AP_Tramp::update()
     481             : {
     482     7525129 :     if (port == nullptr) {
     483     7525129 :         return;
     484             :     }
     485             : 
     486           0 :     AP_VideoTX& vtx = AP::vtx();
     487             : 
     488           0 :     if (vtx.have_params_changed() && retry_count == 0) {
     489             :         // check changes in the order they will be processed; re-arm retries
     490             :         // only on real changes so a VTX rejecting a value can't loop forever
     491           0 :         if (vtx.update_frequency() || vtx.update_band() || vtx.update_channel()) {
     492           0 :             if (vtx.update_frequency()) {
     493           0 :                 vtx.update_configured_channel_and_band();
     494             :             } else {
     495           0 :                 vtx.update_configured_frequency();
     496             :             }
     497           0 :             const uint16_t conf_freq = vtx.get_configured_frequency_mhz();
     498           0 :             if (conf_freq != _last_conf_freq) {
     499           0 :                 _last_conf_freq = conf_freq;
     500           0 :                 set_frequency(conf_freq);
     501             :             }
     502             :         }
     503           0 :         else if (vtx.update_power()) {
     504           0 :             const uint16_t conf_power = vtx.get_configured_power_mw();
     505           0 :             if (conf_power != _last_conf_power) {
     506           0 :                 _last_conf_power = conf_power;
     507           0 :                 retry_count = VTX_TRAMP_MAX_RETRIES;
     508           0 :                 _power_warn_pending = true;
     509           0 :             } else if (_power_warn_pending) {
     510           0 :                 GCS_SEND_TEXT(MAV_SEVERITY_WARNING,
     511             :                               "VTX: rejected power %umW", unsigned(conf_power));
     512           0 :                 _power_warn_pending = false;
     513             :             }
     514             :         }
     515           0 :         else if (vtx.update_options()) {
     516           0 :             const uint16_t conf_options = vtx.get_configured_options();
     517           0 :             if (conf_options != _last_conf_options) {
     518           0 :                 _last_conf_options = conf_options;
     519           0 :                 retry_count = VTX_TRAMP_MAX_RETRIES;
     520             :             }
     521             :         }
     522             :     }
     523             : 
     524           0 :     process_requests();
     525             : }
     526             : 
     527             : // we missed a response too many times - update the baud rate in case the temperature has increased
     528           0 : void AP_Tramp::update_baud_rate()
     529             : {
     530             :     // on my Unify Pro32 the VTX will respond immediately on power up to a settings request, so 5 packets is easily more than enough
     531             :     // we want to bias autobaud to only frequency hop when the current frequency is clearly exhausted, but after that hop quickly
     532             :     // on a Foxeer Reaper Infinity the actual response baudrate is more like 9400, so auto-bauding down in the first instance.
     533           0 :     if (_packets_sent - _packets_rcvd < 5) {
     534           0 :         return;
     535             :     }
     536             : 
     537           0 :     if (_smartbaud_direction == AutobaudDirection::UP
     538           0 :         && _smartbaud == VTX_TRAMP_SMARTBAUD_MAX) {
     539           0 :         _smartbaud_direction = AutobaudDirection::DOWN;
     540           0 :     } else if (_smartbaud_direction == AutobaudDirection::DOWN
     541           0 :         && _smartbaud == VTX_TRAMP_SMARTBAUD_MIN) {
     542           0 :         _smartbaud_direction = AutobaudDirection::UP;
     543             :     }
     544             : 
     545           0 :     _smartbaud += VTX_TRAMP_SMARTBAUD_STEP * int32_t(_smartbaud_direction);
     546             : 
     547             :     debug("autobaud: %d", int(_smartbaud));
     548             : 
     549           0 :     port->discard_input();
     550           0 :     port->begin(_smartbaud);
     551             : 
     552           0 :     _packets_sent = _packets_rcvd = 0;
     553             : }
     554             : 
     555             : 
     556        2086 : bool AP_Tramp::init(void)
     557             : {
     558        2086 :     if (AP::vtx().get_enabled() == 0) {
     559             :         debug("protocol is not active");
     560        2082 :         return false;
     561             :     }
     562             : 
     563             :     // init uart
     564           4 :     port = AP::serialmanager().find_serial(AP_SerialManager::SerialProtocol_Tramp, 0);
     565           4 :     if (port != nullptr) {
     566           0 :         port->configure_parity(0);
     567           0 :         port->set_stop_bits(1);
     568           0 :         port->set_flow_control(AP_HAL::UARTDriver::FLOW_CONTROL_DISABLE);
     569           0 :         port->set_options((port->get_options() & ~AP_HAL::UARTDriver::OPTION_RXINV));
     570             : 
     571           0 :         port->begin(AP_TRAMP_UART_BAUD, AP_TRAMP_UART_BUFSIZE_RX, AP_TRAMP_UART_BUFSIZE_TX);
     572             :         debug("port opened");
     573             : 
     574           0 :         AP::vtx().set_provider_enabled(AP_VideoTX::VTXType::Tramp);
     575             : 
     576           0 :         return true;
     577             :     }
     578           4 :     return false;
     579             : }
     580             : 
     581             : #endif // AP_TRAMP_ENABLED

Generated by: LCOV version 1.14