Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,16 @@ jobs:
with:
name: targets
path: targets.txt
- name: Save PR number
if: github.event_name == 'pull_request'
run: echo "${{ github.event.pull_request.number }}" > pr_number.txt
- name: Upload PR number
if: github.event_name == 'pull_request'
uses: actions/upload-artifact@v4
with:
name: pr-number
path: pr_number.txt
retention-days: 1

build-SITL-Linux-arm64:
runs-on: ubuntu-22.04-arm
Expand Down
153 changes: 153 additions & 0 deletions .github/workflows/pr-test-builds.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
name: PR Test Builds

# Runs after "Build firmware" completes. Uses workflow_run (rather than
# pull_request directly) so that secrets are available even for PRs from forks.
#
# Requires a repository secret PR_BUILDS_TOKEN with Contents: write access
# to iNavFlight/pr-test-builds (fine-grained PAT or classic PAT with repo scope).
on:
workflow_run:
workflows: ["Build firmware"]
types: [completed]

jobs:
publish:
runs-on: ubuntu-latest
# Only act on pull_request-triggered runs that succeeded.
if: >
github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.conclusion == 'success'
# Prevent concurrent runs for the same PR branch racing on the
# release delete/create cycle.
concurrency:
group: pr-test-build-${{ github.event.workflow_run.head_repository.full_name }}-${{ github.event.workflow_run.head_branch }}
cancel-in-progress: true
permissions:
actions: read # to download artifacts from the triggering workflow run
issues: write # github.rest.issues.* endpoints used to post PR comments
pull-requests: write # to post the PR comment

steps:
- name: Download PR number
uses: actions/download-artifact@v4
with:
name: pr-number
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Read PR number
id: pr
run: |
PR_NUM=$(tr -dc '0-9' < pr_number.txt)
if [ -z "$PR_NUM" ]; then
echo "::error::Invalid PR number in artifact"
exit 1
fi
echo "number=${PR_NUM}" >> $GITHUB_OUTPUT

- name: Download firmware artifacts
uses: actions/download-artifact@v4
with:
pattern: matrix-inav-*
merge-multiple: true
path: hexes
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Get build info
id: info
run: |
COUNT=$(find hexes -name '*.hex' -type f | wc -l)
if [ "$COUNT" -eq 0 ]; then
echo "::error::No .hex files found in downloaded artifacts"
exit 1
fi
echo "count=${COUNT}" >> $GITHUB_OUTPUT
echo "short_sha=$(echo '${{ github.event.workflow_run.head_sha }}' | cut -c1-7)" >> $GITHUB_OUTPUT

# Delete the previous release for this PR (if any) so assets are replaced
# cleanly on each new commit. --cleanup-tag removes the old tag so it is
# recreated fresh pointing to the new commit.
- name: Delete existing PR release
env:
GH_TOKEN: ${{ secrets.PR_BUILDS_TOKEN }}
run: |
gh release delete "pr-${{ steps.pr.outputs.number }}" \
--repo iNavFlight/pr-test-builds --cleanup-tag --yes 2>/dev/null || true

- name: Create PR release
env:
GH_TOKEN: ${{ secrets.PR_BUILDS_TOKEN }}
PR_NUMBER: ${{ steps.pr.outputs.number }}
SHORT_SHA: ${{ steps.info.outputs.short_sha }}
HEX_COUNT: ${{ steps.info.outputs.count }}
HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
REPO: ${{ github.repository }}
run: |
PR_URL="https://github.com/${REPO}/pull/${PR_NUMBER}"
printf '%s\n\n%s\n\n%s\n' \
"Test build for [PR #${PR_NUMBER}](${PR_URL}) — commit \`${SHORT_SHA}\`" \
"**${HEX_COUNT} targets built.** Find your board's \`.hex\` file by name (e.g. \`MATEKF405SE.hex\`)." \
"> Development build for testing only. Use Full Chip Erase when flashing." \
> release-notes.md
gh release create "pr-${PR_NUMBER}" hexes/*.hex \
--repo iNavFlight/pr-test-builds \
--prerelease \
--target "${HEAD_SHA}" \
--title "PR #${PR_NUMBER} (${SHORT_SHA})" \
--notes-file release-notes.md

- name: Post or update PR comment
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ steps.pr.outputs.number }}
SHORT_SHA: ${{ steps.info.outputs.short_sha }}
HEX_COUNT: ${{ steps.info.outputs.count }}
with:
script: |
const prNumber = parseInt(process.env.PR_NUMBER, 10);
if (isNaN(prNumber)) throw new Error(`Invalid PR number: ${process.env.PR_NUMBER}`);
const shortSha = process.env.SHORT_SHA;
const count = process.env.HEX_COUNT;
const releaseUrl = `https://github.com/iNavFlight/pr-test-builds/releases/tag/pr-${prNumber}`;

const body = [
'<!-- pr-test-build -->',
'**Test firmware build ready** — commit `' + shortSha + '`',
'',
`[Download firmware for PR #${prNumber}](${releaseUrl})`,
'',
`${count} targets built. Find your board's \`.hex\` file by name on that page ` +
'(e.g. `MATEKF405SE.hex`). Files are individually downloadable — no GitHub login required.',
'',
'> Development build for testing only. Use Full Chip Erase when flashing.',
].join('\n');

const comments = await github.paginate(
github.rest.issues.listComments,
{
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
}
);

const existing = comments.find(c =>
c.user.type === 'Bot' && c.body.includes('<!-- pr-test-build -->')
);

if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body,
});
}
2 changes: 1 addition & 1 deletion docs/policies/NEW_HARDWARE_POLICY.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ If one of the core developers has the hardware in possession they may opt in and

1. Requester is advised to open a feature request to add support for certain hardware to INAV by following [this link](https://github.com/iNavFlight/inav/issues/new/choose)

2. After opening a feature request, Requester is advised to contact the core development team by [email](mailto:coredev@inavflight.com) mentioning the open feature request and communicate with developer team via email to arrange hardware and specifications delivery.
2. After opening a feature request, Requester is advised to contact the core development team via [Discord](https://discord.gg/peg2hhbYwN) mentioning the open feature request and communicate with developer team via email to arrange hardware and specifications delivery.


## See also
Expand Down
2 changes: 1 addition & 1 deletion src/main/blackbox/blackbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
#define BLACKBOX_INVERTED_CARD_DETECTION 0
#endif

PG_REGISTER_WITH_RESET_TEMPLATE(blackboxConfig_t, blackboxConfig, PG_BLACKBOX_CONFIG, 4);
PG_REGISTER_WITH_RESET_TEMPLATE(blackboxConfig_t, blackboxConfig, PG_BLACKBOX_CONFIG, 5);

PG_RESET_TEMPLATE(blackboxConfig_t, blackboxConfig,
.device = DEFAULT_BLACKBOX_DEVICE,
Expand Down
2 changes: 1 addition & 1 deletion src/main/blackbox/blackbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ typedef enum BlackboxState {
} BlackboxState;

typedef struct blackboxConfig_s {
uint32_t includeFlags;
uint16_t rate_num;
uint16_t rate_denom;
uint8_t device;
uint8_t invertedCardDetection;
uint32_t includeFlags;
int8_t arm_control;
} blackboxConfig_t;

Expand Down
2 changes: 1 addition & 1 deletion src/main/fc/stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#define MIN_FLIGHT_DISTANCE_M 30 // minimum distance flown for a flight to be registered [m]


PG_REGISTER_WITH_RESET_TEMPLATE(statsConfig_t, statsConfig, PG_STATS_CONFIG, 2);
PG_REGISTER_WITH_RESET_TEMPLATE(statsConfig_t, statsConfig, PG_STATS_CONFIG, 3);

PG_RESET_TEMPLATE(statsConfig_t, statsConfig,
.stats_enabled = SETTING_STATS_DEFAULT,
Expand Down
2 changes: 1 addition & 1 deletion src/main/fc/stats.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
typedef struct statsConfig_s {
uint32_t stats_total_time; // [Seconds]
uint32_t stats_total_dist; // [Metres]
uint16_t stats_flight_count;
#ifdef USE_ADC
uint32_t stats_total_energy; // deciWatt hour (x0.1Wh)
#endif
uint16_t stats_flight_count;
uint8_t stats_enabled;
} statsConfig_t;

Expand Down
2 changes: 1 addition & 1 deletion src/main/flight/pid.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ static EXTENDED_FASTRAM bool angleHoldIsLevel = false;
static EXTENDED_FASTRAM float fixedWingLevelTrim;
static EXTENDED_FASTRAM pidController_t fixedWingLevelTrimController;

PG_REGISTER_PROFILE_WITH_RESET_TEMPLATE(pidProfile_t, pidProfile, PG_PID_PROFILE, 11);
PG_REGISTER_PROFILE_WITH_RESET_TEMPLATE(pidProfile_t, pidProfile, PG_PID_PROFILE, 12);

PG_RESET_TEMPLATE(pidProfile_t, pidProfile,
.bank_mc = {
Expand Down
73 changes: 37 additions & 36 deletions src/main/flight/pid.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,71 +97,72 @@ typedef enum {
} itermRelax_e;

typedef struct pidProfile_s {
uint8_t pidControllerType;
// Fields ordered largest-to-smallest to eliminate alignment padding holes
pidBank_t bank_fw;
pidBank_t bank_mc;

uint8_t dterm_lpf_type; // Dterm LPF type: PT1, BIQUAD
uint16_t dterm_lpf_hz;

uint8_t yaw_lpf_hz;

uint8_t heading_hold_rate_limit; // Maximum rotation rate HEADING_HOLD mode can feed to yaw rate PID controller

uint8_t itermWindupPointPercent; // Experimental ITerm windup threshold, percent of motor saturation

uint32_t axisAccelerationLimitYaw; // Max rate of change of yaw angular rate setpoint (deg/s^2 = dps/s)
uint32_t axisAccelerationLimitRollPitch; // Max rate of change of roll/pitch angular rate setpoint (deg/s^2 = dps/s)

int16_t max_angle_inclination[ANGLE_INDEX_COUNT]; // Max possible inclination (roll and pitch axis separately

uint16_t pidItermLimitPercent;

// Airplane-specific parameters
float fixedWingReferenceAirspeed; // Reference tuning airspeed for the airplane - the speed for which PID gains are tuned
float fixedWingCoordinatedYawGain; // This is the gain of the yaw rate required to keep the yaw rate consistent with the turn rate for a coordinated turn.
float fixedWingCoordinatedPitchGain; // This is the gain of the pitch rate to keep the pitch angle constant during coordinated turns.
uint16_t fixedWingYawItermBankFreeze; // Freeze yaw Iterm when bank angle is more than this many degrees

float fixedWingCoordinatedPitchGain; // This is the gain of the pitch rate to keep the pitch angle constant during coordinated turns.
float navVelXyDTermLpfHz;
uint8_t navVelXyDtermAttenuation; // VEL_XY dynamic Dterm scale: Dterm will be attenuatedby this value (in percent) when UAV is traveling with more than navVelXyDtermAttenuationStart percents of max velocity
uint8_t navVelXyDtermAttenuationStart; // VEL_XY dynamic Dterm scale: Dterm attenuation will begin at this percent of max velocity
uint8_t navVelXyDtermAttenuationEnd; // VEL_XY dynamic Dterm scale: Dterm will be fully attenuated at this percent of max velocity
uint8_t iterm_relax_cutoff; // This cutoff frequency specifies a low pass filter which predicts average response of the quad to setpoint
uint8_t iterm_relax; // Enable iterm suppression during stick input
float fixedWingLevelTrim;
float fixedWingLevelTrimGain;

#ifdef USE_D_BOOST
float dBoostMin;
float dBoostMax;
float dBoostMaxAtAlleceleration;
uint8_t dBoostGyroDeltaLpfHz;
#endif

#ifdef USE_ANTIGRAVITY
float antigravityGain;
float antigravityAccelerator;
uint8_t antigravityCutoff;
#endif

uint16_t navFwPosHdgPidsumLimit;
uint8_t controlDerivativeLpfHz;

float fixedWingLevelTrim;
float fixedWingLevelTrimGain;

uint8_t fwAltControlResponseFactor;
bool fwAltControlUsePos;
#ifdef USE_SMITH_PREDICTOR
float smithPredictorStrength;
float smithPredictorDelay;
uint16_t smithPredictorFilterHz;
#endif

uint32_t axisAccelerationLimitYaw; // Max rate of change of yaw angular rate setpoint (deg/s^2 = dps/s)
uint32_t axisAccelerationLimitRollPitch; // Max rate of change of roll/pitch angular rate setpoint (deg/s^2 = dps/s)

int16_t max_angle_inclination[ANGLE_INDEX_COUNT]; // Max possible inclination (roll and pitch axis separately
uint16_t pidItermLimitPercent;
uint16_t fixedWingYawItermBankFreeze; // Freeze yaw Iterm when bank angle is more than this many degrees
uint16_t navFwPosHdgPidsumLimit;
uint16_t fwItermLockTimeMaxMs;
uint16_t dterm_lpf_hz;

#ifdef USE_SMITH_PREDICTOR
uint16_t smithPredictorFilterHz;
#endif

uint8_t pidControllerType;
uint8_t dterm_lpf_type; // Dterm LPF type: PT1, BIQUAD
uint8_t yaw_lpf_hz;
uint8_t heading_hold_rate_limit; // Maximum rotation rate HEADING_HOLD mode can feed to yaw rate PID controller
uint8_t itermWindupPointPercent; // Experimental ITerm windup threshold, percent of motor saturation
uint8_t navVelXyDtermAttenuation; // VEL_XY dynamic Dterm scale: Dterm will be attenuated by this value (in percent) when UAV is traveling with more than navVelXyDtermAttenuationStart percents of max velocity
uint8_t navVelXyDtermAttenuationStart; // VEL_XY dynamic Dterm scale: Dterm attenuation will begin at this percent of max velocity
uint8_t navVelXyDtermAttenuationEnd; // VEL_XY dynamic Dterm scale: Dterm will be fully attenuated at this percent of max velocity
uint8_t iterm_relax_cutoff; // This cutoff frequency specifies a low pass filter which predicts average response of the quad to setpoint
uint8_t iterm_relax; // Enable iterm suppression during stick input
uint8_t controlDerivativeLpfHz;
uint8_t fwAltControlResponseFactor;
bool fwAltControlUsePos;
uint8_t fwItermLockRateLimit;
uint8_t fwItermLockEngageThreshold;

#ifdef USE_D_BOOST
uint8_t dBoostGyroDeltaLpfHz;
#endif

#ifdef USE_ANTIGRAVITY
uint8_t antigravityCutoff;
#endif

} pidProfile_t;

typedef struct pidAutotuneConfig_s {
Expand Down
30 changes: 0 additions & 30 deletions src/main/io/displayport_msp_osd.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@
typedef enum { // defines are from hdzero code
SD_3016,
HD_5018,
HD_3016, // Special HDZERO mode that just sends the centre 30x16 of the 50x18 canvas to the VRX
HD_6022, // added to support DJI wtfos 60x22 grid
HD_5320 // added to support Avatar and BetaflightHD
} resolutionType_e;
Expand Down Expand Up @@ -139,31 +138,6 @@ static int output(displayPort_t *displayPort, uint8_t cmd, uint8_t *subcmd, int
return sent;
}

static uint8_t determineHDZeroOsdMode(void)
{
if (cmsInMenu) {
return HD_5018;
}

// Check if all visible widgets are in the center 30x16 chars of the canvas.
int activeLayout = osdGetActiveLayout(NULL);
osd_items_e index = 0;
do {
index = osdIncElementIndex(index);
uint16_t pos = osdLayoutsConfig()->item_pos[activeLayout][index];
if (OSD_VISIBLE(pos)) {
uint8_t elemPosX = OSD_X(pos);
uint8_t elemPosY = OSD_Y(pos);
if (!osdItemIsFixed(index) && (elemPosX < 10 || elemPosX > 39 || elemPosY == 0 || elemPosY == 17)) {
return HD_5018;
}
}
} while (index > 0);

return HD_3016;
}


uint8_t setAttrPage(uint8_t origAttr, uint8_t page)
{
return (origAttr & ~DISPLAYPORT_MSP_ATTR_FONTPAGE_MASK) | (page & DISPLAYPORT_MSP_ATTR_FONTPAGE_MASK);
Expand All @@ -181,10 +155,6 @@ uint8_t setAttrVersion(uint8_t origAttr, uint8_t version)

static int setDisplayMode(displayPort_t *displayPort)
{
if (osdVideoSystem == VIDEO_SYSTEM_HDZERO) {
currentOsdMode = determineHDZeroOsdMode(); // Can change between layouts
}

uint8_t subcmd[] = { MSP_DP_OPTIONS, 0, currentOsdMode }; // Font selection, mode (SD/HD)
return output(displayPort, MSP_DISPLAYPORT, subcmd, sizeof(subcmd));
}
Expand Down
Loading
Loading