mirror of
https://github.com/betaflight/betaflight-configurator.git
synced 2025-07-24 08:45:28 +03:00
Motor direction dialog for Dshot escs
This commit is contained in:
parent
0f8a2911d9
commit
ca09909d6e
20 changed files with 1255 additions and 104 deletions
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue