...restoring some files

10.3.x-maintenance
skaman82 2015-10-23 15:42:32 +02:00
parent 6c9c64de31
commit 87e9bfd3d9
31 changed files with 1043 additions and 471 deletions

81
README.md Normal file
View File

@ -0,0 +1,81 @@
# Cleanflight Configurator
Cleanflight Configurator is a crossplatform configuration tool for the [Cleanflight](http://cleanflight.com/) flight control system.
It runs as an app within Google Chrome and allows you to configure the Cleanflight software running on any [supported Cleanflight target](https://github.com/cleanflight/cleanflight/blob/master/docs/Boards.md).
Various types of aircraft are supported by the tool and by cleanflight, e.g. quadcopters, hexacopters, octocopters and fixed-wing aircraft.
[![available in the Chrome web store](https://developer.chrome.com/webstore/images/ChromeWebStore_Badge_v2_206x58.png)](https://chrome.google.com/webstore/detail/cleanflight-configurator/enacoimjcgeinfnnnpajinjgmkahmfgb)
## Authors
Dominic Clifton/hydra - maintainer of the Cleanflight firmware and configurator.
Cleanflight Configurator was originally a [fork](#credits) of Baseflight Configurator with support for Cleanflight instead of Baseflight.
This configurator is the only configurator with support for Cleanflight specific features. It will likely require that you run the latest firmware on the flight controller.
If you are experiencing any problems please make sure you are running the [latest firmware version](https://github.com/cleanflight/cleanflight/releases/latest).
## Installation
### Via chrome webstore
1. Visit [Chrome web store](https://chrome.google.com/webstore/detail/cleanflight-configurator/enacoimjcgeinfnnnpajinjgmkahmfgb)
2. Click **+ Free**
Please note - the application will automatically update itself when new versions are released. Please ensure you maintain configuration backups as described in the Cleanflight documentation.
### Alternative way
1. Clone the repo to any local directory or download it as zip
2. Start Chromium or Google Chrome and go to tools -> extension
3. Check the "Developer mode" checkbox
4. Click on load unpacked extension and point it to the Cleanflight Configurator directory (for example D:/cleanflight-configurator)
## How to use
You can find the Cleanflight Configurator icon in your application tab "Apps"
## Notes
### WebGL
Make sure Settings -> System -> "User hardware acceleration when available" is checked to achieve the best performance
### Linux users
1. Dont forget to add your user into dialout group "sudo usermod -aG dialout YOUR_USERNAME" for serial access
2. If you have 3D model animation problems, enable "Override software rendering list" in Chrome flags chrome://flags/#ignore-gpu-blacklist
## Support
If you need help your please use the multiwii or rcgroups forums or visit the IRC channel before raising issues in the issue trackers.
### Issue trackers
For Cleanflight configurator issues raise them here
https://github.com/cleanflight/cleanflight-configurator/issues
For Cleanflight firmware issues raise them here
https://github.com/cleanflight/cleanflight/issues
### IRC Channel
There is an IRC channel for Cleanflight, here: irc://irc.freenode.net/#cleanflight
Support for Baseflight Configurator can also be found on IRC, here: irc://irc.freenode.net/#multiwii
## Technical details
The configurator is based on chrome.serial API running on Google Chrome/Chromium core.
## Developers
We accept clean and reasonable patches, submit them!
## Credits
ctn - primary author and maintainer of Baseflight Configurator from which this project was forked.

View File

@ -211,7 +211,7 @@
"message": "Request Optional Permissions"
},
"defaultWelcomeText": {
"message": "Welcome to <strong>Cleanflight - Configurator</strong>, a utility designed to simplify updating, configuring and tuning of your flight controller.<br /><br />The application supports all hardware that can run cleanflight (<a href=\"http://seriouslypro.com/spracingf3\" target=\"_blank\">SPRacingF3</a>, <a href=\"http://www.immersionrc.com/fpv-products/vortex-racing-quad/\" target=\"_blank\">Vortex</a>, <a href=\"https://github.com/TauLabs/TauLabs/wiki/Sparky\" target=\"_blank\">Sparky</a>, <a href=\"https://www.openpilot.org/product/coptercontrol/\" target=\"_blank\">CC3D/EVO</a>, <a href=\"http://www.multiwiicopter.com/products/paris-air-hero-32-naze\" target=\"_blank\">Air Hero 32</a>, <a href=\"http://www.readytoflyquads.com/flight-controllers/flip-series\" target=\"_blank\">Flip32/+/Deluxe</a>, <a href=\"http://www.goodluckbuy.com/micro-quadcopter-flight-driver-controller-9dof-9-axis-altitude-sensor-stm32f103.html\" target=\"_blank\">CJMCU Microquad</a>, Chebuzz F3, <a href=\"http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/PF254044\" target=\"_blank\">STM32F3Discovery</a>, <a href=\"http://www.overskyrc.com/hermit-micro-fpv-brushless-quadcopter-145mm-98g-fully-assembled-p-621.html\" target=\"_blank\">Hermit</a>, <a href=\"http://rcexplorer.se/blog/2015/05/introducing-the-naze32-tricopter-frame/\" target=\"_blank\">Naze32 Tricopter Frame</a>, <a href=\"http://www.2dogrc.com/skyline-32-naze-32-bit-flight-controller-acro-version.html\" target=\"_blank\">Skyline32</a>, <a href=\"http://abusemark.com/store/index.php?main_page=index&cPath=1\" target=\"_blank\">Naze/32/Mini/Pro</a>/<a href=\"http://www.massiverc.com/PrestaShop/en/574-massive-acro-blackbox-flight-control-board.html\" target=\"_blank\">Blackbox</a> etc)<br /><br />The firmware source code can be downloaded from <a href=\"https://github.com/cleanflight/cleanflight\" title=\"www.github.com\" target=\"_blank\">here</a><br />The newest binary firmware image is available <a href=\"https://github.com/cleanflight/cleanflight/releases\" title=\"www.github.com\" target=\"_blank\">here</a><br /><br />Latest <strong>CP210x Drivers</strong> can be downloaded from <a href=\"http://www.silabs.com/products/mcu/pages/usbtouartbridgevcpdrivers.aspx\" title=\"http://www.silabs.com/\" target=\"_blank\">here</a><br />"
"message": "Welcome to <strong>Cleanflight - Configurator</strong>, a utility designed to simplify updating, configuring and tuning of your flight controller.<br /><br />The application supports all hardware that can run cleanflight (<a href=\"http://seriouslypro.com/spracingf3\" target=\"_blank\">SPRacingF3</a>, <a href=\"http://www.immersionrc.com/fpv-products/vortex-racing-quad/\" target=\"_blank\">Vortex</a>, <a href=\"https://github.com/TauLabs/TauLabs/wiki/Sparky\" target=\"_blank\">Sparky</a>, <a href=\"http://www.readymaderc.com/store/index.php?main_page=product_info&cPath=76_156&products_id=4221\" target=\"_blank\">DoDo</a>, <a href=\"https://www.openpilot.org/product/coptercontrol/\" target=\"_blank\">CC3D/EVO</a>, <a href=\"http://www.multiwiicopter.com/products/paris-air-hero-32-naze\" target=\"_blank\">Air Hero 32</a>, <a href=\"http://www.readytoflyquads.com/flight-controllers/flip-series\" target=\"_blank\">Flip32/+/Deluxe</a>, <a href=\"http://multirotormania.com/129-dragonfly32\" target=\"_blank\">DragonFly32</a>, <a href=\"http://www.goodluckbuy.com/micro-quadcopter-flight-driver-controller-9dof-9-axis-altitude-sensor-stm32f103.html\" target=\"_blank\">CJMCU Microquad</a>, Chebuzz F3, <a href=\"http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/PF254044\" target=\"_blank\">STM32F3Discovery</a>, <a href=\"http://www.overskyrc.com/hermit-micro-fpv-brushless-quadcopter-145mm-98g-fully-assembled-p-621.html\" target=\"_blank\">Hermit</a>, <a href=\"http://rcexplorer.se/blog/2015/05/introducing-the-naze32-tricopter-frame/\" target=\"_blank\">Naze32 Tricopter Frame</a>, <a href=\"http://www.2dogrc.com/skyline-32-naze-32-bit-flight-controller-acro-version.html\" target=\"_blank\">Skyline32</a>, <a href=\"http://abusemark.com/store/index.php?main_page=index&cPath=1\" target=\"_blank\">Naze/32/Mini/Pro</a>/<a href=\"http://www.massiverc.com/PrestaShop/en/574-massive-acro-blackbox-flight-control-board.html\" target=\"_blank\">Blackbox</a> etc)<br /><br />The firmware source code can be downloaded from <a href=\"https://github.com/cleanflight/cleanflight\" title=\"www.github.com\" target=\"_blank\">here</a><br />The newest binary firmware image is available <a href=\"https://github.com/cleanflight/cleanflight/releases\" title=\"www.github.com\" target=\"_blank\">here</a>, development builds available <a href=\"http://cleanflight.memoryleaks.org/builds/\" target=\"_blank\">here</a><br /><br />Latest <strong>CP210x Drivers</strong> can be downloaded from <a href=\"http://www.silabs.com/products/mcu/pages/usbtouartbridgevcpdrivers.aspx\" title=\"http://www.silabs.com/\" target=\"_blank\">here</a><br />"
},
"defaultContributingHead": {
"message": "Contributing"
@ -253,7 +253,7 @@
"message": "Calibrate Accelerometer"
},
"initialSetupCalibrateAccelText": {
"message": "Place board or frame on <strong>leveled</strong> surface, proceed with calibration, ensure platform is not moving during calibration"
"message": "Place board or frame on <strong>leveled</strong> surface, proceed with calibration, ensure platform is not moving during calibration period"
},
"initialSetupButtonCalibrateMag": {
"message": "Calibrate Magnetometer"
@ -372,8 +372,8 @@
"initialSetupModel": {
"message": "Model: $1"
},
"initialSetupHeading": {
"message": "Heading: $1 deg"
"initialSetupAttitude": {
"message": "$1 deg"
},
"initialSetupAccelCalibStarted": {
"message": "Accelerometer calibration started"
@ -426,6 +426,10 @@
"configurationFeaturesHelp": {
"message": "<strong>Note:</strong> Not all combinations of features are valid. When the flight controller firmware detects invalid feature combinations conflicting features will be disabled.<br /><strong>Note:</strong> Configure serial ports <span style=\"color: red\">before</span> enabling the features that will use the ports."
},
"configurationSerialRXHelp": {
"message": "<strong>Note:</strong> Rememer to configure a Serial Port (via Ports tab) and choose a Serial Receiver Provider when using RX_SERIAL feature."
},
"configurationBoardAlignment": {
"message": "Board Alignment"
@ -478,9 +482,6 @@
"configurationBatteryMinimum": {
"message": "Minimum Cell Voltage"
},
"configurationBatteryWarning": {
"message": "Warning Cell Voltage"
},
"configurationBatteryMaximum": {
"message": "Maximum Cell Voltage"
},
@ -502,6 +503,18 @@
"configurationBatteryMultiwiiCurrent": {
"message": "Enable support for legacy Multiwii MSP current output"
},
"configurationSystem": {
"message": "System configuration"
},
"configurationLoopTime": {
"message": "Flight Controller Loop Time"
},
"configurationCalculatedCyclesSec": {
"message": "Cycles/Sec (Hz)"
},
"configurationLoopTimeHelp": {
"message": "<strong>Note:</strong> Changing this may require PID re-tuning."
},
"configurationGPS": {
"message": "GPS"
},
@ -514,6 +527,10 @@
"configurationGPSubxSbas": {
"message": "Ground Assistance Type"
},
"configurationGPSHelp": {
"message": "<strong>Note:</strong> Remember to configure a Serial Port (via Ports tab) when using GPS feature."
},
"configurationSerialRX": {
"message": "Serial Receiver Provider"
},
@ -525,7 +542,10 @@
},
"portsHelp": {
"message": "Configure serial ports. <strong>Note:</strong> not all combinations are valid. When the flight controller firmware detects this the serial port configuration will be reset."
"message": "<strong>Note:</strong> not all combinations are valid. When the flight controller firmware detects this the serial port configuration will be reset."
},
"portsMSPHelp": {
"message": "<strong>Note:</strong> Do <span style=\"color: red\">NOT</span> disable MSP on the first serial port unless you know what you are doing. You may have to reflash and erase your configuration if you do."
},
"portsFirmwareUpgradeRequired": {
"message": "Firmware upgrade <span style=\"color: red\">required</span>. Serial port configurations of firmware &lt; 1.8.0 is not supported."
@ -616,6 +636,9 @@
"message": "EEPROM <span style=\"color: green\">saved</span>"
},
"receiverHelp": {
"message": "Please read receiver chapter of the documentation. Configure serial port (if required), receiver mode (serial/ppm/pwm), provider (for serial receivers), bind receiver, set channel map, configure channel endpoints/range on TX so that all channels go from ~1000 to ~2000. Set midpoint (default 1500), trim channels to 1500, configure stick deadband, verify behaviour when TX is off or out of range.<br /><span style=\"color: red\">IMPORTANT:</span> Before flying read failsafe chapter of documentation and configure failsafe."
},
"receiverThrottleMid": {
"message": "Throttle MID"
},
@ -649,6 +672,9 @@
"receiverButtonRefresh": {
"message": "Refresh"
},
"receiverButtonSticks": {
"message": "Control sticks"
},
"receiverDataRefreshed": {
"message": "RC Tuning data <strong>refreshed</strong>"
},
@ -794,15 +820,13 @@
},
"servosModel": {
"message": "Model:"
"servosFirmwareUpgradeRequired": {
"message": "Servos requires firmware &gt;= 1.10.0."
},
"servosChangeDirection": {
"message": "Change Direction in TX To Match"
},
"servosGyroAccelDirection": {
"message": "Gyroscope / Accelerometer Direction"
},
"servosName": {
"message": "Name"
},
@ -815,8 +839,14 @@
"servosMax": {
"message": "MAX"
},
"servosDirection": {
"message": "Direction"
"servosAngleAtMin": {
"message": "Angle at min"
},
"servosAngleAtMax": {
"message": "Angle at max"
},
"servosDirectionAndRate": {
"message": "Direction and rate"
},
"servosLiveMode": {
"message": "Enable Live mode:"
@ -824,9 +854,6 @@
"servosButtonSave": {
"message": "Save"
},
"servosModelNoSupport": {
"message": "This model doesn't support servos"
},
"servosNormal": {
"message": "Normal"
},
@ -1045,7 +1072,7 @@
"message": "Attempt to flash the board automatically (triggered by newly detected serial port)"
},
"firmwareFlasherFullChipErase": {
"message": "Full Chip Erase"
"message": "Full chip erase"
},
"firmwareFlasherFullChipEraseDescription": {
"message": "Wipes all configuration data currently stored on the board"
@ -1057,7 +1084,7 @@
"message": "Flash most recent (untested) development firmware"
},
"firmwareFlasherManualBaud": {
"message": "Manual Baud Rate"
"message": "Manual baud rate"
},
"firmwareFlasherManualBaudDescription": {
"message": "Manual selection of baud rate for boards that don't support the default speed or for flashing via bluetooth."
@ -1102,7 +1129,7 @@
"message": "Warning"
},
"firmwareFlasherWarningText": {
"message": "Please do not try to flash <strong>non-cleanflight</strong> hardware with this firmware flasher (it wont work).<br />Do not <strong>disconnect</strong> the board or <strong>turn off</strong> your computer while flashing.<br /><br />Note: <strong>STM32</strong> bootloader is stored in <strong>ROM</strong>, it cannot be bricked.<br />Note: <strong>Auto-Connect</strong> is always disabled while you are inside firmware flasher.<br />Note: This can wipe your configuration including but not limited to PIDs, Auxiliary, and FEATURES. Make sure you have a backup.<br />"
"message": "Please do <span style=\"color: red\">not</span> try to flash <strong>non-cleanflight</strong> hardware with this firmware flasher.<br />Do <span style=\"color: red\">not</span> <strong>disconnect</strong> the board or <strong>turn off</strong> your computer while flashing.<br /><br /><span style=\"color: green\">Note: </span>STM32 bootloader is stored in ROM, it cannot be bricked.<br />Note: <strong>Auto-Connect</strong> is always disabled while you are inside firmware flasher.<br /><span style=\"color: red\">Note: </span>Make sure you have a backup; some upgrades/downgrades will wipe your configuration.<br /><span style=\"color: green\">Note:</span> If you have problems flashing try disconnecting all cables from your FC.<br /><br /><span style=\"color: green\">Note: </span>If you have lost comminication with your board then power off the board, jumper the bootloader pins, power on, enable 'No reboot sequence', enable 'Full chip erase', re-flash, then power off, remove bootloader jumper, power on and connect (For all firmware except OPBL firmware)."
},
"firmwareFlasherButtonLeave": {
"message": "Leave Firmware Flasher"
@ -1128,5 +1155,41 @@
},
"ledStripEepromSaved": {
"message": "EEPROM <span style=\"color: green\">saved</span>"
},
"controlAxisRoll": {
"message": "Roll"
},
"controlAxisPitch": {
"message": "Pitch"
},
"controlAxisYaw": {
"message": "Yaw"
},
"controlAxisThrottle": {
"message": "Throttle"
},
"controlAxisAux1": {
"message": "AUX 1"
},
"controlAxisAux2": {
"message": "AUX 2"
},
"controlAxisAux3": {
"message": "AUX 3"
},
"controlAxisAux4": {
"message": "AUX 4"
},
"controlAxisAux5": {
"message": "AUX 5"
},
"controlAxisAux6": {
"message": "AUX 6"
},
"controlAxisAux7": {
"message": "AUX 7"
},
"controlAxisAux8": {
"message": "AUX 8"
}
}
}

View File

@ -1,3 +1,10 @@
<span>2015.10.02 - 0.66.0 - cleanflight</span>
<p>
- Update servo configuration (requires firmware &gt;= 1.10.0).<br />
- Add some notes and help messages for common issues.<br />
- Update sponsors panel and add links to new boards.<br />
- Upgrade some JS libraries to latest versions (Three, JQuery/UI, D3)<br />
</p>
<span>2015.05.23 - 0.65.0 - cleanflight</span>
<p>
- Support flashing of the SPRacingF3.<br />
@ -23,10 +30,10 @@
</p>
<span>2015.03.29 - 0.63.0 - cleanflight</span>
<p>
- Configuration tab supports auto_disarm_delay and disarm_kill_switch - Requires 1.8.0 firmware.<br />
- PID Tuning tab allows TPA Breakpoint changes - Requires 1.8.0 firmware.<br />
- Corrected Artificial Horizon Pitch/Roll views.<br />
- Changed logging time stamp to include date stamp.<br />
- Configuration tab supports auto_disarm_delay and disarm_kill_switch (requires firmware &gt;= 1.8.0).<br />
- PID Tuning tab allows TPA Breakpoint changes (requires firmware &gt;= 1.8.0).<br />
- Correct Artificial Horizon Pitch/Roll views.<br />
- Change logging time stamp to include date stamp.<br />
- Support new firmware 1.8 serial port configuration.<br />
- Move documentation and help to new tab.<br />
- Add contributing section to welcome tab.<br />
@ -38,7 +45,7 @@
<span>2015.02.26 - 0.62.0 - cleanflight</span>
<p>
- Add flight indicators to setup screen tab.<br />
- Add dataflash tab. Requires 1.8.0 firmware.<br />
- Add dataflash tab (requires firmware &gt;= 1.8.0)..<br />
- Add Cleanflight logos.<br />
- Fix loading online flash files - github moved them to amazon aws.<br />
- Fix to fallback 3D model.<br />
@ -46,7 +53,7 @@
</p>
<span>2015.02.03 - 0.61.0 - cleanflight</span>
<p>
- Support changing PID controller - there new PID controllers in 1.7.0 firmware.<br />
- Support changing PID controller - three new PID controllers in 1.7.0 firmware.<br />
- Support for LED thrust ring.<br />
- Support for LED colors.<br />
- Support for displaying sonar sensor reading on the sensors tab.<br />
@ -54,21 +61,21 @@
- New Logo. (Tom McCullough)<br />
- New 3D models (AkFreak).<br />
- Update presentation of LEDs that have multiple functions.<br />
- Added Documentation and Support panels to welcome tab.<br />
- Add Documentation and Support panels to welcome tab.<br />
- Add support for backup and restore of LED strip configuration.<br />
- Fix for disappearing tabs in chrome 41 beta.<br />
- Various other minor improvements.<br />
</p>
<span>2015.01.08 - 0.60.0 - cleanflight</span>
<p>
- Add LED strip tab for LED configuration - requires v1.6.0 firmware to save.<br />
- Add LED strip tab for LED configuration (requires firmware &gt;= 1.6.0)..<br />
- Replace motor order images (stronnag)<br />
</p>
<span>2015.01.08 - 0.59.1 - cleanflight</span>
<p>
- Add support for Blackbox flight recorder feature (requires v1.5.0 firmware).<br />
- Add support for Blackbox flight recorder feature (requires firmware &gt;= 1.5.0).<br />
- Update RSSI channel section to allow any channel.<br />
- Implemented configuration migration to aid with backwards compatibility.<br />
- Implement configuration migration to aid with backwards compatibility.<br />
- Allow CLI access when connecting firmware with an out-of-date API.<br />
- Support 'release candidate' and 'stable' releases.
</p>
@ -88,7 +95,7 @@
<span>2014.12.06 - 0.57.1 - cleanflight</span>
<p>
- Latest firmware <strong>required</strong>.<br />
- Merged latest baseflight configurator changes.<br />
- Merge latest baseflight configurator changes.<br />
- Added support for choosing and downloading firmware via the github relases API.<br />
- Added Armattan Quads as a sponsor.<br />
- Various UI tweaks.<br />
@ -96,17 +103,17 @@
<span>2014.12.06 - 0.57</span>
<p>
- Firmware flasher now contains firmware builds picker<br />
- Implemented new and experimental review mechanism<br />
- Implement new and experimental review mechanism<br />
- Support for new A-tail Quad craft type<br />
- Firmware flasher flashing speed optimizations<br />
- Added specific 3D models for atail/vtail quad (norem)<br />
- Add specific 3D models for atail/vtail quad (norem)<br />
- Major bugfix for stuck UI after delayed port open procedure<br />
- Bugfix for GPS distance to home not displaying<br />
- Bugfix for backup/restore misbehaving (mostly on OSX)<br />
</p>
<span>2014.11.04 - 0.56</span>
<p>
- Added hex plus, hex X, tri, y4, y6 3D models (jef79m)<br />
- Add hex plus, hex X, tri, y4, y6 3D models (jef79m)<br />
- Bugfix for battery voltage saving sequence<br />
- Bugfix for fetching development firmware<br />
</p>
@ -116,9 +123,9 @@
- Minimum accepted firmware version set to 2.31<br />
- Support for flashing development firmware<br />
- Setup tab performance improvements, faster 3D model<br />
- Strongly improved amount of data stored in backups<br />
- Improved flash on connect in firmware flasher<br />
- Rearranged texts and options in firmware flasher<br />
- Strongly improve amount of data stored in backups<br />
- Improve flash on connect in firmware flasher<br />
- Rearrange texts and options in firmware flasher<br />
- Bugfix for corrupted minimum window size on Windows 7<br />
- Bugfix for incorrect date &amp; time in firmware flasher<br />
- Bugfix for port handler firing before port being initialized<br />

View File

@ -30,12 +30,21 @@ function configuration_backup(callback) {
MSP_codes.MSP_PID,
MSP_codes.MSP_RC_TUNING,
MSP_codes.MSP_ACC_TRIM,
MSP_codes.MSP_SERVO_CONF,
MSP_codes.MSP_CHANNEL_FORWARDING,
MSP_codes.MSP_SERVO_CONFIGURATIONS,
MSP_codes.MSP_MODE_RANGES,
MSP_codes.MSP_ADJUSTMENT_RANGES
];
function update_profile_specific_data_list() {
if (semver.lt(CONFIG.apiVersion, "1.12.0")) {
profileSpecificData.push(MSP_codes.MSP_CHANNEL_FORWARDING);
} else {
profileSpecificData.push(MSP_codes.MSP_SERVO_MIX_RULES);
}
}
update_profile_specific_data_list();
function fetch_specific_data() {
var fetchingProfile = 0,
codeKey = 0;
@ -54,6 +63,7 @@ function configuration_backup(callback) {
'RC': jQuery.extend(true, {}, RC_tuning),
'AccTrim': jQuery.extend(true, [], CONFIG.accelerometerTrims),
'ServoConfig': jQuery.extend(true, [], SERVO_CONFIG),
'ServoRules': jQuery.extend(true, [], SERVO_RULES),
'ModeRanges': jQuery.extend(true, [], MODE_RANGES),
'AdjustmentRanges': jQuery.extend(true, [], ADJUSTMENT_RANGES)
});
@ -428,6 +438,38 @@ function configuration_restore(callback) {
}
}
if (semver.lt(migratedVersion, '0.66.0')) {
// api 1.12 updated servo configuration protocol and added servo mixer rules
for (var profileIndex = 0; i < configuration.profiles.length; i++) {
if (semver.eq(configuration.apiVersion, '1.10.0')) {
// drop two unused servo configurations
while (configuration.profiles[profileIndex].ServoConfig.length > 8) {
configuration.profiles[profileIndex].ServoConfig.pop();
}
}
for (var i = 0; i < configuration.profiles[profileIndex].ServoConfig.length; i++) {
var servoConfig = profiles[profileIndex].ServoConfig;
servoConfig[i].angleAtMin = 90;
servoConfig[i].angleAtMax = 90;
servoConfig[i].reversedInputSources = 0;
// set the rate to 0 if an invalid value is detected.
if (servoConfig[i].rate < -100 || servoConfig[i].rate > 100) {
servoConfig[i].rate = 0;
}
}
configuration.profiles[profileIndex].ServoRules = [];
}
migratedVersion = '0.66.0';
appliedMigrationsCount++;
}
if (appliedMigrationsCount > 0) {
GUI.log(chrome.i18n.getMessage('configMigrationSuccessful', [appliedMigrationsCount]));
}
@ -444,9 +486,7 @@ function configuration_restore(callback) {
MSP_codes.MSP_SET_PID_CONTROLLER,
MSP_codes.MSP_SET_PID,
MSP_codes.MSP_SET_RC_TUNING,
MSP_codes.MSP_SET_ACC_TRIM,
MSP_codes.MSP_SET_SERVO_CONF,
MSP_codes.MSP_SET_CHANNEL_FORWARDING
MSP_codes.MSP_SET_ACC_TRIM
];
MSP.send_message(MSP_codes.MSP_STATUS, false, false, function () {
@ -472,6 +512,7 @@ function configuration_restore(callback) {
RC_tuning = configuration.profiles[profile].RC;
CONFIG.accelerometerTrims = configuration.profiles[profile].AccTrim;
SERVO_CONFIG = configuration.profiles[profile].ServoConfig;
SERVO_RULES = configuration.profiles[profile].ServoRules;
MODE_RANGES = configuration.profiles[profile].ModeRanges;
ADJUSTMENT_RANGES = configuration.profiles[profile].AdjustmentRanges;
}
@ -501,6 +542,14 @@ function configuration_restore(callback) {
});
}
function upload_servo_mix_rules() {
MSP.sendServoMixRules(upload_servo_configuration);
}
function upload_servo_configuration() {
MSP.sendServoConfigurations(upload_mode_ranges);
}
function upload_mode_ranges() {
MSP.sendModeRanges(upload_adjustment_ranges);
}
@ -510,7 +559,7 @@ function configuration_restore(callback) {
}
// start uploading
load_objects(0);
upload_mode_ranges();
upload_servo_configuration();
}
function upload_unique_data() {

View File

@ -3,58 +3,43 @@
var BOARD_DEFINITIONS = [
{
name: "CC3D",
identifier: "CC3D",
vcp: true
identifier: "CC3D"
}, {
name: "ChebuzzF3",
identifier: "CHF3",
vcp: false
identifier: "CHF3"
}, {
name: "CJMCU",
identifier: "CJM1",
vcp: false
identifier: "CJM1"
}, {
name: "EUSTM32F103RB",
identifier: "EUF1",
vcp: false
identifier: "EUF1"
}, {
name: "Naze/Flip32+",
identifier: "AFNA",
vcp: false
identifier: "AFNA"
}, {
name: "Naze32Pro",
identifier: "AFF3",
vcp: false
identifier: "AFF3"
}, {
name: "Olimexino",
identifier: "OLI1"
}, {
name: "Port103R",
identifier: "103R",
vcp: false
identifier: "103R"
}, {
name: "Sparky",
identifier: "SPKY",
vcp: true
identifier: "SPKY"
}, {
name: "STM32F3Discovery",
identifier: "SDF3",
vcp: true
}, {
name: "Colibri Race",
identifier: "CLBR",
vcp: true
identifier: "SDF3"
}, {
name: "SP Racing F3",
identifier: "SRF3",
vcp: false
identifier: "SRF3"
}
];
var DEFAULT_BOARD_DEFINITION = {
name: "Unknown",
identifier: "????",
vcp: false
identifier: "????"
};
var BOARD = {

View File

@ -1,7 +1,7 @@
'use strict';
var CONFIGURATOR = {
'releaseDate': 1432389468227, // new Date().getTime() - Sat May 23 2015 14:57:54 GMT+0100 (BST)
'releaseDate': 1443815435720, // new Date().getTime() - Fri Oct 02 2015 20:50:49 GMT+0100 (GMT Daylight Time)
// all versions are specified and compared using semantic versioning http://semver.org/
'apiVersionAccepted': '1.2.0',
@ -86,6 +86,7 @@ var MODE_RANGES = [];
var ADJUSTMENT_RANGES = [];
var SERVO_CONFIG = [];
var SERVO_RULES = [];
var SERIAL_CONFIG = {
ports: [],

4
js/libraries/jquery-2.1.4.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

13
js/libraries/jquery-ui-1.11.4.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -2,27 +2,30 @@
// generate mixer
var mixerList = [
{name: 'Tricopter', model: 'tricopter', image: 'tri'},
{name: 'Quad +', model: 'quad_x', image: 'quad_p'},
{name: 'Quad X', model: 'quad_x', image: 'quad_x'},
{name: 'Bicopter', model: 'custom', image: 'bicopter'},
{name: 'Gimbal', model: 'custom', image: 'custom'},
{name: 'Y6', model: 'y6', image: 'y6'},
{name: 'Hex +', model: 'hex_plus', image: 'hex_p'},
{name: 'Flying Wing', model: 'custom', image: 'flying_wing'},
{name: 'Y4', model: 'y4', image: 'y4'},
{name: 'Hex X', model: 'hex_x', image: 'hex_x'},
{name: 'Octo X8', model: 'custom', image: 'octo_x8'},
{name: 'Octo Flat +', model: 'custom', image: 'octo_flat_p'},
{name: 'Octo Flat X', model: 'custom', image: 'octo_flat_x'},
{name: 'Airplane', model: 'custom', image: 'airplane'},
{name: 'Heli 120', model: 'custom', image: 'custom'},
{name: 'Heli 90', model: 'custom', image: 'custom'},
{name: 'V-tail Quad', model: 'quad_vtail', image: 'vtail_quad'},
{name: 'Hex H', model: 'custom', image: 'custom'},
{name: 'PPM to SERVO', model: 'custom', image: 'custom'},
{name: 'Dualcopter', model: 'custom', image: 'custom'},
{name: 'Singlecopter', model: 'custom', image: 'custom'},
{name: 'A-tail Quad', model: 'quad_atail', image: 'atail_quad'},
{name: 'Custom', model: 'custom', image: 'custom'}
{name: 'Tricopter', model: 'tricopter', image: 'tri'},
{name: 'Quad +', model: 'quad_x', image: 'quad_p'},
{name: 'Quad X', model: 'quad_x', image: 'quad_x'},
{name: 'Bicopter', model: 'custom', image: 'bicopter'},
{name: 'Gimbal', model: 'custom', image: 'custom'},
{name: 'Y6', model: 'y6', image: 'y6'},
{name: 'Hex +', model: 'hex_plus', image: 'hex_p'},
{name: 'Flying Wing', model: 'custom', image: 'flying_wing'},
{name: 'Y4', model: 'y4', image: 'y4'},
{name: 'Hex X', model: 'hex_x', image: 'hex_x'},
{name: 'Octo X8', model: 'custom', image: 'octo_x8'},
{name: 'Octo Flat +', model: 'custom', image: 'octo_flat_p'},
{name: 'Octo Flat X', model: 'custom', image: 'octo_flat_x'},
{name: 'Airplane', model: 'custom', image: 'airplane'},
{name: 'Heli 120', model: 'custom', image: 'custom'},
{name: 'Heli 90', model: 'custom', image: 'custom'},
{name: 'V-tail Quad', model: 'quad_vtail', image: 'vtail_quad'},
{name: 'Hex H', model: 'custom', image: 'custom'},
{name: 'PPM to SERVO', model: 'custom', image: 'custom'},
{name: 'Dualcopter', model: 'custom', image: 'custom'},
{name: 'Singlecopter', model: 'custom', image: 'custom'},
{name: 'A-tail Quad', model: 'quad_atail', image: 'atail_quad'},
{name: 'Custom', model: 'custom', image: 'custom'},
{name: 'Custom Airplane', model: 'custom', image: 'custom'},
{name: 'Custom Tricopter', model: 'custom', image: 'custom'}
];

View File

@ -238,21 +238,10 @@ function onConnect() {
$('#tabs ul.mode-connected').show();
if ("CLFL" == CONFIG.flightControllerIdentifier){
/* placing this elsewhere
var documentationButton = $('#button-documentation');
var documentationButton = $('#button-documentation');
documentationButton.show();
documentationButton.html("Documentation for "+CONFIG.flightControllerVersion);
documentationButton.attr("href","https://github.com/cleanflight/cleanflight/tree/v{0}/docs".format(CONFIG.flightControllerVersion));
*/
/* just a thought
var sensor_state = $('#sensor-status');
sensor_state.show();
*/
var flashstate = $('#header_dataflash');
flashstate.show();
}
}
@ -266,14 +255,8 @@ function onClosed(result) {
$('#tabs ul.mode-connected').hide();
$('#tabs ul.mode-disconnected').show();
var flashstate = $('#header_dataflash');
flashstate.hide();
/* just a thought
var sensor_state = $('#sensor-status');
sensor_state.hide();
*/
var documentationButton = $('#button-documentation');
documentationButton.hide();
}
function read_serial(info) {

View File

@ -141,6 +141,13 @@ TABS.cli.read = function (readInfo) {
text += "<br />";
}
break;
case 60:
text += '&lt';
break;
case 62:
text += '&gt';
break;
default:
text += String.fromCharCode(data[i]);
}

View File

@ -99,6 +99,13 @@
border: 1px solid silver;
}
.tab-configuration .number input.disabled {
width: 50px;
padding: 0px 5px;
background-color: #ececec;
}
.tab-configuration .number span {
margin-left: 10px;
line-height: 20px;
@ -154,7 +161,6 @@
.tab-configuration .disarm .checkbox span {
margin-left: 15px;
}
.tab-configuration .save {
display: block;
float: right;

View File

@ -127,19 +127,10 @@
<!-- list generated here -->
</select>
<div class="groupTitle" i18n="configurationRSSI"></div>
<table>
<thead>
<tr>
<th i18n="configurationFeatureEnabled"></th>
<th i18n="configurationFeatureName"></th>
<th i18n="configurationFeatureDescription"></th>
</tr>
</thead>
<tbody class="features rssi">
<!-- table generated here -->
</tbody>
</table>
<div class="help">
<p i18n="configurationSerialRXHelp"></p>
</div>
<div class="groupTitle" i18n="configurationFailsafe"></div>
<table>
<thead>
@ -159,8 +150,6 @@
<span i18n="configurationThrottleFailsafe"></span>
</label>
</div>
</div>
<div class="rightWrapper current voltage">
<div class="groupTitle" i18n="configurationBatteryVoltage"></div>
@ -183,12 +172,6 @@
<span i18n="configurationBatteryMinimum"></span>
</label>
</div>
<div class="number">
<label>
<input type="number" name="warningcellvoltage" step="0.1" min="1" max="5" />
<span i18n="configurationBatteryWarning"></span>
</label>
</div>
<div class="number">
<label>
<input type="number" name="maxcellvoltage" step="0.1" min="1" max="5" />
@ -207,7 +190,7 @@
<span i18n="configurationBatteryScale"></span>
</label>
</div>
<div class="groupTitle" i18n="configurationCurrent"></div>
<div class="groupTitle" i18n="configurationCurrent"></div>
<table>
<thead>
<tr>
@ -239,8 +222,42 @@
</div>
<span i18n="configurationBatteryMultiwiiCurrent"></span>
</label>
</div>
</div>
</div>
<div class="clear-both"></div>
<div class="leftWrapper rssi">
<div class="groupTitle" i18n="configurationRSSI"></div>
<table>
<thead>
<tr>
<th i18n="configurationFeatureEnabled"></th>
<th i18n="configurationFeatureName"></th>
<th i18n="configurationFeatureDescription"></th>
</tr>
</thead>
<tbody class="features rssi">
<!-- table generated here -->
</tbody>
</table>
</div>
<div class="rightWrapper system">
<div class="groupTitle" i18n="configurationSystem"></div>
<div class="number">
<label>
<input type="number" name="looptime" step="100" min="0" max="9000"/>
<span i18n="configurationLoopTime"></span>
</label>
</div>
<div class="number">
<label>
<input type="text" name="looptimehz" readonly="readonly" class="disabled"/>
<span i18n="configurationCalculatedCyclesSec"></span>
</label>
</div>
<p class="help" i18n="configurationLoopTimeHelp"></p>
</div>
<div class="clear-both"></div>
<div class="leftWrapper gps">
<div class="groupTitle" i18n="configurationGPS"></div>
@ -281,6 +298,11 @@
<span i18n="configurationMagDeclination"></span>
</label>
</div>
<div class="help">
<p i18n="configurationGPSHelp"></p>
</div>
</div>
<div class="rightWrapper">
<div class="groupTitle" i18n="configurationFeatures"></div>
@ -297,6 +319,7 @@
</tbody>
</table>
</div>
<div class="clear-both"></div>
<div class="buttons">
<a class="save" href="#" i18n="configurationButtonSave"></a>

67
tabs/configuration.js Executable file → Normal file
View File

@ -36,7 +36,11 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
}
function load_arming_config() {
MSP.send_message(MSP_codes.MSP_ARMING_CONFIG, false, false, load_html);
MSP.send_message(MSP_codes.MSP_ARMING_CONFIG, false, false, load_loop_time);
}
function load_loop_time() {
MSP.send_message(MSP_codes.MSP_LOOP_TIME, false, false, load_html);
}
function load_html() {
@ -45,6 +49,17 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
MSP.send_message(MSP_codes.MSP_IDENT, false, false, load_config);
function recalculate_cycles_sec() {
var looptime = $('input[name="looptime"]').val();
var message = 'Max';
if (looptime > 0) {
message = parseFloat((1 / looptime) * 1000 * 1000).toFixed(0);
}
$('input[name="looptimehz"]').val(message);
}
function process_html() {
// translate to user-selected language
localize();
@ -73,7 +88,7 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
{bit: 3, group: 'rxMode', mode: 'group', name: 'RX_SERIAL', description: 'Serial-based receiver (SPEKSAT, SBUS, SUMD)'},
{bit: 4, group: 'esc', name: 'MOTOR_STOP', description: 'Don\'t spin the motors when armed'},
{bit: 5, group: 'other', name: 'SERVO_TILT', description: 'Servo gimbal'},
{bit: 6, group: 'other', name: 'SOFTSERIAL', description: 'Enable CPU based serial ports (configure port scenario first)'},
{bit: 6, group: 'other', name: 'SOFTSERIAL', description: 'Enable CPU based serial ports'},
{bit: 7, group: 'gps', name: 'GPS', description: 'GPS (configure port scenario first)'},
{bit: 8, group: 'rxFailsafe', name: 'FAILSAFE', description: 'Failsafe settings on RX signal loss'},
{bit: 9, group: 'other', name: 'SONAR', description: 'Sonar'},
@ -88,6 +103,12 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
{bit: 18, group: 'esc', name: 'ONESHOT125', description: 'ONESHOT ESC support (disconnect ESCs, remove props)'},
{bit: 19, group: 'other', name: 'BLACKBOX', description: 'Blackbox flight data recorder'}
];
if (semver.gte(CONFIG.apiVersion, "1.12.0")) {
features.push(
{bit: 20, group: 'other', name: 'CHANNEL_FORWARDING', description: 'Forward aux channels to remaining servo outputs'}
);
}
var radioGroups = [];
@ -256,7 +277,7 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
// fill magnetometer
$('input[name="mag_declination"]').val(MISC.mag_declination);
//fill motor disarm params
//fill motor disarm params and FC loop time
if(semver.gte(CONFIG.apiVersion, "1.8.0")) {
$('input[name="autodisarmdelay"]').val(ARMING_CONFIG.auto_disarm_delay);
$('input[name="disarmkillswitch"]').prop('checked', ARMING_CONFIG.disarm_kill_switch);
@ -265,6 +286,13 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
$('div.disarmdelay').show();
else
$('div.disarmdelay').hide();
// fill FC loop time
$('input[name="looptime"]').val(FC_CONFIG.loopTime);
recalculate_cycles_sec();
$('div.cycles').show();
}
// fill throttle
@ -276,7 +304,6 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
// fill battery
$('input[name="mincellvoltage"]').val(MISC.vbatmincellvoltage);
$('input[name="warningcellvoltage"]').val(MISC.vbatwarningcellvoltage);
$('input[name="maxcellvoltage"]').val(MISC.vbatmaxcellvoltage);
$('input[name="warningcellvoltage"]').val(MISC.vbatwarningcellvoltage);
$('input[name="voltagescale"]').val(MISC.vbatscale);
@ -288,6 +315,10 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
// UI hooks
$('input[name="looptime"]').change(function() {
recalculate_cycles_sec();
});
$('input[type="checkbox"].feature', features_e).change(function () {
var element = $(this),
index = element.data('bit'),
@ -339,6 +370,7 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
if(semver.gte(CONFIG.apiVersion, "1.8.0")) {
ARMING_CONFIG.auto_disarm_delay = parseInt($('input[name="autodisarmdelay"]').val());
ARMING_CONFIG.disarm_kill_switch = ~~$('input[name="disarmkillswitch"]').is(':checked'); // ~~ boolean to decimal conversion
FC_CONFIG.loopTime = parseInt($('input[name="looptime"]').val());
}
MISC.minthrottle = parseInt($('input[name="minthrottle"]').val());
@ -348,7 +380,6 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
MISC.mincommand = parseInt($('input[name="mincommand"]').val());
MISC.vbatmincellvoltage = parseFloat($('input[name="mincellvoltage"]').val());
MISC.vbatwarningcellvoltage = parseFloat($('input[name="warningcellvoltage"]').val());
MISC.vbatmaxcellvoltage = parseFloat($('input[name="maxcellvoltage"]').val());
MISC.vbatwarningcellvoltage = parseFloat($('input[name="warningcellvoltage"]').val());
MISC.vbatscale = parseInt($('input[name="voltagescale"]').val());
@ -375,7 +406,11 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
}
function save_arming_config() {
MSP.send_message(MSP_codes.MSP_SET_ARMING_CONFIG, MSP.crunch(MSP_codes.MSP_SET_ARMING_CONFIG), false, save_to_eeprom);
MSP.send_message(MSP_codes.MSP_SET_ARMING_CONFIG, MSP.crunch(MSP_codes.MSP_SET_ARMING_CONFIG), false, save_looptime_config);
}
function save_looptime_config() {
MSP.send_message(MSP_codes.MSP_SET_LOOP_TIME, MSP.crunch(MSP_codes.MSP_SET_LOOP_TIME), false, save_to_eeprom);
}
function save_to_eeprom() {
@ -392,21 +427,13 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
function reinitialize() {
GUI.log(chrome.i18n.getMessage('deviceRebooting'));
if (BOARD.find_board_definition(CONFIG.boardIdentifier).vcp) { // VCP-based flight controls may crash old drivers, we catch and reconnect
$('a.connect').click();
GUI.timeout_add('start_connection',function start_connection() {
$('a.connect').click();
},2000);
} else {
GUI.timeout_add('waiting_for_bootup', function waiting_for_bootup() {
MSP.send_message(MSP_codes.MSP_IDENT, false, false, function () {
GUI.log(chrome.i18n.getMessage('deviceReady'));
TABS.configuration.initialize(false, $('#content').scrollTop());
});
},1500); // 1500 ms seems to be just the right amount of delay to prevent data request timeouts
}
GUI.timeout_add('waiting_for_bootup', function waiting_for_bootup() {
MSP.send_message(MSP_codes.MSP_IDENT, false, false, function () {
GUI.log(chrome.i18n.getMessage('deviceReady'));
TABS.configuration.initialize(false, $('#content').scrollTop());
});
},1500); // 1500 ms seems to be just the right amount of delay to prevent data request timeouts
}
MSP.send_message(MSP_codes.MSP_SET_BF_CONFIG, MSP.crunch(MSP_codes.MSP_SET_BF_CONFIG), false, save_serial_config);

View File

@ -59,7 +59,7 @@ TABS.dataflash.initialize = function (callback) {
display: 'block'
});
$(".tab-dataflash .dataflash-used div").text('Used space: ' + formatFilesize(DATAFLASH.usedSize));
$(".tab-dataflash .dataflash-used div").text('Used space ' + formatFilesize(DATAFLASH.usedSize));
} else {
$(".tab-dataflash .dataflash-used").css({
display: 'none'
@ -71,7 +71,7 @@ TABS.dataflash.initialize = function (callback) {
width: ((DATAFLASH.totalSize - DATAFLASH.usedSize) / DATAFLASH.totalSize * 100) + "%",
display: 'block'
});
$(".tab-dataflash .dataflash-free div").text('Free space: ' + formatFilesize(DATAFLASH.totalSize - DATAFLASH.usedSize));
$(".tab-dataflash .dataflash-free div").text('Free space ' + formatFilesize(DATAFLASH.totalSize - DATAFLASH.usedSize));
} else {
$(".tab-dataflash .dataflash-free").css({
display: 'none'
@ -146,53 +146,66 @@ TABS.dataflash.initialize = function (callback) {
$(".dataflash-saving").addClass("done");
}
function flash_save_begin() {
var
maxBytes = DATAFLASH.usedSize;
if (GUI.connected_to) {
prepare_file(function(fileWriter) {
var
nextAddress = 0;
show_saving_dialog();
function onChunkRead(chunkAddress, chunkDataView) {
if (chunkDataView != null) {
// Did we receive any data?
if (chunkDataView.byteLength > 0) {
nextAddress += chunkDataView.byteLength;
$(".dataflash-saving progress").attr("value", nextAddress / maxBytes * 100);
function flash_update_summary(onDone) {
MSP.send_message(MSP_codes.MSP_DATAFLASH_SUMMARY, false, false, function() {
update_html();
if (onDone) {
onDone();
}
});
}
var
blob = new Blob([chunkDataView]);
fileWriter.onwriteend = function(e) {
if (saveCancelled || nextAddress >= maxBytes) {
if (saveCancelled) {
dismiss_saving_dialog();
} else {
mark_saving_dialog_done();
}
} else {
MSP.dataflashRead(nextAddress, onChunkRead);
}
};
fileWriter.write(blob);
} else {
// A zero-byte block indicates end-of-file, so we're done
mark_saving_dialog_done();
}
} else {
// There was an error with the received block (address didn't match the one we asked for), retry
MSP.dataflashRead(nextAddress, onChunkRead);
}
}
function flash_save_begin() {
if (GUI.connected_to) {
// Begin by refreshing the occupied size in case it changed while the tab was open
flash_update_summary(function() {
var
maxBytes = DATAFLASH.usedSize;
// Fetch the initial block
MSP.dataflashRead(nextAddress, onChunkRead);
prepare_file(function(fileWriter) {
var
nextAddress = 0;
show_saving_dialog();
function onChunkRead(chunkAddress, chunkDataView) {
if (chunkDataView != null) {
// Did we receive any data?
if (chunkDataView.byteLength > 0) {
nextAddress += chunkDataView.byteLength;
$(".dataflash-saving progress").attr("value", nextAddress / maxBytes * 100);
var
blob = new Blob([chunkDataView]);
fileWriter.onwriteend = function(e) {
if (saveCancelled || nextAddress >= maxBytes) {
if (saveCancelled) {
dismiss_saving_dialog();
} else {
mark_saving_dialog_done();
}
} else {
MSP.dataflashRead(nextAddress, onChunkRead);
}
};
fileWriter.write(blob);
} else {
// A zero-byte block indicates end-of-file, so we're done
mark_saving_dialog_done();
}
} else {
// There was an error with the received block (address didn't match the one we asked for), retry
MSP.dataflashRead(nextAddress, onChunkRead);
}
}
// Fetch the initial block
MSP.dataflashRead(nextAddress, onChunkRead);
});
});
}
}
@ -246,8 +259,7 @@ TABS.dataflash.initialize = function (callback) {
}
function poll_for_erase_completion() {
MSP.send_message(MSP_codes.MSP_DATAFLASH_SUMMARY, false, false, function() {
update_html();
flash_update_summary(function() {
if (!eraseCancelled) {
if (DATAFLASH.ready) {
$(".dataflash-confirm-erase")[0].close();

View File

@ -39,7 +39,7 @@ TABS.firmware_flasher.initialize = function (callback) {
var showDevReleases = ($('input.show_development_releases').is(':checked'));
releases_e.append($("<option value='0'>{0}</option>".format(chrome.i18n.getMessage('firmwareFlasherOptionLabelSelectFirmware'))));
var releaseDescritpors = [];
var releaseDescriptors = [];
TABS.firmware_flasher.releases.forEach(function(release){
release.assets.forEach(function(asset){
var targetFromFilenameExpression = /.*_(.*)\.(.*)/;
@ -81,11 +81,11 @@ TABS.firmware_flasher.initialize = function (callback) {
"status" : release.prerelease ? "release-candidate" : "stable"
};
releaseDescritpors.push(descriptor);
releaseDescriptors.push(descriptor);
});
});
releaseDescritpors.sort(function(o1,o2){
releaseDescriptors.sort(function(o1,o2){
// compare versions descending
var cmpVal = semver(o2.version).compare(semver(o1.version));
if (cmpVal == 0){
@ -96,7 +96,7 @@ TABS.firmware_flasher.initialize = function (callback) {
});
var optionIndex = 1;
releaseDescritpors.forEach(function(descriptor){
releaseDescriptors.forEach(function(descriptor){
var select_e =
$("<option value='{0}'>{1} {2} {3} ({4})</option>".format(
optionIndex++,

View File

@ -272,7 +272,7 @@ TABS.motors.initialize = function (callback) {
');
servos_wrapper.append('\
<div class="m-block servo-' + i + '">\
<div class="m-block servo-' + (7 - i) + '">\
<div class="meter-bar">\
<div class="label"></div>\
<div class="indicator">\

View File

@ -71,13 +71,13 @@
border: 1px dashed silver;
margin-bottom: 8px;
}
.require-support {
.tab-ports .require-support {
display:none;
}
.tab-ports.supported .require-support {
display:block;
}
.require-upgrade {
.tab-ports .require-upgrade {
display:block;
}
.tab-ports.supported .require-upgrade {

View File

@ -18,6 +18,11 @@
<tbody>
</tbody>
</table>
<div class="help">
<p i18n="portsMSPHelp"></p>
</div>
<div class="clear-both"></div>
<div class="buttons">
<a class="save" href="#" i18n="portsButtonSave"></a>

27
tabs/ports.js Executable file → Normal file
View File

@ -239,9 +239,12 @@ TABS.ports.initialize = function (callback, scrollPosition) {
blackbox_baudrate: $(portConfiguration_e).find('.blackbox_baudrate').val(),
identifier: oldSerialPort.identifier
};
console.log(serialPort);
SERIAL_CONFIG.ports.push(serialPort);
});
MSP.send_message(MSP_codes.MSP_SET_CF_SERIAL_CONFIG, MSP.crunch(MSP_codes.MSP_SET_CF_SERIAL_CONFIG), false, save_to_eeprom);
function save_to_eeprom() {
@ -259,22 +262,14 @@ TABS.ports.initialize = function (callback, scrollPosition) {
function on_reboot_success_handler() {
GUI.log(chrome.i18n.getMessage('deviceRebooting'));
if (BOARD.find_board_definition(CONFIG.boardIdentifier).vcp) { // VCP-based flight controls may crash old drivers, we catch and reconnect
$('a.connect').click();
GUI.timeout_add('start_connection',function start_connection() {
$('a.connect').click();
},2000);
} else {
GUI.timeout_add('waiting_for_bootup', function waiting_for_bootup() {
MSP.send_message(MSP_codes.MSP_IDENT, false, false, function () {
GUI.log(chrome.i18n.getMessage('deviceReady'));
TABS.ports.initialize(false, $('#content').scrollTop());
});
}, 1500); // seems to be just the right amount of delay to prevent data request timeouts
}
var rebootTimeoutDelay = 1500; // seems to be just the right amount of delay to prevent data request timeouts
GUI.timeout_add('waiting_for_bootup', function waiting_for_bootup() {
MSP.send_message(MSP_codes.MSP_IDENT, false, false, function () {
GUI.log(chrome.i18n.getMessage('deviceReady'));
TABS.ports.initialize(false, $('#content').scrollTop());
});
}, rebootTimeoutDelay);
}
}
};

View File

@ -3,6 +3,12 @@
.tab-receiver input[type="number"]::-webkit-inner-spin-button {
border: 0;
}
.tab-receiver .help {
padding: 10px;
background-color: #ffcb18;
margin-bottom: 10px;
}
.tab-receiver .bars {
float: left;
width: 45%;
@ -218,7 +224,7 @@
margin: 0 10px 10px 0;
width: 220px;
height: 58px;
height: 120px;
border: 1px solid silver;
}
@ -226,7 +232,7 @@
margin: 0 10px 0 0;
width: 220px;
height: 58px;
height: 120px;
border: 1px solid silver;
}
@ -293,6 +299,7 @@
position: absolute;
bottom: 10px;
}
.tab-receiver .sticks,
.tab-receiver .update,
.tab-receiver .refresh {
display: block;
@ -311,6 +318,7 @@
border: 1px solid silver;
background-color: #ececec;
}
.tab-receiver .sticks,
.tab-receiver .refresh {
margin-right: 10px;
}
@ -334,4 +342,4 @@
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
}

View File

@ -1,5 +1,9 @@
<div id="content-watermark"></div>
<div class="tab-receiver">
<div class="help">
<p i18n="receiverHelp"></p>
</div>
<div class="bars">
</div>
<div class="tunings">
@ -53,10 +57,10 @@
</div>
<div class="curves">
<div class="throttle_curve">
<canvas width="220" height="58"></canvas>
<canvas width="220" height="120"></canvas>
</div>
<div class="pitch_roll_curve">
<canvas width="220" height="58"></canvas>
<canvas width="220" height="120"></canvas>
</div>
</div>
<div class="clear-both"></div>
@ -82,5 +86,6 @@
<div class="buttons">
<a class="update" href="#" i18n="receiverButtonSave"></a>
<a class="refresh" href="#" i18n="receiverButtonRefresh"></a>
<a class="sticks" href="#" i18n="receiverButtonSticks"></a>
</div>
</div>

View File

@ -1,6 +1,9 @@
'use strict';
TABS.receiver = {};
TABS.receiver = {
rateChartHeight: 120
};
TABS.receiver.initialize = function (callback) {
var self = this;
@ -18,7 +21,12 @@ TABS.receiver.initialize = function (callback) {
}
function get_rc_map() {
MSP.send_message(MSP_codes.MSP_RX_MAP, false, false, load_html);
MSP.send_message(MSP_codes.MSP_RX_MAP, false, false, load_config);
}
// Fetch features so we can check if RX_MSP is enabled:
function load_config() {
MSP.send_message(MSP_codes.MSP_BF_CONFIG, false, false, load_html);
}
function load_html() {
@ -38,11 +46,11 @@ TABS.receiver.initialize = function (callback) {
$('.tunings .rate input[name="rate"]').val(RC_tuning.RC_RATE.toFixed(2));
$('.tunings .rate input[name="expo"]').val(RC_tuning.RC_EXPO.toFixed(2));
$('.tunings .yaw_rate input[name="yaw_expo"]').val(RC_tuning.RC_YAW_EXPO.toFixed(2));
if (semver.lt(CONFIG.apiVersion, "1.10.0")) {
$('.tunings .yaw_rate input[name="yaw_expo"]').hide();
}
chrome.storage.local.get('rx_refresh_rate', function (result) {
if (result.rx_refresh_rate) {
$('select[name="rx_refresh_rate"]').val(result.rx_refresh_rate).change();
@ -52,7 +60,12 @@ TABS.receiver.initialize = function (callback) {
});
// generate bars
var bar_names = ['Roll', 'Pitch', 'Yaw', 'Throttle'],
var bar_names = [
chrome.i18n.getMessage('controlAxisRoll'),
chrome.i18n.getMessage('controlAxisPitch'),
chrome.i18n.getMessage('controlAxisYaw'),
chrome.i18n.getMessage('controlAxisThrottle')
],
bar_container = $('.tab-receiver .bars'),
aux_index = 1;
@ -61,7 +74,7 @@ TABS.receiver.initialize = function (callback) {
if (i < bar_names.length) {
name = bar_names[i];
} else {
name = 'AUX ' + aux_index++;
name = chrome.i18n.getMessage("controlAxisAux" + (aux_index++));
}
bar_container.append('\
@ -176,6 +189,8 @@ TABS.receiver.initialize = function (callback) {
$('select[name="rssi_channel"]').val(MISC.rssi_channel);
var rateHeight = TABS.receiver.rateChartHeight;
// UI Hooks
// curves
$('.tunings .throttle input').on('input change', function () {
@ -201,14 +216,14 @@ TABS.receiver.initialize = function (callback) {
var midx = 220 * mid,
midxl = midx * 0.5,
midxr = (((220 - midx) * 0.5) + midx),
midy = 58 - (midx * (58 / 220)),
midyl = 58 - ((58 - midy) * 0.5 *(expo + 1)),
midy = rateHeight - (midx * (rateHeight / 220)),
midyl = rateHeight - ((rateHeight - midy) * 0.5 *(expo + 1)),
midyr = (midy / 2) * (expo + 1);
// draw
context.clearRect(0, 0, 220, 58);
context.clearRect(0, 0, 220, rateHeight);
context.beginPath();
context.moveTo(0, 58);
context.moveTo(0, rateHeight);
context.quadraticCurveTo(midxl, midyl, midx, midy);
context.moveTo(midx, midy);
context.quadraticCurveTo(midxr, midyr, 220, 0);
@ -237,13 +252,13 @@ TABS.receiver.initialize = function (callback) {
}
// math magic by englishman
var ratey = 58 * rate;
var ratey = rateHeight * rate;
// draw
context.clearRect(0, 0, 220, 58);
context.clearRect(0, 0, 220, rateHeight);
context.beginPath();
context.moveTo(0, 58);
context.quadraticCurveTo(110, 58 - ((ratey / 2) * (1 - expo)), 220, 58 - ratey);
context.moveTo(0, rateHeight);
context.quadraticCurveTo(110, rateHeight - ((ratey / 2) * (1 - expo)), 220, rateHeight - ratey);
context.lineWidth = 2;
context.stroke();
}, 0);
@ -302,6 +317,35 @@ TABS.receiver.initialize = function (callback) {
MSP.send_message(MSP_codes.MSP_SET_RC_TUNING, MSP.crunch(MSP_codes.MSP_SET_RC_TUNING), false, save_rc_map);
});
$("a.sticks").click(function() {
var
windowWidth = 370,
windowHeight = 510;
chrome.app.window.create("/tabs/receiver_msp.html", {
id: "receiver_msp",
innerBounds: {
minWidth: windowWidth, minHeight: windowHeight,
width: windowWidth, height: windowHeight,
maxWidth: windowWidth, maxHeight: windowHeight
},
alwaysOnTop: true
}, function(createdWindow) {
// Give the window a callback it can use to send the channels (otherwise it can't see those objects)
createdWindow.contentWindow.setRawRx = function(channels) {
if (CONFIGURATOR.connectionValid && GUI.active_tab != 'cli') {
MSP.setRawRx(channels);
return true;
} else {
return false;
}
}
});
});
// Only show the MSP control sticks if the MSP Rx feature is enabled
$("a.sticks").toggle(bit_check(BF_CONFIG.features, 14 /* RX_MSP */));
$('select[name="rx_refresh_rate"]').change(function () {
var plot_update_rate = parseInt($(this).val(), 10);

109
tabs/receiver_msp.css Normal file
View File

@ -0,0 +1,109 @@
body {
font-family: 'Segoe UI', Tahoma, sans-serif;
font-size: 12px;
color: #303030;
margin: 10px;
}
.control-gimbals {
/* A generous padding around the window edges ensures that we continue to receive mousemove events (since
* cursor stays in the window for longer)
*/
padding:25px;
padding-bottom:0;
text-align:center;
}
.control-gimbal {
position:relative;
width:120px;
height:120px;
background-color:#eee;
margin-left:1em;
margin-right:1em;
margin-bottom:2em;
display:inline-block;
border-radius:5px;
cursor:pointer;
}
.crosshair {
display:block;
position:absolute;
background-color:#ddd;
}
.crosshair-vert {
width:1px;
height:100%;
left:50%;
}
.crosshair-horz {
height:1px;
width:100%;
top:50%;
}
.gimbal-label {
display:block;
position:absolute;
text-align:center;
}
.gimbal-label-horz {
top:calc(100% + 0.5em);
width:100%;
}
.gimbal-label-vert {
transform:rotate(-90deg);
/*transform-origin:0% 100%;*/
top:calc(50% - 0.5em);
width:100%;
left:calc(-50% - 1em);
}
.control-stick {
background-color:rgba(255,50,50,1.0);
width:20px;
height:20px;
margin-left:-10px;
margin-top:-10px;
display:block;
border-radius:100%;
position:absolute;
cursor:pointer;
}
.control-slider {
margin:20px;
}
.tooltip {
position: absolute;
left: calc(100% + 24px);
top: 0;
}
.control-slider .slider {
margin-left:50px;
margin-right:50px;
}
.slider-label {
position:absolute;
text-align:right;
width:40px;
left:-65px;
}
.button-enable {
padding:0.5em;
font-size:110%;
margin-left:auto;
margin-right:auto;
display:block;
}

71
tabs/receiver_msp.html Normal file
View File

@ -0,0 +1,71 @@
<html>
<head>
<script type="text/javascript" src="/js/libraries/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="/js/libraries/jquery-ui-1.11.4.min.js"></script>
<script type="text/javascript" src="/js/libraries/jquery.nouislider.all.min.js"></script>
<script type="text/javascript" src="receiver_msp.js"></script>
<link type="text/css" rel="stylesheet" href="/js/libraries/jquery.nouislider.min.css">
<link type="text/css" rel="stylesheet" href="/js/libraries/jquery.nouislider.pips.min.css">
<link type="text/css" rel="stylesheet" href="receiver_msp.css" media="all" />
</head>
<body>
<div class="control-gimbals">
<div class="control-gimbal left">
<span class="gimbal-label gimbal-label-vert"></span>
<span class="gimbal-label gimbal-label-horz"></span>
<span class="crosshair crosshair-vert"></span>
<span class="crosshair crosshair-horz"></span>
<div class="control-stick">
</div>
</div>
<div class="control-gimbal right">
<span class="gimbal-label gimbal-label-vert"></span>
<span class="gimbal-label gimbal-label-horz"></span>
<span class="crosshair crosshair-vert"></span>
<span class="crosshair crosshair-horz"></span>
<div class="control-stick">
</div>
</div>
</div>
<div class="control-sliders">
<div class="control-slider">
<div class="slider">
<span class="slider-label"></span>
</div>
</div>
<div class="control-slider">
<div class="slider">
<span class="slider-label"></span>
</div>
</div>
<div class="control-slider">
<div class="slider">
<span class="slider-label"></span>
</div>
</div>
<div class="control-slider">
<div class="slider">
<span class="slider-label"></span>
</div>
</div>
</div>
<div class="warning">
<p>
These sticks allow Cleanflight to be armed and tested without a transmitter or receiver being
present. However, <strong>this feature is not intended for flight and propellers must not be attached.</strong>
</p>
<p>
This feature does not guarantee reliable control of your craft. <strong>Serious injury is likely to
result if propellers are left on.</strong>
</p>
<button class="button-enable" type="button">Enable controls</button>
</div>
</body>
</html>

185
tabs/receiver_msp.js Normal file
View File

@ -0,0 +1,185 @@
"use strict";
var
CHANNEL_MIN_VALUE = 1000,
CHANNEL_MID_VALUE = 1500,
CHANNEL_MAX_VALUE = 2000,
// What's the index of each channel in the MSP channel list?
channelMSPIndexes = {
roll: 0,
pitch: 1,
yaw: 2,
throttle: 3,
aux1: 4,
aux2: 5,
aux3: 6,
aux4: 7,
},
// Set reasonable initial stick positions (Mode 2)
stickValues = {
throttle: CHANNEL_MIN_VALUE,
pitch: CHANNEL_MID_VALUE,
roll: CHANNEL_MID_VALUE,
yaw: CHANNEL_MID_VALUE,
aux1: CHANNEL_MIN_VALUE,
aux2: CHANNEL_MIN_VALUE,
aux3: CHANNEL_MIN_VALUE,
aux4: CHANNEL_MIN_VALUE
},
// First the vertical axis, then the horizontal:
gimbals = [
["throttle", "yaw"],
["pitch", "roll"],
],
gimbalElems,
sliderElems,
enableTX = false;
function transmitChannels() {
var
channelValues = [0, 0, 0, 0, 0, 0, 0, 0];
if (!enableTX) {
return;
}
for (var stickName in stickValues) {
channelValues[channelMSPIndexes[stickName]] = stickValues[stickName];
}
// Callback given to us by the window creator so we can have it send data over MSP for us:
if (!window.setRawRx(channelValues)) {
// MSP connection has gone away
chrome.app.window.current().close();
}
}
function stickPortionToChannelValue(portion) {
portion = Math.min(Math.max(portion, 0.0), 1.0);
return Math.round(portion * (CHANNEL_MAX_VALUE - CHANNEL_MIN_VALUE) + CHANNEL_MIN_VALUE);
}
function channelValueToStickPortion(channel) {
return (channel - CHANNEL_MIN_VALUE) / (CHANNEL_MAX_VALUE - CHANNEL_MIN_VALUE);
}
function updateControlPositions() {
for (var stickName in stickValues) {
var
stickValue = stickValues[stickName];
// Look for the gimbal which corresponds to this stick name
for (var gimbalIndex in gimbals) {
var
gimbal = gimbals[gimbalIndex],
gimbalElem = gimbalElems.get(gimbalIndex),
gimbalSize = $(gimbalElem).width(),
stickElem = $(".control-stick", gimbalElem);
if (gimbal[0] == stickName) {
stickElem.css('top', (1.0 - channelValueToStickPortion(stickValue)) * gimbalSize + "px");
break;
} else if (gimbal[1] == stickName) {
stickElem.css('left', channelValueToStickPortion(stickValue) * gimbalSize + "px");
break;
}
}
}
}
function handleGimbalMouseDrag(e) {
var
gimbal = $(gimbalElems.get(e.data.gimbalIndex)),
gimbalOffset = gimbal.offset(),
gimbalSize = gimbal.width();
stickValues[gimbals[e.data.gimbalIndex][0]] = stickPortionToChannelValue(1.0 - (e.pageY - gimbalOffset.top) / gimbalSize);
stickValues[gimbals[e.data.gimbalIndex][1]] = stickPortionToChannelValue((e.pageX - gimbalOffset.left) / gimbalSize);
updateControlPositions();
}
function localizeAxisNames() {
for (var gimbalIndex in gimbals) {
var
gimbal = gimbalElems.get(gimbalIndex);
$(".gimbal-label-vert", gimbal).text(chrome.i18n.getMessage("controlAxis" + gimbals[gimbalIndex][0]));
$(".gimbal-label-horz", gimbal).text(chrome.i18n.getMessage("controlAxis" + gimbals[gimbalIndex][1]));
}
for (var sliderIndex = 0; sliderIndex < 4; sliderIndex++) {
$(".slider-label", sliderElems.get(sliderIndex)).text(chrome.i18n.getMessage("controlAxisAux" + (sliderIndex + 1)));
}
}
$(document).ready(function() {
$(".button-enable").click(function() {
var
shrinkHeight = $(".warning").height();
$(".warning").slideUp("short", function() {
chrome.app.window.current().innerBounds.minHeight -= shrinkHeight;
chrome.app.window.current().innerBounds.height -= shrinkHeight;
chrome.app.window.current().innerBounds.maxHeight -= shrinkHeight;
});
enableTX = true;
});
gimbalElems = $(".control-gimbal");
sliderElems = $(".control-slider");
gimbalElems.each(function(gimbalIndex) {
$(this).on('mousedown', {gimbalIndex: gimbalIndex}, function(e) {
if (e.which == 1) { // Only move sticks on left mouse button
handleGimbalMouseDrag(e);
$(window).on('mousemove', {gimbalIndex: gimbalIndex}, handleGimbalMouseDrag);
}
});
});
$(".slider", sliderElems).each(function(sliderIndex) {
var
initialValue = stickValues["aux" + (sliderIndex + 1)];
$(this)
.noUiSlider({
start: initialValue,
range: {
min: CHANNEL_MIN_VALUE,
max: CHANNEL_MAX_VALUE
}
}).on('slide change set', function(e, value) {
value = Math.round(parseFloat(value));
stickValues["aux" + (sliderIndex + 1)] = value;
$(".tooltip", this).text(value);
});
$(this).append('<div class="tooltip"></div>');
$(".tooltip", this).text(initialValue);
});
/*
* Mouseup handler needs to be bound to the window in order to receive mouseup if mouse leaves window.
*/
$(window).mouseup(function(e) {
$(this).off('mousemove', handleGimbalMouseDrag);
});
localizeAxisNames();
updateControlPositions();
setInterval(transmitChannels, 50);
});

View File

@ -15,6 +15,7 @@ TABS.sensors.initialize = function (callback) {
SENSOR_DATA.gyroscope[i] = 0;
SENSOR_DATA.magnetometer[i] = 0;
SENSOR_DATA.sonar = 0;
SENSOR_DATA.altitude = 0;
SENSOR_DATA.debug[i] = 0;
}
}

View File

@ -3,10 +3,6 @@
.tab-servos input[type="number"]::-webkit-inner-spin-button {
border: 0;
}
.tab-servos .supported_wrapper,
.tab-servos .direction_wrapper {
display: none;
}
.tab-servos .title {
margin-top: 10px;
@ -129,4 +125,17 @@
}
.tab-servos .update:hover {
background-color: #dedcdc;
}
}
.tab-servos .require-support {
display:none;
}
.tab-servos.supported .require-support {
display:block;
}
.tab-servos .require-upgrade {
display:block;
}
.tab-servos.supported .require-upgrade {
display:none;
}

View File

@ -1,6 +1,5 @@
<div class="tab-servos">
<span i18n="servosModel"></span> <strong class="model"></strong>
<div class="supported_wrapper">
<div class="require-support">
<div class="title" i18n="servosChangeDirection"></div>
<table class="fields">
<tr class="main">
@ -8,21 +7,14 @@
<th style="width: 120px" i18n="servosMid"></th>
<th style="width: 120px" i18n="servosMin"></th>
<th style="width: 120px" i18n="servosMax"></th>
<th style="width: 120px" i18n="servosAngleAtMin"></th>
<th style="width: 120px" i18n="servosAngleAtMax"></th>
<th style="width: 40px">CH1</th>
<th style="width: 40px">CH2</th>
<th style="width: 40px">CH3</th>
<th style="width: 40px">CH4</th>
</tr>
</table>
<div class="direction_wrapper">
<div class="title" style="width: 258px" i18n="servosGyroAccelDirection"></div>
<table class="directions" style="width: 260px">
<tr class="main">
<th style="width: 200px" i18n="servosName"></th>
<th i18n="servosDirection"></th>
</tr>
</table>
</div>
<div class="live">
<span i18n="servosLiveMode"></span> <input type="checkbox" />
</div>
@ -30,4 +22,7 @@
<a class="update" href="#" i18n="servosButtonSave"></a>
</div>
</div>
<div class="note require-upgrade" i18n="servosFirmwareUpgradeRequired">
</div>
</div>

View File

@ -1,9 +1,3 @@
/* Please don't take code in this file very seriously !!!
I was "kinda" forced to write this implementation "this way" because the Servo code implementation
from multiwii is so horrible, obstructive and non dynamic, not to mention it doesn't make any sense
that there was just no other way around this then hardcoding/implementing each model separately.
*/
'use strict';
TABS.servos = {};
@ -15,15 +9,25 @@ TABS.servos.initialize = function (callback) {
googleAnalytics.sendAppView('Servos');
}
function get_servo_conf_data() {
MSP.send_message(MSP_codes.MSP_SERVO_CONF, false, false, get_channel_forwarding_data);
function get_servo_configurations() {
MSP.send_message(MSP_codes.MSP_SERVO_CONFIGURATIONS, false, false, get_servo_mix_rules);
}
function get_channel_forwarding_data() {
MSP.send_message(MSP_codes.MSP_CHANNEL_FORWARDING, false, false, get_rc_data);
function get_servo_mix_rules() {
MSP.send_message(MSP_codes.MSP_SERVO_MIX_RULES, false, false, get_channel_forwarding);
}
function get_rc_data() {
function get_channel_forwarding() {
var nextFunction = get_rc_data;
if (semver.lt(CONFIG.apiVersion, "1.12.0")) {
MSP.send_message(MSP_codes.MSP_CHANNEL_FORWARDING, false, false, nextFunction);
} else {
nextFunction();
}
}
function get_rc_data() {
MSP.send_message(MSP_codes.MSP_RC, false, false, get_boxnames_data);
}
@ -35,10 +39,18 @@ TABS.servos.initialize = function (callback) {
$('#content').load("./tabs/servos.html", process_html);
}
MSP.send_message(MSP_codes.MSP_IDENT, false, false, get_servo_conf_data);
function process_html() {
MSP.send_message(MSP_codes.MSP_IDENT, false, false, get_servo_configurations);
function update_ui() {
if (semver.lt(CONFIG.apiVersion, "1.12.0")) {
$(".tab-servos").removeClass("supported");
return;
}
$(".tab-servos").addClass("supported");
var servoCheckbox = '';
var servoHeader = '';
for (var i = 0; i < RC.active_channels-4; i++) {
@ -46,94 +58,52 @@ TABS.servos.initialize = function (callback) {
<th >A' + (i+1) + '</th>\
';
}
servoHeader = servoHeader + '<th style="width: 200px" i18n="servosDirection"></th>';
servoHeader = servoHeader + '<th style="width: 200px" i18n="servosDirectionAndRate"></th>';
for (var i = 0; i < RC.active_channels; i++) {
servoCheckbox = servoCheckbox + '\
<td class="channel"><input type="checkbox"/></td>\
';
}
$('div.tab-servos table.fields tr.main').append(servoHeader);
function process_directions(name, obj, bitpos) {
$('div.direction_wrapper').show();
var val;
$('div.tab-servos table.directions').append('\
<tr>\
<td class="name" style="text-align: center">' + name + '</td>\
<td class="direction" style="text-align: right">\
<select name="direction">\
<option value="0">' + chrome.i18n.getMessage('servosNormal') + '</option>\
<option value="1">' + chrome.i18n.getMessage('servosReverse') + '</option>\
</select>\
</td>\
</tr>\
');
if (bit_check(SERVO_CONFIG[obj].rate, bitpos)) val = 1;
else val = 0;
$('div.tab-servos table.directions tr:last select').val(val);
$('div.tab-servos table.directions tr:last select').data('info', {'obj': obj, 'bitpos': bitpos});
}
function process_servos(name, alternate, obj, directions) {
function process_servos(name, alternate, obj) {
$('div.supported_wrapper').show();
$('div.tab-servos table.fields').append('\
<tr> \
<td style="text-align: center">' + name + '</td>\
<td class="middle"><input type="number" min="1000" max="2000" value="' + SERVO_CONFIG[obj].middle + '" /></td>\
<td class="min"><input type="number" min="1000" max="2000" value="' + SERVO_CONFIG[obj].min +'" /></td>\
<td class="max"><input type="number" min="1000" max="2000" value="' + SERVO_CONFIG[obj].max +'" /></td>\
<td class="middle"><input type="number" min="500" max="2500" value="' + SERVO_CONFIG[obj].middle + '" /></td>\
<td class="min"><input type="number" min="500" max="2500" value="' + SERVO_CONFIG[obj].min +'" /></td>\
<td class="max"><input type="number" min="500" max="2500" value="' + SERVO_CONFIG[obj].max +'" /></td>\
<td class="angleAtMin"><input type="number" min="-90" max="0" value="' + SERVO_CONFIG[obj].angleAtMin +'" /></td>\
<td class="angleAtMax"><input type="number" min="0" max="90" value="' + SERVO_CONFIG[obj].angleAtMax +'" /></td>\
' + servoCheckbox + '\
<td class="direction">\
<input class="first" type="checkbox"/><span class="name">' + name + '</span>\
<input class="second" type="checkbox"/><span class="alternate">' + alternate + '</span>\
</td>\
</tr> \
');
// translate to user-selected language
localize();
$('div.tab-servos table.fields tr:last td.channel input').eq(SERVO_CONFIG[obj].indexOfChannelToForward).prop('checked', true);
if (directions == true) {
$('div.tab-servos table.fields tr:last td.direction input:first').prop('checked', bit_check(SERVO_CONFIG[obj].rate, 0));
$('div.tab-servos table.fields tr:last td.direction input:last').prop('checked', bit_check(SERVO_CONFIG[obj].rate, 1));
} else if (directions == 2) {
// removing checkboxes
$('div.tab-servos table.fields tr:last td.direction').html('');
// adding select box and generating options
$('div.tab-servos table.fields tr:last td.direction').append('\
<select class="rate" name="rate"></select>\
');
var select = $('div.tab-servos table.fields tr:last td.direction select');
for (var i = 100; i > -101; i--) {
select.append('<option value="' + i + '">Rate: ' + i + '%</option>');
}
// select current rate
select.val(SERVO_CONFIG[obj].rate);
} else {
// removing checkboxes
$('div.tab-servos table.fields tr:last td.direction').html('');
if (SERVO_CONFIG[obj].indexOfChannelToForward >= 0) {
$('div.tab-servos table.fields tr:last td.channel input').eq(SERVO_CONFIG[obj].indexOfChannelToForward).prop('checked', true);
}
// adding select box and generating options
$('div.tab-servos table.fields tr:last td.direction').append('\
<select class="rate" name="rate"></select>\
');
var select = $('div.tab-servos table.fields tr:last td.direction select');
for (var i = 100; i > -101; i--) {
select.append('<option value="' + i + '">Rate: ' + i + '%</option>');
}
// select current rate
select.val(SERVO_CONFIG[obj].rate);
$('div.tab-servos table.fields tr:last').data('info', {'obj': obj});
// UI hooks
@ -146,18 +116,7 @@ TABS.servos.initialize = function (callback) {
});
}
function servos_update(save_to_eeprom) {
// update bitfields
$('div.tab-servos table.directions tr:not(".main")').each(function () {
var info = $('select', this).data('info');
var val = parseInt($('select', this).val());
// in this stage we need to know which bitfield and which bitposition needs to be flipped
if (val) SERVO_CONFIG[info.obj].rate = bit_set(SERVO_CONFIG[info.obj].rate, info.bitpos);
else SERVO_CONFIG[info.obj].rate = bit_clear(SERVO_CONFIG[info.obj].rate, info.bitpos);
});
// update the rest
function servos_update(save_configuration_to_eeprom) {
$('div.tab-servos table.fields tr:not(".main")').each(function () {
var info = $(this).data('info');
@ -174,122 +133,37 @@ TABS.servos.initialize = function (callback) {
SERVO_CONFIG[info.obj].middle = parseInt($('.middle input', this).val());
SERVO_CONFIG[info.obj].min = parseInt($('.min input', this).val());
SERVO_CONFIG[info.obj].max = parseInt($('.max input', this).val());
SERVO_CONFIG[info.obj].angleAtMin = parseInt($('.angleAtMin input', this).val());
SERVO_CONFIG[info.obj].angleAtMax = parseInt($('.angleAtMax input', this).val());
// update rate if direction fields exist
if ($('.direction input', this).length) {
if ($('.direction input:first', this).is(':checked')) SERVO_CONFIG[info.obj].rate = bit_set(SERVO_CONFIG[info.obj].rate, 0);
else SERVO_CONFIG[info.obj].rate = bit_clear(SERVO_CONFIG[info.obj].rate, 0);
if ($('.direction input:last', this).is(':checked')) SERVO_CONFIG[info.obj].rate = bit_set(SERVO_CONFIG[info.obj].rate, 1);
else SERVO_CONFIG[info.obj].rate = bit_clear(SERVO_CONFIG[info.obj].rate, 1);
} else if ($('.direction select', this).length) {
var val = parseInt($('.direction select', this).val());
SERVO_CONFIG[info.obj].rate = val;
}
var val = parseInt($('.direction select', this).val());
SERVO_CONFIG[info.obj].rate = val;
});
MSP.send_message(MSP_codes.MSP_SET_CHANNEL_FORWARDING, MSP.crunch(MSP_codes.MSP_SET_CHANNEL_FORWARDING), false, function () {
MSP.send_message(MSP_codes.MSP_SET_SERVO_CONF, MSP.crunch(MSP_codes.MSP_SET_SERVO_CONF), false, function () {
if (save_to_eeprom) {
// Save changes to EEPROM
MSP.send_message(MSP_codes.MSP_EEPROM_WRITE, false, false, function () {
GUI.log(chrome.i18n.getMessage('servosEepromSave'));
});
}
});
});
//
// send data to FC
//
MSP.sendServoConfigurations(send_servo_mixer_rules);
function send_servo_mixer_rules() {
MSP.sendServoConfigurations(save_to_eeprom);
}
function save_to_eeprom() {
if (save_configuration_to_eeprom) {
MSP.send_message(MSP_codes.MSP_EEPROM_WRITE, false, false, function () {
GUI.log(chrome.i18n.getMessage('servosEepromSave'));
});
}
}
}
// drop previous table
$('div.tab-servos table.fields tr:not(:first)').remove();
var model = $('div.tab-servos strong.model');
var supported_models = [1, 4, 5, 8, 14, 20, 21];
switch (CONFIG.multiType) {
case 1: // TRI
// looking ok so far
model.text('TRI');
process_directions('YAW', 5, 0);
process_servos('Yaw Servo', '', 5, false);
break;
case 4: // BI
// looking ok so far
model.text('BI');
process_directions('L YAW', 4, 1);
process_directions('R YAW', 5, 1);
process_directions('L NICK', 4, 0);
process_directions('R NICK', 5, 0);
process_servos('Left Servo', '', 4, false);
process_servos('Right Servo', '', 5, false);
break;
case 5: // Gimbal
// needs to be verified
model.text('Gimbal');
// rate
process_servos('Pitch Servo', '', 0, 2);
process_servos('Roll Servo', '', 1, 2);
break;
case 8: // Flying Wing
// looking ok so far
model.text('Flying Wing');
process_directions('L ROLL', 3, 1);
process_directions('R ROLL', 4, 1);
process_directions('L NICK', 3, 0);
process_directions('R NICK', 4, 0);
process_servos('Left Wing', '', 3, false);
process_servos('Right Wing', '', 4, false);
break;
case 14: // Airplane
model.text('Airplane');
// rate
process_servos('Wing 1', '', 3, 2);
process_servos('Wing 2', '', 4, 2);
process_servos('Rudd', '', 5, 2);
process_servos('Elev', '', 6, 2);
break;
case 20: // Dualcopter
// looking ok so far
model.text('Dualcopter');
process_directions('PITCH', 4, 0);
process_directions('ROLL', 5, 0);
process_servos('Roll', '', 5, false);
process_servos('Nick', '', 4, false);
break;
case 21: // Singlecopter
// looking ok so far
model.text('Singlecopter');
process_servos('Right', 'R YAW', 3, true);
process_servos('Left', 'L YAW', 4, true);
process_servos('Front', 'F YAW', 5, true);
process_servos('Rear', 'YAW', 6, true);
break;
default:
model.text(chrome.i18n.getMessage('servosModelNoSupport'));
// implementation of feature servo_tilt
if (AUX_CONFIG.indexOf('CAMSTAB') > -1 || AUX_CONFIG.indexOf('CAMTRIG') > -1) {
// Gimbal on
// needs to be verified
model.text('Gimbal / Tilt Servos');
// rate
process_servos('Pitch Servo', '', 0, 2);
process_servos('Roll Servo', '', 1, 2);
}
for (var servoIndex = 0; servoIndex < 8; servoIndex++) {
process_servos('Servo ' + servoIndex, '', servoIndex, false);
}
// UI hooks for dynamically generated elements
@ -299,14 +173,20 @@ TABS.servos.initialize = function (callback) {
GUI.timeout_add('servos_update', servos_update, 10);
}
});
$('a.update').click(function () {
// standard check for supported_models + custom implementation for feature servo_tilt
if (supported_models.indexOf(CONFIG.multiType) != -1 || AUX_CONFIG.indexOf('CAMSTAB') > -1 || AUX_CONFIG.indexOf('CAMTRIG') > -1) {
servos_update(true);
}
servos_update(true);
});
}
function process_html() {
update_ui();
// translate to user-selected language
localize();
// status data pulled via separate timer with static speed
GUI.interval_add('status_pull', function () {
MSP.send_message(MSP_codes.MSP_STATUS);
@ -318,4 +198,4 @@ TABS.servos.initialize = function (callback) {
TABS.servos.cleanup = function (callback) {
if (callback) callback();
};
};