diff options
-rwxr-xr-x | _locales/en/messages.json | 115 | ||||
-rw-r--r-- | images/icons/cf_icon_transponder_grey.svg | 27 | ||||
-rw-r--r-- | images/icons/cf_icon_transponder_white.svg | 27 | ||||
-rw-r--r-- | js/fc.js | 6 | ||||
-rw-r--r-- | js/gui.js | 11 | ||||
-rw-r--r-- | js/msp.js | 20 | ||||
-rw-r--r-- | main.css | 13 | ||||
-rwxr-xr-x | main.html | 5 | ||||
-rw-r--r-- | main.js | 3 | ||||
-rw-r--r-- | tabs/configuration.js | 68 | ||||
-rw-r--r-- | tabs/transponder.css | 75 | ||||
-rw-r--r-- | tabs/transponder.html | 52 | ||||
-rw-r--r-- | tabs/transponder.js | 105 |
13 files changed, 490 insertions, 37 deletions
diff --git a/_locales/en/messages.json b/_locales/en/messages.json index d0564a6f..9e90bd36 100755 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -87,6 +87,12 @@ "tabServos": { "message": "Servos" }, + "tabFailsafe": { + "message": "Failsafe" + }, + "tabTransponder": { + "message": "Race Transponder" + }, "tabGPS": { "message": "GPS" }, @@ -433,6 +439,88 @@ "message": "EEPROM <span style=\"color: #57a929\">saved</span>" }, + "featureRX_PPM": { + "message": "PPM RX input" + }, + "featureVBAT": { + "message": "Battery voltage monitoring" + }, + "featureINFLIGHT_ACC_CAL": { + "message": "In-flight level calibration" + }, + "featureRX_SERIAL": { + "message": "Serial-based receiver (SPEKSAT, SBUS, SUMD)" + }, + "featureMOTOR_STOP": { + "message": "Don't spin the motors when armed" + }, + "featureSERVO_TILT": { + "message": "Servo gimbal" + }, + "featureSOFTSERIAL": { + "message": "Enable CPU based serial ports" + }, + "featureSOFTSERIALTip": { + "message": "Configure ports on the Ports tab after enabling." + }, + "featureGPS": { + "message": "GPS for navigation and telemetry" + }, + "featureGPSTip": { + "message": "Configure port scenario first" + }, + "featureFAILSAFE": { + "message": "Apply failsafe settings on RX signal loss" + }, + "featureSONAR": { + "message": "Sonar" + }, + "featureTELEMETRY": { + "message": "Telemetry output" + }, + "featureCURRENT_METER": { + "message": "Battery current monitoring" + }, + "feature3D": { + "message": "3D mode (for use with reversible ESCs)" + }, + "featureRX_PARALLEL_PWM": { + "message": "PWM RX input (one wire per channel)" + }, + "featureRX_MSP": { + "message": "MSP RX input (control via MSP port)" + }, + "featureRSSI_ADC": { + "message": "Analog RSSI input" + }, + "featureLED_STRIP": { + "message": "Multi-color RGB LED strip support" + }, + "featureDISPLAY": { + "message": "OLED Screen Display" + }, + "featureONESHOT125": { + "message": "ONESHOT ESC support" + }, + "featureONESHOT125Tip": { + "message": "Disconnect flight battery and remove props before enabling." + }, + "featureBLACKBOX": { + "message": "Blackbox flight data recorder" + }, + "featureBLACKBOXTip": { + "message": "Configure via the BlackBox tab after enabling." + }, + "featureCHANNEL_FORWARDING": { + "message": "Forward aux channels to servo outputs" + }, + "featureTRANSPONDER": { + "message": "Race Transponder" + }, + "featureTRANSPONDERTip": { + "message": "Configure via the Race Transponder tab after enabling." + }, + "configurationFeatureEnabled": { "message": "Enabled" }, @@ -943,6 +1031,33 @@ "message": "EEPROM <span style=\"color: #57a929\">saved</span>" }, + "transponderNotSupported": { + "message": "Your flight controller's firmware does not support transponder functionality." + }, + "transponderHelp": { + "message": "Configure your transponder code here. Note: Only valid codes will be recognised by race timing systems. Valid transponder codes can be obtained from <a href=\"http://seriouslypro.com/transponder-codes\" target=\"_blank\">Seriously Pro</a>." + }, + "transponderInformation": { + "message": "Transponders systems allow race organizers to time your laps. The transponder is fitted to your aircraft and when your aircraft passes the timing gate the track-side receiver registers your code and records your laptime. When fitting an IR based transponder your should ensure that it points outward from your aircraft towards the track-side receivers and that the light beam is not obstructed by your airframe, battery-straps, cables, propellers, etc." + }, + "transponderConfiguration": { + "message": "Configuration" + }, + "transponderData": { + "message": "Data" + }, + "transponderDataHelp": { + "message": "Hexadecimal digits only, 0-9, A-F" + }, + "transponderButtonSave": { + "message": "Save" + }, + "transponderDataInvalid": { + "message": "Transponder data is <span style=\"color: red\">invalid</span>" + }, + "transponderEepromSaved": { + "message": "EEPROM <span style=\"color: #57a929\">saved</span>" + }, "servosFirmwareUpgradeRequired": { "message": "Servos requires firmware >= 1.10.0. and target support." diff --git a/images/icons/cf_icon_transponder_grey.svg b/images/icons/cf_icon_transponder_grey.svg new file mode 100644 index 00000000..2ca2c849 --- /dev/null +++ b/images/icons/cf_icon_transponder_grey.svg @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="595.281px" height="841.891px" viewBox="0 0 595.281 841.891" enable-background="new 0 0 595.281 841.891"
+ xml:space="preserve">
+<g>
+ <path fill="#818181" d="M127.71,440.9c-7.142,41.59,6.722,84.439,36.549,114.267s72.677,43.69,114.267,36.549
+ c11.763-2.101,19.745-13.443,18.064-25.206c-0.84-4.621-2.94-8.822-5.881-11.763c-4.621-4.621-11.763-7.142-18.904-6.302
+ c-27.727,4.621-56.293-4.621-76.458-24.365c-20.165-19.745-28.987-47.892-24.366-76.038c2.1-11.763-5.881-23.105-18.064-25.206
+ C140.733,420.735,129.811,429.137,127.71,440.9"/>
+ <path fill="#818181" d="M289.028,652.21c-0.42-5.461-2.521-10.502-6.302-14.283c-4.201-4.201-10.083-6.722-16.804-6.302
+ c-47.892,2.521-94.942-15.543-128.971-49.151c-34.028-33.607-51.672-81.079-48.731-128.971c0.84-12.183-8.402-22.265-20.585-23.105
+ c-12.183-0.84-22.265,8.402-23.105,20.585c-3.36,60.494,19.325,119.309,62.175,162.158c42.85,42.851,101.664,65.115,162.158,62.175
+ C280.626,674.895,289.868,664.392,289.028,652.21"/>
+</g>
+<g>
+ <path fill="#818181" d="M480.616,308.596c-10.826,0-19.984,13.633-23.733,32.085h-97.416v32.084h97.416
+ c3.332,18.451,12.491,32.088,23.733,32.088c13.735,0,24.977-21.659,24.977-48.131C505.592,330.255,494.351,308.596,480.616,308.596
+ z"/>
+ <path fill="#818181" d="M297.853,252.445c-29.975,0-55.369,36.899-64.945,88.236h-91.171
+ c-3.331-18.452-12.491-32.085-23.729-32.085c-13.739,0-24.979,21.658-24.979,48.126c0,26.472,11.24,48.131,24.979,48.131
+ c10.822,0,19.982-13.637,23.729-32.088h87.426h132.386h4.995C363.631,304.584,334.073,252.445,297.853,252.445z"/>
+ <rect x="21.007" y="280.52" fill="#818181" width="191.502" height="23.262"/>
+ <rect x="381.115" y="280.52" fill="#818181" width="191.504" height="23.262"/>
+</g>
+</svg>
diff --git a/images/icons/cf_icon_transponder_white.svg b/images/icons/cf_icon_transponder_white.svg new file mode 100644 index 00000000..a58f74b1 --- /dev/null +++ b/images/icons/cf_icon_transponder_white.svg @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="595.281px" height="841.891px" viewBox="0 0 595.281 841.891" enable-background="new 0 0 595.281 841.891"
+ xml:space="preserve">
+<g>
+ <path fill="#FFFFFF" d="M127.71,440.9c-7.142,41.59,6.722,84.439,36.549,114.267s72.677,43.69,114.267,36.549
+ c11.763-2.101,19.745-13.443,18.064-25.206c-0.84-4.621-2.94-8.822-5.881-11.763c-4.621-4.621-11.763-7.142-18.904-6.302
+ c-27.727,4.621-56.293-4.621-76.458-24.365c-20.165-19.745-28.987-47.892-24.366-76.038c2.1-11.763-5.881-23.105-18.064-25.206
+ C140.733,420.735,129.811,429.137,127.71,440.9"/>
+ <path fill="#FFFFFF" d="M289.028,652.21c-0.42-5.461-2.521-10.502-6.302-14.283c-4.201-4.201-10.083-6.722-16.804-6.302
+ c-47.892,2.521-94.942-15.543-128.971-49.151c-34.028-33.607-51.672-81.079-48.731-128.971c0.84-12.183-8.402-22.265-20.585-23.105
+ c-12.183-0.84-22.265,8.402-23.105,20.585c-3.36,60.494,19.325,119.309,62.175,162.158c42.85,42.851,101.664,65.115,162.158,62.175
+ C280.626,674.895,289.868,664.392,289.028,652.21"/>
+</g>
+<g>
+ <path fill="#FFFFFF" d="M480.616,308.596c-10.826,0-19.984,13.633-23.733,32.085h-97.416v32.084h97.416
+ c3.332,18.451,12.491,32.088,23.733,32.088c13.735,0,24.977-21.659,24.977-48.131C505.592,330.255,494.351,308.596,480.616,308.596
+ z"/>
+ <path fill="#FFFFFF" d="M297.853,252.445c-29.975,0-55.369,36.899-64.945,88.236h-91.171
+ c-3.331-18.452-12.491-32.085-23.729-32.085c-13.739,0-24.979,21.658-24.979,48.126c0,26.472,11.24,48.131,24.979,48.131
+ c10.822,0,19.982-13.637,23.729-32.088h87.426h132.386h4.995C363.631,304.584,334.073,252.445,297.853,252.445z"/>
+ <rect x="21.007" y="280.52" fill="#FFFFFF" width="191.502" height="23.262"/>
+ <rect x="381.115" y="280.52" fill="#FFFFFF" width="191.504" height="23.262"/>
+</g>
+</svg>
@@ -29,6 +29,7 @@ var _3D; var DATAFLASH; var SDCARD; var BLACKBOX; +var TRANSPONDER; var RC_deadband; var SENSOR_ALIGNMENT; var RX_CONFIG; @@ -217,6 +218,11 @@ var FC = { blackboxRateDenom: 1 }; + TRANSPONDER = { + supported: false, + data: [] + }; + RC_deadband = { deadband: 0, yaw_deadband: 0, @@ -19,6 +19,7 @@ var GUI_control = function () { ]; this.defaultAllowedTabsWhenConnected = [ 'failsafe', + 'transponder', 'adjustments', 'auxiliary', 'cli', @@ -275,10 +276,12 @@ GUI_control.prototype.content_ready = function (callback) { $(elem).removeClass('togglemedium'); }); - // Build link to in-use CF version documentation - var documentationButton = $('div#content #button-documentation'); - documentationButton.html("Documentation for "+CONFIG.flightControllerVersion); - documentationButton.attr("href","https://github.com/cleanflight/cleanflight/tree/v{0}/docs".format(CONFIG.flightControllerVersion)); + if (CONFIGURATOR.connectionValid) { + // Build link to in-use CF version documentation + var documentationButton = $('div#content #button-documentation'); + documentationButton.html("Documentation for " + CONFIG.flightControllerVersion); + documentationButton.attr("href","https://github.com/cleanflight/cleanflight/tree/v{0}/docs".format(CONFIG.flightControllerVersion)); + } // loading tooltip jQuery(document).ready(function($) { @@ -38,6 +38,8 @@ var MSP_codes = { MSP_SDCARD_SUMMARY: 79, MSP_BLACKBOX_CONFIG: 80, MSP_SET_BLACKBOX_CONFIG: 81, + MSP_TRANSPONDER_CONFIG: 82, + MSP_SET_TRANSPONDER_CONFIG: 83, // Multiwii MSP commands MSP_IDENT: 100, @@ -932,6 +934,18 @@ var MSP = { case MSP_codes.MSP_SET_BLACKBOX_CONFIG: console.log("Blackbox config saved"); break; + case MSP_codes.MSP_TRANSPONDER_CONFIG: + var offset = 0; + TRANSPONDER.supported = (data.getUint8(offset++) & 1) != 0; + TRANSPONDER.data = []; + var bytesRemaining = data.byteLength - offset; + for (var i = 0; i < bytesRemaining; i++) { + TRANSPONDER.data.push(data.getUint8(offset++)); + } + break; + case MSP_codes.MSP_SET_TRANSPONDER_CONFIG: + console.log("Transponder config saved"); + break; case MSP_codes.MSP_SET_MODE_RANGE: console.log('Mode range saved'); break; @@ -1242,6 +1256,12 @@ MSP.crunch = function (code) { } break; + case MSP_codes.MSP_SET_TRANSPONDER_CONFIG: + for (var i = 0; i < TRANSPONDER.data.length; i++) { + buffer.push(TRANSPONDER.data[i]); + } + break; + case MSP_codes.MSP_SET_CHANNEL_FORWARDING: for (var i = 0; i < SERVO_CONFIG.length; i++) { var out = SERVO_CONFIG[i].indexOfChannelToForward; @@ -784,6 +784,19 @@ li.active .ic_flasher { background-image: url(images/icons/cf_icon_flasher_white.svg); } +.ic_transponder { + background-image: url(images/icons/cf_icon_transponder_grey.svg); +} + +.ic_transponder:hover { + background-image: url(images/icons/cf_icon_transponder_white.svg); +} + +li.active .ic_transponder { + background-image: url(images/icons/cf_icon_transponder_white.svg); +} + + /* SPARE Tab-Icons */ .ic_failsafe { background-image: url(images/icons/cf_icon_failsafe_grey.svg); @@ -26,6 +26,7 @@ <link type="text/css" rel="stylesheet" href="./tabs/adjustments.css" media="all" /> <link type="text/css" rel="stylesheet" href="./tabs/auxiliary.css" media="all" /> <link type="text/css" rel="stylesheet" href="./tabs/failsafe.css" media="all" /> +<link type="text/css" rel="stylesheet" href="./tabs/transponder.css" media="all" /> <link type="text/css" rel="stylesheet" href="./css/opensans_webfontkit/fonts.css" media="all" /> <link type="text/css" rel="stylesheet" href="./css/dropdown-lists/css/style_lists.css" media="all" /> <link type="text/css" rel="stylesheet" href="./js/libraries/switchery/switchery.css" media="all" /> @@ -78,6 +79,7 @@ <script type="text/javascript" src="./tabs/onboard_logging.js"></script> <script type="text/javascript" src="./tabs/firmware_flasher.js"></script> <script type="text/javascript" src="./tabs/failsafe.js"></script> +<script type="text/javascript" src="./tabs/transponder.js"></script> <title></title> </head> <body> @@ -191,7 +193,7 @@ <li class="tab_setup"><a href="#" i18n="tabSetup" class="tabicon ic_setup" title="Setup"></a></li> <li class="tab_ports"><a href="#" i18n="tabPorts" class="tabicon ic_ports" title="Ports"></a></li> <li class="tab_configuration"><a href="#" i18n="tabConfiguration" class="tabicon ic_config" title="Configuration"></a></li> - <li class="tab_failsafe"><a href="#" class="tabicon ic_failsafe" title="Failsafe">Failsafe</a></li> + <li class="tab_failsafe"><a href="#" i18n="tabFailsafe" class="tabicon ic_failsafe" title="Failsafe"></a></li> <li class="tab_pid_tuning"><a href="#" i18n="tabPidTuning" class="tabicon ic_pid" title="PID Tuning"></a></li> <li class="tab_receiver"><a href="#" i18n="tabReceiver" class="tabicon ic_rx" title="Receiver"></a></li> <li class="tab_auxiliary"><a href="#" i18n="tabAuxiliary" class="tabicon ic_modes" title="Modes"></a></li> @@ -199,6 +201,7 @@ <li class="tab_servos"><a href="#" i18n="tabServos" class="tabicon ic_servo" title="Servos"></a></li> <li class="tab_gps"><a href="#" i18n="tabGPS" class="tabicon ic_gps" title="GPS"></a></li> <li class="tab_motors"><a href="#" i18n="tabMotorTesting" class="tabicon ic_motor" title="Motors"></a></li> + <li class="tab_transponder"><a href="#" i18n="tabTransponder" class="tabicon ic_transponder" title="Transponder"></a></li> <li class="tab_led_strip"><a href="#" i18n="tabLedStrip" class="tabicon ic_led" title="LED Strip"></a></li> <li class="tab_sensors"><a href="#" i18n="tabRawSensorData" class="tabicon ic_sensors" title="Sensors"></a></li> <li class="tab_logging"><a href="#" i18n="tabLogging" class="tabicon ic_log" title="Tethered Logging"></a></li> @@ -136,6 +136,9 @@ $(document).ready(function () { case 'failsafe': TABS.failsafe.initialize(content_ready); break; + case 'transponder': + TABS.transponder.initialize(content_ready); + break; case 'setup': TABS.setup.initialize(content_ready); break; diff --git a/tabs/configuration.js b/tabs/configuration.js index 63b1d01d..612139c7 100644 --- a/tabs/configuration.js +++ b/tabs/configuration.js @@ -89,9 +89,7 @@ TABS.configuration.initialize = function (callback, scrollPosition) { } function process_html() { - // translate to user-selected language - localize(); - + var mixer_list_e = $('select.mixerList'); for (var i = 0; i < mixerList.length; i++) { mixer_list_e.append('<option value="' + (i + 1) + '">' + mixerList[i].name + '</option>'); @@ -110,37 +108,37 @@ TABS.configuration.initialize = function (callback, scrollPosition) { // generate features var features = [ - {bit: 0, group: 'rxMode', mode: 'group', name: 'RX_PPM', description: 'PPM RX input'}, - {bit: 1, group: 'batteryVoltage', name: 'VBAT', description: 'Battery voltage monitoring'}, - {bit: 2, group: 'other', name: 'INFLIGHT_ACC_CAL', description: 'In-flight level calibration'}, - {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'}, - {bit: 7, group: 'gps', name: 'GPS', description: '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'}, - {bit: 10, group: 'other', name: 'TELEMETRY', description: 'Telemetry output'}, - {bit: 11, group: 'batteryCurrent', name: 'CURRENT_METER', description: 'Battery current monitoring'}, - {bit: 12, group: 'other', name: '3D', description: '3D mode (for use with reversible ESCs)'}, - {bit: 13, group: 'rxMode', mode: 'group', name: 'RX_PARALLEL_PWM', description: 'PWM RX input'}, - {bit: 14, group: 'rxMode', mode: 'group', name: 'RX_MSP', description: 'MSP RX input'}, - {bit: 15, group: 'rssi', name: 'RSSI_ADC', description: 'Analog RSSI input'}, - {bit: 16, group: 'other', name: 'LED_STRIP', description: 'Addressable RGB LED strip support'}, - {bit: 17, group: 'other', name: 'DISPLAY', description: 'OLED Screen Display'}, - {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'} + {bit: 0, group: 'rxMode', mode: 'group', name: 'RX_PPM'}, + {bit: 1, group: 'batteryVoltage', name: 'VBAT'}, + {bit: 2, group: 'other', name: 'INFLIGHT_ACC_CAL'}, + {bit: 3, group: 'rxMode', mode: 'group', name: 'RX_SERIAL'}, + {bit: 4, group: 'esc', name: 'MOTOR_STOP'}, + {bit: 5, group: 'other', name: 'SERVO_TILT'}, + {bit: 6, group: 'other', name: 'SOFTSERIAL', haveTip: true}, + {bit: 7, group: 'gps', name: 'GPS', haveTip: true}, + {bit: 8, group: 'rxFailsafe', name: 'FAILSAFE'}, + {bit: 9, group: 'other', name: 'SONAR'}, + {bit: 10, group: 'other', name: 'TELEMETRY'}, + {bit: 11, group: 'batteryCurrent', name: 'CURRENT_METER'}, + {bit: 12, group: 'other', name: '3D'}, + {bit: 13, group: 'rxMode', mode: 'group', name: 'RX_PARALLEL_PWM'}, + {bit: 14, group: 'rxMode', mode: 'group', name: 'RX_MSP'}, + {bit: 15, group: 'rssi', name: 'RSSI_ADC'}, + {bit: 16, group: 'other', name: 'LED_STRIP'}, + {bit: 17, group: 'other', name: 'DISPLAY'}, + {bit: 18, group: 'esc', name: 'ONESHOT125', haveTip: true}, + {bit: 19, group: 'other', name: 'BLACKBOX', haveTip: true} ]; if (semver.gte(CONFIG.apiVersion, "1.12.0")) { features.push( - {bit: 20, group: 'other', name: 'CHANNEL_FORWARDING', description: 'Forward aux channels to servo outputs'} + {bit: 20, group: 'other', name: 'CHANNEL_FORWARDING'} ); } - if (semver.gte(CONFIG.apiVersion, "1.15.0")) { + if (semver.gte(CONFIG.apiVersion, "1.16.0")) { features.push( - {bit: 21, group: 'other', name: 'TRANSPONDER', description: 'Transponder'} + {bit: 21, group: 'other', name: 'TRANSPONDER', haveTip: true} ); } @@ -159,6 +157,11 @@ TABS.configuration.initialize = function (callback, scrollPosition) { for (var i = 0; i < features.length; i++) { var row_e; + var feature_tip_html = ''; + if (features[i].haveTip) { + feature_tip_html = '<div class="helpicon cf_tip" i18n_title="feature' + features[i].name + 'Tip"></div>'; + } + if (features[i].mode === 'group') { row_e = $('<tr><td style="width: 15px;"><input style="width: 13px;" class="feature" id="feature-' + i @@ -172,9 +175,8 @@ TABS.configuration.initialize = function (callback, scrollPosition) { + i + '">' + features[i].name - + '</label></td><td><span>' - + features[i].description - + '</td><span>'); + + '</label></td><td><span i18n="feature' + features[i].name + '"></span>' + + feature_tip_html + '</td></tr>'); radioGroups.push(features[i].group); } else { row_e = $('<tr><td><input class="feature toggle"' @@ -187,9 +189,8 @@ TABS.configuration.initialize = function (callback, scrollPosition) { + i + '">' + features[i].name - + '</label></td><td><span>' - + features[i].description - + '</span></td>'); + + '</label></td><td><span i18n="feature' + features[i].name + '"></span>' + + feature_tip_html + '</td></tr>'); var feature_e = row_e.find('input.feature'); @@ -203,6 +204,9 @@ TABS.configuration.initialize = function (callback, scrollPosition) { } }); } + + // translate to user-selected language + localize(); for (var i = 0; i < radioGroups.length; i++) { var group = radioGroups[i]; diff --git a/tabs/transponder.css b/tabs/transponder.css new file mode 100644 index 00000000..7465848e --- /dev/null +++ b/tabs/transponder.css @@ -0,0 +1,75 @@ +.tab-transponder .spacer_box { + padding-bottom: 10px; + float: left; + width: calc(100% - 20px); +} + +.tab-transponder .text input { + width: 100px; + padding-left: 3px; + height: 20px; + line-height: 20px; + text-align: left; + border: 1px solid silver; + border-radius: 3px; + margin-right: 11px; + font-size: 12px; + font-weight: normal; +} + +.tab-transponder .text .disabled { + width: 43px; + padding: 0px 5px; + background-color: #ececec; +} + +.tab-transponder .text span { + margin-left: 0px; +} + +.tab-transponder input { + float: left; +} + +.tab-transponder span { + margin: 0px; +} + +.tab-transponder .text + { + margin-bottom: 5px; + clear: left; + padding-bottom: 5px; + border-bottom: 1px solid #ddd; + width: 100%; + float: left; +} + +.tab-transponder .text:last-child { + border-bottom: none; + padding-bottom: 0px; + margin-bottom: 0px; +} + +.tab-transponder .textspacer { + float: left; + width: 115px; + height: 21px; +} + +.tab-transponder .gui_box span { + font-style: normal; + font-family: 'open_sansregular', Arial; + line-height: 19px; + color: #4F4F4F; + font-size: 11px; +} + +.require-transponder-supported, +.tab-transponder.transponder-supported .require-transponder-unsupported { + display: none; +} + +.tab-transponder.transponder-supported .require-transponder-supported { + display: block; +} diff --git a/tabs/transponder.html b/tabs/transponder.html new file mode 100644 index 00000000..7dd70a72 --- /dev/null +++ b/tabs/transponder.html @@ -0,0 +1,52 @@ +<div class="tab-transponder toolbar_fixed_bottom"> + <div class="content_wrapper"> + <div class="tab_title" i18n="tabTransponder">Transponder</div> + <div class="cf_doc_version_bt"> + <a id="button-documentation" href="https://github.com/cleanflight/cleanflight/releases" target="_blank"></a> + </div> + + <div class="require-transponder-unsupported note"> + <div class="note_spacer"> + <p i18n="transponderNotSupported"></p> + </div> + </div> + + <div class="require-transponder-supported"> + + <div class="note" style="margin-bottom: 20px;"> + <div class="note_spacer"> + <p i18n="transponderHelp"></p> + </div> + </div> + + <div class="gui_box grey"> + <div class="gui_box_titlebar"> + <div class="spacer_box_title" i18n="transponderConfiguration"></div> + </div> + <div class="spacer_box"> + <div class="text transponderData"> + <div class="textspacer" > + <input type="text" name="data" spellcheck="false"/> + </div> + <label for="failsafe_feature_new"><span i18n="transponderData"></span> + </label> + <div class="helpicon cf_tip" i18n_title="transponderDataHelp"></div> + </div> + </div> + </div> + <div class="clear-both"></div> + </div> + + <div class="note"> + <div class="note_spacer"> + <p i18n="transponderInformation"></p> + </div> + </div> + + </div> + <div class="content_toolbar require-transponder-supported"> + <div class="btn save_btn"> + <a class="save" href="#" i18n="transponderButtonSave"></a> + </div> + </div> +</div>
\ No newline at end of file diff --git a/tabs/transponder.js b/tabs/transponder.js new file mode 100644 index 00000000..c8b1d00b --- /dev/null +++ b/tabs/transponder.js @@ -0,0 +1,105 @@ +'use strict'; + +TABS.transponder = { + available: false +}; + +TABS.transponder.initialize = function (callback, scrollPosition) { + var self = this; + + if (GUI.active_tab != 'transponder') { + GUI.active_tab = 'transponder'; + googleAnalytics.sendAppView('Transponder'); + } + + // transponder supported added in MSP API Version 1.16.0 + TABS.transponder.available = semver.gte(CONFIG.apiVersion, "1.16.0"); + + if (!TABS.transponder.available) { + load_html(); + return; + } + + function load_html() { + $('#content').load("./tabs/transponder.html", process_html); + } + + // get the transponder data and a flag to see if transponder support is enabled on the FC + MSP.send_message(MSP_codes.MSP_TRANSPONDER_CONFIG, false, false, load_html); + + // Convert a hex string to a byte array + function hexToBytes(hex) { + for (var bytes = [], c = 0; c < hex.length; c += 2) + bytes.push(~parseInt(hex.substr(c, 2), 16)); + return bytes; + } + + function pad(n, width) { + n = n + ''; + return n.length >= width ? n : new Array(width - n.length + 1).join('0') + n; + } + + // Convert a byte array to a hex string + function bytesToHex(bytes) { + for (var hex = [], i = 0; i < bytes.length; i++) { + hex.push(pad(((~bytes[i]) & 0xFF).toString(16),2)); + } + return hex.join("").toUpperCase(); + } + function process_html() { + // translate to user-selected language + localize(); + + $(".tab-transponder") + .toggleClass("transponder-supported", TABS.transponder.available && TRANSPONDER.supported); + + if (TABS.transponder.available) { + + var data = bytesToHex(TRANSPONDER.data); + + $('input[name="data"]').val(data); + $('input[name="data"]').prop('maxLength', data.length); + + $('a.save').click(function () { + + + // gather data that doesn't have automatic change event bound + + var dataString = $('input[name="data"]').val(); + var expectedLength = TRANSPONDER.data.length; + var hexRegExp = new RegExp('[0-9a-fA-F]{' + (expectedLength * 2) + '}', 'gi'); + if (!dataString.match(hexRegExp)) { + GUI.log(chrome.i18n.getMessage('transponderDataInvalid')); + return; + } + + TRANSPONDER.data = hexToBytes(dataString); + + + // + // send data to FC + // + function save_transponder_config() { + MSP.send_message(MSP_codes.MSP_SET_TRANSPONDER_CONFIG, MSP.crunch(MSP_codes.MSP_SET_TRANSPONDER_CONFIG), false, save_to_eeprom); + } + function save_to_eeprom() { + MSP.send_message(MSP_codes.MSP_EEPROM_WRITE, false, false, function () { + GUI.log(chrome.i18n.getMessage('transponderEepromSaved')); + }); + } + + save_transponder_config(); + }); + } + // status data pulled via separate timer with static speed + GUI.interval_add('status_pull', function status_pull() { + MSP.send_message(MSP_codes.MSP_STATUS); + }, 250, true); + + GUI.content_ready(callback); + } +}; + +TABS.transponder.cleanup = function (callback) { + if (callback) callback(); +}; |