Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
426 changes: 426 additions & 0 deletions .github/copilot-instructions.md

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion .github/scripts/check-pg-versions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,9 @@ while IFS= read -r file; do
fi

# Determine companion file (.c <-> .h)
local companion=""
# NOTE: this loop runs in the main script body, not inside a function, so
# `local` is invalid here and aborts the script under `set -e`.
companion=""
if [[ "$file" == *.c ]]; then
companion="${file%.c}.h"
elif [[ "$file" == *.h ]]; then
Expand Down
1 change: 1 addition & 0 deletions docs/Settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -3273,6 +3273,7 @@ Protocol that is used to send motor updates to ESCs. Possible values - STANDARD,
| DSHOT150 | |
| DSHOT300 | |
| DSHOT600 | |
| SRXL2 | |

---

Expand Down
2 changes: 2 additions & 0 deletions src/main/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,8 @@ main_sources(COMMON_SRC
drivers/rcc.h
drivers/serial.c
drivers/serial.h
drivers/srxl2_esc.c
drivers/srxl2_esc.h
drivers/sound_beeper.c
drivers/sound_beeper.h
drivers/stack_check.c
Expand Down
6 changes: 4 additions & 2 deletions src/main/common/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,10 @@ void _logBufferHex(logTopic_e topic, unsigned level, const void *buffer, size_t
{
// Print lines of up to maxBytes bytes. We need 5 characters per byte
// 0xAB[space|\n]
const size_t charsPerByte = 5;
const size_t maxBytes = 8;
// Use enum constants (not const size_t locals) so the buffer size is a true
// integer constant expression. Newer Apple clang otherwise folds the const
// locals and reports the array as a VLA (-Werror=gnu-folding-constant).
enum { charsPerByte = 5, maxBytes = 8 };
char buf[LOG_PREFIX_FORMATTED_SIZE + charsPerByte * maxBytes + 1]; // +1 for the null terminator
size_t bufPos = LOG_PREFIX_FORMATTED_SIZE;
const uint8_t *inputPtr = buffer;
Expand Down
1 change: 1 addition & 0 deletions src/main/drivers/pwm_mapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ static const motorProtocolProperties_t motorProtocolProperties[] = {
[PWM_TYPE_DSHOT150] = { .usesHwTimer = true, .isDSHOT = true },
[PWM_TYPE_DSHOT300] = { .usesHwTimer = true, .isDSHOT = true },
[PWM_TYPE_DSHOT600] = { .usesHwTimer = true, .isDSHOT = true },
[PWM_TYPE_SRXL2] = { .usesHwTimer = false, .isDSHOT = false },
};

pwmInitError_e getPwmInitError(void)
Expand Down
1 change: 1 addition & 0 deletions src/main/drivers/pwm_mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ typedef enum {
PWM_TYPE_DSHOT150,
PWM_TYPE_DSHOT300,
PWM_TYPE_DSHOT600,
PWM_TYPE_SRXL2,
} motorPwmProtocolTypes_e;

typedef enum {
Expand Down
55 changes: 46 additions & 9 deletions src/main/drivers/pwm_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "drivers/timer.h"
#include "drivers/pwm_mapping.h"
#include "drivers/pwm_output.h"
#include "drivers/srxl2_esc.h"
#include "io/servo_sbus.h"
#include "sensors/esc_sensor.h"

Expand Down Expand Up @@ -211,6 +212,11 @@ static void pwmWriteStandard(uint8_t index, uint16_t value)
}
}

static void pwmWriteSrxl2(uint8_t index, uint16_t value)
{
srxl2EscWriteMotor(index, value);
}

void pwmWriteMotor(uint8_t index, uint16_t value)
{
if (motorWritePtr && index < MAX_MOTORS && pwmMotorsEnabled) {
Expand Down Expand Up @@ -518,7 +524,27 @@ static bool executeDShotCommands(void){
}
#endif

#else // digital motor protocol

// This stub is needed to avoid ESC_SENSOR dependency on DSHOT
void pwmRequestMotorTelemetry(int motorIndex)
{
UNUSED(motorIndex);
}

#endif

// pwmCompleteMotorUpdate must also exist for SRXL2-only targets (no DSHOT),
// where it just drives the SRXL2 transmit. The digital/DSHOT body below is
// kept behind USE_DSHOT so it is omitted on those targets.
#if defined(USE_DSHOT) || defined(USE_SRXL2_ESC)
void pwmCompleteMotorUpdate(void) {
if (initMotorProtocol == PWM_TYPE_SRXL2) {
srxl2EscUpdate(micros());
return;
}

#ifdef USE_DSHOT
// This only makes sense for digital motor protocols
if (!isMotorProtocolDigital()) {
return;
Expand Down Expand Up @@ -574,16 +600,8 @@ void pwmCompleteMotorUpdate(void) {
#endif
}
#endif
#endif
}

#else // digital motor protocol

// This stub is needed to avoid ESC_SENSOR dependency on DSHOT
void pwmRequestMotorTelemetry(int motorIndex)
{
UNUSED(motorIndex);
}

#endif

void pwmMotorPreconfigure(void)
Expand All @@ -608,6 +626,18 @@ void pwmMotorPreconfigure(void)
motorWritePtr = pwmWriteStandard;
break;

case PWM_TYPE_SRXL2:
// SRXL2 paces its own transmissions inside srxl2EscUpdate() and
// pwmCompleteMotorUpdate() returns early for it, so the digital update
// interval is unused here. Avoid calling motorConfigDigitalUpdateInterval()
// which is only defined when USE_DSHOT is enabled.
if (srxl2EscInit()) {
motorWritePtr = pwmWriteSrxl2;
} else {
motorWritePtr = pwmWriteNull;
}
break;

#ifdef USE_DSHOT
case PWM_TYPE_DSHOT600:
case PWM_TYPE_DSHOT300:
Expand Down Expand Up @@ -642,6 +672,9 @@ uint32_t getEscUpdateFrequency(void) {
case PWM_TYPE_DSHOT600:
return 16000;

case PWM_TYPE_SRXL2:
return SRXL2_ESC_UPDATE_HZ;

case PWM_TYPE_ONESHOT125:
default:
return 1000;
Expand Down Expand Up @@ -676,6 +709,10 @@ bool pwmMotorConfig(const timerHardware_t *timerHardware, uint8_t motorIndex, bo
motors[motorIndex].pwmPort = motorConfigPwm(timerHardware, 1e-3f, 1e-3f, getEscUpdateFrequency(), enableOutput);
break;

case PWM_TYPE_SRXL2:
motors[motorIndex].pwmPort = NULL;
break;

default:
motors[motorIndex].pwmPort = NULL;
break;
Expand Down
Loading
Loading