mirror of
https://github.com/betaflight/betaflight-configurator.git
synced 2025-07-14 20:10:13 +03:00
Merge pull request #2296 from limonspb/esc_dshot_reverse
This commit is contained in:
commit
d5d0146af7
20 changed files with 1255 additions and 103 deletions
|
@ -2586,6 +2586,82 @@
|
|||
"message": "Start over"
|
||||
},
|
||||
|
||||
"escDshotDirectionDialog-Title": {
|
||||
"message": "Motor Direction - <strong class=\"message-negative-italic\">Warning: Ensure props are removed!</strong>"
|
||||
},
|
||||
"escDshotDirectionDialog-SelectMotor": {
|
||||
"message": "Select one or all motors"
|
||||
},
|
||||
"escDshotDirectionDialog-SelectMotorSafety": {
|
||||
"message": "Motors will spin when selected!"
|
||||
},
|
||||
"escDshotDirectionDialog-RiskNotice": {
|
||||
"message": "<strong>Safety notice</strong><br /><strong class=\"message-negative-italic\">Remove all propellers to prevent injury!</strong><br />The motors will <strong>spin up</strong> immediately when selected!"
|
||||
},
|
||||
"escDshotDirectionDialog-UnderstandRisks": {
|
||||
"message": "<strong>I understand the risks</strong>,<br />all propellers are removed."
|
||||
},
|
||||
"escDshotDirectionDialog-InformationNotice": {
|
||||
"message": "<strong>Information notice</strong><br />To change the motor directions, the battery must be plugged in and the correct ESC protocol must be set up in the $t(tabConfiguration.message) tab. Note that not all Dshot ESCs will work with this dialog. Check your ESC firmware."
|
||||
},
|
||||
"escDshotDirectionDialog-NormalInformationNotice": {
|
||||
"message": "Set motor spin direction by selecting and spinning each motor individually."
|
||||
},
|
||||
"escDshotDirectionDialog-WizardInformationNotice": {
|
||||
"message": "Resets all motor spin directions, then allows the user to choose which to reverse."
|
||||
},
|
||||
"escDshotDirectionDialog-Open": {
|
||||
"message": "Motor direction"
|
||||
},
|
||||
"escDshotDirectionDialog-CommandNormal": {
|
||||
"message": "Normal"
|
||||
},
|
||||
"escDshotDirectionDialog-CommandReverse": {
|
||||
"message": "Reverse"
|
||||
},
|
||||
"escDshotDirectionDialog-CommandSpin": {
|
||||
"message": "Test motor"
|
||||
},
|
||||
"escDshotDirectionDialog-ReleaseButtonToStop": {
|
||||
"message": "Release button to stop"
|
||||
},
|
||||
"escDshotDirectionDialog-ReleaseToStop": {
|
||||
"message": "Release to stop"
|
||||
},
|
||||
"escDshotDirectionDialog-Start": {
|
||||
"message": "Individually"
|
||||
},
|
||||
"escDshotDirectionDialog-StartWizard": {
|
||||
"message": "Wizard"
|
||||
},
|
||||
"escDshotDirectionDialog-SetDirectionHint": {
|
||||
"message": "Change direction of selected motor(s)"
|
||||
},
|
||||
"escDshotDirectionDialog-SetDirectionHintSafety": {
|
||||
"message": "Motors will spin when setting the direction!"
|
||||
},
|
||||
"escDshotDirectionDialog-WrongProtocolText": {
|
||||
"message": "Feature works with DSHOT ESCs only.<br />Verify that your ESC (electric speed controller) supports DSHOT protocol and change it on $t(tabConfiguration.message) tab."
|
||||
},
|
||||
"escDshotDirectionDialog-WrongMixerText": {
|
||||
"message": "Number of motors is 0.<br />Verify the current Mixer on $t(tabConfiguration.message) tab or setup a custom one through CLI. Refer to this <a href=\"https://github.com/betaflight/betaflight/blob/master/docs/Mixer.md\" target=\"_blank\" rel=\"noopener noreferrer\">Wiki page</a>."
|
||||
},
|
||||
"escDshotDirectionDialog-WrongFirmwareText": {
|
||||
"message": "Update the firmware.<br /> Make sure you are using the latest firmware: Betaflight 4.3 or newer."
|
||||
},
|
||||
"escDshotDirectionDialog-WizardActionHint": {
|
||||
"message": "Click on motor numbers individually to change spin direction"
|
||||
},
|
||||
"escDshotDirectionDialog-WizardActionHintSecondLine": {
|
||||
"message": "Verify all motors are spinning correctly"
|
||||
},
|
||||
"escDshotDirectionDialog-SpinWizard": {
|
||||
"message": "Start / spin motors"
|
||||
},
|
||||
"escDshotDirectionDialog-StopWizard": {
|
||||
"message": "Stop motors"
|
||||
},
|
||||
|
||||
"sensorsInfo": {
|
||||
"message": "Keep in mind that using fast update periods and rendering multiple graphs at the same time is resource heavy and will burn your battery quicker if you use a laptop.<br />We recommend to only render graphs for sensors you are interested in while using reasonable update periods."
|
||||
},
|
||||
|
|
66
src/components/EscDshotDirection/Body.html
Normal file
66
src/components/EscDshotDirection/Body.html
Normal file
|
@ -0,0 +1,66 @@
|
|||
<div class="escDshotDirection-Component">
|
||||
<h3 i18n="escDshotDirectionDialog-Title" class="escDshotDirection-ComponentHeader"></h3>
|
||||
<div class="componentContent" id="escDshotDirectionDialog-ConfigErrors">
|
||||
<div class="escDshotDirectionErrorTextBlock" id="escDshotDirectionDialog-WrongProtocol" i18n="escDshotDirectionDialog-WrongProtocolText"></div>
|
||||
<div class="escDshotDirectionErrorTextBlock" id="escDshotDirectionDialog-WrongMixer" i18n="escDshotDirectionDialog-WrongMixerText"></div>
|
||||
<div class="escDshotDirectionErrorTextBlock" id="escDshotDirectionDialog-WrongFirmware" i18n="escDshotDirectionDialog-WrongFirmwareText"></div>
|
||||
</div>
|
||||
<div class="componentContent" id="escDshotDirectionDialog-MainContent">
|
||||
<div id="escDshotDirectionDialog-MixerPreview" class="grey">
|
||||
<img id="escDshotDirectionDialog-MixerPreviewImg" alt="" src="./resources/motor_order/custom.svg" />
|
||||
</div>
|
||||
<div id="escDshotDirectionDialog-NormalDialog" class="display-contents">
|
||||
<h4 id="escDshotDirectionDialog-ActionHint" i18n="escDshotDirectionDialog-SelectMotor"></h4>
|
||||
<h4 id="escDshotDirectionDialog-ActionHintSafety" i18n="escDshotDirectionDialog-SelectMotorSafety"></h4>
|
||||
<div id="escDshotDirectionDialog-SelectMotorButtonsWrapper">
|
||||
</div>
|
||||
<div id = "escDshotDirectionDialog-SecondActionBlock" class="display-contents">
|
||||
<h4 id="escDshotDirectionDialog-SecondHint" i18n="escDshotDirectionDialog-SetDirectionHint"></h4>
|
||||
<h4 id="escDshotDirectionDialog-SecondHintSafety" i18n="escDshotDirectionDialog-SetDirectionHintSafety"></h4>
|
||||
<div id="escDshotDirectionDialog-CommandsWrapper">
|
||||
<a href="#" id="escDshotDirectionDialog-RotationNormal" class="regular-button" i18n="escDshotDirectionDialog-CommandNormal"></a>
|
||||
<a href="#" id="escDshotDirectionDialog-RotationReverse" class="regular-button" i18n="escDshotDirectionDialog-CommandReverse"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="escDshotDirectionDialog-WizardDialog" class="display-contents">
|
||||
<a href="#" id="escDshotDirectionDialog-SpinWizard" class="regular-button" i18n="escDshotDirectionDialog-SpinWizard"></a>
|
||||
<div id="escDshotDirectionDialog-SpinningWizard" class="display-contents">
|
||||
<h4 id="escDshotDirectionDialog-WizardActionHint" i18n="escDshotDirectionDialog-WizardActionHint"></h4>
|
||||
<h4 id="escDshotDirectionDialog-WizardActionHintSecondLine" i18n="escDshotDirectionDialog-WizardActionHintSecondLine"></h4>
|
||||
<div id="escDshotDirectionDialog-WizardMotorButtons">
|
||||
</div>
|
||||
<a href="#" id="escDshotDirectionDialog-StopWizard" class="regular-button" i18n="escDshotDirectionDialog-StopWizard"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="componentContent" id="escDshotDirectionDialog-Warning">
|
||||
<div>
|
||||
<p class="escDshotDirectionDialog-RiskNoticeText" i18n="escDshotDirectionDialog-RiskNotice"></p>
|
||||
<div class="escDshotDirectionToggleParentContainer">
|
||||
<div class="escDshotDirectionToggleNarrow">
|
||||
<input id="escDshotDirectionDialog-safetyCheckbox" type="checkbox" class="toggle"/>
|
||||
</div>
|
||||
<div class="escDshotDirectionDialog-ToggleWide">
|
||||
<span class="motorsEnableTestMode escDshotDirectionDialog-RiskNoticeText" i18n="escDshotDirectionDialog-UnderstandRisks"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="escDshotDirectionDialog-InformationNotice" i18n="escDshotDirectionDialog-InformationNotice"></div>
|
||||
|
||||
<div id="escDshotDirectionDialog-StartWizardBlock" class="escDshotDirectionDialog-StartBlock">
|
||||
<div class="escDshotDirectionDialog-Buttons">
|
||||
<a href="#" id="escDshotDirectionDialog-StartWizard" class="regular-button escDshotDirectionDialog-StartButton" i18n="escDshotDirectionDialog-StartWizard"></a>
|
||||
</div>
|
||||
<div class="escDshotDirectionDialog-Description" i18n="escDshotDirectionDialog-WizardInformationNotice"></div>
|
||||
</div>
|
||||
|
||||
<div id="escDshotDirectionDialog-StartNormalBlock" class="escDshotDirectionDialog-StartBlock">
|
||||
<div class="escDshotDirectionDialog-Buttons">
|
||||
<a href="#" id="escDshotDirectionDialog-Start" class="regular-button escDshotDirectionDialog-StartButton" i18n="escDshotDirectionDialog-Start"></a>
|
||||
</div>
|
||||
<div class="escDshotDirectionDialog-Description" i18n="escDshotDirectionDialog-NormalInformationNotice"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
67
src/components/EscDshotDirection/EscDshotCommandQueue.js
Normal file
67
src/components/EscDshotDirection/EscDshotCommandQueue.js
Normal file
|
@ -0,0 +1,67 @@
|
|||
'use strict';
|
||||
|
||||
class EscDshotCommandQueue
|
||||
{
|
||||
constructor (intervalMs)
|
||||
{
|
||||
this._intervalId = null;
|
||||
this._interval = intervalMs;
|
||||
this._queue = [];
|
||||
this._purging = false;
|
||||
}
|
||||
|
||||
pushCommand(command, buffer)
|
||||
{
|
||||
this._queue.push([command, buffer]);
|
||||
}
|
||||
|
||||
pushPause(milliseconds)
|
||||
{
|
||||
const counter = Math.ceil(milliseconds / this._interval);
|
||||
|
||||
for (let i = 0; i < counter; i++) {
|
||||
this.pushCommand(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
start()
|
||||
{
|
||||
if (null === this._intervalId) {
|
||||
this._intervalId = setInterval(
|
||||
() => { this._checkQueue(); },
|
||||
this._interval);
|
||||
}
|
||||
}
|
||||
|
||||
stop()
|
||||
{
|
||||
if(null !== this._intervalId) {
|
||||
clearInterval(this._intervalId);
|
||||
this._intervalId = null;
|
||||
}
|
||||
}
|
||||
|
||||
stopWhenEmpty()
|
||||
{
|
||||
this._purging = true;
|
||||
}
|
||||
|
||||
clear()
|
||||
{
|
||||
this._queue = [];
|
||||
}
|
||||
|
||||
_checkQueue()
|
||||
{
|
||||
if (0 !== this._queue.length) {
|
||||
const command = this._queue.shift();
|
||||
|
||||
if (null !== command[0]) {
|
||||
MSP.send_message(command[0], command[1]);
|
||||
}
|
||||
} else if (this._purging) {
|
||||
this._purging = false;
|
||||
this.stop();
|
||||
}
|
||||
}
|
||||
}
|
383
src/components/EscDshotDirection/EscDshotDirectionComponent.js
Normal file
383
src/components/EscDshotDirection/EscDshotDirectionComponent.js
Normal file
|
@ -0,0 +1,383 @@
|
|||
'use strict';
|
||||
|
||||
class EscDshotDirectionComponent
|
||||
{
|
||||
constructor(contentDiv, onLoadedCallback, motorConfig)
|
||||
{
|
||||
this._buttonTimeoutMs = 400;
|
||||
const motorDriverQueueIntervalMs = 100;
|
||||
const motorDriverStopMotorsPauseMs = 400;
|
||||
|
||||
this._motorDriver = new EscDshotDirectionMotorDriver(motorConfig,
|
||||
motorDriverQueueIntervalMs, motorDriverStopMotorsPauseMs);
|
||||
this._escProtocolIsDshot = motorConfig.escProtocolIsDshot;
|
||||
this._numberOfMotors = motorConfig.numberOfMotors;
|
||||
this._contentDiv = contentDiv;
|
||||
this._onLoadedCallback = onLoadedCallback;
|
||||
this._currentSpinningMotor = -1;
|
||||
this._selectedMotor = -1;
|
||||
this._motorIsSpinning = false;
|
||||
this._allMotorsAreSpinning = false;
|
||||
this._spinDirectionToggleIsActive = true;
|
||||
this._activationButtonTimeoutId = null;
|
||||
|
||||
this._contentDiv.load("./components/EscDshotDirection/Body.html", () =>
|
||||
{
|
||||
this._initializeDialog();
|
||||
});
|
||||
}
|
||||
|
||||
static get PUSHED_BUTTON_CLASS() { return "pushed"; }
|
||||
static get HIGHLIGHTED_BUTTON_CLASS() { return "highlighted"; }
|
||||
static get RED_TEXT_CLASS() { return "red-text"; }
|
||||
|
||||
_readDom()
|
||||
{
|
||||
this._domAgreeSafetyCheckBox = $("#escDshotDirectionDialog-safetyCheckbox");
|
||||
this._domStartButton = $("#escDshotDirectionDialog-Start");
|
||||
this._domStartWizardButton = $("#escDshotDirectionDialog-StartWizard");
|
||||
this._domMainContentBlock = $("#escDshotDirectionDialog-MainContent");
|
||||
this._domWarningContentBlock = $("#escDshotDirectionDialog-Warning");
|
||||
this._domMixerImg = $("#escDshotDirectionDialog-MixerPreviewImg");
|
||||
this._domMotorButtonsBlock = $("#escDshotDirectionDialog-SelectMotorButtonsWrapper");
|
||||
this._domSpinDirectionWrapper = $("#escDshotDirectionDialog-CommandsWrapper");
|
||||
this._domActionHint = $("#escDshotDirectionDialog-ActionHint");
|
||||
this._domSpinNormalButton = $("#escDshotDirectionDialog-RotationNormal");
|
||||
this._domSpinReverseButton = $("#escDshotDirectionDialog-RotationReverse");
|
||||
this._domSecondHint = $("#escDshotDirectionDialog-SecondHint");
|
||||
this._domSecondActionDiv = $("#escDshotDirectionDialog-SecondActionBlock");
|
||||
this._domConfigErrors = $("#escDshotDirectionDialog-ConfigErrors");
|
||||
this._domWrongProtocolMessage = $("#escDshotDirectionDialog-WrongProtocol");
|
||||
this._domWrongMixerMessage = $("#escDshotDirectionDialog-WrongMixer");
|
||||
this._domWrongFirmwareMessage = $("#escDshotDirectionDialog-WrongFirmware");
|
||||
this._domWizardBlock = $("#escDshotDirectionDialog-WizardDialog");
|
||||
this._domNormalDialogBlock = $("#escDshotDirectionDialog-NormalDialog");
|
||||
this._domSpinningWizard = $("#escDshotDirectionDialog-SpinningWizard");
|
||||
this._domSpinWizardButton = $("#escDshotDirectionDialog-SpinWizard");
|
||||
this._domStopWizardButton = $("#escDshotDirectionDialog-StopWizard");
|
||||
this._domWizardMotorButtonsBlock = $("#escDshotDirectionDialog-WizardMotorButtons");
|
||||
this._domStartWizardBlock = $("#escDshotDirectionDialog-StartWizardBlock");
|
||||
this._domStartNormalBlock = $("#escDshotDirectionDialog-StartNormalBlock");
|
||||
|
||||
this._topHintText = i18n.getMessage("escDshotDirectionDialog-SelectMotor");
|
||||
this._releaseToStopText = i18n.getMessage("escDshotDirectionDialog-ReleaseToStop");
|
||||
this._releaseButtonToStopText = i18n.getMessage("escDshotDirectionDialog-ReleaseButtonToStop");
|
||||
this._normalText = i18n.getMessage("escDshotDirectionDialog-CommandNormal");
|
||||
this._reverseText = i18n.getMessage("escDshotDirectionDialog-CommandReverse");
|
||||
this._secondHintText = i18n.getMessage("escDshotDirectionDialog-SetDirectionHint");
|
||||
}
|
||||
|
||||
_initializeDialog()
|
||||
{
|
||||
this._readDom();
|
||||
this._createMotorButtons();
|
||||
this._createWizardMotorButtons();
|
||||
this._domSecondActionDiv.toggle(false);
|
||||
i18n.localizePage();
|
||||
|
||||
this._resetGui();
|
||||
|
||||
this._domAgreeSafetyCheckBox.on("change", () => {
|
||||
const enabled = this._domAgreeSafetyCheckBox.is(':checked');
|
||||
this._domStartNormalBlock.toggle(enabled);
|
||||
this._domStartWizardBlock.toggle(enabled);
|
||||
});
|
||||
|
||||
this._domStartButton.on("click", () => {
|
||||
this._onStartButtonClicked();
|
||||
});
|
||||
|
||||
this._domStartWizardButton.on("click", () => {
|
||||
this._onStartWizardButtonClicked();
|
||||
});
|
||||
|
||||
this._domSpinWizardButton.on("click", () => {
|
||||
this._onSpinWizardButtonClicked();
|
||||
});
|
||||
|
||||
this._domStopWizardButton.on("click", () => {
|
||||
this._onStopWizardButtonClicked();
|
||||
});
|
||||
|
||||
const imgSrc = CommonUtils.GetMixerImageSrc(FC.MIXER_CONFIG.mixer, FC.MIXER_CONFIG.reverseMotorDir, FC.CONFIG.apiVersion);
|
||||
this._domMixerImg.attr('src', imgSrc);
|
||||
|
||||
this._onLoadedCallback();
|
||||
}
|
||||
|
||||
_activateNormalReverseButtons(timeoutMs)
|
||||
{
|
||||
this._activationButtonTimeoutId = setTimeout(() => {
|
||||
this._subscribeDirectionSpinButton(this._domSpinNormalButton,
|
||||
DshotCommand.dshotCommands_e.DSHOT_CMD_SPIN_DIRECTION_1, this._normalText);
|
||||
this._subscribeDirectionSpinButton(this._domSpinReverseButton,
|
||||
DshotCommand.dshotCommands_e.DSHOT_CMD_SPIN_DIRECTION_2, this._reverseText);
|
||||
}, timeoutMs);
|
||||
}
|
||||
|
||||
_deactivateNormalReverseButtons()
|
||||
{
|
||||
if (null !== this._activationButtonTimeoutId)
|
||||
{
|
||||
clearTimeout(this._activationButtonTimeoutId);
|
||||
}
|
||||
|
||||
this._domSpinNormalButton.off();
|
||||
this._domSpinReverseButton.off();
|
||||
}
|
||||
|
||||
_subscribeDirectionSpinButton(button, direction, buttonText)
|
||||
{
|
||||
button.on("mousedown touchstart", () => {
|
||||
this._sendCurrentEscSpinDirection(direction);
|
||||
this._motorIsSpinning = true;
|
||||
button.text(this._releaseToStopText);
|
||||
button.addClass(EscDshotDirectionComponent.HIGHLIGHTED_BUTTON_CLASS);
|
||||
this._motorDriver.spinMotor(this._selectedMotor);
|
||||
this._domSecondHint.html(this._releaseButtonToStopText);
|
||||
this._domSecondHint.addClass(EscDshotDirectionComponent.RED_TEXT_CLASS);
|
||||
});
|
||||
|
||||
button.on("mouseup mouseout touchend", () => {
|
||||
if (this._motorIsSpinning) {
|
||||
button.text(buttonText);
|
||||
this._motorIsSpinning = false;
|
||||
button.removeClass(EscDshotDirectionComponent.HIGHLIGHTED_BUTTON_CLASS);
|
||||
this._motorDriver.stopAllMotors();
|
||||
this._domSecondHint.text(this._secondHintText);
|
||||
this._domSecondHint.removeClass(EscDshotDirectionComponent.RED_TEXT_CLASS);
|
||||
|
||||
this._deactivateNormalReverseButtons();
|
||||
this._activateNormalReverseButtons(this._buttonTimeoutMs);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_sendCurrentEscSpinDirection(direction)
|
||||
{
|
||||
this._motorDriver.setEscSpinDirection(this._selectedMotor, direction);
|
||||
}
|
||||
|
||||
_createMotorButtons()
|
||||
{
|
||||
this._motorButtons = {};
|
||||
|
||||
for (let i = 0; i < this._numberOfMotors; i++) {
|
||||
this._addMotorButton(i + 1, i);
|
||||
}
|
||||
|
||||
this._addMotorButton("All", DshotCommand.ALL_MOTORS);
|
||||
}
|
||||
|
||||
_addMotorButton(buttonText, motorIndex)
|
||||
{
|
||||
const button = $(`<a href="#" class="regular-button ${EscDshotDirectionComponent.PUSHED_BUTTON_CLASS}"></a>`).text(buttonText);
|
||||
this._domMotorButtonsBlock.append(button);
|
||||
this._motorButtons[motorIndex] = button;
|
||||
|
||||
button.on("mousedown touchstart", () => {
|
||||
this._domSecondActionDiv.toggle(true);
|
||||
this._motorIsSpinning = true;
|
||||
this._domActionHint.html(this._releaseButtonToStopText);
|
||||
this._domActionHint.addClass(EscDshotDirectionComponent.RED_TEXT_CLASS);
|
||||
this._changeSelectedMotor(motorIndex);
|
||||
button.addClass(EscDshotDirectionComponent.HIGHLIGHTED_BUTTON_CLASS);
|
||||
this._motorDriver.spinMotor(this._selectedMotor);
|
||||
});
|
||||
|
||||
button.on("mouseup mouseout touchend", () => {
|
||||
if (this._motorIsSpinning) {
|
||||
this._domActionHint.html(this._topHintText);
|
||||
this._domActionHint.removeClass(EscDshotDirectionComponent.RED_TEXT_CLASS);
|
||||
this._motorIsSpinning = false;
|
||||
button.removeClass(EscDshotDirectionComponent.HIGHLIGHTED_BUTTON_CLASS);
|
||||
this._motorDriver.stopAllMotors();
|
||||
|
||||
this._deactivateNormalReverseButtons();
|
||||
this._activateNormalReverseButtons(this._buttonTimeoutMs);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_createWizardMotorButtons()
|
||||
{
|
||||
this._wizardMotorButtons = {};
|
||||
|
||||
for (let i = 0; i < this._numberOfMotors; i++) {
|
||||
this._addWizardMotorButton(i + 1, i);
|
||||
}
|
||||
}
|
||||
|
||||
_activateWizardMotorButtons(timeoutMs)
|
||||
{
|
||||
this._activationButtonTimeoutId = setTimeout(() => {
|
||||
for (let i = 0; i < this._numberOfMotors; i++) {
|
||||
this._activateWizardMotorButton(i);
|
||||
}
|
||||
}, timeoutMs);
|
||||
}
|
||||
|
||||
_deactivateWizardMotorButtons()
|
||||
{
|
||||
if (null !== this._activationButtonTimeoutId)
|
||||
{
|
||||
clearTimeout(this._activationButtonTimeoutId);
|
||||
}
|
||||
|
||||
for (let i = 0; i < this._numberOfMotors; i++) {
|
||||
const button = this._wizardMotorButtons[i];
|
||||
button.off();
|
||||
}
|
||||
}
|
||||
|
||||
_addWizardMotorButton(buttonText, motorIndex)
|
||||
{
|
||||
const button = $(`<a href="#" class="regular-button"></a>`).text(buttonText);
|
||||
this._domWizardMotorButtonsBlock.append(button);
|
||||
this._wizardMotorButtons[motorIndex] = button;
|
||||
}
|
||||
|
||||
_activateWizardMotorButton(motorIndex)
|
||||
{
|
||||
const button = this._wizardMotorButtons[motorIndex];
|
||||
|
||||
button.on("click", () => {
|
||||
this._wizardMotorButtonClick(button, motorIndex);
|
||||
});
|
||||
}
|
||||
|
||||
_wizardMotorButtonClick(button, motorIndex)
|
||||
{
|
||||
this._deactivateWizardMotorButtons();
|
||||
const currentlyDown = button.hasClass(EscDshotDirectionComponent.PUSHED_BUTTON_CLASS);
|
||||
|
||||
if (currentlyDown) {
|
||||
button.removeClass(EscDshotDirectionComponent.PUSHED_BUTTON_CLASS);
|
||||
this._motorDriver.setEscSpinDirection(motorIndex, DshotCommand.dshotCommands_e.DSHOT_CMD_SPIN_DIRECTION_1);
|
||||
} else {
|
||||
this._motorDriver.setEscSpinDirection(motorIndex, DshotCommand.dshotCommands_e.DSHOT_CMD_SPIN_DIRECTION_2);
|
||||
button.addClass(EscDshotDirectionComponent.PUSHED_BUTTON_CLASS);
|
||||
}
|
||||
|
||||
this._activateWizardMotorButtons(this._buttonTimeoutMs);
|
||||
}
|
||||
|
||||
_changeSelectedMotor(newIndex)
|
||||
{
|
||||
if (this._selectedMotor >= 0) {
|
||||
this._motorButtons[this._selectedMotor].addClass(EscDshotDirectionComponent.PUSHED_BUTTON_CLASS);
|
||||
}
|
||||
|
||||
this._selectedMotor = newIndex;
|
||||
|
||||
if (this._selectedMotor > -1) {
|
||||
this._motorButtons[this._selectedMotor].removeClass(EscDshotDirectionComponent.PUSHED_BUTTON_CLASS);
|
||||
}
|
||||
}
|
||||
|
||||
close()
|
||||
{
|
||||
this._motorDriver.stopAllMotorsNow();
|
||||
this._motorDriver.deactivate();
|
||||
this._resetGui();
|
||||
}
|
||||
|
||||
_resetGui()
|
||||
{
|
||||
this._toggleMainContent(false);
|
||||
this._domStartNormalBlock.hide();
|
||||
this._domStartWizardBlock.hide();
|
||||
|
||||
this._domAgreeSafetyCheckBox.prop('checked', false);
|
||||
this._domAgreeSafetyCheckBox.trigger('change');
|
||||
this._domSecondActionDiv.toggle(false);
|
||||
this._changeSelectedMotor(-1);
|
||||
|
||||
this._checkForConfigurationErrors();
|
||||
}
|
||||
|
||||
_checkForConfigurationErrors()
|
||||
{
|
||||
let anyError = false;
|
||||
|
||||
this._domWrongProtocolMessage.hide();
|
||||
this._domWrongMixerMessage.hide();
|
||||
this._domWrongFirmwareMessage.hide();
|
||||
|
||||
if (!this._escProtocolIsDshot) {
|
||||
anyError = true;
|
||||
this._domWrongProtocolMessage.show();
|
||||
}
|
||||
|
||||
if (this._numberOfMotors <= 0) {
|
||||
anyError = true;
|
||||
this._domWrongMixerMessage.show();
|
||||
}
|
||||
|
||||
if (!semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
|
||||
// if BF4.2 or older - show the error message
|
||||
anyError = true;
|
||||
this._domWrongFirmwareMessage.show();
|
||||
}
|
||||
|
||||
if (anyError) {
|
||||
this._domMainContentBlock.hide();
|
||||
this._domWarningContentBlock.hide();
|
||||
this._domStartNormalBlock.hide();
|
||||
this._domStartWizardBlock.hide();
|
||||
this._domConfigErrors.show();
|
||||
} else {
|
||||
this._domConfigErrors.hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_onStartButtonClicked()
|
||||
{
|
||||
this._toggleMainContent(true);
|
||||
this._domWizardBlock.toggle(false);
|
||||
this._domNormalDialogBlock.toggle(true);
|
||||
this._motorDriver.activate();
|
||||
}
|
||||
|
||||
_onStartWizardButtonClicked()
|
||||
{
|
||||
this._domSpinningWizard.toggle(false);
|
||||
this._domSpinWizardButton.toggle(true);
|
||||
this._toggleMainContent(true);
|
||||
this._domWizardBlock.toggle(true);
|
||||
this._domNormalDialogBlock.toggle(false);
|
||||
this._motorDriver.activate();
|
||||
}
|
||||
|
||||
_onSpinWizardButtonClicked()
|
||||
{
|
||||
for (let i = 0; i < this._numberOfMotors; i++) {
|
||||
this._wizardMotorButtons[i].removeClass(EscDshotDirectionComponent.PUSHED_BUTTON_CLASS);
|
||||
}
|
||||
|
||||
this._motorDriver.setEscSpinDirection(DshotCommand.ALL_MOTORS, DshotCommand.dshotCommands_e.DSHOT_CMD_SPIN_DIRECTION_1);
|
||||
|
||||
this._domSpinWizardButton.toggle(false);
|
||||
this._domSpinningWizard.toggle(true);
|
||||
this._motorDriver.spinAllMotors();
|
||||
|
||||
this._activateWizardMotorButtons(0);
|
||||
}
|
||||
|
||||
_onStopWizardButtonClicked()
|
||||
{
|
||||
this._domSpinWizardButton.toggle(true);
|
||||
this._domSpinningWizard.toggle(false);
|
||||
this._motorDriver.stopAllMotorsNow();
|
||||
this._deactivateWizardMotorButtons();
|
||||
}
|
||||
|
||||
_toggleMainContent(value)
|
||||
{
|
||||
this._domWarningContentBlock.toggle(!value);
|
||||
this._domMainContentBlock.toggle(value);
|
||||
this._domConfigErrors.toggle(false);
|
||||
}
|
||||
|
||||
}
|
155
src/components/EscDshotDirection/EscDshotDirectionMotorDriver.js
Normal file
155
src/components/EscDshotDirection/EscDshotDirectionMotorDriver.js
Normal file
|
@ -0,0 +1,155 @@
|
|||
'use strict';
|
||||
|
||||
class EscDshotDirectionMotorDriver
|
||||
{
|
||||
constructor(motorConfig, motorDriverQueueIntervalMs, motorDriverStopMotorsPauseMs)
|
||||
{
|
||||
this._numberOfMotors = motorConfig.numberOfMotors;
|
||||
this._motorStopValue = motorConfig.motorStopValue;
|
||||
this._motorSpinValue = motorConfig.motorSpinValue;
|
||||
this._motorDriverStopMotorsPauseMs = motorDriverStopMotorsPauseMs;
|
||||
|
||||
this._state = [];
|
||||
|
||||
for (let i = 0; i < this._numberOfMotors; i++)
|
||||
{
|
||||
this._state.push(this._motorStopValue);
|
||||
}
|
||||
|
||||
this._stateStack = [];
|
||||
|
||||
this._EscDshotCommandQueue = new EscDshotCommandQueue(motorDriverQueueIntervalMs);
|
||||
}
|
||||
|
||||
activate()
|
||||
{
|
||||
this._EscDshotCommandQueue.start();
|
||||
}
|
||||
|
||||
deactivate()
|
||||
{
|
||||
this._EscDshotCommandQueue.stopWhenEmpty();
|
||||
}
|
||||
|
||||
stopMotor(motorIndex)
|
||||
{
|
||||
this._spinMotor(motorIndex, this._motorStopValue);
|
||||
}
|
||||
|
||||
|
||||
spinMotor(motorIndex)
|
||||
{
|
||||
this._spinMotor(motorIndex, this._motorSpinValue);
|
||||
}
|
||||
|
||||
spinAllMotors()
|
||||
{
|
||||
this._spinAllMotors(this._motorSpinValue);
|
||||
}
|
||||
|
||||
stopAllMotors()
|
||||
{
|
||||
this._spinAllMotors(this._motorStopValue);
|
||||
}
|
||||
|
||||
stopAllMotorsNow()
|
||||
{
|
||||
this._EscDshotCommandQueue.clear();
|
||||
this._spinAllMotors(this._motorStopValue);
|
||||
}
|
||||
|
||||
setEscSpinDirection(motorIndex, direction)
|
||||
{
|
||||
let needStopMotor = false;
|
||||
|
||||
if (DshotCommand.ALL_MOTORS === motorIndex) {
|
||||
needStopMotor = this._isAnythingSpinning();
|
||||
} else {
|
||||
needStopMotor = this._isMotorSpinning(motorIndex);
|
||||
}
|
||||
|
||||
if (needStopMotor) {
|
||||
this._pushState();
|
||||
this._spinMotor(motorIndex, this._motorStopValue);
|
||||
this._EscDshotCommandQueue.pushPause(this._motorDriverStopMotorsPauseMs);
|
||||
this._sendEscSpinDirection(motorIndex, direction);
|
||||
this._popState();
|
||||
this._sendState();
|
||||
} else {
|
||||
this._sendEscSpinDirection(motorIndex, direction);
|
||||
}
|
||||
}
|
||||
|
||||
_pushState()
|
||||
{
|
||||
const state = [...this._state];
|
||||
this._stateStack.push(state);
|
||||
}
|
||||
|
||||
_popState()
|
||||
{
|
||||
const state = this._stateStack.pop();
|
||||
this._state = [...state];
|
||||
}
|
||||
|
||||
_isAnythingSpinning()
|
||||
{
|
||||
let result = false;
|
||||
|
||||
for (let i = 0; i < this._numberOfMotors; i++) {
|
||||
if (this._motorStopValue !== this._state[i]) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
_isMotorSpinning(motorIndex)
|
||||
{
|
||||
return (this._motorStopValue !== this._state[motorIndex]);
|
||||
}
|
||||
|
||||
_sendEscSpinDirection(motorIndex, direction)
|
||||
{
|
||||
const buffer = [];
|
||||
buffer.push8(DshotCommand.dshotCommandType_e.DSHOT_CMD_TYPE_BLOCKING);
|
||||
buffer.push8(motorIndex);
|
||||
buffer.push8(2); // two commands
|
||||
buffer.push8(direction);
|
||||
buffer.push8(DshotCommand.dshotCommands_e.DSHOT_CMD_SAVE_SETTINGS);
|
||||
this._EscDshotCommandQueue.pushCommand(MSPCodes.MSP2_SEND_DSHOT_COMMAND, buffer);
|
||||
}
|
||||
|
||||
_spinMotor(motorIndex, value)
|
||||
{
|
||||
if (DshotCommand.ALL_MOTORS === motorIndex) {
|
||||
this._spinAllMotors(value);
|
||||
} else {
|
||||
this._state[motorIndex] = value;
|
||||
this._sendState();
|
||||
}
|
||||
}
|
||||
|
||||
_spinAllMotors(value)
|
||||
{
|
||||
for (let i = 0; i < this._numberOfMotors; i++) {
|
||||
this._state[i] = value;
|
||||
}
|
||||
|
||||
this._sendState();
|
||||
}
|
||||
|
||||
_sendState()
|
||||
{
|
||||
const buffer = [];
|
||||
|
||||
for (let i = 0; i < this._numberOfMotors; i++) {
|
||||
buffer.push16(this._state[i]);
|
||||
}
|
||||
|
||||
this._EscDshotCommandQueue.pushCommand(MSPCodes.MSP_SET_MOTOR, buffer);
|
||||
}
|
||||
|
||||
}
|
177
src/components/EscDshotDirection/Styles.css
Normal file
177
src/components/EscDshotDirection/Styles.css
Normal file
|
@ -0,0 +1,177 @@
|
|||
.escDshotDirection-Component {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
flex-flow: column;
|
||||
}
|
||||
|
||||
.escDshotDirection-ComponentHeader {
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
#escDshotDirectionDialog-MainContent {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
flex-flow: column;
|
||||
}
|
||||
|
||||
#escDshotDirectionDialog-Warning {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
flex-flow: column;
|
||||
border-top: 1px solid var(--superSubtleAccent);
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
.escDshotDirectionToggleParentContainer {
|
||||
display: flex;
|
||||
margin-bottom: 1.5em;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
.escDshotDirectionToggleNarrow {
|
||||
margin-right: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.escDshotDirectionDialog-ToggleWide {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.escDshotDirectionDialog-RiskNoticeText {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.escDshotDirectionDialogInformationNotice {
|
||||
font-size: 1.0em;
|
||||
margin-bottom: 1.5em;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
#escDshotDirectionDialog-MixerPreview {
|
||||
width: 100%;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 9px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
#escDshotDirectionDialog-MixerPreviewImg {
|
||||
display: block;
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
}
|
||||
|
||||
#escDshotDirectionDialog-MainContent h4 {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
#escDshotDirectionDialog-MainContent .red-text {
|
||||
color: #EE0000;
|
||||
}
|
||||
|
||||
#escDshotDirectionDialog-ActionHint, #escDshotDirectionDialog-SecondHint, #escDshotDirectionDialog-WizardActionHint {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#escDshotDirectionDialog-ActionHintSafety, #escDshotDirectionDialog-SecondHintSafety {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
#escDshotDirectionDialog-SelectMotorButtonsWrapper, #escDshotDirectionDialog-WizardMotorButtons {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
#escDshotDirectionDialog-SelectMotorButtonsWrapper .regular-button, #escDshotDirectionDialog-WizardMotorButtons .regular-button {
|
||||
font-size: 15px;
|
||||
line-height: 34px;
|
||||
padding: 0px;
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
border-radius: 17px;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#escDshotDirectionDialog-NormalDialog .regular-button.pushed:hover {
|
||||
background-color: #993333;
|
||||
}
|
||||
|
||||
#escDshotDirectionDialog-NormalDialog .regular-button:hover {
|
||||
background-color: #993333;
|
||||
}
|
||||
|
||||
#escDshotDirectionDialog-MainContent .regular-button.highlighted {
|
||||
background-color: #EE2222;
|
||||
}
|
||||
|
||||
#escDshotDirectionDialog-CommandsWrapper {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
#escDshotDirectionDialog-CommandSpin {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 224px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#escDshotDirectionDialog-CommandsWrapper .regular-button {
|
||||
width: 130px;
|
||||
text-align: center;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
|
||||
.escDshotDirectionErrorTextBlock {
|
||||
margin-top: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.display-contents {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
#escDshotDirectionDialog-SpinWizard, #escDshotDirectionDialog-StopWizard {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 160px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.escDshotDirectionDialog-InformationNotice {
|
||||
margin-top: 18px;
|
||||
padding-top: 16px;
|
||||
padding-bottom: 16px;
|
||||
border-top: 1px solid var(--superSubtleAccent);
|
||||
border-bottom: 1px solid var(--superSubtleAccent);
|
||||
}
|
||||
|
||||
.escDshotDirectionDialog-StartButton {
|
||||
width: 80px;
|
||||
text-align: center;
|
||||
margin-left: 0px;
|
||||
margin-right: 16px;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.escDshotDirectionDialog-Buttons {
|
||||
float: left;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.escDshotDirectionDialog-StartBlock {
|
||||
display: flex;
|
||||
margin-top: 16px;
|
||||
}
|
|
@ -25,7 +25,7 @@ class MotorOutputReorderComponent
|
|||
_readDom()
|
||||
{
|
||||
this._domAgreeSafetyCheckBox = $('#motorsEnableTestMode-dialogMotorOutputReorder');
|
||||
this._domAgreeButton = $('#dialogMotorOutputReorderAgreeButton');
|
||||
this._domStartButton = $('#dialogMotorOutputReorderAgreeButton');
|
||||
this._domStartOverButton = $('#motorsRemapDialogStartOver');
|
||||
this._domSaveButton = $('#motorsRemapDialogSave');
|
||||
this._domMainContentBlock = $('#dialogMotorOutputReorderMainContent');
|
||||
|
@ -44,12 +44,12 @@ class MotorOutputReorderComponent
|
|||
this._domAgreeSafetyCheckBox.change(() =>
|
||||
{
|
||||
const enabled = this._domAgreeSafetyCheckBox.is(':checked');
|
||||
this._domAgreeButton.toggle(enabled);
|
||||
this._domStartButton.toggle(enabled);
|
||||
});
|
||||
|
||||
this._domAgreeButton.click(() =>
|
||||
this._domStartButton.click(() =>
|
||||
{
|
||||
this._onAgreeButtonClicked();
|
||||
this._onStartButtonClicked();
|
||||
});
|
||||
this._domStartOverButton.click(() =>
|
||||
{
|
||||
|
@ -75,7 +75,7 @@ class MotorOutputReorderComponent
|
|||
{
|
||||
this._domMainContentBlock.hide();
|
||||
this._domWarningContentBlock.show();
|
||||
this._domAgreeButton.hide();
|
||||
this._domStartButton.hide();
|
||||
|
||||
this._domAgreeSafetyCheckBox.prop('checked', false);
|
||||
this._domAgreeSafetyCheckBox.change();
|
||||
|
@ -138,7 +138,7 @@ class MotorOutputReorderComponent
|
|||
}
|
||||
}
|
||||
|
||||
_onAgreeButtonClicked()
|
||||
_onStartButtonClicked()
|
||||
{
|
||||
this._domActionHintBlock.text(i18n.getMessage("motorOutputReorderDialogSelectSpinningMotor"));
|
||||
this._domWarningContentBlock.hide();
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
}
|
||||
|
||||
.motorOutputReorderComponentHeader {
|
||||
border-bottom: 1px solid var(--accent);
|
||||
margin-bottom: 10px;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,10 @@
|
|||
--gimbalBackground: var(--subtleAccent);
|
||||
--gimbalCrosshair: var(--mutedText);
|
||||
--switcherysecond: #858585;
|
||||
--pushedButton-background: #616161;
|
||||
--pushedButton-fontColor: #ffffff;
|
||||
--hoverButton-background: #ffcc3e;
|
||||
--superSubtleAccent: #595959;
|
||||
}
|
||||
|
||||
.background_paper {
|
||||
|
@ -24,6 +28,11 @@ body {
|
|||
color: white;
|
||||
}
|
||||
|
||||
::backdrop {
|
||||
background-image: none;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
#options-window {
|
||||
background-color: #393b3a;
|
||||
}
|
||||
|
@ -219,7 +228,7 @@ button {
|
|||
}
|
||||
|
||||
.tab-auxiliary .buttons a:hover {
|
||||
background-color: #393b3a;
|
||||
background-color: var(--hoverButton-background);
|
||||
}
|
||||
|
||||
|
||||
|
@ -357,7 +366,7 @@ button {
|
|||
}
|
||||
|
||||
.tab-gps #loadmap .controls a:hover {
|
||||
background-color: #393b3a;
|
||||
background-color: var(--hoverButton-background);
|
||||
}
|
||||
|
||||
.tab-gps #loadmap .controls a:active {
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
--gimbalBackground: #eee;
|
||||
--gimbalCrosshair: var(--subtleAccent);
|
||||
--switcherysecond: #c4c4c4;
|
||||
--pushedButton-background: #c4c4c4;
|
||||
--pushedButton-fontColor: #000000;
|
||||
--hoverButton-background: #ffcc3e;
|
||||
--superSubtleAccent: #CCCCCC;
|
||||
}
|
||||
|
||||
* {
|
||||
|
@ -40,6 +44,11 @@ body {
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
::backdrop {
|
||||
background-image: none;
|
||||
background-color: rgba(1, 1, 1, 0.5);
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: var(--linkText);
|
||||
|
@ -140,7 +149,11 @@ input[type="number"]::-webkit-inner-spin-button {
|
|||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
|
||||
.message-negative-italic {
|
||||
color: var(--error) !important;
|
||||
font-weight: bold !important;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/** Main wrapper **/
|
||||
#main-wrapper {
|
||||
|
@ -1478,7 +1491,7 @@ dialog .dialog_toolbar .btn a {
|
|||
}
|
||||
|
||||
dialog .dialog_toolbar .btn a:hover {
|
||||
background-color: #ffcc3e;
|
||||
background-color: var(--hoverButton-background);
|
||||
transition: all ease 0.2s;
|
||||
}
|
||||
|
||||
|
@ -1574,7 +1587,7 @@ dialog .dialog_toolbar .btn a.disabled {
|
|||
}
|
||||
|
||||
.content_toolbar .btn a:hover {
|
||||
background-color: #ffcc3e;
|
||||
background-color: var(--hoverButton-background);
|
||||
transition: all ease 0.2s;
|
||||
}
|
||||
|
||||
|
@ -1862,7 +1875,7 @@ dialog .dialog_toolbar .btn a.disabled {
|
|||
}
|
||||
|
||||
.fixed_band .save_btn a:hover {
|
||||
background-color: #ffcc3f;
|
||||
background-color: var(--hoverButton-background);
|
||||
transition: all ease 0.2s;
|
||||
}
|
||||
|
||||
|
@ -1898,7 +1911,7 @@ dialog .dialog_toolbar .btn a.disabled {
|
|||
}
|
||||
|
||||
.default_btn a:hover {
|
||||
background-color: #ffcc3f;
|
||||
background-color: var(--hoverButton-background);
|
||||
color: #000;
|
||||
text-shadow: 0 1px rgba(255, 255, 255, 0.25);
|
||||
transition: all ease 0.2s;
|
||||
|
@ -1907,7 +1920,7 @@ dialog .dialog_toolbar .btn a.disabled {
|
|||
}
|
||||
|
||||
.default_btn a:active {
|
||||
background-color: #ffcc3f;
|
||||
background-color: var(--hoverButton-background);
|
||||
transition: all ease 0.0s;
|
||||
box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
@ -1917,6 +1930,7 @@ dialog .dialog_toolbar .btn a.disabled {
|
|||
}
|
||||
|
||||
.regular-button {
|
||||
-webkit-user-drag: none;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 8px;
|
||||
margin-right: 10px;
|
||||
|
@ -1934,6 +1948,16 @@ dialog .dialog_toolbar .btn a.disabled {
|
|||
line-height: 28px;
|
||||
}
|
||||
|
||||
.regular-button:hover {
|
||||
background-color: var(--hoverButton-background);
|
||||
}
|
||||
|
||||
.regular-button.pushed {
|
||||
background-color: var(--pushedButton-background);
|
||||
color: var(--pushedButton-fontColor);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.small {
|
||||
width: auto;
|
||||
position: relative;
|
||||
|
|
|
@ -39,6 +39,31 @@
|
|||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.tab-motors #escDshotDirectionDialog-closebtn {
|
||||
margin-right: 0px;
|
||||
margin-bottom: 0px;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
.tab-motors #escDshotDirectionDialog {
|
||||
width: 400px;
|
||||
height: 440px;
|
||||
}
|
||||
|
||||
.tab-motors #escDshotDirectionDialog-ContentWrapper {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab-motors #escDshotDirectionDialog-Content {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.tab-motors .mixerPreview img {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
|
@ -457,4 +482,16 @@
|
|||
margin: 0;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.tab-motors #escDshotDirectionDialog- {
|
||||
position: fixed;
|
||||
width: calc(100% - 2em);
|
||||
bottom: 0;
|
||||
top: 56px;
|
||||
border-radius: unset;
|
||||
border: none;
|
||||
overflow: auto;
|
||||
margin: 0;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -181,4 +181,5 @@ const MSPCodes = {
|
|||
MSP2_BETAFLIGHT_BIND: 0x3000,
|
||||
MSP2_MOTOR_OUTPUT_REORDERING: 0x3001,
|
||||
MSP2_SET_MOTOR_OUTPUT_REORDERING: 0x3002,
|
||||
MSP2_SEND_DSHOT_COMMAND: 0x3003,
|
||||
};
|
||||
|
|
|
@ -57,26 +57,6 @@ function MspHelper() {
|
|||
self.mspMultipleCache = [];
|
||||
}
|
||||
|
||||
MspHelper.prototype.reorderPwmProtocols = function (protocol) {
|
||||
let result = protocol;
|
||||
if (semver.lt(FC.CONFIG.apiVersion, "1.26.0")) {
|
||||
switch (protocol) {
|
||||
case 5:
|
||||
result = 7;
|
||||
|
||||
break;
|
||||
case 7:
|
||||
result = 5;
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
MspHelper.prototype.process_data = function(dataHandler) {
|
||||
const self = this;
|
||||
const data = dataHandler.dataView; // DataView (allowing us to view arrayBuffer as struct/union)
|
||||
|
@ -1039,7 +1019,7 @@ MspHelper.prototype.process_data = function(dataHandler) {
|
|||
FC.PID_ADVANCED_CONFIG.gyro_sync_denom = data.readU8();
|
||||
FC.PID_ADVANCED_CONFIG.pid_process_denom = data.readU8();
|
||||
FC.PID_ADVANCED_CONFIG.use_unsyncedPwm = data.readU8();
|
||||
FC.PID_ADVANCED_CONFIG.fast_pwm_protocol = self.reorderPwmProtocols(data.readU8());
|
||||
FC.PID_ADVANCED_CONFIG.fast_pwm_protocol = EscProtocols.ReorderPwmProtocols(FC.CONFIG.apiVersion, data.readU8());
|
||||
FC.PID_ADVANCED_CONFIG.motor_pwm_rate = data.readU16();
|
||||
if (semver.gte(FC.CONFIG.apiVersion, "1.24.0")) {
|
||||
FC.PID_ADVANCED_CONFIG.digitalIdlePercent = data.readU16() / 100;
|
||||
|
@ -1569,6 +1549,9 @@ MspHelper.prototype.process_data = function(dataHandler) {
|
|||
case MSPCodes.MSP2_SET_MOTOR_OUTPUT_REORDERING:
|
||||
console.log('Motor output reordering set');
|
||||
break;
|
||||
case MSPCodes.MSP2_SEND_DSHOT_COMMAND:
|
||||
console.log('DSHOT command sent');
|
||||
break;
|
||||
|
||||
case MSPCodes.MSP_MULTIPLE_MSP:
|
||||
|
||||
|
@ -1981,7 +1964,7 @@ MspHelper.prototype.crunch = function(code) {
|
|||
buffer.push8(FC.PID_ADVANCED_CONFIG.gyro_sync_denom)
|
||||
.push8(FC.PID_ADVANCED_CONFIG.pid_process_denom)
|
||||
.push8(FC.PID_ADVANCED_CONFIG.use_unsyncedPwm)
|
||||
.push8(self.reorderPwmProtocols(FC.PID_ADVANCED_CONFIG.fast_pwm_protocol))
|
||||
.push8(EscProtocols.ReorderPwmProtocols(FC.CONFIG.apiVersion, FC.PID_ADVANCED_CONFIG.fast_pwm_protocol))
|
||||
.push16(FC.PID_ADVANCED_CONFIG.motor_pwm_rate);
|
||||
if (semver.gte(FC.CONFIG.apiVersion, "1.24.0")) {
|
||||
buffer.push16(FC.PID_ADVANCED_CONFIG.digitalIdlePercent * 100);
|
||||
|
@ -2278,6 +2261,10 @@ MspHelper.prototype.crunch = function(code) {
|
|||
|
||||
break;
|
||||
|
||||
case MSPCodes.MSP2_SEND_DSHOT_COMMAND:
|
||||
buffer.push8(1);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -213,14 +213,8 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
}
|
||||
|
||||
function refreshMixerPreview() {
|
||||
const mixer = FC.MIXER_CONFIG.mixer
|
||||
let reverse = "";
|
||||
|
||||
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_36)) {
|
||||
reverse = FC.MIXER_CONFIG.reverseMotorDir ? "_reversed" : "";
|
||||
}
|
||||
|
||||
$('.mixerPreview img').attr('src', './resources/motor_order/' + mixerList[mixer - 1].image + reverse + '.svg');
|
||||
const imgSrc = CommonUtils.GetMixerImageSrc(FC.MIXER_CONFIG.mixer, FC.MIXER_CONFIG.reverseMotorDir, FC.CONFIG.apiVersion);
|
||||
$('.mixerPreview img').attr('src', imgSrc);
|
||||
}
|
||||
|
||||
const reverseMotorSwitch_e = $('#reverseMotorSwitch');
|
||||
|
@ -462,34 +456,7 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
}
|
||||
|
||||
// ESC protocols
|
||||
const escProtocols = [
|
||||
'PWM',
|
||||
'ONESHOT125',
|
||||
'ONESHOT42',
|
||||
'MULTISHOT',
|
||||
];
|
||||
|
||||
if (semver.gte(FC.CONFIG.apiVersion, "1.20.0")) {
|
||||
escProtocols.push('BRUSHED');
|
||||
}
|
||||
|
||||
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_31)) {
|
||||
escProtocols.push('DSHOT150');
|
||||
escProtocols.push('DSHOT300');
|
||||
escProtocols.push('DSHOT600');
|
||||
|
||||
if (semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_42)) {
|
||||
escProtocols.push('DSHOT1200');
|
||||
}
|
||||
}
|
||||
|
||||
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_36)) {
|
||||
escProtocols.push('PROSHOT1000');
|
||||
}
|
||||
|
||||
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_43)) {
|
||||
escProtocols.push('DISABLED');
|
||||
}
|
||||
const escProtocols = EscProtocols.GetAvailableProtocols(FC.CONFIG.apiVersion);
|
||||
|
||||
const esc_protocol_e = $('select.escprotocol');
|
||||
|
||||
|
|
|
@ -31,7 +31,8 @@ TABS.motors = {
|
|||
// These are translated into proper Dshot values on the flight controller
|
||||
DSHOT_DISARMED_VALUE: 1000,
|
||||
DSHOT_MAX_VALUE: 2000,
|
||||
DSHOT_3D_NEUTRAL: 1500
|
||||
DSHOT_3D_NEUTRAL: 1500,
|
||||
numberOfValidOutputs: -1,
|
||||
};
|
||||
|
||||
TABS.motors.initialize = function (callback) {
|
||||
|
@ -105,7 +106,7 @@ TABS.motors.initialize = function (callback) {
|
|||
}
|
||||
|
||||
function initDataArray(length) {
|
||||
const data = new Array(length);
|
||||
const data = Array.from({length: length});
|
||||
for (let i = 0; i < length; i++) {
|
||||
data[i] = [];
|
||||
data[i].min = -1;
|
||||
|
@ -126,8 +127,8 @@ TABS.motors.initialize = function (callback) {
|
|||
}
|
||||
}
|
||||
while (data[0].length > 300) {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
data[i].shift();
|
||||
for (const item of data) {
|
||||
item.shift();
|
||||
}
|
||||
}
|
||||
return sampleNumber + 1;
|
||||
|
@ -220,13 +221,8 @@ TABS.motors.initialize = function (callback) {
|
|||
}
|
||||
|
||||
function update_model(mixer) {
|
||||
let reverse = "";
|
||||
|
||||
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_36)) {
|
||||
reverse = FC.MIXER_CONFIG.reverseMotorDir ? "_reversed" : "";
|
||||
}
|
||||
|
||||
$('.mixerPreview img').attr('src', './resources/motor_order/' + mixerList[mixer - 1].image + reverse + '.svg');
|
||||
const imgSrc = CommonUtils.GetMixerImageSrc(mixer, FC.MIXER_CONFIG.reverseMotorDir, FC.CONFIG.apiVersion);
|
||||
$('.mixerPreview img').attr('src', imgSrc);
|
||||
|
||||
const motorOutputReorderConfig = new MotorOutputReorderConfig(100);
|
||||
const domMotorOutputReorderDialogOpen = $('#motorOutputReorderDialogOpen');
|
||||
|
@ -234,6 +230,8 @@ TABS.motors.initialize = function (callback) {
|
|||
const isMotorReorderingAvailable = (mixerList[mixer - 1].name in motorOutputReorderConfig)
|
||||
&& (FC.MOTOR_OUTPUT_ORDER) && (FC.MOTOR_OUTPUT_ORDER.length > 0);
|
||||
domMotorOutputReorderDialogOpen.toggle(isMotorReorderingAvailable);
|
||||
|
||||
self.escProtocolIsDshot = EscProtocols.IsProtocolDshot(FC.CONFIG.apiVersion, FC.PID_ADVANCED_CONFIG.fast_pwm_protocol);
|
||||
}
|
||||
|
||||
function process_html() {
|
||||
|
@ -244,12 +242,6 @@ TABS.motors.initialize = function (callback) {
|
|||
|
||||
self.feature3DEnabled = FC.FEATURE_CONFIG.features.isEnabled('3D');
|
||||
|
||||
if (FC.PID_ADVANCED_CONFIG.fast_pwm_protocol >= TABS.configuration.DSHOT_PROTOCOL_MIN_VALUE) {
|
||||
self.escProtocolIsDshot = true;
|
||||
} else {
|
||||
self.escProtocolIsDshot = false;
|
||||
}
|
||||
|
||||
$('#motorsEnableTestMode').prop('checked', false);
|
||||
|
||||
if (semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_42) || !(FC.MOTOR_CONFIG.use_dshot_telemetry || FC.MOTOR_CONFIG.use_esc_sensor)) {
|
||||
|
@ -455,6 +447,7 @@ TABS.motors.initialize = function (callback) {
|
|||
motor_mah_drawing_e.text(i18n.getMessage('motorsADrawingValue', [FC.ANALOG.amperage.toFixed(2)]));
|
||||
motor_mah_drawn_e.text(i18n.getMessage('motorsmAhDrawnValue', [FC.ANALOG.mAhdrawn]));
|
||||
}
|
||||
|
||||
GUI.interval_add('motors_power_data_pull_slow', power_data_pull, 250, true); // 4 fps
|
||||
|
||||
$('a.reset_max').click(function () {
|
||||
|
@ -463,7 +456,7 @@ TABS.motors.initialize = function (callback) {
|
|||
accelOffsetEstablished = false;
|
||||
});
|
||||
|
||||
const numberOfValidOutputs = (FC.MOTOR_DATA.indexOf(0) > -1) ? FC.MOTOR_DATA.indexOf(0) : 8;
|
||||
self.numberOfValidOutputs = (FC.MOTOR_DATA.indexOf(0) > -1) ? FC.MOTOR_DATA.indexOf(0) : 8;
|
||||
let rangeMin;
|
||||
let rangeMax;
|
||||
let neutral3d;
|
||||
|
@ -526,7 +519,7 @@ TABS.motors.initialize = function (callback) {
|
|||
|
||||
function setSlidersEnabled(isEnabled) {
|
||||
if (isEnabled && !self.armed) {
|
||||
$('div.sliders input').slice(0, numberOfValidOutputs).prop('disabled', false);
|
||||
$('div.sliders input').slice(0, self.numberOfValidOutputs).prop('disabled', false);
|
||||
|
||||
// unlock master slider
|
||||
$('div.sliders input:last').prop('disabled', false);
|
||||
|
@ -583,14 +576,14 @@ TABS.motors.initialize = function (callback) {
|
|||
const val = $(this).val();
|
||||
|
||||
$('div.sliders input:not(:disabled, :last)').val(val);
|
||||
$('div.values li:not(:last)').slice(0, numberOfValidOutputs).text(val);
|
||||
$('div.values li:not(:last)').slice(0, self.numberOfValidOutputs).text(val);
|
||||
$('div.sliders input:not(:last):first').trigger('input');
|
||||
});
|
||||
|
||||
// check if motors are already spinning
|
||||
let motorsRunning = false;
|
||||
|
||||
for (let i = 0; i < numberOfValidOutputs; i++) {
|
||||
for (let i = 0; i < self.numberOfValidOutputs; i++) {
|
||||
if (!self.feature3DEnabled) {
|
||||
if (FC.MOTOR_DATA[i] > rangeMin) {
|
||||
motorsRunning = true;
|
||||
|
@ -747,7 +740,11 @@ TABS.motors.initialize = function (callback) {
|
|||
zeroThrottleValue = neutral3d;
|
||||
}
|
||||
|
||||
setup_motor_output_reordering_dialog(content_ready, zeroThrottleValue);
|
||||
setup_motor_output_reordering_dialog(SetupEscDshotDirectionDialogCallback, zeroThrottleValue);
|
||||
|
||||
function SetupEscDshotDirectionDialogCallback() {
|
||||
SetupdescDshotDirectionDialog(content_ready, zeroThrottleValue);
|
||||
}
|
||||
|
||||
function content_ready() {
|
||||
GUI.content_ready(callback);
|
||||
|
@ -764,9 +761,9 @@ TABS.motors.initialize = function (callback) {
|
|||
callbackFunction, mixerList[FC.MIXER_CONFIG.mixer - 1].name,
|
||||
zeroThrottleValue, zeroThrottleValue + 200);
|
||||
|
||||
$('#dialogMotorOutputReorder-closebtn').click(closeDialog);
|
||||
$('#dialogMotorOutputReorder-closebtn').click(closeDialogMotorOutputReorder);
|
||||
|
||||
function closeDialog()
|
||||
function closeDialogMotorOutputReorder()
|
||||
{
|
||||
domDialogMotorOutputReorder[0].close();
|
||||
motorOutputReorderComponent.close();
|
||||
|
@ -776,7 +773,7 @@ TABS.motors.initialize = function (callback) {
|
|||
function onDocumentKeyPress(event)
|
||||
{
|
||||
if (27 === event.which) {
|
||||
closeDialog();
|
||||
closeDialogMotorOutputReorder();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -786,6 +783,47 @@ TABS.motors.initialize = function (callback) {
|
|||
domDialogMotorOutputReorder[0].showModal();
|
||||
});
|
||||
}
|
||||
|
||||
function SetupdescDshotDirectionDialog(callbackFunction, zeroThrottleValue)
|
||||
{
|
||||
const domEscDshotDirectionDialog = $('#escDshotDirectionDialog');
|
||||
|
||||
const idleThrottleValue = zeroThrottleValue + FC.PID_ADVANCED_CONFIG.digitalIdlePercent * 1000 / 100;
|
||||
|
||||
const motorConfig = {
|
||||
numberOfMotors: self.numberOfValidOutputs,
|
||||
motorStopValue: zeroThrottleValue,
|
||||
motorSpinValue: idleThrottleValue,
|
||||
escProtocolIsDshot: self.escProtocolIsDshot,
|
||||
};
|
||||
|
||||
const escDshotDirectionComponent = new EscDshotDirectionComponent(
|
||||
$('#escDshotDirectionDialog-Content'), callbackFunction, motorConfig);
|
||||
|
||||
$('#escDshotDirectionDialog-closebtn').on("click", closeEscDshotDirectionDialog);
|
||||
|
||||
function closeEscDshotDirectionDialog()
|
||||
{
|
||||
domEscDshotDirectionDialog[0].close();
|
||||
escDshotDirectionComponent.close();
|
||||
$(document).off("keydown", onDocumentKeyPress);
|
||||
}
|
||||
|
||||
function onDocumentKeyPress(event)
|
||||
{
|
||||
if (27 === event.which) {
|
||||
closeEscDshotDirectionDialog();
|
||||
}
|
||||
}
|
||||
|
||||
$('#escDshotDirectionDialog-Open').click(function()
|
||||
{
|
||||
$(document).on("keydown", onDocumentKeyPress);
|
||||
domEscDshotDirectionDialog[0].showModal();
|
||||
});
|
||||
|
||||
callbackFunction();
|
||||
}
|
||||
};
|
||||
|
||||
TABS.motors.cleanup = function (callback) {
|
||||
|
|
15
src/js/utils/CommonUtils.js
Normal file
15
src/js/utils/CommonUtils.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
'use strict';
|
||||
|
||||
class CommonUtils
|
||||
{
|
||||
static GetMixerImageSrc(mixerIndex, reverseMotorDir, apiVersion)
|
||||
{
|
||||
let reverse = "";
|
||||
|
||||
if (semver.gte(apiVersion, API_VERSION_1_36)) {
|
||||
reverse = reverseMotorDir ? "_reversed" : "";
|
||||
}
|
||||
|
||||
return `./resources/motor_order/${mixerList[mixerIndex - 1].image}${reverse}.svg`;
|
||||
}
|
||||
}
|
40
src/js/utils/DshotCommand.js
Normal file
40
src/js/utils/DshotCommand.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
'use strict';
|
||||
|
||||
class DshotCommand
|
||||
{
|
||||
static get ALL_MOTORS() { return 255; }
|
||||
}
|
||||
|
||||
DshotCommand.dshotCommands_e = {
|
||||
DSHOT_CMD_MOTOR_STOP: 0,
|
||||
DSHOT_CMD_BEACON1: 1,
|
||||
DSHOT_CMD_BEACON2: 2,
|
||||
DSHOT_CMD_BEACON3: 3,
|
||||
DSHOT_CMD_BEACON4: 4,
|
||||
DSHOT_CMD_BEACON5: 5,
|
||||
DSHOT_CMD_ESC_INFO: 6, // V2 includes settings
|
||||
DSHOT_CMD_SPIN_DIRECTION_1: 7,
|
||||
DSHOT_CMD_SPIN_DIRECTION_2: 8,
|
||||
DSHOT_CMD_3D_MODE_OFF: 9,
|
||||
DSHOT_CMD_3D_MODE_ON: 10,
|
||||
DSHOT_CMD_SETTINGS_REQUEST: 11, // Currently not implemented
|
||||
DSHOT_CMD_SAVE_SETTINGS: 12,
|
||||
DSHOT_CMD_SPIN_DIRECTION_NORMAL: 20,
|
||||
DSHOT_CMD_SPIN_DIRECTION_REVERSED: 21,
|
||||
DSHOT_CMD_LED0_ON: 22, // BLHeli32 only
|
||||
DSHOT_CMD_LED1_ON: 23, // BLHeli32 only
|
||||
DSHOT_CMD_LED2_ON: 24, // BLHeli32 only
|
||||
DSHOT_CMD_LED3_ON: 25, // BLHeli32 only
|
||||
DSHOT_CMD_LED0_OFF: 26, // BLHeli32 only
|
||||
DSHOT_CMD_LED1_OFF: 27, // BLHeli32 only
|
||||
DSHOT_CMD_LED2_OFF: 28, // BLHeli32 only
|
||||
DSHOT_CMD_LED3_OFF: 29, // BLHeli32 only
|
||||
DSHOT_CMD_AUDIO_STREAM_MODE_ON_OFF: 30, // KISS audio Stream mode on/Off
|
||||
DSHOT_CMD_SILENT_MODE_ON_OFF: 31, // KISS silent Mode on/Off
|
||||
DSHOT_CMD_MAX: 47,
|
||||
};
|
||||
|
||||
DshotCommand.dshotCommandType_e = {
|
||||
DSHOT_CMD_TYPE_INLINE: 0, // dshot commands sent inline with motor signal (motors must be enabled)
|
||||
DSHOT_CMD_TYPE_BLOCKING: 1, // dshot commands sent in blocking method (motors must be disabled)
|
||||
};
|
95
src/js/utils/EscProtocols.js
Normal file
95
src/js/utils/EscProtocols.js
Normal file
|
@ -0,0 +1,95 @@
|
|||
'use strict';
|
||||
|
||||
class EscProtocols
|
||||
{
|
||||
static get PROTOCOL_PWM() { return "PWM"; }
|
||||
static get PROTOCOL_ONESHOT125() { return "ONESHOT125"; }
|
||||
static get PROTOCOL_ONESHOT42() { return "ONESHOT42"; }
|
||||
static get PROTOCOL_MULTISHOT() { return "MULTISHOT"; }
|
||||
static get PROTOCOL_BRUSHED() { return "BRUSHED"; }
|
||||
static get PROTOCOL_DSHOT150() { return "DSHOT150"; }
|
||||
static get PROTOCOL_DSHOT300() { return "DSHOT300"; }
|
||||
static get PROTOCOL_DSHOT600() { return "DSHOT600"; }
|
||||
static get PROTOCOL_DSHOT1200() { return "DSHOT1200"; }
|
||||
static get PROTOCOL_PROSHOT1000() { return "PROSHOT1000"; }
|
||||
static get PROTOCOL_DISABLED() { return "DISABLED"; }
|
||||
|
||||
static get DSHOT_PROTOCOLS_SET()
|
||||
{
|
||||
return [
|
||||
EscProtocols.PROTOCOL_DSHOT150,
|
||||
EscProtocols.PROTOCOL_DSHOT300,
|
||||
EscProtocols.PROTOCOL_DSHOT600,
|
||||
EscProtocols.PROTOCOL_DSHOT1200,
|
||||
EscProtocols.PROTOCOL_PROSHOT1000,
|
||||
];
|
||||
}
|
||||
|
||||
static GetProtocolName(apiVersion, protocolIndex)
|
||||
{
|
||||
const escProtocols = EscProtocols.GetAvailableProtocols(apiVersion);
|
||||
return escProtocols[protocolIndex];
|
||||
}
|
||||
|
||||
static IsProtocolDshot(apiVersion, protocolIndex)
|
||||
{
|
||||
const protocolName = EscProtocols.GetProtocolName(apiVersion, protocolIndex);
|
||||
return EscProtocols.DSHOT_PROTOCOLS_SET.includes(protocolName);
|
||||
}
|
||||
|
||||
static GetAvailableProtocols(apiVersion)
|
||||
{
|
||||
const escProtocols = [
|
||||
EscProtocols.PROTOCOL_PWM,
|
||||
EscProtocols.PROTOCOL_ONESHOT125,
|
||||
EscProtocols.PROTOCOL_ONESHOT42,
|
||||
EscProtocols.PROTOCOL_MULTISHOT,
|
||||
];
|
||||
|
||||
if (semver.gte(apiVersion, "1.20.0")) {
|
||||
escProtocols.push(EscProtocols.PROTOCOL_BRUSHED);
|
||||
}
|
||||
|
||||
if (semver.gte(apiVersion, API_VERSION_1_31)) {
|
||||
escProtocols.push(EscProtocols.PROTOCOL_DSHOT150);
|
||||
escProtocols.push(EscProtocols.PROTOCOL_DSHOT300);
|
||||
escProtocols.push(EscProtocols.PROTOCOL_DSHOT600);
|
||||
|
||||
if (semver.lt(apiVersion, API_VERSION_1_42)) {
|
||||
escProtocols.push(EscProtocols.PROTOCOL_DSHOT1200);
|
||||
}
|
||||
}
|
||||
|
||||
if (semver.gte(apiVersion, API_VERSION_1_36)) {
|
||||
escProtocols.push(EscProtocols.PROTOCOL_PROSHOT1000);
|
||||
}
|
||||
|
||||
if (semver.gte(apiVersion, API_VERSION_1_43)) {
|
||||
escProtocols.push(EscProtocols.PROTOCOL_DISABLED);
|
||||
}
|
||||
|
||||
return escProtocols;
|
||||
}
|
||||
|
||||
static ReorderPwmProtocols(apiVersion, protocolIndex)
|
||||
{
|
||||
let result = protocolIndex;
|
||||
|
||||
if (semver.lt(apiVersion, "1.26.0")) {
|
||||
switch (protocolIndex) {
|
||||
case 5:
|
||||
result = 7;
|
||||
break;
|
||||
case 7:
|
||||
result = 5;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -42,6 +42,7 @@
|
|||
<link type="text/css" rel="stylesheet" href="./components/MotorOutputReordering/Styles.css" media="all"/>
|
||||
<link type="text/css" rel="stylesheet" href="./css/select2_custom.css" media="all"/>
|
||||
<link type="text/css" rel="stylesheet" href="./node_modules/select2/dist/css/select2.min.css" media="all"/>
|
||||
<link type="text/css" rel="stylesheet" href="./components/EscDshotDirection/Styles.css" media="all"/>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="./css/dark-theme.css" media="all" disabled/>
|
||||
|
||||
|
@ -72,6 +73,7 @@
|
|||
<script type="text/javascript" src="./js/utils/common.js"></script>
|
||||
<script type="text/javascript" src="./js/utils/css.js"></script>
|
||||
<script type="text/javascript" src="./js/utils/window_watchers.js"></script>
|
||||
<script type="text/javascript" src="./js/utils/CommonUtils.js"></script>
|
||||
<script type="text/javascript" src="./js/injected_methods.js"></script>
|
||||
<script type="text/javascript" src="./js/ConfigStorage.js"></script>
|
||||
<script type="text/javascript" src="./js/data_storage.js"></script>
|
||||
|
@ -142,6 +144,11 @@
|
|||
<script type="text/javascript" src="./components/MotorOutputReordering/MotorOutputReorderingCanvas.js"></script>
|
||||
<script type="text/javascript" src="./components/MotorOutputReordering/MotorOutputReorderingConfig.js"></script>
|
||||
<script type="text/javascript" src="./node_modules/select2/dist/js/select2.min.js"></script>
|
||||
<script type="text/javascript" src="./js/utils/EscProtocols.js"></script>
|
||||
<script type="text/javascript" src="./js/utils/DshotCommand.js"></script>
|
||||
<script type="text/javascript" src="./components/EscDshotDirection/EscDshotDirectionComponent.js"></script>
|
||||
<script type="text/javascript" src="./components/EscDshotDirection/EscDshotDirectionMotorDriver.js"></script>
|
||||
<script type="text/javascript" src="./components/EscDshotDirection/EscDshotCommandQueue.js"></script>
|
||||
|
||||
<title></title>
|
||||
</head>
|
||||
|
|
|
@ -101,6 +101,7 @@
|
|||
</div>
|
||||
<div class="power_info">
|
||||
<a href="#" id="motorOutputReorderDialogOpen" class="regular-button" i18n="motorOutputReorderDialogOpen"></a>
|
||||
<a href="#" id="escDshotDirectionDialog-Open" class="regular-button" i18n="escDshotDirectionDialog-Open"></a>
|
||||
<span i18n="motorsVoltage" class="power_text"></span><span class="motors-bat-voltage power_value"></span>
|
||||
<span i18n="motorsADrawing" class="power_text"></span><span class="motors-bat-mah-drawing power_value"></span>
|
||||
<span i18n="motorsmAhDrawn" class="power_text"></span><span class="motors-bat-mah-drawn power_value"></span>
|
||||
|
@ -200,4 +201,13 @@
|
|||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<dialog id="escDshotDirectionDialog">
|
||||
<div id="escDshotDirectionDialog-ContentWrapper">
|
||||
<div id="escDshotDirectionDialog-Content">
|
||||
</div>
|
||||
<a href="#" id="escDshotDirectionDialog-closebtn" class="regular-button right" i18n="close"></a>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
</div>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue