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
|
@ -2577,7 +2577,7 @@
|
|||
"message": "<strong>Safety notice</strong><br /><strong class=\"message-negative\">Remove all propellers to prevent injury!</strong><br />The motors will <strong>spin up!</strong>"
|
||||
},
|
||||
"motorsRemapDialogExplanations": {
|
||||
"message": "<strong>Information notice</strong><br />Motors will spin up one by one and you will be able to select which motor is spinning. The battery should be plugged in, correct ESC protocol should be selected. This utility can only re-arrange currently active motors. More complex re-mapping requires the CLI Resource command. Refer to this <a href=\"https://github.com/betaflight/betaflight/wiki/Betaflight-resource-remapping\" target=\"_blank\" rel=\"noopener noreferrer\">Wiki page</a>."
|
||||
"message": "<strong>Information notice</strong><br />Motors will spin up one by one and you will be able to select which motor is spinning. The battery should be plugged in, correct ESC protocol should be selected. This utility can only re-arrange currently active motors. More complex re-mapping requires the CLI Resource command. Refer to this <a href=\"https://github.com/betaflight/betaflight/wiki/Betaflight-resource-remapping\" target=\"_blank\" rel=\"noopener noreferrer\">Wiki page</a>."
|
||||
},
|
||||
"motorsRemapDialogSave": {
|
||||
"message": "Save"
|
||||
|
@ -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;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
.tab-motors #dialogMotorOutputReorder {
|
||||
width: 400px;
|
||||
height:440px
|
||||
height: 440px
|
||||
;}
|
||||
|
||||
.tab-motors #dialogMotorOutputReorderContentWrapper {
|
||||
|
@ -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)) {
|
||||
|
@ -416,7 +408,7 @@ TABS.motors.initialize = function (callback) {
|
|||
function computeAndUpdate(sensor_data, data, max_read) {
|
||||
let sum = 0.0;
|
||||
for (let j = 0, jlength = data.length; j < jlength; j++) {
|
||||
for (let k = 0, klength = data[j].length; k < klength; k++){
|
||||
for (let k = 0, klength = data[j].length; k < klength; k++) {
|
||||
sum += data[j][k][1]*data[j][k][1];
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
</div>
|
||||
|
||||
<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