Compare commits

...

145 Commits

Author SHA1 Message Date
Damjan Adamic cf0e7c4a44 Release notes updated 2016-01-15 18:42:32 +01:00
Damjan Adamic fd2e0e4994 Fixes #3230: SD manager bug when scrolling up fixed 2016-01-15 18:16:15 +01:00
Damjan Adamic be457b40fc Fixes #3222 : Throttle Source combobox was populated multiple times (ported from master) 2016-01-10 21:52:33 +01:00
Damjan Adamic 41b91d8f5b Re #2939: additional test for EDGE logical switch (ported from next) 2016-01-10 18:59:27 +01:00
Bertrand Songis 4f9576b09d Merge pull request #3212 from opentx/projectkk2glider/issue_2939_edge_problem
Projectkk2glider/issue 2939 edge problem
2016-01-07 19:29:29 +01:00
Damjan Adamic 04f635404a Re #2939: gtests added 2016-01-07 10:35:09 +01:00
Damjan Adamic 64dd923e86 Re #2939: Version moved to 2.0.19 2016-01-06 21:53:44 +01:00
Damjan Adamic 051503e75c Re #2939: Compilation fix 2016-01-06 21:06:43 +01:00
Damjan Adamic 0520127fe6 Fixes #2939: Logical switch internal state was being reset by the AND switch, that affected its function (it looked like AND was applied before the EDGE processing, not after like it is done for other logical switch types). 2016-01-06 15:17:00 +01:00
Andre Bernet 9d48dca7a8 Release date 2016-01-03 14:54:55 +04:00
martin 426077ed16 CZ translations 2015-11-04 22:03:57 +01:00
Damjan Adamic 81f2b91b91 Version changed to 2.0.18 2015-11-04 19:33:56 +01:00
Damjan Adamic 7ac876af54 Release notes updated, release set to 2015-11-04 2015-11-04 19:08:02 +01:00
Andre Bernet 147d041b20 Had forgotten to add the shift in channel names on failsafe setup page 2015-11-01 14:02:57 +04:00
Andre Bernet 45ea2bf559 Port timer min/max fix from #2702 to 2.0 (issue reported on openrcforums) 2015-11-01 08:47:25 +04:00
Damjan Adamic c9fd91e755 Release notes updated 2015-10-31 20:31:01 +01:00
Andre Bernet f2d316b89b Correct failsafe mapping (fix #2975) 2015-10-30 13:15:08 +04:00
Andre Bernet 0283161f3d Compilation fixes 2015-10-30 13:14:58 +04:00
Damjan Adamic 87b2a4c0f1 Re #2956: removed possibility of INVERS, BOLD and BLINK attributes to Lua lcd.drawChannel() unit (reverted commits 7ad5c1e287 and 82450c6419) 2015-10-18 18:18:41 +02:00
Bertrand Songis 013152cf1f Merge pull request #2977 from opentx/projectkk2glider/issue_2956_unit_attributes
Projectkk2glider/issue 2956 unit attributes
2015-10-17 23:02:36 +02:00
Damjan Adamic 57881edb93 Re #2956: gtest images updated 2015-10-17 21:33:48 +02:00
Damjan Adamic 82450c6419 Re #2956: added SMLSIZE 2015-10-17 20:43:32 +02:00
Damjan Adamic 7ad5c1e287 Fixes #2956: added possibility of INVERS, BOLD and BLINK attributes to Lua lcd.drawChannel() unit 2015-10-17 20:38:59 +02:00
Damjan Adamic 02e9eb3555 Voltage symbol changed to upper case 2015-10-17 20:33:40 +02:00
Bertrand Songis 7284db8514 Fixes #2707 2015-10-13 15:31:19 +02:00
Damjan Adamic f7c1888509 More VC++ errors fixed 2015-10-09 20:15:37 +02:00
Damjan Adamic 3159dd5066 VC++ errors fixed (ported from 2.1 branch commit a142a74c36) 2015-10-09 20:11:35 +02:00
Damjan Adamic 221e3dbdda Fixes #2912: added missing "midtrim" and "endtrim" to FR (ported from 2.1) 2015-09-24 21:48:55 +02:00
Damjan Adamic e5b27d3de4 Helper script added (from 2.1 branch) 2015-09-20 19:09:19 +02:00
Damjan Adamic f9946dff03 Fixes #2728: edge switch could trigger right after the logicalSwitchesReset() was called (ported from 2.1) 2015-09-20 19:06:20 +02:00
Damjan Adamic 2c2b6e7483 Release notes updated 2015-09-20 18:55:49 +02:00
Bertrand Songis 1c16a99d9e Merge pull request #2900 from opentx/bsongis/issue2880_2.0_ppm_center_for_dsm2
Fixes #2880
2015-09-20 11:40:12 +02:00
Bertrand Songis 0771486e4e Travis tests added to 2.0 branch 2015-09-20 11:19:15 +02:00
Bertrand Songis 4040828e7a Fixes #2880 2015-09-19 10:48:44 +02:00
Grieb 66caf7dc79 Missed one place. 2015-09-16 22:35:42 -03:00
Grieb 3decae21b0 Fix logical condition. 2015-09-15 00:44:55 -03:00
Bertrand Songis ff8183fdbb Merge pull request #2770 from opentx/griebd/check_dup_receiver_number_2187
Alert about duplicated receiver id on copy. #2187
2015-09-14 00:20:41 +02:00
Bertrand Songis f0a5b28ef5 Merge pull request #2853 from opentx/griebd/finish_solution_for_2620_2778
should be a final solution for #2620
2015-09-14 00:16:15 +02:00
Damjan Adamic b814373391 Gtests fix 2015-09-12 19:02:01 +02:00
Damjan Adamic c059e9affb Gtests fix 2015-09-12 18:59:39 +02:00
Bertrand Songis 0dee1c207f Jenkins commit tests now stored in the repo 2015-09-12 18:45:30 +02:00
Bertrand Songis cbcf06964e Jenkins commit tests now stored in the repo 2015-09-12 18:45:04 +02:00
Damjan Adamic 9285985ff8 Removed unnecessary #if defined(SIMU) that was introduced in 16bdd1ae93 2015-09-12 18:43:50 +02:00
Damjan Adamic 415ae55a93 Removed unnecessary #if defined(SIMU) that was introduced in 16bdd1ae93 2015-09-12 18:42:20 +02:00
Grieb 526c88dbe8 Fix unrelated unused-but-set-variable. 2015-09-08 17:36:09 -03:00
Grieb 5ccdbeb8f8 Fixes #2620. Finished for backup and xml, needs test. 2015-09-08 17:32:04 -03:00
Grieb f91bfb1310 LoadEeprom error messages interface finished, still missing for LoadBackup and LoadEepromXml. 2015-09-08 14:21:44 -03:00
Grieb 641a382ef3 Cosmetics, trailing spaces. 2015-09-08 14:21:44 -03:00
Grieb 2b6cf2aa9d Changed by sugestions of @bsongis. 😉 2015-09-08 14:21:44 -03:00
Damjan Adamic d476696126 Readme updated 2015-09-03 12:26:10 +02:00
Bertrand Songis 909350dc66 Merge pull request #2789 from opentx/griebd/issue_2620_again
for review: proposed solution for #2620 and #2778
2015-08-28 21:40:42 +02:00
Grieb e62c552217 Possible fix for #2620 and #2778. Not finished, just for review... 2015-08-27 14:54:45 -03:00
Grieb fc935126b2 Cosmetics, trailing spaces and end lines. 2015-08-27 00:31:06 -03:00
Grieb 3018328ae7 Fixes #2187. Warning about used receiver id on copy. 2015-08-25 12:46:20 -03:00
Grieb eb657d5686 Cosmetics. Trailing spaces. 2015-08-25 12:43:42 -03:00
Bertrand Songis fa2bf0afaa Merge pull request #2724 from opentx/projectkk2glider/issue_2623_sd_manager_fixes_for2.0
Fixes #2623: several fixes (ported from 2.1):
2015-08-25 10:01:43 +02:00
Damjan Adamic f481d2f236 Fixes #2734: fixed endless loop in model compare (varable i was used both in outer and inner for loops) (ported from 2.1) 2015-08-19 22:25:20 +02:00
Damjan Adamic bdb22c37c6 Added missing keys initialization for simu (backported from 2.1) 2015-08-18 20:03:25 +02:00
Damjan Adamic 6aa4bd1c68 Re #2623: fixed f_getcwd() on Windows 2015-08-18 17:32:03 +02:00
Damjan Adamic 9f1a6c85c7 Re #2623: fix for non-ARM platforms 2015-08-18 16:52:25 +02:00
Damjan Adamic 23389081a5 Fixes #2623: several fixes (ported from 2.1):
Disable menu for [..],
Refresh file list after delete,
Removed delete menu option for directories,
Several simulator filesystem functions improved
2015-08-17 18:20:00 +02:00
Bertrand Songis 920e856dfd Fixes #2704 2015-08-14 11:50:11 +02:00
Andre Bernet 30336ff481 Frsky-D Telemetry protocol bug (0x5D followed by 0x3D) 2015-08-02 12:14:48 +02:00
bsongis eb03c6a054 Fixes #2271 2015-07-24 16:34:16 +02:00
Bertrand Songis 46218c148e Update README.md 2015-07-16 18:49:10 +02:00
Bertrand Songis 1f557bcda7 Update README.md 2015-07-16 18:48:39 +02:00
Damjan Adamic 19567b099d Fixes #2446: some function static variables were dependent on continuity of g_tmr10ms value between simulator sessions. 2015-07-10 18:31:40 +02:00
bsongis 18e85c4cbb Fixes #2442 2015-07-08 19:47:13 +02:00
Bertrand Songis ad34c2042e Update DONATIONS.txt 2015-07-07 07:25:52 +02:00
Damjan Adamic 8d96cfa420 Fixes #2420: input name buffer overflow in Companion 2015-07-05 18:13:50 +02:00
bsongis 0783f728a9 Fixes #2414 2015-07-04 17:41:39 +02:00
projectkk2glider 9e1f19a8ed Re #1732: stack corruption fixed 2015-07-02 19:21:25 +02:00
Andre Bernet 6914b4347a Add EU-only option to companion on master. Compile script is updated 2015-06-28 17:50:31 +02:00
Bertrand Songis 95ea3514e7 Update DONATIONS.txt 2015-06-28 11:47:00 +02:00
Damjan Adamic 7e385b8754 Release notes updated 2015-06-19 19:12:46 +02:00
bsongis b9a518192b Fixes #2368 2015-06-18 19:43:26 +02:00
Bertrand Songis 70fe6327c9 Update DONATIONS.txt 2015-06-18 19:05:27 +02:00
Bertrand Songis f432a2d4ec Update DONATIONS.txt 2015-06-18 06:52:23 +02:00
Bertrand Songis 7522f97695 Merge pull request #2366 from opentx/projectkk2glider/issue_2326_ge_filtering
Fixes #2326: Google Earth export GPS glitch filtering and lat/lon syn…
2015-06-17 18:07:28 +02:00
Damjan Adamic 674e3a8872 Re #2326: cosmetics 2015-06-17 10:16:24 +02:00
Bertrand Songis f32ff084ad Merge pull request #2365 from opentx/projectkk2glider/issue_2364_s3_ghost_readings
Fixes #2364: use fixed analog value for non-connected pots
2015-06-16 21:34:39 +02:00
Damjan Adamic 31a651ad1a Fixes #2326: Google Earth export GPS glitch filtering and lat/lon synchronization 2015-06-16 15:51:40 +02:00
Damjan Adamic b5cf6a13b0 Fixes #2364: use fixed analog value for non-connected pots 2015-06-16 09:26:06 +02:00
Bertrand Songis 31924c1a23 Update DONATIONS.txt 2015-06-14 21:30:50 +02:00
Bertrand Songis 73cddc76cf Update DONATIONS.txt 2015-06-12 23:52:45 +02:00
Bertrand Songis 64f66133cb Update DONATIONS.txt 2015-06-10 18:09:28 +02:00
Bertrand Songis 9c135095af Update DONATIONS.txt 2015-06-08 18:32:10 +02:00
Bertrand Songis 18f7586890 Update DONATIONS.txt 2015-06-07 09:12:14 +02:00
Bertrand Songis 8818aba486 Update DONATIONS.txt 2015-06-03 06:52:45 +02:00
Bertrand Songis 042b2498b3 Update DONATIONS.txt 2015-05-31 16:54:21 +02:00
Bertrand Songis 03f6d9ca77 Update DONATIONS.txt 2015-05-31 11:10:56 +02:00
Bertrand Songis 82e2ecb362 Update DONATIONS.txt 2015-05-30 17:55:48 +02:00
Bertrand Songis dadac58103 Merge pull request #2344 from opentx/projectkk2glider/issue_2260_simulator_volume_gain
Projectkk2glider/issue 2260 simulator volume gain
2015-05-29 21:18:49 +02:00
Bertrand Songis 297f7fa374 Update DONATIONS.txt 2015-05-28 17:52:08 +02:00
Damjan Adamic b7bdefabb3 Re #2260: All simulator audio globals joined into one structure, code cosmetics 2015-05-27 21:36:23 +02:00
Damjan Adamic 0cb1221312 Re #2260: Release notes updated 2015-05-27 21:09:47 +02:00
Damjan Adamic 00fb68084a Re #2260: ui widget 2015-05-26 19:33:52 +02:00
Damjan Adamic ac0d710efa Re #2260: added volumeGain in simulator 2015-05-26 19:33:52 +02:00
Damjan Adamic a29279e995 Release notes updated 2015-05-26 17:51:31 +02:00
Bertrand Songis 92bc7e9946 Update DONATIONS.txt 2015-05-26 06:33:43 +02:00
Bertrand Songis 3b2878f88a Merge pull request #2341 from opentx/projectkk2glider/issue_2301_findTrueFileName_fix_on_windows
Fixes #2301: findTrueFileName() was not finding any files on Windows
2015-05-25 22:22:33 +02:00
Damjan Adamic d862a13290 Fixes #2301: findTrueFileName() was not finding any files on Windows 2015-05-25 22:10:44 +02:00
Damjan Adamic 9d9e0b83c4 fix (reverted from commit 3fc2a27346) 2015-05-25 21:52:04 +02:00
DA 3fc2a27346 fix 2015-05-25 21:46:14 +02:00
Damjan Adamic e0035aea53 Release notes updated 2015-05-25 20:24:29 +02:00
Bertrand Songis 74cd5e3041 Update DONATIONS.txt 2015-05-25 15:39:31 +02:00
Bertrand Songis 3b9391df96 Update DONATIONS.txt 2015-05-23 19:15:39 +02:00
bsongis 22f0ff4660 [DE firmware] D16 becomes D16-EU (when only this mode is available) 2015-05-22 12:16:48 +02:00
Bertrand Songis 02a84d04cd Merge pull request #2323 from opentx/bsongis/special_eu_taranis_firmware_for_master
Special EU firmware for Taranis - For Master
2015-05-22 11:53:56 +02:00
Bertrand Songis edece6f083 Merge pull request #2295 from opentx/griebd/log_viewer_enhancement_2267
should solve #2267
2015-05-21 23:06:05 +02:00
Andre Bernet d65b04d393 Fix #2327 2015-05-21 22:57:14 +02:00
bsongis 57c4b8a4c6 Special EU firmware for Taranis - For Master
Only D16 mode is EU-compatible. This version will hide both D8 and LR12
modes.
2015-05-20 22:41:33 +02:00
Bertrand Songis 8b74de27d3 Update DONATIONS.txt 2015-05-20 19:10:25 +02:00
Bertrand Songis e726848d83 Update DONATIONS.txt 2015-05-19 20:33:49 +02:00
Bertrand Songis 3d409ba7c0 Merge pull request #2316 from opentx/projectkk2glider/issue_2084_max_expos
Fixes #2084: wrong constant used to limit maximum number of expos
2015-05-17 19:39:46 +02:00
Damjan Adamic 25fdffc417 Fixes #2084: wrong constant used to limit maximum number of expos 2015-05-17 18:50:24 +02:00
Romolo Manfredini f83239945c Missing string in translation 2015-05-16 23:32:37 +02:00
Bertrand Songis ce832b2736 Update DONATIONS.txt 2015-05-16 11:01:09 +02:00
Bertrand Songis 6aa2bd2f83 Update DONATIONS.txt 2015-05-15 13:29:23 +02:00
Bertrand Songis 47f8e6d0b6 Update DONATIONS.txt 2015-05-14 15:06:30 +02:00
Bertrand Songis 0f9ddc736b Update DONATIONS.txt 2015-05-13 08:18:21 +02:00
Grieb a4a6d27f83 logsdialog.cpp: removes unused function. 2015-05-11 13:01:38 -03:00
Grieb 25e60aeb66 Log Viewer: add a second legend and reference to axes in the legends. 2015-05-11 12:38:59 -03:00
Bertrand Songis 5447490fed Update DONATIONS.txt 2015-05-10 08:49:55 +02:00
Grieb 5a4a8ce43e Log Viewer multi-axes. Fixes #2267. 2015-05-09 15:39:07 -03:00
Bertrand Songis b645c9b03a Update DONATIONS.txt 2015-05-08 20:06:26 +02:00
Bertrand Songis 62b21985a8 Update DONATIONS.txt 2015-05-08 08:19:21 +02:00
Grieb fbc31db730 No real changes, just preparing for multi axes in Log Viewer. 2015-05-07 22:54:07 -03:00
Bertrand Songis c86d326869 Update DONATIONS.txt 2015-05-07 18:51:29 +02:00
Bertrand Songis da68fd68c5 Update DONATIONS.txt 2015-05-07 18:51:01 +02:00
Bertrand Songis 89a62f115e Update DONATIONS.txt 2015-05-07 18:45:46 +02:00
Grieb 47fa885cfa Updated QCustomPlot to 1.3.1. 2015-05-06 17:20:17 -03:00
Grieb 6c3591507f Solves item 2 of #2267. And add top/botton margin in graphs. 2015-05-06 16:42:40 -03:00
Bertrand Songis b4ceda1a98 Update DONATIONS.txt 2015-05-06 06:39:17 +02:00
Andre Bernet 27bba73d3c Mixers monitor in simulator (Fix #2258) 2015-05-05 10:25:50 +04:00
Bertrand Songis f4ccc9023b Update DONATIONS.txt 2015-05-04 19:20:29 +02:00
Bertrand Songis ced0546dd9 Update DONATIONS.txt 2015-05-04 07:34:17 +02:00
Bertrand Songis 367bb54119 Version 2.0.17 preparation 2015-05-04 06:59:42 +02:00
Bertrand Songis 88be3ac7a6 Special char introduced by the github editor 2015-05-04 06:54:28 +02:00
Bertrand Songis cb13ad1e8c Fixes #2253 2015-05-03 22:59:03 +02:00
Bertrand Songis 1bada4d7d6 Update mainwindow.cpp 2015-05-03 17:21:32 +02:00
Bertrand Songis 87675d3baf Update license.txt 2015-05-03 17:19:38 +02:00
Bertrand Songis 52226f362a Merge pull request #2252 from opentx/romolo/translations
Italian translations updated and obsolete removed.
2015-05-03 16:29:17 +02:00
Romolo Manfredini 713a99b1a9 Italian translations updated and obsolete removed. 2015-05-03 16:22:05 +02:00
bsongis 2ef2a0cc58 No tests, no code review? Thanks for the spam ... 2015-05-03 15:04:35 +02:00
85 changed files with 3716 additions and 4663 deletions
+14
View File
@@ -0,0 +1,14 @@
language: cpp
before_install:
- sudo apt-get remove cmake cmake-data --yes
- sudo add-apt-repository ppa:george-edison55/precise-backports --yes
- sudo add-apt-repository ppa:terry.guo/gcc-arm-embedded --yes
- sudo apt-get update
install:
- sudo apt-get install -y lcov cmake cmake-data bc curl gcc-arm-none-eabi gcc-avr avr-libc avrdude libqtcore4 libqt4-dev qt4-qmake g++ libxerces-c-dev xsdcxx libsdl1.2-dev libusb-1.0-0 libphonon-dev phonon libqtwebkit-dev python-qt4 python-qt4-dev libfox-1.6-dev libgtest-dev
script:
- radio/util/commit-tests.sh
- mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Debug ../companion/src && cmake --build .
+40 -6
View File
@@ -173,12 +173,12 @@ Keith Hertzog
Johan Moelich
Timo Esser
Dean Church (monthly)
Brian Paddock (monthly)
Brian Paddock
Jean Pierre Parisy
Norbert Martsch
Jean-Marie Guitard
Mike Perkins
Tilman Baumann (monthly)
Tilman Baumann
Fred Larssen
Ari Aalto
Robert Sams
@@ -189,7 +189,7 @@ Paul Robinson
Dave Matison
Mike Matheny
Pino Agostino
Graham Boucher (monthly)
Graham Boucher
Nelson Noura
Joel Allamy
Philip David Martin
@@ -200,7 +200,7 @@ Timothy Pelletier
Glen Roe (ShowMaster)
Jan Van Ooteghem
David Ankers - Special thanks here to the OpenPilot project!
Lawrence Christensen (monthly)
Lawrence Christensen
Leo Duflou
Bruce Wood
Arnd Feige
@@ -259,7 +259,7 @@ Peter Mitrik
Thomas Majewski
ANF King
Henrik Hammarström
Kenneth Lilja (monthly)
Kenneth Lilja
R Wells
Uwe Jordt
Harald Wilczak
@@ -600,7 +600,7 @@ Michel Baily
Donald Burke
Ronald Donker
Fredie Singh
Patrizio Simoncini (monthly)
Patrizio Simoncini
Harald Gabler
Michael Brown
Julien Gérard
@@ -748,3 +748,37 @@ John Lipscomb
Peter Glassey
Joseph Kramer
F.Javier Martinez Velasco
Claudio Piccinini
John Jackson
John Beech
Rene Traa
Sebastien Charpentier (monthly)
Nigel Hendriks
Frédéric Devillard
Albert Herzog
Anindya Mukerjee
Kenny Stanberry
Tauno Rautakorpi
Mathias Krapp
Fernando Rimoldi
Wolfgang Rauser
Richard Shagam
Stephen Bailey
DK-System
Casa Kuxtal
Alain Labonne
Christopher Potts
Douglas George
Michael Banks
Jon Wiltshire
David Green
Guy Willems
Xavier Mestelan Pinon
Maik Gottschalk
Scott Sparks
John Dunning
RAD51
Ron Powell
Alain Labonne
Carol Sills
Franck Aßmann
+2 -4
View File
@@ -1,7 +1,5 @@
##OpenTX Master Branch
##OpenTX 2.0 Branch
You have found your way to the GitHub repository site for the OpenTX Master Branch. This code branch holds the source code for the latest stable release.
The ongoing development is not done in this branch. It is performed in the branch called next.
The ongoing development is not done in this branch. It is performed in the branches `master` and/or `next`. This branch is used for bug fixes of OpenTX 2.0.x series.
Refer to the opentx.wiki for information about setting up the tool chains for building OpenTX and OpenTX Companion as well as other development related issues.
+35
View File
@@ -1,3 +1,38 @@
<h2>Version 2.0.19 / 2016-01-15</h2>
<ul>
<li>Throttle Source combobox was populated multiple times (<a href=https://github.com/opentx/opentx/issues/3222>#3222</a>)</li>
</ul>
<h2>Version 2.0.18 / 2016-01-03</h2>
<ul>
<li>Enabled <i>Mixers monitor</i> in Taranis simulator</li>
<li>Better support for multi-axes in Log Viewer (<a href=https://github.com/opentx/opentx/issues/2267>#2267</a>)</li>
<li>File path issue in Taranis simulator function <i>findTrueFileName()</i> on Windows (<a href=https://github.com/opentx/opentx/issues/2301>#2301</a>)</li>
<li>Added simulator volume gain setting (<a href=https://github.com/opentx/opentx/issues/2260>#2260</a>)</li>
<li>Added GPS glitch filtering and Latitude/Longitude position synchronization to Google Earth export (<a href=https://github.com/opentx/opentx/issues/2326>#2326</a>)</li>
<li>Fixed a rare program crash when editing Input for 9X radio (<a href=https://github.com/opentx/opentx/issues/2420>#2420</a>)</li>
<li>Fixed missing RSSI audio warnings if simulator was started multiple times (<a href=https://github.com/opentx/opentx/issues/2446>#2446</a>)</li>
<li>EU-only firmware option added</li>
<li>Joystick channel mapping bug fixed (<a href=https://github.com/opentx/opentx/issues/1732>#1732</a>)</li>
<li>Physical switches were missing from Adjust Volume special function sources (<a href=https://github.com/opentx/opentx/issues/2414>#2414</a>)</li>
<li>Fixed a rare program crash: input name buffer overflow (<a href=https://github.com/opentx/opentx/issues/2420>#2420</a>)</li>
<li>Alarms did not work if user started radio simulation several times (<a href=https://github.com/opentx/opentx/issues/2446>#2446</a>)</li>
<li>Fixed endless loop in model compare (<a href=https://github.com/opentx/opentx/issues/2734>#2734</a>)</li>
<li>Prevent user from opening 2.1 or higher EEPE (<a href=https://github.com/opentx/opentx/issues/2620>#2620</a>)</li>
<li>Center beep checkbook for P3 was missing for some radios (<a href=https://github.com/opentx/opentx/issues/2707>#2707</a>)</li>
<li>Corrected failsafe mapping when using Custom failsafe mode, D16 protocol and channel range different from from 1-8.
Users with such setups are advised to re-check their failsafe settings (<a href=https://github.com/opentx/opentx/issues/2975>#2975</a>)</li>
</ul>
<h2>Version 2.0.17 / 2015-05-04</h2>
<ul>
<li>Simulator crash (<a href=https://github.com/opentx/opentx/issues/2253>#2253</a>)</li>
</ul>
<h2>Version 2.0.16 / 2015-05-03</h2>
<ul>
<li><i>nooverridech</i> firmware option was not working</li>
+4 -12
View File
@@ -2,7 +2,7 @@ PROJECT( companion )
SET( C9X_VERSION_MAJOR "2" )
SET( C9X_VERSION_MINOR "0" )
SET( C9X_VERSION_REVISION "16" )
SET( C9X_VERSION_REVISION "19" )
SET( C9X_VERSION ${C9X_VERSION_MAJOR}.${C9X_VERSION_MINOR}.${C9X_VERSION_REVISION} )
CMAKE_MINIMUM_REQUIRED( VERSION 2.8 )
@@ -38,7 +38,7 @@ ELSE()
MESSAGE( "SDL not found! Joysticks support will be disabled. Simulator audio will not work." )
ENDIF()
FIND_PACKAGE(Qt4 4.8.4 REQUIRED)
FIND_PACKAGE(Qt4 4.8.1 REQUIRED)
SET( QT_USE_QTNETWORK True )
SET( QT_USE_QTXML True )
INCLUDE( ${QT_USE_FILE} )
@@ -283,11 +283,7 @@ ELSE( )
ADD_EXECUTABLE(companion WIN32 ${companion_SRCS} ${companion_QM})
ENDIF( )
if(SDL_FOUND)
target_link_libraries(companion modeledit simulation common qcustomplot ${QT_LIBRARIES} ${XERCESC_LIBRARY} ${PTHREAD_LIBRARY} ${SDL_LIBRARY} ${PHONON_LIBS} )
else()
target_link_libraries(companion modeledit simulation common qcustomplot ${QT_LIBRARIES} ${QT_QTMAIN_LIBRARY} ${XERCESC_LIBRARY} ${PTHREAD_LIBRARY} ${SDL_LIBRARY} ${PHONON_LIBS} )
endif()
target_link_libraries(companion modeledit simulation common qcustomplot ${QT_LIBRARIES} ${QT_QTMAIN_LIBRARY} ${XERCESC_LIBRARY} ${PTHREAD_LIBRARY} ${SDL_LIBRARY} ${PHONON_LIBS} )
############# Standalone simu ###############
@@ -348,11 +344,7 @@ else()
add_executable(simulator WIN32 ${simu_SRCS})
endif()
if(SDL_FOUND)
target_link_libraries(simulator simulation common ${QT_LIBRARIES} ${PTHREAD_LIBRARY} ${SDL_LIBRARY} ${PHONON_LIBS})
else()
target_link_libraries(simulator simulation common ${QT_LIBRARIES} ${QT_QTMAIN_LIBRARY} ${PTHREAD_LIBRARY} ${SDL_LIBRARY} ${PHONON_LIBS})
endif()
target_link_libraries(simulator simulation common ${QT_LIBRARIES} ${QT_QTMAIN_LIBRARY} ${PTHREAD_LIBRARY} ${SDL_LIBRARY} ${PHONON_LIBS})
############# Packaging ####################
+5
View File
@@ -295,6 +295,7 @@ QString Profile::fwName() const { return _fwName; }
QString Profile::fwType() const { return _fwType; }
QString Profile::name() const { return _name; }
QString Profile::sdPath() const { return _sdPath; }
int Profile::volumeGain() const { return _volumeGain; }
QString Profile::pBackupDir() const { return _pBackupDir; }
QString Profile::splashFile() const { return _splashFile; }
bool Profile::burnFirmware() const { return _burnFirmware; }
@@ -324,6 +325,7 @@ void Profile::name (const QString x) { store(x, _name, "Name"
void Profile::fwName (const QString x) { store(x, _fwName, "fwName" ,"Profiles", QString("profile%1").arg(index));}
void Profile::fwType (const QString x) { store(x, _fwType, "fwType" ,"Profiles", QString("profile%1").arg(index));}
void Profile::sdPath (const QString x) { store(x, _sdPath, "sdPath" ,"Profiles", QString("profile%1").arg(index));}
void Profile::volumeGain (const int x) { store(x, _volumeGain, "volumeGain" ,"Profiles", QString("profile%1").arg(index));}
void Profile::pBackupDir (const QString x) { store(x, _pBackupDir, "pBackupDir" ,"Profiles", QString("profile%1").arg(index));}
void Profile::splashFile (const QString x) { store(x, _splashFile, "SplashFileName" ,"Profiles", QString("profile%1").arg(index));}
void Profile::burnFirmware (const bool x) { store(x, _burnFirmware, "burnFirmware" ,"Profiles", QString("profile%1").arg(index));}
@@ -361,6 +363,7 @@ Profile& Profile::operator=(const Profile& rhs)
fwName ( rhs.fwName() );
fwType ( rhs.fwType() );
sdPath ( rhs.sdPath() );
volumeGain ( rhs.volumeGain() );
pBackupDir ( rhs.pBackupDir() );
splashFile ( rhs.splashFile() );
burnFirmware ( rhs.burnFirmware() );
@@ -438,6 +441,7 @@ void Profile::init(int newIndex)
_fwType = "";
_name = "";
_sdPath = "";
_volumeGain = 10;
_pBackupDir = "";
_splashFile = "";
_burnFirmware = false;
@@ -462,6 +466,7 @@ void Profile::flush()
getset( _fwType, "fwType" ,"" ,"Profiles", QString("profile%1").arg(index));
getset( _name, "Name" ,"" ,"Profiles", QString("profile%1").arg(index));
getset( _sdPath, "sdPath" ,"" ,"Profiles", QString("profile%1").arg(index));
getset( _volumeGain, "volumeGain" ,10 ,"Profiles", QString("profile%1").arg(index));
getset( _pBackupDir, "pBackupDir" ,"" ,"Profiles", QString("profile%1").arg(index));
getset( _splashFile, "SplashFileName" ,"" ,"Profiles", QString("profile%1").arg(index));
getset( _burnFirmware, "burnFirmware" ,false ,"Profiles", QString("profile%1").arg(index));
+3
View File
@@ -107,6 +107,7 @@ class Profile: protected CompStoreObj
QString _fwType;
QString _name;
QString _sdPath;
int _volumeGain;
QString _pBackupDir;
QString _splashFile;
bool _burnFirmware;
@@ -138,6 +139,7 @@ class Profile: protected CompStoreObj
QString fwType() const;
QString name() const;
QString sdPath() const;
int volumeGain() const;
QString pBackupDir() const;
QString splashFile() const;
bool burnFirmware() const;
@@ -166,6 +168,7 @@ class Profile: protected CompStoreObj
void name (const QString);
void fwName (const QString);
void fwType (const QString);
void volumeGain (const int);
void sdPath (const QString);
void pBackupDir (const QString);
void splashFile (const QString);
+2
View File
@@ -48,6 +48,7 @@ void AppPreferencesDialog::writeValues()
g.useWizard(ui->modelWizard_CB->isChecked());
g.historySize(ui->historySize->value());
g.backLight(ui->backLightColor->currentIndex());
g.profile[g.id()].volumeGain(round(ui->volumeGain->value() * 10.0));
g.libDir(ui->libraryPath->text());
g.gePath(ui->ge_lineedit->text());
g.embedSplashes(ui->splashincludeCB->currentIndex());
@@ -111,6 +112,7 @@ void AppPreferencesDialog::initSettings()
ui->showSplash->setChecked(g.showSplash());
ui->historySize->setValue(g.historySize());
ui->backLightColor->setCurrentIndex(g.backLight());
ui->volumeGain->setValue(g.profile[g.id()].volumeGain() / 10.0);
if (IS_TARANIS(GetCurrentFirmware()->getBoard())) {
ui->backLightColor->setEnabled(false);
+115 -78
View File
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>686</width>
<height>550</height>
<height>619</height>
</rect>
</property>
<property name="sizePolicy">
@@ -889,49 +889,10 @@ Mode 4:
<string>Simulator Settings</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item row="5" column="4">
<widget class="QPushButton" name="joystickcalButton">
<property name="text">
<string>Simulator BackLight</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QCheckBox" name="joystickChkB">
<property name="text">
<string>Enable</string>
</property>
</widget>
</item>
<item row="0" column="3">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="4">
<widget class="QPushButton" name="snapshotPathButton">
<property name="text">
<string>Open Folder</string>
</property>
<property name="flat">
<bool>false</bool>
<string>Calibrate</string>
</property>
</widget>
</item>
@@ -970,6 +931,73 @@ Mode 4:
</item>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_19">
<property name="text">
<string>Simulator capture folder</string>
</property>
</widget>
</item>
<item row="8" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1" colspan="4">
<widget class="QCheckBox" name="snapshotClipboardCKB">
<property name="text">
<string>Only capture to clipboard</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QCheckBox" name="joystickChkB">
<property name="text">
<string>Enable</string>
</property>
</widget>
</item>
<item row="0" column="3">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="joystickCB">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QPushButton" name="snapshotPathButton">
<property name="text">
<string>Open Folder</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_11">
<property name="sizePolicy">
@@ -983,43 +1011,22 @@ Mode 4:
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="joystickCB">
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="5" column="4">
<widget class="QPushButton" name="joystickcalButton">
<property name="text">
<string>Calibrate</string>
<string>Simulator BackLight</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_19">
<property name="text">
<string>Simulator capture folder</string>
</property>
</widget>
</item>
<item row="6" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1" colspan="2">
<widget class="QLineEdit" name="snapshotPath">
<property name="enabled">
@@ -1036,13 +1043,6 @@ Mode 4:
</property>
</widget>
</item>
<item row="1" column="1" colspan="4">
<widget class="QCheckBox" name="snapshotClipboardCKB">
<property name="text">
<string>Only capture to clipboard</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="4">
<widget class="QCheckBox" name="simuSW">
<property name="text">
@@ -1050,6 +1050,38 @@ Mode 4:
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_volumeGain">
<property name="text">
<string>Simulator Volume Gain</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QDoubleSpinBox" name="volumeGain">
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>0.500000000000000</double>
</property>
<property name="maximum">
<double>3.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
@@ -1058,6 +1090,7 @@ Mode 4:
</widget>
<tabstops>
<tabstop>tabWidget</tabstop>
<tabstop>profileNameLE</tabstop>
<tabstop>removeProfileButton</tabstop>
<tabstop>downloadVerCB</tabstop>
<tabstop>langCombo</tabstop>
@@ -1067,6 +1100,9 @@ Mode 4:
<tabstop>clearImageButton</tabstop>
<tabstop>sdPath</tabstop>
<tabstop>sdPathButton</tabstop>
<tabstop>profilebackupPath</tabstop>
<tabstop>ProfilebackupPathButton</tabstop>
<tabstop>pbackupEnable</tabstop>
<tabstop>stickmodeCB</tabstop>
<tabstop>channelorderCB</tabstop>
<tabstop>renameFirmware</tabstop>
@@ -1092,6 +1128,7 @@ Mode 4:
<tabstop>joystickCB</tabstop>
<tabstop>joystickChkB</tabstop>
<tabstop>joystickcalButton</tabstop>
<tabstop>volumeGain</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources>
+22 -17
View File
@@ -108,7 +108,7 @@ burnDialog::burnDialog(QWidget *parent, int Type, QString * fileName, bool * bac
}
}
ui->FWFileName->hide();
ui->FlashLoadButton->hide();
ui->FlashLoadButton->hide();
hexfileName->clear();
}
else if (Type==FLASH_FILE_TYPE) {
@@ -168,7 +168,7 @@ void burnDialog::on_FlashLoadButton_clicked()
ui->patchcalib_CB->setChecked(false);
ui->patchhw_CB->setChecked(false);
ui->patchhw_CB->hide();
ui->patchcalib_CB->hide();
ui->patchcalib_CB->hide();
}
QTimer::singleShot(0, this, SLOT(shrink()));
}
@@ -205,7 +205,7 @@ void burnDialog::checkFw(QString fileName)
}
else {
QMessageBox::warning(this, tr("Warning"), tr("%1 may not be a valid firmware file").arg(fileName));
}
}
ui->BurnFlashButton->setEnabled(true);
QTimer::singleShot(0, this, SLOT(shrink()));
g.flashDir( QFileInfo(fileName).dir().absolutePath() );
@@ -238,16 +238,17 @@ bool burnDialog::checkeEprom(QString fileName)
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { //reading HEX TEXT file
QMessageBox::critical(this, tr("Error"),tr("Error opening file %1:\n%2.").arg(fileName).arg(file.errorString()));
return false;
}
}
QDomDocument doc(ER9X_EEPROM_FILE_TYPE);
bool xmlOK = doc.setContent(&file);
if(xmlOK) {
if (!LoadEepromXml(radioData, doc)){
std::bitset<NUM_ERRORS> errors((unsigned long long)LoadEepromXml(radioData, doc));
if (!errors.test(NO_ERROR)) {
return false;
}
}
file.reset();
QTextStream inputStream(&file);
if (fileType==FILE_TYPE_EEPE) { // read EEPE file header
QString hline = inputStream.readLine();
@@ -268,7 +269,9 @@ bool burnDialog::checkeEprom(QString fileName)
return true;
}
file.close();
if (!LoadEeprom(radioData, eeprom, eeprom_size)) {
std::bitset<NUM_ERRORS> errors((unsigned long long)LoadEeprom(radioData, eeprom, eeprom_size));
if (!errors.test(NO_ERROR)) {
int res = QMessageBox::question(this, "Companion",tr("Invalid binary Models and Settings File %1, Proceed anyway ?").arg(fileName),QMessageBox::Yes | QMessageBox::No);
if (res == QMessageBox::No) {
return false;
@@ -292,7 +295,9 @@ bool burnDialog::checkeEprom(QString fileName)
QMessageBox::critical(this, tr("Error"),tr("Error reading file %1:\n%2.").arg(fileName).arg(file.errorString()));
return false;
}
if (!LoadEeprom(radioData, eeprom, eeprom_size)) {
std::bitset<NUM_ERRORS> errors((unsigned long long)LoadEeprom(radioData, eeprom, eeprom_size));
if (!errors.test(NO_ERROR)) {
int res = QMessageBox::question(this, "Companion",tr("Invalid binary Models and Settings File %1, Proceed anyway ?").arg(fileName),QMessageBox::Yes | QMessageBox::No);
if (res == QMessageBox::No) {
return false;
@@ -329,7 +334,7 @@ void burnDialog::updateUI()
ui->useFwImageCB->setChecked( imageSource == FIRMWARE );
ui->useLibraryImageCB->setChecked( imageSource == LIBRARY );
ui->useAnotherImageCB->setChecked( imageSource == ANOTHER );
displaySplash();
}
@@ -384,7 +389,7 @@ void burnDialog::on_useAnotherImageCB_clicked()
else{
imageSource = ANOTHER;
imageFile = fileName;
}
}
}
updateUI();
}
@@ -450,7 +455,7 @@ void burnDialog::on_BurnFlashButton_clicked()
}
else {
QMessageBox::critical(this, tr("Warning"), tr("No firmware selected"));
hexfileName->clear();
hexfileName->clear();
}
}
@@ -463,7 +468,7 @@ void burnDialog::on_BurnFlashButton_clicked()
int8_t PPM_Multiplier=(int8_t) g.profile[g.id()].ppmMultiplier();
uint8_t GSStickMode=(uint8_t) g.profile[g.id()].gsStickMode();
uint8_t vBatWarn=(uint8_t) g.profile[g.id()].vBatWarn();
QString DisplaySet= g.profile[g.id()].display();
QString BeeperSet= g.profile[g.id()].beeper();
QString HapticSet= g.profile[g.id()].haptic();
@@ -557,7 +562,7 @@ void burnDialog::on_BurnFlashButton_clicked()
else {
QMessageBox::critical(this, tr("Warning"), tr("Wrong radio setting data in profile, Settings not patched"));
}
if (patch) {
QString fileName = generateProcessUniqueTempFileName("temp.bin");
QFile file(fileName);
@@ -586,12 +591,12 @@ void burnDialog::on_BurnFlashButton_clicked()
}
else {
hexfileName->clear();
hexfileName->append(ui->FWFileName->text());
hexfileName->append(ui->FWFileName->text());
}
}
else {
hexfileName->clear();
hexfileName->append(ui->FWFileName->text());
hexfileName->append(ui->FWFileName->text());
}
}
this->close();
@@ -599,8 +604,8 @@ void burnDialog::on_BurnFlashButton_clicked()
void burnDialog::on_cancelButton_clicked()
{
hexfileName->clear();
this->close();
hexfileName->clear();
this->close();
}
void burnDialog::on_EEpromCB_toggled(bool checked)
+1
View File
@@ -50,6 +50,7 @@
#include <iostream>
#if defined(JOYSTICKS) || defined(SIMU_AUDIO)
#include <SDL.h>
#undef main
#endif
#include "mainwindow.h"
#include "eeprominterface.h"
+5 -5
View File
@@ -1088,11 +1088,11 @@ void CompareDialog::printCurves()
painter2.drawLine(0,ISIZE/2,ISIZE,ISIZE/2);
painter1.drawLine(ISIZE/2,0,ISIZE/2,ISIZE);
painter2.drawLine(ISIZE/2,0,ISIZE/2,ISIZE);
for(i=0; i<21; i++) {
painter1.drawLine(ISIZE/2-5,(ISIZE*i)/(20),ISIZE/2+5,(ISIZE*i)/(20));
painter2.drawLine(ISIZE/2-5,(ISIZE*i)/(20),ISIZE/2+5,(ISIZE*i)/(20));
painter1.drawLine((ISIZE*i)/(20),ISIZE/2-5,(ISIZE*i)/(20),ISIZE/2+5);
painter2.drawLine((ISIZE*i)/(20),ISIZE/2-5,(ISIZE*i)/(20),ISIZE/2+5);
for(int k=0; k<21; k++) {
painter1.drawLine(ISIZE/2-5,(ISIZE*k)/(20),ISIZE/2+5,(ISIZE*k)/(20));
painter2.drawLine(ISIZE/2-5,(ISIZE*k)/(20),ISIZE/2+5,(ISIZE*k)/(20));
painter1.drawLine((ISIZE*k)/(20),ISIZE/2-5,(ISIZE*k)/(20),ISIZE/2+5);
painter2.drawLine((ISIZE*k)/(20),ISIZE/2-5,(ISIZE*k)/(20),ISIZE/2+5);
}
cm1y.append("]");
+96 -19
View File
@@ -366,7 +366,7 @@ QString RawSource::toString(const ModelData & model)
QObject::tr("L21"), QObject::tr("L22"), QObject::tr("L23"), QObject::tr("L24"), QObject::tr("L25"), QObject::tr("L26"), QObject::tr("L27"), QObject::tr("L28"), QObject::tr("L29"), QObject::tr("L30"),
QObject::tr("L31"), QObject::tr("L32")
};
if (index<0) {
return QObject::tr("----");
}
@@ -402,7 +402,7 @@ QString RawSource::toString(const ModelData & model)
case SOURCE_TYPE_TELEMETRY:
return CHECK_IN_ARRAY(telemetry, index);
case SOURCE_TYPE_GVAR:
return QObject::tr("GV%1").arg(index+1);
return QObject::tr("GV%1").arg(index+1);
default:
return QObject::tr("----");
}
@@ -1155,7 +1155,7 @@ void ModelData::clear()
}
else {
moduleData[0].protocol=PPM;
moduleData[1].protocol=OFF;
moduleData[1].protocol=OFF;
}
for (int i=0; i<C9X_MAX_FLIGHT_MODES; i++) {
flightModeData[i].clear();
@@ -1336,7 +1336,7 @@ void RegisterEepromInterfaces()
eepromInterfaces.push_back(new OpenTxEepromInterface(BOARD_SKY9X));
eepromInterfaces.push_back(new OpenTxEepromInterface(BOARD_9XRPRO));
eepromInterfaces.push_back(new OpenTxEepromInterface(BOARD_TARANIS));
eepromInterfaces.push_back(new OpenTxEepromInterface(BOARD_TARANIS_PLUS));
eepromInterfaces.push_back(new OpenTxEepromInterface(BOARD_TARANIS_PLUS));
eepromInterfaces.push_back(new Gruvin9xInterface(BOARD_STOCK));
eepromInterfaces.push_back(new Gruvin9xInterface(BOARD_GRUVIN9X));
eepromInterfaces.push_back(new Ersky9xInterface());
@@ -1349,7 +1349,7 @@ void UnregisterEepromInterfaces()
foreach(EEPROMInterface * intf, eepromInterfaces) {
// qDebug() << "UnregisterEepromInterfaces(): deleting " << QString::number( reinterpret_cast<uint64_t>(intf), 16 );
delete intf;
}
}
OpenTxEepromCleanup();
}
@@ -1357,42 +1357,119 @@ QList<FirmwareInterface *> firmwares;
FirmwareInterface * default_firmware_variant;
FirmwareInterface * current_firmware_variant;
void UnregisterFirmwares()
void UnregisterFirmwares()
{
foreach (FirmwareInterface * f, firmwares) {
delete f;
}
}
bool LoadEeprom(RadioData &radioData, const uint8_t *eeprom, const int size)
void ShowEepromErrors(QWidget *parent, const QString &title, const QString &mainMessage, unsigned long errorsFound)
{
foreach(EEPROMInterface *eepromInterface, eepromInterfaces) {
if (eepromInterface->load(radioData, eeprom, size))
return true;
std::bitset<NUM_ERRORS> errors((unsigned long long)errorsFound);
QStringList errorsList;
errorsList << QT_TRANSLATE_NOOP("EepromInterface", "Possible causes for this:");
if (errors.test(UNSUPPORTED_NEWER_VERSION)) { errorsList << QT_TRANSLATE_NOOP("EepromInterface", "- Eeprom is from a newer version of OpenTX"); }
if (errors.test(NOT_OPENTX)) { errorsList << QT_TRANSLATE_NOOP("EepromInterface", "- Eeprom is not from OpenTX"); }
if (errors.test(NOT_TH9X)) { errorsList << QT_TRANSLATE_NOOP("EepromInterface", "- Eeprom is not from Th9X"); }
if (errors.test(NOT_GRUVIN9X)) { errorsList << QT_TRANSLATE_NOOP("EepromInterface", "- Eeprom is not from Gruvin9X"); }
if (errors.test(NOT_ERSKY9X)) { errorsList << QT_TRANSLATE_NOOP("EepromInterface", "- Eeprom is not from ErSky9X"); }
if (errors.test(NOT_ER9X)) { errorsList << QT_TRANSLATE_NOOP("EepromInterface", "- Eeprom is not from Er9X"); }
if (errors.test(WRONG_SIZE)) { errorsList << QT_TRANSLATE_NOOP("EepromInterface", "- Eeprom size is invalid"); }
if (errors.test(WRONG_FILE_SYSTEM)) { errorsList << QT_TRANSLATE_NOOP("EepromInterface", "- Eeprom file system is invalid"); }
if (errors.test(UNKNOWN_BOARD)) { errorsList << QT_TRANSLATE_NOOP("EepromInterface", "- Eeprom is from a unknown board"); }
if (errors.test(WRONG_BOARD)) { errorsList << QT_TRANSLATE_NOOP("EepromInterface", "- Eeprom is from the wrong board"); }
if (errors.test(BACKUP_NOT_SUPPORTED)) { errorsList << QT_TRANSLATE_NOOP("EepromInterface", "- Eeprom backup not supported"); }
if (errors.test(UNKNOWN_ERROR)) { errorsList << QT_TRANSLATE_NOOP("EepromInterface", "- Something that couldn't be guessed, sorry"); }
if (errors.test(HAS_WARNINGS)) {
errorsList << QT_TRANSLATE_NOOP("EepromInterface", "Warning:");
if (errors.test(WARNING_WRONG_FIRMWARE)) { errorsList << QT_TRANSLATE_NOOP("EepromInterface", "- Your radio probably uses a wrong firmware,\n eeprom size is 4096 but only the first 2048 are used"); }
}
return false;
QMessageBox msgBox(parent);
msgBox.setWindowTitle(title);
msgBox.setIcon(QMessageBox::Critical);
msgBox.setText(mainMessage);
msgBox.setInformativeText(errorsList.join("\n"));
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.exec();
}
bool LoadBackup(RadioData &radioData, uint8_t *eeprom, int size, int index)
void ShowEepromWarnings(QWidget *parent, const QString &title, unsigned long errorsFound)
{
std::bitset<NUM_ERRORS> errors((unsigned long long)errorsFound);
QStringList warningsList;
if (errors.test(WARNING_WRONG_FIRMWARE)) { warningsList << QT_TRANSLATE_NOOP("EepromInterface", "- Your radio probably uses a wrong firmware,\n eeprom size is 4096 but only the first 2048 are used"); }
QMessageBox msgBox(parent);
msgBox.setWindowTitle(title);
msgBox.setIcon(QMessageBox::Warning);
msgBox.setText(QT_TRANSLATE_NOOP("EepromInterface", "Warnings!"));
msgBox.setInformativeText(warningsList.join("\n"));
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.exec();
}
unsigned long LoadEeprom(RadioData &radioData, const uint8_t *eeprom, const int size)
{
std::bitset<NUM_ERRORS> errors;
foreach(EEPROMInterface *eepromInterface, eepromInterfaces) {
if (eepromInterface->loadBackup(radioData, eeprom, size, index))
return true;
std::bitset<NUM_ERRORS> result((unsigned long long)eepromInterface->load(radioData, eeprom, size));
if (result.test(NO_ERROR)) {
return result.to_ulong();
} else {
errors |= result;
}
}
return false;
if (errors.none()) {
errors.set(UNKNOWN_ERROR);
}
return errors.to_ulong();
}
unsigned long LoadBackup(RadioData &radioData, uint8_t *eeprom, int size, int index)
{
std::bitset<NUM_ERRORS> errors;
foreach(EEPROMInterface *eepromInterface, eepromInterfaces) {
std::bitset<NUM_ERRORS> result((unsigned long long)eepromInterface->loadBackup(radioData, eeprom, size, index));
if (result.test(NO_ERROR)) {
return result.to_ulong();
} else {
errors |= result;
}
}
if (errors.none()) {
errors.set(UNKNOWN_ERROR);
}
return errors.to_ulong();
}
bool LoadEepromXml(RadioData &radioData, QDomDocument &doc)
unsigned long LoadEepromXml(RadioData &radioData, QDomDocument &doc)
{
std::bitset<NUM_ERRORS> errors;
foreach(EEPROMInterface *eepromInterface, eepromInterfaces) {
if (eepromInterface->loadxml(radioData, doc))
return true;
std::bitset<NUM_ERRORS> result((unsigned long long)eepromInterface->loadxml(radioData, doc));
if (result.test(NO_ERROR)) {
return result.to_ulong();
} else {
errors |= result;
}
}
return false;
if (errors.none()) {
errors.set(UNKNOWN_ERROR);
}
return errors.to_ulong();
}
QString getBoardName(BoardEnum board)
+33 -6
View File
@@ -25,6 +25,8 @@
#include <QtXml>
#include <iostream>
#include <bitset>
#if __GNUC__
#define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__))
#else
@@ -1179,11 +1181,11 @@ class EEPROMInterface
inline BoardEnum getBoard() { return board; }
virtual bool load(RadioData &radioData, const uint8_t *eeprom, int size) = 0;
virtual unsigned long load(RadioData &radioData, const uint8_t *eeprom, int size) = 0;
virtual bool loadBackup(RadioData &radioData, uint8_t *eeprom, int esize, int index) = 0;
virtual unsigned long loadBackup(RadioData &radioData, uint8_t *eeprom, int esize, int index) = 0;
virtual bool loadxml(RadioData &radioData, QDomDocument &doc) = 0;
virtual unsigned long loadxml(RadioData &radioData, QDomDocument &doc) = 0;
virtual int save(uint8_t *eeprom, RadioData &radioData, uint32_t variant=0, uint8_t version=0) = 0;
@@ -1305,9 +1307,34 @@ void RegisterEepromInterfaces();
void UnregisterFirmwares();
void registerOpenTxFirmwares();
bool LoadBackup(RadioData &radioData, uint8_t *eeprom, int esize, int index);
bool LoadEeprom(RadioData &radioData, const uint8_t *eeprom, int size);
bool LoadEepromXml(RadioData &radioData, QDomDocument &doc);
enum EepromLoadErrors {
NO_ERROR,
UNKNOWN_ERROR,
UNSUPPORTED_NEWER_VERSION,
WRONG_SIZE,
WRONG_FILE_SYSTEM,
NOT_OPENTX,
NOT_TH9X,
NOT_GRUVIN9X,
NOT_ERSKY9X,
NOT_ER9X,
UNKNOWN_BOARD,
WRONG_BOARD,
BACKUP_NOT_SUPPORTED,
HAS_WARNINGS,
WARNING_WRONG_FIRMWARE,
NUM_ERRORS
};
void ShowEepromErrors(QWidget *parent, const QString &title, const QString &mainMessage, unsigned long errorsFound);
void ShowEepromWarnings(QWidget *parent, const QString &title, unsigned long errorsFound);
unsigned long LoadBackup(RadioData &radioData, uint8_t *eeprom, int esize, int index);
unsigned long LoadEeprom(RadioData &radioData, const uint8_t *eeprom, int size);
unsigned long LoadEepromXml(RadioData &radioData, QDomDocument &doc);
struct Option {
const char * name;
+31 -16
View File
@@ -1,6 +1,6 @@
/*
* Author - Bertrand Songis <bsongis@gmail.com>
*
*
* Based on th9x -> http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
@@ -89,14 +89,17 @@ inline void applyStickModeToModel(Er9xModelData & model, unsigned int mode)
model.swashCollectiveSource = applyStickMode(model.swashCollectiveSource, mode);
}
bool Er9xInterface::loadxml(RadioData &radioData, QDomDocument &doc)
unsigned long Er9xInterface::loadxml(RadioData &radioData, QDomDocument &doc)
{
std::cout << "trying er9x xml import... ";
std::bitset<NUM_ERRORS> errors;
Er9xGeneral er9xGeneral;
memset(&er9xGeneral,0,sizeof(er9xGeneral));
if(!loadGeneralDataXML(&doc, &er9xGeneral)) {
return false;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
} else {
radioData.generalSettings=er9xGeneral;
std::cout << "version " << (unsigned int)er9xGeneral.myVers << " ";
@@ -111,29 +114,35 @@ bool Er9xInterface::loadxml(RadioData &radioData, QDomDocument &doc)
}
}
std::cout << "ok\n";
return true;
errors.set(NO_ERROR);
return errors.to_ulong();
}
bool Er9xInterface::load(RadioData &radioData, const uint8_t *eeprom, int size)
unsigned long Er9xInterface::load(RadioData &radioData, const uint8_t *eeprom, int size)
{
std::cout << "trying er9x import... ";
std::bitset<NUM_ERRORS> errors;
if (size != getEEpromSize()) {
std::cout << "wrong size\n";
return false;
errors.set(WRONG_SIZE);
return errors.to_ulong();
}
if (!efile->EeFsOpen((uint8_t *)eeprom, size, BOARD_STOCK)) {
std::cout << "wrong file system\n";
return false;
errors.set(WRONG_FILE_SYSTEM);
return errors.to_ulong();
}
efile->openRd(FILE_GENERAL);
Er9xGeneral er9xGeneral;
if (efile->readRlc1((uint8_t*)&er9xGeneral, 1) != 1) {
std::cout << "no\n";
return false;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
std::cout << "version " << (unsigned int)er9xGeneral.myVers << " ";
@@ -151,16 +160,19 @@ bool Er9xInterface::load(RadioData &radioData, const uint8_t *eeprom, int size)
break;
default:
std::cout << "not er9x\n";
return false;
errors.set(NOT_ER9X);
return errors.to_ulong();
}
efile->openRd(FILE_GENERAL);
if (!efile->readRlc1((uint8_t*)&er9xGeneral, sizeof(Er9xGeneral))) {
std::cout << "ko\n";
return false;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
radioData.generalSettings = er9xGeneral;
for (int i=0; i<getMaxModels(); i++) {
Er9xModelData er9xModel;
efile->openRd(FILE_MODEL(i));
@@ -170,16 +182,19 @@ bool Er9xInterface::load(RadioData &radioData, const uint8_t *eeprom, int size)
else {
applyStickModeToModel(er9xModel, radioData.generalSettings.stickMode+1);
radioData.models[i] = er9xModel;
}
}
}
std::cout << "ok\n";
return true;
errors.set(NO_ERROR);
return errors.to_ulong();
}
bool Er9xInterface::loadBackup(RadioData &radioData, uint8_t *eeprom, int esize, int index)
unsigned long Er9xInterface::loadBackup(RadioData &radioData, uint8_t *eeprom, int esize, int index)
{
return false;
std::bitset<NUM_ERRORS> errors;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
int Er9xInterface::save(uint8_t *eeprom, RadioData &radioData, uint32_t variant, uint8_t version)
+13 -13
View File
@@ -1,6 +1,6 @@
/*
* Author - Bertrand Songis <bsongis@gmail.com>
*
*
* Based on th9x -> http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
@@ -29,21 +29,21 @@ class Er9xInterface : public EEPROMInterface
virtual ~Er9xInterface();
virtual const char * getName();
virtual const int getEEpromSize();
virtual const int getMaxModels();
virtual bool load(RadioData &, const uint8_t * eeprom, int size);
virtual unsigned long load(RadioData &, const uint8_t * eeprom, int size);
virtual bool loadBackup(RadioData &, uint8_t * eeprom, int esize, int index);
virtual bool loadxml(RadioData &radioData, QDomDocument &doc);
virtual unsigned long loadBackup(RadioData &, uint8_t * eeprom, int esize, int index);
virtual unsigned long loadxml(RadioData &radioData, QDomDocument &doc);
virtual int save(uint8_t * eeprom, RadioData & radioData, uint32_t variant=0, uint8_t version=0);
virtual int getSize(ModelData &);
virtual int getSize(GeneralSettings &settings);
virtual int isAvailable(Protocol proto, int port=0);
@@ -54,17 +54,17 @@ class Er9xInterface : public EEPROMInterface
private:
void appendTextElement(QDomDocument * qdoc, QDomElement * pe, QString name, QString value);
void appendNumberElement(QDomDocument * qdoc, QDomElement * pe,QString name, int value, bool forceZeroWrite = false);
void appendCDATAElement(QDomDocument * qdoc, QDomElement * pe,QString name, const char * data, int size);
QDomElement getGeneralDataXML(QDomDocument * qdoc, Er9xGeneral * tgen); //parse out data to XML format
QDomElement getModelDataXML(QDomDocument * qdoc, Er9xModelData * tmod, int modelNum, int mdver); //parse out data to XML format
bool loadGeneralDataXML(QDomDocument * qdoc, Er9xGeneral * tgen); // get data from XML
bool loadModelDataXML(QDomDocument * qdoc, Er9xModelData * tmod, int modelNum = -1); // get data from XML
};
@@ -1,6 +1,6 @@
/*
* Author - Bertrand Songis <bsongis@gmail.com>
*
*
* Based on th9x -> http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
@@ -15,7 +15,6 @@
*/
#include <iostream>
#include <QMessageBox>
#include "ersky9xinterface.h"
#include "ersky9xeeprom.h"
#include "ersky9xsimulator.h"
@@ -120,14 +119,17 @@ inline void applyStickModeToModel(Ersky9xModelData_v11 & model, unsigned int mod
model.swashCollectiveSource = applyStickMode(model.swashCollectiveSource, mode);
}
bool Ersky9xInterface::loadxml(RadioData &radioData, QDomDocument &doc)
unsigned long Ersky9xInterface::loadxml(RadioData &radioData, QDomDocument &doc)
{
std::cout << "trying ersky9x xml import... ";
std::bitset<NUM_ERRORS> errors;
Ersky9xGeneral ersky9xGeneral;
memset(&ersky9xGeneral,0,sizeof(ersky9xGeneral));
if(!loadGeneralDataXML(&doc, &ersky9xGeneral)) {
return false;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
else {
radioData.generalSettings=ersky9xGeneral;
@@ -137,40 +139,48 @@ bool Ersky9xInterface::loadxml(RadioData &radioData, QDomDocument &doc)
if (ersky9xGeneral.myVers == 10) {
if (!loadModelDataXML<Ersky9xModelData_v10>(&doc, &radioData.models[i], i, radioData.generalSettings.stickMode+1)) {
std::cout << "ko\n";
return false;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
}
else {
if (!loadModelDataXML<Ersky9xModelData_v11>(&doc, &radioData.models[i], i, radioData.generalSettings.stickMode+1)) {
std::cout << "ko\n";
return false;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
}
}
std::cout << "ok\n";
return true;
errors.set(NO_ERROR);
return errors.to_ulong();
}
bool Ersky9xInterface::load(RadioData &radioData, const uint8_t *eeprom, int size)
unsigned long Ersky9xInterface::load(RadioData &radioData, const uint8_t *eeprom, int size)
{
std::cout << "trying ersky9x import... ";
std::bitset<NUM_ERRORS> errors;
if (size != EESIZE_SKY9X) {
std::cout << "wrong size\n";
return false;
errors.set(WRONG_SIZE);
return errors.to_ulong();
}
if (!efile->EeFsOpen((uint8_t *)eeprom, size, BOARD_SKY9X)) {
std::cout << "wrong file system\n";
return false;
errors.set(WRONG_FILE_SYSTEM);
return errors.to_ulong();
}
efile->openRd(FILE_GENERAL);
Ersky9xGeneral ersky9xGeneral;
if (efile->readRlc2((uint8_t*)&ersky9xGeneral, 1) != 1) {
std::cout << "no\n";
return false;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
std::cout << "version " << (unsigned int)ersky9xGeneral.myVers << " ";
@@ -182,21 +192,23 @@ bool Ersky9xInterface::load(RadioData &radioData, const uint8_t *eeprom, int siz
break;
default:
std::cout << "not ersky9x\n";
return false;
errors.set(NOT_ERSKY9X);
return errors.to_ulong();
}
efile->openRd(FILE_GENERAL);
if (!efile->readRlc2((uint8_t*)&ersky9xGeneral, sizeof(Ersky9xGeneral))) {
std::cout << "ko\n";
return false;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
radioData.generalSettings = ersky9xGeneral;
for (int i=0; i<getMaxModels(); i++) {
uint8_t buffer[4096];
uint size;
memset(buffer,0,sizeof(buffer));
efile->openRd(FILE_MODEL(i));
// if (!efile->readRlc2((uint8_t*)&ersky9xModel, sizeof(Ersky9xModelData))) {
size=efile->readRlc2(buffer, 4096);
if (!size) {
@@ -214,16 +226,19 @@ bool Ersky9xInterface::load(RadioData &radioData, const uint8_t *eeprom, int siz
applyStickModeToModel(ersky9xModel, radioData.generalSettings.stickMode+1);
radioData.models[i] = ersky9xModel;
}
}
}
}
std::cout << "ok\n";
return true;
errors.set(NO_ERROR);
return errors.to_ulong();
}
bool Ersky9xInterface::loadBackup(RadioData &radioData, uint8_t *eeprom, int esize, int index)
unsigned long Ersky9xInterface::loadBackup(RadioData &radioData, uint8_t *eeprom, int esize, int index)
{
return false;
std::bitset<NUM_ERRORS> errors;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
int Ersky9xInterface::save(uint8_t *eeprom, RadioData &radioData, uint32_t variant, uint8_t version)
@@ -1,6 +1,6 @@
/*
* Author - Bertrand Songis <bsongis@gmail.com>
*
*
* Based on th9x -> http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
@@ -29,21 +29,21 @@ class Ersky9xInterface : public EEPROMInterface
virtual ~Ersky9xInterface();
virtual const char * getName();
virtual const int getEEpromSize();
virtual const int getMaxModels();
virtual bool load(RadioData &, const uint8_t * eeprom, int size);
virtual unsigned long load(RadioData &, const uint8_t * eeprom, int size);
virtual bool loadBackup(RadioData &, uint8_t * eeprom, int esize, int index);
virtual unsigned long loadBackup(RadioData &, uint8_t * eeprom, int esize, int index);
virtual bool loadxml(RadioData &radioData, QDomDocument &doc);
virtual unsigned long loadxml(RadioData &radioData, QDomDocument &doc);
virtual int save(uint8_t * eeprom, RadioData & radioData, uint32_t variant=0, uint8_t version=0);
virtual int getSize(ModelData &);
virtual int getSize(GeneralSettings &settings);
virtual int isAvailable(Protocol proto, int port=0);
@@ -54,17 +54,17 @@ class Ersky9xInterface : public EEPROMInterface
private:
void appendTextElement(QDomDocument * qdoc, QDomElement * pe, QString name, QString value);
void appendNumberElement(QDomDocument * qdoc, QDomElement * pe,QString name, int value, bool forceZeroWrite = false);
void appendCDATAElement(QDomDocument * qdoc, QDomElement * pe,QString name, const char * data, int size);
QDomElement getGeneralDataXML(QDomDocument * qdoc, Ersky9xGeneral * tgen); //parse out data to XML format
QDomElement getModelDataXML(QDomDocument * qdoc, Ersky9xModelData_v11 * tmod, int modelNum, int mdver); //parse out data to XML format
bool loadGeneralDataXML(QDomDocument * qdoc, Ersky9xGeneral * tgen); // get data from XML
template <class T>
bool loadModelDataXML(QDomDocument * qdoc, ModelData * model, int modelNum, int stickMode); // get data from XML
@@ -1,6 +1,6 @@
/*
* Author - Bertrand Songis <bsongis@gmail.com>
*
*
* Based on th9x -> http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
@@ -93,24 +93,30 @@ bool Gruvin9xInterface::loadGeneral(GeneralSettings &settings, int version)
return false;
}
bool Gruvin9xInterface::loadxml(RadioData &radioData, QDomDocument &doc)
unsigned long Gruvin9xInterface::loadxml(RadioData &radioData, QDomDocument &doc)
{
return false;
std::bitset<NUM_ERRORS> errors;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
bool Gruvin9xInterface::load(RadioData &radioData, const uint8_t *eeprom, int size)
unsigned long Gruvin9xInterface::load(RadioData &radioData, const uint8_t *eeprom, int size)
{
std::cout << "trying " << getName() << " import... ";
std::bitset<NUM_ERRORS> errors;
if (size != this->getEEpromSize()) {
std::cout << "wrong size\n";
return false;
errors.set(WRONG_SIZE);
return errors.to_ulong();
}
if (!efile->EeFsOpen((uint8_t *)eeprom, size, BOARD_STOCK)) {
std::cout << "wrong file system\n";
return false;
errors.set(WRONG_FILE_SYSTEM);
return errors.to_ulong();
}
efile->openRd(FILE_GENERAL);
@@ -118,14 +124,16 @@ bool Gruvin9xInterface::load(RadioData &radioData, const uint8_t *eeprom, int si
uint8_t version;
if (efile->readRlc2(&version, 1) != 1) {
std::cout << "no\n";
return false;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
if (version == 0) {
efile->openRd(FILE_GENERAL);
if (efile->readRlc1(&version, 1) != 1) {
std::cout << "no\n";
return false;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
}
@@ -145,27 +153,35 @@ bool Gruvin9xInterface::load(RadioData &radioData, const uint8_t *eeprom, int si
break;
default:
std::cout << "not gruvin9x\n";
return false;
errors.set(NOT_GRUVIN9X);
return errors.to_ulong();
}
efile->openRd(FILE_GENERAL);
if (version == 5) {
if (!loadGeneral<Gruvin9xGeneral_v103>(radioData.generalSettings, 1))
return false;
if (!loadGeneral<Gruvin9xGeneral_v103>(radioData.generalSettings, 1)) {
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
}
else if (version < 104) {
if (!loadGeneral<Gruvin9xGeneral_v103>(radioData.generalSettings))
return false;
if (!loadGeneral<Gruvin9xGeneral_v103>(radioData.generalSettings)) {
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
}
else if (version <= 106) {
if (!loadGeneral<Gruvin9xGeneral_v104>(radioData.generalSettings))
return false;
if (!loadGeneral<Gruvin9xGeneral_v104>(radioData.generalSettings)) {
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
}
else {
std::cout << "ko\n";
return false;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
for (int i=0; i<getMaxModels(); i++) {
efile->openRd(FILE_MODEL(i));
if (version == 5) {
@@ -185,17 +201,21 @@ bool Gruvin9xInterface::load(RadioData &radioData, const uint8_t *eeprom, int si
}
else {
std::cout << "ko\n";
return false;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
}
std::cout << "ok\n";
return true;
errors.set(NO_ERROR);
return errors.to_ulong();
}
bool Gruvin9xInterface::loadBackup(RadioData &radioData, uint8_t *eeprom, int esize, int index)
unsigned long Gruvin9xInterface::loadBackup(RadioData &radioData, uint8_t *eeprom, int esize, int index)
{
return false;
std::bitset<NUM_ERRORS> errors;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
int Gruvin9xInterface::save(uint8_t *eeprom, RadioData &radioData, uint32_t variant, uint8_t version)
@@ -1,6 +1,6 @@
/*
* Author - Bertrand Songis <bsongis@gmail.com>
*
*
* Based on th9x -> http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
@@ -30,21 +30,21 @@ class Gruvin9xInterface : public EEPROMInterface
virtual ~Gruvin9xInterface();
virtual const char * getName();
virtual const int getEEpromSize();
virtual const int getMaxModels();
virtual bool load(RadioData &, const uint8_t *eeprom, int size);
virtual unsigned long load(RadioData &, const uint8_t *eeprom, int size);
virtual bool loadBackup(RadioData &, uint8_t *eeprom,int esize, int index);
virtual bool loadxml(RadioData &radioData, QDomDocument &doc);
virtual unsigned long loadBackup(RadioData &, uint8_t *eeprom,int esize, int index);
virtual unsigned long loadxml(RadioData &radioData, QDomDocument &doc);
virtual int save(uint8_t *eeprom, RadioData &radioData, uint32_t variant=0, uint8_t version=0);
virtual int getSize(ModelData &);
virtual int getSize(GeneralSettings &settings);
virtual int isAvailable(Protocol proto, int port=0);
@@ -183,7 +183,7 @@ void Open9xSky9xSimulator::start(QByteArray & eeprom, bool tests)
g_rotenc[0] = 0;
memcpy(Open9xSky9x::eeprom, eeprom.data(), std::min<int>(sizeof(Open9xSky9x::eeprom), eeprom.size()));
StartEepromThread(NULL);
StartAudioThread();
StartAudioThread(g.profile[g.id()].volumeGain());
StartMainThread(tests);
}
@@ -191,7 +191,7 @@ void Open9xSky9xSimulator::start(const char * filename, bool tests)
{
g_rotenc[0] = 0;
StartEepromThread(filename);
StartAudioThread();
StartAudioThread(g.profile[g.id()].volumeGain());
StartMainThread(tests);
}
@@ -57,6 +57,7 @@
#define OVERRIDE_CHANNEL_FUNCTION
#define NUM_POTS 5
#define FLAVOUR "taranis-plus"
#define MIXERS_MONITOR
#undef min
#undef max
@@ -223,14 +224,14 @@ void OpentxTaranisSimulator::start(QByteArray & eeprom, bool tests)
{
memcpy(Open9xX9D::eeprom, eeprom.data(), std::min<int>(sizeof(Open9xX9D::eeprom), eeprom.size()));
StartEepromThread(NULL);
StartAudioThread();
StartAudioThread(g.profile[g.id()].volumeGain());
StartMainThread(tests);
}
void OpentxTaranisSimulator::start(const char * filename, bool tests)
{
StartEepromThread(filename);
StartAudioThread();
StartAudioThread(g.profile[g.id()].volumeGain());
StartMainThread(tests);
}
@@ -300,15 +300,19 @@ bool OpenTxEepromInterface::saveModel(unsigned int index, ModelData &model, unsi
return (sz == eeprom.size());
}
bool OpenTxEepromInterface::loadxml(RadioData &radioData, QDomDocument &doc)
unsigned long OpenTxEepromInterface::loadxml(RadioData &radioData, QDomDocument &doc)
{
return false;
std::bitset<NUM_ERRORS> errors;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
bool OpenTxEepromInterface::load(RadioData &radioData, const uint8_t *eeprom, int size)
unsigned long OpenTxEepromInterface::load(RadioData &radioData, const uint8_t *eeprom, int size)
{
std::cout << "trying " << getName() << " import...";
std::bitset<NUM_ERRORS> errors;
if (size != getEEpromSize()) {
if (size==4096) {
int notnull=false;
@@ -319,21 +323,25 @@ bool OpenTxEepromInterface::load(RadioData &radioData, const uint8_t *eeprom, in
}
if (notnull) {
std::cout << " wrong size (" << size << ")\n";
return false;
errors.set(WRONG_SIZE);
return errors.to_ulong();
}
else {
QMessageBox::warning(NULL, "companion", QObject::tr("Your radio probably uses a wrong firmware,\n eeprom size is 4096 but only the first 2048 are used"));
errors.set(HAS_WARNINGS);
errors.set(WARNING_WRONG_FIRMWARE);
size=2048;
}
} else {
std::cout << " wrong size (" << size << ")\n";
return false;
errors.set(WRONG_SIZE);
return errors.to_ulong();
}
}
if (!efile->EeFsOpen((uint8_t *)eeprom, size, board)) {
std::cout << " wrong file system\n";
return false;
errors.set(WRONG_FILE_SYSTEM);
return errors.to_ulong();
}
efile->openRd(FILE_GENERAL);
@@ -341,30 +349,36 @@ bool OpenTxEepromInterface::load(RadioData &radioData, const uint8_t *eeprom, in
uint8_t version;
if (efile->readRlc2(&version, 1) != 1) {
std::cout << " no\n";
return false;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
std::cout << " version " << (unsigned int)version;
if (!checkVersion(version)) {
EepromLoadErrors version_error = checkVersion(version);
if (version_error != NO_ERROR) {
std::cout << " not open9x\n";
return false;
errors.set(version_error);
return errors.to_ulong();
}
if (!loadGeneral<OpenTxGeneralData>(radioData.generalSettings, version)) {
std::cout << " ko\n";
return false;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
std::cout << " variant " << radioData.generalSettings.variant;
for (int i=0; i<getMaxModels(); i++) {
if (!loadModel(version, radioData.models[i], NULL, i, radioData.generalSettings.variant, radioData.generalSettings.stickMode+1)) {
std::cout << " ko\n";
return false;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
}
std::cout << " ok\n";
return true;
errors.set(NO_ERROR);
return errors.to_ulong();
}
int OpenTxEepromInterface::save(uint8_t *eeprom, RadioData &radioData, uint32_t variant, uint8_t version)
@@ -847,7 +861,7 @@ size_t getSizeA(T (&)[SIZE]) {
return SIZE;
}
bool OpenTxEepromInterface::checkVersion(unsigned int version)
EepromLoadErrors OpenTxEepromInterface::checkVersion(unsigned int version)
{
switch(version) {
case 201:
@@ -908,12 +922,13 @@ bool OpenTxEepromInterface::checkVersion(unsigned int version)
break;
case 217:
// 3 logical switches removed on M128 / gruvin9x boards
return UNSUPPORTED_NEWER_VERSION;
break;
default:
return false;
return NOT_OPENTX;
}
return true;
return NO_ERROR;
}
bool OpenTxEepromInterface::checkVariant(unsigned int version, unsigned int variant)
@@ -938,13 +953,16 @@ bool OpenTxEepromInterface::checkVariant(unsigned int version, unsigned int vari
}
}
bool OpenTxEepromInterface::loadBackup(RadioData &radioData, uint8_t *eeprom, int esize, int index)
unsigned long OpenTxEepromInterface::loadBackup(RadioData &radioData, uint8_t *eeprom, int esize, int index)
{
std::bitset<NUM_ERRORS> errors;
std::cout << "trying " << getName() << " backup import...";
if (esize < 8 || memcmp(eeprom, "o9x", 3) != 0) {
std::cout << " no\n";
return false;
errors.set(WRONG_SIZE);
return errors.to_ulong();
}
BoardEnum backupBoard = (BoardEnum)-1;
@@ -960,12 +978,14 @@ bool OpenTxEepromInterface::loadBackup(RadioData &radioData, uint8_t *eeprom, in
break;
default:
std::cout << " unknown board\n";
return false;
errors.set(UNKNOWN_BOARD);
return errors.to_ulong();
}
if (backupBoard != board) {
std::cout << " not right board\n";
return false;
errors.set(WRONG_BOARD);
return errors.to_ulong();
}
uint8_t version = eeprom[4];
@@ -975,29 +995,35 @@ bool OpenTxEepromInterface::loadBackup(RadioData &radioData, uint8_t *eeprom, in
std::cout << " version " << (unsigned int)version << " ";
if (!checkVersion(version)) {
EepromLoadErrors version_error = checkVersion(version);
if (version_error != NO_ERROR) {
std::cout << " not open9x\n";
return false;
errors.set(version_error);
return errors.to_ulong();
}
if (size > esize-8) {
std::cout << " wrong size\n";
return false;
errors.set(WRONG_SIZE);
return errors.to_ulong();
}
if (bcktype=='M') {
if (!loadModel(version, radioData.models[index], &eeprom[8], size, variant)) {
std::cout << " ko\n";
return false;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
}
else {
std::cout << " backup type not supported\n";
return false;
errors.set(BACKUP_NOT_SUPPORTED);
return errors.to_ulong();
}
std::cout << " ok\n";
return true;
errors.set(NO_ERROR);
return errors.to_ulong();
}
QString OpenTxFirmware::getFirmwareUrl()
@@ -1273,6 +1299,7 @@ void registerOpenTxFirmwares()
openTx->addOption("lua", QObject::tr("Support for Lua model scripts"));
openTx->addOption("nojoystick", QObject::tr("No Joystick emulation inside the FW (only Mass Storage as in the Bootloader)"));
openTx->addOption("mixersmon", QObject::tr("Adds mixers output view to the CHANNELS MONITOR screen, pressing [ENT] switches between the views"));
openTx->addOption("eu", QObject::tr("Removes D8 and LR12 FrSky protocols that are not legal for use anymore on radios sold after Jan 1st, 2015"));
addOpenTxCommonOptions(openTx);
firmwares.push_back(openTx);
@@ -1283,6 +1310,7 @@ void registerOpenTxFirmwares()
openTx->addOption("lua", QObject::tr("Support for Lua model scripts"));
openTx->addOption("nojoystick", QObject::tr("No Joystick emulation inside the FW (only Mass Storage as in the Bootloader)"));
openTx->addOption("mixersmon", QObject::tr("Adds mixers output view to the CHANNELS MONITOR screen, pressing [ENT] switches between the views"));
openTx->addOption("eu", QObject::tr("Removes D8 and LR12 FrSky protocols that are not legal for use anymore on radios sold after Jan 1st, 2015"));
addOpenTxCommonOptions(openTx);
firmwares.push_back(openTx);
@@ -1,6 +1,6 @@
/*
* Author - Bertrand Songis <bsongis@gmail.com>
*
*
* Based on th9x -> http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
@@ -34,25 +34,25 @@ class OpenTxEepromInterface : public EEPROMInterface
virtual const int getMaxModels();
virtual bool load(RadioData &, const uint8_t *eeprom, int size);
virtual unsigned long load(RadioData &, const uint8_t *eeprom, int size);
virtual bool loadBackup(RadioData &, uint8_t *eeprom, int esize, int index);
virtual bool loadxml(RadioData &radioData, QDomDocument &doc);
virtual unsigned long loadBackup(RadioData &, uint8_t *eeprom, int esize, int index);
virtual unsigned long loadxml(RadioData &radioData, QDomDocument &doc);
virtual int save(uint8_t *eeprom, RadioData &radioData, uint32_t variant=0, uint8_t version=0);
virtual int getSize(ModelData &);
virtual int getSize(GeneralSettings &);
virtual int isAvailable(Protocol proto, int port=0);
protected:
const char * getName();
bool checkVersion(unsigned int version);
EepromLoadErrors checkVersion(unsigned int version);
bool checkVariant(unsigned int version, unsigned int variant);
@@ -111,7 +111,7 @@ class OpenTxFirmware: public FirmwareInterface {
}
virtual FirmwareInterface * getFirmwareVariant(const QString & id);
virtual QString getStampUrl();
virtual QString getReleaseNotesUrl();
@@ -123,7 +123,7 @@ class OpenTxFirmware: public FirmwareInterface {
virtual bool isTelemetrySourceAvailable(int source);
virtual SimulatorInterface * getSimulator();
};
void registerOpenTxFirmwares();
+27 -15
View File
@@ -1,6 +1,6 @@
/*
* Author - Bertrand Songis <bsongis@gmail.com>
*
*
* Based on th9x -> http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
@@ -57,31 +57,38 @@ const int Th9xInterface::getMaxModels()
return 16;
}
bool Th9xInterface::loadxml(RadioData &radioData, QDomDocument &doc)
unsigned long Th9xInterface::loadxml(RadioData &radioData, QDomDocument &doc)
{
return false;
std::bitset<NUM_ERRORS> errors;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
bool Th9xInterface::load(RadioData &radioData, const uint8_t *eeprom, int size)
unsigned long Th9xInterface::load(RadioData &radioData, const uint8_t *eeprom, int size)
{
std::cout << "trying th9x import... ";
std::bitset<NUM_ERRORS> errors;
if (size != getEEpromSize()) {
std::cout << "wrong size\n";
return false;
errors.set(WRONG_SIZE);
return errors.to_ulong();
}
if (!efile->EeFsOpen((uint8_t *)eeprom, size, BOARD_STOCK)) {
std::cout << "wrong file system\n";
return false;
errors.set(WRONG_FILE_SYSTEM);
return errors.to_ulong();
}
efile->openRd(FILE_GENERAL);
Th9xGeneral th9xGeneral;
if (efile->readRlc2((uint8_t*)&th9xGeneral, 1) != 1) {
std::cout << "no\n";
return false;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
std::cout << "version " << (unsigned int)th9xGeneral.myVers << " ";
@@ -91,17 +98,19 @@ bool Th9xInterface::load(RadioData &radioData, const uint8_t *eeprom, int size)
break;
default:
std::cout << "not th9x\n";
return false;
errors.set(NOT_TH9X);
return errors.to_ulong();
}
efile->openRd(FILE_GENERAL);
int len = efile->readRlc2((uint8_t*)&th9xGeneral, sizeof(Th9xGeneral));
if (len != sizeof(Th9xGeneral)) {
std::cout << "not th9x\n";
return false;
errors.set(NOT_TH9X);
return errors.to_ulong();
}
radioData.generalSettings = th9xGeneral;
for (int i=0; i<getMaxModels(); i++) {
Th9xModelData th9xModel;
efile->openRd(FILE_MODEL(i));
@@ -110,16 +119,19 @@ bool Th9xInterface::load(RadioData &radioData, const uint8_t *eeprom, int size)
}
else {
radioData.models[i] = th9xModel;
}
}
}
std::cout << "ok\n";
return true;
errors.set(NO_ERROR);
return errors.to_ulong();
}
bool Th9xInterface::loadBackup(RadioData &radioData, uint8_t *eeprom, int esize, int index)
unsigned long Th9xInterface::loadBackup(RadioData &radioData, uint8_t *eeprom, int esize, int index)
{
return false;
std::bitset<NUM_ERRORS> errors;
errors.set(UNKNOWN_ERROR);
return errors.to_ulong();
}
int Th9xInterface::save(uint8_t *eeprom, RadioData &radioData, uint32_t variant, uint8_t version)
+4 -4
View File
@@ -1,6 +1,6 @@
/*
* Author - Bertrand Songis <bsongis@gmail.com>
*
*
* Based on th9x -> http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
@@ -34,11 +34,11 @@ class Th9xInterface : public EEPROMInterface
virtual const int getMaxModels();
virtual bool load(RadioData &, const uint8_t *eeprom, int size);
virtual unsigned long load(RadioData &, const uint8_t *eeprom, int size);
virtual bool loadBackup(RadioData &, uint8_t *eeprom, int esize, int index);
virtual unsigned long loadBackup(RadioData &, uint8_t *eeprom, int esize, int index);
virtual bool loadxml(RadioData &radioData, QDomDocument &doc);
virtual unsigned long loadxml(RadioData &radioData, QDomDocument &doc);
virtual int save(uint8_t *eeprom, RadioData &radioData, uint32_t variant=0, uint8_t version=0);
+52
View File
@@ -1097,3 +1097,55 @@ bool caseInsensitiveLessThan(const QString &s1, const QString &s2)
{
return s1.toLower() < s2.toLower();
}
bool GpsGlitchFilter::isGlitch(double latitude, double longitude)
{
if ((fabs(latitude) < 0.1) && (fabs(longitude) < 0.1)) {
return true;
}
if (lastValid) {
if (fabs(latitude - lastLat) > 0.01) {
// qDebug() << "GpsGlitchFilter(): latitude glitch " << latitude << lastLat;
if ( ++glitchCount < 10) {
return true;
}
}
if (fabs(longitude - lastLon) > 0.01) {
// qDebug() << "GpsGlitchFilter(): longitude glitch " << longitude << lastLon;
if ( ++glitchCount < 10) {
return true;
}
}
}
lastLat = latitude;
lastLon = longitude;
lastValid = true;
glitchCount = 0;
return false;
}
bool GpsLatLonFilter::isValid(const QString & latitude, const QString & longitude)
{
if (lastLat == latitude) {
return false;
}
if (lastLon == longitude) {
return false;
}
lastLat = latitude;
lastLon = longitude;
return true;
}
double toDecimalCoordinate(const QString & value)
{
if (value.isEmpty()) return 0.0;
double temp = int(value.left(value.length()-1).toDouble() / 100);
double result = temp + (value.left(value.length() - 1).toDouble() - temp * 100) / 60.0;
QChar direction = value.at(value.size()-1);
if ((direction == 'S') || (direction == 'W')) {
result = -result;
}
return result;
}
+27
View File
@@ -162,4 +162,31 @@ QSet<QString> getFilesSet(const QString &path, const QStringList &filter, int ma
bool caseInsensitiveLessThan(const QString &s1, const QString &s2);
class GpsGlitchFilter
{
public:
GpsGlitchFilter() : lastValid(false), glitchCount(0) {};
bool isGlitch(double latitude, double longitude);
private:
bool lastValid;
int glitchCount;
double lastLat;
double lastLon;
};
class GpsLatLonFilter
{
public:
GpsLatLonFilter() {};
bool isValid(const QString & latitude, const QString & longitude);
private:
QString lastLat;
QString lastLon;
};
double toDecimalCoordinate(const QString & value);
#endif // HELPERS_H
+358 -197
View File
@@ -46,19 +46,35 @@ logsDialog::logsDialog(QWidget *parent) :
ui->customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom |
QCP::iSelectAxes | QCP::iSelectLegend | QCP::iSelectPlottables);
ui->customPlot->xAxis->setLabel(tr("Time (hh:mm:ss)"));
ui->customPlot->xAxis->setTickLabelType(QCPAxis::ltDateTime);
ui->customPlot->xAxis->setDateTimeFormat("hh:mm:ss");
axisRect = ui->customPlot->axisRect();
axisRect->axis(QCPAxis::atBottom)->setLabel(tr("Time (hh:mm:ss)"));
axisRect->axis(QCPAxis::atBottom)->setTickLabelType(QCPAxis::ltDateTime);
axisRect->axis(QCPAxis::atBottom)->setDateTimeFormat("hh:mm:ss");
QDateTime now = QDateTime::currentDateTime();
ui->customPlot->xAxis->setRange(now.addSecs(-60*60*2).toTime_t(),
axisRect->axis(QCPAxis::atBottom)->setRange(now.addSecs(-60*60*2).toTime_t(),
now.toTime_t());
ui->customPlot->yAxis->setTickLabels(false);
axisRect->axis(QCPAxis::atLeft)->setTickLabels(false);
axisRect->addAxis(QCPAxis::atLeft);
axisRect->addAxis(QCPAxis::atRight);
axisRect->axis(QCPAxis::atLeft, 1)->setVisible(false);
axisRect->axis(QCPAxis::atRight, 1)->setVisible(false);
QFont legendFont = font();
legendFont.setPointSize(10);
ui->customPlot->legend->setFont(legendFont);
ui->customPlot->legend->setSelectedFont(legendFont);
axisRect->insetLayout()->setInsetAlignment(0, Qt::AlignTop | Qt::AlignLeft);
rightLegend = new QCPLegend;
axisRect->insetLayout()->addElement(rightLegend, Qt::AlignTop | Qt::AlignRight);
rightLegend->setLayer("legend");
rightLegend->setFont(legendFont);
rightLegend->setSelectedFont(legendFont);
rightLegend->setVisible(false);
ui->customPlot->setAutoAddPlottableToLegend(false);
QString Path=g.gePath();
if (Path.isEmpty() || !QFile(Path).exists()) {
@@ -72,7 +88,7 @@ logsDialog::logsDialog(QWidget *parent) :
connect(ui->customPlot, SIGNAL(mouseWheel(QWheelEvent*)), this, SLOT(mouseWheel()));
// make left axes transfer its range to right axes:
connect(ui->customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(setRangeyAxis2(QCPRange)));
connect(axisRect->axis(QCPAxis::atLeft), SIGNAL(rangeChanged(QCPRange)), this, SLOT(yAxisChangeRanges(QCPRange)));
// connect some interaction slots:
connect(ui->customPlot, SIGNAL(titleDoubleClick(QMouseEvent*, QCPPlotTitle*)), this, SLOT(titleDoubleClick(QMouseEvent*, QCPPlotTitle*)));
@@ -151,24 +167,43 @@ void logsDialog::selectionChanged()
if (plotLock) return;
// handle bottom axis and tick labels as one selectable object:
if (ui->customPlot->xAxis->selectedParts().testFlag(QCPAxis::spAxis) ||
ui->customPlot->xAxis->selectedParts().testFlag(QCPAxis::spTickLabels))
if (axisRect->axis(QCPAxis::atBottom)->selectedParts().testFlag(QCPAxis::spAxis) ||
axisRect->axis(QCPAxis::atBottom)->selectedParts().testFlag(QCPAxis::spTickLabels))
{
ui->customPlot->xAxis->setSelectedParts(QCPAxis::spAxis |
axisRect->axis(QCPAxis::atBottom)->setSelectedParts(QCPAxis::spAxis |
QCPAxis::spTickLabels);
}
// make left and right axes be selected synchronously,
// and handle axis and tick labels as one selectable object:
if (ui->customPlot->yAxis->selectedParts().testFlag(QCPAxis::spAxis) ||
ui->customPlot->yAxis->selectedParts().testFlag(QCPAxis::spTickLabels) ||
ui->customPlot->yAxis2->selectedParts().testFlag(QCPAxis::spAxis) ||
ui->customPlot->yAxis2->selectedParts().testFlag(QCPAxis::spTickLabels))
{
ui->customPlot->yAxis->setSelectedParts(QCPAxis::spAxis |
if (axisRect->axis(QCPAxis::atLeft)->selectedParts().testFlag(QCPAxis::spAxis) ||
axisRect->axis(QCPAxis::atLeft)->selectedParts().testFlag(QCPAxis::spTickLabels) ||
(
axisRect->axis(QCPAxis::atRight)->visible() &&
(axisRect->axis(QCPAxis::atRight)->selectedParts().testFlag(QCPAxis::spAxis) ||
axisRect->axis(QCPAxis::atRight)->selectedParts().testFlag(QCPAxis::spTickLabels))
) || (
axisRect->axis(QCPAxis::atLeft, 1)->visible() &&
(axisRect->axis(QCPAxis::atLeft, 1)->selectedParts().testFlag(QCPAxis::spAxis) ||
axisRect->axis(QCPAxis::atLeft, 1)->selectedParts().testFlag(QCPAxis::spTickLabels))
) || (
axisRect->axis(QCPAxis::atRight)->visible() &&
(axisRect->axis(QCPAxis::atRight, 1)->selectedParts().testFlag(QCPAxis::spAxis) ||
axisRect->axis(QCPAxis::atRight, 1)->selectedParts().testFlag(QCPAxis::spTickLabels))
)
) {
axisRect->axis(QCPAxis::atLeft)->setSelectedParts(QCPAxis::spAxis |
QCPAxis::spTickLabels);
if (hasyAxis2) {
ui->customPlot->yAxis2->setSelectedParts(QCPAxis::spAxis |
if (axisRect->axis(QCPAxis::atRight)->visible()) {
axisRect->axis(QCPAxis::atRight)->setSelectedParts(QCPAxis::spAxis |
QCPAxis::spTickLabels);
if (axisRect->axis(QCPAxis::atLeft, 1)->visible()) {
axisRect->axis(QCPAxis::atLeft, 1)->setSelectedParts(QCPAxis::spAxis |
QCPAxis::spTickLabels);
if (axisRect->axis(QCPAxis::atRight, 1)->visible()) {
axisRect->axis(QCPAxis::atRight, 1)->setSelectedParts(QCPAxis::spAxis |
QCPAxis::spTickLabels);
}
}
}
}
@@ -177,6 +212,7 @@ void logsDialog::selectionChanged()
{
QCPGraph *graph = ui->customPlot->graph(i);
QCPPlottableLegendItem *item = ui->customPlot->legend->itemWithPlottable(graph);
if (item == NULL) item = rightLegend->itemWithPlottable(graph);
if (item->selected() || graph->selected())
{
item->setSelected(true);
@@ -185,38 +221,88 @@ void logsDialog::selectionChanged()
}
}
void logsDialog::on_mapsButton_clicked()
QList<QStringList> logsDialog::filterGePoints(const QList<QStringList> & input)
{
int n = csvlog.count(); // number of points in graph
if (n==0) return;
int latcol=0, longcol=0, altcol=0, speedcol=0;
int itemSelected=0.;
bool rangeSelected=false;
ui->FieldsTW->setDisabled(true);
ui->logTable->setDisabled(true);
QList<QStringList> result;
QString gePath=g.gePath();
if (gePath.isEmpty() || !QFile(gePath).exists()) {
ui->FieldsTW->setDisabled(false);
ui->logTable->setDisabled(false);
return;
int n = input.count();
if (n == 0) {
return result;
}
QSet<int> nondataCols;
for (int i=1; i<csvlog.at(0).count(); i++) {
int latcol=0, longcol=0;
for (int i=1; i<input.at(0).count(); i++) {
//Long,Lat,Course,GPS Speed,GPS Alt
if (csvlog.at(0).at(i).contains("Long")) {
if (input.at(0).at(i).contains("Long")) {
longcol=i;
}
if (input.at(0).at(i).contains("Lat")) {
latcol=i;
}
}
if (longcol==0 || latcol==0) {
return result;
}
result.append(input.at(0));
bool rangeSelected = ui->logTable->selectionModel()->selectedRows().length() > 0;
GpsGlitchFilter glitchFilter;
GpsLatLonFilter latLonFilter;
for (int i = 1; i < n; i++) {
if ((ui->logTable->item(i-1, 1)->isSelected() && rangeSelected) || !rangeSelected) {
QString latitude = input.at(i).at(latcol).trimmed();
QString longitude = input.at(i).at(longcol).trimmed();
double flatitude = toDecimalCoordinate(latitude);
double flongitude = toDecimalCoordinate(longitude);
// glitch filter
if ( glitchFilter.isGlitch(flatitude, flongitude) ) {
qDebug() << "filterGePoints(): GPS glitch detected at" << i << flatitude << flongitude;
continue;
}
// lat long pair filter
if ( !latLonFilter.isValid(latitude, longitude) ) {
// qDebug() << "filterGePoints(): Lat-Lon pair wrong, skipping at" << i << latitude << longitude;
continue;
}
// qDebug() << "point " << latitude << longitude;
result.append(input.at(i));
}
}
qDebug() << "filterGePoints(): filtered from" << input.count() << "to " << result.count() << "points";
return result;
}
void logsDialog::exportToGoogleEarth()
{
// filter data points
QList<QStringList> dataPoints = filterGePoints(csvlog);
int n = dataPoints.count(); // number of points to export
if (n==0) return;
int latcol=0, longcol=0, altcol=0, speedcol=0;
QSet<int> nondataCols;
for (int i=1; i<dataPoints.at(0).count(); i++) {
//Long,Lat,Course,GPS Speed,GPS Alt
if (dataPoints.at(0).at(i).contains("Long")) {
longcol=i;
nondataCols << i;
}
if (csvlog.at(0).at(i).contains("Lat")) {
if (dataPoints.at(0).at(i).contains("Lat")) {
latcol=i;
nondataCols << i;
}
if (csvlog.at(0).at(i).contains("GPS Alt")) {
if (dataPoints.at(0).at(i).contains("GPS Alt")) {
altcol=i;
nondataCols << i;
}
if (csvlog.at(0).at(i).contains("GPS Speed")) {
if (dataPoints.at(0).at(i).contains("GPS Speed")) {
speedcol=i;
nondataCols << i;
}
@@ -224,15 +310,6 @@ void logsDialog::on_mapsButton_clicked()
if (longcol==0 || latcol==0 || altcol==0) {
return;
}
for (int i=1; i<n; i++) {
if (ui->logTable->item(i-1,1)->isSelected()) {
rangeSelected=true;
itemSelected++;
}
}
if (itemSelected==0) {
itemSelected=n-1;
}
QString geIconFilename = generateProcessUniqueTempFileName("track0.png");
if (QFile::exists(geIconFilename)) {
@@ -250,25 +327,25 @@ void logsDialog::on_mapsButton_clicked()
tr("Cannot write file %1:\n%2.")
.arg(geFilename)
.arg(geFile.errorString()));
ui->FieldsTW->setDisabled(false);
ui->logTable->setDisabled(false);
return;
}
QString latitude,longitude;
double flatitude, flongitude,temp;
QTextStream outputStream(&geFile);
// file header
outputStream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<kml xmlns=\"http://www.opengis.net/kml/2.2\" xmlns:gx=\"http://www.google.com/kml/ext/2.2\">\n";
outputStream << "\t<Document>\n\t\t<name>" << logFilename << "</name>\n";
outputStream << "\t\t<Style id=\"multiTrack_n\">\n\t\t\t<IconStyle>\n\t\t\t\t<Icon>\n\t\t\t\t\t<href>file://" << geIconFilename << "</href>\n\t\t\t\t</Icon>\n\t\t\t</IconStyle>\n\t\t\t<LineStyle>\n\t\t\t\t<color>991081f4</color>\n\t\t\t\t<width>6</width>\n\t\t\t</LineStyle>\n\t\t</Style>\n";
outputStream << "\t\t<Style id=\"multiTrack_h\">\n\t\t\t<IconStyle>\n\t\t\t\t<scale>0</scale>\n\t\t\t\t<Icon>\n\t\t\t\t\t<href>file://" << QDir::tempPath() << "/track0.png</href>\n\t\t\t\t</Icon>\n\t\t\t</IconStyle>\n\t\t\t<LineStyle>\n\t\t\t\t<color>991081f4</color>\n\t\t\t\t<width>8</width>\n\t\t\t</LineStyle>\n\t\t</Style>\n";
outputStream << "\t\t<Style id=\"multiTrack_h\">\n\t\t\t<IconStyle>\n\t\t\t\t<scale>0</scale>\n\t\t\t\t<Icon>\n\t\t\t\t\t<href>file://" << geIconFilename << "</href>\n\t\t\t\t</Icon>\n\t\t\t</IconStyle>\n\t\t\t<LineStyle>\n\t\t\t\t<color>991081f4</color>\n\t\t\t\t<width>8</width>\n\t\t\t</LineStyle>\n\t\t</Style>\n";
outputStream << "\t\t<StyleMap id=\"multiTrack\">\n\t\t\t<Pair>\n\t\t\t\t<key>normal</key>\n\t\t\t\t<styleUrl>#multiTrack_n</styleUrl>\n\t\t\t</Pair>\n\t\t\t<Pair>\n\t\t\t\t<key>highlight</key>\n\t\t\t\t<styleUrl>#multiTrack_h</styleUrl>\n\t\t\t</Pair>\n\t\t</StyleMap>\n";
outputStream << "\t\t<Style id=\"lineStyle\">\n\t\t\t<LineStyle>\n\t\t\t\t<color>991081f4</color>\n\t\t\t\t<width>6</width>\n\t\t\t</LineStyle>\n\t\t</Style>\n";
outputStream << "\t\t<Schema id=\"schema\">\n";
outputStream << "\t\t\t<gx:SimpleArrayField name=\"GPSSpeed\" type=\"float\">\n\t\t\t\t<displayName>GPS Speed</displayName>\n\t\t\t</gx:SimpleArrayField>\n";
// declare additional fields
for (int i=0; i<csvlog.at(0).count()-2; i++) {
for (int i=0; i<dataPoints.at(0).count()-2; i++) {
if (ui->FieldsTW->item(0,i)->isSelected() && !nondataCols.contains(i+2)) {
QString origName = csvlog.at(0).at(i+2);
QString origName = dataPoints.at(0).at(i+2);
QString safeName = origName;
safeName.replace(" ","_");
outputStream << "\t\t\t<gx:SimpleArrayField name=\""<< safeName <<"\" ";
@@ -276,7 +353,6 @@ void logsDialog::on_mapsButton_clicked()
outputStream << ">\n\t\t\t\t<displayName>" << origName << "</displayName>\n\t\t\t</gx:SimpleArrayField>\n";
}
}
outputStream << "\t\t</Schema>\n";
QString planeName;
if (logFilename.indexOf("-")>0) {
@@ -284,60 +360,55 @@ void logsDialog::on_mapsButton_clicked()
} else {
planeName=logFilename;
}
outputStream << "\t\t</Schema>\n";
outputStream << "\t\t<Folder>\n\t\t\t<name>Log Data</name>\n\t\t\t<Placemark>\n\t\t\t\t<name>" << planeName << "</name>";
outputStream << "\n\t\t\t\t<styleUrl>#multiTrack</styleUrl>";
outputStream << "\n\t\t\t\t<gx:Track>\n";
outputStream << "\n\t\t\t\t\t<altitudeMode>absolute</altitudeMode>\n";
// time data points
for (int i=1; i<n; i++) {
if ((ui->logTable->item(i-1,1)->isSelected() &&rangeSelected) || !rangeSelected) {
QString tstamp=csvlog.at(i).at(0)+QString("T")+csvlog.at(i).at(1)+QString("Z");
outputStream << "\t\t\t\t\t<when>"<< tstamp <<"</when>\n";
}
QString tstamp=dataPoints.at(i).at(0)+QString("T")+dataPoints.at(i).at(1)+QString("Z");
outputStream << "\t\t\t\t\t<when>"<< tstamp <<"</when>\n";
}
// coordinate data points
for (int i=1; i<n; i++) {
if ((ui->logTable->item(i-1,1)->isSelected() &&rangeSelected) || !rangeSelected) {
latitude=csvlog.at(i).at(latcol).trimmed();
longitude=csvlog.at(i).at(longcol).trimmed();
temp=int(latitude.left(latitude.length()-1).toDouble()/100);
flatitude=temp+(latitude.left(latitude.length()-1).toDouble()-temp*100)/60.0;
temp=int(longitude.left(longitude.length()-1).toDouble()/100);
flongitude=temp+(longitude.left(longitude.length()-1).toDouble()-temp*100)/60.0;
if (latitude.right(1)!="N") {
flatitude*=-1;
}
if (longitude.right(1)!="E") {
flongitude*=-1;
}
latitude.sprintf("%3.8f", flatitude);
longitude.sprintf("%3.8f", flongitude);
outputStream << "\t\t\t\t\t<gx:coord>" << longitude << " " << latitude << " " << csvlog.at(i).at(altcol).toFloat() << " </gx:coord>\n" ;
}
QString latitude=dataPoints.at(i).at(latcol).trimmed();
QString longitude=dataPoints.at(i).at(longcol).trimmed();
latitude.sprintf("%3.8f", toDecimalCoordinate(latitude));
longitude.sprintf("%3.8f", toDecimalCoordinate(longitude));
outputStream << "\t\t\t\t\t<gx:coord>" << longitude << " " << latitude << " " << dataPoints.at(i).at(altcol).toFloat() << " </gx:coord>\n" ;
}
// additional data for data points
outputStream << "\t\t\t\t\t<ExtendedData>\n\t\t\t\t\t\t<SchemaData schemaUrl=\"#schema\">\n";
// gps speed data points
outputStream << "\t\t\t\t\t\t\t<gx:SimpleArrayData name=\"GPSSpeed\">\n";
for (int i=1; i<n; i++) {
if ((ui->logTable->item(i-1,1)->isSelected() &&rangeSelected) || !rangeSelected) {
outputStream << "\t\t\t\t\t\t\t\t<gx:value>"<< csvlog.at(i).at(speedcol) <<"</gx:value>\n";
}
outputStream << "\t\t\t\t\t\t\t\t<gx:value>"<< dataPoints.at(i).at(speedcol) <<"</gx:value>\n";
}
outputStream << "\t\t\t\t\t\t\t</gx:SimpleArrayData>\n";
// add values for additional fields
for (int i=0; i<csvlog.at(0).count()-2; i++) {
for (int i=0; i<dataPoints.at(0).count()-2; i++) {
if (ui->FieldsTW->item(0,i)->isSelected() && !nondataCols.contains(i+2)) {
QString safeName = csvlog.at(0).at(i+2);;
QString safeName = dataPoints.at(0).at(i+2);;
safeName.replace(" ","_");
outputStream << "\t\t\t\t\t\t\t<gx:SimpleArrayData name=\""<< safeName <<"\">\n";
for (int j=1; j<n; j++) {
if ((ui->logTable->item(j-1,1)->isSelected() &&rangeSelected) || !rangeSelected) {
outputStream << "\t\t\t\t\t\t\t\t<gx:value>"<< csvlog.at(j).at(i+2) <<"</gx:value>\n";
}
outputStream << "\t\t\t\t\t\t\t\t<gx:value>"<< dataPoints.at(j).at(i+2) <<"</gx:value>\n";
}
outputStream << "\t\t\t\t\t\t\t</gx:SimpleArrayData>\n";
}
}
outputStream << "\t\t\t\t\t\t</SchemaData>\n\t\t\t\t\t</ExtendedData>\n\t\t\t\t</gx:Track>\n\t\t\t</Placemark>\n\t\t</Folder>\n\t</Document>\n</kml>";
geFile.close();
QString gePath = g.gePath();
QStringList parameters;
#ifdef __APPLE__
parameters << "-a";
@@ -347,22 +418,30 @@ void logsDialog::on_mapsButton_clicked()
parameters << geFilename;
QProcess *process = new QProcess(this);
process->start(gePath, parameters);
}
void logsDialog::on_mapsButton_clicked()
{
ui->FieldsTW->setDisabled(true);
ui->logTable->setDisabled(true);
exportToGoogleEarth();
ui->FieldsTW->setDisabled(false);
ui->logTable->setDisabled(false);
}
void logsDialog::mousePress()
{
// if an axis is selected, only allow the direction of that axis to be dragged
// if no axis is selected, both directions may be dragged
if (ui->customPlot->xAxis->selectedParts().testFlag(QCPAxis::spAxis))
ui->customPlot->axisRect()->setRangeDrag(ui->customPlot->xAxis->orientation());
else if (ui->customPlot->yAxis->selectedParts().testFlag(QCPAxis::spAxis))
ui->customPlot->axisRect()->setRangeDrag(ui->customPlot->yAxis->orientation());
if (axisRect->axis(QCPAxis::atBottom)->selectedParts().testFlag(QCPAxis::spAxis))
axisRect->setRangeDrag(axisRect->axis(QCPAxis::atBottom)->orientation());
else if (axisRect->axis(QCPAxis::atLeft)->selectedParts().testFlag(QCPAxis::spAxis))
axisRect->setRangeDrag(axisRect->axis(QCPAxis::atLeft)->orientation());
else
ui->customPlot->axisRect()->setRangeDrag(Qt::Horizontal | Qt::Vertical);
axisRect->setRangeDrag(Qt::Horizontal | Qt::Vertical);
}
void logsDialog::mouseWheel()
@@ -377,18 +456,9 @@ void logsDialog::mouseWheel()
orientation|=Qt::Vertical;
}
if (orientation) {
ui->customPlot->axisRect()->setRangeZoom((Qt::Orientation)orientation);
axisRect->setRangeZoom((Qt::Orientation)orientation);
} else {
ui->customPlot->axisRect()->setRangeZoom(Qt::Horizontal|Qt::Vertical);
}
}
void logsDialog::removeSelectedGraph()
{
if (ui->customPlot->selectedGraphs().size() > 0)
{
ui->customPlot->removeGraph(ui->customPlot->selectedGraphs().first());
ui->customPlot->replot();
axisRect->setRangeZoom(Qt::Horizontal|Qt::Vertical);
}
}
@@ -396,8 +466,17 @@ void logsDialog::removeAllGraphs()
{
ui->customPlot->clearGraphs();
ui->customPlot->legend->setVisible(false);
ui->customPlot->yAxis2->setVisible(false);
ui->customPlot->yAxis->setTickLabels(false);
rightLegend->clearItems();
rightLegend->setVisible(false);
axisRect->axis(QCPAxis::atRight)->setSelectedParts(QCPAxis::spNone);
axisRect->axis(QCPAxis::atRight)->setVisible(false);
axisRect->axis(QCPAxis::atLeft)->setSelectedParts(QCPAxis::spNone);
axisRect->axis(QCPAxis::atLeft)->setTickLabels(false);
axisRect->axis(QCPAxis::atLeft, 1)->setVisible(false);
axisRect->axis(QCPAxis::atLeft, 1)->setSelectedParts(QCPAxis::spNone);
axisRect->axis(QCPAxis::atRight, 1)->setVisible(false);
axisRect->axis(QCPAxis::atRight, 1)->setSelectedParts(QCPAxis::spNone);
axisRect->axis(QCPAxis::atBottom)->setSelectedParts(QCPAxis::spNone);
ui->customPlot->replot();
}
@@ -525,7 +604,6 @@ bool logsDialog::cvsFileParse()
return true;
}
void logsDialog::on_sessions_CB_currentIndexChanged(int index)
{
if (plotLock) return;
@@ -588,9 +666,9 @@ void logsDialog::plotLogs()
coords plotCoords;
int plotColumn = plot->row() + 2; // Date and Time first
plotCoords.min_y = 999999;
plotCoords.max_y = -999999;
plotCoords.secondRange = false;
plotCoords.min_y = INVALID_MIN;
plotCoords.max_y = INVALID_MAX;
plotCoords.yaxis = firstLeft;
plotCoords.name = plot->text();
for (int row = 0; row < rowCount; row++) {
@@ -612,11 +690,8 @@ void logsDialog::plotLogs()
y = logValue->text().toDouble();
plotCoords.y.push_back(y);
if (plotCoords.min_y > y) {
plotCoords.min_y = y;
} else if (plotCoords.max_y < y) {
plotCoords.max_y = y;
}
if (plotCoords.min_y > y) plotCoords.min_y = y;
if (plotCoords.max_y < y) plotCoords.max_y = y;
if (time_str.contains('.')) {
time = QDateTime::fromString(time_str, "yyyy-MM-dd HH:mm:ss.zzz")
@@ -628,133 +703,219 @@ void logsDialog::plotLogs()
}
plotCoords.x.push_back(time);
if (plots.min_x > time) {
plots.min_x = time;
} else if (plots.max_x < time) {
plots.max_x = time;
}
if (plots.min_x > time) plots.min_x = time;
if (plots.max_x < time) plots.max_x = time;
}
double range_inc = (plotCoords.max_y - plotCoords.min_y) / 100;
if (range_inc == 0) range_inc = 1;
plotCoords.max_y += range_inc;
plotCoords.min_y -= range_inc;
plots.coords.append(plotCoords);
}
plots.rangeOneMin = plots.coords.at(0).min_y;
plots.rangeOneMax = plots.coords.at(0).max_y;
plots.twoRanges = false;
yAxesRanges[firstLeft].min = plots.coords.at(0).min_y;
yAxesRanges[firstLeft].max = plots.coords.at(0).max_y;
for (int i = firstRight; i < AXES_LIMIT; i++) {
yAxesRanges[i].min = INVALID_MIN;
yAxesRanges[i].max = INVALID_MAX;
}
plots.tooManyRanges = false;
for (int i = 1; i < plots.coords.size(); i++) {
if (plots.tooManyRanges) {
if (plots.coords.at(i).min_y < plots.rangeOneMin) {
plots.rangeOneMin = plots.coords.at(i).min_y;
}
if (plots.coords.at(i).max_y > plots.rangeOneMax) {
plots.rangeOneMax = plots.coords.at(i).max_y;
}
continue;
}
double actualRange = plots.rangeOneMax - plots.rangeOneMin;
double actualRange = yAxesRanges[firstLeft].max - yAxesRanges[firstLeft].min;
double thisRange = plots.coords.at(i).max_y - plots.coords.at(i).min_y;
if (thisRange > actualRange * 1.3 || thisRange * 1.3 < actualRange ||
plots.coords.at(i).min_y > plots.rangeOneMax ||
plots.coords.at(i).max_y < plots.rangeOneMin) {
plots.coords[i].secondRange = true;
if (plots.twoRanges) {
actualRange = plots.rangeTwoMax - plots.rangeTwoMin;
if (thisRange > actualRange * 1.3 || thisRange * 1.3 < actualRange ||
plots.coords.at(i).min_y > plots.rangeTwoMax ||
plots.coords.at(i).max_y < plots.rangeTwoMin) {
while (yAxesRanges[plots.coords.at(i).yaxis].max != INVALID_MAX &&
(thisRange > actualRange * 1.3 || thisRange * 1.3 < actualRange ||
plots.coords.at(i).min_y > yAxesRanges[plots.coords.at(i).yaxis].max ||
plots.coords.at(i).max_y < yAxesRanges[plots.coords.at(i).yaxis].min)
) {
switch (plots.coords[i].yaxis) {
case firstLeft:
plots.coords[i].yaxis = firstRight;
break;
case firstRight:
plots.coords[i].yaxis = secondLeft;
break;
case secondLeft:
plots.coords[i].yaxis = secondRight;
break;
case secondRight:
plots.tooManyRanges = true;
plots.twoRanges = false;
if (plots.rangeTwoMin < plots.rangeOneMin) {
plots.rangeOneMin = plots.rangeTwoMin;
}
if (plots.rangeTwoMax > plots.rangeOneMax) {
plots.rangeOneMax = plots.rangeTwoMax;
}
if (plots.coords.at(i).min_y < plots.rangeOneMin) {
plots.rangeOneMin = plots.coords.at(i).min_y;
}
if (plots.coords.at(i).max_y > plots.rangeOneMax) {
plots.rangeOneMax = plots.coords.at(i).max_y;
}
} else {
if (plots.coords.at(i).min_y < plots.rangeTwoMin) {
plots.rangeTwoMin = plots.coords.at(i).min_y;
}
if (plots.coords.at(i).max_y > plots.rangeTwoMax) {
plots.rangeTwoMax = plots.coords.at(i).max_y;
}
}
} else {
plots.twoRanges = true;
plots.rangeTwoMax = plots.coords.at(i).max_y;
plots.rangeTwoMin = plots.coords.at(i).min_y;
break;
default:
break;
}
if (plots.tooManyRanges) break;
actualRange = yAxesRanges[plots.coords.at(i).yaxis].max
- yAxesRanges[plots.coords.at(i).yaxis].min;
}
if (plots.tooManyRanges) {
break;
} else {
if (plots.coords.at(i).min_y < plots.rangeOneMin) {
plots.rangeOneMin = plots.coords.at(i).min_y;
if (plots.coords.at(i).min_y < yAxesRanges[plots.coords.at(i).yaxis].min) {
yAxesRanges[plots.coords.at(i).yaxis].min = plots.coords.at(i).min_y;
}
if (plots.coords.at(i).max_y > plots.rangeOneMax) {
plots.rangeOneMax = plots.coords.at(i).max_y;
if (plots.coords.at(i).max_y > yAxesRanges[plots.coords.at(i).yaxis].max) {
yAxesRanges[plots.coords.at(i).yaxis].max = plots.coords.at(i).max_y;
}
}
}
if (plots.twoRanges) {
rangeRatio = (plots.rangeTwoMax - plots.rangeTwoMin) /
(plots.rangeOneMax - plots.rangeOneMin);
rangeyAxisMin = plots.rangeOneMin;
rangeyAxisMax = plots.rangeOneMax;
rangeyAxis2Min = plots.rangeTwoMin;
rangeyAxis2Max = plots.rangeTwoMax;
if (plots.tooManyRanges) {
yAxesRanges[firstLeft].max = 101;
yAxesRanges[firstLeft].min = -1;
yAxesRanges[firstRight].max = INVALID_MAX;
yAxesRanges[firstRight].min = INVALID_MIN;
yAxesRanges[secondLeft].max = INVALID_MAX;
yAxesRanges[secondLeft].min = INVALID_MIN;
yAxesRanges[secondRight].max = INVALID_MAX;
yAxesRanges[secondRight].min = INVALID_MIN;
hasyAxis2 = true;
for (int i = 0; i < plots.coords.size(); i++) {
plots.coords[i].yaxis = firstLeft;
double factor = 100 / (plots.coords.at(i).max_y - plots.coords.at(i).min_y);
for (int j = 0; j < plots.coords.at(i).y.count(); j++) {
plots.coords[i].y[j] = factor * (plots.coords.at(i).y.at(j) - plots.coords.at(i).min_y);
}
}
} else {
hasyAxis2 = false;
for (int i = firstRight; i < AXES_LIMIT; i++) {
if (yAxesRanges[i].max == INVALID_MAX) break;
yAxesRatios[i] = (yAxesRanges[i].max - yAxesRanges[i].min) /
(yAxesRanges[firstLeft].max - yAxesRanges[firstLeft].min);
}
}
removeAllGraphs();
ui->customPlot->xAxis->setRange(plots.min_x, plots.max_x);
axisRect->axis(QCPAxis::atBottom)->setRange(plots.min_x, plots.max_x);
ui->customPlot->yAxis->setRange(plots.rangeOneMin, plots.rangeOneMax);
ui->customPlot->yAxis->setTickLabels(true);
axisRect->axis(QCPAxis::atLeft)->setRange(yAxesRanges[firstLeft].min,
yAxesRanges[firstLeft].max);
if (plots.twoRanges) {
ui->customPlot->yAxis2->setRange(plots.rangeTwoMin, plots.rangeTwoMax);
ui->customPlot->yAxis2->setVisible(true);
if (plots.tooManyRanges) {
axisRect->axis(QCPAxis::atLeft)->setTickLabels(false);
} else {
axisRect->axis(QCPAxis::atLeft)->setTickLabels(true);
}
if (yAxesRanges[firstRight].max != INVALID_MAX) {
axisRect->axis(QCPAxis::atRight)->setRange(yAxesRanges[firstRight].min,
yAxesRanges[firstRight].max);
axisRect->axis(QCPAxis::atRight)->setVisible(true);
rightLegend->setVisible(true);
if (yAxesRanges[secondLeft].max != INVALID_MAX) {
axisRect->axis(QCPAxis::atLeft, 1)->setVisible(true);
axisRect->axis(QCPAxis::atLeft, 1)->setRange(yAxesRanges[secondLeft].min,
yAxesRanges[secondLeft].max);
if (yAxesRanges[secondRight].max != INVALID_MAX) {
axisRect->axis(QCPAxis::atRight, 1)->setVisible(true);
axisRect->axis(QCPAxis::atRight, 1)->setRange(yAxesRanges[secondRight].min,
yAxesRanges[secondRight].max);
}
}
}
for (int i = 0; i < plots.coords.size(); i++) {
if (plots.coords.at(i).secondRange && plots.twoRanges) {
ui->customPlot->addGraph(ui->customPlot->xAxis, ui->customPlot->yAxis2);
} else {
ui->customPlot->addGraph();
switch (plots.coords[i].yaxis) {
case firstLeft:
ui->customPlot->addGraph();
if (yAxesRanges[secondLeft].max != INVALID_MAX) {
ui->customPlot->graph(i)->setName(plots.coords.at(i).name + tr(" (L1)"));
} else {
ui->customPlot->graph(i)->setName(plots.coords.at(i).name);
}
ui->customPlot->legend->addItem(
new QCPPlottableLegendItem(ui->customPlot->legend, ui->customPlot->graph(i)));
break;
case firstRight:
ui->customPlot->addGraph(axisRect->axis(QCPAxis::atBottom),
axisRect->axis(QCPAxis::atRight));
if (yAxesRanges[secondRight].max != INVALID_MAX) {
ui->customPlot->graph(i)->setName(plots.coords.at(i).name + tr(" (R1)"));
} else {
ui->customPlot->graph(i)->setName(plots.coords.at(i).name);
}
rightLegend->addItem(
new QCPPlottableLegendItem(rightLegend, ui->customPlot->graph(i)));
break;
case secondLeft:
ui->customPlot->addGraph(axisRect->axis(QCPAxis::atBottom),
axisRect->axis(QCPAxis::atLeft, 1));
ui->customPlot->graph(i)->setName(plots.coords.at(i).name + tr(" (L2)"));
ui->customPlot->legend->addItem(
new QCPPlottableLegendItem(ui->customPlot->legend, ui->customPlot->graph(i)));
break;
case secondRight:
ui->customPlot->addGraph(axisRect->axis(QCPAxis::atBottom),
axisRect->axis(QCPAxis::atRight, 1));
ui->customPlot->graph(i)->setName(plots.coords.at(i).name + tr(" (R2)"));
rightLegend->addItem(
new QCPPlottableLegendItem(rightLegend, ui->customPlot->graph(i)));
break;
default:
break;
}
ui->customPlot->graph(i)->setData(plots.coords.at(i).x,
plots.coords.at(i).y);
pen.setColor(colors.at(i % colors.size()));
ui->customPlot->graph(i)->setPen(pen);
ui->customPlot->graph(i)->setName(plots.coords.at(i).name);
}
ui->customPlot->legend->setVisible(true);
ui->customPlot->replot();
}
void logsDialog::setRangeyAxis2(QCPRange range)
void logsDialog::yAxisChangeRanges(QCPRange range)
{
if (hasyAxis2) {
double lowerChange = (range.lower - rangeyAxisMin) * rangeRatio;
double upperChange = (range.upper - rangeyAxisMax) * rangeRatio;
rangeyAxisMin = range.lower;
rangeyAxisMax = range.upper;
rangeyAxis2Min += lowerChange;
rangeyAxis2Max += upperChange;
if (axisRect->axis(QCPAxis::atRight)->visible()) {
double lowerChange = (range.lower - yAxesRanges[firstLeft].min) *
yAxesRatios[firstRight];
double upperChange = (range.upper - yAxesRanges[firstLeft].max) *
yAxesRatios[firstRight];
ui->customPlot->yAxis2->setRange(rangeyAxis2Min, rangeyAxis2Max);
yAxesRanges[firstRight].min += lowerChange;
yAxesRanges[firstRight].max += upperChange;
axisRect->axis(QCPAxis::atRight)->setRange(yAxesRanges[firstRight].min,
yAxesRanges[firstRight].max);
if (axisRect->axisCount(QCPAxis::atLeft) == 2) {
lowerChange = (range.lower - yAxesRanges[firstLeft].min) *
yAxesRatios[secondLeft];
upperChange = (range.upper - yAxesRanges[firstLeft].max) *
yAxesRatios[secondLeft];
yAxesRanges[secondLeft].min += lowerChange;
yAxesRanges[secondLeft].max += upperChange;
axisRect->axis(QCPAxis::atLeft, 1)->setRange(yAxesRanges[secondLeft].min,
yAxesRanges[secondLeft].max);
if (axisRect->axisCount(QCPAxis::atRight) == 2) {
lowerChange = (range.lower - yAxesRanges[firstLeft].min) *
yAxesRatios[secondRight];
upperChange = (range.upper - yAxesRanges[firstLeft].max) *
yAxesRatios[secondRight];
yAxesRanges[secondRight].min += lowerChange;
yAxesRanges[secondRight].max += upperChange;
axisRect->axis(QCPAxis::atRight, 1)->setRange(yAxesRanges[secondRight].min,
yAxesRanges[secondRight].max);
}
}
yAxesRanges[firstLeft].min = range.lower;
yAxesRanges[firstLeft].max = range.upper;
}
}
+27 -15
View File
@@ -5,24 +5,35 @@
#include <QtGui>
#include "qcustomplot/qcustomplot.h"
#define INVALID_MIN 999999
#define INVALID_MAX -999999
enum yaxes_t {
firstLeft = 0,
firstRight,
secondLeft,
secondRight,
AXES_LIMIT // = 4
};
struct coords {
QVector<double> x, y;
double min_y;
double max_y;
bool secondRange;
yaxes_t yaxis;
QString name;
};
struct minMax {
double min;
double max;
};
struct plotsCollection {
QVarLengthArray<struct coords> coords;
double min_x;
double max_x;
bool twoRanges;
bool tooManyRanges;
double rangeOneMin;
double rangeOneMax;
double rangeTwoMin;
double rangeTwoMax;
};
namespace Ui {
@@ -44,30 +55,31 @@ private slots:
void selectionChanged();
void mousePress();
void mouseWheel();
void removeSelectedGraph();
void removeAllGraphs();
void plotLogs();
void on_fileOpen_BT_clicked();
void on_sessions_CB_currentIndexChanged(int index);
void on_mapsButton_clicked();
void setRangeyAxis2(QCPRange range);
void yAxisChangeRanges(QCPRange range);
private:
QList<QStringList> csvlog;
Ui::logsDialog *ui;
bool cvsFileParse();
QCPAxisRect *axisRect;
QCPLegend *rightLegend;
bool plotLock;
QString logFilename;
QVarLengthArray<Qt::GlobalColor> colors;
QPen pen;
bool hasyAxis2;
double rangeRatio;
double rangeyAxisMin;
double rangeyAxisMax;
double rangeyAxis2Min;
double rangeyAxis2Max;
double yAxesRatios[AXES_LIMIT];
minMax yAxesRanges[AXES_LIMIT];
bool cvsFileParse();
QList<QStringList> filterGePoints(const QList<QStringList> & input);
void exportToGoogleEarth();
};
#endif // LOGSDIALOG_H
+74 -66
View File
@@ -110,12 +110,12 @@ MainWindow::MainWindow():
this->setIconSize(QSize(32, 32));
QNetworkProxyFactory::setUseSystemConfiguration(true);
setAcceptDrops(true);
// give time to the splash to disappear and main window to open before starting updates
int updateDelay = 1000;
bool showSplash = g.showSplash();
if (showSplash) {
updateDelay += (SPLASH_TIME*1000);
updateDelay += (SPLASH_TIME*1000);
}
QTimer::singleShot(updateDelay, this, SLOT(doAutoUpdates()));
QTimer::singleShot(updateDelay, this, SLOT(displayWarnings()));
@@ -153,13 +153,13 @@ MainWindow::MainWindow():
child->show();
}
else {
child->show();
child->show();
child->print(model,printfilename);
child->close();
}
}
}
}
}
if (printing) {
QTimer::singleShot(0, this, SLOT(autoClose()));
}
@@ -180,7 +180,7 @@ void MainWindow::displayWarnings()
}
}
else if (warnId==0) {
g.warningId(WARNING_ID);
g.warningId(WARNING_ID);
}
}
@@ -193,10 +193,10 @@ QString MainWindow::getBackupPath() {
if (!QDir(backupPath).exists()) {
backupEnable = false;
}
}
}
else {
backupEnable = false;
}
}
}
if (!backupEnable) {
backupEnable=g.enableBackup();
@@ -213,8 +213,8 @@ QString MainWindow::getBackupPath() {
if ((g.enableBackup() || g.profile[g.id()].penableBackup()) && !(backupEnable) && !IS_TARANIS(GetEepromInterface()->getBoard())) {
if (!QDir(backupPath).exists()) {
QMessageBox::warning(this, tr("Backup is impossible"), tr("The backup dir set in preferences does not exist"));
}
}
}
}
else {
backupEnable=false;
}
@@ -316,15 +316,15 @@ void MainWindow::checkForCompanionUpdateFinished(QNetworkReply * reply)
int c9xver = version2index(c9xversion);
if (c9xver < vnum) {
#if defined WIN32 || !defined __GNUC__ // || defined __APPLE__ // OSX should only notify of updates since no update packages are available.
#if defined WIN32 || !defined __GNUC__ // || defined __APPLE__ // OSX should only notify of updates since no update packages are available.
int ret = QMessageBox::question(this, "Companion", tr("A new version of Companion is available (version %1)<br>"
"Would you like to download it?").arg(version) ,
QMessageBox::Yes | QMessageBox::No);
if (ret == QMessageBox::Yes) {
#if defined __APPLE__
#if defined __APPLE__
QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), g.updatesDir() + QString(C9X_INSTALLER).arg(version));
#else
#else
QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), g.updatesDir() + QString(C9X_INSTALLER).arg(version), tr("Executable (*.exe)"));
#endif
if (!fileName.isEmpty()) {
@@ -337,7 +337,7 @@ void MainWindow::checkForCompanionUpdateFinished(QNetworkReply * reply)
}
#else
QMessageBox::warning(this, tr("New release available"), tr("A new release of Companion is available, please check the OpenTX website!"));
#endif
#endif
}
else {
if (downloadDialog_forWait && checkForUpdatesState==0) {
@@ -564,9 +564,9 @@ void MainWindow::closeEvent(QCloseEvent *event)
}
void MainWindow::setLanguage(QString langString)
{
{
g.locale( langString );
QMessageBox msgBox;
msgBox.setText(tr("The selected language will be used the next time you start Companion."));
msgBox.setIcon(QMessageBox::Information);
@@ -575,9 +575,9 @@ void MainWindow::setLanguage(QString langString)
}
void MainWindow::setTheme(int index)
{
{
g.theme( index );
QMessageBox msgBox;
msgBox.setText(tr("The new theme will be loaded the next time you start Companion."));
msgBox.setIcon(QMessageBox::Information);
@@ -586,7 +586,7 @@ void MainWindow::setTheme(int index)
}
void MainWindow::setIconThemeSize(int index)
{
{
g.iconSize( index );
QMessageBox msgBox;
@@ -725,7 +725,7 @@ void MainWindow::fwchangelog()
}
void MainWindow::customizeSplash()
{
{
customizeSplashDialog *cd = new customizeSplashDialog(this);
cd->exec();
}
@@ -901,7 +901,7 @@ QStringList MainWindow::GetSendFlashCommand(const QString &filename)
QStringList ret;
EEPROMInterface *eepromInterface = GetEepromInterface();
if (IS_TARANIS(eepromInterface->getBoard())) {
ret=GetDFUUtilArguments("-D", filename);
ret=GetDFUUtilArguments("-D", filename);
}
else if (eepromInterface->getBoard() == BOARD_SKY9X) {
ret=GetSambaArguments(QString("send_file {Flash} \"") + filename + "\" 0x400000 0\n" + "FLASH::ScriptGPNMV 2\n");
@@ -919,7 +919,7 @@ QStringList MainWindow::GetReceiveFlashCommand(const QString &filename)
{
EEPROMInterface *eepromInterface = GetEepromInterface();
if (IS_TARANIS(eepromInterface->getBoard())) {
return GetDFUUtilArguments("-U", filename);
return GetDFUUtilArguments("-U", filename);
}
else if (eepromInterface->getBoard() == BOARD_SKY9X) {
return GetSambaArguments(QString("receive_file {Flash} \"") + filename + "\" 0x400000 0x40000 0\n");
@@ -988,7 +988,7 @@ void MainWindow::readEeprom()
EEPROMInterface *eepromInterface = GetEepromInterface();
if (IS_ARM(eepromInterface->getBoard()))
if (IS_ARM(eepromInterface->getBoard()))
tempFile = generateProcessUniqueTempFileName("temp.bin");
else
tempFile += generateProcessUniqueTempFileName("temp.hex");
@@ -1247,7 +1247,7 @@ int MainWindow::getFileType(const QString &fullFileName)
}
bool MainWindow::isValidEEPROM(QString eepromfile)
{
{
int eeprom_size;
QFile file(eepromfile);
int fileType = getFileType(eepromfile);
@@ -1262,10 +1262,12 @@ bool MainWindow::isValidEEPROM(QString eepromfile)
return false;
}
file.close();
RadioData * radioData = new RadioData();
bool result = LoadEeprom(*radioData, (uint8_t *)eeprom.data(), eeprom_size);
std::bitset<NUM_ERRORS> errors((unsigned long long)LoadEeprom(*radioData, (uint8_t *)eeprom.data(), eeprom_size));
delete radioData;
return result;
return errors.test(NO_ERROR);
}
else if (fileType==FILE_TYPE_BIN) { //read binary
if (!file.open(QFile::ReadOnly))
@@ -1277,10 +1279,12 @@ bool MainWindow::isValidEEPROM(QString eepromfile)
if (read != eeprom_size) {
return false;
}
RadioData * radioData = new RadioData();
bool result = LoadEeprom(*radioData, (uint8_t *)eeprom.data(), eeprom_size);
std::bitset<NUM_ERRORS> errors((unsigned long long)LoadEeprom(*radioData, (uint8_t *)eeprom.data(), eeprom_size));
delete radioData;
return result;
return errors.test(NO_ERROR);
}
return false;
}
@@ -1308,7 +1312,8 @@ bool MainWindow::convertEEPROM(QString backupFile, QString restoreFile, QString
file.close();
QSharedPointer<RadioData> radioData = QSharedPointer<RadioData>(new RadioData());
if (!LoadEeprom(*radioData, (uint8_t *)eeprom.data(), eeprom_size) || !firmware->saveEEPROM((uint8_t *)eeprom.data(), *radioData, variant, version))
std::bitset<NUM_ERRORS> errors((unsigned long long)LoadEeprom(*radioData, (uint8_t *)eeprom.data(), eeprom_size));
if (!errors.test(NO_ERROR) || !firmware->saveEEPROM((uint8_t *)eeprom.data(), *radioData, variant, version))
return false;
QFile file2(restoreFile);
@@ -1335,7 +1340,7 @@ void MainWindow::writeFlash(QString fileToFlash)
burnDialog *cd = new burnDialog(this, 2, &fileName, &backup);
cd->exec();
qDebug() << "MainWindow::writeFlash(): flashing " << fileName;
if (IS_TARANIS(GetEepromInterface()->getBoard())) {
backup=false;
}
@@ -1362,11 +1367,9 @@ void MainWindow::writeFlash(QString fileToFlash)
}
g.backupOnFlash(backup);
if (backup) {
bool backupEnable=true;
QString backupFile;
QString backupPath=getBackupPath();
if (backupPath.isEmpty()) {
backupEnable=false;
backupFile = generateProcessUniqueTempFileName("backup.bin");
}
else {
@@ -1481,7 +1484,7 @@ void MainWindow::about()
aboutStr.append("<br/><br/>");
aboutStr.append(QString("Version %1, %2").arg(C9X_VERSION).arg(__DATE__));
aboutStr.append("<br/><br/>");
aboutStr.append(tr("Copyright OpenTX Team") + "<br/>&copy; 2011-2014<br/>");
aboutStr.append(tr("Copyright OpenTX Team") + "<br/>&copy; 2011-2015<br/>");
QMessageBox msgBox(this);
msgBox.setWindowIcon(CompanionIcon("information.png"));
msgBox.setWindowTitle(tr("About Companion"));
@@ -1497,7 +1500,7 @@ void MainWindow::updateMenus()
pasteAct->setEnabled(hasMdiChild ? activeMdiChild()->hasPasteData() : false);
writeEepromAct->setEnabled(hasMdiChild);
separatorAct->setVisible(hasMdiChild);
bool hasSelection = (activeMdiChild() && activeMdiChild()->hasSelection());
cutAct->setEnabled(hasSelection);
copyAct->setEnabled(hasSelection);
@@ -1540,7 +1543,7 @@ QAction * MainWindow::addAct(const QString & icon, const QString & sName, const
QAction * newAction = new QAction( this );
if (!icon.isEmpty())
newAction->setIcon(CompanionIcon(icon));
if (!sName.isEmpty())
if (!sName.isEmpty())
newAction->setText(sName);
if (!lName.isEmpty())
newAction->setStatusTip(lName);
@@ -1561,7 +1564,7 @@ QAction * MainWindow::addAct(QActionGroup *aGroup, const QString & sName, const
{
QAction *action = addAct("", sName, lName, QKeySequence::UnknownKey, slot);
action->setCheckable(true);
aGroup->addAction(action);
aGroup->addAction(action);
return action;
}
@@ -1595,7 +1598,7 @@ void MainWindow::createActions()
cutAct = addAct("cut.png", tr("Cut Model"), tr("Cut current model to the clipboard"), QKeySequence::Cut, SLOT(cut()));
copyAct = addAct("copy.png", tr("Copy Model"), tr("Copy current model to the clipboard"), QKeySequence::Copy, SLOT(copy()));
pasteAct = addAct("paste.png", tr("Paste Model"), tr("Paste model from clipboard"), QKeySequence::Paste, SLOT(paste()));
QActionGroup *themeAlignGroup = new QActionGroup(this);
classicThemeAct = addAct( themeAlignGroup, tr("Classical"), tr("The classic companion9x icon theme"), SLOT(setClassicTheme()));
yericoThemeAct = addAct( themeAlignGroup, tr("Yerico"), tr("Yellow round honey sweet icon theme"), SLOT(setYericoTheme()));
@@ -1648,7 +1651,7 @@ void MainWindow::createActions()
writeBackupToRadioAct = addAct("write_eeprom_file.png", tr("Write Backup to Radio"), tr("Write Backup from file to Radio"), SLOT(writeBackup()));
readBackupToFileAct = addAct("read_eeprom_file.png", tr("Backup Radio to File"), tr("Save a complete backup file of all settings and model data in the Radio"), SLOT(readBackup()));
contributorsAct = addAct("contributors.png", tr("Contributors..."), tr("A tribute to those who have contributed to OpenTX and Companion"), SLOT(contributors()));
compareAct->setEnabled(false);
simulateAct->setEnabled(false);
printAct->setEnabled(false);
@@ -1730,7 +1733,7 @@ void MainWindow::createMenus()
burnMenu->addSeparator();
burnMenu->addSeparator();
EEPROMInterface *eepromInterface = GetEepromInterface();
if (!IS_ARM(eepromInterface->getBoard())) {
if (!IS_ARM(eepromInterface->getBoard())) {
burnMenu->addAction(burnFusesAct);
burnMenu->addAction(burnListAct);
}
@@ -1747,7 +1750,7 @@ void MainWindow::createMenus()
helpMenu->addSeparator();
helpMenu->addAction(contributorsAct);
}
QMenu *MainWindow::createRecentFileMenu()
{
QMenu *recentFileMenu = new QMenu(this);
@@ -1788,7 +1791,7 @@ void MainWindow::createToolBars()
break;
default:
size=QSize(24,24);
break;
break;
}
fileToolBar = addToolBar(tr("File"));
fileToolBar->setIconSize(size);
@@ -1833,7 +1836,7 @@ void MainWindow::createToolBars()
editToolBar->addAction(cutAct);
editToolBar->addAction(copyAct);
editToolBar->addAction(pasteAct);
burnToolBar = new QToolBar(tr("Write"));
addToolBar( Qt::LeftToolBarArea, burnToolBar );
burnToolBar->setIconSize(size);
@@ -1890,7 +1893,7 @@ void MainWindow::setActiveSubWindow(QWidget *window)
void MainWindow::updateRecentFileActions()
{
int i, numRecentFiles;
// Hide all document slots
for ( i=0 ; i < g.historySize(); i++)
recentFileActs[i]->setVisible(false);
@@ -1898,7 +1901,7 @@ void MainWindow::updateRecentFileActions()
// Fill slots with content and unhide them
QStringList files = g.recentFiles();
numRecentFiles = qMin(files.size(), g.historySize());
for ( i = 0; i < numRecentFiles; i++) {
QString text = strippedName(files[i]);
if (!text.trimmed().isEmpty())
@@ -1925,31 +1928,31 @@ void MainWindow::updateLanguageActions()
{
QString langId = g.locale();
if (langId=="")
if (langId=="")
sysLangAct->setChecked(true);
else if (langId=="cs_CZ")
else if (langId=="cs_CZ")
czechLangAct->setChecked(true);
else if (langId=="de_DE")
else if (langId=="de_DE")
germanLangAct->setChecked(true);
else if (langId=="en")
else if (langId=="en")
englishLangAct->setChecked(true);
else if (langId=="fi_FI")
else if (langId=="fi_FI")
finnishLangAct->setChecked(true);
else if (langId=="fr_FR")
else if (langId=="fr_FR")
frenchLangAct->setChecked(true);
else if (langId=="it_IT")
else if (langId=="it_IT")
italianLangAct->setChecked(true);
else if (langId=="he_IL")
else if (langId=="he_IL")
hebrewLangAct->setChecked(true);
else if (langId=="pl_PL")
else if (langId=="pl_PL")
polishLangAct->setChecked(true);
else if (langId=="pt_PT")
else if (langId=="pt_PT")
portugueseLangAct->setChecked(true);
else if (langId=="ru_RU")
else if (langId=="ru_RU")
russianLangAct->setChecked(true);
else if (langId=="sv_SE")
else if (langId=="sv_SE")
swedishLangAct->setChecked(true);
else if (langId=="nl_NL")
else if (langId=="nl_NL")
dutchLangAct->setChecked(true);
}
@@ -1967,9 +1970,9 @@ void MainWindow::updateIconThemeActions()
void MainWindow::updateProfilesActions()
{
for (int i=0; i<MAX_PROFILES; i++)
for (int i=0; i<MAX_PROFILES; i++)
{
if (g.profile[i].existsOnDisk())
if (g.profile[i].existsOnDisk())
{
QString text = tr("%2").arg(g.profile[i].name());
profileActs[i]->setText(text);
@@ -1977,8 +1980,8 @@ void MainWindow::updateProfilesActions()
profileActs[i]->setVisible(true);
if (i == g.id())
profileActs[i]->setChecked(true);
}
else
}
else
{
profileActs[i]->setVisible(false);
}
@@ -1992,7 +1995,7 @@ void MainWindow::createProfile()
;
if (i==MAX_PROFILES) //Failed to find free slot
return;
// Copy current profile to new and give it a new name
g.profile[i] = g.profile[g.id()];
g.profile[i].name(tr("New Radio"));
@@ -2033,16 +2036,17 @@ int MainWindow::getEpromVersion(QString fileName)
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { //reading HEX TEXT file
QMessageBox::critical(this, tr("Error"),tr("Error opening file %1:\n%2.").arg(fileName).arg(file.errorString()));
return -1;
}
}
QDomDocument doc(ER9X_EEPROM_FILE_TYPE);
bool xmlOK = doc.setContent(&file);
if(xmlOK) {
if (!LoadEepromXml(testData, doc)){
std::bitset<NUM_ERRORS> errors((unsigned long long)LoadEepromXml(testData, doc));
if (!errors.test(NO_ERROR)) {
return -1;
}
}
file.reset();
QTextStream inputStream(&file);
if (fileType==FILE_TYPE_EEPE) { // read EEPE file header
QString hline = inputStream.readLine();
@@ -2059,7 +2063,9 @@ int MainWindow::getEpromVersion(QString fileName)
return -1;
}
file.close();
if (!LoadEeprom(testData, eeprom, eeprom_size)) {
std::bitset<NUM_ERRORS> errors((unsigned long long)LoadEeprom(testData, eeprom, eeprom_size));
if (!errors.test(NO_ERROR)) {
QMessageBox::critical(this, tr("Error"),tr("Invalid Models and Settings File %1").arg(fileName));
return -1;
}
@@ -2077,7 +2083,9 @@ int MainWindow::getEpromVersion(QString fileName)
QMessageBox::critical(this, tr("Error"),tr("Error reading file %1:\n%2.").arg(fileName).arg(file.errorString()));
return -1;
}
if (!LoadEeprom(testData, (uint8_t *)eeprom.data(), eeprom_size)) {
std::bitset<NUM_ERRORS> errors((unsigned long long)LoadEeprom(testData, (uint8_t *)eeprom.data(), eeprom_size));
if (!errors.test(NO_ERROR)) {
QMessageBox::critical(this, tr("Error"),tr("Invalid binary Models and Settings File %1").arg(fileName));
return -1;
}
+36 -24
View File
@@ -81,7 +81,7 @@ MdiChild::MdiChild():
}
}
MdiChild::~MdiChild()
MdiChild::~MdiChild()
{
delete ui;
}
@@ -174,7 +174,7 @@ void MdiChild::modelEdit()
if (row == 0){
generalEdit();
}
}
else {
QApplication::setOverrideCursor(Qt::WaitCursor);
checkAndInitModel( row );
@@ -251,7 +251,7 @@ bool MdiChild::loadFile(const QString &fileName, bool resetCurrentFile)
XmlInterface(inputStream).load(radioData);
}
else
#endif
#endif
if (fileType==FILE_TYPE_HEX || fileType==FILE_TYPE_EEPE) { //read HEX file
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { //reading HEX TEXT file
QMessageBox::critical(this, tr("Error"),
@@ -260,18 +260,19 @@ bool MdiChild::loadFile(const QString &fileName, bool resetCurrentFile)
.arg(file.errorString()));
return false;
}
QDomDocument doc(ER9X_EEPROM_FILE_TYPE);
bool xmlOK = doc.setContent(&file);
if(xmlOK) {
if (LoadEepromXml(radioData, doc)){
std::bitset<NUM_ERRORS> errors((unsigned long long)LoadEepromXml(radioData, doc));
if (errors.test(NO_ERROR)) {
ui->modelsList->refreshList();
if(resetCurrentFile) setCurrentFile(fileName);
return true;
}
}
file.reset();
QTextStream inputStream(&file);
if (fileType==FILE_TYPE_EEPE) { // read EEPE file header
@@ -294,12 +295,14 @@ bool MdiChild::loadFile(const QString &fileName, bool resetCurrentFile)
file.close();
if (!LoadEeprom(radioData, eeprom, eeprom_size)) {
QMessageBox::critical(this, tr("Error"),
tr("Invalid EEPROM File %1")
.arg(fileName));
std::bitset<NUM_ERRORS> errors((unsigned long long)LoadEeprom(radioData, eeprom, eeprom_size));
if (!errors.test(NO_ERROR)) {
ShowEepromErrors(this, tr("Error"), tr("Invalid EEPROM File %1").arg(fileName), errors.to_ulong());
return false;
}
if (errors.test(HAS_WARNINGS)) {
ShowEepromWarnings(this, tr("Warning"), errors.to_ulong());
}
ui->modelsList->refreshList();
if(resetCurrentFile) setCurrentFile(fileName);
@@ -330,11 +333,18 @@ bool MdiChild::loadFile(const QString &fileName, bool resetCurrentFile)
return false;
}
if (!LoadEeprom(radioData, eeprom, eeprom_size) && !LoadBackup(radioData, eeprom, eeprom_size, 0)) {
QMessageBox::critical(this, tr("Error"),
tr("Invalid binary EEPROM File %1")
.arg(fileName));
return false;
std::bitset<NUM_ERRORS> errorsEeprom((unsigned long long)LoadEeprom(radioData, eeprom, eeprom_size));
if (!errorsEeprom.test(NO_ERROR)) {
std::bitset<NUM_ERRORS> errorsBackup((unsigned long long)LoadBackup(radioData, eeprom, eeprom_size, 0));
if (!errorsBackup.test(NO_ERROR)) {
ShowEepromErrors(this, tr("Error"), tr("Invalid binary EEPROM File %1").arg(fileName), (errorsEeprom | errorsBackup).to_ulong());
return false;
}
if (errorsBackup.test(HAS_WARNINGS)) {
ShowEepromWarnings(this, tr("Warning"), errorsBackup.to_ulong());
}
} else if (errorsEeprom.test(HAS_WARNINGS)) {
ShowEepromWarnings(this, tr("Warning"), errorsEeprom.to_ulong());
}
ui->modelsList->refreshList();
@@ -367,7 +377,7 @@ bool MdiChild::saveAs(bool isNew)
fileName = QFileDialog::getSaveFileName(this, tr("Save As"), g.eepromDir() + "/" +fi.fileName());
#else
fileName = QFileDialog::getSaveFileName(this, tr("Save As"), g.eepromDir() + "/" +fi.fileName(), tr(BIN_FILES_FILTER));
#endif
#endif
}
else {
QFileInfo fi(curFile);
@@ -375,14 +385,14 @@ bool MdiChild::saveAs(bool isNew)
fileName = QFileDialog::getSaveFileName(this, tr("Save As"), g.eepromDir() + "/" +fi.fileName());
#else
fileName = QFileDialog::getSaveFileName(this, tr("Save As"), g.eepromDir() + "/" +fi.fileName(), tr(EEPROM_FILES_FILTER));
#endif
#endif
}
if (fileName.isEmpty())
return false;
g.eepromDir( QFileInfo(fileName).dir().absolutePath() );
if (isNew)
return saveFile(fileName);
else
else
return saveFile(fileName,true);
}
@@ -505,7 +515,7 @@ void MdiChild::setCurrentFile(const QString &fileName)
files.prepend(fileName);
while (files.size() > MaxRecentFiles)
files.removeLast();
g.recentFiles( files );
}
@@ -594,7 +604,7 @@ void MdiChild::print(int model, QString filename)
else if (ui->modelsList->currentRow() > 0) {
pd = new PrintDialog(this, GetCurrentFirmware()/*firmware*/, &radioData.generalSettings, &radioData.models[ui->modelsList->currentRow()-1]);
}
if (pd) {
pd->setAttribute(Qt::WA_DeleteOnClose, true);
pd->show();
@@ -646,12 +656,14 @@ bool MdiChild::loadBackup()
return false;
}
if (!LoadBackup(radioData, (uint8_t *)eeprom.data(), eeprom_size, index)) {
QMessageBox::critical(this, tr("Error"),
tr("Invalid binary backup File %1")
.arg(fileName));
std::bitset<NUM_ERRORS> errorsEeprom((unsigned long long)LoadBackup(radioData, (uint8_t *)eeprom.data(), eeprom_size, index));
if (!errorsEeprom.test(NO_ERROR)) {
ShowEepromErrors(this, tr("Error"), tr("Invalid binary backup File %1").arg(fileName), (errorsEeprom).to_ulong());
return false;
}
if (errorsEeprom.test(HAS_WARNINGS)) {
ShowEepromWarnings(this, tr("Warning"), errorsEeprom.to_ulong());
}
ui->modelsList->refreshList();
+1 -1
View File
@@ -95,7 +95,7 @@ class MdiChild : public QWidget
void modelEdit();
void wizardEdit();
void openEditWindow();
void cut();
void copy();
void paste();
+1 -1
View File
@@ -691,7 +691,7 @@ void CustomFunctionsPanel::populateFuncParamCB(QComboBox *b, const ModelData & m
b->setCurrentIndex(value);
}
else if (function==FuncVolume) {
populateSourceCB(b, RawSource(value), model, POPULATE_SOURCES|POPULATE_VIRTUAL_INPUTS|POPULATE_TRIMS);
populateSourceCB(b, RawSource(value), model, POPULATE_SOURCES|POPULATE_VIRTUAL_INPUTS|POPULATE_TRIMS|POPULATE_SWITCHES);
}
else if (function==FuncPlayValue) {
populateSourceCB(b, RawSource(value), model, POPULATE_SOURCES|POPULATE_VIRTUAL_INPUTS|POPULATE_SWITCHES|POPULATE_GVARS|POPULATE_TRIMS|POPULATE_TELEMETRYEXT);
+6 -5
View File
@@ -2,7 +2,8 @@
#include "ui_expodialog.h"
#include "helpers.h"
ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, GeneralSettings & generalSettings, FirmwareInterface * firmware, char * inputName) :
ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, GeneralSettings & generalSettings,
FirmwareInterface * firmware, QString & inputName) :
QDialog(parent),
ui(new Ui::ExpoDialog),
model(model),
@@ -62,6 +63,8 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G
ui->inputName->setMaxLength(4);
populateSourceCB(ui->sourceCB, ed->srcRaw, model, POPULATE_SOURCES | POPULATE_SWITCHES | POPULATE_TRIMS | POPULATE_TELEMETRY);
ui->sourceCB->removeItem(0);
ui->inputName->setValidator(new QRegExpValidator(rx, this));
ui->inputName->setText(inputName);
}
else {
ui->inputNameLabel->hide();
@@ -87,9 +90,6 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G
ui->lineName->setMaxLength(expolength);
}
ui->inputName->setValidator(new QRegExpValidator(rx, this));
ui->inputName->setText(inputName);
ui->lineName->setValidator(new QRegExpValidator(rx, this));
ui->lineName->setText(ed->name);
@@ -153,7 +153,8 @@ void ExpoDialog::valuesChanged()
ed->mode = ui->sideCB->currentIndex() + 1;
strcpy(ed->name, ui->lineName->text().toAscii().data());
strcpy(inputName, ui->inputName->text().toAscii().data());
if (firmware->getCapability(VirtualInputs))
inputName = ui->inputName->text();
ed->phases=0;
for (int i=8; i>=0 ; i--) {
+3 -2
View File
@@ -14,7 +14,8 @@ namespace Ui {
class ExpoDialog : public QDialog {
Q_OBJECT
public:
ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expodata, GeneralSettings & generalSettings, FirmwareInterface * firmware, char * inputName);
ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expodata, GeneralSettings & generalSettings,
FirmwareInterface * firmware, QString & inputName);
~ExpoDialog();
protected:
@@ -30,7 +31,7 @@ class ExpoDialog : public QDialog {
GeneralSettings & generalSettings;
FirmwareInterface * firmware;
ExpoData * ed;
char * inputName;
QString & inputName;
GVarGroup * gvWeightGroup;
GVarGroup * gvOffsetGroup;
CurveGroup * curveGroup;
+3 -3
View File
@@ -216,18 +216,18 @@ void InputsPanel::gm_openExpo(int index)
if(index<0 || index>=C9X_MAX_EXPOS) return;
ExpoData mixd(model.expoData[index]);
char inputName[4+1];
emit modified();
update();
QString inputName;
if (firmware->getCapability(VirtualInputs))
strcpy(inputName, model.inputNames[mixd.chn]);
inputName = model.inputNames[mixd.chn];
ExpoDialog *g = new ExpoDialog(this, model, &mixd, generalSettings, firmware, inputName);
if (g->exec()) {
model.expoData[index] = mixd;
if (firmware->getCapability(VirtualInputs))
strcpy(model.inputNames[mixd.chn], inputName);
strncpy(model.inputNames[mixd.chn], inputName.toAscii().data(), 4);
emit modified();
update();
}
+8 -2
View File
@@ -260,6 +260,11 @@ void ModulePanel::update()
ui->failsafesLayoutLabel->setVisible(mask & MASK_FAILSAFES);
ui->failsafesFrame->setVisible(mask & MASK_FAILSAFES);
if (mask & MASK_CHANNELS_RANGE) {
ui->channelsStart->setMaximum(32 - ui->channelsCount->value());
ui->channelsCount->setMaximum(qMin(16, 32-ui->channelsStart->value()));
}
}
void ModulePanel::on_trainerMode_currentIndexChanged(int index)
@@ -428,8 +433,8 @@ SetupPanel::SetupPanel(QWidget *parent, ModelData & model, GeneralSettings & gen
ui->centerBeepLayout->addWidget(checkbox, 0, i+1);
connect(checkbox, SIGNAL(toggled(bool)), this, SLOT(onBeepCenterToggled(bool)));
centerBeepCheckboxes << checkbox;
if (!IS_TARANIS_PLUS(firmware->getBoard()) && i==6) {
checkbox->hide();
if (firmware->getBoard()==BOARD_TARANIS && i==6) {
checkbox->hide();
}
QWidget::setTabOrder(prevFocus, checkbox);
prevFocus = checkbox;
@@ -605,6 +610,7 @@ void SetupPanel::populateThrottleSourceCB()
lock = true;
ui->throttleSource->clear();
if (IS_TARANIS(GetEepromInterface()->getBoard())) {
for (i=0; i<6; i++) {
ui->throttleSource->addItem(sourcesTaranis[i], i);
+1 -1
View File
@@ -344,7 +344,7 @@
<string/>
</property>
<property name="minimum">
<number>1</number>
<number>4</number>
</property>
<property name="maximum">
<number>16</number>
+21
View File
@@ -1,3 +1,24 @@
#### Version 1.3.1 released on 25.04.15 ####
Bugfixes:
- Fixed bug that prevented automatic axis rescaling when some graphs/curves had only NaN data points
- Improved QCPItemBracket selection boundaries, especially bsCurly and bsCalligraphic
- Fixed bug of axis rect and colorscale background shifted downward by one logical pixel (visible in scaled png and pdf export)
- Replot upon mouse release is now only performed if a selection change has actually happened (improves responsivity on particularly complex plots)
- Fixed bug that allowed scatter-only graphs to be selected by clicking the non-existent line between scatters
- Fixed crash when trying to select a scatter-only QCPGraph whose only points in the visible key range are at identical key coordinates and vertically off-screen, with adaptive sampling enabled
- Fixed pdf export of QCPColorMap with enabled interpolation (didn't appear interpolated in pdf)
- Reduced QCPColorMap jitter of internal cell boundaries for small sized maps when viewed with high zoom, by applying oversampling factors dependant on map size
- Fixed bug of QCPColorMap::fill() not causing the buffered internal image map to be updated, and thus the change didn't become visible immediately
- Axis labels with size set in pixels (setPixelSize) instead of points now correctly calculate the exponent's font size if beautifully typeset powers are enabled
- Fixed QCPColorMap appearing at the wrong position for logarithmic axes and color map spanning larger ranges
Other:
- Pdf export used to embed entire QCPColorMaps, potentially leading to large files. Now only the visible portion of the map is embedded in the pdf
- Many documentation fixes and extensions, style modernization
- Reduced documentation file size (and thus full package size) by automatically reducing image palettes during package build
- Fixed MSVC warning message (at warning level 4) due to temporary QLists in some foreach statements
#### Version 1.3.0 released on 27.12.14 ####
Added features:
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -1,7 +1,7 @@
/***************************************************************************
** **
** QCustomPlot, an easy to use, modern plotting widget for Qt **
** Copyright (C) 2011, 2012, 2013, 2014 Emanuel Eichhammer **
** Copyright (C) 2011-2015 Emanuel Eichhammer **
** **
** This program is free software: you can redistribute it and/or modify **
** it under the terms of the GNU General Public License as published by **
@@ -19,8 +19,8 @@
****************************************************************************
** Author: Emanuel Eichhammer **
** Website/Contact: http://www.qcustomplot.com/ **
** Date: 27.12.14 **
** Version: 1.3.0 **
** Date: 25.04.15 **
** Version: 1.3.1 **
****************************************************************************/
#ifndef QCUSTOMPLOT_H
@@ -3099,7 +3099,7 @@ protected:
bool mTightBoundary;
QPointer<QCPColorScale> mColorScale;
// non-property members:
QImage mMapImage;
QImage mMapImage, mUndersampledMapImage;
QPixmap mLegendIcon;
bool mMapImageInvalidated;
+14 -12
View File
@@ -112,22 +112,24 @@ void JoystickDialog::on_cancelButton_clicked()
void JoystickDialog::on_okButton_clicked()
{
int sticks[8] = {0,0,0,0,0,0,0,0};
int stickAssignments[MAX_JOYSTICKS] = {0};
foreach(QComboBox *cb, findChildren<QComboBox *>(QRegExp("jsmapCB_[0-9]+"))) {
sticks[cb->currentIndex()]++;
}
bool duplicated=false;
for (int i=1; i<8;i++) {
if (sticks[i]>1) {
duplicated = true;
int mappedValue = cb->currentIndex() - 1;
// qDebug() << "cb->currentIndex()" << mappedValue;
if (mappedValue >= 0 && mappedValue < MAX_JOYSTICKS) {
stickAssignments[mappedValue]++;
}
}
if (duplicated) {
QMessageBox::critical(this, tr("Error"), tr("Duplicated stick assignement"));
return;
for (int i=0; i<MAX_JOYSTICKS; i++) {
if (stickAssignments[i] > 1) {
QMessageBox::critical(this, tr("Error"), tr("Duplicated stick assignment"));
return;
}
}
joystick->close();
for (int i=0; i<8; i++) {
for (int i=0; i<MAX_JOYSTICKS; i++) {
g.joystick[i].remove();
}
QCheckBox * ib[]={ui->ChInv_1, ui->ChInv_2, ui->ChInv_3, ui->ChInv_4, ui->ChInv_5, ui->ChInv_6, ui->ChInv_7, ui->ChInv_8};
@@ -135,7 +137,7 @@ void JoystickDialog::on_okButton_clicked()
int axe=cb->objectName().mid(cb->objectName().lastIndexOf("_")+1).toInt()-1;
int stick=cb->currentIndex() - 1;
qDebug() << "joystick mapping " << cb->objectName() <<"axe:" << axe << "stick:" << stick;
if (stick >= 0) {
if (stick >= 0 && stick < MAX_JOYSTICKS) {
g.joystick[stick].stick_axe( axe );
g.joystick[stick].stick_max( jscal[axe][2] );
g.joystick[stick].stick_med( jscal[axe][1] );
+1
View File
@@ -50,6 +50,7 @@
#include <iostream>
#if defined(JOYSTICKS) || defined(SIMU_AUDIO)
#include <SDL.h>
#undef main
#endif
#include "simulatordialog.h"
#include "eeprominterface.h"
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -7695,12 +7695,12 @@ p, li { white-space: pre-wrap; }
<message>
<location filename="../eeprominterface.cpp" line="461"/>
<source>EleTrim Down</source>
<translation>TrmE Bas</translation>
<translation>TrmP Bas</translation>
</message>
<message>
<location filename="../eeprominterface.cpp" line="461"/>
<source>EleTrim Up</source>
<translation>TrmE Haut</translation>
<translation>TrmP Haut</translation>
</message>
<message>
<location filename="../eeprominterface.cpp" line="462"/>
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -1,6 +1,6 @@
/*
* Author - Bertrand Songis <bsongis@gmail.com>
*
*
* Based on th9x -> http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
@@ -121,7 +121,7 @@ void saveModel(ModelData & m, model & xm)
if (t.mode) {
timer xt(TimerSwitch::value(t.mode+TMR_NUM_OPTION), direction::value(t.dir), timer::value_type(t.val/3600, (t.val%3600)/60, t.val%60));
timer_sequence.push_back(xt);
}
}
}
*/
if (m.moduleData[0].protocol != PPM || m.moduleData[0].channelsCount != 8 || m.moduleData[0].ppmDelay != 300 || m.moduleData[0].ppmPulsePol != 0) {
@@ -185,7 +185,7 @@ bool XmlInterface::save(RadioData &radioData)
radio r;
// the general settings
global_settings gs;
global_settings gs;
saveGeneralSettings(settings, gs);
r.global_settings(gs);
+2 -2
View File
@@ -1,4 +1,4 @@
Copyright © 2011-2014 OpenTX team
Copyright © 2011-2015 OpenTX team
OpenTX Companion is based on code named eePe by author - Erez Raviv <erezraviv@gmail.com>
@@ -9,4 +9,4 @@ Permission is granted to anyone to use this software for any purpose, including
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any distribution.
3. This notice may not be removed or altered from any distribution.
+46
View File
@@ -1,3 +1,49 @@
<h2>Version 2.0.19 / 2016-01-15</h2>
[ARM Boards]
<ul>
<li>Fixed : Logical switch internal state was being reset by the AND switch, that affected its function
(it looked like AND was applied before the EDGE processing, not after like it is done for other logical switch types)
(<a href=https://github.com/opentx/opentx/issues/2939>#2939</a>)</li>
<li>SD manager bug when scrolling up fixed (<a href=https://github.com/opentx/opentx/issues/3230>#3230</a>)</li>
</ul>
<h2>Version 2.0.18 / 2016-01-03</h2>
[Taranis]
<ul>
<li>Lua <i>model.insertInput()</i> could not add more than 32 inputs (<a href=https://github.com/opentx/opentx/issues/2084>#2084</a>)</li>
<li>Fixed auto-source problem on radios with non-existing S3 pot (<a href=https://github.com/opentx/opentx/issues/2364>#2364</a>)</li>
<li>Corrected failsafe mapping when using Custom failsafe mode, D16 protocol and channel range different from from 1-8.
Users with such setups are advised to re-check their failsafe settings (<a href=https://github.com/opentx/opentx/issues/2975>#2975</a>)</li>
</ul>
[ARM Boards]
<ul>
<li>Fixed Edge Logical switch erroneous delay (<a href=https://github.com/opentx/opentx/issues/2368>#2368</a>)</li>
<li>Fixed a problem with FMxx switches (<a href=https://github.com/opentx/opentx/issues/2442>#2442</a>)</li>
<li>Fixed: playing two background sounds at once causes sound to stop (<a href=https://github.com/opentx/opentx/issues/2704>#2704</a>)</li>
<li>SD Card manager improvements: Disable menu for [..], refresh file list after delete, removed delete menu option for directories (<a href=https://github.com/opentx/opentx/issues/2623>#2623</a>)</li>
<li>Added a warning about used receiver ID on model copy (<a href=https://github.com/opentx/opentx/issues/2187>#2187</a>)</li>
<li>PPM center did not work with the DSM hack module (<a href=https://github.com/opentx/opentx/issues/2880>#2880</a>)</li>
<li>Fixed: Edge Logical Switch could trigger right after the model was loaded or the radio turned on (<a href=https://github.com/opentx/opentx/issues/2728>#2728</a>)</li>
<li>Prevent issue when timer reaches maximum</li>
</ul>
[All]
<ul>
<li>Fixed a compilation problem on MAC (<a href=https://github.com/opentx/opentx/issues/2271>#2271</a>)</li>
<li>Fixed FrSky-D Telemetry protocol bug (0x5D followed by 0x3D)</li>
</ul>
<h2>Version 2.0.17 / 2015-05-04</h2>
Nothing new (only Companion fixes)
<h2>Version 2.0.16 / 2015-05-03</h2>
[Taranis]
+17 -20
View File
@@ -313,6 +313,10 @@ TRACE_AUDIO = NO
# Values = NO, YES
TARANIS_INTERNAL_PPM = NO
# Support for D16-EU only (no D8, no LR12 which are not EU compatible)
# Value = NO, YES
SUPPORT_D16_EU_ONLY = NO
# Enable disk IO simulation in simulator
# Simulator will use FatFs module and simulated IO layer that
# uses "./sdcard.image" file as image of SD card.
@@ -331,7 +335,7 @@ SHELL = sh
IMG2LBM = -python ../util/img2lbm.py
BIN2LBM = -python ../util/bin2lbm.py
TRANSLATE = -python ../util/translate.py
VERSION = 2.0.16
VERSION = 2.0.19
SRC =
CPPSRC =
@@ -734,6 +738,9 @@ ifeq ($(PCB), TARANIS)
ifeq ($(TARANIS_INTERNAL_PPM), YES)
CPPDEFS += -DTARANIS_INTERNAL_PPM
endif
ifeq ($(SUPPORT_D16_EU_ONLY), YES)
CPPDEFS += -DMODULE_D16_EU_ONLY_SUPPORT
endif
LDSCRIPT = targets/taranis/stm32_flash_bl.ld
TRGT = arm-none-eabi-
MCU = cortex-m3
@@ -1551,15 +1558,16 @@ endif
#### GOOGLE TESTS
GTEST_DIR = ../gtest-1.6.0
GTEST_INCDIR = /usr/include/gtest
GTEST_SRCDIR = /usr/src/gtest/
# Where to find user code.
USER_DIR = ./
# All Google Test headers. Usually you shouldn't change this
# definition.
GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
$(GTEST_DIR)/include/gtest/internal/*.h
GTEST_HEADERS = $(GTEST_INCDIR)/*.h \
$(GTEST_INCDIR)/internal/*.h
# House-keeping build targets.
@@ -1567,25 +1575,14 @@ GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
# Usually you shouldn't tweak such internal variables, indicated by a
# trailing _.
GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)
GTEST_SRCS = $(GTEST_SRCDIR)/src/*.cc $(GTEST_HEADERS)
# For simplicity and to avoid depending on Google Test's
# implementation details, the dependencies specified below are
# conservative and not optimized. This is fine as Google Test
# compiles fast and for ordinary users its source rarely changes.
gtest-all.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) -I$(GTEST_DIR)/include -c \
$(GTEST_DIR)/src/gtest-all.cc
gtest_main.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) -I$(GTEST_DIR)/include -c \
$(GTEST_DIR)/src/gtest_main.cc
gtest.a : gtest-all.o
$(AR) $(ARFLAGS) $@ $^
gtest_main.a : gtest-all.o gtest_main.o
$(AR) $(ARFLAGS) $@ $^
gtest-all.o : $(GTEST_SRCS)
$(CXX) $(CPPFLAGS) -I$(GTEST_SRCDIR) -I$(GTEST_INCDIR) -c $(GTEST_SRCDIR)/src/gtest-all.cc
# Builds a sample test. A test should link with either gtest.a or
# gtest_main.a, depending on whether it defines its own main()
@@ -1594,6 +1591,6 @@ gtest_main.a : gtest-all.o gtest_main.o
#use all .cpp files from tests/ dir
GTEST_TESTS_SRCS = $(shell find tests/ -type f -name '*.cpp')
gtests: $(BOARDSRC) $(CPPSRC) $(GTEST_TESTS_SRCS) targets/simu/simpgmspace.cpp *.h gtest_main.a
g++ -std=gnu++0x $(CPPFLAGS) $(BOARDSRC) $(CPPSRC) $(LUASRC) $(GTEST_TESTS_SRCS) targets/simu/simpgmspace.cpp -I$(GTEST_DIR) ${INCFLAGS} -I$(GTEST_DIR)/include -o gtests -lpthread -MD -DSIMU -lQtCore -lQtGui gtest_main.a -fexceptions
gtests: $(BOARDSRC) $(CPPSRC) $(GTEST_TESTS_SRCS) targets/simu/simpgmspace.cpp *.h gtest-all.o
g++ -std=gnu++0x $(CPPFLAGS) $(BOARDSRC) $(CPPSRC) $(LUASRC) $(GTEST_TESTS_SRCS) targets/simu/simpgmspace.cpp ${INCFLAGS} -I$(GTEST_INCDIR) -I/usr/include/qt4 -o gtests -lpthread -MD -DSIMU -lQtCore -lQtGui gtest-all.o -fexceptions
+1 -1
View File
@@ -159,7 +159,7 @@ class AudioQueue {
friend void audioTask(void* pdata);
#if defined(SIMU)
friend void *audio_thread(void *);
friend void *audioThread(void *);
#endif
public:
+27 -18
View File
@@ -36,6 +36,11 @@
#include "../opentx.h"
#define REFRESH_FILES() do { reusableBuffer.sdmanager.offset = 65535; m_posVert = 1; } while(0)
#define NODE_TYPE(fname) fname[SD_SCREEN_FILE_LENGTH+1]
#define IS_DIRECTORY(fname) ((bool)(!NODE_TYPE(fname)))
#define IS_FILE(fname) ((bool)(NODE_TYPE(fname)))
const pm_uchar sticks[] PROGMEM = {
#include "../bitmaps/sticks.lbm"
};
@@ -713,12 +718,12 @@ void menuGeneralSdManagerInfo(uint8_t event)
inline bool isFilenameGreater(bool isfile, const char * fn, const char * line)
{
return (isfile && !line[SD_SCREEN_FILE_LENGTH+1]) || (isfile==(bool)line[SD_SCREEN_FILE_LENGTH+1] && strcasecmp(fn, line) > 0);
return (isfile && IS_DIRECTORY(line)) || (isfile==IS_FILE(line) && strcasecmp(fn, line) > 0);
}
inline bool isFilenameLower(bool isfile, const char * fn, const char * line)
{
return (!isfile && line[SD_SCREEN_FILE_LENGTH+1]) || (isfile==(bool)line[SD_SCREEN_FILE_LENGTH+1] && strcasecmp(fn, line) < 0);
return (!isfile && IS_FILE(line)) || (isfile==IS_FILE(line) && strcasecmp(fn, line) < 0);
}
#if defined(PCBTARANIS)
@@ -845,8 +850,7 @@ void onSdManagerMenu(const char *result)
strncpy(statusLineMsg, reusableBuffer.sdmanager.lines[index], 13);
strcpy_P(statusLineMsg+min((uint8_t)strlen(statusLineMsg), (uint8_t)13), STR_REMOVED);
showStatusLine();
if ((uint16_t)m_posVert == reusableBuffer.sdmanager.count) m_posVert--;
reusableBuffer.sdmanager.offset = s_pgOfs-1;
REFRESH_FILES();
}
#if defined(CPUARM)
/* TODO else if (result == STR_LOAD_FILE) {
@@ -956,7 +960,7 @@ void menuGeneralSdManager(uint8_t _event)
{
if (m_posVert > 0) {
vertpos_t index = m_posVert-1-s_pgOfs;
if (!reusableBuffer.sdmanager.lines[index][SD_SCREEN_FILE_LENGTH+1]) {
if (IS_DIRECTORY(reusableBuffer.sdmanager.lines[index])) {
f_chdir(reusableBuffer.sdmanager.lines[index]);
s_pgOfs = 0;
m_posVert = 1;
@@ -980,10 +984,14 @@ void menuGeneralSdManager(uint8_t _event)
else
#endif
{
#if defined(CPUARM)
uint8_t index = m_posVert-1-s_pgOfs;
char *line = reusableBuffer.sdmanager.lines[index];
if (!strcmp(line, "..")) {
break; // no menu for parent dir
}
#if defined(CPUARM)
// TODO duplicated code for finding extension
char * ext = reusableBuffer.sdmanager.lines[index];
char * ext = line;
int len = strlen(ext) - 4;
ext += len;
/* TODO if (!strcasecmp(ext, MODELS_EXT)) {
@@ -1010,7 +1018,7 @@ void menuGeneralSdManager(uint8_t _event)
}
#endif
if (!READ_ONLY()) {
MENU_ADD_ITEM(STR_DELETE_FILE);
if (IS_FILE(line)) MENU_ADD_ITEM(STR_DELETE_FILE);
// MENU_ADD_ITEM(STR_RENAME_FILE); TODO: Implement
// MENU_ADD_ITEM(STR_COPY_FILE); TODO: Implement
}
@@ -1031,7 +1039,7 @@ void menuGeneralSdManager(uint8_t _event)
else if (s_pgOfs > reusableBuffer.sdmanager.offset) {
memmove(reusableBuffer.sdmanager.lines[0], reusableBuffer.sdmanager.lines[1], 6*sizeof(reusableBuffer.sdmanager.lines[0]));
memset(reusableBuffer.sdmanager.lines[6], 0xff, SD_SCREEN_FILE_LENGTH);
reusableBuffer.sdmanager.lines[6][SD_SCREEN_FILE_LENGTH+1] = 1;
NODE_TYPE(reusableBuffer.sdmanager.lines[6]) = 1;
}
else {
memmove(reusableBuffer.sdmanager.lines[1], reusableBuffer.sdmanager.lines[0], 6*sizeof(reusableBuffer.sdmanager.lines[0]));
@@ -1051,7 +1059,8 @@ void menuGeneralSdManager(uint8_t _event)
#else
fn = fno.fname;
#endif
if (strlen(fn) > SD_SCREEN_FILE_LENGTH) continue;
TRACE("strlen(%s) = %d", fn, strlen(fn));
if (strlen(fn) > SD_SCREEN_FILE_LENGTH) { TRACE("too long"); continue; }
reusableBuffer.sdmanager.count++;
@@ -1062,9 +1071,9 @@ void menuGeneralSdManager(uint8_t _event)
char *line = reusableBuffer.sdmanager.lines[i];
if (line[0] == '\0' || isFilenameLower(isfile, fn, line)) {
if (i < 6) memmove(reusableBuffer.sdmanager.lines[i+1], line, sizeof(reusableBuffer.sdmanager.lines[i]) * (6-i));
memset(line, 0, sizeof(reusableBuffer.sdmanager.lines[i]));
memset(line, 0, sizeof(reusableBuffer.sdmanager.lines[0]));
strcpy(line, fn);
line[SD_SCREEN_FILE_LENGTH+1] = isfile;
NODE_TYPE(line) = isfile;
break;
}
}
@@ -1074,9 +1083,9 @@ void menuGeneralSdManager(uint8_t _event)
char *line = reusableBuffer.sdmanager.lines[i];
if (line[0] == '\0' || isFilenameGreater(isfile, fn, line)) {
if (i > 0) memmove(reusableBuffer.sdmanager.lines[0], reusableBuffer.sdmanager.lines[1], sizeof(reusableBuffer.sdmanager.lines[0]) * i);
memset(line, 0, sizeof(reusableBuffer.sdmanager.lines[i]));
memset(line, 0, sizeof(reusableBuffer.sdmanager.lines[0]));
strcpy(line, fn);
line[SD_SCREEN_FILE_LENGTH+1] = isfile;
NODE_TYPE(line) = isfile;
break;
}
}
@@ -1085,14 +1094,14 @@ void menuGeneralSdManager(uint8_t _event)
if (isFilenameGreater(isfile, fn, reusableBuffer.sdmanager.lines[5]) && isFilenameLower(isfile, fn, reusableBuffer.sdmanager.lines[6])) {
memset(reusableBuffer.sdmanager.lines[6], 0, sizeof(reusableBuffer.sdmanager.lines[0]));
strcpy(reusableBuffer.sdmanager.lines[6], fn);
reusableBuffer.sdmanager.lines[6][SD_SCREEN_FILE_LENGTH+1] = isfile;
NODE_TYPE(reusableBuffer.sdmanager.lines[6]) = isfile;
}
}
else {
if (isFilenameLower(isfile, fn, reusableBuffer.sdmanager.lines[1]) && isFilenameGreater(isfile, fn, reusableBuffer.sdmanager.lines[0])) {
memset(reusableBuffer.sdmanager.lines[0], 0, sizeof(reusableBuffer.sdmanager.lines[0]));
strcpy(reusableBuffer.sdmanager.lines[0], fn);
reusableBuffer.sdmanager.lines[0][SD_SCREEN_FILE_LENGTH+1] = isfile;
NODE_TYPE(reusableBuffer.sdmanager.lines[0]) = isfile;
}
}
}
@@ -1106,9 +1115,9 @@ void menuGeneralSdManager(uint8_t _event)
lcdNextPos = 0;
uint8_t attr = (m_posVert-1-s_pgOfs == i ? BSS|INVERS : BSS);
if (reusableBuffer.sdmanager.lines[i][0]) {
if (!reusableBuffer.sdmanager.lines[i][SD_SCREEN_FILE_LENGTH+1]) { lcd_putcAtt(0, y, '[', attr); }
if (IS_DIRECTORY(reusableBuffer.sdmanager.lines[i])) { lcd_putcAtt(0, y, '[', attr); }
lcd_putsAtt(lcdNextPos, y, reusableBuffer.sdmanager.lines[i], attr);
if (!reusableBuffer.sdmanager.lines[i][SD_SCREEN_FILE_LENGTH+1]) { lcd_putcAtt(lcdNextPos, y, ']', attr); }
if (IS_DIRECTORY(reusableBuffer.sdmanager.lines[i])) { lcd_putcAtt(lcdNextPos, y, ']', attr); }
}
}
+93 -83
View File
@@ -439,7 +439,7 @@ void menuModelSelect(uint8_t event)
s_editMode = 0;
break;
}
// no break;
// no break;
#endif
case EVT_KEY_LONG(KEY_ENTER):
case EVT_KEY_BREAK(KEY_ENTER):
@@ -479,6 +479,10 @@ void menuModelSelect(uint8_t event)
eeDirty(EE_GENERAL);
}
#if defined(CPUARM)
checkModelIdUnique(g_eeGeneral.currModel);
#endif
s_copyMode = 0;
event = EVT_ENTRY_UP;
}
@@ -666,16 +670,17 @@ void menuModelFailsafe(uint8_t event)
static bool longNames = false;
bool newLongNames = false;
uint8_t ch = 0;
uint8_t channelStart = g_model.moduleData[g_moduleIdx].channelsStart;
if (event == EVT_KEY_LONG(KEY_ENTER) && s_editMode) {
s_noHi = NO_HI_LEN;
g_model.moduleData[g_moduleIdx].failsafeChannels[m_posVert] = channelOutputs[m_posVert];
g_model.moduleData[g_moduleIdx].failsafeChannels[m_posVert] = channelOutputs[m_posVert+channelStart];
eeDirty(EE_MODEL);
AUDIO_WARNING1();
SEND_FAILSAFE_NOW(g_moduleIdx);
}
SIMPLE_SUBMENU_NOTITLE(NUM_CHNOUT);
SIMPLE_SUBMENU_NOTITLE(NUM_CHANNELS(g_moduleIdx));
SET_SCROLLBAR_X(0);
@@ -684,10 +689,6 @@ void menuModelFailsafe(uint8_t event)
const uint8_t SLIDER_W = 64;
// Column separator
lcd_vline(LCD_W/2, FH, LCD_H-FH);
if (m_posVert >= 16) {
ch = 16;
}
#else
#define COL_W (LCD_W)
const uint8_t SLIDER_W = 90;
@@ -708,59 +709,64 @@ void menuModelFailsafe(uint8_t event)
// Channels
for (uint8_t line=0; line<8; line++) {
uint8_t y = 9+line*7;
int32_t val;
int32_t failsafeValue = 0;
bool failsafeEditable = false;
uint8_t ofs = (col ? 0 : 1);
if (ch < g_model.moduleData[g_moduleIdx].channelsStart || ch >= NUM_CHANNELS(g_moduleIdx) + g_model.moduleData[g_moduleIdx].channelsStart)
val = 0;
else if (s_editMode && m_posVert == ch)
val = channelOutputs[ch];
else
val = g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line];
if (ch < NUM_CHANNELS(g_moduleIdx)) {
if (s_editMode && m_posVert == ch) {
failsafeValue = channelOutputs[ch+channelStart];
}
else {
failsafeValue = g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line];
}
failsafeEditable = true;
}
if (failsafeEditable) {
#if defined(PCBTARANIS)
// Channel name if present, number if not
uint8_t lenLabel = ZLEN(g_model.limitData[ch].name);
if (lenLabel > 4) {
newLongNames = longNames = true;
}
if (lenLabel > 0)
lcd_putsnAtt(x+1-ofs, y, g_model.limitData[ch].name, sizeof(g_model.limitData[ch].name), ZCHAR | SMLSIZE);
else
// Channel name if present, number if not
uint8_t lenLabel = ZLEN(g_model.limitData[ch+channelStart].name);
if (lenLabel > 4) {
newLongNames = longNames = true;
}
if (lenLabel > 0)
lcd_putsnAtt(x+1-ofs, y, g_model.limitData[ch+channelStart].name, sizeof(g_model.limitData[ch+channelStart].name), ZCHAR | SMLSIZE);
else
putsChn(x+1-ofs, y, ch+1, SMLSIZE);
#else
putsChn(x+1-ofs, y, ch+1, SMLSIZE);
#else
putsChn(x+1-ofs, y, ch+1, SMLSIZE);
#endif
// Value
LcdFlags flags = TINSIZE;
if (m_posVert == ch && !s_noHi) {
flags |= INVERS;
if (s_editMode)
flags |= BLINK;
}
// failsafeValueue
LcdFlags flags = TINSIZE;
if (m_posVert == ch && !s_noHi) {
flags |= INVERS;
if (s_editMode)
flags |= BLINK;
}
#if defined(PPM_UNIT_US)
uint8_t wbar = (longNames ? SLIDER_W-10 : SLIDER_W);
lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, PPM_CH_CENTER(ch)+val/2, flags);
uint8_t wbar = (longNames ? SLIDER_W-10 : SLIDER_W);
lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, PPM_CH_CENTER(ch)+failsafeValue/2, flags);
#elif defined(PPM_UNIT_PERCENT_PREC1)
uint8_t wbar = (longNames ? SLIDER_W-16 : SLIDER_W-6);
lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, calcRESXto1000(val), PREC1|flags);
uint8_t wbar = (longNames ? SLIDER_W-16 : SLIDER_W-6);
lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, calcRESXto1000(failsafeValue), PREC1|flags);
#else
uint8_t wbar = (longNames ? SLIDER_W-10 : SLIDER_W);
lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, calcRESXto1000(val)/10, flags);
uint8_t wbar = (longNames ? SLIDER_W-10 : SLIDER_W);
lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, calcRESXto1000(failsafeValue)/10, flags);
#endif
// Gauge
lcd_rect(x+COL_W-3-wbar-ofs, y, wbar+1, 6);
uint16_t lim = g_model.extendedLimits ? 640*2 : 512*2;
uint8_t len = limit((uint8_t)1, uint8_t((abs(val) * wbar/2 + lim/2) / lim), uint8_t(wbar/2));
uint8_t x0 = (val>0) ? x+COL_W-ofs-3-wbar/2 : x+COL_W-ofs-2-wbar/2-len;
lcd_hline(x0, y+1, len);
lcd_hline(x0, y+2, len);
lcd_hline(x0, y+3, len);
lcd_hline(x0, y+4, len);
// Gauge
lcd_rect(x+COL_W-3-wbar-ofs, y, wbar+1, 6);
uint16_t lim = g_model.extendedLimits ? 640*2 : 512*2;
uint8_t len = limit((uint8_t)1, uint8_t((abs(failsafeValue) * wbar/2 + lim/2) / lim), uint8_t(wbar/2));
uint8_t x0 = (failsafeValue>0) ? x+COL_W-ofs-3-wbar/2 : x+COL_W-ofs-2-wbar/2-len;
lcd_hline(x0, y+1, len);
lcd_hline(x0, y+2, len);
lcd_hline(x0, y+3, len);
lcd_hline(x0, y+4, len);
}
ch++;
}
}
@@ -988,24 +994,28 @@ void menuModelSetup(uint8_t event)
#define IF_EXTERNAL_MODULE_ON(x) (g_model.externalModule == MODULE_TYPE_NONE ? HIDDEN_ROW : (uint8_t)(x))
#define IF_TRAINER_ON(x) (g_model.trainerMode ? (uint8_t)(x) : HIDDEN_ROW)
#define IF_EXTERNAL_MODULE_XJT(x) (IS_MODULE_XJT(EXTERNAL_MODULE) ? (uint8_t)x : HIDDEN_ROW)
#define IS_D8_RX(x) (g_model.moduleData[x].rfProtocol == RF_PROTO_D8)
#define INTERNAL_MODULE_CHANNELS_ROWS() IF_INTERNAL_MODULE_ON(1)
#define EXTERNAL_MODULE_CHANNELS_ROWS() IF_EXTERNAL_MODULE_ON(IS_MODULE_DSM2(EXTERNAL_MODULE) ? (uint8_t)0 : (uint8_t)1)
#define TRAINER_CHANNELS_ROWS() IF_TRAINER_ON(1)
#define PORT_CHANNELS_ROWS(x) (x==INTERNAL_MODULE ? INTERNAL_MODULE_CHANNELS_ROWS() : (x==EXTERNAL_MODULE ? EXTERNAL_MODULE_CHANNELS_ROWS() : TRAINER_CHANNELS_ROWS()))
#define FAILSAFE_ROWS(x) ((g_model.moduleData[x].rfProtocol==RF_PROTO_X16 || g_model.moduleData[x].rfProtocol==RF_PROTO_LR12) ? (g_model.moduleData[x].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW)
#define INTERNAL_MODULE_CHANNELS_ROWS IF_INTERNAL_MODULE_ON(1)
#define EXTERNAL_MODULE_CHANNELS_ROWS IF_EXTERNAL_MODULE_ON(IS_MODULE_DSM2(EXTERNAL_MODULE) ? (uint8_t)0 : (uint8_t)1)
#define TRAINER_CHANNELS_ROWS IF_TRAINER_ON(1)
#define PORT_CHANNELS_ROWS(x) (x==INTERNAL_MODULE ? INTERNAL_MODULE_CHANNELS_ROWS : (x==EXTERNAL_MODULE ? EXTERNAL_MODULE_CHANNELS_ROWS : TRAINER_CHANNELS_ROWS))
#define FAILSAFE_ROWS(x) (HAS_RF_PROTOCOL_FAILSAFE(g_model.moduleData[x].rfProtocol) ? (g_model.moduleData[x].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW)
#if defined(MODULE_D16_EU_ONLY_SUPPORT)
#define EXTERNAL_MODULE_MODE_ROWS IS_MODULE_DSM2(EXTERNAL_MODULE) ? (uint8_t)1 : (uint8_t)0
#else
#define EXTERNAL_MODULE_MODE_ROWS (IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0
#endif
#define MODEL_SETUP_MAX_LINES (1+ITEM_MODEL_SETUP_MAX)
#define POT_WARN_ITEMS() ((g_model.nPotsToWarn >> 6) ? (uint8_t)NUM_POTS : (uint8_t)0)
bool CURSOR_ON_CELL = (m_posHorz >= 0);
MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2|NAVIGATION_LINE_BY_LINE, CASE_PERSISTENT_TIMERS(0) 0, 0, 2|NAVIGATION_LINE_BY_LINE, CASE_PERSISTENT_TIMERS(0) 0, 0, 0, 1, 0, CASE_PCBTARANIS(LABEL(Throttle)) 0, 0, 0, CASE_CPUARM(LABEL(PreflightCheck)) CASE_CPUARM(0) 0, 7, POT_WARN_ITEMS(), NAVIGATION_LINE_BY_LINE|(NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1), LABEL(InternalModule), 0, IF_INTERNAL_MODULE_ON(1), IF_INTERNAL_MODULE_ON(IS_D8_RX(0) ? (uint8_t)1 : (uint8_t)2), IF_INTERNAL_MODULE_ON(FAILSAFE_ROWS(INTERNAL_MODULE)), LABEL(ExternalModule), (IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0, EXTERNAL_MODULE_CHANNELS_ROWS(), (IS_MODULE_XJT(EXTERNAL_MODULE) && IS_D8_RX(EXTERNAL_MODULE)) ? (uint8_t)1 : (IS_MODULE_PPM(EXTERNAL_MODULE) || IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)2 : HIDDEN_ROW, IF_EXTERNAL_MODULE_XJT(FAILSAFE_ROWS(EXTERNAL_MODULE)), LABEL(Trainer), 0, TRAINER_CHANNELS_ROWS(), IF_TRAINER_ON(2)});
MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2|NAVIGATION_LINE_BY_LINE, CASE_PERSISTENT_TIMERS(0) 0, 0, 2|NAVIGATION_LINE_BY_LINE, CASE_PERSISTENT_TIMERS(0) 0, 0, 0, 1, 0, CASE_PCBTARANIS(LABEL(Throttle)) 0, 0, 0, CASE_CPUARM(LABEL(PreflightCheck)) CASE_CPUARM(0) 0, 7, POT_WARN_ITEMS(), NAVIGATION_LINE_BY_LINE|(NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1), LABEL(InternalModule), 0, IF_INTERNAL_MODULE_ON(1), IF_INTERNAL_MODULE_ON(HAS_RF_PROTOCOL_FAILSAFE(g_model.moduleData[0].rfProtocol) ? (uint8_t)2 : (uint8_t)1), IF_INTERNAL_MODULE_ON(FAILSAFE_ROWS(INTERNAL_MODULE)), LABEL(ExternalModule), EXTERNAL_MODULE_MODE_ROWS, EXTERNAL_MODULE_CHANNELS_ROWS, (IS_MODULE_XJT(EXTERNAL_MODULE) && !HAS_RF_PROTOCOL_FAILSAFE(g_model.moduleData[EXTERNAL_MODULE].rfProtocol)) ? (uint8_t)1 : (IS_MODULE_PPM(EXTERNAL_MODULE) || IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)2 : HIDDEN_ROW, IF_EXTERNAL_MODULE_XJT(FAILSAFE_ROWS(EXTERNAL_MODULE)), LABEL(Trainer), 0, TRAINER_CHANNELS_ROWS, IF_TRAINER_ON(2)});
#elif defined(CPUARM)
#define IF_EXTERNAL_MODULE_XJT(x) (IS_MODULE_XJT(EXTERNAL_MODULE) ? (uint8_t)x : HIDDEN_ROW)
#define IF_EXTERNAL_MODULE_ON(x) (g_model.externalModule == MODULE_TYPE_NONE ? HIDDEN_ROW : (uint8_t)(x))
#define IS_D8_RX(x) (g_model.moduleData[x].rfProtocol == RF_PROTO_D8)
#define EXTERNAL_MODULE_CHANNELS_ROWS() IF_EXTERNAL_MODULE_ON(IS_MODULE_DSM2(EXTERNAL_MODULE) ? (uint8_t)0 : (uint8_t)1)
#define EXTERNAL_MODULE_CHANNELS_ROWS IF_EXTERNAL_MODULE_ON(IS_MODULE_DSM2(EXTERNAL_MODULE) ? (uint8_t)0 : (uint8_t)1)
#define TRAINER_CHANNELS_ROWS() (HIDDEN_ROW)
#define PORT_CHANNELS_ROWS(x) (x==EXTERNAL_MODULE ? EXTERNAL_MODULE_CHANNELS_ROWS() : 0)
#define FAILSAFE_ROWS(x) ((g_model.moduleData[x].rfProtocol==RF_PROTO_X16 || g_model.moduleData[x].rfProtocol==RF_PROTO_LR12) ? (g_model.moduleData[x].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW)
#define PORT_CHANNELS_ROWS(x) (x==EXTERNAL_MODULE ? EXTERNAL_MODULE_CHANNELS_ROWS : 0)
#define FAILSAFE_ROWS(x) (HAS_RF_PROTOCOL_FAILSAFE(g_model.moduleData[x].rfProtocol) ? (g_model.moduleData[x].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW)
#define CURSOR_ON_CELL (true)
#define MODEL_SETUP_MAX_LINES (1+ITEM_MODEL_SETUP_MAX)
#define POT_WARN_ITEMS() ((g_model.nPotsToWarn >> 6) ? (uint8_t)NUM_POTS : (uint8_t)0)
@@ -1019,7 +1029,7 @@ void menuModelSetup(uint8_t event)
#else
#define TRAINER_MODULE_ROWS
#endif
MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2, CASE_PERSISTENT_TIMERS(0) 0, 0, 2, CASE_PERSISTENT_TIMERS(0) 0, 0, 0, 1, 0, CASE_PCBTARANIS(LABEL(Throttle)) 0, 0, 0, CASE_CPUARM(LABEL(PreflightCheck)) CASE_CPUARM(0) 0, 6, NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1, LABEL(ExternalModule), (IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0, EXTERNAL_MODULE_CHANNELS_ROWS(), (IS_MODULE_XJT(EXTERNAL_MODULE) && IS_D8_RX(EXTERNAL_MODULE)) ? (uint8_t)1 : (IS_MODULE_PPM(EXTERNAL_MODULE) || IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)2 : HIDDEN_ROW, IF_EXTERNAL_MODULE_XJT(FAILSAFE_ROWS(EXTERNAL_MODULE)), EXTRA_MODULE_ROWS TRAINER_MODULE_ROWS });
MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2, CASE_PERSISTENT_TIMERS(0) 0, 0, 2, CASE_PERSISTENT_TIMERS(0) 0, 0, 0, 1, 0, CASE_PCBTARANIS(LABEL(Throttle)) 0, 0, 0, CASE_CPUARM(LABEL(PreflightCheck)) CASE_CPUARM(0) 0, 6, NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1, LABEL(ExternalModule), (IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0, EXTERNAL_MODULE_CHANNELS_ROWS, (IS_MODULE_XJT(EXTERNAL_MODULE) && IS_D8_RX(EXTERNAL_MODULE)) ? (uint8_t)1 : (IS_MODULE_PPM(EXTERNAL_MODULE) || IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)2 : HIDDEN_ROW, IF_EXTERNAL_MODULE_XJT(FAILSAFE_ROWS(EXTERNAL_MODULE)), EXTRA_MODULE_ROWS TRAINER_MODULE_ROWS });
#elif defined(CPUM64)
#define CURSOR_ON_CELL (true)
#define MODEL_SETUP_MAX_LINES ((IS_PPM_PROTOCOL(protocol)||IS_DSM2_PROTOCOL(protocol)||IS_PXX_PROTOCOL(protocol)) ? 1+ITEM_MODEL_SETUP_MAX : ITEM_MODEL_SETUP_MAX)
@@ -1107,7 +1117,7 @@ void menuModelSetup(uint8_t event)
#if defined(CPUARM)
timer->countdownBeep = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_BEEPCOUNTDOWN, STR_VBEEPCOUNTDOWN, timer->countdownBeep, 0, 2, attr, event);
#else
timer->countdownBeep = onoffMenuItem(timer->countdownBeep, MODEL_SETUP_2ND_COLUMN, y, STR_BEEPCOUNTDOWN, attr, event);
timer->countdownBeep = onoffMenuItem(timer->countdownBeep, MODEL_SETUP_2ND_COLUMN, y, STR_BEEPCOUNTDOWN, attr, event);
#endif
}
else {
@@ -1235,7 +1245,7 @@ void menuModelSetup(uint8_t event)
case ITEM_MODEL_THROTTLE_WARNING:
g_model.disableThrottleWarning = !onoffMenuItem(!g_model.disableThrottleWarning, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLEWARNING, attr, event);
break;
case ITEM_MODEL_SWITCHES_WARNING:
{
lcd_putsLeft(y, STR_SWITCHWARNING);
@@ -1257,7 +1267,7 @@ void menuModelSetup(uint8_t event)
}
#endif
break;
case EVT_KEY_LONG(KEY_ENTER):
#if defined(CPUM64)
getMovedSwitch();
@@ -1274,24 +1284,24 @@ void menuModelSetup(uint8_t event)
}
#endif
killEvents(event);
break;
break;
}
}
}
LcdFlags line = attr;
for (uint8_t i=0; i<NUM_SWITCHES-1; i++) {
uint8_t swactive = !(g_model.nSwToWarn & 1 << i);
#if defined(PCBTARANIS)
c = "\300-\301"[states & 0x03];
lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+i*(2*FW+1), y, 'A'+i, line && (m_posHorz == i) ? INVERS : 0);
if (swactive) lcd_putc(MODEL_SETUP_2ND_COLUMN+i*(2*FW+1)+FWNUM+1, y, c);
lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+((NUM_SWITCHES-1)*2*FW+8), y, PSTR("<]"), (m_posHorz == NUM_SWITCHES-1 && !s_noHi) ? line : 0);
lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+((NUM_SWITCHES-1)*2*FW+8), y, PSTR("<]"), (m_posHorz == NUM_SWITCHES-1 && !s_noHi) ? line : 0);
states >>= 2;
#else
attr = 0;
if (IS_3POS(i)) {
c = '0'+(states & 0x03);
states >>= 2;
@@ -1310,7 +1320,7 @@ void menuModelSetup(uint8_t event)
lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+i*FW, y, (swactive || (attr & BLINK)) ? c : '-', attr);
#if !defined(CPUM64)
lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+(NUM_SWITCHES*FW), y, PSTR("<]"), (m_posHorz == NUM_SWITCHES-1 && !s_noHi) ? line : 0);
#endif
#endif
#endif
}
break;
@@ -1356,7 +1366,7 @@ void menuModelSetup(uint8_t event)
x += (2*FW+3);
}
}
if (attr && (m_posHorz == 0)) {
CHECK_INCDEC_MODELVAR(event, potMode, 0, 2);
g_model.nPotsToWarn = (g_model.nPotsToWarn & 0x3F) | ((potMode << 6) & 0xC0);
@@ -1542,7 +1552,7 @@ void menuModelSetup(uint8_t event)
else {
horzpos_t l_posHorz = m_posHorz;
uint8_t xOffsetBind = MODEL_SETUP_BIND_OFS;
if (IS_MODULE_XJT(moduleIdx) && IS_D8_RX(moduleIdx)) {
if (IS_MODULE_XJT(moduleIdx) && !HAS_RF_PROTOCOL_FAILSAFE(g_model.moduleData[moduleIdx].rfProtocol)) {
xOffsetBind = 0;
lcd_putsLeft(y, INDENT "Receiver");
if (attr) l_posHorz += 1;
@@ -2216,7 +2226,7 @@ void menuModelFlightModesAll(uint8_t event)
#endif
}
if (p->fadeIn || p->fadeOut)
if (p->fadeIn || p->fadeOut)
lcd_putc(LCD_W-FW-MENUS_SCROLLBAR_WIDTH, y, (p->fadeIn && p->fadeOut) ? '*' : (p->fadeIn ? 'I' : 'O'));
}
@@ -3189,7 +3199,7 @@ void menuModelMixOne(uint8_t event)
if ((m_posVert == MIX_FIELD_TRIM && md2->srcRaw > NUM_STICKS) || (m_posVert == MIX_FIELD_CURVE && md2->curveMode == MODE_CURVE))
#else
if (m_posVert == MIX_FIELD_TRIM && md2->srcRaw > NUM_STICKS)
#endif
#endif
SUBMENU_NOTITLE(MIX_FIELD_COUNT, {CASE_CPUARM(0) 0, 0, 0, CASE_9X(0) CASE_CURVES(0) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/})
else
SUBMENU_NOTITLE(MIX_FIELD_COUNT, {CASE_CPUARM(0) 0, 0, 0, CASE_9X(1) CASE_CURVES(1) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/});
@@ -3508,7 +3518,7 @@ void displayExpoInfos(uint8_t y, ExpoData *ed)
#if defined(PCBTARANIS)
void displayExpoLine(uint8_t y, ExpoData *ed)
{
{
putsMixerSource(EXPO_LINE_SRC_POS, y, ed->srcRaw, 0);
if (ed->carryTrim != TRIM_ON) {
@@ -3519,7 +3529,7 @@ void displayExpoLine(uint8_t y, ExpoData *ed)
displayExpoInfos(y, ed);
else
displayFlightModes(EXPO_LINE_FM_POS, y, ed->flightModes);
if (ed->name[0]) {
lcd_putsnAtt(EXPO_LINE_NAME_POS, y, ed->name, sizeof(ed->name), ZCHAR);
}
@@ -3528,7 +3538,7 @@ void displayExpoLine(uint8_t y, ExpoData *ed)
void displayExpoLine(uint8_t y, ExpoData *ed)
{
displayExpoInfos(y, ed);
if (ed->name[0]) {
lcd_putsnAtt(EXPO_LINE_NAME_POS, y, ed->name, sizeof(ed->name), ZCHAR);
}
@@ -3536,7 +3546,7 @@ void displayExpoLine(uint8_t y, ExpoData *ed)
#else
#define displayExpoLine(y, ed) \
displayExpoInfos(y, ed); \
displayFlightModes(EXPO_LINE_FM_POS, y, ed->flightModes)
displayFlightModes(EXPO_LINE_FM_POS, y, ed->flightModes)
#endif
void menuModelExpoMix(uint8_t expo, uint8_t event)
@@ -3735,13 +3745,13 @@ void menuModelExpoMix(uint8_t expo, uint8_t event)
s_currIdx = i;
}
if (s_pgOfs < cur && cur-s_pgOfs < 8) {
uint8_t attr = ((s_copyMode || sub != cur) ? 0 : INVERS);
uint8_t attr = ((s_copyMode || sub != cur) ? 0 : INVERS);
if (expo) {
ed->weight = GVAR_MENU_ITEM(EXPO_LINE_WEIGHT_POS, y, ed->weight, MIN_EXPO_WEIGHT, 100, attr | (isExpoActive(i) ? BOLD : 0), 0, event);
displayExpoLine(y, ed);
if (ed->mode!=3) {
lcd_putc(EXPO_LINE_SIDE_POS, y, ed->mode == 2 ? 126 : 127);
}
}
}
else {
#if LCD_W >= 212
@@ -3757,7 +3767,7 @@ void menuModelExpoMix(uint8_t expo, uint8_t event)
gvarWeightItem(MIX_LINE_WEIGHT_POS, y, md, attr | (isMixActive(i) ? BOLD : 0), event);
displayMixLine(y, md);
char cs = ' ';
if (md->speedDown || md->speedUp)
cs = 'S';
@@ -5645,7 +5655,7 @@ enum menuModelTelemetryItems {
#if defined(FAS_OFFSET) || !defined(CPUM64)
#define IF_FAS_OFFSET(x) x,
#else
#define IF_FAS_OFFSET(x)
#define IF_FAS_OFFSET(x)
#endif
#if defined(PCBTARANIS)
@@ -5884,7 +5894,7 @@ void menuModelTelemetry(uint8_t event)
lcd_putsiAtt(TELEM_COL2, y, STR_AMPSRC, g_model.frsky.currentSource, attr);
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.currentSource, FRSKY_CURRENT_SOURCE_LAST);
break;
#if defined(FAS_OFFSET) || !defined(CPUM64)
case ITEM_TELEMETRY_FAS_OFFSET:
lcd_putsLeft(y, STR_FAS_OFFSET);
@@ -5898,7 +5908,7 @@ void menuModelTelemetry(uint8_t event)
#if defined(CPUARM)
case ITEM_TELEMTETRY_PERSISTENT_MAH:
g_model.frsky.mAhPersistent = onoffMenuItem(g_model.frsky.mAhPersistent, TELEM_COL2, y, STR_PERSISTENT_MAH, attr, event);
break;
break;
#endif
#if defined(VARIO)
+1 -1
View File
@@ -398,7 +398,7 @@ void displayBattVoltage()
LcdFlags att = (g_vbat100mV <= g_eeGeneral.vBatWarn ? BLINK|INVERS : 0) | BIGSIZE;
putsVBat(VBATT_X-1, VBATT_Y, att|NO_UNIT);
#if LCD_W >= 212
lcd_putcAtt(VBATTUNIT_X, VBATTUNIT_Y, 'v', MIDSIZE);
lcd_putcAtt(VBATTUNIT_X, VBATTUNIT_Y, 'V', MIDSIZE);
#else
lcd_putc(VBATT_X, VBATTUNIT_Y, 'V');
#endif
+2 -2
View File
@@ -666,7 +666,7 @@ void putsTimer(xcoord_t x, uint8_t y, putstime_t tme, LcdFlags att, LcdFlags att
void putsVolts(xcoord_t x, uint8_t y, uint16_t volts, LcdFlags att)
{
lcd_outdezAtt(x, y, (int16_t)volts, (~NO_UNIT) & (att | ((att&PREC2)==PREC2 ? 0 : PREC1)));
if (~att & NO_UNIT) lcd_putcAtt(lcdLastPos, y, 'v', att);
if (~att & NO_UNIT) lcd_putcAtt(lcdLastPos, y, 'V', att);
}
void putsVBat(xcoord_t x, uint8_t y, LcdFlags att)
@@ -1079,7 +1079,7 @@ void putsTelemetryChannel(xcoord_t x, uint8_t y, uint8_t channel, lcdint_t val,
case TELEM_TX_VOLTAGE-1:
lcd_outdezAtt(x, y, val, (att|PREC1) & (~NO_UNIT));
if (!(att & NO_UNIT))
lcd_putc(lcdLastPos/*+1*/, y, 'v');
lcd_putc(lcdLastPos/*+1*/, y, 'V');
break;
}
}
+1 -1
View File
@@ -689,7 +689,7 @@ static int luaModelInsertInput(lua_State *L)
unsigned int first = getFirstInput(chn);
unsigned int count = getInputsCountFromFirst(chn, first);
if (chn<MAX_INPUTS && getExpoMixCount(1)<MAX_INPUTS && idx<=count) {
if (chn<MAX_INPUTS && getExpoMixCount(1)<MAX_EXPOS && idx<=count) {
idx = first + idx;
s_currCh = chn + 1;
insertExpoMix(1, idx);
+10
View File
@@ -1676,11 +1676,21 @@ enum Protocols {
enum RFProtocols {
RF_PROTO_OFF = -1,
RF_PROTO_X16,
#if defined(MODULE_D16_EU_ONLY_SUPPORT)
RF_PROTO_LAST = RF_PROTO_X16
#else
RF_PROTO_D8,
RF_PROTO_LR12,
RF_PROTO_LAST = RF_PROTO_LR12
#endif
};
#if defined(MODULE_D16_EU_ONLY_SUPPORT)
#define HAS_RF_PROTOCOL_FAILSAFE(protocol) ((protocol) == RF_PROTO_X16)
#else
#define HAS_RF_PROTOCOL_FAILSAFE(protocol) ((protocol) == RF_PROTO_X16 || (protocol) == RF_PROTO_LR12)
#endif
enum DSM2Protocols {
DSM2_PROTO_LP45,
DSM2_PROTO_DSM2,
+6 -4
View File
@@ -247,7 +247,7 @@ void per10ms()
}
#endif
#if defined(FRSKY) || defined(JETI) || defined(SIMU)
#if defined(FRSKY) || defined(JETI)
if (!IS_DSM2_SERIAL_PROTOCOL(s_current_protocol[0]))
telemetryInterrupt10ms();
#endif
@@ -2076,9 +2076,11 @@ void evalFunctions()
}
case FUNC_BACKGND_MUSIC:
newActiveFunctions |= (1 << FUNCTION_BACKGND_MUSIC);
if (!IS_PLAYING(i+1)) {
playCustomFunctionFile(sd, i+1);
if (!(newActiveFunctions & (1 << FUNCTION_BACKGND_MUSIC))) {
newActiveFunctions |= (1 << FUNCTION_BACKGND_MUSIC);
if (!IS_PLAYING(i+1)) {
playCustomFunctionFile(sd, i+1);
}
}
break;
+3 -1
View File
@@ -171,7 +171,9 @@ void setupPulsesDSM2(unsigned int port)
dsmDat[1] = g_model.header.modelId; // DSM2 Header second byte for model match
for (int i=0; i<DSM2_CHANS; i++) {
uint16_t pulse = limit(0, ((channelOutputs[g_model.moduleData[port].channelsStart+i]*13)>>5)+512, 1023);
int channel = g_model.moduleData[port].channelsStart+i;
int value = channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER;
uint16_t pulse = limit(0, ((value*13)>>5)+512, 1023);
dsmDat[2+2*i] = (i<<2) | ((pulse>>8)&0x03);
dsmDat[3+2*i] = pulse & 0xff;
}
+2 -2
View File
@@ -243,9 +243,9 @@ void setupPulsesPXX(unsigned int port)
}
else {
if (i < sendUpperChannels)
chan = limit(2049, PPM_CH_CENTER(8+g_model.moduleData[port].channelsStart+i) - PPM_CENTER + (g_model.moduleData[port].failsafeChannels[8+g_model.moduleData[port].channelsStart+i] * 512 / 682) + 3072, 4094);
chan = limit(2049, PPM_CH_CENTER(8+g_model.moduleData[port].channelsStart+i) - PPM_CENTER + (g_model.moduleData[port].failsafeChannels[8+i] * 512 / 682) + 3072, 4094);
else
chan = limit(1, PPM_CH_CENTER(g_model.moduleData[port].channelsStart+i) - PPM_CENTER + (g_model.moduleData[port].failsafeChannels[g_model.moduleData[port].channelsStart+i] * 512 / 682) + 1024, 2046);
chan = limit(1, PPM_CH_CENTER(g_model.moduleData[port].channelsStart+i) - PPM_CENTER + (g_model.moduleData[port].failsafeChannels[i] * 512 / 682) + 1024, 2046);
}
}
else {
+2
View File
@@ -421,6 +421,8 @@ int main(int argc,char **argv)
printf("Model size = %d\n", (int)sizeof(g_model));
simuInit();
StartEepromThread(argc >= 2 ? argv[1] : "eeprom.bin");
StartAudioThread();
StartMainThread();
+14 -1
View File
@@ -219,7 +219,12 @@ bool getLogicalSwitch(uint8_t idx)
#endif
if (ls->func == LS_FUNC_NONE || (s && !getSwitch(s))) {
#if defined(CPUARM)
if (ls->func != LS_FUNC_STICKY && ls->func != LS_FUNC_STAY ) {
#else
if (ls->func != LS_FUNC_STICKY) {
#endif
// AND switch must not affect STICKY and EDGE (STAY) processing
LS_LAST_VALUE(mixerCurrentFlightMode, idx) = CS_LAST_VALUE_INIT;
}
result = false;
@@ -378,7 +383,7 @@ DurationAndDelayProcessing:
if (context.timerState == SWITCH_START) {
// set delay timer
context.timerState = SWITCH_DELAY;
context.timer = ls->delay;
context.timer = (ls->func == LS_FUNC_STAY ? 0 : ls->delay);
}
if (context.timerState == SWITCH_DELAY) {
@@ -776,6 +781,13 @@ void logicalSwitchesTimerTick()
#if defined(CPUARM)
else if (ls->func == LS_FUNC_STAY) {
ls_stay_struct & lastValue = (ls_stay_struct &)LS_LAST_VALUE(fm, i);
// if this ls was reset by the logicalSwitchesReset() the lastValue will be set to CS_LAST_VALUE_INIT(0x8000)
// when it is unpacked into ls_stay_struct the lastValue.duration will have a value of 0x4000
// this will produce an instant true for edge logical switch if the second parameter is big enough.
// So we reset it here.
if (LS_LAST_VALUE(fm, i) == CS_LAST_VALUE_INIT) {
lastValue.duration = 0;
}
lastValue.state = false;
bool state = getSwitch(ls->v1);
if (state) {
@@ -834,6 +846,7 @@ int16_t lswTimerValue(delayval_t val)
void logicalSwitchesReset()
{
#if defined(CPUARM)
flightModeTransitionLast = 255;
memset(lswFm, 0, sizeof(lswFm));
#else
s_last_switch_value = 0;
+100 -48
View File
@@ -109,6 +109,14 @@ char simuSdDirectory[1024] = "";
uint8_t eeprom[EESIZE_SIMU];
sem_t *eeprom_write_sem;
void simuInit()
{
for (int i = 0; i <= 17; i++) {
simuSetSwitch(i, 0);
simuSetKey(i, false); // a little dirty, but setting keys that don't exist is perfectly OK here
}
}
#if defined(CPUARM)
#if defined(PCBTARANIS)
#define SWITCH_CASE(swtch, pin, mask) \
@@ -380,7 +388,21 @@ void StartMainThread(bool tests)
pthread_mutex_init(&audioMutex, NULL);
#endif
g_tmr10ms = 1; // must be non-zero otherwise some SF functions (that use this timer as a marker when it was last executed) will be executed twice on startup
/*
g_tmr10ms must be non-zero otherwise some SF functions (that use this timer as a marker when it was last executed)
will be executed twice on startup. Normal radio does not see this issue because g_tmr10ms is already a big number
before the first call to the Special Functions. Not so in the simulator.
There is another issue, some other function static variables depend on this value. If simulator is started
multiple times in one Companion session, they are set to their initial values only first time the simulator
is started. Therefore g_tmr10ms must also be set to non-zero value only the first time, then it must be left
alone to continue from the previous simulator session value. See the issue #2446
*/
if (g_tmr10ms == 0) {
g_tmr10ms = 1;
}
#if defined(RTCLOCK)
g_rtcTime = time(0);
#endif
@@ -396,7 +418,16 @@ void StopMainThread()
}
#if defined(CPUARM)
int Volume = volumeScale[VOLUME_LEVEL_DEF];
struct SimulatorAudio {
int volumeGain;
int currentVolume;
uint16_t leftoverData[AUDIO_BUFFER_SIZE];
int leftoverLen;
bool threadRunning;
pthread_t threadPid;
} simuAudio;
bool dacQueue(AudioBuffer *buffer)
{
return false;
@@ -404,33 +435,31 @@ bool dacQueue(AudioBuffer *buffer)
void setVolume(uint8_t volume)
{
Volume = volumeScale[min<uint8_t>(volume, VOLUME_LEVEL_MAX)];
simuAudio.currentVolume = min<int>((volumeScale[min<uint8_t>(volume, VOLUME_LEVEL_MAX)] * simuAudio.volumeGain) / 10, 127);
// TRACE("setVolume(): in: %u, out: %u", volume, simuAudio.currentVolume);
}
#endif
#if defined(SIMU_AUDIO) && defined(CPUARM)
int leftover_len = 0;
uint16_t leftover_data[AUDIO_BUFFER_SIZE];
void copyBuffer(uint8_t * dest, uint16_t * buff, unsigned int samples)
{
for(unsigned int i=0; i<samples; i++) {
int sample = ((int32_t)(uint32_t)(buff[i]) - 0x8000); // conversion from uint16_t
*((uint16_t*)dest) = (int16_t)((sample * Volume)/127);
*((uint16_t*)dest) = (int16_t)((sample * simuAudio.currentVolume)/127);
dest += 2;
}
}
void fill_audio(void *udata, Uint8 *stream, int len)
void fillAudioBuffer(void *udata, Uint8 *stream, int len)
{
SDL_memset(stream, 0, len);
if (leftover_len) {
copyBuffer(stream, leftover_data, leftover_len);
len -= leftover_len*2;
stream += leftover_len*2;
leftover_len = 0;
if (simuAudio.leftoverLen) {
copyBuffer(stream, simuAudio.leftoverData, simuAudio.leftoverLen);
len -= simuAudio.leftoverLen*2;
stream += simuAudio.leftoverLen*2;
simuAudio.leftoverLen = 0;
// putchar('l');
}
@@ -447,8 +476,8 @@ void fill_audio(void *udata, Uint8 *stream, int len)
else {
//partial
copyBuffer(stream, nextBuffer->data, len/2);
leftover_len = (nextBuffer->size-len/2);
memcpy(leftover_data, &nextBuffer->data[len/2], leftover_len*2);
simuAudio.leftoverLen = (nextBuffer->size-len/2);
memcpy(simuAudio.leftoverData, &nextBuffer->data[len/2], simuAudio.leftoverLen*2);
len = 0;
// putchar('p');
break;
@@ -467,9 +496,7 @@ void fill_audio(void *udata, Uint8 *stream, int len)
}
}
bool audio_thread_running = false;
void *audio_thread(void *)
void * audioThread(void *)
{
/*
Checking here if SDL audio was initialized is wrong, because
@@ -488,7 +515,7 @@ void *audio_thread(void *)
wanted.format = AUDIO_S16SYS;
wanted.channels = 1; /* 1 = mono, 2 = stereo */
wanted.samples = AUDIO_BUFFER_SIZE*2; /* Good low-latency value for callback */
wanted.callback = fill_audio;
wanted.callback = fillAudioBuffer;
wanted.userdata = NULL;
/*
@@ -501,7 +528,7 @@ void *audio_thread(void *)
}
SDL_PauseAudio(0);
while (audio_thread_running) {
while (simuAudio.threadRunning) {
audioQueue.wakeup();
sleep(1);
}
@@ -509,26 +536,28 @@ void *audio_thread(void *)
return 0;
}
pthread_t audio_thread_pid;
void StartAudioThread()
void StartAudioThread(int volumeGain)
{
simuAudio.leftoverLen = 0;
simuAudio.threadRunning = true;
simuAudio.volumeGain = volumeGain;
setVolume(VOLUME_LEVEL_DEF);
pthread_attr_t attr;
pthread_attr_init(&attr);
struct sched_param sp;
sp.sched_priority = SCHED_RR;
pthread_attr_setschedparam(&attr, &sp);
pthread_create(&audio_thread_pid, &attr, &audio_thread, NULL);
audio_thread_running = true;
pthread_create(&simuAudio.threadPid, &attr, &audioThread, NULL);
return;
}
void StopAudioThread()
{
audio_thread_running = false;
pthread_join(audio_thread_pid, NULL);
simuAudio.threadRunning = false;
pthread_join(simuAudio.threadPid, NULL);
}
#endif // #if defined(CPUARM)
#endif // #if defined(SIMU_AUDIO) && defined(CPUARM)
pthread_t eeprom_thread_pid;
@@ -673,28 +702,26 @@ char *findTrueFileName(const char *path)
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
_splitpath(path, drive, dir, fname, ext);
std::string fileName = std::string(fname) + "." + std::string(ext);
std::string fileName = std::string(fname) + std::string(ext);
std::string dirName = std::string(drive) + std::string(dir);
if (dir) {
// TRACE("\tsearching for: %s", fileName.c_str());
WIN32_FIND_DATA ffd;
HANDLE hFind = FindFirstFile(dirName.c_str(), &ffd);
if (INVALID_HANDLE_VALUE != hFind) {
do {
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == 0) {
// TRACE("comparing with: %s", ffd.cFileName);
if (!strcasecmp(fileName.c_str(), ffd.cFileName)) {
strcpy(result, dirName.c_str());
strcat(result, "/");
strcat(result, ffd.cFileName);
TRACE("\tfound: %s", ffd.cFileName);
fileMap.insert(filemap_t:: value_type(path, result));
return result;
}
std::string searchName = dirName + "*";
// TRACE("\tsearching for: %s", fileName.c_str());
WIN32_FIND_DATA ffd;
HANDLE hFind = FindFirstFile(searchName.c_str(), &ffd);
if (INVALID_HANDLE_VALUE != hFind) {
do {
if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
//TRACE("comparing with: %s", ffd.cFileName);
if (!strcasecmp(fileName.c_str(), ffd.cFileName)) {
strcpy(result, dirName.c_str());
strcat(result, ffd.cFileName);
TRACE("\tfound: %s", ffd.cFileName);
fileMap.insert(filemap_t:: value_type(path, result));
return result;
}
}
while (FindNextFile(hFind, &ffd) != 0);
}
while (FindNextFile(hFind, &ffd) != 0);
}
#else
strcpy(result, path);
@@ -707,7 +734,11 @@ char *findTrueFileName(const char *path)
for (;;) {
struct simu::dirent * res = simu::readdir(dir);
if (res == 0) break;
#if defined(__APPLE__)
if ((res->d_type == DT_REG) || (res->d_type == DT_LNK)) {
#else
if ((res->d_type == simu::DT_REG) || (res->d_type == simu::DT_LNK)) {
#endif
// TRACE("comparing with: %s", res->d_name);
if (!strcasecmp(fileName.c_str(), res->d_name)) {
strcpy(result, dirName.c_str());
@@ -861,8 +892,14 @@ FRESULT f_mkdir (const TCHAR*)
return FR_OK;
}
FRESULT f_unlink (const TCHAR*)
FRESULT f_unlink (const TCHAR* name)
{
char *path = convertSimuPath(name);
if (unlink(path)) {
TRACE("f_unlink(%s) = error %d (%s)", path, errno, strerror(errno));
return FR_INVALID_NAME;
}
TRACE("f_unlink(%s) = OK", path);
return FR_OK;
}
@@ -892,7 +929,22 @@ int f_printf (FIL *fil, const TCHAR * format, ...)
FRESULT f_getcwd (TCHAR *path, UINT sz_path)
{
strcpy(path, ".");
char cwd[1024];
if (!getcwd(cwd, 1024)) {
TRACE("f_getcwd() = getcwd() error %d (%s)", errno, strerror(errno));
strcpy(path, ".");
return FR_NO_PATH;
}
if (strlen(cwd) < strlen(simuSdDirectory)) {
TRACE("f_getcwd() = logic error strlen(cwd) < strlen(simuSdDirectory): cwd: \"%s\", simuSdDirectory: \"%s\"", cwd, simuSdDirectory);
strcpy(path, ".");
return FR_NO_PATH;
}
// remove simuSdDirectory from the cwd
strcpy(path, cwd + strlen(simuSdDirectory));
TRACE("f_getcwd() = %s", path);
return FR_OK;
}
+2 -1
View File
@@ -345,6 +345,7 @@ extern uint8_t main_thread_running;
#define SIMU_SLEEP(x) do { if (!main_thread_running) return; sleep(x/*ms*/); } while (0)
void simuInit();
void simuSetKey(uint8_t key, bool state);
void simuSetTrim(uint8_t trim, bool state);
void simuSetSwitch(uint8_t swtch, int8_t state);
@@ -354,7 +355,7 @@ void StopMainThread();
void StartEepromThread(const char *filename="eeprom.bin");
void StopEepromThread();
#if defined(SIMU_AUDIO) && defined(CPUARM)
void StartAudioThread(void);
void StartAudioThread(int volumeGain = 10);
void StopAudioThread(void);
#else
#define StartAudioThread()
+6
View File
@@ -136,6 +136,12 @@ void adcRead()
Analog_values[i] = 0;
}
#endif
if (IS_POT(i) && !IS_POT_AVAILABLE(i)) {
// Use fixed analog value for non-existing and/or non-connected pots.
// Non-connected analog inputs will slightly follow the adjacent connected analog inputs,
// which produces ghost readings on these inputs.
Analog_values[i] = 0;
}
}
#endif
}
+1 -1
View File
@@ -84,7 +84,7 @@ void parseTelemHubByte(uint8_t byte)
byte = byte ^ 0x60;
state = (TS_STATE)(state - TS_XOR);
}
if (byte == 0x5d) {
else if (byte == 0x5d) {
state = (TS_STATE)(state | TS_XOR);
return;
}
+2
View File
@@ -40,11 +40,13 @@ inline void MIXER_RESET()
logicalSwitchesReset();
}
#if defined(FRSKY)
inline void TELEMETRY_RESET()
{
memclear(&frskyData, sizeof(frskyData));
frskyData.rssi[0].value = 100;
}
#endif
bool checkScreenshot(QString test);
Binary file not shown.

Before

Width:  |  Height:  |  Size: 904 B

After

Width:  |  Height:  |  Size: 909 B

+193
View File
@@ -361,3 +361,196 @@ TEST(getSwitch, inputWithTrim)
EXPECT_EQ(getSwitch(SWSRC_SW1), true);
}
#endif
#if defined(PCBTARANIS)
/*
PACK(typedef struct t_LogicalSwitchData { // Logical Switches data
int8_t v1;
int16_t v2;
int16_t v3;
uint8_t func;
uint8_t delay;
uint8_t duration;
int8_t andsw;
}) LogicalSwitchData;
*/
TEST(getSwitch, edgeInstant)
{
MODEL_RESET();
MIXER_RESET();
// LS1 setup: EDGE SFup (0:instant)
// LS2 setup: (EDGE SFup (0:instant)) AND SAup
g_model.logicalSw[0] = { SWSRC_SF2, -129, -1, LS_FUNC_STAY };
g_model.logicalSw[1] = { SWSRC_SF2, -129, -1, LS_FUNC_STAY, 0, 0, SWSRC_SA2 };
simuSetSwitch(0, -1); //SA down
simuSetSwitch(5, 0); //SF down
// EXPECT_EQ(getSwitch(SWSRC_SF2), false);
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), false);
EXPECT_EQ(getSwitch(SWSRC_SW2), false);
// now trigger SFup, LS1 should become true
simuSetSwitch(5, 1); //SF up
// EXPECT_EQ(getSwitch(SWSRC_SF2), true);
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), true);
EXPECT_EQ(getSwitch(SWSRC_SW2), false);
// now release SA0 and SW2 should stay true
simuSetSwitch(5, 0); //SF down
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), false);
EXPECT_EQ(getSwitch(SWSRC_SW2), false);
// now reset logical switches
logicalSwitchesReset();
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), false);
EXPECT_EQ(getSwitch(SWSRC_SW2), false);
// second part with SAup
simuSetSwitch(0, 1); //SA up
simuSetSwitch(5, 0); //SF down
// EXPECT_EQ(getSwitch(SWSRC_SF2), false);
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), false);
EXPECT_EQ(getSwitch(SWSRC_SW2), false);
// now trigger SFup, LS1 should become true
simuSetSwitch(5, 1); //SF up
// EXPECT_EQ(getSwitch(SWSRC_SF2), true);
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), true);
EXPECT_EQ(getSwitch(SWSRC_SW2), true);
// now release SA0 and SW2 should stay true
simuSetSwitch(5, 0); //SF down
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), false);
EXPECT_EQ(getSwitch(SWSRC_SW2), false);
// now reset logical switches
logicalSwitchesReset();
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), false);
EXPECT_EQ(getSwitch(SWSRC_SW2), false);
// now bug #2939
// SF is kept up and SA is toggled
simuSetSwitch(0, -1); //SA down
simuSetSwitch(5, 1); //SF up
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), true);
EXPECT_EQ(getSwitch(SWSRC_SW2), false);
simuSetSwitch(0, 1); //SA up
simuSetSwitch(5, 1); //SF up
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), false);
EXPECT_EQ(getSwitch(SWSRC_SW2), false);
simuSetSwitch(0, -1); //SA down
simuSetSwitch(5, 1); //SF up
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), false);
EXPECT_EQ(getSwitch(SWSRC_SW2), false);
//test what happens when EDGE condition is true and
//logical switches are reset - the switch should fire again
simuSetSwitch(0, 1); //SA up
simuSetSwitch(5, 1); //SF up
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), false); //switch will not trigger, because SF was already up
EXPECT_EQ(getSwitch(SWSRC_SW2), false);
logicalSwitchesReset();
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), true);
EXPECT_EQ(getSwitch(SWSRC_SW2), true);
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), false);
EXPECT_EQ(getSwitch(SWSRC_SW2), false);
}
TEST(getSwitch, edgeRelease)
{
MODEL_RESET();
MIXER_RESET();
// test for issue #2728
// LS1 setup: EDGE SFup (0:release)
// LS2 setup: (EDGE SFup (0:release)) AND SAup
g_model.logicalSw[0] = { SWSRC_SF2, -129, 0, LS_FUNC_STAY };
g_model.logicalSw[1] = { SWSRC_SF2, -129, 0, LS_FUNC_STAY, 0, 0, SWSRC_SA2 };
simuSetSwitch(0, -1); //SA down
simuSetSwitch(5, 0); //SF down
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), false);
EXPECT_EQ(getSwitch(SWSRC_SW2), false);
simuSetSwitch(5, 1); //SF up
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), false);
EXPECT_EQ(getSwitch(SWSRC_SW2), false);
simuSetSwitch(5, 0); //SF down
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), true);
EXPECT_EQ(getSwitch(SWSRC_SW2), false);
// second part with SAup
simuSetSwitch(0, 1); //SA up
simuSetSwitch(5, 0); //SF down
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), false);
EXPECT_EQ(getSwitch(SWSRC_SW2), false);
simuSetSwitch(5, 1); //SF up
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), false);
EXPECT_EQ(getSwitch(SWSRC_SW2), false);
simuSetSwitch(5, 0); //SF down
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), true);
EXPECT_EQ(getSwitch(SWSRC_SW2), true);
// with switches reset both should remain false
logicalSwitchesReset();
logicalSwitchesTimerTick();
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), false);
EXPECT_EQ(getSwitch(SWSRC_SW2), false);
}
#endif // #if defined(CPUARM)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 981 B

After

Width:  |  Height:  |  Size: 986 B

+2 -2
View File
@@ -42,8 +42,8 @@
#define TMR_NEGATIVE 2
#define TMR_STOPPED 3
#define TIMER_MAX (32767)
#define TIMER_MIN (-32767-1)
#define TIMER_MIN (-0xffff/2)
#define TIMER_MAX (-TIMER_MIN-1)
struct TimerState {
uint16_t cnt;
+5 -5
View File
@@ -342,9 +342,9 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010")
#define TR_VUNITSSYSTEM TR("Metr.\0""Imper.", "Metrické""Imperial")
#define LEN_VTELEMUNIT_METR "\003"
#define TR_VTELEMUNIT_METR "v\0 ""A\0 ""m/s""-\0 ""kmh""m\0 ""@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT_METR "V\0 ""A\0 ""m/s""-\0 ""kmh""m\0 ""@\0 ""%\0 ""mA\0""mAh""W\0 "
#define LEN_VTELEMUNIT_IMP "\003"
#define TR_VTELEMUNIT_IMP "v\0 ""A\0 ""m/s""-\0 ""kts""ft\0""@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT_IMP "V\0 ""A\0 ""m/s""-\0 ""kts""ft\0""@\0 ""%\0 ""mA\0""mAh""W\0 "
#else
#if defined(IMPERIAL_UNITS)
#define LENGTH_UNIT LENGTH_UNIT_IMP
@@ -354,7 +354,7 @@
#define SPEED_UNIT SPEED_UNIT_METR
#endif
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#endif
#define STR_V (STR_VTELEMUNIT+1)
@@ -706,7 +706,7 @@
#define TR_RESTORE_MODEL "Obnov model z SD"
#define TR_SDCARD_ERROR "Chyba SD karty"
#define TR_NO_SDCARD "Není SD karta"
#define TR_SDCARD_FULL "SD Card Full"
#define TR_SDCARD_FULL "SD je již plná"
#define TR_INCOMPATIBLE "Nekompatibilní"
#define TR_WARNING "KONTROLA"
#define TR_EEPROMWARN "EEPROM"
@@ -765,7 +765,7 @@
#define TR_DATE "Datum"
#define TR_ROTARY_ENCODER "R.Encs"
#define TR_CHANNELS_MONITOR "MONITOR KANÁLU"
#define TR_MIXERS_MONITOR "MIXERS MONITOR"
#define TR_MIXERS_MONITOR "MONITOR MIXU"
#define TR_PATH_TOO_LONG "Cesta je moc dlouhá"
#define TR_VIEW_TEXT "Zobrazit text"
#define TR_FLASH_BOOTLOADER "Flash BootLoader"
+10 -5
View File
@@ -100,8 +100,13 @@
#define LEN_TARANIS_PROTOCOLS "\004"
#define TR_TARANIS_PROTOCOLS "AUS\0""PPM\0""XJT\0""DSM2"
#define LEN_XJT_PROTOCOLS "\004"
#define TR_XJT_PROTOCOLS "AUS\0""D16\0""D8\0 ""LR12"
#if defined(MODULE_D16_EU_ONLY_SUPPORT)
#define LEN_XJT_PROTOCOLS "\006"
#define TR_XJT_PROTOCOLS "AUS\0 ""D16-EU"
#else
#define LEN_XJT_PROTOCOLS "\004"
#define TR_XJT_PROTOCOLS "AUS\0""D16\0""D8\0 ""LR12"
#endif
#define LEN_DSM_PROTOCOLS "\004"
#define TR_DSM_PROTOCOLS "LP45""DSM2""DSMX"
@@ -561,12 +566,12 @@
#define TR_MIXER "MISCHER"
#define TR_CV "KV"
#define TR_GV "GV"
#define TR_ACHANNEL TR("A\004gemessen","A\004Kanal gemessen =>") //9XR-Pro
#define TR_RANGE TR(INDENT"Bereich",INDENT"Messbereich") //9XR-Pro
#define TR_ACHANNEL TR("A\004gemessen", "A\004Kanal gemessen =>") // 9XR-Pro
#define TR_RANGE TR(INDENT"Bereich", INDENT "Reichweite") // 9XR-Pro
#define TR_BAR "Streifen"
#define TR_ALARM INDENT"Alarm"
#define TR_USRDATA "Daten berechnen aus"
#define TR_BLADES TR(INDENT"Prop",INDENT"Prop-Blätter") //9XR-Pro
#define TR_BLADES TR(INDENT"Prop", INDENT "Prop-Blätter") // 9XR-Pro
#define TR_SCREEN "Telm-Bild "
#define TR_SOUND_LABEL "----Töne---------"
#define TR_LENGTH INDENT"Dauer"
+3 -3
View File
@@ -344,9 +344,9 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010")
#define TR_VUNITSSYSTEM TR("Metric""Imper.", "Metric\0 ""Imperial")
#define LEN_VTELEMUNIT_METR "\003"
#define TR_VTELEMUNIT_METR "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT_METR LENGTH_UNIT_METR "@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT_METR "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT_METR LENGTH_UNIT_METR "@\0 ""%\0 ""mA\0""mAh""W\0 "
#define LEN_VTELEMUNIT_IMP "\003"
#define TR_VTELEMUNIT_IMP "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT_IMP LENGTH_UNIT_IMP "@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT_IMP "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT_IMP LENGTH_UNIT_IMP "@\0 ""%\0 ""mA\0""mAh""W\0 "
#else
#if defined(IMPERIAL_UNITS)
#define LENGTH_UNIT LENGTH_UNIT_IMP
@@ -356,7 +356,7 @@
#define SPEED_UNIT SPEED_UNIT_METR
#endif
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#endif
#define STR_V (STR_VTELEMUNIT+1)
+3 -3
View File
@@ -342,9 +342,9 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010")
#define TR_VUNITSSYSTEM TR("Metric""Imper.", "Metric\0 ""Imperial")
#define LEN_VTELEMUNIT_METR "\003"
#define TR_VTELEMUNIT_METR "v\0 ""A\0 ""m/s""-\0 ""kmh""m\0 ""@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT_METR "V\0 ""A\0 ""m/s""-\0 ""kmh""m\0 ""@\0 ""%\0 ""mA\0""mAh""W\0 "
#define LEN_VTELEMUNIT_IMP "\003"
#define TR_VTELEMUNIT_IMP "v\0 ""A\0 ""m/s""-\0 ""kts""ft\0""@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT_IMP "V\0 ""A\0 ""m/s""-\0 ""kts""ft\0""@\0 ""%\0 ""mA\0""mAh""W\0 "
#else
#if defined(IMPERIAL_UNITS)
#define LENGTH_UNIT LENGTH_UNIT_IMP
@@ -354,7 +354,7 @@
#define SPEED_UNIT SPEED_UNIT_METR
#endif
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#endif
#define STR_V (STR_VTELEMUNIT+1)
+3 -3
View File
@@ -342,9 +342,9 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010")
#define TR_VUNITSSYSTEM TR("Metric""Imper.", "Metric\0 ""Imperial")
#define LEN_VTELEMUNIT_METR "\003"
#define TR_VTELEMUNIT_METR "v\0 ""A\0 ""m/s""-\0 ""kmh""m\0 ""@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT_METR "V\0 ""A\0 ""m/s""-\0 ""kmh""m\0 ""@\0 ""%\0 ""mA\0""mAh""W\0 "
#define LEN_VTELEMUNIT_IMP "\003"
#define TR_VTELEMUNIT_IMP "v\0 ""A\0 ""m/s""-\0 ""kts""ft\0""@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT_IMP "V\0 ""A\0 ""m/s""-\0 ""kts""ft\0""@\0 ""%\0 ""mA\0""mAh""W\0 "
#else
#if defined(IMPERIAL_UNITS)
#define LENGTH_UNIT LENGTH_UNIT_IMP
@@ -354,7 +354,7 @@
#define SPEED_UNIT SPEED_UNIT_METR
#endif
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#endif
#define STR_V (STR_VTELEMUNIT+1)
+3 -3
View File
@@ -342,9 +342,9 @@
#define LEN_VUNITSSYSTEM TR("\006", "\012")
#define TR_VUNITSSYSTEM TR("Métr.\0""Impér.", "Métriques\0""Impériales")
#define LEN_VTELEMUNIT_METR "\003"
#define TR_VTELEMUNIT_METR "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT_METR LENGTH_UNIT_METR "@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT_METR "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT_METR LENGTH_UNIT_METR "@\0 ""%\0 ""mA\0""mAh""W\0 "
#define LEN_VTELEMUNIT_IMP "\003"
#define TR_VTELEMUNIT_IMP "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT_IMP LENGTH_UNIT_IMP "@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT_IMP "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT_IMP LENGTH_UNIT_IMP "@\0 ""%\0 ""mA\0""mAh""W\0 "
#else
#if defined(IMPERIAL_UNITS)
#define LENGTH_UNIT LENGTH_UNIT_IMP
@@ -354,7 +354,7 @@
#define SPEED_UNIT SPEED_UNIT_METR
#endif
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#endif
#define STR_V (STR_VTELEMUNIT+1)
+6 -6
View File
@@ -342,9 +342,9 @@
#define LEN_VUNITSSYSTEM TR("\006", "\011")
#define TR_VUNITSSYSTEM TR("Metric""Imper.", "Metriche\0""Imperiali")
#define LEN_VTELEMUNIT_METR "\003"
#define TR_VTELEMUNIT_METR "v\0 ""A\0 ""m/s""-\0 ""kmh""m\0 ""@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT_METR "V\0 ""A\0 ""m/s""-\0 ""kmh""m\0 ""@\0 ""%\0 ""mA\0""mAh""W\0 "
#define LEN_VTELEMUNIT_IMP "\003"
#define TR_VTELEMUNIT_IMP "v\0 ""A\0 ""m/s""-\0 ""kts""ft\0""@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT_IMP "V\0 ""A\0 ""m/s""-\0 ""kts""ft\0""@\0 ""%\0 ""mA\0""mAh""W\0 "
#else
#if defined(IMPERIAL_UNITS)
#define LENGTH_UNIT LENGTH_UNIT_IMP
@@ -354,7 +354,7 @@
#define SPEED_UNIT SPEED_UNIT_METR
#endif
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#endif
#define STR_V (STR_VTELEMUNIT+1)
@@ -381,7 +381,7 @@
#define LEN_VARIOSRC "\005"
#if defined(FRSKY_SPORT)
#define TR_VARIOSRC "Vario""A1\0 ""A2\0 "
#define TR_VARIOSRC "Vario""A1\0 ""A2\0 ""dTE\0 "
#else
#define TR_VARIOSRC "Alti\0""Alti+""Vario""A1\0 ""A2\0 "
#endif
@@ -562,9 +562,9 @@
#define TR_CV "CV"
#define TR_GV "GV"
#define TR_ACHANNEL "A\002ingresso"
#define TR_RANGE tr(INDENT"Campo",INDENT"Campo")
#define TR_RANGE INDENT "Campo"
#define TR_BAR "Barra"
#define TR_ALARM tr(INDENT"Allar.",INDENT"Allarme")
#define TR_ALARM TR(INDENT"Allar.", INDENT"Allarme")
#define TR_USRDATA "Dati"
#define TR_BLADES INDENT"Pale"
#define TR_SCREEN "Schermo "
+3 -3
View File
@@ -342,9 +342,9 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010")
#define TR_VUNITSSYSTEM TR("Metr. ""Imper.", "Metryczn""Imperial")
#define LEN_VTELEMUNIT_METR "\003"
#define TR_VTELEMUNIT_METR "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT_METR LENGTH_UNIT_METR "@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT_METR "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT_METR LENGTH_UNIT_METR "@\0 ""%\0 ""mA\0""mAh""W\0 "
#define LEN_VTELEMUNIT_IMP "\003"
#define TR_VTELEMUNIT_IMP "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT_IMP LENGTH_UNIT_IMP "@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT_IMP "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT_IMP LENGTH_UNIT_IMP "@\0 ""%\0 ""mA\0""mAh""W\0 "
#else
#if defined(IMPERIAL_UNITS)
#define LENGTH_UNIT LENGTH_UNIT_IMP
@@ -354,7 +354,7 @@
#define SPEED_UNIT SPEED_UNIT_METR
#endif
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#endif
#define STR_V (STR_VTELEMUNIT+1)
+3 -3
View File
@@ -342,9 +342,9 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010")
#define TR_VUNITSSYSTEM TR("Metric""Imper.", "Metric\0 ""Imperial")
#define LEN_VTELEMUNIT_METR "\003"
#define TR_VTELEMUNIT_METR "v\0 ""A\0 ""m/s""-\0 ""kmh""m\0 ""@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT_METR "V\0 ""A\0 ""m/s""-\0 ""kmh""m\0 ""@\0 ""%\0 ""mA\0""mAh""W\0 "
#define LEN_VTELEMUNIT_IMP "\003"
#define TR_VTELEMUNIT_IMP "v\0 ""A\0 ""m/s""-\0 ""kts""ft\0""@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT_IMP "V\0 ""A\0 ""m/s""-\0 ""kts""ft\0""@\0 ""%\0 ""mA\0""mAh""W\0 "
#else
#if defined(IMPERIAL_UNITS)
#define LENGTH_UNIT LENGTH_UNIT_IMP
@@ -354,7 +354,7 @@
#define SPEED_UNIT SPEED_UNIT_METR
#endif
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#endif
#define STR_V (STR_VTELEMUNIT+1)
+3 -3
View File
@@ -342,9 +342,9 @@
#define LEN_VUNITSSYSTEM TR("\006", "\010")
#define TR_VUNITSSYSTEM TR("Metri.""Imper.", "Metriska""Imperial")
#define LEN_VTELEMUNIT_METR "\003"
#define TR_VTELEMUNIT_METR "v\0 ""A\0 ""m/s""-\0 ""kmh""m\0 ""@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT_METR "V\0 ""A\0 ""m/s""-\0 ""kmh""m\0 ""@\0 ""%\0 ""mA\0""mAh""W\0 "
#define LEN_VTELEMUNIT_IMP "\003"
#define TR_VTELEMUNIT_IMP "v\0 ""A\0 ""m/s""-\0 ""kts""ft\0""@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT_IMP "V\0 ""A\0 ""m/s""-\0 ""kts""ft\0""@\0 ""%\0 ""mA\0""mAh""W\0 "
#else
#if defined(IMPERIAL_UNITS)
#define LENGTH_UNIT LENGTH_UNIT_IMP
@@ -354,7 +354,7 @@
#define SPEED_UNIT SPEED_UNIT_METR
#endif
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#define TR_VTELEMUNIT "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#endif
#define STR_V (STR_VTELEMUNIT+1)
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
import traceback
import time
import re
import re
if len(sys.argv) > 1:
inputFile = sys.argv[1]
inp = open(inputFile, "r")
else:
inp = sys.stdin
pattern = re.compile("#\d+")
while True:
skip = False
line = inp.readline()
if len(line) == 0:
break
line = line.strip('\r\n')
if len(line) == 0:
skip = True
if line.startswith("<"):
skip = True
if line.startswith("["):
skip = True
if not skip:
#line = line.strip()
#print "line: %s" % line
found = re.findall(pattern, line)
if len(found) > 0:
for issue in found:
line = line.replace(issue, '')
#add issues
issue_links = ["<a href=https://github.com/opentx/opentx/issues/%d>#%d</a>" % (int(issue[1:]), int(issue[1:])) for issue in found]
links = "(" + ", ".join(issue_links) + ")"
line = "<li>" + line + " " + links + "</li>"
print line
inp.close()
sys.exit(0)
+51
View File
@@ -0,0 +1,51 @@
#!/bin/bash
# Stops on first error, echo on
set -e
set -x
cd radio/src/
# OpenTX on 9X stock
make clean
make PCB=9X EXT=FRSKY HELI=YES
make simu PCB=9X EXT=FRSKY HELI=YES
make gtests EXT=FRSKY HELI=YES
./gtests
# OpenTX on Taranis X9E
make clean
make PCB=TARANIS PCBREV=REV9E HELI=YES GVARS=YES LUA=YES
make simu PCB=TARANIS PCBREV=REV9E HELI=YES GVARS=YES LUA=YES
make gtests PCB=TARANIS PCBREV=REV9E HELI=YES GVARS=YES LUA=YES
./gtests
# OpenTX on Taranis Plus
make clean
make PCB=TARANIS PCBREV=REVPLUS HELI=YES LUA=YES
make simu PCB=TARANIS PCBREV=REVPLUS HELI=YES LUA=YES
make gtests PCB=TARANIS PCBREV=REVPLUS HELI=YES LUA=YES
./gtests
# OpenTX on Taranis
make clean
make PCB=TARANIS HELI=YES LUA=YES
make simu PCB=TARANIS HELI=YES LUA=YES
make gtests PCB=TARANIS HELI=YES LUA=YES
./gtests
# OpenTX on Sky9x
make clean
make PCB=SKY9X HELI=YES
make simu PCB=SKY9X HELI=YES
make gtests PCB=SKY9X HELI=YES
./gtests
# OpenTX on Gruvin9x
make clean
make PCB=GRUVIN9X EXT=FRSKY SDCARD=YES
make simu PCB=GRUVIN9X EXT=FRSKY SDCARD=YES
# OpenTX on MEGA2560
make clean
make PCB=MEGA2560
+3 -1
View File
@@ -255,7 +255,9 @@ def ttsFr():
systemSounds.append((s, filename(PROMPT_SYSTEM_BASE+146+i)))
for i, s in enumerate(["virgule 0", "virgule 1", "virgule 2", "virgule 3", "virgule 4", "virgule 5", "virgule 6", "virgule 7", "virgule 8", "virgule 9"]):
systemSounds.append((s, filename(PROMPT_SYSTEM_BASE+180+i)))
for s, f, a in [(u"Batterie radio faible !", "lowbatt", 485),
for s, f, a in [(u"Trim centré", "midtrim", 495),
(u"Trim maximum atteint", "endtrim", NO_ALTERNATE),
(u"Batterie radio faible !", "lowbatt", 485),
(u"Radio inactive !", "inactiv", 486),
(u"Alerte manche des gaz", "thralert", 481),
(u"Alerte inters", "swalert", 482),