|
|
|
@ -39,10 +39,9 @@ AP_RCProtocol_SRXL2* AP_RCProtocol_SRXL2::_singleton;
@@ -39,10 +39,9 @@ AP_RCProtocol_SRXL2* AP_RCProtocol_SRXL2::_singleton;
|
|
|
|
|
|
|
|
|
|
AP_RCProtocol_SRXL2::AP_RCProtocol_SRXL2(AP_RCProtocol &_frontend) : AP_RCProtocol_Backend(_frontend) |
|
|
|
|
{ |
|
|
|
|
const uint32_t uniqueID = AP_HAL::micros(); |
|
|
|
|
#if !APM_BUILD_TYPE(APM_BUILD_UNKNOWN) |
|
|
|
|
if (_singleton != nullptr) { |
|
|
|
|
AP_HAL::panic("Duplicate SRXL2 handler"); |
|
|
|
|
AP_HAL::panic("Duplicate SRXL2 handler\n"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_singleton = this; |
|
|
|
@ -51,16 +50,27 @@ AP_RCProtocol_SRXL2::AP_RCProtocol_SRXL2(AP_RCProtocol &_frontend) : AP_RCProtoc
@@ -51,16 +50,27 @@ AP_RCProtocol_SRXL2::AP_RCProtocol_SRXL2(AP_RCProtocol &_frontend) : AP_RCProtoc
|
|
|
|
|
_singleton = this; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void AP_RCProtocol_SRXL2::_bootstrap(uint8_t device_id) |
|
|
|
|
{ |
|
|
|
|
if (_device_id == device_id) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Init the local SRXL device
|
|
|
|
|
if (!srxlInitDevice(SRXL_DEVICE_ID, SRXL_DEVICE_PRIORITY, SRXL_DEVICE_INFO, uniqueID)) { |
|
|
|
|
AP_HAL::panic("Failed to initialize SRXL2 device"); |
|
|
|
|
if (!srxlInitDevice(device_id, SRXL_DEVICE_PRIORITY, SRXL_DEVICE_INFO, device_id)) { |
|
|
|
|
AP_HAL::panic("Failed to initialize SRXL2 device\n"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Init the SRXL bus: The bus index must always be < SRXL_NUM_OF_BUSES -- in this case, it can only be 0
|
|
|
|
|
if (!srxlInitBus(0, 0, SRXL_SUPPORTED_BAUD_RATES)) { |
|
|
|
|
AP_HAL::panic("Failed to initialize SRXL2 bus"); |
|
|
|
|
AP_HAL::panic("Failed to initialize SRXL2 bus\n"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_device_id = device_id; |
|
|
|
|
|
|
|
|
|
debug("Bootstrapped as 0x%x", _device_id); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
AP_RCProtocol_SRXL2::~AP_RCProtocol_SRXL2() { |
|
|
|
@ -121,7 +131,19 @@ void AP_RCProtocol_SRXL2::_process_byte(uint32_t timestamp_us, uint8_t byte)
@@ -121,7 +131,19 @@ void AP_RCProtocol_SRXL2::_process_byte(uint32_t timestamp_us, uint8_t byte)
|
|
|
|
|
|
|
|
|
|
if (_buflen == _frame_len_full) { |
|
|
|
|
log_data(AP_RCProtocol::SRXL2, timestamp_us, _buffer, _buflen); |
|
|
|
|
|
|
|
|
|
// we got a full frame but never handshaked before
|
|
|
|
|
if (!is_bootstrapped()) { |
|
|
|
|
if (_buffer[1] == 0x21) { |
|
|
|
|
_bootstrap(SRXL_DEVICE_ID); |
|
|
|
|
_last_handshake_ms = timestamp_us / 1000; |
|
|
|
|
} else { |
|
|
|
|
// not a handshake frame so reset without initializing the SRXL2 engine
|
|
|
|
|
_decode_state = STATE_IDLE; |
|
|
|
|
_buflen = 0; |
|
|
|
|
_frame_len_full = 0; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Try to parse SRXL packet -- this internally calls srxlRun() after packet is parsed and resets timeout
|
|
|
|
|
if (srxlParsePacket(0, _buffer, _frame_len_full)) { |
|
|
|
|
add_input(MAX_CHANNELS, _channels, _in_failsafe, _new_rssi); |
|
|
|
@ -228,9 +250,45 @@ void AP_RCProtocol_SRXL2::process_byte(uint8_t byte, uint32_t baudrate)
@@ -228,9 +250,45 @@ void AP_RCProtocol_SRXL2::process_byte(uint8_t byte, uint32_t baudrate)
|
|
|
|
|
if (baudrate != 115200) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_process_byte(AP_HAL::micros(), byte); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// handshake
|
|
|
|
|
void AP_RCProtocol_SRXL2::process_handshake(uint32_t baudrate) |
|
|
|
|
{ |
|
|
|
|
// only bootstrap if only SRXL2 is enabled
|
|
|
|
|
if (baudrate != 115200 || (get_rc_protocols_mask() & ~(1U<<(uint8_t(AP_RCProtocol::SRXL2)+1)))) { |
|
|
|
|
_handshake_start_ms = 0; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
uint32_t now = AP_HAL::millis(); |
|
|
|
|
|
|
|
|
|
// record the time of the first request in this cycle
|
|
|
|
|
if (_handshake_start_ms == 0) { |
|
|
|
|
_handshake_start_ms = now; |
|
|
|
|
// it seems the handshake protocol only sets the baudrate after receiving data
|
|
|
|
|
// since we are sending data unprompted make sure that the uart is set up correctly
|
|
|
|
|
_change_baud_rate(baudrate); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// we have not bootstrapped and attempts to listen first have failed
|
|
|
|
|
// we should receive a handshake request within the first 250ms
|
|
|
|
|
if (!is_bootstrapped() && now - _handshake_start_ms > 250) { |
|
|
|
|
_bootstrap(SRXL_DEVICE_ID_BASE_RX); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// certain RXs (e.g. AR620) are "listen-only" - they require the flight controller to initiate
|
|
|
|
|
// a handshake in order to switch to SRXL2 mode. This requires that we send data on the UART even
|
|
|
|
|
// if we have not decoded SRXL2 (recently). We try this every 50ms.
|
|
|
|
|
if (now - _handshake_start_ms > 250 && (_last_handshake_ms == 0 || (now - _last_run_ms > 50 && now - _last_handshake_ms > 50))) { |
|
|
|
|
_in_bootstrap_or_failsafe = true; |
|
|
|
|
srxlRun(0, 50); // 50 is a magic number at which the handshake protocol is initiated
|
|
|
|
|
_in_bootstrap_or_failsafe = false; |
|
|
|
|
_last_handshake_ms = now; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// send data to the uart
|
|
|
|
|
void AP_RCProtocol_SRXL2::send_on_uart(uint8_t* pBuffer, uint8_t length) |
|
|
|
|
{ |
|
|
|
@ -307,7 +365,7 @@ void AP_RCProtocol_SRXL2::_send_on_uart(uint8_t* pBuffer, uint8_t length)
@@ -307,7 +365,7 @@ void AP_RCProtocol_SRXL2::_send_on_uart(uint8_t* pBuffer, uint8_t length)
|
|
|
|
|
uint64_t tend = uart->receive_time_constraint_us(1); |
|
|
|
|
uint64_t now = AP_HAL::micros64(); |
|
|
|
|
uint64_t tdelay = now - tend; |
|
|
|
|
if (tdelay > 2000) { |
|
|
|
|
if (tdelay > 2000 && !_in_bootstrap_or_failsafe) { |
|
|
|
|
// we've been too slow in responding
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -338,6 +396,7 @@ void AP_RCProtocol_SRXL2::_change_baud_rate(uint32_t baudrate)
@@ -338,6 +396,7 @@ void AP_RCProtocol_SRXL2::_change_baud_rate(uint32_t baudrate)
|
|
|
|
|
uart->begin(baudrate); |
|
|
|
|
uart->set_flow_control(AP_HAL::UARTDriver::FLOW_CONTROL_DISABLE); |
|
|
|
|
uart->set_unbuffered_writes(true); |
|
|
|
|
uart->set_blocking_writes(false); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|