Compare commits

...

983 Commits

Author SHA1 Message Date
ajjjjjjjj afb2d86560 CircleCI multiple pipelines attempt 2021-12-12 10:53:54 +01:00
ajjjjjjjj d1bed1f9dc CircleCI multiple pipelines attempt 2021-12-12 10:23:32 +01:00
ajjjjjjjj 0865041adb CircleCI multiple pipelines attempt 2021-12-12 10:21:17 +01:00
ajjjjjjjj 0dcba3c680 CircleCI multiple pipelines attempt 2021-12-12 10:04:47 +01:00
ajjjjjjjj 2e3025a07c CircleCI multiple pipelines attempt 2021-12-12 10:01:27 +01:00
ajjjjjjjj 20e1d81386 CircleCI multiple pipelines attempt 2021-12-12 09:56:05 +01:00
ajjjjjjjj e1b3711d88 CircleCI multiple pipelines attempt 2021-12-12 09:55:51 +01:00
ajjjjjjjj 7b38157c6e Merge branch 'circleci-project-setup' of https://github.com/OpenI6X/opentx into circleci-project-setup
 Conflicts:
	.circleci/config.yml
2021-12-12 09:52:06 +01:00
ajjjjjjjj 2528e51d29 CircleCI multiple pipelines attempt 2021-12-12 09:50:45 +01:00
Mariano Dupont abdf507c2e Updated config.yml 2021-12-12 09:47:00 +01:00
Mariano Dupont cb712ef60d Updated config.yml 2021-12-12 09:47:00 +01:00
Mariano Dupont b3fd84e6c2 Updated config.yml 2021-12-12 09:47:00 +01:00
Mariano Dupont 6e99ccb07d Updated config.yml 2021-12-12 09:47:00 +01:00
Mariano Dupont 6ebd36b1aa Add .circleci/config.yml 2021-12-12 09:47:00 +01:00
Mariano Dupont d95a22c873 Add .circleci/config.yml 2021-12-12 09:47:00 +01:00
Mariano Dupont 7f10734457 Add .circleci/config.yml 2021-12-12 09:47:00 +01:00
Janek 89786a000c Merge pull request #74 from OpenI6X/janek/backport-renames-avr-cleanup
Backported refactored names and AVR legacies.
2021-12-12 09:38:20 +01:00
Janek cb9a8c12ed Merge pull request #73 from OpenI6X/janek/button-names
Use FS-i6X button names
2021-12-12 09:37:26 +01:00
Mariano Dupont 3c7931665b Reverted backlight not turning on when moving sticks or switches 2021-12-11 20:38:21 -03:00
ajjjjjjjj 7a7e4a0e93 Backported refactored names and AVR legacies.
Minor ELRSV2 improvement
2021-12-11 22:55:45 +01:00
ajjjjjjjj 9689a35819 Use FS-i6X button names 2021-12-11 18:05:13 +01:00
ajjjjjjjj 7942f48e75 Use FS-i6X button names 2021-12-11 18:00:19 +01:00
Janek 3ad2328bac Merge pull request #72 from OpenI6X/janek/elrsv2-port
ExpressLRS v2.0 lua menu port.
2021-12-11 17:06:58 +01:00
Janek 7d1f7f23df Merge pull request #71 from OpenI6X/janek/modules-off
Default modules to off backport
2021-12-11 17:06:46 +01:00
Janek a5a803a83f Merge pull request #70 from OpenI6X/janek/baudrate-option-refactor
Baudrate option refactor
2021-12-11 17:06:32 +01:00
Janek 6422d4ed88 Merge pull request #69 from OpenI6X/janek/gvars-display-fix
Display 9 GVARS instead of 10
2021-12-11 17:06:11 +01:00
Janek f3fcd9ddef Merge pull request #68 from OpenI6X/janek/mode-option-accessible
Mode option accessible
2021-12-11 17:06:00 +01:00
Janek b47101666a Merge pull request #67 from OpenI6X/janek/buzzer-cleanup
Buzzer cleanup
2021-12-11 17:05:51 +01:00
Janek 683aaa74cd Merge pull request #66 from OpenI6X/janek/version-page
Fixed version screen layout, no longer broken long press - backport
2021-12-11 17:05:42 +01:00
Janek 85317d52a1 Merge pull request #65 from OpenI6X/janek/eeprom-speed
EEPROM i2c @ 400k
2021-12-11 17:05:20 +01:00
ajjjjjjjj 6b1aef2c7f Backported TOOLS menu.
Backported and customized Gauge widget.
Backported text centering feature.
Added custom CRSF hooks for scripts.
Removed ExpressLRS menu references from core.
Removed previous ExpressLRS menu implementation.
Ported ELRSV2.lua.
Telemetry sensors max at 22 for ELRSV2 builds.
Diagnostic keys screen is now define guarded and removed by default.
Diagnostic analogs screen is now define guarded and removed by default.
2021-12-11 11:11:25 +01:00
ajjjjjjjj 5bda82614c Defaut modules to OFF backport (but do not works for AFHDS) 2021-12-11 11:01:06 +01:00
ajjjjjjjj 6c3527a268 Baudrate option refactor, hide USB CDC in debug, remove hand icon, minor backports 2021-12-11 10:57:15 +01:00
ajjjjjjjj 8d9b3c8cd8 Display 9 GVARS instead of 10 2021-12-11 10:52:04 +01:00
ajjjjjjjj ab1443ce54 Fixed access to setup mode option 2021-12-11 10:31:07 +01:00
ajjjjjjjj a5cfc60e4a Fixed access to setup mode option 2021-12-11 10:28:41 +01:00
ajjjjjjjj 61577db82b Buzzer cleanup to save flash 2021-12-11 10:25:34 +01:00
ajjjjjjjj 09cfec8ed0 Fixed layout, no longer broken long press 2021-12-11 10:22:27 +01:00
ajjjjjjjj a1d703a7dd EEPROM i2c @ 400k 2021-12-11 10:12:45 +01:00
Mariano Dupont c3632b1a89 Updated config.yml 2021-11-24 22:32:07 -03:00
Mariano Dupont 50072ad337 Updated config.yml 2021-11-24 22:05:18 -03:00
Mariano Dupont ebffde6170 Updated config.yml 2021-11-24 22:02:16 -03:00
Mariano Dupont b5d98a03fe Updated config.yml 2021-11-24 21:25:41 -03:00
Mariano Dupont 3cff737064 Add .circleci/config.yml 2021-11-24 21:08:40 -03:00
Mariano Dupont f53a9860c6 Add .circleci/config.yml 2021-11-24 21:06:22 -03:00
Mariano Dupont e8e7a194ca Add .circleci/config.yml 2021-11-24 20:39:01 -03:00
ajjjjjjjj cebb6cf0b0 Merge pull request #57 from OpenI6X/janek/dfu-bootloader
System DFU Bootloader
2021-11-14 14:47:15 +01:00
ajjjjjjjj 75c5588a76 - Start system DFU Bootloader using trims,
- removed few bytes from crc
2021-11-14 13:31:20 +01:00
Mariano Dupont 96f7db2387 Merge pull request #50 from OpenI6X/janek/splash
Added splash image for release builds
2021-11-12 20:55:02 -03:00
ajjjjjjjj 6df7d74e2b Merge pull request #54 from OpenI6X/janek/backlight-maintance
Don't pass fake backlight values (save flash)
2021-11-13 00:34:42 +01:00
ajjjjjjjj 4cadada18a Don't pass fake backlight values (save flash) 2021-11-13 00:29:23 +01:00
ajjjjjjjj 8df70aab80 Update README.md 2021-11-12 22:56:14 +01:00
Janek 2b74737351 Added splash image for release builds 2021-11-12 21:34:17 +01:00
ajjjjjjjj 47fad215d6 Merge pull request #49 from ajjjjjjjj/janek/beep-on-warn
Beep on warning
2021-11-12 11:16:18 +01:00
Janek 64464f186d Beep on warning 2021-11-12 11:15:31 +01:00
ajjjjjjjj 0b01a6a664 Update README.md 2021-11-12 00:33:59 +01:00
ajjjjjjjj 2f1c75268f Update README.md 2021-11-11 23:25:31 +01:00
Mariano Dupont b0158b3a1e Ignore unknown IBUS sensors. 2021-11-11 18:24:59 -03:00
Mariano Dupont b619806d6d Merge pull request #48 from ajjjjjjjj/janek/hardware-crc
Hardware CRC implementation
2021-11-11 18:10:56 -03:00
Janek f6b2f374c4 Hardware CRC implementation.
- 16 times faster than lookup table,
- almost 200b less of flash space occupied
2021-11-11 21:06:33 +01:00
Mariano Dupont 34c40569bd Merge pull request #46 from ajjjjjjjj/janek/crossfire-baudrates
Format baud rates to make it easier to read
2021-11-10 13:37:06 -03:00
Janek 86178e5788 increased write delay 2021-11-10 17:35:28 +01:00
Mariano Dupont 0eb9b1149d Merge pull request #47 from ajjjjjjjj/janek/pot-navigation
Solve POT editing values outside limits.
2021-11-10 13:15:17 -03:00
Janek b7be159a3b Solve POT editing values outside limits.
It's not perfect but at least don't mess up values.
2021-11-10 14:17:43 +01:00
Janek 43c0820686 Format baud rates to make it easier to read 2021-11-10 11:46:19 +01:00
Janek a0bd47e39f Format baud rates to make it easier to read 2021-11-10 11:01:51 +01:00
Janek 63b0b477eb Format baud rates to make it easier to read 2021-11-10 09:29:07 +01:00
ajjjjjjjj 7571d806ad Update README.md 2021-11-09 22:39:46 +01:00
ajjjjjjjj 6e39214f3b Update README.md 2021-11-09 22:39:02 +01:00
Mariano Dupont f4741c88c5 Merge pull request #45 from ajjjjjjjj/janek/crossfire-baudrates
Added faster baud rates.
2021-11-09 18:38:55 -03:00
Janek 768f0e0520 Added faster baudrates, works fine on mine DIY Slimmer 2.4.
Inspired by https://github.com/EdgeTX/edgetx/pull/640
2021-11-09 22:20:46 +01:00
Mariano Dupont 71b1d21656 Further removed AFHDS3 unused code 2021-11-09 10:48:25 -03:00
Mariano Dupont 4fcb545ae6 Bumped telemetry slots to 28. Removed AFHDS3 telemetry ID's. 2021-11-09 10:20:46 -03:00
Mariano Dupont a26f484cb4 AFHDS2A extended telemetry support. 2021-11-08 16:46:07 -03:00
Mariano Dupont 5b4a2f57b9 Merge pull request #43 from ajjjjjjjj/janek/vario-improvements
Implemented vario volume and proper sound priority handling
2021-11-08 13:18:06 -03:00
Mariano Dupont b51b68de45 Merge pull request #42 from ajjjjjjjj/janek/ext-module-power
External module power switch on PC9
2021-11-08 13:17:25 -03:00
ajjjjjjjj 61c1455557 Update README.md 2021-11-07 18:41:33 +01:00
Janek f3c34ae5bc hide volume implementation 2021-11-07 18:34:19 +01:00
Janek 030c798d5c Implemented vario volume and proper sound priority handling 2021-11-07 16:33:12 +01:00
Janek dbaa273b6b Implemented vario volume and proper sound priority handling 2021-11-07 15:29:22 +01:00
Janek 16cf07b91f Init external module power pin 2021-11-07 12:24:06 +01:00
Janek 5b5751dea4 Inline "one liners" to save call overhead and flash space. 2021-11-06 17:24:09 +01:00
Janek 56522adddb External module power switch on PC9 2021-11-06 15:10:18 +01:00
ajjjjjjjj 25753334fc Merge pull request #41 from ajjjjjjjj/janek/usb-msd-fix2
USB MSD - don't zero memory twice
2021-11-05 23:10:34 +01:00
Janek 4369ed5e7a - don't zero memory twice 2021-11-05 23:09:27 +01:00
Mariano Dupont 4e97a3f1ef Merge pull request #40 from ajjjjjjjj/janek/usb-msd-fix
USB MSD improvements
2021-11-05 18:34:16 -03:00
Janek 8ffe4bbbc5 - USB MSD bug fix
- better adjusted for PCBI6
- 100 bytes less
2021-11-05 20:52:33 +01:00
Janek 078a642e1f - USB MSD bug fix
- better adjusted for PCBI6
- 100 bytes less
2021-11-05 19:48:36 +01:00
Mariano Dupont dd1d07cf03 Update README.md 2021-11-05 11:44:04 -03:00
Mariano Dupont 04c7e9c93e Merge pull request #39 from marianomd/crsfshot
CRSFshot (mixer sync) enabled
2021-11-05 11:43:20 -03:00
Mariano Dupont a0bbadba06 Fixed 25Hz mixer sync 2021-11-05 11:31:52 -03:00
Mariano Dupont 124b2b16ec CRSFshot (mixer sync) enabled. Working ok in all rates except 25Hz. 2021-11-04 23:25:45 -03:00
Mariano Dupont 7b60100d18 Merge pull request #38 from ajjjjjjjj/janek/usart-deinit
This is backport from EdgeTX and other OpenTX targets.
2021-11-04 18:40:22 -03:00
Janek ea23f27f43 This is backport from EdgeTX and other OpenTX targets. 2021-11-04 22:07:44 +01:00
Mariano Dupont 080521625e Update README.md 2021-11-04 17:04:40 -03:00
Mariano Dupont 362a2b51ca Merge branch '2.3_M0' of github.com:marianomd/opentx into 2.3_M0 2021-11-04 10:31:33 -03:00
Mariano Dupont 06056db521 Removed duplicate definition 2021-11-04 10:31:06 -03:00
Mariano Dupont 5d9fae0bc8 Merge pull request #37 from ajjjjjjjj/janek/elrs-fix
ExpressLRS reboot fix
2021-11-04 10:24:57 -03:00
Mariano Dupont 6227d8f19e Merge pull request #36 from ajjjjjjjj/feature/cleanup
Renamed SDCard to Storag(e) to reduce confusion.
2021-11-04 10:24:28 -03:00
Janek 182aea5ef6 Fix for John's errors 2021-11-04 10:38:09 +01:00
Janek 04abf6780c Reset issue fixed on DIY Slimmer TX 2.4 2021-11-04 10:03:35 +01:00
Janek 78c750445f Reset issue fixed on DIY Slimmer TX 2.4 2021-11-04 09:49:19 +01:00
Janek 9e0ee49a73 Seems like less likely to reboot on cold start with deinit.
Shaved almost 100 bytes from elrs script.
Realigned telemetry errors value.
2021-11-03 23:47:40 +01:00
Janek 470617b957 Without this change on DIY Slimmer 2.4 TX i have reboots every 5-30 seconds. With this change I was able to stay online for over 2 hours. 2021-11-03 16:21:24 +01:00
Janek 93db93ccee Renamed SDCard to Storag(e) to reduce confusion.
Minor cleanup
2021-11-03 16:18:09 +01:00
Mariano Dupont a3d00a585d Merge pull request #35 from marianomd/elrs_menu
ExpressLRS v1.x config menu. Still missing: binding mode and web server.
2021-11-02 09:18:13 -03:00
Mariano Dupont b4d7d81bf5 Update README.md 2021-10-31 23:52:04 -03:00
Mariano Dupont 293b497909 Show ELRS version info 2021-10-31 23:17:44 -03:00
Mariano Dupont 28945301c5 ExpressLRS menu working. Still missing: show commitSHA, Enable binding mode, Enable web server. 2021-10-31 19:28:28 -03:00
Mariano Dupont 67ab6689b1 Merge pull request #34 from ajjjjjjjj/janek/pin-configuation
Chaged USB Vbus pin mode
2021-10-29 20:42:48 -03:00
Janek 30086f9ce2 After reading this one looks like more suitable. 2021-10-29 20:20:50 +02:00
Mariano Dupont 2df77e9b82 Merge pull request #33 from ajjjjjjjj/janek/usb
backported #8195
2021-10-28 21:41:35 -03:00
Janek 4475e7c074 backported #8195 2021-10-28 23:45:51 +02:00
ajjjjjjjj 9878630ad3 Merge pull request #32 from ajjjjjjjj/janek/vario
Audio vario improvement
2021-10-28 22:57:27 +02:00
Janek 3a6e18e72c Audio vario improvement 2021-10-28 22:54:55 +02:00
Janek 3292b80269 Audio vario improvement 2021-10-28 22:53:40 +02:00
Mariano Dupont be4ad6ef3d Merge pull request #31 from ajjjjjjjj/janek/sound-handling2
Improved concurrent sounds handling
2021-10-28 09:38:26 -03:00
Janek d0c34e1ca5 Improved concurrent sounds handling 2021-10-28 14:01:39 +02:00
ajjjjjjjj cda10cc2c4 Merge branch 'marianomd:2.3_M0' into 2.3_M0 2021-10-28 13:57:05 +02:00
ajjjjjjjj 34e8e95df4 Update README.md 2021-10-27 21:13:13 +02:00
ajjjjjjjj dce714556e Update README.md 2021-10-27 19:04:55 +02:00
Mariano Dupont ffb4c5d2e0 Update README.md 2021-10-27 09:23:50 -03:00
Mariano Dupont 863c4559dd Merge pull request #29 from ajjjjjjjj/janek/usb-msd-and-detect
Enabled USB MSD Mode
2021-10-27 08:53:28 -03:00
Janek 47357e074a USB Detect is now Auto/Once
USB Detect is not stored and defaults to Auto
Decreased MENU_STACK_SIZE by ~10%
Enabled USB MSD Mode
2021-10-27 13:06:04 +02:00
Janek 84be5a77d8 USB Detect is now Auto/Once
USB Detect is not stored and defaults to Auto
Decreased MENU_STACK_SIZE by ~10%
Enabled USB MSD Mode
2021-10-27 13:05:07 +02:00
ajjjjjjjj df2fba6206 Merge branch 'marianomd:2.3_M0' into 2.3_M0 2021-10-26 22:39:01 +02:00
Mariano Dupont 0340c23cb8 Merge pull request #28 from ajjjjjjjj/janek/usb-msd-switch
added PCBI6_USB_MSD switch when there will be more RAM
2021-10-26 15:54:03 -03:00
Janek 501b97098a added PCBI6_USB_MSD switch when there will be more RAM,
fix I2C_RCC_APB1Periph used twice
2021-10-26 20:23:11 +02:00
Janek 72e0ce885f I2C_RCC_APB1Periph used twice 2021-10-26 20:04:18 +02:00
Mariano Dupont aae495062c Merge pull request #27 from ajjjjjjjj/janek/joystick2
Improved joystick mapping workaround.
2021-10-25 17:59:05 -03:00
Janek 99c3fc1054 Improved joystick mapping workaround. 2021-10-25 21:44:13 +02:00
Mariano Dupont b1c9fe13a8 Merge branch '2.3_M0' of github.com:marianomd/opentx into 2.3_M0 2021-10-25 16:12:43 -03:00
Mariano Dupont effd281be1 Max sensors lowered to 24 2021-10-25 16:12:28 -03:00
Mariano Dupont 578b26d4d3 Update README.md 2021-10-25 11:51:58 -03:00
Mariano Dupont ae0baa3d3c Merge pull request #26 from ajjjjjjjj/feature/joystick-fix
Joystick fixed
2021-10-24 09:21:38 -03:00
Janek f42d952020 Joystick fixed 2021-10-24 13:27:19 +02:00
Janek 5f0bcf0835 Joystick fixed 2021-10-24 13:17:45 +02:00
Mariano Dupont 71e368d8f0 Merge pull request #25 from ajjjjjjjj/janek/usb-enable
"USB Detect" general menu
2021-10-23 13:26:08 -03:00
Janek b2aa871a0d - added "USB Detect" to general menu with Auotp/On option - auto is USB_Vbus at PA15, On is force on
- restore warning "hand" icon on release builds
2021-10-23 18:19:55 +02:00
Mariano Dupont 0b27b371d7 Merge pull request #24 from ajjjjjjjj/feature/vario
PLAY_BACKGROUND support
2021-10-21 14:00:39 -03:00
Janek 144f71303d - initial PLAY_BACKGROUND support 2021-10-21 18:52:47 +02:00
Mariano Dupont f6259800d0 Merge pull request #23 from ajjjjjjjj/feature/ram-opt
RAM optimizations and disabled USB MSD
2021-10-21 08:50:56 -03:00
Janek 84c0382226 - skip on trimms flood 2021-10-21 12:23:57 +02:00
Janek 3a82c6dedb - skip on trimms flood 2021-10-21 12:21:57 +02:00
Janek b85d22ecb8 - skip on trimms flood 2021-10-21 11:58:37 +02:00
Janek a3071a966e - skip on trimms flood 2021-10-21 11:52:43 +02:00
Janek 2065aea794 - skip on trimms flood 2021-10-21 11:49:33 +02:00
Janek 73826cdbbf - disabled USB MSD,
- reduced overall RAM usage,
- reduced buzzer RAM usage,
- buzzer sounds can be now interleaved!
2021-10-21 11:36:57 +02:00
Mariano Dupont 7c0680bc9a Merge pull request #22 from ajjjjjjjj/feature/bootloader-boot-usb
Bootloader (but disabled) and USB support
2021-10-20 16:10:20 -03:00
Janek 138a224675 - VBUS sense at PA15 2021-10-20 19:57:27 +02:00
Janek da3dc260bf - fix DEBUG builds with enabled USB 2021-10-20 19:33:26 +02:00
Janek b28a906a42 - USB improvements,
- reenabled FIRMWARE.TXT file
2021-10-20 15:20:51 +02:00
Janek f4dd914139 - save USB flash space 2021-10-17 13:43:39 +02:00
Janek 37b465570b - save fat table flash space 2021-10-17 13:32:09 +02:00
Janek 8f3d576ffa - save USB msd fat table flash space 2021-10-17 12:55:13 +02:00
Janek dc55df76cf - backup FIRMWARE.BIN is valid 2021-10-16 23:40:10 +02:00
Janek 816b783225 - removed USB_SERIAL_MODE reduced size by ~200B 2021-10-16 22:10:45 +02:00
Janek e4e8de72e4 - removed About view 2021-10-16 20:44:48 +02:00
Janek a09bfc136f - removed firmware.txt to fit under 16kb 2021-10-16 19:56:39 +02:00
Janek 8064fd1d43 - fixed reading EEPROM.BIN
- refactored i2cInit to better match otx codestyle
- restoring backup works,
- added IFdefs to disable firmware.txt (broken)
2021-10-16 19:33:08 +02:00
Janek 9681b80ffc works:
- bootloader boots main fw,
- main fw properly exposes version,
- USB registers as mass storage with fat FS and reports 3 files,

broken:
- input/output error when accessing files,
2021-10-16 15:27:24 +02:00
Mariano Dupont c7077989a8 Fixed broken telemetry sensors. 2021-10-14 01:03:28 -03:00
Mariano Dupont 5f9c792cd3 Merge branch '2.3_M0' of github.com:marianomd/opentx into 2.3_M0 2021-10-13 19:44:12 -03:00
Mariano Dupont 2b83eaac4a Increased telemetry sensors to 24. Increase max contrast to 63. Default value a little darker. Fixed typo. 2021-10-13 19:43:23 -03:00
Mariano Dupont fe8674ef6b Update README.md 2021-10-12 20:06:34 -03:00
Mariano Dupont 50414472b9 Update README.md 2021-10-12 20:06:08 -03:00
Mariano Dupont df5b5aea39 Merge pull request #21 from ajjjjjjjj/feature/countdown-voice
Remove "Voice" from countdown options
2021-10-12 17:19:35 -03:00
Janek 9cf815ebd6 Remove "Voice" from countdown options 2021-10-12 20:26:49 +02:00
Mariano Dupont be091818a6 Merge pull request #20 from ajjjjjjjj/feature/timer-countdown
Timer countdown start missing
2021-10-12 14:12:23 -03:00
Janek 2012225307 Timer countdown start missing in 128 (fix #8252)
Upstream #8247 and #8533
Minor cleanup
2021-10-12 16:00:23 +02:00
Mariano Dupont dca30b1830 Merge pull request #19 from ajjjjjjjj/feature/bootloader
Bootloader
2021-10-11 17:38:15 -03:00
Janek dcf3101b17 Bootloader
- commented usbStart() because of freeze,
- fixed menu,
- finding version works if pointed at bootloader addr,
- booting image from another address probably needs some work: https://community.st.com/s/question/0D53W00000trgpiSAA/how-to-boot-to-random-address-without-vecttaboffset-stm32f072

Backlight:
- improved init
2021-10-11 21:56:18 +02:00
Mariano Dupont 2598946891 Merge pull request #18 from ajjjjjjjj/janek/rebranded
Rebranded to OpenI6X ;)
2021-10-07 17:19:49 -03:00
Janek 3a2e1e5ea2 Rebranded to OpenI6X ;) 2021-10-07 22:08:25 +02:00
Mariano Dupont e95ac4639f Merge pull request #17 from ajjjjjjjj/janek/removed-icons-and-text
Recovered ~1.3KB of FLASH space
2021-10-07 16:36:04 -03:00
Janek cd7bd6e99c Recovered ~1.3KB of FLASH space:
- removed about icon and simplified text in about screen,
- removed asterisk icon in popup screens, replaced with "x",
2021-10-07 21:15:50 +02:00
Mariano Dupont ec8f2dba30 No more crashes with CRSF. Now counting real telemetry errors. 2021-10-07 11:06:30 -03:00
Mariano Dupont 6c1fa1953e Added key combination for I6X 2021-10-07 08:05:00 -03:00
Mariano Dupont ac927e63f0 Removed bootloader unnecessary dependencies 2021-10-06 21:14:00 -03:00
Mariano Dupont e9311cde2d Tried to enable CLI but there's not enough RAM nor FLASH. 2021-10-06 20:11:00 -03:00
Mariano Dupont 11b6a8eab9 Merge pull request #16 from ajjjjjjjj/janek/cmakefile-sections-size
Show section sizes after compilation.
2021-10-06 17:53:55 -03:00
Mariano Dupont 1bd2178753 Merge pull request #15 from ajjjjjjjj/feature/buzzer-s2ep9
Buzzer
2021-10-06 17:53:25 -03:00
Mariano Dupont 61b241c1b6 Merge pull request #14 from ajjjjjjjj/feature/flavour-name
Valid build flavour in about page.
2021-10-06 17:51:47 -03:00
Janek b54c232e75 Show section sizes after compilation.
RAM = bss + data
2021-10-06 22:51:35 +02:00
Mariano Dupont 3274e5818c Merge pull request #13 from ajjjjjjjj/feature/ram-savings
Backported Bsongis/ram saving #6685
2021-10-06 17:49:36 -03:00
Janek c17d27fff5 Buzzer
Restored "stock" siren pitch.
Fixed volume once again.
2021-10-06 21:18:47 +02:00
Janek 7b400b7cb8 Valid build flavour in about page. 2021-10-06 21:08:58 +02:00
Janek e722f2accb Backported Bsongis/ram saving #6685
In our case this reclaims 584 bytes of RAM, leaving us with total of 1112 bytes free at the moment.
The most of it is change to MIXER_STACK_SIZE. My basic tests showed no issue so far.
2021-10-06 21:06:03 +02:00
Mariano Dupont d59490c309 Bootloader 2021-10-06 10:56:12 -03:00
Mariano Dupont b5b66f903f Merge pull request #12 from marianomd/crossfire
CRSF support. ExpressLRS (including telemetry) working at 400k bauds.
2021-10-05 00:48:50 -03:00
Mariano Dupont d31275a873 CRSF working. ExpressLRS working. 2021-10-05 00:44:10 -03:00
Mariano Dupont 7aa965eb9c Crossfire support. Random crashes at 115200 baudrate. Continuous crashes at 400000. 2021-10-04 16:38:44 -03:00
Mariano Dupont bd7795d5be Cleanup 2021-10-02 20:26:35 -03:00
Mariano Dupont 6baabd445b EEPROM delay_ms instead of RTOS_WAIT_MS as corruption happens. 2021-10-02 09:30:40 -03:00
Mariano Dupont 033fd635c6 Fixed mixer scheduler 2021-10-01 19:15:50 -03:00
Mariano Dupont c064fa3472 Merge pull request #11 from ajjjjjjjj/feature/coos-fix2
Fixed CoOS Tick for STM32
2021-10-01 17:08:43 -03:00
Janek fb614956bc Fixed CoOS Tick for STM32 2021-10-01 21:08:56 +02:00
Mariano Dupont 71b53f3455 Merge pull request #10 from ajjjjjjjj/feature/coos-tick
Fixed CoOS Tick for STM32
2021-10-01 15:23:16 -03:00
Janek cb393ca5e2 Fixed CoOS Tick for STM32 2021-10-01 20:20:14 +02:00
Mariano Dupont 8ef5ceac41 Update README.md 2021-09-29 22:41:39 -03:00
Mariano Dupont 5764e73a84 Update README.md 2021-09-29 22:34:30 -03:00
Mariano Dupont 23a395c231 Update README.md 2021-09-29 22:33:37 -03:00
Mariano Dupont b748811487 Update README.md 2021-09-29 22:21:44 -03:00
Mariano Dupont 9642c2f6eb Merge branch '2.3_M0' of github.com:marianomd/opentx into 2.3_M0 2021-09-29 22:18:37 -03:00
Mariano Dupont 1d5e21e577 Internal module can be turned on and off correctly. 2021-09-29 22:18:22 -03:00
Mariano Dupont b400a21c62 Update README.md 2021-09-29 21:18:28 -03:00
Mariano Dupont 9dc49741e6 Merge branch '2.3_M0' of github.com:marianomd/opentx into 2.3_M0 2021-09-29 21:17:06 -03:00
Mariano Dupont bde2cb3630 External module (PPM) can be turned on and off correctly. 2021-09-29 21:16:47 -03:00
Mariano Dupont 6477fa6d8f Merge pull request #9 from ajjjjjjjj/feature/remove-sleep-logo
Sleep logo replaced with "Z Z Z", removes almost 0.5KB
2021-09-29 12:58:54 -03:00
Janek bd553dc9ed Sleep logo replaced with "Z Z Z", removes almost 0.5KB 2021-09-29 17:57:13 +02:00
Mariano Dupont 3c933fbb1c Update README.md 2021-09-29 12:09:45 -03:00
Mariano Dupont 9ed18d443f fix PPM timing 2021-09-29 11:58:26 -03:00
Mariano Dupont d4dcca8fcc Merge pull request #6 from marianomd/ppmout_wip
PPM out wip
2021-09-29 11:41:30 -03:00
Mariano Dupont 0b78fb627e PPM out working 2021-09-29 11:40:48 -03:00
Mariano Dupont 9ebd422aa2 Merge pull request #8 from ajjjjjjjj/feature/menu-final-touch
Menu hopefully done.
2021-09-28 20:33:30 -03:00
Janek 8c21f88ac0 - Removed [SD Logs] 2021-09-28 19:42:32 +02:00
Janek dc06b9f6bc - Removed unused functions from special function. In effect shaved off around 200 bytes. I have left [SD Logs] for now.
- Special function "Beep" is now "Play tone"
- fixed div / 3
2021-09-28 18:31:48 +02:00
Mariano Dupont e9072f6b76 Merge pull request #7 from ajjjjjjjj/feateure/main-menu
Removed blanks from Radio setup and optimized playTone routine.
2021-09-27 09:58:23 -03:00
Janek 74669077d4 Removed blanks from Radio setup.
Removed division from playTone routine.
2021-09-27 11:28:46 +02:00
Mariano Dupont 895213c01e PPM out: Fix pulses data 2021-09-26 14:17:58 -03:00
Mariano Dupont 18fa309d92 PPM out wip 2021-09-26 10:44:42 -03:00
Mariano Dupont 82035de603 Merge pull request #5 from ajjjjjjjj/feature/custom-telemetry-sounds
Fixed inactivity alarm, added custom telemetry sounds, improved settings
2021-09-26 10:41:44 -03:00
Janek 2bba3bfe71 Removed unused options from main menu, added pitch and length options 2021-09-26 15:25:37 +02:00
Janek 0bbc64d382 Changed tone 2021-09-26 13:43:31 +02:00
Janek 194d226903 Added board switch to do not break upstream 2021-09-26 09:32:12 +02:00
Janek 3583857225 Added custom telemetry sounds.
Fixed inactivity alarm.
2021-09-26 09:20:39 +02:00
Mariano Dupont 2a3e8a69d8 Update README.md 2021-09-25 20:07:58 -03:00
Mariano Dupont 09cc92fbea Merge pull request #4 from ajjjjjjjj/feature/alarms
Fixed battery and telemetry alarms.
2021-09-25 19:49:14 -03:00
Mariano Dupont 0b19e19ce7 Merge pull request #3 from ajjjjjjjj/feature/buzzer-tune
Buzzer improvements
2021-09-25 19:49:01 -03:00
Janek 16dea9fd3e Fixed battery and telemetry alarms. 2021-09-26 00:12:17 +02:00
Janek 7409b8621b Fine tuned volume steps.
Rearanged and remove traces to take less cycles.
Fixed queueing logic.
2021-09-25 23:23:11 +02:00
Mariano Dupont 0f5dad4dd5 Merge pull request #2 from ajjjjjjjj/feature/buzzer-tones
Playing tones implementation for buzzer driver
2021-09-25 15:58:36 -03:00
Janek 3561c2541a Added support for PLAY_NOW flag, prevents sound lags 2021-09-25 20:17:21 +02:00
Janek 9a5d12edab typo 2021-09-25 20:02:17 +02:00
Janek 9e35258da1 Fixed missing clock enable for GPIOA on release builds 2021-09-25 19:50:24 +02:00
Janek bdf6af5ae4 Playing tones implementation for buzzer driver 2021-09-25 18:42:58 +02:00
Mariano Dupont 4057179aa5 Update README.md 2021-09-23 16:55:29 -03:00
Mariano Dupont 9e39e461cc Update README.md 2021-09-23 16:55:01 -03:00
Mariano Dupont 927ea7538f Update README.md 2021-09-23 16:53:13 -03:00
Mariano Dupont ddfd11cdf3 Update README.md 2021-09-23 16:48:11 -03:00
Mariano Dupont 555f68c2e7 Merge pull request #1 from ajjjjjjjj/feature/buzzer
Added buzzer support using TIMER1
2021-09-23 14:17:26 -03:00
Janek 09adccaa1a cleanup 2021-09-23 18:49:56 +02:00
Janek bbc5d2d202 Added buzzer support using TIMER6 2021-09-23 18:32:53 +02:00
Mariano Dupont 2e9e366dbb Update README.md 2021-09-10 01:43:32 -03:00
Mariano Dupont 80e29f4c49 Update README.md 2021-09-09 12:48:22 -03:00
Mariano Dupont c5ef8bbb23 Backported mixer scheduler 2021-09-09 12:34:27 -03:00
Mariano Dupont 16384b5d83 Long press EXIT to shutdown gracefully. (Saves timers state) 2021-08-10 01:59:50 -03:00
Mariano Dupont 45d4007131 Update README.md 2021-08-08 18:25:04 -03:00
Mariano Dupont 7b957f5cf3 RSSI on channel 14 fixed. Selection of protocol subtype. Servo frequency setting. Fixed telemetry type setting. 2021-08-08 18:10:18 -03:00
Mariano Dupont 21d8cf97ba Corrected timers multiplier, timers were counting at half the speed. 2021-08-04 21:46:06 -03:00
Mariano Dupont 6707ba4599 Passed first test flight. Corrected main view channel output count, which caused a crash when scrolling to the nonexistent channels. 2021-08-04 17:46:50 -03:00
Mariano Dupont bed30d333a Telemetry 2021-08-03 10:04:33 -03:00
Mariano Dupont b0f26b4717 README 2021-08-02 14:03:17 -03:00
Mariano Dupont 52f14b35d9 st-link pinout 2021-08-02 14:01:41 -03:00
Mariano Dupont cc077a9088 README 2021-08-02 13:47:28 -03:00
Mariano Dupont d0192ab2be README 2021-08-02 13:44:26 -03:00
Mariano Dupont c6bf211ee4 README 2021-08-02 13:43:31 -03:00
Mariano Dupont 7aa17844d4 README 2021-08-02 13:42:25 -03:00
Mariano Dupont 69b5a51646 Failsafe working. Removed BIND as SHIFT. Keys mapping added to README. 2021-08-02 13:39:03 -03:00
Mariano Dupont a2c98d2fbb Internal module config in model setup. RF working. Binding working. Range check working. Channels transmitting. 2021-07-28 21:47:14 -03:00
Mariano Dupont fa8097cbf2 LCD contrast setting 2021-06-19 18:10:40 -03:00
Mariano Dupont 7c97574595 Trims working correctly 2021-06-18 13:06:06 -03:00
Mariano Dupont 32e22372f9 Update README.md 2021-06-17 14:21:15 -03:00
Mariano Dupont 040ff45116 Update README.md 2021-06-17 12:49:31 -03:00
Mariano Dupont 9c6f2d7fa1 * Set good calibration defaults on factory reset, taken from erfly6. * Restored BIND as SHIFT. SHIFT+UP for LEFT, SHIT+DN for RIGHT. Trims freed. * Fixed radio and model settings garbled text and crashes. 2021-06-17 12:20:31 -03:00
Mariano Dupont c27889358e Merge branch '2.3_M0' of https://github.com/marianomd/opentx into 2.3_M0 2021-06-16 23:59:34 -03:00
Mariano Dupont 7f96884927 Warning now dissapears when moving switches 2021-06-16 23:59:20 -03:00
Mariano Dupont 8d7b42a966 Update README.md 2021-06-16 11:15:20 -03:00
Mariano Dupont 0f1f091931 Update README.md 2021-06-16 06:38:15 -03:00
Mariano Dupont a234f60ff5 Updated README 2021-06-15 21:46:11 -03:00
Mariano Dupont 98a6aaa2ba Updated README 2021-06-15 20:56:12 -03:00
Mariano Dupont 3d7d7e51fb Switches working. Removed graceful shutdown as it seems it's not needed, trim freed up. MENU key moved to ENTER key again, hold for model config. Bind button freed. 2021-06-15 20:30:38 -03:00
Mariano Dupont 45c303c81a README updated 2021-06-14 20:29:10 -03:00
Mariano Dupont a8c4cfded2 Merge branch '2.3_M0' of https://github.com/marianomd/opentx into 2.3_M0 2021-06-14 20:25:43 -03:00
Mariano Dupont f62f367e0a EEPROM compression enabled. No more EEPROM errors. 2021-06-14 20:25:25 -03:00
Mariano Dupont 084162b4f3 Update README.md 2021-06-14 11:41:58 -03:00
Mariano Dupont eccb7f6424 Update README.md 2021-06-14 10:14:22 -03:00
Mariano Dupont 7d49d0035b * Graceful shutdown with right horizontal trim up 2021-06-14 10:13:02 -03:00
Mariano Dupont 2b1909f441 Update README.md 2021-06-13 17:24:30 -03:00
Mariano Dupont 7725731c54 README 2021-06-13 17:11:15 -03:00
Mariano Dupont 479df8b469 * ADC readings enabled
* Mixer enabled
* Enable WDT reset every 100ms (countdown was broken)
* Fix sticks inverted
* Fix battery voltage calculation
* Fix crash in calibration checksum 
* Bind key as MENU
2021-06-13 16:58:30 -03:00
Mariano Dupont 79aa45a7fa Disabled watchdog, to avoid resets in the meantime. Turn on backlight on keypress 2021-06-12 14:20:20 -03:00
Mariano Dupont 6ee22ab229 EEPROM implementation progress 2021-06-12 13:07:47 -03:00
Mariano Dupont ebac6de662 Merge branch '2.3_M0' of https://github.com/marianomd/opentx into 2.3_M0 2021-06-12 12:46:02 -03:00
Mariano Dupont 2780a4b2fe several failed alternatives to write eeprom 2021-06-10 20:50:40 -03:00
Mariano Dupont e7cf168eef Update README.md 2021-06-09 21:39:23 -03:00
Mariano Dupont 8b2ac12d42 Added USART1 on PA9/PA10 for debugging purposes. Added ADC processing (untested). Added i2c code (not working yet) 2021-06-09 21:21:04 -03:00
Mariano Dupont f8dac21700 Added USART1 on PA9/PA10 for debugging purposes. Added ADC processing (untested). Added i2c code (not working yet) 2021-06-09 21:19:27 -03:00
Jakub 29a552f870 Buzzer methods moved to buzzer.h. 2019-02-25 20:32:45 +01:00
Jakub 6f45c82c55 Merge remote-tracking branch 'remotes/origin/M0' into m0_2.3 2019-02-24 17:08:51 +01:00
Bertrand Songis 627c0282c9 Update CREDITS.txt 2019-02-22 19:25:01 +01:00
Bertrand Songis 5e7722b766 Update CREDITS.txt 2019-02-20 20:51:39 +01:00
3djc 5780a8fd78 Add telem1-32 and lua mixer outputs to LUA 2019-02-18 09:19:58 +01:00
Bertrand Songis 26692b457b Update CREDITS.txt 2019-02-12 20:07:43 +01:00
Bertrand Songis 2ff56febb8 Update CREDITS.txt 2019-02-11 00:14:06 +01:00
Bertrand Songis 0b3d9a7c16 Merge pull request #6311 from mzambrini/2.3
Corrected grammatical errors
2019-01-25 21:31:47 +01:00
Bertrand Songis f813b9923d Update CREDITS.txt 2019-01-25 13:03:12 +01:00
Bertrand Songis d3e839c8d0 Update CREDITS.txt 2019-01-25 11:37:33 +01:00
Massimiliano Zambrini a030f215dd Corrected grammatical errors 2019-01-24 10:48:17 +01:00
3djc 6a15e5373f Merge pull request #6308 from mzambrini/2.3
Enhanced Italian language sounds
2019-01-22 11:34:01 +01:00
Massimiliano Zambrini 490243eb11 enhanced Italian language sounds 2019-01-22 10:35:13 +01:00
Kilrah 00e28d3c0e flexr9m was missing from compile scripts for sky9x (fix #6305) 2019-01-20 19:56:45 +04:00
Bertrand Songis cf6f0f6f0b Update CREDITS.txt 2019-01-17 22:00:40 +01:00
Bertrand Songis 75ed73412d Update CREDITS.txt 2019-01-16 12:42:47 +01:00
Bertrand Songis 677df3c18e Update CREDITS.txt 2019-01-13 21:28:51 +01:00
Bertrand Songis 25761039f6 Update CREDITS.txt 2019-01-13 21:28:22 +01:00
Bertrand Songis 23e2c50300 Update CREDITS.txt 2019-01-09 17:44:15 +01:00
Bertrand Songis 31f1c7761f Update CREDITS.txt 2019-01-09 16:02:57 +01:00
3djc 415544d012 Fix Horus wiazrd when 'no motor' is choosen (continued) 2019-01-08 17:04:47 +01:00
3djc fd7f839342 Fix Horus wiazrd when 'no motor' is choosen 2019-01-08 16:36:18 +01:00
3djc d363f957f5 Fix SBEC sensor scale 2019-01-08 08:09:46 +01:00
3djc 7f7a694799 SBEC telem support 2019-01-08 08:09:30 +01:00
Neil Horne e67cb385be Add file name to model edit window title (#6288) 2019-01-07 09:33:56 +01:00
Bertrand Songis f858fa2234 Update CREDITS.txt 2019-01-06 11:05:07 +01:00
Bryan Mayland 0d7a486630 Display FlySky VOLTS values as signed integers (#6252)
Standard AFHDS2A protocol transmits all values as 2 raw bytes
and a stock FS-i6 transmitter shows voltage type values properly
as signed. This change interprets all UNIT_VOLTS FlySky telemetry
items as being signed 16-bit values so their display matches the
values displayed on stock FS-i6 and FS-i6X receivers.

Signed-off-by: Bryan Mayland <bmayland@capnbry.net>
2019-01-06 11:02:10 +01:00
MRC3742 350acc3cc3 Multi protocol updates to MPM version 1.2.1.16 (#6249) 2019-01-06 10:59:40 +01:00
Kilrah 3407f91aa0 Use website for release notes 2019-01-06 10:29:55 +01:00
Kilrah 1a96655173 R9M 1W setting is Auto up to 1W 2019-01-06 10:28:24 +01:00
Kilrah d35a8bdea3 R9M 1W setting is Auto up to 1W 2019-01-06 10:19:49 +01:00
Bertrand Songis 419da20ca4 Update CREDITS.txt 2019-01-05 20:58:01 +01:00
Bertrand Songis cad0d48456 Update CREDITS.txt 2018-12-24 00:25:23 +01:00
Bertrand Songis fb4160e8e8 Update CREDITS.txt 2018-12-23 11:47:49 +01:00
3djc e1d056486f Fix wrong default channels in D8 (thx @Kilrah) 2018-12-22 11:08:16 +01:00
Bertrand Songis 32a7b50318 Update CREDITS.txt 2018-12-22 10:11:34 +01:00
Bertrand Songis c7896aeecf Update CREDITS.txt 2018-12-20 19:39:17 +01:00
3djc 74b9446a30 Fix backlight not turning off on radio with physical on/off switch
This fixes #6270
2018-12-20 09:22:47 +01:00
Bertrand Songis c3cb7b78fe Update CREDITS.txt 2018-12-18 18:59:11 +01:00
Bertrand Songis b50a152dd5 Update CREDITS.txt 2018-12-17 21:31:39 +01:00
3djc edec4149cf Fix alignement 2018-12-16 14:55:20 +01:00
Bertrand Songis 2f4863241b Update CREDITS.txt 2018-12-16 09:21:50 +01:00
Bertrand Songis 03835558fc Update CREDITS.txt 2018-12-15 15:24:17 +01:00
Bertrand Songis 2ed1b6cf7c Update CREDITS.txt 2018-12-15 12:08:03 +01:00
Bertrand Songis 1d28f31916 Update CREDITS.txt 2018-12-13 19:41:36 +01:00
Kilrah 19898e3e0a Fix DIY_FIRST_ID 2018-12-13 11:25:40 +01:00
Bertrand Songis 3ecf8448f0 Update CREDITS.txt 2018-12-11 22:40:04 +01:00
Bertrand Songis ac80681b77 Update CREDITS.txt 2018-12-08 13:40:35 +01:00
Bertrand Songis 45ebb29de4 Update CREDITS.txt 2018-12-07 08:17:05 +01:00
Bertrand Songis 874356694c Update CREDITS.txt 2018-12-02 16:40:35 +01:00
Bertrand Songis 609a2a7d02 Remove unused variable 2018-11-28 16:50:47 +01:00
Bertrand Songis 8c336d52fa Update CREDITS.txt 2018-11-28 08:35:01 +01:00
Bertrand Songis ef94cf1dc1 Update CREDITS.txt 2018-11-16 07:51:57 +08:00
Bertrand Songis 861bb78be5 Update CREDITS.txt 2018-11-11 15:08:38 +01:00
Bertrand Songis 48070764e0 Update CREDITS.txt 2018-11-10 10:03:32 +01:00
Bertrand Songis c8676783d1 Update CREDITS.txt 2018-11-10 09:10:30 +01:00
3djc 5233fc85b8 Fix pxx1 2018-11-05 16:22:56 +01:00
Bertrand Songis 543021a300 Merge pull request #6213 from opentx/bsongis/pxx2
Pulses refactoring
2018-11-03 16:42:57 +01:00
Bertrand Songis 9d93d88a66 PXX seems now OK on X7. More tests needed 2018-11-03 16:28:57 +01:00
Bertrand Songis 2ddc047ac8 Update CREDITS.txt 2018-11-02 22:29:30 +01:00
Bertrand Songis da0fe00c10 Update CREDITS.txt 2018-10-27 16:13:12 +02:00
Bertrand Songis afb99946b2 Update CREDITS.txt 2018-10-26 21:33:04 +02:00
Kilrah 4ab9730ed6 flexr9m also for non-frsky arm (fix #6224) 2018-10-21 09:49:11 +02:00
Kilrah 8a56cbd577 No topbar on horus 2018-10-18 11:43:39 +02:00
Bertrand Songis d1ff86d336 Merge pull request #6220 from opentx/3djc/lua-add-curves-to-inputs
LUA : Add curves to inputs
2018-10-12 17:13:47 +02:00
Bertrand Songis 73d9d0ec06 Merge pull request #6219 from MRC3742/2.3
Multiprotocol listing updates for 2.3 branch
2018-10-12 08:09:12 +02:00
3djc 04c95d2fdb LUA : Add curves to inputs 2018-10-12 07:34:56 +02:00
3djc 577eb6224f Allow commit-tests to be run much faster on dev PC (does not affect adversely Travis) 2018-10-12 07:31:34 +02:00
MRC3742 8dd10103d6 Updates to build in 2.3 for ARM9X 2018-10-11 23:01:12 -04:00
MRC3742 3dbcd436e8 Multiprotocol listing updates for 2.3 branch 2018-10-11 21:53:05 -04:00
3djc b393976879 Add binding options to ARM non FRSKY boards (2.3 branch) 2018-10-11 10:07:55 +02:00
Bertrand Songis c19e363025 Merge pull request #6155 from elecpower/print_center_beep_refactor
Refactor print center beep
2018-10-11 09:50:06 +02:00
Bertrand Songis 4525087ce9 Merge pull request #6180 from opentx/mpaperno/cpn_noavr
Companion AVR removal - stage 1.
2018-10-11 09:47:44 +02:00
Bertrand Songis 15ed4f6d56 Merge pull request #6160 from opentx/mpaperno/simu_better_shutdown_2.3
Refactor simu startup and shutdown handling (for 2.3 branch):
2018-10-11 09:41:58 +02:00
3djc 7064a9fbcc Improve #6208 fix 2018-10-11 07:09:55 +02:00
Bertrand Songis 53df20c005 Fixes #6208 2018-10-10 18:23:05 +02:00
Bertrand Songis bbfa94151f Regular PXX will need to be checked 2018-10-10 09:49:25 +02:00
Bertrand Songis fd4b309e0b PXX2 uses S.PORT CRC algorithm 2018-10-10 09:47:34 +02:00
Bertrand Songis 2823fe9a12 PXX2 init was not called 2018-10-10 08:49:58 +02:00
Bertrand Songis 67b145b22e Compilation fixes 2018-10-09 22:56:51 +02:00
bsongis 62dcd6ac5e Refactoring continued 2018-10-09 12:47:22 +02:00
Bertrand Songis 946f66b128 Pulses refactoring ... WIP 2018-10-09 07:57:58 +02:00
Bertrand Songis f798bbfcc7 Wrong baudrate chosen for PXX2 on setup 2018-10-08 08:22:20 +02:00
Bertrand Songis 713402b572 PXX2 first draft 2018-10-08 00:12:53 +02:00
Bertrand Songis 415cda6fc9 Update CREDITS.txt 2018-10-06 12:14:52 +02:00
Bertrand Songis 1156aa24d0 Update CREDITS.txt 2018-10-05 07:42:28 +02:00
3djc 3faa7e10d0 Improve spanish timer speech 2018-10-04 17:13:00 +02:00
Bertrand Songis b97696624f Update CREDITS.txt 2018-10-01 20:31:15 +02:00
Bertrand Songis ece41bdd75 Update CREDITS.txt 2018-09-29 20:03:20 +02:00
3djc eddce1d770 Merge branch '2.3' of https://github.com/opentx/opentx into 2.3 2018-09-28 10:01:57 +02:00
3djc 4387fef301 Fixes to Gassuit for future firmware
SxR script for all radio
2018-09-28 10:01:15 +02:00
Bertrand Songis 39e761b76c Update CREDITS.txt 2018-09-27 19:16:44 +02:00
3djc f330ea8a90 Minor spanish TTS changes 2018-09-27 09:28:43 +02:00
Bertrand Songis 34f0ca5e8f Update CREDITS.txt 2018-09-26 09:07:29 +02:00
3djc e954d87b53 Improve x9 multi wizard 2018-09-24 14:34:36 +02:00
3djc 1c7a2194e1 Small multi wizard fixes 2018-09-24 14:28:02 +02:00
3djc af0b55f642 Default channel order to AETR and review pages sequence 2018-09-24 14:17:35 +02:00
Bertrand Songis bfcc0ffddf Update CREDITS.txt 2018-09-24 07:58:28 +02:00
Bertrand Songis b280886bca Update CREDITS.txt 2018-09-23 17:11:29 +02:00
Bertrand Songis 8d3ea37309 Update CREDITS.txt 2018-09-22 23:25:40 +02:00
3djc 3ee37466fd Xlite/X7 multi wizard update (now includes switches) 2018-09-21 19:04:56 +02:00
3djc 26c4927993 Prep for upcommnig GasSuite firmware update 2018-09-21 13:02:22 +02:00
Bertrand Songis 1bd8558eeb Update CREDITS.txt 2018-09-21 10:25:02 +02:00
Max Paperno a93ab235be [Companion][MdiChild] En/disable radio settings and model copy/paste actions when clipboard changes externally (another MDI window or CPN instance). 2018-09-19 17:21:38 -04:00
Bertrand Songis 347a6251e3 Update CREDITS.txt 2018-09-19 18:56:58 +02:00
Max Paperno f8afc40198 [Companion][Boards] Remove final usage of two function alias macros. 2018-09-19 06:47:36 -04:00
Max Paperno 681bc82185 [Companion] Move CHECK_IN_ARRAY() to macros.h; Change DIM() return type; Refactor/fix removeAccents() to handle uppercase. 2018-09-19 06:47:36 -04:00
Max Paperno b4d992f490 [Companion][Firmware] Make Option struct a member; Add/use typedefs for options group and list; Use accessor functions for languages and options; Re-arrange fw options a little for better layout in UI; Remove dead code, cosmetics. 2018-09-19 06:47:36 -04:00
Max Paperno 13b156402f [Companion] Verify that radio type in chosen profile actually exists, and add warning to the contrary (at startup and also on profile switch); Add/move some functionality to AppMessages and make it classy (todo: rename file). 2018-09-19 06:47:35 -04:00
Max Paperno fdcee1ca9f [Companion][Firmware] Cosmetics on translation calls. 2018-09-19 06:47:35 -04:00
Max Paperno 02655d055c [Companion][Firmware] Remove all AVR flavors and options from available firmwares list, but keep base types for import purposes; Consolidate "ARM9X" flavor options; Consolidate Rf options. 2018-09-19 06:47:35 -04:00
Max Paperno d8a06158b1 [Companion][AppPreferencesDialog] Refactor firmwareOptionChanged(), getFirmwareVariant(), & populateFirmwareOptions() for clarity/efficiency; Remove AVR-only "voice" option handling and related items; Add getBaseFirmware(). 2018-09-19 06:47:35 -04:00
Max Paperno 62608cdc7d [Companion][TelemetrySensorPanel] Fix signed/unsigned compare warning. 2018-09-19 05:23:41 -04:00
Max Paperno 1b00fd2a9d [Companion][TelemetrySimulator] Fix sending of A3/A4 values (closes #6177); Adjust some min/max value ranges which were too small, and individual cell max values which were too high. 2018-09-19 04:00:04 -04:00
Max Paperno 0ea4b9ed9b [Companion][TelemetrySensorPanel] Fix offset decimals not updating properly when sensor precision is changed. 2018-09-19 03:58:46 -04:00
Andre Bernet e85ad43821 Prevent page changes during value editing (#6124) 2018-09-18 10:54:54 +02:00
3djc 1257b50bf4 Fix for non certified firmware 2018-09-18 10:51:29 +02:00
Kilrah aa9fa1dc84 eu and flexr9m now mutually exclusive 2018-09-18 10:51:24 +02:00
3djc 6ed7c30952 GasSuite protocol changes 2018-09-11 16:34:35 +02:00
Max Paperno 31b9f805ea [Simulator] Fix telemetry simulator log reader expected header for Cels column (closes #6167). 2018-09-10 23:20:51 -04:00
Bertrand Songis 8da83db1e5 Update CREDITS.txt 2018-09-09 23:25:59 +02:00
Bertrand Songis 9b6ac82ad8 Update CREDITS.txt 2018-09-09 23:18:10 +02:00
Max Paperno 66cd99bf6b [simu] Updates for RTOS abstraction layer; Remove further SIMU_SLEEP usages. 2018-09-08 22:04:37 -04:00
Max Paperno a2006940db [simu] Refactor simu startup and shutdown handling (for 2.3 branch):
* Use pwrCheck() as primary control point for shutdown, centralizes thread control in simpgmspace module;
 * Remove main_thread_running in favor of separate variables for startup mode and shutdown flag;
 * Don't start a thread for ARM startup, just run simuMain() directly (the thread just exits anyway);
 * Refactor SIMU_SLEEP() macro, and remove all unnecessary uses of it, also remove SIMU_SLEEP_NORET;
 * Add startType param to opentxStart() to control splash and startup checks;
 * Fixes backlight never turning off in simulator with "SWITCH" power button type (pwrPressed() was always true);
 * Fixes simu shutdown when model checklist is displayed at startup;
 * Adds stubs to possibly simulate a "soft" power button in the future.
2018-09-08 22:04:37 -04:00
Max Paperno 942ae1847d [CLI] Update CLI to use RTOS abstraction layer; Also remove a redundant/unused runMemoryTest(). 2018-09-08 19:07:43 -04:00
Max Paperno 691d3e6e33 [rtos] Make sure RTOS_WAIT_MS() sleeps > 0 ticks; Add RTOS_GET_MS(); Calculate ticks per ms at compile time; Fix field narrowing warning on RTOS_GET_TIME(). 2018-09-08 18:51:36 -04:00
3djc 55789db088 Merge pull request #6154 from elecpower/print_model_switch_issue_23
Fix getSize corrupting model and settings
2018-09-05 11:55:52 +02:00
elecpower a006abb94b Fix getSize corrupting model and settings 2018-09-05 19:13:32 +10:00
elecpower a4e92e8821 Refactor center beep 2018-09-05 17:35:20 +10:00
3djc 7b61185287 Fix german sensor lost audio 2018-09-05 08:38:04 +02:00
Sebastien Charpentier 210cee96d8 Updated French translation (#6151)
* Initial version.

* Updated French translation.
2018-09-04 11:47:08 +02:00
Max Paperno 4ff75ae87f [Simulator] Fix mixer outputs monitor not updating when channel value hasn't changed (fixes #6064). (#6122) 2018-09-04 11:46:40 +02:00
3djc f13bf76699 Turn on backlight on power press (but not on startup) (#6145) 2018-09-02 13:35:25 +02:00
Bertrand Songis ddb9fac4e1 Update CREDITS.txt 2018-09-01 13:47:32 +02:00
3djc c259dbc6e0 Cosmetics 2018-09-01 09:38:39 +02:00
3djc 34891142ac Introduce GasSuite config tool (untested) 2018-09-01 09:06:00 +02:00
3djc cc92c8a229 Fix R9M flex power settings missing for non xlite 2018-08-31 18:26:35 +02:00
3djc e97cdd00a8 Merge fixes 2018-08-30 13:34:13 +02:00
3djc 95c035ed73 Support for non certified firmwares (#6118)
* Support new r9m firmwares

* More future proof, thx Kilrah

* (significant) typo

* Companion part

* Make support a compilation option

* Fix compilation for normal users

* Warning popup for usability tests

* Better implementation

* All sizes

* Cosmetics

* Flex is EU+/AU+ only

* [Companion] Handle "flexr9m" option in module settings UI (to match radio UI, including warning msg); Move some "toString" functions out of ModelPrinter into ModuleData/Multiprotocols; "Future-proof" available R9M power options based on "stdr9m" fw option; Fix missing "Hitec" MM protocol name; Fix printing of R9M-EU power level in ModelPrinter.

* Cosmetics

* Rename R9M flex option

* Move failsafe further back to prevent nav oddity
2018-08-30 13:16:39 +02:00
Bertrand Songis 6113494d08 Update CREDITS.txt 2018-08-27 22:18:35 +02:00
Bertrand Songis e2f126dd27 Update CREDITS.txt 2018-08-27 22:16:23 +02:00
Bertrand Songis a476ee53aa Update CREDITS.txt 2018-08-27 22:15:38 +02:00
Kilrah bf5e5874b4 [Companion] Set decimals first on autospinbox or value can be truncated (fix #6094) 2018-08-25 21:03:45 +02:00
Amir Guindehi 51b3a0c68f inverted direction of X9E wheel in devices menu, which was different from the direction taken in device menu. turning the wheel to the right moves down in the menus everywhere now. (#6117) 2018-08-25 10:13:59 +02:00
Bertrand Songis e65f72476a Update CREDITS.txt 2018-08-22 18:33:55 +02:00
Kilrah 9df21ceb6e NL TTS as copy of EN as per new info on #6108. 2018-08-19 11:43:04 +02:00
Kilrah d3d5e6f215 Sync companion TTS language list with firmware (fix #6108) 2018-08-18 11:53:28 +02:00
Bertrand Songis a13d17e413 Update CREDITS.txt 2018-08-15 14:45:29 +02:00
Bertrand Songis baf44c321a Update CREDITS.txt 2018-08-07 21:17:38 +02:00
Kilrah fbcdcabab5 VC++ compilation 2018-08-05 20:04:12 +02:00
Bertrand Songis 73c1ed4023 VC++ compilation fix 2018-08-05 19:55:59 +02:00
Bertrand Songis 2c47883cc2 Companion GCC8 warnings removed 2018-08-05 19:33:28 +02:00
Bertrand Songis 8a51682190 Merge pull request #6087 from opentx/rtos_and_align_macros
Rtos and align macros
2018-08-05 16:26:18 +02:00
Bertrand Songis f1c6333d5f The splash was not aligned => radio doesn't boot 2018-08-05 16:16:15 +02:00
Bertrand Songis 92de1313e7 Cosmetics 2018-08-05 15:58:16 +02:00
Kilrah ce7cb7f7e9 Fix Horus bootloader needing 2 encoder clicks per line 2018-08-05 15:47:57 +02:00
Bertrand Songis 4f741dfad2 Cosmetics 2018-08-05 15:47:53 +02:00
Bertrand Songis f226cde6fe Dead code removed 2018-08-05 15:27:50 +02:00
Bertrand Songis 7eb3eb9ec5 Cosmetics 2018-08-05 14:26:44 +02:00
Bertrand Songis ffa012eeb6 Cosmetics 2018-08-05 14:24:30 +02:00
Bertrand Songis 94f9eb7a35 Unused FSPLASH option removed 2018-08-05 14:22:23 +02:00
Bertrand Songis 6a520f18cf Update CREDITS.txt 2018-08-05 14:07:55 +02:00
Bertrand Songis de8f9ebac9 Compilation fix 2018-08-05 14:06:12 +02:00
Bertrand Songis b14f1f29a9 Compilation fix 2018-08-05 13:38:58 +02:00
Bertrand Songis 49aac252d7 Remaining Phase instead of Flightmode 2018-08-05 13:35:52 +02:00
Bertrand Songis ed91931184 More AVR removal 2018-08-05 13:12:51 +02:00
Bertrand Songis ea76998beb More AVR removal 2018-08-05 12:39:05 +02:00
Bertrand Songis f3bfde242b RTOS refactoring + more AVR removal 2018-08-05 12:06:48 +02:00
Bertrand Songis f60733b561 __ALIGNED macro unified 2018-08-05 09:56:47 +02:00
Bertrand Songis d47c3cedb4 Update CREDITS.txt 2018-08-05 09:04:34 +02:00
Bertrand Songis ea7ade197e MODULE_ALWAYS_SEND_PULSES define removed 2018-08-04 21:14:44 +02:00
Bertrand Songis bba0e5e00c Merge pull request #6038 from opentx/mpaperno/cpn_src_models
Conitnued RawSource/RawSwitch data models refactoring
2018-08-04 10:19:53 +02:00
Bertrand Songis b1cd632bd4 Merge pull request #6079 from opentx/schwabe/multinewprotocol
Update Multi protocols
2018-08-04 10:18:20 +02:00
Bertrand Songis 61b82254d0 Merge pull request #6084 from opentx/modules_type_macros
All macros for modules removed
2018-08-04 10:17:35 +02:00
Bertrand Songis 3c66454953 Merge pull request #6083 from opentx/gcc8_warnings_fixed
Gcc8 warnings fixed
2018-08-04 10:16:38 +02:00
Bertrand Songis 85ad25e0e8 All macros for modules removed 2018-08-04 00:13:32 +02:00
Bertrand Songis 131078e3a0 GCC new warnings fixed (GCC) 8.1.1 20180531 2018-08-03 23:02:43 +02:00
Bertrand Songis a77f00d665 Some bitmaps shifted by 2 pixels on load 2018-08-03 23:00:42 +02:00
Arne Schwabe eaae858a38 Update Multi protocols 2018-08-03 13:21:31 +02:00
Bertrand Songis cdfdcf6d13 VOICE definition removed (always used) 2018-08-03 08:33:33 +02:00
Bertrand Songis 298f41fc76 Update CREDITS.txt 2018-08-03 08:13:16 +02:00
Bertrand Songis cdab8a4d9e Update CREDITS.txt 2018-08-03 08:03:54 +02:00
Bertrand Songis d6d3bc0159 Update CREDITS.txt 2018-08-01 11:12:28 +02:00
Bertrand Songis 9ee8f3613f Update CREDITS.txt 2018-07-31 08:06:30 +02:00
Bertrand Songis 3b8dd447fa Update CREDITS.txt 2018-07-30 22:31:37 +02:00
Max Paperno b6a97318ec [Companion][FirmwarePreferencesDialog] Update the displayed latest firmware version number after a download completes. 2018-07-16 18:38:36 -04:00
Max Paperno 989abd017e [Companion][downloadDialog] Canceling the download dialog during download now terminates the active network request and removes the file. 2018-07-16 18:37:00 -04:00
Max Paperno 71fd6dfa47 [Companion][AppData] Fix firmware version storage path when reading. 2018-07-16 18:34:21 -04:00
Max Paperno 8d00e1dc8c [Companion][MainWindow] Allow aborting version update check network request. 2018-07-16 17:48:19 -04:00
Max Paperno 34e1075582 [Companion][AppPreferencesDialog] If not ALLOW_NIGHTLY_BUILDS then either hide nightly channel option, or if user already has it selected then display a warning (in case they also have nightly installed in parallel). 2018-07-16 17:39:22 -04:00
Max Paperno df5722717a [Companion] Centralize download URLs; URLs now based on build major.minor version macros; Remove AVR fw download URL; Make some QStrings cheaper. 2018-07-16 17:36:33 -04:00
Max Paperno 71c5132c57 [Companion][MainWindow] Fix update check progress bar dialog remaining open when unnecessary; Also check for firmware updates even if CPN check fails with error. 2018-07-16 16:54:36 -04:00
Max Paperno b15ac0f2e1 Merge branch '2.2' into 2.3 2018-07-16 14:01:33 -04:00
Kilrah 2296cd5faf Flight modes and "Tele" were unreachable in LS on 128x64 radios 2018-07-14 20:01:03 +02:00
Kilrah b50826bc74 Do not load global function scripts if global functions are disabled in model settings (fix #6029) 2018-07-14 13:21:24 +02:00
3djc 409036b6ed Possible fix to gtest 2018-07-14 11:13:46 +02:00
Bertrand Songis 5ee3825a50 Merge pull request #6041 from opentx/schwabe/fix_setcurves_6026
Fix setting x values < 0 for custom curvs (fixes #6026)
2018-07-13 19:58:14 +02:00
Arne Schwabe c99dc375e8 Fix setting x values < 0 for custom curves (fixes #6026)
Also accept bool for smooth parameter as the documentation suggest
2018-07-13 09:36:30 +02:00
Max Paperno ca63b92e5b [Companion] Refactor RawSource & RawSwitch data models to abstract the base classes and reduce redundancy; Move data models to own folder. 2018-07-12 13:20:07 -04:00
Max Paperno 70aa7c6ad8 [Companion] Refactor FlightModePanel and TimerPanel to use shared RawSwitch data models instead of one per instance. 2018-07-12 13:20:07 -04:00
Max Paperno 81c33b6432 [Companion] Refactor RawSwitchItemModel and RawSwitchFilterItemModel for better efficiency, does not invalidate whole model on updates (structure is almost identical to the RawSource variants). 2018-07-12 13:20:07 -04:00
Max Paperno b76a0a8789 Minor cleanup on RawSourceItemModel and TelemetryCustomScreen. 2018-07-12 13:20:07 -04:00
Max Paperno ed255ce1c3 [Companion] Updates to use new RawSource data models in UI. 2018-07-12 13:20:06 -04:00
Max Paperno 3b8d177861 [Companion] Start RawSource / RawSwitch data models refactor; Create RawSourceItemModel and RawSourceFilterItemModel. 2018-07-12 13:20:06 -04:00
Max Paperno 00efc0d571 Merge fix. 2018-07-12 13:15:41 -04:00
Max Paperno 7bc59784b5 Merge branch '2.2' into 2.3 2018-07-12 13:09:34 -04:00
3djc 3556d7c0e8 Apply #6036 equivalent to 2.3 2018-07-12 12:22:07 +02:00
Bertrand Songis b5078c5326 Merge pull request #6036 from opentx/bsongis/revert_PR#5664
Fixes #6032
2018-07-12 11:40:08 +02:00
3djc 89656d8195 Fix Gtest (fullfilling my debt !) 2018-07-12 08:56:03 +02:00
3djc 69d3e9be0a Add Gtest (fullfilling my debt !) 2018-07-12 07:40:57 +02:00
Bertrand Songis 94bd8a237d Revert "Apply THR trim when cross triming (#5664)"
This reverts commit 1ebd289
2018-07-12 00:42:38 +02:00
Bertrand Songis e10cbed69f Fixes #6032 2018-07-11 22:51:10 +02:00
Bertrand Songis 12d675a0a7 Merge pull request #6035 from opentx/virtual_inputs_define_removed
VIRTUAL_INPUTS #define removed
2018-07-11 22:39:26 +02:00
Bertrand Songis d2697345e1 VIRTUAL_INPUTS #define removed 2018-07-11 18:54:05 +02:00
Bertrand Songis a8707baf57 Merge pull request #6034 from opentx/navigation_files_splitted
Navigation methods splitted to avoid a lot of #ifdef
2018-07-11 16:39:02 +02:00
Bertrand Songis 5eff34ce8a Navigation methods splitted to avoid a lot of #ifdef 2018-07-11 15:17:14 +02:00
Bertrand Songis 0bb96a7413 Merge pull request #6033 from opentx/remaining_cpuarm_removed
Remaining CPUARM removed
2018-07-11 14:03:14 +02:00
Bertrand Songis db1d3fcb32 Remaining CPUARM removed 2018-07-11 13:33:51 +02:00
Bertrand Songis 3f1d09bc68 Merge pull request #6016 from opentx/schwabe/removeAVR
Remove a lot more AVR specific code
2018-07-11 13:19:23 +02:00
Max Paperno 39db1b6537 [Companion][LogicalSwitchesPanel] Workaround for added LSs missing from Sources selector on LS edit page (closes #4917 (again)). 2018-07-10 14:38:00 -04:00
Max Paperno c408c30bc1 Fix libsimulator build MSVC warnings introduced in commit 6110bbc. 2018-07-09 13:06:38 -04:00
Max Paperno 1e6cfc373e Rename jtag-flash -> flash-jtag 2018-07-09 12:18:40 -04:00
Max Paperno a611281a01 Flash with ST-LINK_CLI. 2018-07-09 12:18:39 -04:00
Max Paperno 6110bbce98 Support Companion build with clang-cl on Windows (fw/libsimu not working yet due to compiler-specific macros in that code). 2018-07-09 12:02:26 -04:00
Max Paperno d507dbb5dd Add SIMU_TARGET build option to exclude libsimulator & simu from all/install. 2018-07-09 11:53:38 -04:00
Max Paperno f60d3b80be Exclude Qt rendering engine binaries from Windows Companion install. 2018-07-09 11:48:04 -04:00
Max Paperno e24a736fc9 Merge branch '2.2' into 2.3 2018-07-08 21:01:01 -04:00
Raphael Coeffic e916c6dc9a fixed GPS coords precision in telemetry simulator when loaded from CSV log 2018-07-08 21:00:37 -04:00
Bertrand Songis 3540015132 Merge pull request #6002 from opentx/raphaelcoeffic/rle_bitmaps
[Horus] save space in bootloader and firmware by using RLE compression
2018-07-08 16:47:22 +02:00
Bertrand Songis 4909d176ec Merge pull request #6008 from opentx/raphaelcoeffic/lua_serial
add LUA access to serial port (serial2 and USB)
2018-07-08 16:44:55 +02:00
Bertrand Songis 2001c0d408 Merge pull request #6020 from opentx/mpaperno/sim_telemsim_pause_options
Add start/pause/RSSI-disable options to Telemetry Simulator
2018-07-08 16:41:36 +02:00
Kilrah 1383afb36f Use BT detection on X-Lite too (current prod has no module, preprod has one, future batches unknown) 2018-07-08 15:49:10 +02:00
Kilrah 9904d6deb0 Fix typo 2018-07-08 15:38:39 +02:00
Bertrand Songis e8d8fc1806 Prevent from writing the whole font when a char is missing (i.e. special chars) 2018-07-08 13:18:33 +02:00
Max Paperno 10e6745e21 Don't send telemetry when main simulator is not running. 2018-07-06 15:15:14 -04:00
Max Paperno b2713df6bb Cosmetics. 2018-07-06 14:59:43 -04:00
Max Paperno 23aaee9ecf [Simulator][TelemetrySimulator] Add persistent option to enable simulation when window is opened; Add option to pause simulation on window hide (was always true); Add option to set RSSI=0 on simulation pause to trigger “telemetry lost” alarm. 2018-07-06 14:03:41 -04:00
Raphael Coeffic 1fec7a7c51 enabled USB_SERIAL on Horus by default 2018-07-06 10:01:09 +02:00
Raphael Coeffic 25c02b96f3 add LUA access to serial port (serial2 and USB) 2018-07-06 10:01:09 +02:00
Raphael Coeffic 8e39de0368 fix horus LCD tests 2018-07-06 08:59:34 +02:00
Raphael Coeffic 7806382d8e add RLE support for other bootloader bitmaps as well 2018-07-06 08:59:34 +02:00
Raphael Coeffic 96afa57d84 use RLE compressed fonts on Horus 2018-07-06 08:59:34 +02:00
Raphael Coeffic caaba0ab3f img2lbm: added RLE encoding for 1bit, 4bit & 8bit formats
RLE encoding is triggered by using an output filename with “.rle” extension.
2018-07-06 08:59:33 +02:00
3djc 5dd365238e Merge branch '2.2' into 2.3 2018-07-06 07:16:27 +02:00
Bertrand Songis e6aea64689 Merge pull request #6006 from opentx/mpaperno/cpn_settings_refact
Refactor Companion settings system
2018-07-05 19:09:47 +02:00
Bertrand Songis 86b48d8258 Merge pull request #6009 from opentx/mpaperno/cpn_fsync_v2
SD Sync "version 3"
2018-07-05 19:07:10 +02:00
Raphael Coeffic 4880497db5 generate_datacopy.py fixes (#6015)
* fix generate_datacopy on osx

* more datacopy fixes

* added support for linux & llvm-3.8 (default on debian stretch)
2018-07-05 19:04:28 +02:00
Max Paperno d253c3163b [Companion] Delete QNetworkReply after update checks and release notes d-load (prevents leftover open handles, see QNetworkAccessManager docs); Use only one QNetworkAccessManager in MainWindow and properly dispose of it. (#6010) 2018-07-05 19:01:55 +02:00
Arne Schwabe 961c1d60e0 Remove templates 2018-07-05 12:05:55 +02:00
Arne Schwabe aa5d8c4ba7 Remove remaining references to Mavlink 2018-07-05 12:05:55 +02:00
Arne Schwabe c80f0da4ac Remove various references of AVR from script and referenced files 2018-07-05 12:05:55 +02:00
Arne Schwabe 9c7cfe9252 Remove all CPUM128/CPUM2560/CPUM2561 macros
Also remove pulses_avr*
2018-07-05 12:05:55 +02:00
Arne Schwabe a5b44fa877 Remove ARM_FIELD and AVR_FIELD macros 2018-07-05 12:05:55 +02:00
Arne Schwabe fdedcf4de0 Remove CASE_CURVES 2018-07-05 12:05:55 +02:00
Arne Schwabe 8530cce10a Remove CASE_PERSISTENT_TIMERS 2018-07-05 12:05:55 +02:00
Arne Schwabe c75d873b91 Remove CASE_CPUARM and IF_CPUARM macros 2018-07-05 12:05:55 +02:00
Arne Schwabe cbf60380f2 Assume CURVES are always defined 2018-07-05 12:05:55 +02:00
Arne Schwabe e76d1d0c3d Remove unused telemetry protocols 2018-07-05 12:05:55 +02:00
Arne Schwabe d831b0f55e More AVR cleanup 2018-07-05 12:05:54 +02:00
Max Paperno 4300e4b022 Merge branch '2.2' into 2.3 2018-07-05 05:30:58 -04:00
3djc ca3093e07e Do not build avr simu anymore 2018-07-05 10:26:17 +02:00
3djc 47cfd7da98 Fix some files permission 2018-07-05 10:06:19 +02:00
3djc 8e66b32c95 Fix some files permission 2018-07-05 10:05:07 +02:00
Kilrah 1dd3aadbd8 Display stick type when applicable
(cherry picked from commit daedeed)
2018-07-05 08:44:39 +02:00
LapinFou ec49fb9e49 Shorten translation.
(cherry picked from commit 337e224)
2018-07-05 08:44:28 +02:00
LapinFou 4313d23ba7 Updated French Translation.
(cherry picked from commit 8dda878)
2018-07-05 08:44:19 +02:00
LapinFou 5a6f3f04e7 Initial version.
(cherry picked from commit eeaab12)
2018-07-05 08:44:13 +02:00
Arne Schwabe aa1493cad0 Use nano.spec for linking bootloader (#6004)
This saves about 2kB on the Taranis X-Lite

(cherry picked from commit 5dd0ac7)
2018-07-05 08:43:46 +02:00
3djc dd632969f3 Massive clean thanks to Schwabe : unifdef -m -DCPUARM -UCPUM64 -UCPUM2560 -UPCBSTD -UPCBMEGA2560 -UPCBGRUVIN9X -UPCB9X $(find . -name "*.cpp" -or -name "*.h") 2018-07-05 08:04:55 +02:00
3djc c032b30247 avr-remove remove files in main dir and targets 2018-07-03 09:44:03 +02:00
3djc ec0c82a4bf avr-remove main CmakeList 2018-07-03 09:29:20 +02:00
3djc b07547df75 Remove avr from commit-tests.sh 2018-07-03 09:00:27 +02:00
3djc 617cc47231 Ask Travis to not build avr anymore 2018-07-02 15:14:42 +02:00
3djc fd68286b2f Merge pull request #6011 from opentx/LapinFou/Fr_Translation
Updated French translation
2018-07-02 12:33:33 +02:00
Kilrah daedeed8d7 Display stick type when applicable 2018-07-02 12:29:54 +02:00
LapinFou 337e224ad3 Shorten translation. 2018-07-02 10:17:25 +02:00
LapinFou 8dda878c62 Updated French Translation. 2018-07-01 18:05:56 +02:00
LapinFou eeaab1268e Initial version. 2018-07-01 18:03:23 +02:00
Max Paperno 66ffa18dce [Companion] Rework SD Sync implementation:
~ Move UI to new FileSyncDialog class;
  ~ Improve UI responsiveness during operation (closes #5005);
  + Add log verbosity option (also helps with UI response);
  + Add several filtering settings in new "extra options" panel (include/exlude patterns, symlinks, recursive, empty folders);
  ~ Exclude patterns ".*" and "System Volume*" by default (addresses #5213, #5106);
  + Sanity check file timestamps when using date comparison, future dates are invalid (addresses #5735);
  ~ Folders are no longer included in file counts (total/created/etc);
  ~ Ignore unreadable files/dirs (also enables NTFS permissions check);
  ~ Switch from QMutex to QReadWriteLock.
2018-06-30 12:03:49 -04:00
Arne Schwabe 5dd0ac75bc Use nano.spec for linking bootloader (#6004)
This saves about 2kB on the Taranis X-Lite
2018-06-30 17:40:33 +02:00
Max Paperno a236b4c59b [Companion][ProgressWidget] Improve handling of showing/hiding details text; Speed up addMessage(); Adjust layout size policies. 2018-06-30 10:24:09 -04:00
Max Paperno ff82a575f6 [Companion][AutoLineEdit] Add ability to work with QString data type w/out default validation. 2018-06-30 10:24:08 -04:00
Max Paperno 86fb88cdee [Companion][AutoComboBox] Add updateValue() function in line with other Auto* widgets; Add currentDataChanged() signal. 2018-06-30 10:24:08 -04:00
Max Paperno 316a2508a5 [Companion] Add AutoBitsetCheckBox 2018-06-30 10:24:08 -04:00
Max Paperno 63476c03f3 [Companion] Implement application settings import and export via GUI and CLI. 2018-06-29 20:18:35 -04:00
Max Paperno 60c8b1b2be Change to v2.3 [ci skip] 2018-06-29 20:13:27 -04:00
Max Paperno 988c837011 [Companion] Refactor settings system (CompStoreObj/AppData/etc):
~ All stored properties are fully dynamic, using an extended version of the Qt Property System;
 ~ CompStoreObj is now QObject subclass;
 + All properties now have change notifier signals;
 ~ Do not store default values in settings;
 + Add _reset() and _default() functions for each property;
 + Settings import now ignores all non-existent properties automatically;
 + Add settings export functions;
 + Add more version macros;
 ~ Remove template functions;
 ~ Move DownloadBranchType and create NewModelAction enums and register with Qt meta system;
 ~ Multiple efficiency and optimization changes (const functions, literals, etc).
2018-06-29 20:00:10 -04:00
Max Paperno 2869d8574d [SimulatorOptions] Add comparison operators. 2018-06-29 19:47:25 -04:00
Max Paperno d233fa39bd Bump version to 2.3.0 in CMakeFiles. 2018-06-29 19:44:39 -04:00
Arne Schwabe a26879dca8 Revert "Remove -nostartfiles linker option from bootloader (#5996)"
This reverts commit 17b4aa2466.

Removing the -nostartfiles caused the Taranis bootloader to include
a number of strange functions. Instead define _fini to avoid the linker
issues.
2018-06-30 00:46:50 +02:00
Arne Schwabe 429d55769c Revert "Remove -nostartfiles linker option from bootloader (#5996)"
This reverts commit 17b4aa2466.

Removing the -nostartfiles caused the Taranis bootloader to include
a number of strange functions. Instead define _fini to avoid the linker
issues.
2018-06-30 00:39:54 +02:00
Yannick Richter 9cbd0b9813 Full 11 bit USB HID gamepad resolution and fixed offsets for compatibility (#5825)
* Changed USB Gamepad resolution to full 11 bit and fixed offset issues for some games

* Changed USB Gamepad resolution to full 11 bit and fixed offset issues for some games

* Changed USB Gamepad resolution to full 11 bit and fixed offset issues for some games
2018-06-29 08:07:30 +02:00
Max Paperno 71912cfdbd Refactor Companion Windows install and installer targets (#5949)
* [companion][build][Windows] Refactor 'install' and 'installer' targets: Use qtwindeploy to collect Qt dependencies; 'install' with WIN_DO_FULL_INSTALL=YES now really copies everything needed; Simplified NSIS script, now also supports MinGW build; Refactor libeay search.

* Rename nsis input script.

* Fix NSIS input script name in CMakeLists.txt.

* [Companion][build] Create new Windows icon with more sizes; move icon files out of src root.
2018-06-29 08:07:02 +02:00
3djc 7db74cb017 Review pulse start sequence (#5998) 2018-06-29 08:05:08 +02:00
Max Paperno 2eec091ac0 Companion custom functions sound playback fixes (#6000)
* [CompanionIcon] Can now add multiple image files to icon for representing different UI states (checked/active/etc).

* [Companion][CustomFunctionsPanel] Fix sound file locked after playback (fixes #5222, fixes #5997); Refactor play button (fixes #4929); Create new QMediaPlayer on each play and load in "LowLatency" mode instead of stream.
2018-06-29 08:04:45 +02:00
Bertrand Songis cb19949a82 Update CREDITS.txt 2018-06-28 00:28:47 +02:00
Sebastien Charpentier 54e0795e51 Fr Translation update (#5991)
* Initial version.

* Updated French translation.
2018-06-27 16:13:40 +02:00
Raphael Coeffic 1492a346d3 fixes #5988 (#5992) 2018-06-27 16:12:33 +02:00
Arne Schwabe 968e7233e5 Clean up PWM stick reads, remove double averaging (#5995)
We already do averaging in the normal anaIn/getADC().
Also according to Mike's and my own research we don't need the averaging.

Tested on two X-Lites with PMW sticks
2018-06-27 16:10:27 +02:00
Arne Schwabe 17b4aa2466 Remove -nostartfiles linker option from bootloader (#5996)
* Remove -nostartfiles linker option from bootloader

Compiling with this option creates undefined references to _fini

* Remove now empty init.c
2018-06-27 16:09:12 +02:00
Bertrand Songis 6be0c3f4c6 Update CREDITS.txt 2018-06-25 14:45:50 +02:00
Kilrah c3b23fcc6e Prevent users from cheating (fix #5990) 2018-06-25 09:44:16 +02:00
Bertrand Songis af88b60c0e Update CREDITS.txt 2018-06-24 15:50:37 +02:00
3djc 793e971460 early release prep 2018-06-23 10:22:12 +02:00
3djc a9e88c272a Remove misleading RC99 (#5982)
Replace 'release' by 'version' in a few places
2018-06-23 09:07:13 +02:00
3djc f76c23d7f7 Remove nofp option for a few board (#5986)
* Remove nofp option for a few board

* Little fix
2018-06-23 09:06:43 +02:00
3djc c8205c4cff Cosmetics around R9M Lite FCC 2018-06-22 19:33:25 +02:00
3djc ab9b77fa90 Merge pull request #5985 from DieHertz/diehertz/crossfire-lua-xlite-support
Added X-Lite support to CROSSFIRE Lua
2018-06-22 09:44:37 +02:00
Andrey Mironov 80c2bc7242 Added X-Lite support to CROSSFIRE Lua 2018-06-22 10:11:06 +03:00
3djc 4d126dd91a Fix setFailafe SF
Fixes #5984
2018-06-22 07:51:05 +02:00
Bertrand Songis 8a30c5d951 Update CREDITS.txt 2018-06-20 16:04:27 +02:00
Bertrand Songis 817994c47e Update CREDITS.txt 2018-06-20 07:22:36 +02:00
Arne Schwabe e3ea859592 Ignore hidden folder on sync (#5976) 2018-06-18 15:39:34 +02:00
Kilrah 23f53077cf PPM frame length default was missing 2018-06-18 10:07:50 +02:00
Kilrah 091bf2fdf0 Hide hidden files 2018-06-17 22:07:33 +02:00
3djc 47dbd0dd3e Increment SDCard version for Russian TTS 2018-06-17 09:17:22 +02:00
Alexander Novikov 67585a6fa7 Fixed: long filenames (RU TTS) (#5974) 2018-06-16 22:35:30 +02:00
3djc 0d9aca84a9 Fix X7 R9M power line not enabled (#5973)
* Do not expect MODULE_R9M_FULLSIZE to be defined for non xlite

* Cosmetics
2018-06-16 19:24:46 +02:00
Kilrah a0c2f0bf19 Timer mode overflow (fix #5927) 2018-06-16 11:44:34 +02:00
3djc bd1c9274b3 Xlite adc stick fix (#5972)
* Xlite ADC stick order fix

* In the right order this time
2018-06-16 11:24:39 +02:00
Max Paperno 812ba76e0d [Companion][ModulePanel] Fix RF Output Power setting getting reset to default on every update() (re-opening model editor, etc) (fixes #5954); Prevent some needless updates during setup. (#5970) 2018-06-16 00:09:09 +02:00
Kilrah 60cf6b8058 DE translation fix 2018-06-15 23:00:06 +02:00
Kilrah ee4f8bda88 Don't reinitialise last flight mode on flight reset (Fix #5932) 2018-06-15 22:48:43 +02:00
3djc f50f2aefc0 French sensorok audio message changed to something less error prone. Update SDcard version to 17 2018-06-15 17:36:22 +02:00
Sebastien Charpentier 0e7e27edbf Updated French translation (#5967)
* Initial version

* Updated French translation.
2018-06-14 19:34:18 +02:00
Sebastien Charpentier a2d797310a Updated French Translation (#5955)
* Initial version

* French Translation
2018-06-13 22:28:08 +02:00
Max Paperno 1de4d86661 [Companion][MixesPanel] Fix disappearing mixer lines after an invalid line is removed. (#5957) 2018-06-13 22:27:45 +02:00
3djc cd7c075b3b Do not display disabled trim on main views (#5962)
* Proof of concept

* Add Horus

* Better implementation

* AVR compilation fix
2018-06-13 22:26:49 +02:00
Raphael Coeffic 6595bcfc3c fix models list reload after USB mass storage connection (#5963) 2018-06-13 22:26:11 +02:00
3djc 60423b81ad Turn backlight on for switch warning (#5965)
* Turn backlight on for switch warning

* Turn backlight on for splash screen
2018-06-13 22:25:42 +02:00
3djc 6898efcc02 Prevent X9E simu crash when BT is enabled (#5966)
* Better 'non horus BT' XE handling

* Cleanup

* Adjust BT message for X9E

* [Companion][HardwarePanel][X9E] Change BT Mode options to OFF/Enabled, X9E only.
2018-06-13 22:25:22 +02:00
3djc 7aca3eb5b7 Merge pull request #5964 from opentx/schwabe/fix_german
Fix a few things in german translation
2018-06-13 17:01:37 +02:00
Arne Schwabe 6f116510da Fix tts for German number over 100 with decimal point 2018-06-12 17:31:45 +02:00
Arne Schwabe ad26e4acba Fix German timer tts 2018-06-12 17:31:45 +02:00
Arne Schwabe 169d03ea9c Remove unused files for mac build 2018-06-12 14:20:23 +02:00
3djc 2de9c62083 Adapt to new server 2018-06-12 10:26:32 +02:00
3djc fd9ecc589e Add missing German tts strings 2018-06-12 09:58:37 +02:00
Kilrah d74c6acc0b We can now know what radio a random file comes from a little more easily... 2018-06-11 23:01:50 +02:00
3djc 9bdd0c682d Fix 2.2.2RC1 no gvar compile (#5961)
* Make model_gars.cpp flag dependend

* Cosmetics
2018-06-11 19:05:40 +01:00
3djc f135413b6d rc != release 2018-06-10 11:03:06 +02:00
3djc cebe1d0cb7 rc != release 2018-06-10 10:57:30 +02:00
3djc a3ee869ee9 Release prep 2018-06-10 10:09:35 +02:00
3djc f510650a42 Release prep 2018-06-10 09:04:19 +02:00
3djc add297920a Cosmetics 2018-06-09 12:04:36 +02:00
3djc 8cc61e5a8a Merge branch '2.2' of https://github.com/opentx/opentx into 2.2 2018-06-09 11:59:11 +02:00
3djc d58c660822 Add translation for HORUS text viewer 2018-06-09 11:59:02 +02:00
Neil Horne d460f005c6 Companion curve enhancements (#5947)
* Add point to custom curve using mouse click

* Add more curve enhancements delete and resize points

* add scene constructor
2018-06-09 11:35:41 +02:00
3djc 13c5387dc9 Disable pulse while model notes are displayed (#5758)
* Implement model note view without menu handler. Use it before pulse starts

* Also at model change. Handle wd reset and start pulses after mixer

* Fix Horus compile

* Fix Horus crash

* Fix coding style issue
2018-06-09 11:34:56 +02:00
3djc 45804b318a Improve r9m power handling (#5950)
* Rework around reusable buffer

* small fix

* Rework 212 & 480 handling too

* Optimize

* Compilation fix
2018-06-06 17:07:27 +02:00
Sebastien Charpentier 9ffcac744a Updated French Translation (#5948)
* Initial version

* Updated French translation + fixed some typo

* Fixed warning message
2018-06-06 11:19:18 +02:00
Bertrand Songis 365554980d Update CREDITS.txt 2018-06-05 18:27:05 +02:00
Arne Schwabe 702a8cb0c3 fix clang compiler warning 2018-06-05 11:21:10 +02:00
Max Paperno 0a4ca595ed [Companion][MixersListWidget] Enable multiple selection capability on Inputs and Mixes editors (closes #5029); Fix bug with custom style propagation; cosmetics. 2018-06-05 03:34:42 -04:00
Sebastien Charpentier 5302254462 Fr Translation (#5941)
* Initial version

* Updated French translation.
2018-06-04 22:23:21 +02:00
Max Paperno 41419b4cee [Companion] Move some single-use functions out of helpers module; cosmetics. 2018-06-04 05:15:16 -04:00
Max Paperno 8de53f18e6 [LogsDialog] Fix GE export on OSX (since 9796654). 2018-06-04 05:12:57 -04:00
Max Paperno 777fc58578 [Companion][ModulePanel] Fix RF Output Power warning message display. 2018-06-04 04:51:32 -04:00
Max Paperno e2977540d9 [Simulator][SimulatorOptions] Fix the misguided version check. 2018-06-04 04:51:09 -04:00
Arne Schwabe 0073889d93 Remove leftover text from old template 2018-06-04 10:28:12 +02:00
3djc c11a88f108 Fix title display issue in french under Liunux 2018-06-04 09:37:16 +02:00
Andre Bernet 14a96e17be OSX compilation 2018-06-04 07:57:28 +01:00
Max Paperno 2c5b54d7f3 [Companion][build][Windows] Allow alternate locations for OpenSSL DLLs to be included with CPN installation (removes PyQt4 dependency). (#5939) 2018-06-04 07:44:00 +02:00
Max Paperno 3af2b090e5 Fix remaining model editor sync issues with RawSource changes. (#5936)
* [Companion] Fix RawSource updates in Custom Function selectors (part fix for #4917).

* [Companion] Fix RawSource updates in HeliPanel selectors (closes #4917).
2018-06-03 23:20:14 +02:00
Max Paperno 9796654816 [Companion] Log viewer Google Earth fixes (#5937)
* [Companion][LogsDialog] Use relative path for Google Earth track icon (fixes #5080); Use detached process to launch GE (does not restart GE for every export, does not keep handle to GE process); Fix typo in warning message.

* [LogsDialog] Use GE export file path as base for icon path (don't assume TempDir); Fix auto-connection warning from Qt due to misnamed function; Remove redundant check for existing GE file.
2018-06-03 23:19:25 +02:00
Raphael Coeffic a6afbebc94 support for CLI (over USB CDC) without DEBUG (#5940) 2018-06-03 23:17:29 +02:00
Max Paperno 487c0de90f [Companion][InputsPanel] Fix "ghost" input names being left over when moving items (closes #5740); Cut/paste and drag-move will now also copy the input name if destination input is nameless and source input becomes empty (will not duplicate names); Clean up/simplify some code. (#5942) 2018-06-03 23:16:20 +02:00
Max Paperno c19b1a65bf [Companion][MdiChild] Possible fix for "disappearing" toolbars in file editor windows. 2018-06-03 15:42:52 -04:00
Max Paperno cd8f006d31 [Companion] HardwarePanel - fix saving of Bluetooth Mode selection (and related Qt warning), introduced in a87722b. 2018-06-02 21:10:51 -04:00
Max Paperno 40c5f0432c [Companion] AutoComboBox - fix possible crash with null field. 2018-06-02 21:10:51 -04:00
Bertrand Songis 6c51026357 Update CREDITS.txt 2018-06-02 21:31:21 +02:00
Bertrand Songis 806715e166 Bsongis/companion r9m fixes (#5914)
* Cosmetics

* First part ...

* First part ...

* Second part ...

* End?

* Handle new  R9M and R9M lite

* Display 'mini' module in case of R9M and xlite
2018-06-02 18:16:51 +02:00
Arne Schwabe 0e1a6bd60b Add issue templates (#5922) 2018-06-02 18:16:31 +02:00
Neil Horne 48f804210c Use fixed width font for checklist (#5925) 2018-06-02 18:15:53 +02:00
3djc a87722b078 Add BT mode handling (#5926)
Enable BT for Xlite and X7
2018-06-02 18:15:37 +02:00
Arne Schwabe e3f2664440 Update multi protocol definitions (#5930) 2018-06-02 18:15:13 +02:00
Arne Schwabe ce77fbd2ff No longer use deprecated qt5_use_modules (#5931)
QT 5.11 finally removes the qt5_use_modules macro.
Instead target_link_libraries with the Qt5::Lib added should be used.
Since we already use that in one place, it should work everywhere. Since
the common companion lib already depends on Core, widges and multimedia
components that link against it, also implicitly link against those
libraries.
2018-06-02 18:14:49 +02:00
Bertrand Songis 9612d6e347 Update CREDITS.txt 2018-05-31 20:53:12 +02:00
mhotar dd4cc710f2 Xlite simu images with transparency 2018-05-31 01:21:55 +02:00
3djc db9420e715 Adjust antenna selection text to actual radio capabilities 2018-05-30 10:10:35 +02:00
3djc f2c82a6262 Remove warning 2018-05-30 09:41:22 +02:00
Kilrah d23dd5b430 Antenna selection missing in companion for xlite 2018-05-30 09:24:36 +02:00
3djc 6d649279c8 Remove potentially misleading message. Fixes #5918 2018-05-30 08:40:39 +02:00
Kilrah 2cd4e6acfa Horus UI cosmetics 2018-05-27 17:57:03 +02:00
Kilrah b8e9d5542d Xlite LRUD key REPT events were missing in lua 2018-05-27 12:01:28 +02:00
Kilrah 487bf8bce7 Xlite can now change telemetry screens 2018-05-27 11:34:47 +02:00
3djc 535e41d43e Add required keyword for xlite. Fix #5909 2018-05-26 08:51:08 +02:00
Kilrah adbeb30c8b Remove inactive trims from Xlite right simu stick (TODO something nicer) 2018-05-24 21:01:35 +02:00
Sebastien Charpentier fc9ca545ad Fr translation update (#5906)
* Initial version

* Updated French translation

* 1 space was missing.

* - Translate last remaining field.
- Fixed F.In/F.Out translation.
2018-05-24 18:13:41 +02:00
Kilrah 3680b93d89 Fix compilation warning / code errors 2018-05-23 19:40:55 +02:00
Andre Bernet dba05e9adf Add missing simulators to linux companion build script 2018-05-23 19:03:38 +02:00
3djc ce344bc704 Cleanup 2018-05-23 17:12:48 +02:00
Kilrah 1df88dcb5f Disable option until implemented 2018-05-23 14:12:18 +02:00
Raphael Coeffic 3665d2afb4 added X9E navigation to the crossfire scripts (#5904)
Submitted on behalf of @aguindehi

fixes #5893
2018-05-23 08:10:35 +02:00
Kilrah ffb6b1a6fd Doc 2018-05-22 23:12:12 +02:00
Kilrah a1de19c105 Xlite simu shift working, dirty hack to get mouse wheel to do the right thing 2018-05-22 23:09:32 +02:00
Kilrah 31073fc0a9 Add X-Lite to simu build scripts 2018-05-22 22:35:45 +02:00
Kilrah 5fefc69eb6 Cosmetics 2018-05-22 22:29:08 +02:00
Kilrah f0bea027c1 Match voltage settings and fix simu giving voltage below default min 2018-05-22 22:27:59 +02:00
Andre Bernet 7ce17c56a2 Directory case issue 2018-05-22 21:46:15 +02:00
Kilrah e4fc76503c VC++ compilation 2018-05-22 21:29:55 +02:00
Kilrah d181050706 Cleanup 2018-05-22 21:09:50 +02:00
Kilrah a93692ee59 Xlite simulator WIP 2018-05-22 20:53:55 +02:00
Kilrah 88c72e0cb9 VC++ compilation 2018-05-22 19:29:48 +02:00
Raphael Coeffic 7379f6064e Horus: add receiver number check (#5841)
* add receiver number check for Horus

* find the first free model ID on LONG ENTER

* use the next free model ID for new models

* improve free model ID support for std LCD as well

* fixed “duplicate model”

* fixed ModelsList::isModelIdUnique()
2018-05-21 19:03:51 +02:00
Raphael Coeffic ea898e5122 [Horus] font fixes (#5901)
* avoid generating a blank part for font size that do not have extras

* use “stretch” instead of “jessie”

.. and add libgtest-dev.

* keep space width equal 4, no matter what

* updated generated fonts

* updated reference images

* Replace PyQt completely (#5902)

* ported img2lbm.py to Pillow (and get rid of PyQt)

* removed PyQt from Dockerfile

* fixed travis

* fixed issue with img2lbm and Horus bitmaps
2018-05-21 19:03:15 +02:00
Sebastien Charpentier 842b04627a DE Translation (#5892)
* Initial version.

* I'm pushing DE update on behalf of Helmut Renz.

* Version 2 of translation
2018-05-21 14:27:59 +02:00
Kilrah a368d74619 Revert "Xlite PPM/Heartbeat trainer input (#5881)"
This reverts commit 25049d041d.
2018-05-21 11:17:19 +02:00
mhotar 899240d2ac Xlite simu images
..someone should do the coding magic here :)
2018-05-21 10:50:04 +02:00
Raphael Coeffic 526f460cd4 Generate font bitmaps without Qt (using Python Pillow) (#5891)
* Generate font bitmaps without Qt (using Python Pillow)
* Roboto font now default
2018-05-21 10:45:13 +02:00
Andre Bernet 8e7e036591 Potential fix for #5895 (#5897)
Fixes #5895
2018-05-21 10:43:44 +02:00
Bertrand Songis 993e543162 Bsongis/issue 5896 (#5898)
* Fixes #5896
* No voltage alarm during X-Lite debugging ...
* Some cleanups
2018-05-21 10:40:34 +02:00
marbalon 1b3897a425 Validate RSSI instance to allow user defined RSSI source (issue #5842) (#5846) 2018-05-21 10:37:09 +02:00
Neil Horne 2f91eba85d Model print and compare user customisable style (#5866)
* New feature: Model print and compare customisable style

* Layout cosmetics.

* File handling tweak
Message cosmetics
2018-05-21 10:07:49 +02:00
Andre Bernet 25049d041d Xlite PPM/Heartbeat trainer input (#5881)
* Xlite PPM/Heartbeat trainer input

* UI adaptations

* Sky9x has no trainer settings!
2018-05-21 10:06:59 +02:00
3djc ae1aff6863 Fix scrolling on x7 model setup screen when pot warn is set to off 2018-05-20 15:45:06 +02:00
3djc 9227edac18 Revert "Fix #5896 (xlite center beep config missing last collumn)"
This reverts commit f5d61306c9.
2018-05-18 12:42:45 +02:00
3djc f5d61306c9 Fix #5896 (xlite center beep config missing last collumn) 2018-05-18 12:39:41 +02:00
Bertrand Songis 396b5fb270 Update CREDITS.txt 2018-05-17 18:11:17 +02:00
Bertrand Songis d2c0b0e0f5 Update CREDITS.txt 2018-05-16 08:34:57 +02:00
3djc 8366d6ec2a R9M Lite FCC has only one power mode (#5887)
* R9M Lite FCC has only one power mode

* Increase code reliability if new option changes are introduced
2018-05-15 16:41:56 +02:00
Bertrand Songis 0eeb197c81 Update CREDITS.txt 2018-05-14 18:47:38 +02:00
Kilrah 065c5916b7 Update all translations (getting close) 2018-05-13 21:26:56 +02:00
Sebastien Charpentier 0e93a43ab5 Updated French translation (#5886)
* Initial version

* Updated French Translation

* Clarification
2018-05-13 21:25:29 +02:00
Bertrand Songis fd3f2eb1e5 Compilation fix 2018-05-10 13:57:52 +02:00
3djc 46881aff2e Prep work 2018-05-10 09:33:56 +02:00
Bertrand Songis db276cecbf S.PORT flash on all available interfaces (possibly 3) 2018-05-10 08:22:39 +02:00
Bertrand Songis 0c7add8f8e Bsongis/travis fail (#5882)
Travis again here
2018-05-10 08:20:55 +02:00
3djc 6896381ab2 Bumping SD version so it does not get forgotten 2018-05-09 10:50:24 +02:00
Raphael Coeffic 56d040ee06 Reset backlight timer on rotary encoder (keys mode) (#5874)
* horus: reset backlight timer on rotary encoder (keys mode)
* taranis: reset backlight timer on rotary encoder (keys mode)
2018-05-08 22:39:02 +02:00
Raphael Coeffic 462f6244aa fixes #5870 (#5876)
fixes #5870
2018-05-08 22:33:58 +02:00
Raphael Coeffic 54d430f3c5 [X10] mute audio when fifo buffer is empty (#5875)
* [X10] mute audio when fifo buffer is empty
* do not push audio data if volume is muted.
2018-05-08 22:27:19 +02:00
3djc f2d444e2d5 some xlite peripheral settings (#5877)
* Refine xlite compilation options

* noras is for 9d+ only
2018-05-08 22:19:04 +02:00
3djc 23e2e3743c Future R9MEU firmware preparation (#5869)
PXX update for R9M FCC/EU
2018-05-07 21:54:20 +02:00
Alexander Novikov 2d207b528a Added: "thousand" and "thousands" (system sounds, Russian voice) (#5872)
Fixed: pronunciation of some phrases (Ru)
Added: some extra voice messages (Ru): flight modes/statuses etc
2018-05-07 21:52:07 +02:00
Kilrah 843f17e56f Merge remote-tracking branch 'origin/3djc/xlite-swwarning-fix' into 2.2 2018-05-07 10:36:59 +02:00
3djc 9915a1fd3a Make xlite sw toggle warning more natural 2018-05-07 10:33:51 +02:00
3djc 3334e06ec6 Fix xlite POTS 2018-05-07 09:59:52 +02:00
Kilrah 78e0a4ff1e PPM center was displayed wrong on 128x64 2018-05-07 09:42:49 +02:00
3djc b5d6761fe4 Fix missing column on xlite 2018-05-07 09:38:51 +02:00
Raphael Coeffic b29352b816 fixes trim re-use for T5 & T6 (#5873) 2018-05-06 21:42:43 +02:00
3djc a778116b9a Dirty fix (but can we do any better ?) (#5863) 2018-05-04 15:10:08 +02:00
Bertrand Songis 1afaded712 [Xlite] Either ADC or PWM used for sticks (similar to X10) (#5867) 2018-05-04 13:58:47 +02:00
3djc c7e63f52ce Update Travis QT version 2018-05-03 12:47:06 +02:00
Bertrand Songis 5696165d66 Update CREDITS.txt 2018-05-02 16:04:54 +02:00
qba667 2ef3d72c72 LEFT and RIGHT working for navigation again. 2018-05-01 15:45:08 +02:00
qba667 33807621bc Boot success. Mixed disabled. 2018-05-01 13:42:28 +02:00
Bertrand Songis cfc02f67eb Bsongis/xlite pxx (#5856)
Pulses refactoring
2018-04-29 22:55:29 +02:00
3djc 6ec64b227c 3djc/xlite sf nav (#5855)
* Another nav

* Fix popup

* Cosmetics
2018-04-29 22:17:27 +02:00
Bertrand Songis 5ca7cbc91e Update CREDITS.txt 2018-04-29 18:53:26 +02:00
qba667 bb51e7c0f6 Boot on M0 completed. 2018-04-29 14:33:01 +02:00
Kilrah 6ada5d46b0 Better trainer mode default on Xlite 2018-04-29 11:20:08 +02:00
Andre Bernet 69bf7b3cd3 Always map xlite primary trims to Aileron/Elev (#5852) 2018-04-28 15:51:29 +02:00
Kilrah b386dd23fb Fix fast value edit 2018-04-27 12:56:28 +02:00
Kilrah fd4e03c565 Correct switch support 2018-04-27 12:46:06 +02:00
Kilrah 15c5898488 Fix SF Play Track on SC-SD 2018-04-27 12:35:24 +02:00
Bertrand Songis a0c1beb61f [X-Lite] Next round of changes (#5847)
* [X-Lite] PXX is now sent every 4ms
* New option PXX_FREQUENCY (HIGH / LOW)
* [X-Lite] It now sends 16 channels per 4ms
2018-04-27 08:45:00 +02:00
3djc 7979401675 Remove unneeded test 2018-04-26 19:29:35 +02:00
3djc 09e6fde327 Fix broken name edition (@bsongis please double check) 2018-04-26 10:22:09 +02:00
3djc a2518c1156 fix sxr xlite 2018-04-26 09:57:16 +02:00
3djc f70dba5e6e 'shift' less nav 2018-04-26 09:19:34 +02:00
Bertrand Songis 99604dccc9 XLite support (#5806) 2018-04-25 23:07:04 +02:00
Sebastien Charpentier 37f96d452a Fr Translation (#5845)
* Fixed few typos.

* CFN (Custom Fonction N) translation.

* Removed useless dot.
2018-04-25 19:14:14 +02:00
Bertrand Songis 584a4e082e Update CREDITS.txt 2018-04-25 13:05:06 +02:00
Jesper Frickmann d59a853f0c Issue #5696 (#5698)
When an "Adjust GV" special function is reusing trim buttons to increase/decrease GVs, then the trim limits are applied instead of GV limits. This patch applies the GV limits.
2018-04-25 08:04:43 +02:00
Raphael Coeffic 2ad0db2d80 Set all custom failsafe channels at once (#5834)
* added setCustomFailsafe()

* failsafe setup: set all custom channels with ENTER long press

implements #5820

* added “outputs -> failsafe” menu item on horus

* change “Trims >> Subtrims” to “Trims => Subtrims”

* use translated string for “Outputs => Failsafe”

* fixed entered TR_TRIMS2OFFSETS and TR_OUTPUTS2FAILSAFE

When using ZCHARs in Horus texts, there are some artefacts when highlighted.

* added “outputs -> failsafe” menu item on taranis 212x64 LCD

* added “outputs -> failsafe” menu item on taranis 128x64 LCD

* fixed indentation
2018-04-24 08:13:09 +02:00
qba667 9a66d29b6b Merge branch 'M0' of https://github.com/qba667/opentx into M0 2018-04-23 18:22:44 +02:00
qba667 2cb53563f2 Using --specs=nano.specs 2018-04-23 18:22:09 +02:00
3djc 4f8f00c4e2 Make cut use mixer instead of override (#5799)
Make cut use mixer instead of override
2018-04-23 13:15:14 +02:00
Raphael Coeffic 697403b841 fixed PIXEL_PTR() macro on X10
fixes #5764
2018-04-22 12:06:20 +02:00
Jakub 43add842ae Unused modules removed.
Telemetry sensors limited to 16
MSC_MEDIA_PACKET set to 128
Serial2 disabled
Menu stack reduced
2018-04-19 14:45:27 +02:00
Jakub b4b6e064f3 Using nano.specs but not bin allocator. 2018-04-19 13:42:20 +02:00
Jakub 44bbcd9c06 Using AVR sound on STM32F0 2018-04-19 13:27:09 +02:00
Bertrand Songis 1f8ebea10c Update CREDITS.txt 2018-04-18 15:42:56 +02:00
Bertrand Songis fb4bc0a528 Update CREDITS.txt 2018-04-18 15:42:33 +02:00
Andre Bernet 01c37701d9 New chat URL 2018-04-18 16:50:38 +04:00
Jakub 23c1d39bc4 PXX removed for M0 2018-04-18 12:22:42 +02:00
3djc 5b15481138 Update README.md 2018-04-17 12:21:50 +02:00
Sebastien Charpentier 8f8b809756 Updated French Translation (#5832)
* Initial version

* Updated French translation
2018-04-16 22:48:39 +02:00
qba667 a13f6f4dd9 Try to fit into STM32F091 2018-04-16 21:34:01 +02:00
Raphael Coeffic 29cbeb8782 add boot version tag to taranis bootloader (#5831)
Allows for detecting the bootloader at the beginning of firmware.

fixes #5826
2018-04-16 07:30:09 +04:00
qba667 ea55b42bc8 Compiling without errors. 2018-04-15 18:19:29 +02:00
3djc 746a2ae528 Improve switch warning UI for 128x64 Taranis (#5822)
* - Match X9 behavior
- Made to handle replacing SH by a two pos and the future two additional switches
- Use string tables to find switch standard designation

* Compile fix
2018-04-15 09:47:35 +02:00
Bertrand Songis 9c4a81a6ee Fixes #5816 (#5830) 2018-04-15 09:46:17 +02:00
Bertrand Songis bae00c0e20 Update CREDITS.txt 2018-04-12 22:12:41 +02:00
3djc 1835cb12be Fix small negative GPS values (#5810) 2018-04-12 22:05:15 +04:00
Max Paperno 9e4a0680ab [Simulator] Add mixes display to Radio Outputs widget (#5811)
* [Simulator] Add mixes output display to RadioOutputsWidget (closes #2655).

* Add proper limits reporting & representation for channel and mix values in RadioOutputsWidget.
2018-04-12 22:02:27 +04:00
Raphael Coeffic 7b12c99a0b bootloader: use software reset instead of jump (#5823)
fixes #5627
2018-04-12 20:49:50 +04:00
Bertrand Songis 39c5d65f76 Update CREDITS.txt 2018-04-11 21:53:29 +02:00
Bertrand Songis 5f91426fec Update CREDITS.txt 2018-04-10 17:57:26 +02:00
Jakub 3049096b3e porting backup 2018-04-10 16:54:06 +02:00
3djc 910fc28dce Rework BL behavior for Horus (#5813) 2018-04-10 11:40:45 +02:00
qba667 2a57b9317c Target added 2018-04-10 07:20:47 +02:00
qba667 64e79d6a78 Working copy 2018-04-10 07:20:21 +02:00
Bertrand Songis f79703e7fd Update CREDITS.txt 2018-04-08 21:09:38 +02:00
qba667 73e72be323 Common files added for F0 2018-04-08 13:57:16 +02:00
qba667 16009cfde9 CoOS added config for M0 2018-04-08 13:54:33 +02:00
qba667 99369facbf STM32F0xx_StdPeriph_Lib_V1.5.0 added 2018-04-08 13:53:13 +02:00
Bertrand Songis 85a2a575a3 Update CREDITS.txt 2018-04-07 08:33:08 +02:00
3djc a07f37e99d Merge pull request #5805 from opentx/LapinFou/Fr_Translation
Updated French translation
2018-04-05 20:17:39 +02:00
LapinFou 3d0fd81cc4 Fixed wrong (and confusing) translation. 2018-04-05 20:10:17 +02:00
Bertrand Songis ec463819fe Bsongis/xlite fixes (#5803)
X-Lite fixes
2018-04-04 23:40:21 +02:00
Bertrand Songis fabee0e675 X-Lite bootloader 2018-04-04 16:01:15 +02:00
3djc 1b005c83eb Review newAntennaSel 2018-04-04 11:29:34 +02:00
Bertrand Songis c7e882e97d X-Lite external antenna on internal module 2018-04-04 11:05:07 +02:00
Bertrand Songis 0c09c07cd2 xlite antenna selection menu (#5801) 2018-04-04 11:00:24 +02:00
3djc b02344ffc5 Rework Horus BL handling (#5800) 2018-04-03 23:05:27 +02:00
Bertrand Songis 329b753df5 XLite REV 0.2 support (#5785)
XLite REV 0.2 support
2018-04-02 20:37:34 +02:00
3djc 6535ccbdd8 Improve RSSI shutdown display message on Horus (#5782)
Improve RSSI shutdown display message on Horus
2018-04-02 17:11:45 +02:00
Martin Hotar 6a7ed83f6a horus mask_iconback fixed (#5795)
mask_iconback in modelsel did not fit to the category text size
2018-04-02 17:04:09 +02:00
Bertrand Songis a1863b9fed Update CREDITS.txt 2018-04-01 14:54:09 +02:00
Bertrand Songis 5af04b84f0 Update CREDITS.txt 2018-03-31 10:03:00 +02:00
Bertrand Songis f11de747de Update CREDITS.txt 2018-03-29 07:28:18 +02:00
3djc e51eae5203 Merge pull request #5788 from opentx/LapinFou/Fr_Translation
Updated French translation
2018-03-28 22:08:07 +02:00
LapinFou a3838e1023 Update French translation 2018-03-28 21:28:03 +02:00
LapinFou fb6790c4f5 Initial version 2018-03-28 21:18:08 +02:00
Bertrand Songis 93ca928e98 Update CREDITS.txt 2018-03-28 19:14:31 +02:00
Bertrand Songis 40cd40cebd Update CREDITS.txt 2018-03-26 18:19:23 +02:00
Bertrand Songis 59f680048b Update CREDITS.txt 2018-03-25 23:55:05 +02:00
Neil Horne 33998c2981 Add Companion Outputs context menu (#5665)
* Start of cut copy paste delete

* Outputs context menu continued

* Mods from testing

* Add tool tip to channel label
2018-03-25 09:44:41 +02:00
Alexander Novikov 6e756c434a Fixed: compilation if SIMU_DISKIO = ON (#5723) 2018-03-25 09:39:17 +02:00
3djc b00c4e30d0 Use first persistant timer as display value in Horus modelselect (#5772)
[Horus] When selecting model, displays first permanent timer or 00:00 if none exist
2018-03-25 09:33:55 +02:00
3djc 0025c01024 Add mixer warning UI to Horus (#5780) 2018-03-25 09:21:40 +02:00
Bertrand Songis 05c7fbeb0b Update CREDITS.txt 2018-03-22 18:54:27 +01:00
Bertrand Songis 84c4b3c1b8 Missing x100 factor for ESC RPMs 2018-03-21 18:56:41 +01:00
3djc d76c693147 Improve some messsages (#5778) 2018-03-21 18:48:23 +01:00
Bertrand Songis b331363de1 Update CREDITS.txt 2018-03-19 19:36:35 +01:00
Bertrand Songis daad94eedb Update CREDITS.txt 2018-03-18 18:01:33 +01:00
Bertrand Songis 2b604a49ea FrSky new sensors support (#5766)
FrSky new sensors support
2018-03-17 22:50:06 +01:00
Bertrand Songis 2415418dca Update CREDITS.txt 2018-03-17 22:28:44 +01:00
3djc 1ffc4b9f7f Fix for S6R that are not showing quick mode for unknown reason (#5768) 2018-03-17 18:20:42 +04:00
Bertrand Songis dd5fb2cf88 Update CREDITS.txt 2018-03-16 20:28:54 +01:00
Bertrand Songis cdb2b2e1a7 Update CREDITS.txt 2018-03-13 21:05:24 +01:00
Arne Schwabe 14ea97337b Fix translation of remotes (closes #5760) (#5762) 2018-03-13 21:25:24 +04:00
3djc 533225f106 Merge pull request #5755 from opentx/LapinFou/Fr_Translation
Updated French translation
2018-03-10 19:19:38 +01:00
LapinFou 760b5ad276 Updated French translation. 2018-03-10 18:20:43 +01:00
LapinFou b5d689f39f Initial version 2018-03-10 18:13:21 +01:00
Bertrand Songis e5203b6e4a Update CREDITS.txt 2018-03-09 18:21:37 +01:00
Bertrand Songis a9d787b340 Update CREDITS.txt 2018-03-08 20:45:28 +01:00
Bertrand Songis 05144f39df Update CREDITS.txt 2018-03-06 17:29:54 +01:00
3djc 6bd38ce13a Replicate center trim beep behavior also when crossing trims (#5693)
* Replicate center trim beep behavior also when crossing trims

* Cosmetics
2018-03-04 13:11:22 +01:00
3djc a9716a340d For tests (#5702) 2018-03-04 13:10:35 +01:00
3djc 4a88660a3d Allow more the 2 hours digits for TIMEHOUR (#5715)
* Handle 3 digits or more in TIMEHOUR

* Cleanup
2018-03-04 13:09:59 +01:00
Andre Bernet da5af2cac2 Merge pull request #5742 from opentx/3djc/r9m-internall-ppm
Fix R9M missing bind when internal ppm is selected
2018-03-04 13:09:09 +01:00
Andre Bernet f7756d7d4d Merge pull request #5746 from opentx/3djc/fix-version-display
Fix UUID display on version screen
2018-03-04 13:04:34 +01:00
3djc a7a6a3d124 Lets not get something you can't display ! 2018-03-04 13:00:19 +01:00
3djc c905ed0338 Refresh UUID each run 2018-03-04 10:19:47 +01:00
3djc 455093ca23 Adapt FAI warning message 2018-03-03 18:58:08 +01:00
3djc cbf596e410 Remove internalppm from x7 options since it was never coded into 128 gui 2018-03-03 08:50:09 +01:00
3djc 78b3c5ec3f TARANIS_INTERNAL_PPM fixes 2018-03-02 16:01:01 +01:00
3djc 236b8991f6 Merge pull request #5736 from opentx/3djc/faimode-review
FAI mode reworks
2018-03-02 10:10:06 +01:00
3djc c8d9d18537 Fine tune 2018-03-02 08:29:41 +01:00
Bertrand Songis 3d7cca91ff Update CREDITS.txt 2018-02-28 22:56:38 +01:00
3djc 09a391dbf4 Crossfire compile fixes 2018-02-28 19:36:23 +01:00
3djc 9e0d29db1a Completely untested crossfire 2018-02-28 19:11:46 +01:00
3djc fcf32c82ba multi protocol 2018-02-28 18:09:18 +01:00
3djc 3ea835117a RxBt is allowed too 2018-02-28 17:46:47 +01:00
3djc 90ebc1a8be AVR compilation fix 2018-02-28 12:58:55 +01:00
3djc af7183151c Restore access from LUA since values are controled 2018-02-28 12:32:47 +01:00
3djc b8cb379234 Display telem screen is now ok since we control values 2018-02-28 12:30:06 +01:00
3djc fdf4d4926f POC for review and discussion 2018-02-28 11:34:32 +01:00
Kilrah 4cccff934f AVR version handling issues 2018-02-26 20:31:20 +01:00
Bertrand Songis 52e3a3fc15 Update CREDITS.txt 2018-02-25 20:54:55 +01:00
tgreer 4b7f822848 added case for UNIT_TEXT used by crossfire FM Sensor (#5724) 2018-02-25 01:18:23 +01:00
Jim Taylor a35ffe16cc Fix Issue 5633 - Workaround for Linux QT Styles (Breeze, Oxygen, ?) returning bad rect width. (#5695)
* Fix Issue 5633 - Workaround for Linux QT Styles (Breeze, Oxygen, ?) returning bad rect width.
2018-02-20 01:25:54 -05:00
Bertrand Songis 3785e24077 Update CREDITS.txt 2018-02-18 17:24:06 +01:00
Bertrand Songis 82ba845fc7 Update CREDITS.txt 2018-02-18 09:59:37 +01:00
Bertrand Songis a113154708 Update CREDITS.txt 2018-02-15 08:21:15 +01:00
3djc 11c2440dcd Small cleanup 2018-02-13 13:12:49 +01:00
3djc 17f686f39c Merge pull request #5689 from opentx/LapinFou/FixedWizard
Fixed Wizard Lua scripts for Horus radios.
2018-02-12 16:54:18 +01:00
LapinFou f498b54648 Fixed Wizard Lua script for Horus radios. 2018-02-12 16:29:45 +01:00
Kilrah 06141feb8b Translations 2018-02-11 23:46:19 +01:00
3djc b74b005215 Rename confusing Master/Battery to Master/Serial (#5663) 2018-02-11 23:43:12 +01:00
Kilrah 4c212ae507 Translations 2018-02-11 23:42:56 +01:00
3djc 1ebd2894c2 Apply THR trim when cross triming (#5664) 2018-02-11 23:26:29 +01:00
3djc d3951235bd Add gtimer support to LUA (#5669)
* Add gtimer support to LUA

* Copy/paste issue
2018-02-11 23:25:04 +01:00
3djc 073e1a8462 Align X9E audio definitions to ana inputs (#5687) 2018-02-11 23:23:40 +01:00
3djc 4cf257b997 Display only timer name if defined (#5684) 2018-02-11 23:23:19 +01:00
Bertrand Songis 51db756385 Update CREDITS.txt 2018-02-11 09:07:10 +01:00
3djc fc4d70a5e9 Fix tts generation on the new server 2018-02-10 13:22:41 +01:00
Bertrand Songis a73d8bc8f4 Update CREDITS.txt 2018-02-10 08:45:49 +01:00
3djc dc0b5838b1 Trigger SD card version change for S8R scripts 2018-02-09 08:26:06 +01:00
3djc afb0ca384a Compensate for S8R firmware bug
This fixes #5677
2018-02-08 19:14:09 +01:00
Bertrand Songis 817f81ebb2 Update CREDITS.txt 2018-02-08 18:51:45 +01:00
3djc 119b367205 128x64 GVAR support update (#5675)
* POC for usability feedbacks

* Working version for tests

* Remove tests leftover

* Make Travis happy ?

* Gvar popup handling
2018-02-07 20:44:04 +01:00
Bertrand Songis 975ecd0b9d Update CREDITS.txt 2018-02-07 13:00:14 +01:00
3djc 13c0b4b5f6 Update fr.h.txt 2018-02-05 20:48:37 +01:00
3djc 25d1cf4455 French translation. This fixes #5667 2018-02-05 07:40:33 +01:00
Bertrand Songis cd456a9a60 Update CREDITS.txt 2018-02-04 09:12:58 +01:00
Bertrand Songis cae1dd964d Update CREDITS.txt 2018-01-31 22:43:14 +01:00
Sebastien Charpentier 16a3bf10c8 Updated French translations. (#5659)
* Initial version

* Updated French translations.
2018-01-29 10:35:25 +01:00
Bertrand Songis 5e0f93210d Update CREDITS.txt 2018-01-28 07:49:39 +01:00
Bertrand Songis 2396a2b2e5 Update CREDITS.txt 2018-01-27 21:06:24 +01:00
Bertrand Songis 4dfbb9e597 Update CREDITS.txt 2018-01-26 19:20:22 +01:00
Bertrand Songis 6af5f94f90 Flash savings on 9X 2018-01-26 19:06:59 +01:00
Arne Schwabe 4925e756a6 Save memory (move usb mass storage buffer to reusableBuffer) (#5579)
* Save 128 byte by moving variable to stack

* Make usb mass storage buffer smaller on F2 processors and put into reuseablebuffer

- Lower USB mass storage buffer to 512 bytes per default on F2
  targets, makes usb speed slightly slower ~600 kB/s instead ~700 KB/s
  in my tests, saving 3584 bytes
- Save another ~300 bytes by putting that buffer into reusableBuffer

* Don't put id into reusuableBuffer

All uses of id can be on the stack as well. Makes no difference for ram usage but makes it safer to reuse reusableBuffer

* Only link cdc serial when needed

We always linked usb cdc even in non debug builds. CDC uses about ~600 byte of RAM for its buffers and structures.
2018-01-26 19:00:47 +01:00
3djc 95df593c2f Align python crossfire parser to c equivalent (#5595)
Align python Crossfire parser to C equivalent
2018-01-26 18:57:34 +01:00
3djc 8be6818a6d Fix custom scripts outputs handling (#5601) 2018-01-26 18:56:02 +01:00
3djc fcc3cd369e First draft of glider wiz (#5603) 2018-01-26 18:54:53 +01:00
3djc 87eec92c5d Expose more internal GPS data to lua (#5628) 2018-01-26 18:54:22 +01:00
Neil Horne d745e14cb5 Model print telemetry (#5645)
Model Print Telemetry
2018-01-26 18:53:15 +01:00
3djc 3355d41642 X7 : add missing trainer mode (#5652) 2018-01-26 18:51:25 +01:00
Bertrand Songis 0832a5c254 X-Lite PWM sticks (#5632)
X-Lite PWM sticks
2018-01-26 18:50:39 +01:00
Kilrah c7df47703e Translation cosmetics 2018-01-26 11:36:13 +01:00
Bertrand Songis a1ee9f865f Update CREDITS.txt 2018-01-25 11:44:03 +01:00
Bertrand Songis 1033e9fe96 Update CREDITS.txt 2018-01-20 21:58:31 +01:00
3djc 323b30a14b Fix companion x7 radio data and model read (#5638)
* Fix

* Typo
2018-01-19 13:46:44 +01:00
Bertrand Songis 2a2c0420a7 Update CREDITS.txt 2018-01-19 07:39:42 +01:00
Bertrand Songis f78704af93 Update CREDITS.txt 2018-01-18 19:06:54 +01:00
Bertrand Songis 34e61c45c9 Update CREDITS.txt 2018-01-17 09:08:58 +01:00
Bertrand Songis a1951f9756 Update CREDITS.txt 2018-01-16 08:05:21 +01:00
Bertrand Songis c96dc403b9 Update CREDITS.txt 2018-01-15 20:32:29 +01:00
Bertrand Songis 48f05f97b7 Update CREDITS.txt 2018-01-13 09:02:31 +01:00
Bertrand Songis 3208946017 Update CREDITS.txt 2018-01-12 14:33:03 +01:00
Bertrand Songis 7052f9504a Update CREDITS.txt 2018-01-10 08:28:06 +01:00
3djc 45d1755e19 X12S : give internal GPS access to LUA (#5610)
* Initial test

* Tested version

* Cosmetics
2018-01-08 15:12:28 +01:00
Kilrah bf29ebc354 Currently no working Bluetooth implementation on sky9x family 2018-01-06 13:21:09 +01:00
3djc e50fc2022f Fix #5558 2018-01-05 19:45:51 +01:00
Max Paperno a63e0eed4c [Companion] Fix logical switch misnumbering since a951292 (closes #5597). 2018-01-05 07:27:30 -05:00
Bertrand Songis 1218c9fa7d Update CREDITS.txt 2018-01-04 18:32:37 +01:00
3djc e50d10bfe6 Review crossfire python parser (reverted from commit 18a9758511) 2018-01-04 14:24:00 +01:00
3djc 18a9758511 Review crossfire python parser 2018-01-04 14:20:54 +01:00
3djc fcd8f05c3c X9 : Do not display timer name on telemetry page top bar (#5588)
* Do not display timer name on telemetry page top bar

* Size does matter, after all
2018-01-03 16:18:25 +01:00
Sebastien Charpentier 56afc57b7b Updated French translation (#5589)
* Initial version.

* Updated French Translation.
2018-01-03 16:17:23 +01:00
Bertrand Songis b3a0befe33 Update CREDITS.txt 2018-01-03 00:01:24 +01:00
3djc 669dfe73a4 x10 antenna is either int or ext (#5585)
* Differentiate x10 and x12

* Cosmetics
2018-01-02 14:38:15 +01:00
Bertrand Songis c4001c8507 Bsongis/frsky xlite (#5574)
FrSky X-Lite support added
2018-01-02 14:36:48 +01:00
Bertrand Songis 269831e0c4 Fixes #5502 (#5575)
* Fixes #5502

* RAS renamed to SWR
2018-01-02 10:41:15 +01:00
Bertrand Songis b22fa48e90 Update CREDITS.txt 2018-01-02 10:39:13 +01:00
Max Paperno 397388d230 Add .user files to gitignore [ci skip] 2018-01-02 02:26:43 -05:00
Max Paperno f5de319f40 [Companion] Remember last used log folder in Telemetry Simulator (fixes #5583). 2018-01-01 22:50:52 -05:00
Bertrand Songis 1c2fe7b9a6 Update CREDITS.txt 2017-12-30 21:23:58 +01:00
Sebastien Charpentier c545a2f0ed Updated French Translation. (#5580)
* Initial version

* Updated French translation.
2017-12-30 15:44:38 +01:00
Arne Schwabe 7f1dea6129 Silence CLangs warnings so -DWARNING_AS_ERROR does not break the build under OS X 2017-12-30 11:16:35 +01:00
Neil Horne 96d9ae4776 Model print enhancements - General settings (#5568)
* General model settings enhancements
* General model settings add custom failsafe settings
2017-12-29 06:19:34 -05:00
3djc 8ee9199abc R9M : activate automatically MODULE telem when possible (#5553)
* Fix #5543

* Auto activate R9M telem

* Adjust radio ui

* Thx @schwabe

* Stop being stupid ?

* PR rework

* [Companion] Removed "Module Telemetry" checkbox.
2017-12-29 09:47:45 +01:00
Bertrand Songis 3cba3a76a4 Sonar completely removed from Travis builds 2017-12-29 01:14:48 +01:00
Alexander Novikov 84d2a22b18 [Companion] Missing "Russian" voice in Radio Settings (#5570) 2017-12-29 01:11:46 +01:00
Sebastien Charpentier 8f87a07f62 Check Fr translations (#5567)
* Initial version.

* Check and updated French Translation.
2017-12-28 15:17:49 +01:00
Bertrand Songis fa9e829f5d Update CREDITS.txt 2017-12-27 20:31:24 +01:00
Bertrand Songis 920faa97d2 Update CREDITS.txt 2017-12-27 09:42:40 +01:00
Max Paperno f018425e12 [Companion] Qualify all translation strings (#5557)
* [Companion] Qualify all remaining QObject translations with proper class/object names; Centralize some common strings into constants.h.

* [Companion] Replace all instances of some common strings with macros from constants.h.

* [Companion] Fix translation warnings from lupdate.
2017-12-25 13:36:34 +01:00
3djc ad0f727880 128x64 Display RAS when needed (#5563)
* Display RAS when needed on 128x64

* AVR compile fixes
2017-12-25 13:34:54 +01:00
3djc 9696284e1d Make server build use 2 threads 2017-12-24 13:36:06 +01:00
Bertrand Songis 10d733d312 Update CREDITS.txt 2017-12-23 22:40:29 +01:00
3djc e9c2768cc0 Fix compilation in several languages 2017-12-23 10:36:46 +01:00
Bertrand Songis 4f7aba9c05 Revert "Bsongis/sonar (#5555)"
This reverts commit 7806c20
2017-12-22 20:18:21 +01:00
Bertrand Songis 892cece2aa Update CREDITS.txt 2017-12-22 08:05:01 +01:00
Bertrand Songis 7cb3f43862 Update CREDITS.txt 2017-12-21 22:13:54 +01:00
3djc 04ab98a634 Fix for stretch cmake in docker environment 2017-12-21 20:47:24 +01:00
Bertrand Songis 18ff09d52f Update CREDITS.txt 2017-12-21 18:32:11 +01:00
Max Paperno a951292f27 [Companion] Radio data translation/strings (#5554)
* [Companion] Add Qt tr() functions to all radio data classes instead of using generic QObject type.  (no functional changes)

* Small fix for gcc.

* Move more element name string generation to individual classes; settle on nameToString as function name.

* Also put firmware build options translations into Firmware scope.
2017-12-21 18:26:11 +01:00
Bertrand Songis 7806c2096d Bsongis/sonar (#5555)
Some sonar issues fixed
2017-12-21 18:25:27 +01:00
3djc b7855cf14d Fix firmware compile 2017-12-21 13:10:50 +01:00
Bertrand Songis dfb4153049 Update CREDITS.txt 2017-12-21 07:27:00 +01:00
Alexander Novikov 14d5416616 Added: scripts for nightly/rc/release builds (SD card content, Russian voice), Audio normalization, PSV files for TTSAutomate (#5469)
* Added: scripts for nightly build (SD card content, Russian voice), system sounds: done, other sounds: partially
Fixed: gTTS issue with unicode (Cyrillic) chars in command params (gTTS module instead of system command)

* Fixed: gTTS issue with Unicode (Cyrillic) chars in command params (gTTS module instead of system command), for release candidates and release
Changed: SOX params to normalize the audio
Added: "psv" parameter to export list of audio files into PSV format (see TTSAutomate https://github.com/CaffeineAU/TTSAutomate , to generate voice files using TTS engines from Microsoft, Amazon, Google etc)
Added: some extra voice files for RU
2017-12-20 18:30:44 +01:00
Max Paperno 63f6e0c43d Fix Companion build with Qt 5.2. 2017-12-20 11:22:36 -05:00
3djc 8069426b5c Prep 2.2.2N 2017-12-20 13:44:50 +01:00
Max Paperno 59a835b1b3 [Companion] Radio data refactoring (#5551)
* [Companion] Refactor radio data classes to own files, out of eeprominterface.cpp.  No functional changes.

* Move files related to refactoring. No functional or code changes.

* Fix clang warning and an include path.

* Fix indents on curvereference.cpp. [ci skip]
2017-12-20 13:31:43 +01:00
Bertrand Songis 727da06266 Files refactoring + costmetics (#5552) 2017-12-20 11:03:33 +01:00
Max Paperno 38762fb618 Move __attribute__ ((section(s), used)) macro, and cosmetics in definitions.h. (#5549) 2017-12-20 10:19:59 +01:00
3djc aff40dac8d Move a decade forward ! 2017-12-20 09:56:07 +01:00
Max Paperno e097d88ab2 Fix build with CMake < 3.1. 2017-12-20 03:04:50 -05:00
Max Paperno a16e64420e [Companion] Recent files menu: show full path of each file in status bar and tooltips. 2017-12-19 21:21:20 -05:00
Max Paperno 76ee7cdd7f Fix libsimulator builds, especially MSVC. 2017-12-19 17:58:15 -05:00
3djc 0e0ae3c4d1 1 too short (#5542)
* 1 too short

* Let the compiler do it's magic
2017-12-19 18:30:23 +01:00
Max Paperno 76ce186bd4 [Companion] Adjust source value ranges and editors in LS/CF/Telemetry (#5437)
* [Companion] RawSourceRange: Fix for timers and RTC; Remove unused "single precision" flag and logic; Add logic for "short" timer handling.

* [Companion] Add TimerEdit class for editing negative times; Implement TimerEdit in LS, CF, and Telemetry (bars) editors;

* [Companion] Refactor LogicalSwitchesPanel for fewer & more efficient updates; Fix newly-added LS not being available in source lists; Fix bug with timer/rtc comparison values getting reset to value of spin box instead of time editor.

* Add forgotten #include.

* [Companion] LogicalSwitchesPanel: Update raw sources list upon screen refresh (fixes #5374); Improve data entry in spin boxes (fixes #5375).

* Make gcc happy.

* [Companion] Set proper RawSourceRange for GVars, trims, mixer scripts, and sticks/switches/cyclic/MAX.

* [Companion] Fix backwards precision/range logic on telemetry sensors offset spinbox; Fix other minor range issues with ratio & offset.

* [Companion] Remove short limit on min/max timer values for LS & telem. bars.

* Switch to TimerEdit in maxLibQt.

* Fix gcc build.

* Remove unused files.

* Caps fix.
2017-12-19 12:17:49 +01:00
Max Paperno b69f36afe4 [Radio] Adjust value limits for mix sources and update UI for LSs, CFs & telem. (#5445)
* [firmware][ARM] Adjust some value limits for mix sources and update editing UI for LSs, CFs, & telem. bars:
    * Increase timer limits to +/-8:59:59 when used with LSs, CFs, & bars;
    * Increase Lua script output limits to +/-30K;
    * Trim limits based on extended limit model setting;
    * Limit TX voltage to 25.5;
    * Limit TX time comparison value to 29:59m;
    * Use proper GVar limits (user-configured), display precision, & unit in LSs & telem. bars;
    * Display timer values properly with hours (instead of mmm:ss).

* [firmware] getTimerString() would fail with times >= 100min if hours weren't shown.

* Fix builds w/out GVars.
2017-12-19 12:17:12 +01:00
Raphael Coeffic 716a91fc0c allow splash image to be loaded from SD on Horus (#5463)
* allow splash image to be loaded from SD on Horus

* added a new menu entry to assign splash screen
2017-12-19 12:15:03 +01:00
Raphael Coeffic 0d7832b208 Horus bootloader (#5455)
Horus bootloader
2017-12-19 12:13:59 +01:00
Max Paperno 908adb4d2b [sim] Cosmetics for switch position macros (also removes PCBFLAMENCO from simuSetSwitch). (#5474) 2017-12-19 12:13:18 +01:00
Bertrand Songis 7697bcb087 Update CREDITS.txt 2017-12-19 09:40:59 +01:00
Arne Schwabe 975759284d Implement reading firmware on Horus via USB (#5442)
* Add firmware lun target for non EEPROM platforms

* Fix Fat fat tables and make FAT 1024 byte big

* Niceify some constants

* Cleanup (saves 1024 byte of flash) and fix reporting wrong Size of drive

* Silence compiler warning, set right size for flash on X12/X10

* Add firmware.txt/bootload.txt to virtual drive that displays version information

* Report also version of other component (bootloader/firmware)

* Show version also in bootloader and fix F4 platforms

* Save space on X7

* Fix X7 logic

* Compile fix for AVR

* avr-gcc does not like no newline after ifdef

* Really fix avr
2017-12-18 23:19:19 +01:00
Raphael Coeffic d13e770ac4 improved Horus rotary encoder driver and generic behavior (#5510)
Improved Horus rotary encoder driver
2017-12-18 23:12:29 +01:00
3djc 04547a9206 Merge companion and firmware notes, and get them from the server (#5530) 2017-12-18 23:02:40 +01:00
Arne Schwabe 7dd32c8878 Implement s.port polling for multi (#5521)
Sport polling is implemented quite low level for regular s.port.
Go another approach for multi and add another multi type for s.port polling
2017-12-18 23:00:03 +01:00
Arne Schwabe d0ec3e0266 Fix problem with multi frsky fallback (#5496)
* Fix problem with frsky fallback

* Try to fix code style
2017-12-18 22:58:24 +01:00
Max Paperno 0dbad182e8 [Companion] Radio conversion improvements (#5534)
* Move MultiposPots & MultiposPotsPositions capability lookups and getAnalogInputName() to Boards class.

* Add RawSource::isAvailable() and RawSwitch::isAvailable(); Add board type param to various RawSource lookup functions.

* Add CustomFunctionData::toString(), FlightModeData::toString(), FactoryInstalledPots board capability, MAX_SWITCH_TYPE, & break out GeneralSettings source/switch defaults to own function.

* Add RadioDataConversionState class for tracking conversion actions.

* Implement RadioDataConversionState handler, add conversion process report, and improve/fix conversion issues:
    * Make sure all switches/pots/knobs have default configs for destination board type;
    * Try to move more custom control names, intelligently;
    * Convert model timers and throttle source;
    * Adjust for Horus 6P switch in place of Taranis S2 knob;
    * Adjust for extra sliders on X12 and X9E to move LS and RS to proper slots as needed;
    * Make sure ALL controls are validated, eg. to always account for extra trims/analogs/switches/etc which don't exist on destination;
    * Properly indicate invalid RawSource::toString() items with "???".

* Allow user to cancel out of file conversions & provide ample warnings if switching radio type/profile with unsaved file(s) still open;
Also: Fix bug with some orphaned MdiChild windows never being deleted; Create static bool Storage::isBoardCompatible(b1, b2).

* Add maxLibQt "stub" (will not compile).

* Add ExportableTableView for better presentation of conversion results table.

* Move getFourCC() and isBoardCompatible() to Boards class.
2017-12-18 22:56:39 +01:00
Raphael Coeffic e63a877ed6 added getRtcTime() LUA function (#5524)
This allows for retrieving the UNIX timestamp kept internally.
2017-12-18 21:04:02 +01:00
3djc 4df64695c7 BT Pin code (#5536)
* x7

* add x12 pin code
make strings translatable

* Cosmetics
2017-12-18 21:03:18 +01:00
3djc 394bc1689f Massive cleaning (#5538) 2017-12-18 20:54:22 +01:00
Bertrand Songis 6839939140 Update CREDITS.txt 2017-12-18 19:41:43 +01:00
Bertrand Songis 00c7b23d15 Update CREDITS.txt 2017-12-18 18:32:20 +01:00
lfischer85 bc6bfccade fix for X12s crossfire issues #5162 (#5533)
* fix X12s crossfire issues

* Update radio_hardware.cpp

* Update crossfire.h

* Update radio_hardware.cpp

* Removed now unnecessary macros.
2017-12-18 15:15:28 +01:00
Bertrand Songis ed2becce88 Update CREDITS.txt 2017-12-18 07:29:39 +01:00
3djc b39acdf18a Merge pull request #5526 from opentx/3djc/2.2.2-nightlies
Post 2.2.1
2017-12-18 07:18:28 +01:00
Bertrand Songis 149e039cd0 Update CREDITS.txt 2017-12-17 23:38:03 +01:00
Bertrand Songis f99fadaa20 Update CREDITS.txt 2017-12-17 22:48:43 +01:00
Bertrand Songis b5fd533362 Update CREDITS.txt 2017-12-17 22:41:29 +01:00
Bertrand Songis 8e88cfbf9a Update CREDITS.txt 2017-12-17 21:50:47 +01:00
Bertrand Songis 3969413779 Update CREDITS.txt 2017-12-17 19:19:25 +01:00
Damjan Adamic eedbf2fbb7 Launchpad files for 2.2.1 release:
* dropped support for trusty (Ubuntu 14.04 LTS) since it's QT version 5.2 is too old, we need at least 5.3
 * added bionic (Ubuntu 18.04 LTS)
2017-12-17 18:40:25 +01:00
Bertrand Songis fbb358bf71 Update CREDITS.txt 2017-12-17 15:39:07 +01:00
Bertrand Songis b3602cad87 Update CREDITS.txt 2017-12-17 15:01:31 +01:00
Bertrand Songis b9387ceeda Update CREDITS.txt 2017-12-17 14:08:50 +01:00
3djc 3aa7452e48 Post 2.2.1 2017-12-17 13:32:13 +01:00
992 changed files with 182030 additions and 91079 deletions
+69
View File
@@ -0,0 +1,69 @@
# Use the latest 2.1 version of CircleCI pipeline process engine.
# See: https://circleci.com/docs/2.0/configuration-reference
version: 2.1
# Define a job to be invoked later in a workflow.
# See: https://circleci.com/docs/2.0/configuration-reference/#jobs
jobs:
build-elrsv2:
machine: true
steps:
- checkout
- run: docker run -it -e "BOARD_NAME=I6X" -e "CMAKE_FLAGS=PCB=I6X HELI=NO GVARS=NO LUA_COMPILER=NO MULTIMODULE=NO DEBUG=NO PCBI6_ELRSV2=YES" -v $PWD:/opentx vitass/opentx-fw-build
- store_artifacts:
path: opentx-i6x-2.3.0.bin
destination: ./artifacts/opentx-i6x-elrsv2-<< pipeline.git.tag >>.bin
build-gvars:
machine: true
steps:
- checkout
- run: docker run -it -e "BOARD_NAME=I6X" -e "CMAKE_FLAGS=PCB=I6X HELI=NO GVARS=YES LUA_COMPILER=NO MULTIMODULE=NO DEBUG=NO" -v $PWD:/opentx vitass/opentx-fw-build
- store_artifacts:
path: opentx-i6x-2.3.0.bin
destination: ./artifacts/opentx-i6x-gvars-<< pipeline.git.tag >>.bin
build-heli:
machine: true
steps:
- checkout
- run: docker run -it -e "BOARD_NAME=I6X" -e "CMAKE_FLAGS=PCB=I6X HELI=YES GVARS=YES LUA_COMPILER=NO MULTIMODULE=NO DEBUG=NO" -v $PWD:/opentx vitass/opentx-fw-build
- store_artifacts:
path: opentx-i6x-2.3.0.bin
destination: ./artifacts/opentx-i6x-heli-<< pipeline.git.tag >>.bin
publish-github-release:
docker:
- image: cibuilds/github:0.13
steps:
- attach_workspace:
at: ./artifacts
- run:
name: "Publish Release on GitHub"
command: |
ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} -delete latest ./artifacts/
# Invoke jobs via workflows
# See: https://circleci.com/docs/2.0/configuration-reference/#workflows
workflows:
openi6x-workflow:
jobs:
- build-elrsv2
# filters:
# branches:
# ignore: /.*/
# tags:
# only: /.*-release$/
- build-gvars
# filters:
# branches:
# ignore: /.*/
# tags:
# only: /.*-release$/
- build-heli
# filters:
# branches:
# ignore: /.*/
# tags:
# only: /.*-release$/
- publish-github-release:
requires:
- build-elrsv2
- build-gvars
- build-heli
+31
View File
@@ -0,0 +1,31 @@
---
name: Bug report
about: Create a report to help the OpenTX team to improve OpenTX
---
*Before submitting, search the open issue if there is already a report of the bug*
Also often minor bugs are already fixed in nightly builds, often it is
a good idea to test (in a controlled environment like a bench setup)
with a nightly firmware to see if the bug still exists.
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**General information**
- OpenTX version (e.g. 2.1.23 or N123)
- Hardware (e.g. Frsky X9D+ or 9X Pro)
- OpenTX Companion (e.g. 2.1.23 on Ubuntu 16.04)
+16
View File
@@ -0,0 +1,16 @@
---
name: Help
about: Problems or question of using OpenTX
---
The issue tracker here is for devlopment of OpenTX. This is not a
support site, only a bug tracking system. Please use support groups
like [rcgroups](https://rcgroups.com/) or
[openrcforum](https://www.openrcforums.com/forum/). See also our
[manual](https://opentx.gitbooks.io/manual-for-opentx-2-2/).
For quick questions you can also join our general chat.
Issues that fall into the category of asking for help, will be
generally closed as invalid without an answer.
+18
View File
@@ -0,0 +1,18 @@
---
name: Feature request
about: Suggest an idea for this project to make OpenTX even better
---
*Before suggesting a new feature here, please search the open issue if there is already a request for the feature*
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
+15 -1
View File
@@ -2,7 +2,21 @@
/.*project
/.settings
/.autotools
/doc/
/*.user
/*.user.*
build*/
cmake-build-*/
/debian/
/CMakeFiles/*
radio/src/CmakeFiles/*
/.vscode/
*.cmake
*.make
*.marks
/nbproject/
*.bin
/radio/src/CMakeFiles/firmware.dir/link.txt
.push.settings.jsonc
build.sh
firm.sh
flash.sh
+11 -44
View File
@@ -1,23 +1,16 @@
sudo: required
dist: trusty
language: python
language: cpp
compiler: gcc
virtualenv:
system_site_packages: true
python:
- 3.4
env:
global:
- QT_BASE=53
# - QT_BASE=53
# - QT_BASE=54
# - QT_BASE=55
# - QT_BASE=56
# - QT_BASE=57
#- GCC_ARM=/opt/gcc-arm-none-eabi/bin
- AVR_FLAVORS="AVR9X 9X GRUVIN9X MEGA2560"
- QT_BASE=57
# - GCC_ARM=/opt/gcc-arm-none-eabi/bin
- PYTHONPATH=${PYTHONPATH}:/usr/lib/python3/dist-packages
matrix:
#
@@ -26,15 +19,12 @@ env:
#
# - FLAVOR=ALL
- FLAVOR=DEFAULT
- FLAVOR=AVR9X
# - FLAVOR=9X
# - FLAVOR=GRUVIN9X
# - FLAVOR=MEGA2560
- FLAVOR=ARM9X
# - FLAVOR=AR9X
# - FLAVOR=SKY9X
# - FLAVOR=9XRPRO
- FLAVOR=X7
- FLAVOR=XLITE
- FLAVOR=X9
# - FLAVOR=X9D
# - FLAVOR=X9D+
@@ -54,40 +44,17 @@ before_install:
- if [ "$QT_BASE" = "56" ]; then sudo add-apt-repository ppa:beineri/opt-qt562-trusty -y; fi
- if [ "$QT_BASE" = "57" ]; then sudo add-apt-repository ppa:beineri/opt-qt571-trusty -y; fi
- sudo apt-get update -qq
- pyenv uninstall -f 2.7.6 && pyenv install 3.5.4 && pyenv global 3.5.4
- pip install pillow
install:
- sudo apt-get --yes --force-yes install python3-pyqt5 curl libmpfr4 libmpc3 libfox-1.6-dev libgtest-dev
- |
if [[ " ${AVR_FLAVORS} " =~ " ${FLAVOR} " || ${FLAVOR} == "ALL" ]]; then
wget --quiet https://launchpad.net/ubuntu/+source/gcc-avr/1:4.9.2+Atmel3.5.0-1/+build/8403710/+files/gcc-avr_4.9.2+Atmel3.5.0-1_amd64.deb
wget --quiet https://launchpad.net/ubuntu/+source/avr-libc/1:1.8.0+Atmel3.5.0-1/+build/8435473/+files/avr-libc_1.8.0+Atmel3.5.0-1_all.deb
wget --quiet https://launchpad.net/ubuntu/+source/binutils-avr/2.25+Atmel3.5.0-2/+build/8435474/+files/binutils-avr_2.25+Atmel3.5.0-2_amd64.deb
sudo dpkg --install gcc-avr_4.9.2+Atmel3.5.0-1_amd64.deb avr-libc_1.8.0+Atmel3.5.0-1_all.deb binutils-avr_2.25+Atmel3.5.0-2_amd64.deb
fi
if [[ ! " ${AVR_FLAVORS} " =~ " ${FLAVOR} " || ${FLAVOR} == "ALL" ]]; then
sudo apt-get --yes --force-yes install gcc-arm-none-eabi
# Trying to build with gcc-arm 4.7 isn't working because it can't find the compiler, despite adding to PATH (in commit-tests.sh) by defining GCC_ARM above
- sudo apt-get --yes --force-yes install curl libmpfr4 libmpc3 libfox-1.6-dev libgtest-dev
- sudo apt-get --yes --force-yes install gcc-arm-none-eabi
# Trying to build with gcc-arm 4.7 isn't working because it can't find the compiler, despite adding to PATH (in commit-tests.sh) by defining GCC_ARM above
# - wget --quiet https://launchpad.net/gcc-arm-embedded/4.7/4.7-2013-q3-update/+download/gcc-arm-none-eabi-4_7-2013q3-20130916-linux.tar.bz2
# - tar xjf gcc-arm-none-eabi-4_7-2013q3-20130916-linux.tar.bz2
# - mv gcc-arm-none-eabi-4_7-2013q3 /opt/gcc-arm-none-eabi
fi
- sudo apt-get install --yes --force-yes -qq qt${QT_BASE}base qt${QT_BASE}multimedia qt${QT_BASE}svg qt${QT_BASE}tools; source /opt/qt${QT_BASE}/bin/qt${QT_BASE}-env.sh
addons:
sonarcloud:
organization: "opentx-github"
token:
secure: "BuQrGRijNpL2V/IQNcOxvjChj8PScfCdiv403EE73Nqb4+sB8YL92Fnzrnw9bC8wF7BVSDJVpYF0gbdaTzuCmaeZfM8NJK0TOJAbH6+B8bhIrU/V1SBuVjHQnndV/wysieruKnK/KxYJZqItgSlnPo+PmiFxtXJNlas0Kstb2O4="
# github_token:
# secure: "Qkmp4VrQJtKgZ/pz65SNnCDiF4slgFfQS/3whyLXLcDbFb1Hv1oj7Hqz9EVDUSO2eEhgQGaOKkRc0CfAAOBwW6OvhE0xh7P1CJEjzOp6+3gI/LyZUNsqa+awVRZTsfm1YZaOPaPWJ7cI0uz3/OoSUeIecs4PDWPrQMGRlsrq7Q8="
branches:
- "2.2"
script:
- build-wrapper-linux-x86-64 --out-dir bw_output ./tools/commit-tests.sh
- sonar-scanner
cache:
directories:
- '$HOME/.sonar/cache'
- ./tools/commit-tests.sh
+15 -4
View File
@@ -1,12 +1,12 @@
project(OpenTX)
set(VERSION_MAJOR "2")
set(VERSION_MINOR "2")
set(VERSION_REVISION "1")
set(VERSION_MINOR "3")
set(VERSION_REVISION "0")
set(VERSION_SUFFIX $ENV{OPENTX_VERSION_SUFFIX})
set(VERSION_FAMILY ${VERSION_MAJOR}.${VERSION_MINOR})
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}${VERSION_SUFFIX})
set(SDCARD_REVISION "0013")
set(SDCARD_REVISION "0018")
set(SDCARD_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}V${SDCARD_REVISION})
cmake_minimum_required(VERSION 2.8)
@@ -72,6 +72,13 @@ else()
set(LUA NO)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") # regular Clang or AppleClang
set(CLANG TRUE)
endif()
option(DISABLE_COMPANION "Disable building companion and simulators" OFF)
if(NOT DISABLE_COMPANION) # FIXME cosmetics/style
find_package(Qt5Core)
find_package(Qt5Widgets)
find_package(Qt5Xml)
@@ -111,6 +118,9 @@ if(Qt5Core_FOUND)
list(APPEND APP_COMMON_DEFINES -DQXT_STATIC)
list(APPEND APP_COMMON_DEFINES -DQT_USE_QSTRINGBUILDER) # more efficient QString construction using % operator
if(MSVC)
list(APPEND APP_COMMON_DEFINES -D__STDC_LIMIT_MACROS)
endif()
if(APP_CUSTOM_DBG_HANDLER)
# provide full qDebug log context to our custom handler. This may also affect libsimulator, which is why it is here
list(APPEND APP_COMMON_DEFINES -DQT_MESSAGELOGCONTEXT)
@@ -150,6 +160,7 @@ if(Qt5Core_FOUND OR FOX_FOUND)
message(STATUS "SDL not found! Simulator audio, and joystick inputs, will not work.")
endif()
endif()
endif(NOT DISABLE_COMPANION)
# Check for a file that is typically left from a OpenTX 2.1 build and abort if found
if (EXISTS ${RADIO_SRC_DIRECTORY}/stamp.h OR EXISTS ${RADIO_SRC_DIRECTORY}/translations/en.h)
@@ -180,6 +191,6 @@ endif()
add_subdirectory(${RADIO_SRC_DIRECTORY})
if(Qt5Core_FOUND)
if(Qt5Core_FOUND AND NOT DISABLE_COMPANION)
add_subdirectory(${COMPANION_SRC_DIRECTORY})
endif()
+197 -7
View File
@@ -26,20 +26,22 @@ Pat Mackenzie
Michael Byrne
[Companies and projects who have donated to OpenTX]
<a href="http://frsky-rc.com">FrSky (monthly)</a>
<a href="http://alofthobbies.com">Aloft Hobbies</a>
<a href="http://jonathan.it">Jonathan Modellismo</a>
<a href="https://www.frsky-rc.com">FrSky (monthly)</a>
<a href="https://alofthobbies.com">Aloft Hobbies</a>
<a href="https://jonathan.it">Jonathan Modellismo</a>
<a href="http://wstech.de">WsTech</a>
<a href="http://aviomotive.com">Aviomotive</a>
<a href="http://boltrc.com">BoltRC</a>
<a href="http://aerialtechhobbies.com">Aerial Tech Hobbies</a>
<a href="http://litepilots.com">LitePilots</a>
<a href="http://openpilot.com">David Ankers (OpenPilot)</a>
<a href="http://3drobotics.com">3D Robotics</a>
<a href="http://rcstudio.cz">RC Studio (monthly)</a>
<a href="https://3dr.com">3D Robotics</a>
<a href="https://rcstudio.cz">RC Studio (monthly)</a>
<a href="http://www.craftandtheoryllc.com">Craft & Theory (monthly)</a>
<a href="http://alofthobbies.com/taranis-q-x7--opentx-user-manual.html">OpenTX Manuals by Lothar Thole</a>
<a href="http://www.team-blacksheep.com">Team BlackSheep</a>
<a href="https://alofthobbies.com/taranis-q-x7--opentx-user-manual.html">OpenTX Manuals by Lothar Thole</a>
<a href="https://www.team-blacksheep.com">Team BlackSheep</a>
<a href="https://www.3dxr.co.uk">Team BlackSheep</a>
www.3dxr.co.uk
[People who have donated to OpenTX]
Mario Sette
@@ -1301,3 +1303,191 @@ Rachel Berkhahn
Luca Massimiliano Comolli
Mario Wesierski
Evening Shade Pottery
Jean Desmet
Alexis Pons
Roger Bergevin
Eddie Ehlin
Bernard Avisse
Brent Warman
Tim Johnson
Reinhard Herden
Mark Hanson
Sander Helling
Anthony Hrabusicky
David Frazier
Alexander Orlov
Wes Warner
Samuel Grob
Wolfgang Kuhl
Stuart Olson
Michael Shellim
Jay Watkins
Juan Rodriguez
John Bitzer
Bryan Anderson
Claudio Piccinini
Patrick Breidenbach
Harald Puff
Mike Frizell
James A Davey
Ronald Fahlbusch
Piet Teekens
Jean Jacques Bultez
Paul Dittman
Philippe Faure
Jean-Jacques Pointel
Didier Christien
Huguette Viale
Marc Rivière
Cyril Maquaire
Nick Webb
Kristjan Crnoja
Gaines Smith
Tomasz Łapucha
Karl-Heinz Behn
Geir Atle Storhaug
Marco Lange
2 Brains Design
Philip Michels
Peter Helbling
Guy Lamaison
Michael Oeschger
Alistair Sutherland
Chris Hawley
Jeffrey Albers
Thomas Hollatz
Patrice Lafeuille
Gary Jones
Benoit Gruson
Petr Kysela
Sebastien Jehan
Jean Mathieu
Barry Andersen
James Vincent
Baker Hart
Thomas Voth
Michael Kiefer
Ronald Dalton
Thierry Laligand
Joel Lefebvre
Murray Rogers
Renato Elias
Richard Husta
Ian Ferreira
Zhang Tianyu
Josef de Beer
Ewald Moehring
Kevin Karamitros
Beat Zurflueh
Frank Morris
Edwin Butin Bik
Geir Atle Storhaug
Ted Hoenderdos
Sebastian Stefanitsch
Leif Pernstig
Michael Garofalo
Chris Sunman
Adam Kalus
Christoffer H Henni
Michael Stauning
Stuart Smith
Giuseppe Esposito
Stefano Boggia
Manuel Peon
Mark Bennett
Nicholas Platts
Carol B Meravi
Norman Hunt
Raymond Henderson
Christopher Marshall
Christopher Prinos
AntiSocial Engineering
Pierre Duvezin-Caubet
Hermann Haberer
Guy Poignonec
Robin Lauff
Renato Müller
Hannes Mössler
Cédric Lagoutte
Alexander Mathis
Barry Andersen
Philippe Glur
Felix Tang
Heiko Polig
Pierre Marty
Dirk Weiler
Eddie Ehlin
John Clarke
Laurent Thibaudet
James A Davey
Stuart Olson
claudio Piccinini
Kenneth Kriegel
Evening Shade Pottery
Raymond Henderson
Clifton Hipsher
François Carton
Olivier Portron
Didier Hochedez
Julien Gérard
Christian Syrbe
Juan Luis Guerrero Portero
Jonathan Badley
Ms Place
Heart of NM LLC
Daniele Gnesutta
Erik Peterson
SkyRaccoon
James Lummel
Jürgen Husske
Marko Domagoj Zic
Fabrice Debonnet
Ms Place
Jörg Hammer
Rapid Informatics LLC
Renaud Perriguey
Edmond Dufresne
Jaroslav Gazik
Philippe Desrichard
Vincent Heron
Marcel Schäfer
Stefano Pascucci
Frédéric Bourgois
Stefan Hufnagl
Jean Philippe Bonacci
Jack Mitchell
Santiago Iglesias Garcia
Steve Kurywchak
Tore Skjefstad
Sergio Digiandco di Molino
Xavier Delepine
Miles Shearman
Bernard Teyssier
Entel Consulting BVBA
Stuart Olson
Maximilian Wechselberger
Kenneth Crump
Ken Elder
Darko Perković
Martin Krueger
Jack Lopes
Huguette Viale
Didier Christien
Pascal Roublot
Arnaud Sourisse
Aldo Midali
Sidney Gates
Serhiy Semenenko
Miguel Esquer Ramiro
Stefan Grunenberg
Ferenc Kunkli
Stefano Boggia
Lee Bennett
Morgantech
Marek Přikryl
Peter Scott
Ernst Camenzind
Steve Robbins
Jean Noel Berlan
Walter Szempruch
Petr Kysela
+48 -12
View File
@@ -1,16 +1,52 @@
## OpenTX 2.2 Branch
# FlySky i6x port of OpenTX
[![Travis build Status](https://travis-ci.org/opentx/opentx.svg?branch=2.2)](https://travis-ci.org/opentx/opentx)
[![Quality Gate](https://sonarcloud.io/api/badges/gate?key=OpenTX:2.2)](https://sonarcloud.io/dashboard?id=OpenTX:2.2)
[![Join the chat at https://opentx.rocket.chat](https://camo.githubusercontent.com/3d659054abd6ce21c0e47cf3b83a51bda69ca282/68747470733a2f2f64656d6f2e726f636b65742e636861742f696d616765732f6a6f696e2d636861742e737667)](https://opentx.rocket.chat)
[![Donate using Paypal](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=DJ9MASSKVW8WN)
This is a port of OpenTX for the venerable Flysky I6X RC radio transmitter. You can find the latest build and some instructions and videos contributed by fellow early adopters in the [RCGroups thread](https://www.rcgroups.com/forums/showthread.php?3916435-FlySky-I6X-port-of-OpenTX)
The ongoing development on 2.2.x is done in this branch.
## Implemented features
Refer to the [OpenTX wiki](https://github.com/opentx/opentx/wiki) for information about setting up the tool chains for building OpenTX and OpenTX Companion as well as other development related issues.
* AFHDS2A protocol
* PPM out
* CRSF working with ExpressLRS and Crossfire modules at rates from 115k to 3.75M bauds, CRSFshot enabled
* Telemetry
* Audio tones, alarms and vario custom implementation (Janek)
* USB (To enable on standard cable: General Settings > USB Detect set to "Once") (Janek)
* Joystick mode (Janek)
* Mass Storage to backup/restore eeprom (Janek)
* ExpressLRS V1.x configuration in model setup
## Users Telegram group
Useful links:
* OpenTX Main Site http://www.open-tx.org/
* OpenTx University http://open-txu.org/
* OpenTX User Manual https://www.gitbook.com/book/opentx/opentx-taranis-manual/details
* OpenTX Lua Reference Guide https://www.gitbook.com/book/opentx/opentx-lua-reference-guide/details
https://t.me/otx_flysky_i6x
## Navigation:
| Key | Function |
| --- | --- |
| UP | Hold for stats |
| DOWN | Hold for telemetry |
| OK | Hold for Model menu |
| CANCEL | EXIT. Hold for graceful shutdown (Needed to save timers) |
| BIND | Go RIGHT. Go to next PAGE. Hold for general menu. |
| RIGHT POT | Scroll right or left |
## ST-Link pinout
![ST-Link pinout](https://raw.githubusercontent.com/marianomd/opentx/2.3_M0/doc/flysky/flysky-i6x%20st-link%20pinout%20small.png)
## Linux instructions
### Compile
`docker run --rm -it -e "BOARD_NAME=I6X" -e "CMAKE_FLAGS=PCB=I6X HELI=NO GVARS=NO LUA_COMPILER=NO MULTIMODULE=NO DEBUG=YES" -v $PWD:/opentx vitass/opentx-fw-build`
### Flash
`sudo st-flash write <file_to_flash>.bin 0x08000000`
### Debug tty:
`sudo cat /dev/ttyUSB0 115200`
## Contributors
* Janek (@ajjjjjjjj) ongoing collaboration.
* All the RF code was taken from the great KotelloRC's erfly6: Er9X for i6 and i6x. You can find his project here: https://bitbucket.org/KotelloRC/erfly6/src/master/
* ADC code taken from OpenGround: https://github.com/fishpepper/OpenGround
* This work is based on Jakub's (qba667) work and is forked from his repo.
* All the contributors of OpenTX.
+2 -2
View File
@@ -14,10 +14,10 @@ macro(add_bitmaps_target targetname filter width format)
add_custom_target(${targetname} DEPENDS ${bitmaps_files})
endmacro(add_bitmaps_target)
macro(add_truetype_font_target radio name font size bold)
macro(add_truetype_font_target radio name font size offset)
set(target ${RADIO_SRC_DIRECTORY}/fonts/${radio}/font_${name})
add_custom_target(ttf_${radio}_${name}
COMMAND ${PYTHON_EXECUTABLE} ${RADIO_DIRECTORY}/util/font2png.py ${font} ${size} ${bold} ${target}
COMMAND ${PYTHON_EXECUTABLE} ${RADIO_DIRECTORY}/util/font2png.py ${font} ${size} ${offset} ${target}
WORKING_DIRECTORY ${RADIO_SRC_DIRECTORY}
)
set(ttf_${radio}_fonts_targets ${ttf_${radio}_fonts_targets} ttf_${radio}_${name})
+2 -2
View File
@@ -49,8 +49,8 @@ macro(use_cxx11)
endmacro(use_cxx11)
macro(PrintTargetReport targetName)
if(CMAKE_CXX_COMPILER MATCHES "/cl\\.exe$")
set(cpp_version ${MSVC_VERSION})
if(CMAKE_CXX_COMPILER MATCHES "/(clang-)?cl\\.exe$")
set(cpp_version ${CMAKE_CXX_COMPILER_VERSION})
else()
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE cpp_version)
endif()
+11 -7
View File
@@ -1,3 +1,7 @@
<h2>Version 2.2.1 / 2017-12-17</h2>
Please see <a href=http://www.open-tx.org/2017/12/16/opentx-2.2.1>this page</a> for details.
<h2>Version 2.2.0 / 2017-05-30</h2>
Major release! Please see <a href=http://www.open-tx.org/2017/05/30/opentx-2.2.0>this page</a> for details.
@@ -91,10 +95,10 @@ Notice: version 2.1.4 was skipped by the OpenTX team to avoid confusion with FrS
<li>Fixed a problem with updates path on Windows (<a href=https://github.com/opentx/opentx/issues/2876>#2876</a>)</li>
<li>Edge representation unified (changed from "no release" to "instant") (<a href=https://github.com/opentx/opentx/issues/2837>#2837</a>)</li>
<li>Added channel names on failsafe sliders (<a href=https://github.com/opentx/opentx/issues/3021>#3021</a>)</li>
<li>Corrected failsafe mapping when using Custom failsafe mode, D16 protocol and channel range different from from 1-8.
<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>
<li>Various texts and translations corrections</li>
<li>Various small bug-fixes: <a href=https://github.com/opentx/opentx/issues/2994>#2994</a>,
<li>Various small bug-fixes: <a href=https://github.com/opentx/opentx/issues/2994>#2994</a>,
<a href=https://github.com/opentx/opentx/issues/3016>#3016</a>,
<a href=https://github.com/opentx/opentx/issues/3012>#3012</a>
</li>
@@ -112,8 +116,8 @@ Notice: version 2.1.4 was skipped by the OpenTX team to avoid confusion with FrS
<ul>
<li>Fixed: Lua model scripts outputs not working in a simulator (<a href=https://github.com/opentx/opentx/issues/2684>#2684</a>)</li>
<li>Fixed a problem of Companion 2.1 trying to install into 2.0 path.
The effect will only be visible for the users that did not install any of the previous 2.1.x versions.
<li>Fixed a problem of Companion 2.1 trying to install into 2.0 path.
The effect will only be visible for the users that did not install any of the previous 2.1.x versions.
(<a href=https://github.com/opentx/opentx/issues/2645>#2645</a>)</li>
<li>Added missing SDL libraries to MAC package (<a href=https://github.com/opentx/opentx/issues/2678>#2678</a>)</li>
<li>Added used channels check/warning in Wizard (<a href=https://github.com/opentx/opentx/issues/2091>#2091</a>)</li>
@@ -194,7 +198,7 @@ Notice: version 2.1.4 was skipped by the OpenTX team to avoid confusion with FrS
<li>Added Battery meter range setting (<a href=https://github.com/opentx/opentx/issues/2195>#2195</a>)</li>
<li>Improvements in Print and Compare dialogs (<a href=https://github.com/opentx/opentx/issues/2219>#2219</a>)</li>
<li>Reset pots to the middle by right double clicking them in Simulator (<a href=https://github.com/opentx/opentx/issues/1939>#1939</a>)</li>
<li>Minor fixes: <a href=https://github.com/opentx/opentx/issues/2153>#2153</a>,
<li>Minor fixes: <a href=https://github.com/opentx/opentx/issues/2153>#2153</a>,
<a href=https://github.com/opentx/opentx/issues/2138>#2138</a>,
<a href=https://github.com/opentx/opentx/issues/2090>#2090</a>,
<a href=https://github.com/opentx/opentx/issues/2122>#2122</a>
@@ -297,13 +301,13 @@ Notice: version 2.1.4 was skipped by the OpenTX team to avoid confusion with FrS
<ul>
<li>Sound should be ok on all platforms</li>
<li>Min/Max reviewed in Logical switches (for the whole telemetry)</li>
<li>Various bug fixes</li>
<li>Various bug fixes</li>
</ul>
<h2>Version 2.0.3</h2>
<ul>
<li>EEPROM import bug on AdjustGVAR function</li>
<li>Timers correctly displayed in logical switches tab</li>
<li>Timers correctly displayed in logical switches tab</li>
</ul>
<h2>Version 2.0.2</h2>
+89 -83
View File
@@ -81,11 +81,14 @@ if(WIN32)
set(WIN_EXECUTABLE_TYPE WIN32) # GUI (WinMain) app
endif()
if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc /LD /MP")
if(NOT CLANG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /LD /MP")
endif()
if(NOT WIN_USE_CONSOLE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS,5.01") # is this even needed?
endif()
elseif(MINGW)
get_filename_component(MINGW_DIR ${CMAKE_CXX_COMPILER} DIRECTORY)
# struct packing breaks on MinGW w/out -mno-ms-bitfields: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991 & http://stackoverflow.com/questions/24015852/struct-packing-and-alignment-with-mingw
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mno-ms-bitfields")
endif()
@@ -161,18 +164,9 @@ endif()
set(common_SRCS
appdebugmessagehandler.cpp
boards.cpp
customdebug.cpp
eeprominterface.cpp
helpers.cpp
radiodata.cpp
translations.cpp
firmwares/er9x/er9xeeprom.cpp
firmwares/er9x/er9xinterface.cpp
firmwares/ersky9x/ersky9xeeprom.cpp
firmwares/ersky9x/ersky9xinterface.cpp
firmwares/opentx/opentxeeprom.cpp
firmwares/opentx/opentxinterface.cpp
modeledit/node.cpp # used in simulator
modeledit/edge.cpp # used by node
)
@@ -190,23 +184,35 @@ set(common_RESOURCES
qt5_wrap_cpp(common_SRCS ${common_MOC_HDRS})
qt5_add_resources(common_RCC ${common_RESOURCES})
#add_custom_target(gen_qrc DEPENDS ${common_RCC} ${companion_QM})
add_library(common ${common_SRCS} ${common_RCC})
qt5_use_modules(common Core Xml Widgets)
target_link_libraries(common PRIVATE simulation)
#add_dependencies(common gen_qrc)
target_link_libraries(common
firmwares
storage
simulation
maxLibQtWidgets
Qt5::Core
Qt5::Xml
Qt5::Widgets
${PTHREAD_LIBRARY}
${SDL_LIBRARY}
${WIN_LINK_LIBRARIES}
)
set(CPN_COMMON_LIB common)
############# Supporting libraries ###############
add_subdirectory(datamodels)
add_subdirectory(firmwares)
add_subdirectory(shared)
add_subdirectory(modeledit)
add_subdirectory(generaledit)
add_subdirectory(simulation)
add_subdirectory(storage)
add_subdirectory(thirdparty/qcustomplot)
add_subdirectory(thirdparty/maxlibqt/src/widgets)
############# Companion ###############
@@ -242,7 +248,8 @@ set(companion_SRCS
radionotfound.cpp
wizarddata.cpp
wizarddialog.cpp
multiprotocols.cpp
styleeditdialog.cpp
dialogs/filesyncdialog.cpp # TODO move to own lib with other dialogs
)
set(companion_MOC_HDRS
@@ -274,6 +281,9 @@ set(companion_MOC_HDRS
modelprinter.h
multimodelprinter.h
modelslist.h
styleeditdialog.h
helpers_html.h
dialogs/filesyncdialog.h
)
set(companion_UIS
@@ -294,18 +304,18 @@ set(companion_UIS
flashfirmwaredialog.ui
flasheepromdialog.ui
radionotfound.ui
styleeditdialog.ui
)
if(WIN32)
set(icon_RC icon.rc)
set(icon_RC images/winicons/icon.rc)
endif()
qt5_wrap_ui(companion_SRCS ${companion_UIS})
qt5_wrap_cpp(companion_SRCS ${companion_MOC_HDRS})
add_executable(${COMPANION_NAME} MACOSX_BUNDLE ${WIN_EXECUTABLE_TYPE} ${companion_SRCS} ${icon_RC})
qt5_use_modules(${COMPANION_NAME} Core Widgets Network)
target_link_libraries(${COMPANION_NAME} PRIVATE generaledit modeledit simulation ${CPN_COMMON_LIB} qcustomplot shared storage ${PTHREAD_LIBRARY} ${SDL_LIBRARY} ${WIN_LINK_LIBRARIES})
target_link_libraries(${COMPANION_NAME} PRIVATE generaledit modeledit qcustomplot shared ${CPN_COMMON_LIB})
PrintTargetReport("${COMPANION_NAME}")
@@ -314,7 +324,7 @@ PrintTargetReport("${COMPANION_NAME}")
set(simu_SRCS simulator.cpp )
add_executable(${SIMULATOR_NAME} MACOSX_BUNDLE ${WIN_EXECUTABLE_TYPE} ${simu_SRCS} ${icon_RC})
target_link_libraries(${SIMULATOR_NAME} PRIVATE simulation ${CPN_COMMON_LIB} storage ${PTHREAD_LIBRARY} ${SDL_LIBRARY} ${WIN_LINK_LIBRARIES})
target_link_libraries(${SIMULATOR_NAME} PRIVATE ${CPN_COMMON_LIB})
############# Install ####################
@@ -326,8 +336,10 @@ string(TOLOWER ${PCB} FLAVOUR)
if(POLICY CMP0026)
cmake_policy(SET CMP0026 OLD) # https://cmake.org/cmake/help/v3.0/policy/CMP0026.html
endif()
get_property(current_plugin TARGET opentx-${FLAVOUR}-simulator PROPERTY LOCATION)
list(APPEND simulator_plugins "${current_plugin}")
if(SIMU_TARGET)
get_property(current_plugin TARGET opentx-${FLAVOUR}-simulator PROPERTY LOCATION)
list(APPEND simulator_plugins "${current_plugin}")
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
@@ -357,13 +369,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
elseif(WIN32)
set(QT_DLL_DIR ${QT_LIB_DIR})
set(INSTALL_TEMP_QTDLL_FILES Qt5Core Qt5Gui Qt5Widgets Qt5Xml Qt5Network Qt5PrintSupport Qt5Multimedia Qt5Svg)
set(INSTALL_TEMP_ICUDLL_FILES icudt54.dll icuin54.dll icuuc54.dll)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(INSTALL_TEMP_QTDLL_SFX "d")
endif()
if(NOT WIN_DO_FULL_INSTALL)
# Just copy supporting DLLs to build folder
set(INSTALL_DESTINATION "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
@@ -377,89 +382,90 @@ elseif(WIN32)
install(TARGETS ${SIMULATOR_NAME} DESTINATION ${INSTALL_DESTINATION})
install(FILES ${simulator_plugins} DESTINATION "${INSTALL_DESTINATION}")
# supporting utilities
set(INSTALL_TEMP_FILES avrdude.exe avrdude.conf dfu-util.exe libusb0.dll libusb-1.0.dll)
set(INSTALL_TEMP_FILES avrdude.exe avrdude.conf dfu-util.exe libusb0.dll libusb-1.0.dll license.txt)
foreach(tmpfile ${INSTALL_TEMP_FILES})
install(FILES "${COMPANION_SRC_DIRECTORY}/../targets/windows/${tmpfile}" DESTINATION ${INSTALL_DESTINATION})
endforeach()
endif() # WIN_DO_FULL_INSTALL
# Qt dlls
foreach(tmpfile ${INSTALL_TEMP_QTDLL_FILES})
install(FILES ${QT_DLL_DIR}/${tmpfile}${INSTALL_TEMP_QTDLL_SFX}.dll DESTINATION ${INSTALL_DESTINATION})
endforeach()
install(FILES ${QT_DLL_DIR}/../plugins/platforms/qwindows${INSTALL_TEMP_QTDLL_SFX}.dll DESTINATION ${INSTALL_DESTINATION}/platforms)
# ICU dlls
foreach(tmpfile ${INSTALL_TEMP_ICUDLL_FILES})
# Qt5.7+ doesn't use icu dlls anymore, hence optional
install(FILES ${QT_DLL_DIR}/${tmpfile}.dll DESTINATION ${INSTALL_DESTINATION} OPTIONAL)
endforeach()
# Qt dlls (using windeployqt)
## Qt translations are already packaged into our custom qrc. Also don't need software rendering engines.
set(wdqtopts --no-translations --no-opengl-sw --no-system-d3d-compiler --no-angle)
if(CMAKE_BUILD_TYPE STREQUAL "Release")
set(wdqtopts ${wdqtopts} --release) # release builds aren't always properly detected with mingw
endif()
if(MSVC)
set(wdqtopts ${wdqtopts} --no-compiler-runtime) # --compiler-runtime includes vcredist_x86, but we just copy the required DLLs manually
endif()
set(wdqtopts ${wdqtopts} -dir "${INSTALL_DESTINATION}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${COMPANION_NAME}.exe" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${SIMULATOR_NAME}.exe")
# Add installer command to execute windeployqt
install(CODE "execute_process(COMMAND \"${QT_BIN_DIR}/windeployqt.exe\" ${wdqtopts})")
# SDL dll
if(SDL_FOUND AND SDL_LIBRARY_PATH AND EXISTS "${SDL_LIBRARY_PATH}/SDL.dll")
if(SDL_FOUND AND EXISTS "${SDL_LIBRARY_PATH}/SDL.dll")
set(SDL_DIR ${SDL_LIBRARY_PATH}) # this is also used by NSIS installer script
install(FILES ${SDL_DIR}/SDL.dll DESTINATION ${INSTALL_DESTINATION})
elseif(SDL_FOUND)
message(WARNING "Installer: SDL.dll not found!")
message(WARNING "Installer: SDL.dll not found, set SDL_LIBRARY_PATH manually.")
endif()
# libeay (SSL) dlls (used by QtNetwork) -- not strictly required but avoids possible issues with downloads and Qt warnings.
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" WIN_PROGRAM_FILES)
find_path(EAY_LIB_DIR libeay32.dll HINTS
"${WIN_PROGRAM_FILES}/OpenSSL" "${WIN_PROGRAM_FILES}/OpenSSL-Win32"
"C:/OpenSSL/" "C:/OpenSSL-Win32/"
"${WIN_EXTRA_LIBS_PATH}" "${WIN_EXTRA_LIBS_PATH}/OpenSSL" "${WIN_EXTRA_LIBS_PATH}/OpenSSL-Win32"
"${MINGW_DIR}/../opt/bin"
"${PYTHON_DIRECTORY}/lib/site-packages/PyQt4"
PATH_SUFFIXES bin
DOC "Path to libeay32.dll and ssleay32.dll (OpenSSL)"
)
if (EAY_LIB_DIR)
install(FILES "${EAY_LIB_DIR}/libeay32.dll" "${EAY_LIB_DIR}/ssleay32.dll" DESTINATION ${INSTALL_DESTINATION} OPTIONAL)
else()
message(WARNING "Installer: SSL libs not found, set EAY_LIB_DIR manually.")
endif()
# C++/system dlls, depends on compiler
if(MSVC)
string(REPLACE "\\" "/" WIN_SYSDIR "$ENV{windir}")
set(WIN_SYSDIR "${WIN_SYSDIR}/SysWOW64") # This would be "system32" for a 64-bit build or on x86... but how to tell?
if(IS_DIRECTORY "${WIN_SYSDIR}")
install(FILES "${WIN_SYSDIR}/msvcp140.dll" "${WIN_SYSDIR}/vcruntime140.dll" DESTINATION ${INSTALL_DESTINATION} OPTIONAL)
file(TO_CMAKE_PATH "$ENV{windir}/SysWOW64" WIN_SYSDIR) # This would be "system32" for a 64-bit build or on x86... but how to tell?
if (NOT EXISTS "${WIN_SYSDIR}")
file(TO_CMAKE_PATH "$ENV{windir}/system32" WIN_SYSDIR) # Must be 32-bit Windows.
endif()
install(FILES "${WIN_SYSDIR}/msvcp140.dll" "${WIN_SYSDIR}/vcruntime140.dll" DESTINATION ${INSTALL_DESTINATION} OPTIONAL)
if(WIN_PTHREAD_DLL)
install(FILES "${WIN_PTHREAD_DLL}" DESTINATION ${INSTALL_DESTINATION})
endif()
elseif(MINGW)
get_filename_component(MINGW_DIR ${CMAKE_CXX_COMPILER} PATH)
if(IS_DIRECTORY ${MINGW_DIR})
install(FILES "${MINGW_DIR}/libgcc_s_dw2-1.dll" "${MINGW_DIR}/libstdc++-6.dll" "${MINGW_DIR}/libwinpthread-1.dll" DESTINATION ${INSTALL_DESTINATION})
set(MINGW_DIR "${MINGW_DIR}/../opt/bin")
# SSL support
install(FILES "${MINGW_DIR}/libeay32.dll" "${MINGW_DIR}/ssleay32.dll" DESTINATION ${INSTALL_DESTINATION} OPTIONAL)
endif()
endif()
endif() # WIN32 install
############# Packaging ####################
# Create Windows installer with NSIS (only works for MSVC for now)
# Create Windows installer with NSIS
if(WIN32)
if(MSVC)
set(COMPANION_NSI_IN_FILE companion-vs.nsi.in)
set(SIMULATOR_NSI_IN_FILE simulator-vs.nsi.in)
else()
set(COMPANION_NSI_IN_FILE companion-msys.nsi.in)
set(SIMULATOR_NSI_IN_FILE simulator-msys.nsi.in)
endif()
set(SYSDIR "$ENV{windir}/system32")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../targets/windows/${COMPANION_NSI_IN_FILE} ${PROJECT_BINARY_DIR}/companion/companion.nsi @ONLY)
#configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../targets/windows/${SIMULATOR_NSI_IN_FILE} ${PROJECT_BINARY_DIR}/companion/simulator.nsi @ONLY)
find_program(NSIS_EXE makensis.exe PATHS
"C:/Program Files/NSIS"
"C:/Program Files (x86)/NSIS"
"C:/Programs/NSIS"
"${WIN_EXTRA_LIBS_PATH}/NSIS"
)
if (NSIS_EXE)
file(TO_NATIVE_PATH "${INSTALL_DESTINATION}" NSIS_DISTRO) # all files in here will be included in installer
set(NSI_FILE "${PROJECT_BINARY_DIR}/companion/companion.nsi")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../targets/windows/companion.nsi.in" "${NSI_FILE}" @ONLY)
add_custom_target(installer
# The 'install' target prepares all the distro files, make sure it has been executed first.
COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}" --target install
COMMAND "${NSIS_EXE}" "${NSI_FILE}"
DEPENDS "${NSI_FILE}"
COMMENT "Building Windows NSIS installer..."
)
endif()
add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/companion/companion-windows.exe
COMMAND "${NSIS_EXE}" ARGS ${PROJECT_BINARY_DIR}/companion/companion.nsi
DEPENDS companion simulator opentx-simulators ${PROJECT_BINARY_DIR}/companion/companion.nsi
COMMENT "Companion Windows NSIS Installer")
# add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/companion/simulator-install.exe
# COMMAND "${NSIS_EXE}" ARGS ${PROJECT_BINARY_DIR}/companion/simulator.nsi
# DEPENDS simulator ${PROJECT_BINARY_DIR}/companion/simulator.nsi
# COMMENT "Simulator Windows NSIS Installer")
add_custom_target(installer
DEPENDS ${PROJECT_BINARY_DIR}/companion/companion-windows.exe
# DEPENDS ${PROJECT_BINARY_DIR}/companion/simulator-windows.exe
SOURCES ${PROJECT_BINARY_DIR}/companion/companion.nsi
# SOURCES ${PROJECT_BINARY_DIR}/companion/simulator.nsi
)
endif()
set(CPACK_PACKAGE_NAME "companion${C9X_NAME_SUFFIX}")
@@ -528,9 +534,9 @@ IF(APPLE)
get_filename_component(AVRDUDECONF_ABSOLUTE_PATH ${AVRDUDE_CONF} REALPATH)
install(PROGRAMS ${DFU_UTIL_ABSOLUTE_PATH} ${AVRDUDE_ABSOLUTE_PATH} DESTINATION ${companion_res_dir} COMPONENT Runtime)
install(FILES ${AVRDUDECONF_ABSOLUTE_PATH} DESTINATION ${companion_res_dir} COMPONENT Runtime)
set(bundle_tools_path "\${CMAKE_INSTALL_PREFIX}/${companion_res_dir}/dfu-util;\${CMAKE_INSTALL_PREFIX}/${companion_res_dir}/avrdude")
# Include depencies (adding frameworks, fixing the embbeded libraries)
# I get write errors without setting BU_CHMOD_BUNDLE_ITEMS even though it is
+153 -155
View File
@@ -23,6 +23,7 @@
#include "mainwindow.h"
#include "appdata.h"
#include "helpers.h"
#include "storage.h"
#if defined(JOYSTICKS)
#include "joystick.h"
#include "joystickdialog.h"
@@ -30,17 +31,17 @@
AppPreferencesDialog::AppPreferencesDialog(QWidget * parent) :
QDialog(parent),
ui(new Ui::AppPreferencesDialog)
ui(new Ui::AppPreferencesDialog),
updateLock(false),
mainWinHasDirtyChild(false)
{
ui->setupUi(this);
updateLock=false;
setWindowIcon(CompanionIcon("apppreferences.png"));
initSettings();
connect(ui->downloadVerCB, SIGNAL(currentIndexChanged(int)), this, SLOT(baseFirmwareChanged()));
connect(ui->downloadVerCB, SIGNAL(currentIndexChanged(int)), this, SLOT(onBaseFirmwareChanged()));
connect(ui->opt_appDebugLog, &QCheckBox::toggled, this, &AppPreferencesDialog::toggleAppLogSettings);
connect(ui->opt_fwTraceLog, &QCheckBox::toggled, this, &AppPreferencesDialog::toggleAppLogSettings);
connect(this, SIGNAL(accepted()), this, SLOT(writeValues()));
#if !defined(JOYSTICKS)
ui->joystickCB->hide();
@@ -58,18 +59,25 @@ AppPreferencesDialog::~AppPreferencesDialog()
delete ui;
}
void AppPreferencesDialog::writeValues()
void AppPreferencesDialog::setMainWinHasDirtyChild(bool value)
{
mainWinHasDirtyChild = value;
}
void AppPreferencesDialog::accept()
{
Profile & profile = g.currentProfile();
g.autoCheckApp(ui->autoCheckCompanion->isChecked());
g.OpenTxBranch(DownloadBranchType(ui->OpenTxBranch->currentIndex()));
g.OpenTxBranch(AppData::DownloadBranchType(ui->OpenTxBranch->currentIndex()));
g.autoCheckFw(ui->autoCheckFirmware->isChecked());
g.showSplash(ui->showSplash->isChecked());
g.simuSW(ui->simuSW->isChecked());
g.removeModelSlots(ui->opt_removeBlankSlots->isChecked());
g.newModelAction(ui->opt_newMdl_useWizard->isChecked() ? 1 : ui->opt_newMdl_useEditor->isChecked() ? 2 : 0);
g.newModelAction(ui->opt_newMdl_useWizard->isChecked() ? AppData::MODEL_ACT_WIZARD : ui->opt_newMdl_useEditor->isChecked() ? AppData::MODEL_ACT_EDITOR : AppData::MODEL_ACT_NONE);
g.historySize(ui->historySize->value());
g.backLight(ui->backLightColor->currentIndex());
g.profile[g.id()].volumeGain(round(ui->volumeGain->value() * 10.0));
profile.volumeGain(round(ui->volumeGain->value() * 10.0));
g.libDir(ui->libraryPath->text());
g.gePath(ui->ge_lineedit->text());
g.embedSplashes(ui->splashincludeCB->currentIndex());
@@ -87,30 +95,57 @@ void AppPreferencesDialog::writeValues()
g.jsSupport(false);
g.jsCtrl(0);
}
g.profile[g.id()].channelOrder(ui->channelorderCB->currentIndex());
g.profile[g.id()].defaultMode(ui->stickmodeCB->currentIndex());
g.profile[g.id()].renameFwFiles(ui->renameFirmware->isChecked());
g.profile[g.id()].burnFirmware(ui->burnFirmware->isChecked());
g.profile[g.id()].sdPath(ui->sdPath->text());
g.profile[g.id()].pBackupDir(ui->profilebackupPath->text());
g.profile[g.id()].penableBackup(ui->pbackupEnable->isChecked());
g.profile[g.id()].splashFile(ui->SplashFileName->text());
profile.channelOrder(ui->channelorderCB->currentIndex());
profile.defaultMode(ui->stickmodeCB->currentIndex());
profile.renameFwFiles(ui->renameFirmware->isChecked());
profile.burnFirmware(ui->burnFirmware->isChecked());
profile.sdPath(ui->sdPath->text());
profile.pBackupDir(ui->profilebackupPath->text());
profile.penableBackup(ui->pbackupEnable->isChecked());
profile.splashFile(ui->SplashFileName->text());
// The profile name may NEVER be empty
if (ui->profileNameLE->text().isEmpty())
g.profile[g.id()].name(tr("My Radio"));
profile.name(tr("My Radio"));
else
g.profile[g.id()].name(ui->profileNameLE->text());
profile.name(ui->profileNameLE->text());
bool fwchange = false;
Firmware * newFw = getFirmwareVariant(); // always !null
// If a new fw type has been choosen, several things need to reset
Firmware::setCurrentVariant(getFirmwareVariant());
QString id = Firmware::getCurrentVariant()->getId();
if (g.profile[g.id()].fwType() != id) {
g.profile[g.id()].fwName("");
g.profile[g.id()].initFwVariables();
g.profile[g.id()].fwType(id);
emit firmwareProfileChanged(g.id());
if (Firmware::getCurrentVariant()->getId() != newFw->getId()) {
// check if we're going to be converting to a new radio type and there are unsaved files in the main window
if (mainWinHasDirtyChild && !Boards::isBoardCompatible(Firmware::getCurrentVariant()->getBoard(), newFw->getBoard())) {
QString q = tr("<p><b>You cannot switch Radio Type or change Build Options while there are unsaved file changes. What do you wish to do?</b></p> <ul>" \
"<li><i>Save All</i> - Save any open file(s) before saving Settings.<li>" \
"<li><i>Reset</i> - Revert to the previous Radio Type and Build Options before saving Settings.</li>" \
"<li><i>Cancel</i> - Return to the Settings editor dialog.</li></ul>");
int resp = QMessageBox::question(this, windowTitle(), q, (QMessageBox::SaveAll | QMessageBox::Reset | QMessageBox::Cancel), QMessageBox::Cancel);
if (resp == QMessageBox::SaveAll) {
// signal main window to save files, need to do this before the fw actually changes
emit firmwareProfileAboutToChange();
}
else if (resp == QMessageBox::Reset) {
// bail out early before saving the radio type & firmware options
QDialog::accept();
return;
}
else {
// we do not accept the dialog close
return;
}
}
Firmware::setCurrentVariant(newFw);
profile.fwName("");
profile.resetFwVariables();
profile.fwType(newFw->getId());
fwchange = true;
}
QDialog::accept();
if (fwchange)
emit firmwareProfileChanged(); // important to do this after the accepted() signal
}
void AppPreferencesDialog::on_snapshotPathButton_clicked()
@@ -125,24 +160,33 @@ void AppPreferencesDialog::on_snapshotPathButton_clicked()
void AppPreferencesDialog::initSettings()
{
const Profile & profile = g.currentProfile();
ui->snapshotClipboardCKB->setChecked(g.snapToClpbrd());
ui->burnFirmware->setChecked(g.profile[g.id()].burnFirmware());
ui->burnFirmware->setChecked(profile.burnFirmware());
ui->snapshotPath->setText(g.snapshotDir());
ui->snapshotPath->setReadOnly(true);
if (ui->snapshotClipboardCKB->isChecked()) {
ui->snapshotPath->setDisabled(true);
ui->snapshotPathButton->setDisabled(true);
}
#if !defined(ALLOW_NIGHTLY_BUILDS)
// TODO should we gray out nightly builds here?
// remove nightly version option entirely unless it's the current one (because user might have nightly version also installed)
if (g.OpenTxBranch() != AppData::BRANCH_NIGHTLY_UNSTABLE)
ui->OpenTxBranch->removeItem(2);
// if it's already selected, add a warning message
else
ui->updatesLayout->addWidget(new QLabel("<font color='red'>" % tr("Note: Nightly builds are not available in this version, Release/RC update channel will be used.") % "</font>", this));
#endif
ui->OpenTxBranch->setCurrentIndex(g.OpenTxBranch());
ui->autoCheckCompanion->setChecked(g.autoCheckApp());
ui->autoCheckFirmware->setChecked(g.autoCheckFw());
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);
ui->volumeGain->setValue(profile.volumeGain() / 10.0);
if (IS_TARANIS(getCurrentBoard())) {
ui->backLightColor->setEnabled(false);
@@ -150,9 +194,9 @@ void AppPreferencesDialog::initSettings()
ui->simuSW->setChecked(g.simuSW());
ui->opt_removeBlankSlots->setChecked(g.removeModelSlots());
ui->opt_newMdl_useNone->setChecked(g.newModelAction() == 0);
ui->opt_newMdl_useWizard->setChecked(g.newModelAction() == 1);
ui->opt_newMdl_useEditor->setChecked(g.newModelAction() == 2);
ui->opt_newMdl_useNone->setChecked(g.newModelAction() == AppData::MODEL_ACT_NONE);
ui->opt_newMdl_useWizard->setChecked(g.newModelAction() == AppData::MODEL_ACT_WIZARD);
ui->opt_newMdl_useEditor->setChecked(g.newModelAction() == AppData::MODEL_ACT_EDITOR);
ui->libraryPath->setText(g.libDir());
ui->ge_lineedit->setText(g.gePath());
@@ -204,15 +248,15 @@ void AppPreferencesDialog::initSettings()
}
#endif
// Profile Tab Inits
ui->channelorderCB->setCurrentIndex(g.profile[g.id()].channelOrder());
ui->stickmodeCB->setCurrentIndex(g.profile[g.id()].defaultMode());
ui->renameFirmware->setChecked(g.profile[g.id()].renameFwFiles());
ui->sdPath->setText(g.profile[g.id()].sdPath());
if (!g.profile[g.id()].pBackupDir().isEmpty()) {
if (QDir(g.profile[g.id()].pBackupDir()).exists()) {
ui->profilebackupPath->setText(g.profile[g.id()].pBackupDir());
ui->channelorderCB->setCurrentIndex(profile.channelOrder());
ui->stickmodeCB->setCurrentIndex(profile.defaultMode());
ui->renameFirmware->setChecked(profile.renameFwFiles());
ui->sdPath->setText(profile.sdPath());
if (!profile.pBackupDir().isEmpty()) {
if (QDir(profile.pBackupDir()).exists()) {
ui->profilebackupPath->setText(profile.pBackupDir());
ui->pbackupEnable->setEnabled(true);
ui->pbackupEnable->setChecked(g.profile[g.id()].penableBackup());
ui->pbackupEnable->setChecked(profile.penableBackup());
} else {
ui->pbackupEnable->setDisabled(true);
}
@@ -221,14 +265,14 @@ void AppPreferencesDialog::initSettings()
ui->pbackupEnable->setDisabled(true);
}
ui->profileNameLE->setText(g.profile[g.id()].name());
ui->profileNameLE->setText(profile.name());
QString hwSettings;
if (g.profile[g.id()].stickPotCalib() == "" ) {
if (profile.stickPotCalib() == "" ) {
hwSettings = tr("EMPTY: No radio settings stored in profile");
}
else {
QString str = g.profile[g.id()].timeStamp();
QString str = profile.timeStamp();
if (str.isEmpty())
hwSettings = tr("AVAILABLE: Radio settings of unknown age");
else
@@ -236,7 +280,7 @@ void AppPreferencesDialog::initSettings()
}
ui->lblGeneralSettings->setText(hwSettings);
QString currType = QStringList(g.profile[g.id()].fwType().split('-').mid(0, 2)).join('-');
QString currType = QStringList(profile.fwType().split('-').mid(0, 2)).join('-');
foreach(Firmware * firmware, Firmware::getRegisteredFirmwares()) {
ui->downloadVerCB->addItem(firmware->getName(), firmware->getId());
if (currType == firmware->getId()) {
@@ -244,7 +288,7 @@ void AppPreferencesDialog::initSettings()
}
}
baseFirmwareChanged();
onBaseFirmwareChanged();
}
void AppPreferencesDialog::on_libraryPathButton_clicked()
@@ -344,7 +388,7 @@ void AppPreferencesDialog::on_joystickcalButton_clicked() {
void AppPreferencesDialog::on_sdPathButton_clicked()
{
QString fileName = QFileDialog::getExistingDirectory(this,tr("Select the folder replicating your SD structure"), g.profile[g.id()].sdPath());
QString fileName = QFileDialog::getExistingDirectory(this,tr("Select the folder replicating your SD structure"), g.currentProfile().sdPath());
if (!fileName.isEmpty()) {
ui->sdPath->setText(fileName);
}
@@ -391,81 +435,47 @@ void AppPreferencesDialog::on_clearImageButton_clicked()
ui->SplashFileName->clear();
}
void AppPreferencesDialog::showVoice(bool show)
void AppPreferencesDialog::onBaseFirmwareChanged()
{
ui->voiceLabel->setVisible(show);
ui->voiceCombo->setVisible(show);
populateFirmwareOptions(getBaseFirmware());
}
void AppPreferencesDialog::baseFirmwareChanged()
Firmware *AppPreferencesDialog::getBaseFirmware() const
{
QString selected_firmware = ui->downloadVerCB->currentData().toString();
foreach(Firmware * firmware, Firmware::getRegisteredFirmwares()) {
if (firmware->getId() == selected_firmware) {
populateFirmwareOptions(firmware);
break;
}
}
return Firmware::getFirmwareForId(ui->downloadVerCB->currentData().toString());
}
Firmware * AppPreferencesDialog::getFirmwareVariant()
Firmware * AppPreferencesDialog::getFirmwareVariant() const
{
QString selected_firmware = ui->downloadVerCB->currentData().toString();
QString id = ui->downloadVerCB->currentData().toString();
foreach(Firmware * firmware, Firmware::getRegisteredFirmwares()) {
QString id = firmware->getId();
if (id == selected_firmware) {
foreach(QCheckBox *cb, optionsCheckBoxes) {
if (cb->isChecked()) {
id += "-" + cb->text();
}
}
if (voice && voice->isChecked()) {
id += "-tts" + ui->voiceCombo->currentText();
}
if (ui->langCombo->count()) {
id += "-" + ui->langCombo->currentText();
}
return Firmware::getFirmwareForId(id);
}
foreach(QCheckBox *cb, optionsCheckBoxes.values()) {
if (cb->isChecked())
id += "-" + cb->text();
}
// Should never occur...
return Firmware::getDefaultVariant();
if (ui->langCombo->count())
id += "-" + ui->langCombo->currentText();
return Firmware::getFirmwareForId(id);
}
void AppPreferencesDialog::firmwareOptionChanged(bool state)
void AppPreferencesDialog::onFirmwareOptionChanged(bool state)
{
QCheckBox *cb = qobject_cast<QCheckBox*>(sender());
if (cb == voice) {
showVoice(voice->isChecked());
}
Firmware * firmware=NULL;
if (cb && state) {
QVariant selected_firmware = ui->downloadVerCB->currentData();
foreach(firmware, Firmware::getRegisteredFirmwares()) {
if (firmware->getId() == selected_firmware) {
foreach(QList<Option> opts, firmware->opts) {
foreach(Option opt, opts) {
if (cb->text() == opt.name) {
foreach(Option other, opts) {
if (other.name != opt.name) {
foreach(QCheckBox *ocb, optionsCheckBoxes) {
if (ocb->text() == other.name) {
ocb->setChecked(false);
}
}
}
}
return;
}
}
}
if (!(cb && state))
return;
// This de-selects any mutually exlusive options (that is, members of the same QList<Option> list).
const Firmware::OptionsList & fwOpts = getBaseFirmware()->optionGroups();
for (const Firmware::OptionsGroup & optGrp : fwOpts) {
for (const Firmware::Option & opt : optGrp) {
if (cb->text() == opt.name) {
QCheckBox *ocb = nullptr;
foreach(const Firmware::Option & other, optGrp)
if (other.name != opt.name && (ocb = optionsCheckBoxes.value(other.name, nullptr)))
ocb->setChecked(false);
return;
}
}
}
@@ -481,79 +491,67 @@ void AppPreferencesDialog::toggleAppLogSettings()
void AppPreferencesDialog::populateFirmwareOptions(const Firmware * firmware)
{
const Firmware * parent = firmware->getFirmwareBase();
const Firmware * baseFw = firmware->getFirmwareBase();
QStringList currVariant = Firmware::getCurrentVariant()->getId().split('-');
const QString currLang = ui->langCombo->count() ? ui->langCombo->currentText() : currVariant.last();
updateLock = true;
QString id = Firmware::getCurrentVariant()->getId();
ui->langCombo->clear();
foreach(const char *lang, parent->languages) {
for (const char *lang : baseFw->languageList()) {
ui->langCombo->addItem(lang);
if (id.endsWith(lang)) {
if (currLang == lang) {
ui->langCombo->setCurrentIndex(ui->langCombo->count() - 1);
}
}
voice = NULL; // we will search for a voice checkbox
if (optionsCheckBoxes.size()) {
currVariant.clear();
QMutableMapIterator<QString, QCheckBox *> it(optionsCheckBoxes);
while (it.hasNext()) {
it.next();
QCheckBox * cb = it.value();
if (cb->isChecked())
currVariant.append(it.key()); // keep previous selections
ui->optionsLayout->removeWidget(cb);
cb->deleteLater();
it.remove();
}
}
int index = 0;
QWidget * prevFocus = ui->voiceCombo;
foreach(QList<Option> opts, parent->opts) {
foreach(Option opt, opts) {
if (index >= optionsCheckBoxes.size()) {
QCheckBox * checkbox = new QCheckBox(ui->profileTab);
ui->optionsLayout->addWidget(checkbox, optionsCheckBoxes.count()/4, optionsCheckBoxes.count()%4, 1, 1);
optionsCheckBoxes.push_back(checkbox);
connect(checkbox, SIGNAL(toggled(bool)), this, SLOT(firmwareOptionChanged(bool)));
if (prevFocus) {
QWidget::setTabOrder(prevFocus, checkbox);
}
}
QCheckBox *cb = optionsCheckBoxes.at(index++);
if (cb) {
cb->show();
cb->setText(opt.name);
cb->setToolTip(opt.tooltip);
cb->setCheckState(id.contains(opt.name) ? Qt::Checked : Qt::Unchecked);
if (opt.name == QString("voice")) {
voice = cb;
}
prevFocus = cb;
}
QWidget * prevFocus = ui->langCombo;
for (const Firmware::OptionsGroup &optGrp : baseFw->optionGroups()) {
for (const Firmware::Option &opt : optGrp) {
QCheckBox * cb = new QCheckBox(ui->profileTab);
cb->setText(opt.name);
cb->setToolTip(opt.tooltip);
cb->setChecked(currVariant.contains(opt.name));
ui->optionsLayout->addWidget(cb, index / 4, index % 4);
QWidget::setTabOrder(prevFocus, cb);
// connect to duplicates check handler if this option is part of a group
if (optGrp.size() > 1)
connect(cb, &QCheckBox::toggled, this, &AppPreferencesDialog::onFirmwareOptionChanged);
optionsCheckBoxes.insert(opt.name, cb);
prevFocus = cb;
++index;
}
}
for (; index<optionsCheckBoxes.size(); index++) {
QCheckBox *cb = optionsCheckBoxes.at(index);
cb->hide();
cb->setCheckState(Qt::Unchecked);
}
ui->voiceCombo->clear();
foreach(const char *lang, parent->ttslanguages) {
ui->voiceCombo->addItem(lang);
if (id.contains(QString("-tts%1").arg(lang))) {
ui->voiceCombo->setCurrentIndex(ui->voiceCombo->count() - 1);
}
}
showVoice(voice && voice->isChecked());
// TODO: Remove once splash replacement supported on Horus
// NOTE: 480x272 image causes issues on screens <800px high, needs a solution like scrolling once reinstated
if (IS_HORUS(parent->getBoard())) {
if (IS_HORUS(baseFw->getBoard())) {
ui->widget_splashImage->hide();
ui->SplashFileName->setText("");
}
else {
ui->widget_splashImage->show();
ui->SplashFileName->setText(g.profile[g.id()].splashFile());
displayImage(g.profile[g.id()].splashFile());
ui->SplashFileName->setText(g.currentProfile().splashFile());
displayImage(g.currentProfile().splashFile());
}
updateLock = false;
QTimer::singleShot(50, this, SLOT(shrink()));
QTimer::singleShot(50, this, &AppPreferencesDialog::shrink);
}
void AppPreferencesDialog::shrink()
+21 -19
View File
@@ -38,33 +38,23 @@ class AppPreferencesDialog : public QDialog
public:
explicit AppPreferencesDialog(QWidget * parent = 0);
~AppPreferencesDialog();
Joystick * joystick;
public slots:
void accept() Q_DECL_OVERRIDE;
void setMainWinHasDirtyChild(bool value);
signals:
void firmwareProfileChanged(int profId);
private:
QList<QCheckBox *> optionsCheckBoxes;
bool updateLock;
void showVoice(bool);
void showVoice();
void hideVoice();
void populateLocale();
void populateFirmwareOptions(const Firmware *);
Firmware * getFirmwareVariant();
QCheckBox * voice;
Ui::AppPreferencesDialog *ui;
void initSettings();
bool displayImage(const QString & fileName);
void firmwareProfileChanged();
void firmwareProfileAboutToChange(bool saveFiles = true);
protected slots:
void shrink();
void baseFirmwareChanged();
void firmwareOptionChanged(bool state);
void onBaseFirmwareChanged();
void onFirmwareOptionChanged(bool state);
void toggleAppLogSettings();
void writeValues();
void on_libraryPathButton_clicked();
void on_snapshotPathButton_clicked();
void on_snapshotClipboardCKB_clicked();
@@ -81,6 +71,18 @@ class AppPreferencesDialog : public QDialog
void on_joystickChkB_clicked();
void on_joystickcalButton_clicked();
#endif
private:
void initSettings();
void populateFirmwareOptions(const Firmware *);
Firmware * getBaseFirmware() const;
Firmware * getFirmwareVariant() const;
bool displayImage(const QString & fileName);
Ui::AppPreferencesDialog *ui;
QMap<QString, QCheckBox *> optionsCheckBoxes;
bool updateLock;
bool mainWinHasDirtyChild;
};
#endif // _APPPREFERENCESDIALOG_H_
+350 -396
View File
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>863</width>
<height>673</height>
<width>741</width>
<height>668</height>
</rect>
</property>
<property name="sizePolicy">
@@ -26,16 +26,6 @@
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="sizePolicy">
@@ -52,24 +42,37 @@
<string>Radio Profile</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,0,0,0">
<item row="8" column="2" colspan="2">
<widget class="QPushButton" name="sdPathButton">
<property name="text">
<string>Select Folder</string>
<item row="5" column="1">
<widget class="QWidget" name="optionsWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QGridLayout" name="optionsLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="horizontalSpacing">
<number>5</number>
</property>
<property name="verticalSpacing">
<number>4</number>
</property>
</layout>
</widget>
</item>
<item row="9" column="2" colspan="2">
<widget class="QPushButton" name="ProfilebackupPathButton">
<property name="toolTip">
<string>The profile specific folder, if set, will override general Backup folder</string>
</property>
<property name="text">
<string>Select Folder</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="4">
<item row="7" column="0" colspan="4">
<widget class="QWidget" name="widget_splashImage" native="true">
<layout class="QGridLayout" name="gridLayout_5">
<property name="leftMargin">
@@ -183,28 +186,19 @@
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<item row="16" column="1">
<widget class="QCheckBox" name="burnFirmware">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Profile Name</string>
<string>Offer to write FW to Tx after download</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="profileNameLE"/>
</item>
<item row="1" column="0" colspan="4">
<widget class="Line" name="line_8">
<property name="sizePolicy">
@@ -218,319 +212,7 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_7">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Sans Serif</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Radio Type</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="downloadVerCB">
<property name="enabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="langLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Menu Language</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1,1">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<widget class="QComboBox" name="langCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="voiceLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Sans Serif</family>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Voice Language</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="voiceCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Set voice language.
May be different from firmware language</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Build Options</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item row="5" column="0" colspan="4">
<widget class="Line" name="splashSeparator">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="sdPathLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>SD Structure path</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLineEdit" name="sdPath">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string/>
</property>
<property name="readOnly">
<bool>false</bool>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="profilebackupPathLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>The profile specific folder, if set, will override general Backup folder</string>
</property>
<property name="text">
<string>Backup folder</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLineEdit" name="profilebackupPath">
<property name="toolTip">
<string>If set it will override the application general setting</string>
</property>
<property name="readOnly">
<bool>false</bool>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QCheckBox" name="pbackupEnable">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>if set, will override general backup enable</string>
</property>
<property name="text">
<string>Enable automatic backup before writing firmware</string>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>General Settings</string>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QLabel" name="lblGeneralSettings">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">General Settings Label</string>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QLabel" name="label_14">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Default Stick Mode</string>
</property>
</widget>
</item>
<item row="12" column="1">
<widget class="QComboBox" name="stickmodeCB">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="whatsThis">
<string>Mode selection:
Mode 1:
Left stick: Elevator, Rudder
Right stick: Throttle, Aileron
Mode 2:
Left stick: Throttle, Rudder
Right stick: Elevator, Aileron
Mode 3:
Left stick: Elevator, Aileron
Right stick: Throttle, Rudder
Mode 4:
Left stick: Throttle, Aileron
Right stick: Elevator, Rudder
</string>
</property>
<property name="currentIndex">
<number>1</number>
</property>
<item>
<property name="text">
<string>Mode 1 (RUD ELE THR AIL)</string>
</property>
</item>
<item>
<property name="text">
<string>Mode 2 (RUD THR ELE AIL)</string>
</property>
</item>
<item>
<property name="text">
<string>Mode 3 (AIL ELE THR RUD)</string>
</property>
</item>
<item>
<property name="text">
<string>Mode 4 (AIL THR ELE RUD)</string>
</property>
</item>
</widget>
</item>
<item row="13" column="0">
<widget class="QLabel" name="label_13">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Default Channel Order</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="13" column="1">
<item row="14" column="1">
<widget class="QComboBox" name="channelorderCB">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@@ -666,7 +348,30 @@ Mode 4:
</item>
</widget>
</item>
<item row="14" column="1">
<item row="2" column="1">
<widget class="QComboBox" name="downloadVerCB">
<property name="enabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Build Options</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item row="15" column="1">
<widget class="QCheckBox" name="renameFirmware">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@@ -679,8 +384,56 @@ Mode 4:
</property>
</widget>
</item>
<item row="15" column="1">
<widget class="QCheckBox" name="burnFirmware">
<item row="9" column="2" colspan="2">
<widget class="QPushButton" name="sdPathButton">
<property name="text">
<string>Select Folder</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Profile Name</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="profileNameLE"/>
</item>
<item row="10" column="0">
<widget class="QLabel" name="profilebackupPathLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>The profile specific folder, if set, will override general Backup folder</string>
</property>
<property name="text">
<string>Backup folder</string>
</property>
</widget>
</item>
<item row="12" column="1">
<widget class="QLabel" name="lblGeneralSettings">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
@@ -688,24 +441,11 @@ Mode 4:
</sizepolicy>
</property>
<property name="text">
<string>Offer to write FW to Tx after download</string>
<string notr="true">General Settings Label</string>
</property>
</widget>
</item>
<item row="16" column="1">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item row="7" column="0" colspan="4">
<item row="8" column="0" colspan="4">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@@ -724,34 +464,240 @@ Mode 4:
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QWidget" name="optionsWidget" native="true">
<item row="13" column="0">
<widget class="QLabel" name="label_14">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QGridLayout" name="optionsLayout">
<property name="leftMargin">
<number>0</number>
<property name="text">
<string>Default Stick Mode</string>
</property>
</widget>
</item>
<item row="13" column="1">
<widget class="QComboBox" name="stickmodeCB">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="whatsThis">
<string>Mode selection:
Mode 1:
Left stick: Elevator, Rudder
Right stick: Throttle, Aileron
Mode 2:
Left stick: Throttle, Rudder
Right stick: Elevator, Aileron
Mode 3:
Left stick: Elevator, Aileron
Right stick: Throttle, Rudder
Mode 4:
Left stick: Throttle, Aileron
Right stick: Elevator, Rudder
</string>
</property>
<property name="currentIndex">
<number>1</number>
</property>
<item>
<property name="text">
<string>Mode 1 (RUD ELE THR AIL)</string>
</property>
<property name="topMargin">
<number>0</number>
</item>
<item>
<property name="text">
<string>Mode 2 (RUD THR ELE AIL)</string>
</property>
<property name="rightMargin">
<number>0</number>
</item>
<item>
<property name="text">
<string>Mode 3 (AIL ELE THR RUD)</string>
</property>
<property name="bottomMargin">
<number>0</number>
</item>
<item>
<property name="text">
<string>Mode 4 (AIL THR ELE RUD)</string>
</property>
<property name="horizontalSpacing">
<number>5</number>
</property>
<property name="verticalSpacing">
<number>4</number>
</property>
</layout>
</item>
</widget>
</item>
<item row="14" column="0">
<widget class="QLabel" name="label_13">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Default Channel Order</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QCheckBox" name="pbackupEnable">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>if set, will override general backup enable</string>
</property>
<property name="text">
<string>Enable automatic backup before writing firmware</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="4">
<widget class="Line" name="splashSeparator">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QLineEdit" name="profilebackupPath">
<property name="toolTip">
<string>If set it will override the application general setting</string>
</property>
<property name="readOnly">
<bool>false</bool>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="sdPathLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>SD Structure path</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="10" column="2" colspan="2">
<widget class="QPushButton" name="ProfilebackupPathButton">
<property name="toolTip">
<string>The profile specific folder, if set, will override general Backup folder</string>
</property>
<property name="text">
<string>Select Folder</string>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>General Settings</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_7">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Sans Serif</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Radio Type</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="langLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Menu Language</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLineEdit" name="sdPath">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string/>
</property>
<property name="readOnly">
<bool>false</bool>
</property>
</widget>
</item>
<item row="17" column="1">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="langCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
@@ -767,8 +713,8 @@ Mode 4:
<number>6</number>
</property>
<item row="7" column="1">
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="0">
<layout class="QVBoxLayout" name="updatesLayout">
<item>
<widget class="QCheckBox" name="autoCheckFirmware">
<property name="text">
<string>Automatic check for OpenTX firmware updates</string>
@@ -778,7 +724,7 @@ Mode 4:
</property>
</widget>
</item>
<item row="1" column="0">
<item>
<widget class="QCheckBox" name="autoCheckCompanion">
<property name="text">
<string>Automatic check for Companion updates</string>
@@ -788,7 +734,7 @@ Mode 4:
</property>
</widget>
</item>
<item row="2" column="0">
<item>
<widget class="QComboBox" name="OpenTxBranch">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@@ -1464,14 +1410,22 @@ Mode 4:
</widget>
</widget>
</item>
<item row="1" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>tabWidget</tabstop>
<tabstop>profileNameLE</tabstop>
<tabstop>downloadVerCB</tabstop>
<tabstop>langCombo</tabstop>
<tabstop>voiceCombo</tabstop>
<tabstop>sdPath</tabstop>
<tabstop>sdPathButton</tabstop>
<tabstop>profilebackupPath</tabstop>
+3 -3
View File
@@ -57,7 +57,7 @@ burnConfigDialog::burnConfigDialog(QWidget *parent) :
ui->label_sb1->hide();
ui->label_sb3->hide();
ui->samba_location->hide();
ui->samba_port->hide();
ui->samba_port->hide();
ui->sb_browse->hide();
}
else if (IS_SKY9X(board)) {
@@ -181,7 +181,7 @@ void burnConfigDialog::getSettings()
ui->pushButton_3->setEnabled(true);
} else {
ui->pushButton_3->setDisabled(true);
}
}
}
void burnConfigDialog::putSettings()
@@ -358,7 +358,7 @@ void burnConfigDialog::on_advCtrChkB_toggled(bool checked)
else {
ui->label_av3->show();
ui->avrdude_mcu->show();
QMessageBox::warning(this, tr("Companion"),
QMessageBox::warning(this, CPN_STR_APP_NAME,
tr("<b><u>WARNING!</u></b><br>Normally CPU type is automatically selected according to the chosen firmware.<br>If you change the CPU type the resulting eeprom could be inconsistent."),
QMessageBox::Ok);
}
+132 -20
View File
@@ -22,6 +22,7 @@
#include <QDateTime>
#include <QDir>
#include <QFile>
#include <QMessageBox>
#include <QSplashScreen>
#if defined(JOYSTICKS) || defined(SIMU_AUDIO)
#include <SDL.h>
@@ -33,8 +34,10 @@
#include "mainwindow.h"
#include "version.h"
#include "appdata.h"
#include "simulatorinterface.h"
#include "storage.h"
#include "translations.h"
#include "helpers.h"
#ifdef __APPLE__
#include <QProxyStyle>
@@ -51,6 +54,84 @@ class MyProxyStyle : public QProxyStyle
};
#endif
void importError()
{
QMessageBox::critical(nullptr, CPN_STR_APP_NAME, QCoreApplication::translate("Companion", "The saved settings could not be imported, please try again or continue with current settings."), QMessageBox::Ok, 0);
}
void checkSettingsImport(bool force = false)
{
QString previousVersion;
bool found;
if (!(found = g.findPreviousVersionSettings(&previousVersion))) {
found = QDir(CPN_SETTINGS_BACKUP_DIR).entryList(QStringList({"*.ini"}), QDir::Files).size() > 0;
}
if (!found && !force)
return;
const QString impFileBtn = QCoreApplication::translate("Companion", "Import from File");
const QString impPrevBtn = QCoreApplication::translate("Companion", "Import from v%1").arg(previousVersion);
const QString impNoneBtn = QCoreApplication::translate("Companion", "Do not import");
QString msg;
if (previousVersion.isEmpty()) {
if (found)
msg = QCoreApplication::translate("Companion", "We have found possible Companion settings backup file(s).\nDo you want to import settings from a file?");
else
msg = QCoreApplication::translate("Companion", "Import settings from a file, or start with current values.");
}
else {
msg = QCoreApplication::translate("Companion", "We have found existing settings for Companion version: %1.\nDo you want to import them?\n\n" \
"If you have a settings backup file, you may import that instead.").arg(previousVersion);
}
const int ret = QMessageBox::question(nullptr, CPN_STR_APP_NAME, msg, impNoneBtn, impFileBtn, (previousVersion.isEmpty() ? QString() : impPrevBtn), 0, 0);
if (!ret)
return;
// Import from previous version
if (ret == 2) {
if (!g.importSettings(previousVersion)) {
// very unlikely, but just in case of unexpected error, restart the import
importError();
checkSettingsImport();
}
return;
}
// Import from file
bool err = false;
QString impFile = CPN_SETTINGS_BACKUP_DIR;
impFile = QFileDialog::getOpenFileName(nullptr, QCoreApplication::translate("Companion", "Select %1:").arg(CPN_STR_APP_SETTINGS_FILES), impFile, CPN_STR_APP_SETTINGS_FILTER);
if (!impFile.isEmpty() && QFileInfo(impFile).isReadable()) {
QSettings fromSettings(impFile, QSettings::IniFormat);
if (g.importSettings(&fromSettings)) {
return;
}
else {
importError();
err = true;
}
}
// Restart the import prompt if user cancelled the file select dialog but we do have previous settings, or if we had a file import error.
if (err || !previousVersion.isEmpty())
checkSettingsImport();
}
void printHelpText()
{
printf(qPrintable(QString(APP_COMPANION % " v%s\n\n")), VERSION);
const char tmpl[] = " %s \t %s\n";
printf(tmpl, "--export", QCoreApplication::translate("Companion", "Save application settings to file...").toUtf8().constData());
printf(tmpl, "--import", QCoreApplication::translate("Companion", "Load application settings from file or previous version...").toUtf8().constData());
printf(tmpl, "--defaults", QCoreApplication::translate("Companion", "Reset ALL application settings to default and remove radio profiles...").toUtf8().constData());
printf(tmpl, "--quit ", QCoreApplication::translate("Companion", "Exit before settings initialization and application startup.").toUtf8().constData());
printf(tmpl, "--version", QCoreApplication::translate("Companion", "Print version number and exit.").toUtf8().constData());
printf(tmpl, "--help|-h", QCoreApplication::translate("Companion", "Print this help text.").toUtf8().constData());
fflush(stdout);
}
int main(int argc, char *argv[])
{
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
@@ -64,6 +145,19 @@ int main(int argc, char *argv[])
app.setOrganizationDomain(COMPANY_DOMAIN);
app.setAttribute(Qt::AA_DontShowIconsInMenus, false);
const QStringList args(QApplication::arguments());
if (args.contains("--help") || args.contains("-h") || args.contains("/?")) {
printHelpText();
exit(0);
}
if (args.contains("--version")) {
printf("%s\n", VERSION);
fflush(stdout);
exit(0);
}
Q_INIT_RESOURCE(companion);
if (AppDebugMessageHandler::instance())
@@ -71,28 +165,45 @@ int main(int argc, char *argv[])
CustomDebug::setFilterRules();
if (!g.hasCurrentSettings()) {
QString previousVersion;
if (g.findPreviousVersionSettings(&previousVersion)) {
QMessageBox msgBox;
msgBox.setText(QObject::tr("We have found existing settings for Companion version: %1.\nDo you want to import them?").arg(previousVersion));
msgBox.setIcon(QMessageBox::Information);
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::Yes);
int ret = msgBox.exec();
// handle settings export/import/reset via CLI
if (ret == QMessageBox::Yes)
g.importSettings(previousVersion);
bool doExport = args.contains("--export");
bool doImport = args.contains("--import");
bool doReset = args.contains("--defaults");
if (doExport)
Helpers::exportAppSettings();
if (doReset) {
char ok;
printf("%s [Y/N] ", QCoreApplication::translate("Companion", "Reset ALL application settings to default values and remove radio profiles, are you sure?").toUtf8().constData());
std::cin >> ok;
if (ok != 'Y' && ok != 'y')
exit(0);
if (!doExport) {
printf("%s [Y/N] ", QCoreApplication::translate("Companion", "Would you like to perform a backup first?").toUtf8().constData());
std::cin >> ok;
if (ok == 'Y' || ok == 'y')
Helpers::exportAppSettings();
}
g.resetAllSettings();
g.storeAllSettings();
std::cout << QCoreApplication::translate("Companion", "Application settings were reset and saved.").toUtf8().constData() << std::endl;
}
g.init();
QStringList strl = QApplication::arguments();
if (strl.contains("--version")) {
printf("%s\n", VERSION);
fflush(stdout);
if (doImport)
checkSettingsImport(true);
// give option to quit before settings init
if (args.contains("--quit"))
exit(0);
}
// end CLI handling
if (!doImport && g.isFirstUse())
checkSettingsImport(false);
g.init();
QFile dbgLog;
if (AppDebugMessageHandler::instance() && g.appDebugLog() && !g.appLogsDir().isEmpty() && QDir().mkpath(g.appLogsDir())) {
@@ -126,9 +237,10 @@ int main(int argc, char *argv[])
registerOpenTxFirmwares();
SimulatorLoader::registerSimulators();
if (g.profile[g.id()].fwType().isEmpty()){
g.profile[g.id()].fwType(Firmware::getDefaultVariant()->getId());
g.profile[g.id()].fwName("");
Profile & profile = g.currentProfile();
if (profile.fwType().isEmpty()){
profile.fwType(Firmware::getDefaultVariant()->getId());
profile.fwName("");
}
QString splashScreen;
+14 -1
View File
@@ -1,7 +1,7 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>images/customize.png</file>
<file>icon.png</file>
<file alias="icon.png">images/icon.png</file>
<file>../../CREDITS.txt</file>
<file>../releasenotes.txt</file>
<file>images/screenshot.png</file>
@@ -136,6 +136,18 @@
<file>images/simulator/X9E/right.png</file>
<file>images/simulator/X9E/right_enter.png</file>
<file>images/simulator/X9E/top.png</file>
<file>images/simulator/XLITE/bottom.png</file>
<file>images/simulator/XLITE/left.png</file>
<file>images/simulator/XLITE/left_scrnshot.png</file>
<file>images/simulator/XLITE/right.png</file>
<file>images/simulator/XLITE/right_ent.png</file>
<file>images/simulator/XLITE/top.png</file>
<file>images/simulator/XLITE/right_exit.png</file>
<file>images/simulator/XLITE/right_shift.png</file>
<file>images/simulator/XLITE/right_right.png</file>
<file>images/simulator/XLITE/right_left.png</file>
<file>images/simulator/XLITE/right_up.png</file>
<file>images/simulator/XLITE/right_down.png</file>
<file>images/wizard/ailerons.png</file>
<file>images/wizard/airbrakes.png</file>
<file>images/wizard/elevons.png</file>
@@ -235,6 +247,7 @@
<file>images/library/10802.png</file>
<file>themes/default/style.css</file>
<file>themes/default/style-osx.css</file>
<file>themes/default/modelprt.css</file>
<file>themes/monochrome/16/paintbrush.png</file>
<file>themes/monochrome/16/open.png</file>
<file>themes/monochrome/16/edit.png</file>
+8
View File
@@ -23,6 +23,7 @@
#include "appdata.h"
#include "helpers.h"
#include "modelslist.h"
#include "styleeditdialog.h"
#include <QPrinter>
#include <QPrintDialog>
@@ -189,3 +190,10 @@ void CompareDialog::on_printFileButton_clicked()
ui->textEdit->print(&printer);
}
}
void CompareDialog::on_styleButton_clicked()
{
StyleEditDialog *g = new StyleEditDialog(this, MODEL_PRINT_CSS);
if (g->exec() == QDialog::Accepted)
compare();
}
+1
View File
@@ -51,6 +51,7 @@ class CompareDialog : public QDialog
void removeModelBtnClicked();
void on_printButton_clicked();
void on_printFileButton_clicked();
void on_styleButton_clicked();
protected:
virtual void closeEvent(QCloseEvent * event);
+10
View File
@@ -43,6 +43,9 @@
<property name="text">
<string>To compare models, drag and drop them anywhere in this window.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
@@ -65,6 +68,13 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="styleButton">
<property name="text">
<string>Style</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="printButton">
<property name="text">
+12 -8
View File
@@ -49,6 +49,12 @@
#define CPN_MAX_MOUSE_ANALOGS 2
#define CPN_MAX_ANALOGS (CPN_MAX_STICKS + CPN_MAX_POTS + CPN_MAX_MOUSE_ANALOGS)
#define CPN_STR_APP_NAME QCoreApplication::translate("Companion", "OpenTX Companion")
#define CPN_STR_TTL_INFO QCoreApplication::translate("Companion", "Information") // shared Title Case words, eg. for a window title or section heading
#define CPN_STR_TTL_WARNING QCoreApplication::translate("Companion", "Warning")
#define CPN_STR_TTL_ERROR QCoreApplication::translate("Companion", "Error")
#define CPN_STR_TTL_CONFIRM QCoreApplication::translate("Companion", "Please Confirm")
#define CPN_STR_FILES QCoreApplication::translate("Companion", "files")
#define CPN_STR_RAD_MOD_SETTINGS QCoreApplication::translate("Companion", "Radio and Models settings")
#define HEX_FILES_FILTER "HEX " % CPN_STR_FILES % " (*.hex);;"
@@ -63,17 +69,15 @@
#define EEPE_EEPROM_FILE_HEADER "EEPE EEPROM FILE"
#define EEPE_MODEL_FILE_HEADER "EEPE MODEL FILE"
#define CPN_STR_APP_SETTINGS QCoreApplication::translate("Companion", "Application Settings")
#define CPN_STR_APP_SETTINGS_FILES CPN_STR_APP_SETTINGS % " " % CPN_STR_FILES
#define CPN_STR_APP_SETTINGS_FILTER CPN_STR_APP_SETTINGS_FILES % " (*.ini)"
#define CPN_STR_UNKNOWN_ITEM "???"
#define CPN_STR_SW_INDICATOR_UP QCoreApplication::translate("RawSwitch", "\xE2\x86\x91") // Switch up position indicator: Up arrow, or similar.
#define CPN_STR_SW_INDICATOR_DN QCoreApplication::translate("RawSwitch", "\xE2\x86\x93") // Switch down position indicator: Down arrow, or similar.
#define CPN_STR_SW_INDICATOR_NEUT QCoreApplication::translate("RawSwitch", "-") // Switch neutral (middle) position indicator.
#define CPN_STR_SW_INDICATOR_REV QCoreApplication::translate("RawSwitch", "!") // Switch reversed logic (NOT) indicator.
enum DownloadBranchType {
BRANCH_RELEASE_STABLE,
BRANCH_RC_TESTING,
BRANCH_NIGHTLY_UNSTABLE
};
Q_DECLARE_METATYPE(DownloadBranchType)
#endif // _CONSTANTS_H_
+10 -10
View File
@@ -74,7 +74,7 @@ bool Side::displayImage(QString fileName, Source pictSource)
if (pictSource== PICT)
*format = image.width()>WIDTH_9X ? LCDTARANIS : LCD9X;
else if (pictSource == PROFILE)
*format = (g.profile[g.id()].fwType().contains("x9")) ? LCDTARANIS : LCD9X;
*format = (g.profile[g.id()].fwType().contains("x9")) ? LCDTARANIS : LCD9X;
}
if (image.isNull()) {
@@ -88,17 +88,17 @@ bool Side::displayImage(QString fileName, Source pictSource)
switch (pictSource) {
case FW:
fileNameEdit->setText(QObject::tr("FW: %1").arg(fileName));
fileNameEdit->setText(CustomizeSplashDialog::tr("FW: %1").arg(fileName));
*saveToFileName = fileName;
*source = FW;
break;
case PICT:
fileNameEdit->setText(QObject::tr("Pict: %1").arg(fileName));
fileNameEdit->setText(CustomizeSplashDialog::tr("Pict: %1").arg(fileName));
*saveToFileName = fileName;
*source = PICT;
break;
case PROFILE:
fileNameEdit->setText(QObject::tr("Profile image"));
fileNameEdit->setText(CustomizeSplashDialog::tr("Profile image"));
*saveToFileName = fileName;
*source = PROFILE;
break;
@@ -158,7 +158,7 @@ CustomizeSplashDialog::CustomizeSplashDialog(QWidget *parent) :
setWindowIcon(CompanionIcon("paintbrush.png"));
ui->leftLibraryButton->setIcon(CompanionIcon("library.png"));
ui->rightLibraryButton->setIcon(CompanionIcon("library.png"));
left.imageLabel = ui->leftImageLabel;
right.imageLabel = ui->rightImageLabel;
left.fileNameEdit = ui->leftFileNameEdit;
@@ -169,7 +169,7 @@ CustomizeSplashDialog::CustomizeSplashDialog(QWidget *parent) :
right.libraryButton = ui->rightLibraryButton;
left.invertButton = ui->leftInvertButton;
right.invertButton = ui->rightInvertButton;
left.loadFwButton = ui->leftLoadFwButton;
right.loadFwButton = ui->rightLoadFwButton;
left.loadPictButton = ui->leftLoadPictButton;
@@ -203,7 +203,7 @@ void CustomizeSplashDialog::loadFirmware(Side side)
QString fileName = QFileDialog::getOpenFileName(this, tr("Open Firmware File"), g.flashDir(), FLASH_FILES_FILTER);
if (!fileName.isEmpty()) {
if (!side.displayImage( fileName, FW ))
QMessageBox::critical(this, tr("Error"), tr("Can not load embedded image from firmware file %1.").arg(fileName));
QMessageBox::critical(this, CPN_STR_TTL_ERROR, tr("Can not load embedded image from firmware file %1.").arg(fileName));
else
g.flashDir( QFileInfo(fileName).dir().absolutePath() );
}
@@ -223,7 +223,7 @@ void CustomizeSplashDialog::loadPicture(Side side)
if (!fileName.isEmpty()) {
if (!side.displayImage( fileName, PICT ))
QMessageBox::critical(this, tr("Error"), tr("Cannot load the image file %1.").arg(fileName));
QMessageBox::critical(this, CPN_STR_TTL_ERROR, tr("Cannot load the image file %1.").arg(fileName));
else
g.imagesDir( QFileInfo(fileName).dir().absolutePath() );
}
@@ -238,7 +238,7 @@ void CustomizeSplashDialog::loadProfile(Side side)
if (!fileName.isEmpty()) {
if (!side.displayImage( fileName, PROFILE ))
QMessageBox::critical(this, tr("Error"), tr("Cannot load profile image %1.").arg(fileName));
QMessageBox::critical(this, CPN_STR_TTL_ERROR, tr("Cannot load profile image %1.").arg(fileName));
}
side.markSourceButton();
}
@@ -252,7 +252,7 @@ void CustomizeSplashDialog::libraryButton_clicked( Side side )
ld->exec();
if (!fileName.isEmpty()) {
if (!side.displayImage( fileName, UNDEFINED ))
QMessageBox::critical(this, tr("Error"), tr("Cannot load the library image %1.").arg(fileName));
QMessageBox::critical(this, CPN_STR_TTL_ERROR, tr("Cannot load the library image %1.").arg(fileName));
}
}
+24
View File
@@ -0,0 +1,24 @@
set(datamodels_SRCS
rawitemdatamodels.cpp
rawitemfilteredmodel.cpp
)
set(datamodels_HDRS
rawitemdatamodels.h
rawitemfilteredmodel.h
)
qt5_wrap_cpp(datamodels_SRCS ${datamodels_HDRS})
add_library(datamodels ${datamodels_SRCS} ${datamodels_HDRS})
target_link_libraries(datamodels PRIVATE ${CPN_COMMON_LIB})
target_include_directories(datamodels
PRIVATE
"${CMAKE_SOURCE_DIR}"
"${CMAKE_CURRENT_BINARY_DIR}"
"${COMPANION_SRC_DIRECTORY}"
PUBLIC
"${CMAKE_CURRENT_LIST_DIR}"
)
@@ -0,0 +1,172 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "rawitemdatamodels.h"
#include "generalsettings.h"
#include "eeprominterface.h"
#include "modeldata.h"
RawSourceItemModel::RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) :
AbstractRawItemDataModel(generalSettings, modelData, parent)
{
const Boards board = Boards(getCurrentBoard());
Firmware * fw = getCurrentFirmware();
const int anasCount = CPN_MAX_STICKS + board.getCapability(Board::Pots) + board.getCapability(Board::Sliders) + board.getCapability(Board::MouseAnalogs);
addItems(SOURCE_TYPE_NONE, RawSource::NoneGroup, 1);
for (int i=0; i < fw->getCapability(LuaScripts); i++)
addItems(SOURCE_TYPE_LUA_OUTPUT, RawSource::ScriptsGroup, fw->getCapability(LuaOutputsPerScript), i * 16);
addItems(SOURCE_TYPE_VIRTUAL_INPUT, RawSource::InputsGroup, fw->getCapability(VirtualInputs));
addItems(SOURCE_TYPE_STICK, RawSource::SourcesGroup, anasCount);
addItems(SOURCE_TYPE_ROTARY_ENCODER, RawSource::SourcesGroup, fw->getCapability(RotaryEncoders));
addItems(SOURCE_TYPE_TRIM, RawSource::TrimsGroup, board.getCapability(Board::NumTrims));
addItems(SOURCE_TYPE_MAX, RawSource::SourcesGroup, 1);
addItems(SOURCE_TYPE_SWITCH, RawSource::SwitchesGroup, board.getCapability(Board::Switches));
addItems(SOURCE_TYPE_CUSTOM_SWITCH, RawSource::SwitchesGroup, fw->getCapability(LogicalSwitches));
addItems(SOURCE_TYPE_CYC, RawSource::SourcesGroup, CPN_MAX_CYC);
addItems(SOURCE_TYPE_PPM, RawSource::SourcesGroup, fw->getCapability(TrainerInputs));
addItems(SOURCE_TYPE_CH, RawSource::SourcesGroup, fw->getCapability(Outputs));
addItems(SOURCE_TYPE_SPECIAL, RawSource::TelemGroup, 5);
addItems(SOURCE_TYPE_TELEMETRY, RawSource::TelemGroup, CPN_MAX_SENSORS * 3);
addItems(SOURCE_TYPE_GVAR, RawSource::GVarsGroup, fw->getCapability(Gvars));
}
void RawSourceItemModel::setDynamicItemData(QStandardItem * item, const RawSource & src) const
{
Board::Type board = getCurrentBoard();
item->setText(src.toString(modelData, generalSettings, board));
item->setData(src.isAvailable(modelData, generalSettings, board), IsAvailableRole);
}
void RawSourceItemModel::addItems(const RawSourceType & type, const int group, const int count, const int start)
{
for (int i = start; i < start + count; i++) {
const RawSource src = RawSource(type, i);
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(src.toValue(), ItemIdRole);
modelItem->setData(type, ItemTypeRole);
modelItem->setData(group, ItemFlagsRole);
setDynamicItemData(modelItem, src);
appendRow(modelItem);
}
}
void RawSourceItemModel::update() const
{
for (int i=0; i < rowCount(); ++i)
setDynamicItemData(item(i), RawSource(item(i)->data(ItemIdRole).toInt()));
}
//
// RawSwitchItemModel
//
RawSwitchItemModel::RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) :
AbstractRawItemDataModel(generalSettings, modelData, parent)
{
Boards board = Boards(getCurrentBoard());
Firmware * fw = getCurrentFirmware();
// Descending switch direction: NOT (!) switches
addItems(SWITCH_TYPE_SENSOR, -CPN_MAX_SENSORS);
addItems(SWITCH_TYPE_TELEMETRY, -1);
addItems(SWITCH_TYPE_FLIGHT_MODE, -fw->getCapability(FlightModes));
addItems(SWITCH_TYPE_VIRTUAL, -fw->getCapability(LogicalSwitches));
addItems(SWITCH_TYPE_ROTARY_ENCODER, -fw->getCapability(RotaryEncoders));
addItems(SWITCH_TYPE_TRIM, -board.getCapability(Board::NumTrimSwitches));
addItems(SWITCH_TYPE_MULTIPOS_POT, -(board.getCapability(Board::MultiposPots) * board.getCapability(Board::MultiposPotsPositions)));
addItems(SWITCH_TYPE_SWITCH, -board.getCapability(Board::SwitchPositions));
// Ascending switch direction (including zero)
addItems(SWITCH_TYPE_TIMER_MODE, 5);
addItems(SWITCH_TYPE_NONE, 1);
addItems(SWITCH_TYPE_SWITCH, board.getCapability(Board::SwitchPositions));
addItems(SWITCH_TYPE_MULTIPOS_POT, board.getCapability(Board::MultiposPots) * board.getCapability(Board::MultiposPotsPositions));
addItems(SWITCH_TYPE_TRIM, board.getCapability(Board::NumTrimSwitches));
addItems(SWITCH_TYPE_ROTARY_ENCODER, fw->getCapability(RotaryEncoders));
addItems(SWITCH_TYPE_VIRTUAL, fw->getCapability(LogicalSwitches));
addItems(SWITCH_TYPE_FLIGHT_MODE, fw->getCapability(FlightModes));
addItems(SWITCH_TYPE_TELEMETRY, 1);
addItems(SWITCH_TYPE_SENSOR, CPN_MAX_SENSORS);
addItems(SWITCH_TYPE_ON, 1);
addItems(SWITCH_TYPE_ONE, 1);
}
void RawSwitchItemModel::setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const
{
const Board::Type board = getCurrentBoard();
item->setText(rsw.toString(board, generalSettings, modelData));
item->setData(rsw.isAvailable(modelData, generalSettings, board), IsAvailableRole);
}
void RawSwitchItemModel::addItems(const RawSwitchType & type, int count)
{
// Most RawSwitch() indices are one-based (vs. typical zero); these are exceptions to the rule:
const static QVector<int> rawSwitchIndexBaseZeroTypes = QVector<int>() << SWITCH_TYPE_NONE << SWITCH_TYPE_ON << SWITCH_TYPE_OFF << SWITCH_TYPE_TIMER_MODE;
// handle exceptions in RawSwitch() index values
const short rawIdxAdj = rawSwitchIndexBaseZeroTypes.contains(type) ? -1 : 0;
// determine cotext flags
int context = RawSwitch::AllSwitchContexts;
switch (type) {
case SWITCH_TYPE_FLIGHT_MODE:
context &= ~RawSwitch::MixesContext;
// fallthrough
case SWITCH_TYPE_VIRTUAL:
case SWITCH_TYPE_SENSOR:
context &= ~RawSwitch::GlobalFunctionsContext;
break;
case SWITCH_TYPE_TIMER_MODE:
context = RawSwitch::TimersContext;
break;
case SWITCH_TYPE_NONE:
context &= ~RawSwitch::TimersContext;
break;
case SWITCH_TYPE_ON:
case SWITCH_TYPE_ONE:
context = RawSwitch::SpecialFunctionsContext | RawSwitch::GlobalFunctionsContext;
break;
default:
break;
}
int i = (count < 0 ? count : 1);
count = (i < 0 ? 0 : count + i);
for ( ; i < count; ++i) {
RawSwitch rs(type, i + rawIdxAdj);
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(rs.toValue(), ItemIdRole);
modelItem->setData(type, ItemTypeRole);
modelItem->setData(context, ItemFlagsRole);
setDynamicItemData(modelItem, rs);
appendRow(modelItem);
}
}
void RawSwitchItemModel::update() const
{
for (int i=0; i < rowCount(); ++i)
setDynamicItemData(item(i), RawSwitch(item(i)->data(ItemIdRole).toInt()));
}
@@ -0,0 +1,84 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef RAWITEMDATAMODELS_H
#define RAWITEMDATAMODELS_H
#include "rawsource.h"
#include "rawswitch.h"
#include <QStandardItemModel>
class GeneralSettings;
class ModelData;
class AbstractRawItemDataModel: public QStandardItemModel
{
Q_OBJECT
public:
enum DataRoles { ItemIdRole = Qt::UserRole, ItemTypeRole, ItemFlagsRole, IsAvailableRole };
Q_ENUM(DataRoles)
explicit AbstractRawItemDataModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr) :
QStandardItemModel(parent),
generalSettings(generalSettings),
modelData(modelData)
{}
public slots:
virtual void update() const = 0;
protected:
const GeneralSettings * generalSettings;
const ModelData * modelData;
};
class RawSourceItemModel: public AbstractRawItemDataModel
{
Q_OBJECT
public:
explicit RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr);
public slots:
void update() const override;
protected:
void setDynamicItemData(QStandardItem * item, const RawSource & src) const;
void addItems(const RawSourceType & type, const int group, const int count, const int start = 0);
};
class RawSwitchItemModel: public AbstractRawItemDataModel
{
Q_OBJECT
public:
explicit RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr);
public slots:
void update() const override;
protected:
void setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const;
void addItems(const RawSwitchType & type, int count);
};
#endif // RAWITEMDATAMODELS_H
@@ -0,0 +1,74 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "rawitemfilteredmodel.h"
#include "rawitemdatamodels.h"
RawItemFilteredModel::RawItemFilteredModel(QAbstractItemModel * sourceModel, int flags, QObject * parent) :
QSortFilterProxyModel(parent),
filterFlags(0)
{
setFilterRole(AbstractRawItemDataModel::IsAvailableRole);
setFilterKeyColumn(0);
setFilterFlags(flags);
setDynamicSortFilter(true);
setSourceModel(sourceModel);
}
void RawItemFilteredModel::setFilterFlags(int flags)
{
if (filterFlags != flags) {
filterFlags = flags;
invalidateFilter();
}
}
bool RawItemFilteredModel::filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const
{
const QModelIndex & srcIdx = sourceModel()->index(sourceRow, 0, sourceParent);
if (!srcIdx.isValid() || !sourceModel()->data(srcIdx, filterRole()).toBool())
return false;
if (!filterFlags)
return true;
bool ok;
const int flags = sourceModel()->data(srcIdx, AbstractRawItemDataModel::ItemFlagsRole).toInt(&ok);
return (ok && (!flags || (filterFlags & flags)));
}
void RawItemFilteredModel::update() const
{
AbstractRawItemDataModel * model = qobject_cast<AbstractRawItemDataModel *>(sourceModel());
if (model)
model->update();
}
RawSourceFilterItemModel::RawSourceFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, int flags, QObject * parent) :
RawItemFilteredModel(new RawSourceItemModel(generalSettings, modelData, parent), flags, parent)
{
}
RawSwitchFilterItemModel::RawSwitchFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, int context, QObject * parent) :
RawItemFilteredModel(new RawSwitchItemModel(generalSettings, modelData, parent), context, parent)
{
}
@@ -0,0 +1,74 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef RAWITEMFILTEREDMODEL_H
#define RAWITEMFILTEREDMODEL_H
#include <QSortFilterProxyModel>
class GeneralSettings;
class ModelData;
class RawSourceItemModel;
class RawSwitchItemModel;
class RawItemFilteredModel: public QSortFilterProxyModel
{
Q_OBJECT
public:
explicit RawItemFilteredModel(QAbstractItemModel * sourceModel, int flags, QObject * parent = nullptr);
explicit RawItemFilteredModel(QAbstractItemModel * sourceModel, QObject * parent = nullptr) : RawItemFilteredModel(sourceModel, 0, parent) {}
public slots:
void setFilterFlags(int flags);
void update() const;
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const override;
int filterFlags;
};
// The specialized "convenience" types below can go away once centralalized RawSource/RawSwitch item models are established.
// These proxy classes will automatically create a source model of the corresponding type.
class RawSwitchFilterItemModel: public RawItemFilteredModel
{
Q_OBJECT
public:
using RawItemFilteredModel::RawItemFilteredModel;
explicit RawSwitchFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, int context, QObject * parent = nullptr);
};
class RawSourceFilterItemModel: public RawItemFilteredModel
{
Q_OBJECT
public:
using RawItemFilteredModel::RawItemFilteredModel;
explicit RawSourceFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, int flags, QObject * parent = nullptr);
explicit RawSourceFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr) :
RawSourceFilterItemModel(generalSettings, modelData, 0, parent) {}
};
#endif // RAWITEMFILTEREDMODEL_H
+502
View File
@@ -0,0 +1,502 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "filesyncdialog.h"
#include "autobitsetcheckbox.h"
#include "autocheckbox.h"
#include "autocombobox.h"
#include "autolineedit.h"
#include "constants.h"
#include "helpers.h"
#include "progresswidget.h"
#include <QApplication>
#include <QComboBox>
#include <QCompleter>
#include <QCheckBox>
#include <QDir>
#include <QFileDialog>
#include <QFileSystemModel>
#include <QLayout>
#include <QLineEdit>
#include <QMenu>
#include <QSpinBox>
FileSyncDialog::FileSyncDialog(QWidget * parent, const SyncProcess::SyncOptions & syncOptions) :
QDialog(parent),
m_syncOptions(syncOptions),
m_running(false)
{
setWindowTitle(tr("Synchronize Files"));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setSizeGripEnabled(true);
setupUi();
toggleExtraOptions(false);
validate();
updateRunningState();
}
void FileSyncDialog::reject()
{
// override close event via window system close or esc. key
if (m_running) {
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Are you sure you wish to abort the sync?")) == QMessageBox::No)
return;
emit stopSync();
// Force termination if the sync hasn't finished within 5s
QElapsedTimer tim;
tim.start();
while (!tim.hasExpired(5000) && m_running)
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 10);
if (m_running)
qWarning() << "Terminating thread while Sync process was still running.";
}
QDialog::reject();
}
// Create a widget with a line edit and folder select button and handles all interactions. Features autosuggest
// path hints while typing, invalid paths shown in red.
// This should probably be moved some place more reusable, esp. the QFileSystemModel.
static QWidget * folderSelectorWidget(QLineEdit * le, QWidget * parent)
{
static QFileSystemModel fileModel;
static bool init = false;
if (!init) {
init = true;
fileModel.setFilter(QDir::Dirs);
fileModel.setRootPath("/");
}
QWidget * fsw = new QWidget(parent);
//le = new QLineEdit(parent);
QCompleter * fsc = new QCompleter(fsw);
fsc->setModel(&fileModel);
//fsc->setCompletionMode(QCompleter::InlineCompletion);
le->setCompleter(fsc);
QToolButton * btn = new QToolButton(fsw);
btn->setIcon(CompanionIcon("open.png"));
QHBoxLayout * l = new QHBoxLayout(fsw);
l->setContentsMargins(0,0,0,0);
l->setSpacing(3);
l->addWidget(le);
l->addWidget(btn);
QObject::connect(btn, &QToolButton::clicked, [=]() {
QString dir = QFileDialog::getExistingDirectory(parent, fsw->property("fileDialogTitle").toString(), le->text(), 0);
if (!dir.isEmpty()) {
le->setText(QDir::toNativeSeparators(dir));
le->setFocus();
}
});
QObject::connect(le, &QLineEdit::textChanged, [=](const QString & text) {
if (QFile::exists(text))
le->setStyleSheet("");
else
le->setStyleSheet("QLineEdit {color: red;}");
});
return fsw;
}
void FileSyncDialog::setupUi()
{
const QString srcArw = CPN_STR_SW_INDICATOR_UP % " ";
const QString dstArw = CPN_STR_SW_INDICATOR_DN % " ";
int row = 0;
CompanionIcon playIcon("play.png");
playIcon.addImage("stop.png", QIcon::Normal, QIcon::On);
QLabel * lblSrc = new QLabel(tr("Source Folder:"), this);
AutoLineEdit * leSrc = new AutoLineEdit(this, true);
leSrc->setField(m_syncOptions.folderA);
leSrc->setText(QDir::toNativeSeparators(m_syncOptions.folderA));
QWidget * wdgSrc = folderSelectorWidget(leSrc, this);
QLabel * lblDst = new QLabel(tr("Destination Folder:"), this);
AutoLineEdit * leDst = new AutoLineEdit(this, true);
leDst->setField(m_syncOptions.folderB);
leDst->setText(QDir::toNativeSeparators(m_syncOptions.folderB));
QWidget * wdgDst = folderSelectorWidget(leDst, this);
AutoComboBox * syncDir = new AutoComboBox(this);
syncDir->addItem(tr("%1%2 Both directions, to destination folder first").arg(dstArw, srcArw), SyncProcess::SYNC_A2B_B2A);
syncDir->addItem(tr("%1%2 Both directions, to source folder first").arg(srcArw, dstArw), SyncProcess::SYNC_B2A_A2B);
syncDir->addItem(tr(" %1 Only from source folder to destination folder").arg(dstArw), SyncProcess::SYNC_A2B);
syncDir->addItem(tr(" %1 Only from destination folder to source folder").arg(srcArw), SyncProcess::SYNC_B2A);
syncDir->setCurrentIndex(-1); // we set the default option later
AutoComboBox * copyMode = new AutoComboBox(this);
copyMode->setToolTip(tr("How to handle overwriting files which already exist in the destination folder."));
copyMode->addItem(tr("Copy only if newer and different (compare contents)"), SyncProcess::OVERWR_NEWER_IF_DIFF);
copyMode->addItem(tr("Copy only if newer (do not compare contents)"), SyncProcess::OVERWR_NEWER_ALWAYS);
copyMode->addItem(tr("Copy only if different (ignore file time stamps)"), SyncProcess::OVERWR_IF_DIFF);
copyMode->addItem(tr("Always copy (force overwite existing files)"), SyncProcess::OVERWR_ALWAYS);
copyMode->setField(m_syncOptions.compareType);
QSpinBox * maxSize = new QSpinBox(this);
maxSize->setRange(0, 100 * 1024);
maxSize->setAccelerated(true);
maxSize->setSpecialValueText(tr("Any size"));
maxSize->setToolTip(tr("Skip files larger than this size. Enter zero for unlimited."));
maxSize->setGroupSeparatorShown(true);
maxSize->setValue(0); // we set the real default value later
AutoComboBox * logLevel = new AutoComboBox(this);
logLevel->setToolTip(tr("Minimum reporting level. Events of this type and of higher importance are shown.\n" \
"WARNING: High log rates may make the user interface temporarily unresponsive."));
logLevel->addItem(tr("Skipped"), QtDebugMsg);
logLevel->addItem(tr("Created"), QtInfoMsg);
logLevel->addItem(tr("Updated"), QtWarningMsg);
//logLevel->addItem(tr("Item Deleted"), QtCriticalMsg); // unused
logLevel->addItem(tr("Errors Only"), QtFatalMsg);
logLevel->setField(m_syncOptions.logLevel);
AutoBitsetCheckBox * testRun = new AutoBitsetCheckBox(m_syncOptions.flags, SyncProcess::OPT_DRY_RUN, tr("Test-run only"), this);
testRun->setToolTip(tr("Run as normal but do not actually copy anything. Useful for verifying results before real sync."));
// layout to hold size spinbox and checkbox option(s)
QHBoxLayout * hlay1 = new QHBoxLayout();
hlay1->addWidget(maxSize, 1);
hlay1->addWidget(testRun);
hlay1->addWidget(new QLabel(tr("Log Level:"), this));
hlay1->addWidget(logLevel);
// "extra" options
QLabel * lbFilter = new QLabel(tr("Filters:"), this);
lbFilter->setToolTip(tr("The \"Include\" filter will only copy files which match the pattern(s).\n" \
"The \"Exclude\" filter will skip files matching the filter pattern(s).\n" \
"The Include filter is evaluated first."));
AutoLineEdit * leFiltExc = new AutoLineEdit(this, true);
leFiltExc->setField(m_syncOptions.excludeFilter);
leFiltExc->setToolTip(tr("One or more file pattern(s) to exclude, separated by commas.\n" "Blank means exclude none. ?, *, and [...] wildcards accepted."));
AutoLineEdit * leFiltInc = new AutoLineEdit(this, true);
leFiltInc->setField(m_syncOptions.includeFilter);
leFiltInc->setToolTip(tr("One or more file pattern(s) to include, separated by commas.\n" "Blank means include all. ?, *, and [...] wildcards accepted."));
// layout to hold filter options
QHBoxLayout * filtLo = new QHBoxLayout();
filtLo->addWidget(new QLabel(tr("Include:"), this));
filtLo->addWidget(leFiltInc, 1);
filtLo->addWidget(new QLabel(tr("Exclude:"), this));
filtLo->addWidget(leFiltExc, 1);
// file options
QHBoxLayout * filOptsLo = new QHBoxLayout();
filOptsLo->addWidget(new AutoBitsetCheckBox(m_syncOptions.dirFilterFlags, QDir::CaseSensitive, tr("Case sensitive"), this));
filOptsLo->addWidget(new AutoBitsetCheckBox(m_syncOptions.dirFilterFlags, QDir::NoSymLinks, true, tr("Follow links"), this));
filOptsLo->addWidget(new AutoBitsetCheckBox(m_syncOptions.dirFilterFlags, QDir::Hidden, tr("Include hidden"), this));
// folder options
QHBoxLayout * dirOptsLo = new QHBoxLayout();
dirOptsLo->addWidget(new AutoBitsetCheckBox(m_syncOptions.flags, SyncProcess::OPT_RECURSIVE, tr("Recursive"), this));
dirOptsLo->addWidget(new AutoBitsetCheckBox(m_syncOptions.flags, SyncProcess::OPT_SKIP_DIR_LINKS, true, tr("Follow links"), this));
dirOptsLo->addWidget(new AutoBitsetCheckBox(m_syncOptions.dirFilterFlags, QDir::Dirs, true, tr("Skip empty"), this));
dirOptsLo->addWidget(new AutoBitsetCheckBox(m_syncOptions.dirFilterFlags, QDir::AllDirs, true, tr("Apply filters"), this));
// extra options container widget and layout
ui_extraOptions = new QWidget(this);
ui_extraOptions->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
QGridLayout * xOptsLay = new QGridLayout(ui_extraOptions);
xOptsLay->setContentsMargins(0, 0, 0, 0);
xOptsLay->addWidget(lbFilter, row, 0);
xOptsLay->addLayout(filtLo, row++, 1);
xOptsLay->addWidget(new QLabel(tr("Filter Options:"), this), row, 0);
xOptsLay->addLayout(filOptsLo, row++, 1);
xOptsLay->addWidget(new QLabel(tr("Folder Options:"), this), row, 0);
xOptsLay->addLayout(dirOptsLo, row++, 1);
// status label
ui_statusLabel = new QLabel(this);
// progress widget
ui_progress = new ProgressWidget(this);
ui_progress->setMinimumWidth(0);
ui_progress->setVisible(false);
// dialog buttons & menu
QMenu * optionsMenu = new QMenu(tr("Options"));
QAction * xtrasAct = optionsMenu->addAction(CompanionIcon("fuses.png"), tr("Show extra options"), this, &FileSyncDialog::toggleExtraOptions);
xtrasAct->setCheckable(true);
connect(this, &FileSyncDialog::extraOptionsToggled, xtrasAct, &QAction::setChecked);
optionsMenu->addAction(CompanionIcon("paintbrush.png"), tr("Reset to defaults"), this, &FileSyncDialog::resetOptions);
QToolButton * btnOpts = new QToolButton(this);
btnOpts->setDefaultAction(xtrasAct);
btnOpts->setMenu(optionsMenu);
btnOpts->setToolButtonStyle(Qt::ToolButtonIconOnly);
btnOpts->setPopupMode(QToolButton::MenuButtonPopup);
btnOpts->setToolTip(xtrasAct->text());
ui_btnStartStop = new QToolButton(this);
ui_btnStartStop->setCheckable(true);
ui_btnStartStop->setIcon(playIcon);
ui_btnStartStop->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
ui_btnClose = new QToolButton(this);
ui_btnClose->setText(tr("Close"));
ui_btnClose->setToolButtonStyle(Qt::ToolButtonTextOnly);
ui_btnClose->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
ui_buttonBox = new QDialogButtonBox(this);
ui_buttonBox->addButton(btnOpts, QDialogButtonBox::ActionRole);
ui_buttonBox->addButton(ui_btnStartStop, QDialogButtonBox::ActionRole);
ui_buttonBox->addButton(ui_btnClose, QDialogButtonBox::RejectRole);
// The options group box.
ui_optionsPanel = new QGroupBox(tr("Options"), this);
QGridLayout * optsLay = new QGridLayout(ui_optionsPanel);
row = 0;
optsLay->addWidget(lblSrc, row, 0);
optsLay->addWidget(wdgSrc, row++, 1);
optsLay->addWidget(lblDst, row, 0);
optsLay->addWidget(wdgDst, row++, 1);
optsLay->addWidget(new QLabel(tr("Sync. Direction:"), this), row, 0);
optsLay->addWidget(syncDir, row++, 1);
optsLay->addWidget(new QLabel(tr("Existing Files:"), this), row, 0);
optsLay->addWidget(copyMode, row++, 1);
optsLay->addWidget(new QLabel(tr("Max. File Size:"), this), row, 0);
optsLay->addLayout(hlay1, row++, 1);
optsLay->addWidget(ui_extraOptions, row, 0, 1, 2);
// layout to hold warning label and button box
QHBoxLayout * hlay2 = new QHBoxLayout();
hlay2->addWidget(ui_statusLabel, 1);
hlay2->addWidget(ui_buttonBox);
// Create main layout and add options, progress, buttons.
QVBoxLayout * dlgL = new QVBoxLayout(this);
dlgL->addWidget(ui_optionsPanel, 0, Qt::AlignTop);
dlgL->addLayout(hlay2);
dlgL->addWidget(ui_progress, 1);
// Connect all signal handlers
// source path
connect(leSrc, &AutoLineEdit::textChanged, this, &FileSyncDialog::validate);
// destination path
connect(leDst, &AutoLineEdit::textChanged, this, &FileSyncDialog::validate);
// function to dis/enable the OVERWR_ALWAYS option depending on sync direction
connect(syncDir, &AutoComboBox::currentDataChanged, [=](int dir) {
int idx = copyMode->findData(SyncProcess::OVERWR_ALWAYS);
int flg = (dir == SyncProcess::SYNC_A2B || dir == SyncProcess::SYNC_B2A) ? 33 : 0;
if (!flg && idx == copyMode->currentIndex())
copyMode->setCurrentIndex(copyMode->findData(SyncProcess::OVERWR_NEWER_IF_DIFF));
copyMode->setItemData(idx, flg, Qt::UserRole - 1);
});
// function to set magnitude of file size spinbox, KB or MB
connect(maxSize, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), [=](int value) {
const QSignalBlocker blocker(maxSize);
int multi = maxSize->property("multi").isValid() ? maxSize->property("multi").toInt() : 0;
if (value >= 10 * 1024 && multi != 1024 * 1024) {
// KB -> MB
multi = 1024 * 1024;
maxSize->setValue(value / 1024);
maxSize->setMaximum(100);
maxSize->setSingleStep(1);
maxSize->setSuffix(tr(" MB"));
}
else if ((value < 10 && multi != 1024) || !multi) {
// MB -> KB
if (multi)
value *= 1024;
multi = 1024;
if (value == 9 * 1024)
value += 1024 - 32; // avoid large jump when stepping from 10MB to 10,208KB
maxSize->setMaximum(100 * 1024);
maxSize->setValue(value);
maxSize->setSingleStep(32);
maxSize->setSuffix(tr(" KB"));
}
maxSize->setProperty("multi", multi);
m_syncOptions.maxFileSize = value * multi;
});
// we set these after connections are made because we want the signal processors to run
syncDir->setField(m_syncOptions.direction);
maxSize->setValue(m_syncOptions.maxFileSize / 1024);
// connect Reset action to all fields
for (AutoLineEdit * a : ui_optionsPanel->findChildren<AutoLineEdit *>())
connect(this, &FileSyncDialog::optionsWereReset, a, &AutoLineEdit::updateValue);
for (AutoComboBox * a : ui_optionsPanel->findChildren<AutoComboBox *>())
connect(this, &FileSyncDialog::optionsWereReset, a, &AutoComboBox::updateValue);
for (AutoBitsetCheckBox * a : ui_optionsPanel->findChildren<AutoBitsetCheckBox *>())
connect(this, &FileSyncDialog::optionsWereReset, a, &AutoBitsetCheckBox::updateValue);
connect(this, &FileSyncDialog::optionsWereReset, [=]() { maxSize->setValue(m_syncOptions.maxFileSize / 1024); });
// React to name changes for source and destination path labels
connect(this, &FileSyncDialog::folderNameAChanged, [=](const QString &text) {
lblSrc->setText(text % ":");
wdgSrc->setProperty("fileDialogTitle", text);
});
connect(this, &FileSyncDialog::folderNameBChanged, [=](const QString &text) {
lblDst->setText(text % ":");
wdgDst->setProperty("fileDialogTitle", text);
});
// button actions
connect(ui_btnStartStop, &QPushButton::clicked, this, &FileSyncDialog::toggleSync);
connect(ui_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
connect(ui_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(ui_progress, &ProgressWidget::detailsToggled, this, &FileSyncDialog::adjustSizeDelayed);
}
void FileSyncDialog::toggleSync(bool)
{
if (m_running) {
setCursor(Qt::WaitCursor);
emit stopSync();
return;
}
ui_progress->clearDetails();
ui_progress->setInfo("");
SyncProcess * syncProcess = new SyncProcess(m_syncOptions);
// move sync process to separate thread, we only use signals/slots from here on...
QThread * syncThread = new QThread(this);
syncProcess->moveToThread(syncThread);
// ...and quite a few of them!
connect(this, &FileSyncDialog::startSync, syncProcess, &SyncProcess::run);
connect(this, &FileSyncDialog::stopSync, syncProcess, &SyncProcess::stop);
connect(syncProcess, &SyncProcess::started, this, &FileSyncDialog::onSyncStarted);
connect(syncProcess, &SyncProcess::finished, this, &FileSyncDialog::onSyncFinished);
connect(syncProcess, &SyncProcess::statusMessage, this, &FileSyncDialog::setStatusText);
connect(syncProcess, &SyncProcess::statusUpdate, this, &FileSyncDialog::onStatusUpdate);
connect(syncProcess, &SyncProcess::fileCountChanged, ui_progress, &ProgressWidget::setMaximum);
connect(syncProcess, &SyncProcess::progressMessage, ui_progress, &ProgressWidget::addMessage);
connect(syncProcess, &SyncProcess::finished, syncThread, &QThread::quit);
connect(syncThread, &QThread::finished, syncThread, &QThread::deleteLater);
connect(syncThread, &QThread::destroyed, syncProcess, &SyncProcess::deleteLater);
// go
syncThread->start(QThread::LowPriority);
emit startSync();
}
void FileSyncDialog::onSyncStarted()
{
m_running = true;
updateRunningState();
}
void FileSyncDialog::onSyncFinished()
{
m_running = false;
updateRunningState();
if (parentWidget())
QApplication::alert(parentWidget());
}
void FileSyncDialog::updateRunningState()
{
ui_btnStartStop->setChecked(m_running);
ui_optionsPanel->setEnabled(!m_running);
ui_btnClose->setEnabled(!m_running);
ui_btnStartStop->setText(m_running ? tr("Abort") : tr("Start"));
if (m_running) {
ui_progress->setVisible(true); // don't hide after run
}
else {
setCursor(Qt::ArrowCursor); // in case we set a wait cursor upon abort request
}
}
void FileSyncDialog::onStatusUpdate(const SyncProcess::SyncStatus & stat)
{
static const QString reportTemplate = tr("Total: <b>%1</b>; Created: <b>%2</b>; Updated: <b>%3</b>; Skipped: <b>%4</b>; Errors: <font color=%6><b>%5</b></font>;");
ui_progress->setInfo((stat.index < stat.count ? tr("Current: <b>%1</b> of ").arg(stat.index) : "") % reportTemplate.arg(stat.count).arg(stat.created).arg(stat.updated).arg(stat.skipped).arg(stat.errored).arg(stat.errored ? "red" : "black"));
ui_progress->setValue(stat.index);
}
void FileSyncDialog::setSyncOptions(const SyncProcess::SyncOptions & syncOptions)
{
m_syncOptions = syncOptions;
emit optionsWereReset();
}
void FileSyncDialog::resetOptions()
{
m_syncOptions.reset();
emit optionsWereReset();
}
void FileSyncDialog::toggleExtraOptions(bool show)
{
ui_extraOptions->setVisible(show);
if (!ui_progress->detailsVisible())
adjustSizeDelayed();
m_extraOptionsVisible = show;
emit extraOptionsToggled(show);
}
void FileSyncDialog::setFolderNameA(const QString & name)
{
if (m_folderNameA != name) {
m_folderNameA = name;
emit folderNameAChanged(name);
}
}
void FileSyncDialog::setFolderNameB(const QString & name)
{
if (m_folderNameB != name) {
m_folderNameB = name;
emit folderNameBChanged(name);
}
}
void FileSyncDialog::setStatusText(const QString & text, int type)
{
ui_statusLabel->setText(text);
ui_statusLabel->setStyleSheet(type != QtInfoMsg && type >= QtWarningMsg ? "QLabel { color: red; }:" : "");
}
bool FileSyncDialog::validate()
{
QString msg;
if (m_syncOptions.folderA.isEmpty() || !QFileInfo(m_syncOptions.folderA).exists())
msg = tr("Source folder not found.");
else if (m_syncOptions.folderB.isEmpty() || !QFileInfo(m_syncOptions.folderB).exists())
msg = tr("Destination folder not found.");
else if (QFileInfo(m_syncOptions.folderA).canonicalFilePath() == QFileInfo(m_syncOptions.folderB).canonicalFilePath())
msg = tr("Source and destination folders are the same.");
setStatusText(msg, QtCriticalMsg);
ui_btnStartStop->setEnabled(msg.isEmpty());
return msg.isEmpty();
}
void FileSyncDialog::adjustSizeDelayed()
{
QTimer::singleShot(0, [=]() { adjustSize(); });
}
+96
View File
@@ -0,0 +1,96 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef FILESYNCDIALOG_H
#define FILESYNCDIALOG_H
#include "process_sync.h"
#include <QDialog>
#include <QDialogButtonBox>
#include <QGroupBox>
#include <QLabel>
#include <QToolButton>
class ProgressWidget;
class FileSyncDialog : public QDialog
{
Q_OBJECT
Q_PROPERTY(SyncProcess::SyncOptions syncOptions READ syncOptions WRITE setSyncOptions RESET resetOptions NOTIFY optionsWereReset)
Q_PROPERTY(bool extraOptionsVisible READ extraOptionsVisible WRITE toggleExtraOptions NOTIFY extraOptionsToggled)
Q_PROPERTY(QString folderNameA READ folderNameA WRITE setFolderNameA NOTIFY folderNameAChanged)
Q_PROPERTY(QString folderNameB READ folderNameB WRITE setFolderNameB NOTIFY folderNameBChanged)
public:
FileSyncDialog(QWidget * parent = nullptr, const SyncProcess::SyncOptions & syncOptions = SyncProcess::SyncOptions());
inline SyncProcess::SyncOptions syncOptions() const { return m_syncOptions; }
void setSyncOptions(const SyncProcess::SyncOptions & syncOptions);
void resetOptions();
inline bool extraOptionsVisible() const { return m_extraOptionsVisible; }
void toggleExtraOptions(bool show);
inline QString folderNameA() const { return m_folderNameA; }
void setFolderNameA(const QString & name);
inline QString folderNameB() const { return m_folderNameB; }
void setFolderNameB(const QString & name);
public slots:
virtual void reject() override;
void setStatusText(const QString & text, int type = QtWarningMsg);
bool validate();
signals:
void startSync();
void stopSync();
void folderNameAChanged(const QString & name);
void folderNameBChanged(const QString & name);
void extraOptionsToggled(bool show);
void optionsWereReset();
private slots:
void setupUi();
void toggleSync(bool);
void onSyncStarted();
void onSyncFinished();
void updateRunningState();
void onStatusUpdate(const SyncProcess::SyncStatus & stat);
void adjustSizeDelayed();
private:
SyncProcess::SyncOptions m_syncOptions;
QString m_folderNameA;
QString m_folderNameB;
bool m_running;
bool m_extraOptionsVisible;
QGroupBox * ui_optionsPanel;
QWidget * ui_extraOptions;
ProgressWidget * ui_progress;
QDialogButtonBox * ui_buttonBox;
QToolButton * ui_btnStartStop;
QToolButton * ui_btnClose;
QLabel * ui_statusLabel;
};
#endif // FILESYNCDIALOG_H
+35 -22
View File
@@ -20,13 +20,17 @@
#include "downloaddialog.h"
#include "ui_downloaddialog.h"
#include <QTime>
#include "constants.h"
#include "helpers.h"
#include <QTime>
downloadDialog::downloadDialog(QWidget *parent, QString src, QString tgt):
QDialog(parent),
ui(new Ui::downloadDialog),
file(NULL)
reply(nullptr),
file(nullptr),
aborted(false)
{
ui->setupUi(this);
setWindowIcon(CompanionIcon("fwpreferences.png"));
@@ -41,7 +45,7 @@ downloadDialog::downloadDialog(QWidget *parent, QString src, QString tgt):
file = new QFile(tgt);
if (!file->open(QIODevice::WriteOnly)) {
QMessageBox::critical(this, "Companion",
QMessageBox::critical(this, CPN_STR_APP_NAME,
tr("Unable to save the file %1: %2.")
.arg(tgt).arg(file->errorString()));
QTimer::singleShot(0, this, SLOT(fileError()));
@@ -60,29 +64,38 @@ downloadDialog::~downloadDialog()
delete file;
}
void downloadDialog::reject()
{
if (reply && reply->isRunning()) {
aborted = true;
reply->abort(); // this will call QNetworkReply::finished()
return;
}
QDialog::reject();
}
void downloadDialog::httpFinished()
{
file->flush();
file->close();
file->flush();
file->close();
bool ok = true;
if (reply->error()) {
file->remove();
QMessageBox::information(this, tr("Companion"),
tr("Download failed: %1.")
.arg(reply->errorString()));
ok = false;
}
const bool ok = !(reply->error() || aborted);
if (!ok) {
file->remove();
if (!aborted)
QMessageBox::information(this, CPN_STR_APP_NAME, tr("Download failed: %1.").arg(reply->errorString()));
}
reply->deleteLater();
reply = 0;
delete file;
file = NULL;
reply->deleteLater();
reply = nullptr;
file->deleteLater();
file = nullptr;
if (ok)
accept();
else
reject();
if (ok)
accept();
else
reject();
}
void downloadDialog::httpReadyRead()
@@ -111,7 +124,7 @@ void downloadDialog::closeEvent( QCloseEvent * event)
// Delay closing 2 seconds to avoid unpleasant flashing download dialogs
QTime closeTime= QTime::currentTime().addSecs(2);
while( QTime::currentTime() < closeTime )
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
event->accept();
}
+4 -1
View File
@@ -39,6 +39,9 @@ public:
explicit downloadDialog(QWidget *parent = 0, QString src = "", QString tgt = "");
~downloadDialog();
public slots:
virtual void reject() override;
private slots:
void fileError();
void httpFinished();
@@ -54,7 +57,7 @@ private:
QNetworkAccessManager qnam;
QNetworkReply *reply;
QFile *file;
bool aborted;
};
#endif // _DOWNLOADDIALOG_H_
File diff suppressed because it is too large Load Diff
+46
View File
@@ -0,0 +1,46 @@
set(firmwares_SRCS
boards.cpp
curvereference.cpp
customfunctiondata.cpp
eeprominterface.cpp
generalsettings.cpp
gvardata.cpp
io_data.cpp
logicalswitchdata.cpp
modeldata.cpp
moduledata.cpp
multiprotocols.cpp
radiodata.cpp
radiodataconversionstate.cpp
rawsource.cpp
rawswitch.cpp
sensordata.cpp
telem_data.cpp
er9x/er9xeeprom.cpp
er9x/er9xinterface.cpp
ersky9x/ersky9xeeprom.cpp
ersky9x/ersky9xinterface.cpp
opentx/opentxeeprom.cpp
opentx/opentxinterface.cpp
)
string(REPLACE ".cpp" ".h" firmwares_HDRS "${firmwares_SRCS}")
list(APPEND firmwares_HDRS
eepromimportexport.h
moduledata.h
)
add_library(firmwares ${firmwares_SRCS} ${firmwares_HDRS})
target_link_libraries(firmwares ${CPN_COMMON_LIB} Qt5::Core Qt5::Xml Qt5::Widgets)
target_include_directories(firmwares
PRIVATE
${CMAKE_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
PUBLIC
"${CMAKE_CURRENT_LIST_DIR}"
"${CMAKE_CURRENT_LIST_DIR}/er9x"
"${CMAKE_CURRENT_LIST_DIR}/ersky9x"
"${CMAKE_CURRENT_LIST_DIR}/opentx"
)
@@ -53,6 +53,34 @@ void Boards::setBoardType(const Type & board)
m_boardType = BOARD_UNKNOWN;
}
uint32_t Boards::getFourCC(Type board)
{
switch (board) {
case BOARD_X12S:
return 0x3478746F;
case BOARD_X10:
return 0x3778746F;
case BOARD_TARANIS_XLITE:
return 0x3978746F;
case BOARD_TARANIS_X7:
return 0x3678746F;
case BOARD_TARANIS_X9E:
return 0x3578746F;
case BOARD_TARANIS_X9D:
case BOARD_TARANIS_X9DP:
return 0x3378746F;
case BOARD_SKY9X:
case BOARD_AR9X:
case BOARD_9XRPRO:
return 0x3278746F;
case BOARD_MEGA2560:
case BOARD_GRUVIN9X:
return 0x3178746F;
default:
return 0;
}
}
const int Boards::getEEpromSize(Board::Type board)
{
switch (board) {
@@ -68,11 +96,11 @@ const int Boards::getEEpromSize(Board::Type board)
case BOARD_9XRPRO:
case BOARD_AR9X:
return EESIZE_9XRPRO;
case BOARD_TARANIS_XLITE:
case BOARD_TARANIS_X7:
case BOARD_TARANIS_X9D:
case BOARD_TARANIS_X9DP:
case BOARD_TARANIS_X9E:
case BOARD_FLAMENCO:
return EESIZE_TARANIS;
case BOARD_UNKNOWN:
return EESIZE_MAX;
@@ -96,11 +124,11 @@ const int Boards::getFlashSize(Type board)
case BOARD_9XRPRO:
case BOARD_AR9X:
return FSIZE_9XRPRO;
case BOARD_TARANIS_XLITE:
case BOARD_TARANIS_X7:
case BOARD_TARANIS_X9D:
case BOARD_TARANIS_X9DP:
case BOARD_TARANIS_X9E:
case BOARD_TARANIS_X7:
case BOARD_FLAMENCO:
return FSIZE_TARANIS;
case BOARD_X12S:
case BOARD_X10:
@@ -112,8 +140,21 @@ const int Boards::getFlashSize(Type board)
}
}
const SwitchInfo Boards::getSwitchInfo(Board::Type board, unsigned index)
const SwitchInfo Boards::getSwitchInfo(Board::Type board, int index)
{
if (index < 0)
return {SWITCH_NOT_AVAILABLE, CPN_STR_UNKNOWN_ITEM};
if (IS_TARANIS_XLITE(board)) {
const Board::SwitchInfo switches[] = {
{SWITCH_3POS, "SA"},
{SWITCH_3POS, "SB"},
{SWITCH_2POS, "SC"},
{SWITCH_2POS, "SD"}
};
if (index < DIM(switches))
return switches[index];
}
if (IS_TARANIS_X7(board)) {
const Board::SwitchInfo switches[] = {
{SWITCH_3POS, "SA"},
@@ -164,7 +205,7 @@ const SwitchInfo Boards::getSwitchInfo(Board::Type board, unsigned index)
return switches[index];
}
return {SWITCH_NOT_AVAILABLE, "???"};
return {SWITCH_NOT_AVAILABLE, CPN_STR_UNKNOWN_ITEM};
}
const int Boards::getCapability(Board::Type board, Board::Capability capability)
@@ -174,13 +215,19 @@ const int Boards::getCapability(Board::Type board, Board::Capability capability)
return 4;
case Pots:
if (IS_TARANIS_X7(board))
if (IS_TARANIS_SMALL(board))
return 2;
else if (IS_TARANIS_X9E(board))
return 4;
else
return 3;
case FactoryInstalledPots:
if (IS_TARANIS_X9(board))
return 2;
else
return getCapability(board, Pots);
case Sliders:
if (IS_HORUS_X12S(board) || IS_TARANIS_X9E(board))
return 4;
@@ -195,11 +242,22 @@ const int Boards::getCapability(Board::Type board, Board::Capability capability)
else
return 0;
case MaxAnalogs:
return getCapability(board, Board::Sticks) + getCapability(board, Board::Pots) + getCapability(board, Board::Sliders) + getCapability(board, Board::MouseAnalogs);
case MultiposPots:
return IS_HORUS_OR_TARANIS(board) ? 3 : 0;
case MultiposPotsPositions:
return IS_HORUS_OR_TARANIS(board) ? 6 : 0;
case Switches:
if (IS_TARANIS_X9E(board))
return 18;
else if (IS_TARANIS_X7(board))
return 6;
else if (IS_TARANIS_XLITE(board))
return 4;
else if (IS_HORUS_OR_TARANIS(board))
return 8;
else
@@ -233,20 +291,104 @@ const int Boards::getCapability(Board::Type board, Board::Capability capability)
const QString Boards::getAxisName(int index)
{
const QString axes[] = {
QObject::tr("Left Horizontal"),
QObject::tr("Left Vertical"),
QObject::tr("Right Vertical"),
QObject::tr("Right Horizontal"),
QObject::tr("Aux. 1"),
QObject::tr("Aux. 2"),
tr("Left Horizontal"),
tr("Left Vertical"),
tr("Right Vertical"),
tr("Right Horizontal"),
tr("Aux. 1"),
tr("Aux. 2"),
};
if (index < (int)DIM(axes))
return axes[index];
else
return QObject::tr("Unknown");
return tr("Unknown");
}
/* Currently unused
const QString Boards::getAnalogInputName(Board::Type board, int index)
{
if (index < 0)
return CPN_STR_UNKNOWN_ITEM;
if (index < getBoardCapability(board, Board::Sticks)) {
const QString sticks[] = {
tr("Rud"),
tr("Ele"),
tr("Thr"),
tr("Ail")
};
return sticks[index];
}
index -= getCapability(board, Board::Sticks);
if (IS_9X(board) || IS_2560(board) || IS_SKY9X(board)) {
const QString pots[] = {
"P1",
"P2",
"P3"
};
if (index < DIM(pots))
return pots[index];
}
else if (IS_TARANIS_X9E(board)) {
const QString pots[] = {
"F1",
"F2",
"F3",
"F4",
"S1",
"S2",
"LS",
"RS"
};
if (index < DIM(pots))
return pots[index];
}
else if (IS_TARANIS(board)) {
const QString pots[] = {
"S1",
"S2",
"S3",
"LS",
"RS"
};
if (index < DIM(pots))
return pots[index];
}
else if (IS_HORUS_X12S(board)) {
const QString pots[] = {
"S1",
"6P",
"S2",
"L1",
"L2",
"LS",
"RS",
"JSx",
"JSy"
};
if (index < DIM(pots))
return pots[index];
}
else if (IS_HORUS_X10(board)) {
const QString pots[] = {
"S1",
"6P",
"S2",
"LS",
"RS"
};
if (index < DIM(pots))
return pots[index];
}
return CPN_STR_UNKNOWN_ITEM;
}
const bool Boards::isBoardCompatible(Type board1, Type board2)
{
return (getFourCC(board1) == getFourCC(board2));
}
const QString Boards::getBoardName(Board::Type board)
{
@@ -260,7 +402,9 @@ const QString Boards::getBoardName(Board::Type board)
case BOARD_MEGA2560:
return "MEGA2560";
case BOARD_TARANIS_X7:
return "Taranis X7";
return "Taranis X7/X7S";
case BOARD_TARANIS_XLITE:
return "Taranis X-Lite";
case BOARD_TARANIS_X9D:
return "Taranis X9D";
case BOARD_TARANIS_X9DP:
@@ -274,11 +418,10 @@ const QString Boards::getBoardName(Board::Type board)
case BOARD_AR9X:
return "AR9X";
case BOARD_X12S:
return "Horus";
return "Horus X12S";
case BOARD_X10:
return "X10";
return "Horus X10/X10S";
default:
return QObject::tr("Unknown");
return tr("Unknown");
}
}
*/
@@ -21,6 +21,7 @@
#ifndef _BOARDS_H_
#define _BOARDS_H_
#include <QtCore>
#include <QObject>
#include <QString>
@@ -42,9 +43,9 @@ namespace Board {
BOARD_TARANIS_X9D,
BOARD_TARANIS_X9DP,
BOARD_TARANIS_X9E,
BOARD_FLAMENCO,
BOARD_X12S,
BOARD_X10,
BOARD_TARANIS_XLITE,
BOARD_ENUM_COUNT
};
@@ -108,8 +109,12 @@ namespace Board {
enum Capability {
Sticks,
Pots,
FactoryInstalledPots,
Sliders,
MouseAnalogs,
MaxAnalogs,
MultiposPots,
MultiposPotsPositions,
Switches,
SwitchPositions,
FactoryInstalledSwitches,
@@ -137,6 +142,8 @@ namespace Board {
class Boards
{
Q_DECLARE_TR_FUNCTIONS(Boards)
public:
Boards(Board::Type board)
@@ -147,16 +154,23 @@ class Boards
void setBoardType(const Board::Type & board);
Board::Type getBoardType() const { return m_boardType; }
const int getEEpromSize() { return getEEpromSize(m_boardType); }
const int getFlashSize() { return getFlashSize(m_boardType); }
const Board::SwitchInfo getSwitchInfo(unsigned index) { return getSwitchInfo(m_boardType, index); }
const int getCapability(Board::Capability capability) { return getCapability(m_boardType, capability); }
const uint32_t getFourCC() const { return getFourCC(m_boardType); }
const int getEEpromSize() const { return getEEpromSize(m_boardType); }
const int getFlashSize() const { return getFlashSize(m_boardType); }
const Board::SwitchInfo getSwitchInfo(int index) const { return getSwitchInfo(m_boardType, index); }
const int getCapability(Board::Capability capability) const { return getCapability(m_boardType, capability); }
const QString getAnalogInputName(int index) const { return getAnalogInputName(m_boardType, index); }
const bool isBoardCompatible(Board::Type board2) const { return isBoardCompatible(m_boardType, board2); }
static uint32_t getFourCC(Board::Type board);
static const int getEEpromSize(Board::Type board);
static const int getFlashSize(Board::Type board);
static const Board::SwitchInfo getSwitchInfo(Board::Type board, unsigned index);
static const Board::SwitchInfo getSwitchInfo(Board::Type board, int index);
static const int getCapability(Board::Type board, Board::Capability capability);
static const QString getAxisName(int index);
static const QString getAnalogInputName(Board::Type board, int index);
static const bool isBoardCompatible(Board::Type board1, Board::Type board2);
static const QString getBoardName(Board::Type board);
protected:
@@ -165,27 +179,28 @@ class Boards
// temporary aliases for transition period, use Boards class instead.
#define getBoardCapability(b__, c__) Boards::getCapability(b__, c__)
#define getEEpromSize(b__) Boards::getEEpromSize(b__)
#define getSwitchInfo(b__, i__) Boards::getSwitchInfo(b__, i__)
#define IS_9X(board) (board==Board::BOARD_STOCK || board==Board::BOARD_M128)
#define IS_STOCK(board) (board==Board::BOARD_STOCK)
#define IS_M128(board) (board==Board::BOARD_M128)
#define IS_2560(board) (board==Board::BOARD_GRUVIN9X || board==Board::BOARD_MEGA2560)
#define IS_SKY9X(board) (board==Board::BOARD_SKY9X || board==Board::BOARD_9XRPRO || board==Board::BOARD_AR9X)
#define IS_9XRPRO(board) (board==Board::BOARD_9XRPRO)
#define IS_TARANIS_XLITE(board) (board==Board::BOARD_TARANIS_XLITE)
#define IS_TARANIS_X7(board) (board==Board::BOARD_TARANIS_X7)
#define IS_TARANIS_X9(board) (board==Board::BOARD_TARANIS_X9D || board==Board::BOARD_TARANIS_X9DP || board==Board::BOARD_TARANIS_X9E)
#define IS_TARANIS_X9D(board) (board==Board::BOARD_TARANIS_X9D || board==Board::BOARD_TARANIS_X9DP)
#define IS_TARANIS_PLUS(board) (board==Board::BOARD_TARANIS_X9DP || board==Board::BOARD_TARANIS_X9E)
#define IS_TARANIS_X9E(board) (board==Board::BOARD_TARANIS_X9E)
#define IS_TARANIS(board) (IS_TARANIS_X9(board) || IS_TARANIS_X7(board))
#define IS_TARANIS(board) (IS_TARANIS_X9(board) || IS_TARANIS_X7(board) || IS_TARANIS_XLITE(board))
#define IS_TARANIS_SMALL(board) (board==Board::BOARD_TARANIS_X7 || board==Board::BOARD_TARANIS_XLITE)
#define IS_TARANIS_NOT_X9E(board) (IS_TARANIS(board) && !IS_TARANIS_X9E(board))
#define IS_HORUS_X12S(board) (board==Board::BOARD_X12S)
#define IS_HORUS_X10(board) (board==Board::BOARD_X10)
#define IS_HORUS(board) (IS_HORUS_X12S(board) || IS_HORUS_X10(board))
#define IS_HORUS_OR_TARANIS(board) (IS_HORUS(board) || IS_TARANIS(board))
#define IS_FLAMENCO(board) (board==Board::BOARD_FLAMENCO)
#define IS_STM32(board) (IS_TARANIS(board) || IS_HORUS(board) || IS_FLAMENCO(board))
#define IS_STM32(board) (IS_TARANIS(board) || IS_HORUS(board))
#define IS_ARM(board) (IS_STM32(board) || IS_SKY9X(board))
#define HAS_LARGE_LCD(board) (IS_HORUS(board) || (IS_TARANIS(board) && !IS_TARANIS_X7(board)))
#define HAS_LARGE_LCD(board) (IS_HORUS(board) || IS_TARANIS_X9(board))
#endif // _BOARDS_H_
@@ -0,0 +1,63 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "curvereference.h"
#include "helpers.h" // for Helpers::getAdjustmentString()
#include "radiodata.h" // for ModelData
QString CurveReference::toString(const ModelData * model, bool verbose) const
{
if (value == 0) {
return "----";
}
QString ret;
unsigned idx = abs(value) - 1;
switch(type) {
case CURVE_REF_DIFF:
ret = tr("Diff(%1)").arg(Helpers::getAdjustmentString(value, model));
break;
case CURVE_REF_EXPO:
ret = tr("Expo(%1)").arg(Helpers::getAdjustmentString(value, model));
break;
case CURVE_REF_FUNC:
ret = QString("x>0" "x<0" "|x|" "f>0" "f<0" "|f|").mid(3*(value-1), 3);
if (verbose)
ret = tr("Function(%1)").arg(ret);
break;
default:
if (model)
ret = model->curves[idx].nameToString(idx);
else
ret = CurveData().nameToString(idx);
if (verbose)
ret = tr("Curve(%1)").arg(ret);
if (value < 0)
ret.prepend(CPN_STR_SW_INDICATOR_REV);
break;
}
return ret;
}
+55
View File
@@ -0,0 +1,55 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef CURVEREFERENCE_H
#define CURVEREFERENCE_H
#include <QtCore>
class ModelData;
class CurveReference {
Q_DECLARE_TR_FUNCTIONS(CurveReference)
public:
enum CurveRefType {
CURVE_REF_DIFF,
CURVE_REF_EXPO,
CURVE_REF_FUNC,
CURVE_REF_CUSTOM
};
CurveReference() { clear(); }
CurveReference(CurveRefType type, int value):
type(type),
value(value)
{
}
void clear() { memset(this, 0, sizeof(CurveReference)); }
CurveRefType type;
int value;
QString toString(const ModelData * model = NULL, bool verbose = true) const;
};
#endif // CURVEREFERENCE_H
@@ -0,0 +1,254 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "customfunctiondata.h"
#include "eeprominterface.h"
#include "radiodata.h"
#include "radiodataconversionstate.h"
void CustomFunctionData::clear()
{
memset(reinterpret_cast<void *>(this), 0, sizeof(CustomFunctionData));
if (!getCurrentFirmware()->getCapability(SafetyChannelCustomFunction)) {
func = FuncTrainer;
}
}
bool CustomFunctionData::isEmpty() const
{
return (swtch.type == SWITCH_TYPE_NONE);
}
QString CustomFunctionData::nameToString(int index, bool globalContext) const
{
return RadioData::getElementName((globalContext ? tr("GF") : tr("SF")), index+1, 0, true);
}
QString CustomFunctionData::funcToString(const ModelData * model) const
{
if (func >= FuncOverrideCH1 && func <= FuncOverrideCH32)
return tr("Override %1").arg(RawSource(SOURCE_TYPE_CH, func).toString(model));
else if (func == FuncTrainer)
return tr("Trainer");
else if (func == FuncTrainerRUD)
return tr("Trainer RUD");
else if (func == FuncTrainerELE)
return tr("Trainer ELE");
else if (func == FuncTrainerTHR)
return tr("Trainer THR");
else if (func == FuncTrainerAIL)
return tr("Trainer AIL");
else if (func == FuncInstantTrim)
return tr("Instant Trim");
else if (func == FuncPlaySound)
return tr("Play Sound");
else if (func == FuncPlayHaptic)
return tr("Haptic");
else if (func == FuncReset)
return tr("Reset");
else if (func >= FuncSetTimer1 && func <= FuncSetTimer3)
return tr("Set Timer %1").arg(func-FuncSetTimer1+1);
else if (func == FuncVario)
return tr("Vario");
else if (func == FuncPlayPrompt)
return tr("Play Track");
else if (func == FuncPlayBoth)
return tr("Play Both");
else if (func == FuncPlayValue)
return tr("Play Value");
else if (func == FuncPlayScript)
return tr("Play Script");
else if (func == FuncLogs)
return tr("SD Logs");
else if (func == FuncVolume)
return tr("Volume");
else if (func == FuncBacklight)
return tr("Backlight");
else if (func == FuncScreenshot)
return tr("Screenshot");
else if (func == FuncBackgroundMusic)
return tr("Background Music");
else if (func == FuncBackgroundMusicPause)
return tr("Background Music Pause");
else if (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast)
return tr("Adjust %1").arg(RawSource(SOURCE_TYPE_GVAR, func-FuncAdjustGV1).toString(model));
else if (func == FuncSetFailsafeInternalModule)
return tr("SetFailsafe Int. Module");
else if (func == FuncSetFailsafeExternalModule)
return tr("SetFailsafe Ext. Module");
else if (func == FuncRangeCheckInternalModule)
return tr("RangeCheck Int. Module");
else if (func == FuncRangeCheckExternalModule)
return tr("RangeCheck Ext. Module");
else if (func == FuncBindInternalModule)
return tr("Bind Int. Module");
else if (func == FuncBindExternalModule)
return tr("Bind Ext. Module");
else {
return QString("???"); // Highlight unknown functions with output of question marks.(BTW should not happen that we do not know what a function is)
}
}
void CustomFunctionData::populateResetParams(const ModelData * model, QComboBox * b, unsigned int value = 0)
{
int val = 0;
Firmware * firmware = Firmware::getCurrentVariant();
Board::Type board = firmware->getBoard();
b->addItem(tr("Timer1"), val++);
b->addItem(tr("Timer2"), val++);
if (IS_ARM(board)) {
b->addItem( tr("Timer3"), val++);
}
b->addItem(tr("Flight"), val++);
b->addItem(tr("Telemetry"), val++);
int reCount = firmware->getCapability(RotaryEncoders);
if (reCount == 1) {
b->addItem(tr("Rotary Encoder"), val++);
}
else if (reCount == 2) {
b->addItem(tr("REa"), val++);
b->addItem(tr("REb"), val++);
}
if ((int)value < b->count()) {
b->setCurrentIndex(value);
}
if (model && IS_ARM(board)) {
for (int i=0; i<CPN_MAX_SENSORS; ++i) {
if (model->sensorData[i].isAvailable()) {
RawSource item = RawSource(SOURCE_TYPE_TELEMETRY, 3*i);
b->addItem(item.toString(model), val+i);
if ((int)value == val+i) {
b->setCurrentIndex(b->count()-1);
}
}
}
}
}
void CustomFunctionData::populatePlaySoundParams(QStringList & qs)
{
qs <<"Beep 1" << "Beep 2" << "Beep 3" << "Warn1" << "Warn2" << "Cheep" << "Ratata" << "Tick" << "Siren" << "Ring" ;
qs << "SciFi" << "Robot" << "Chirp" << "Tada" << "Crickt" << "AlmClk" ;
}
void CustomFunctionData::populateHapticParams(QStringList & qs)
{
qs << "0" << "1" << "2" << "3";
}
QString CustomFunctionData::paramToString(const ModelData * model) const
{
QStringList qs;
if (func <= FuncInstantTrim) {
return QString("%1").arg(param);
}
else if (func==FuncLogs) {
return QString("%1").arg(param/10.0) + tr("s");
}
else if (func==FuncPlaySound) {
CustomFunctionData::populatePlaySoundParams(qs);
if (param>=0 && param<(int)qs.count())
return qs.at(param);
else
return tr("<font color=red><b>Inconsistent parameter</b></font>");
}
else if (func==FuncPlayHaptic) {
CustomFunctionData::populateHapticParams(qs);
if (param>=0 && param<(int)qs.count())
return qs.at(param);
else
return tr("<font color=red><b>Inconsistent parameter</b></font>");
}
else if (func==FuncReset) {
QComboBox cb;
CustomFunctionData::populateResetParams(model, &cb);
int pos = cb.findData(param);
if (pos >= 0)
return cb.itemText(pos);
else
return tr("<font color=red><b>Inconsistent parameter</b></font>");
}
else if ((func==FuncVolume)|| (func==FuncPlayValue)) {
RawSource item(param);
return item.toString(model);
}
else if ((func==FuncPlayPrompt) || (func==FuncPlayBoth)) {
if ( getCurrentFirmware()->getCapability(VoicesAsNumbers)) {
return QString("%1").arg(param);
}
else {
return paramarm;
}
}
else if ((func>=FuncAdjustGV1) && (func<FuncCount)) {
switch (adjustMode) {
case FUNC_ADJUST_GVAR_CONSTANT:
return tr("Value ")+QString("%1").arg(param);
case FUNC_ADJUST_GVAR_SOURCE:
case FUNC_ADJUST_GVAR_GVAR:
return RawSource(param).toString();
case FUNC_ADJUST_GVAR_INCDEC:
if (param==0) return tr("Decr:") + " -1";
else return tr("Incr:") + " +1";
}
}
return "";
}
QString CustomFunctionData::repeatToString() const
{
if (repeatParam == -1) {
return tr("played once, not during startup");
}
else if (repeatParam == 0) {
return "";
}
else {
unsigned int step = IS_ARM(getCurrentBoard()) ? 1 : 10;
return tr("repeat(%1s)").arg(step*repeatParam);
}
}
QString CustomFunctionData::enabledToString() const
{
if ((func>=FuncOverrideCH1 && func<=FuncOverrideCH32) ||
(func>=FuncAdjustGV1 && func<=FuncAdjustGVLast) ||
(func==FuncReset) ||
(func>=FuncSetTimer1 && func<=FuncSetTimer2) ||
(func==FuncVolume) ||
(func <= FuncInstantTrim)) {
if (!enabled) {
return tr("DISABLED");
}
}
return "";
}
void CustomFunctionData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("CFN"), 8);
cstate.setSubComp(nameToString(cstate.subCompIdx, (cstate.toModel() ? false : true)));
swtch.convert(cstate);
if (func == FuncVolume || func == FuncPlayValue || (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast && adjustMode == 1)) {
param = RawSource(param).convert(cstate.withComponentField("PARAM")).toValue();
}
}
@@ -0,0 +1,112 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef CUSTOMFUNCTIONDATA_H
#define CUSTOMFUNCTIONDATA_H
#include "boards.h"
#include "constants.h"
#include "rawswitch.h"
#include <QtCore>
#include <QComboBox>
class Firmware;
class ModelData;
class GeneralSettings;
class RadioDataConversionState;
enum AssignFunc {
FuncOverrideCH1 = 0,
FuncOverrideCH32 = FuncOverrideCH1+CPN_MAX_CHNOUT-1,
FuncTrainer,
FuncTrainerRUD,
FuncTrainerELE,
FuncTrainerTHR,
FuncTrainerAIL,
FuncInstantTrim,
FuncPlaySound,
FuncPlayHaptic,
FuncReset,
FuncSetTimer1,
FuncSetTimer2,
FuncSetTimer3,
FuncVario,
FuncPlayPrompt,
FuncPlayBoth,
FuncPlayValue,
FuncPlayScript,
FuncLogs,
FuncVolume,
FuncBacklight,
FuncScreenshot,
FuncBackgroundMusic,
FuncBackgroundMusicPause,
FuncAdjustGV1,
FuncAdjustGVLast = FuncAdjustGV1+CPN_MAX_GVARS-1,
FuncSetFailsafeInternalModule,
FuncSetFailsafeExternalModule,
FuncRangeCheckInternalModule,
FuncRangeCheckExternalModule,
FuncBindInternalModule,
FuncBindExternalModule,
FuncCount,
FuncReserve = -1
};
enum GVarAdjustModes
{
FUNC_ADJUST_GVAR_CONSTANT,
FUNC_ADJUST_GVAR_SOURCE,
FUNC_ADJUST_GVAR_GVAR,
FUNC_ADJUST_GVAR_INCDEC
};
class CustomFunctionData {
Q_DECLARE_TR_FUNCTIONS(CustomFunctionData)
public:
CustomFunctionData(AssignFunc func=FuncOverrideCH1) { clear(); this->func = func; }
RawSwitch swtch;
AssignFunc func;
int param;
char paramarm[10];
unsigned int enabled; // TODO perhaps not any more the right name
unsigned int adjustMode;
int repeatParam;
void clear();
bool isEmpty() const;
QString nameToString(int index, bool globalContext = false) const;
QString funcToString(const ModelData * model = NULL) const;
QString paramToString(const ModelData * model) const;
QString repeatToString() const;
QString enabledToString() const;
static void populateResetParams(const ModelData * model, QComboBox * b, unsigned int value);
static void populatePlaySoundParams(QStringList & qs);
static void populateHapticParams(QStringList & qs);
void convert(RadioDataConversionState & cstate);
};
#endif // CUSTOMFUNCTIONDATA_H
@@ -22,9 +22,13 @@
#define _EEPROMIMPORTEXPORT_H_
#include "customdebug.h"
#include <QtCore>
#include <QBitArray>
class DataField {
Q_DECLARE_TR_FUNCTIONS(DataField)
public:
DataField(DataField * parent, const char * name=""):
parent(parent),
@@ -382,8 +386,33 @@ class CharField: public DataField {
bool truncate;
};
int8_t char2idx(char c);
char idx2char(int8_t idx);
static const char specialCharsTab[] = "_-.,";
static inline int8_t char2idx(char c)
{
if (c==' ') return 0;
if (c>='A' && c<='Z') return 1+c-'A';
if (c>='a' && c<='z') return -1-c+'a';
if (c>='0' && c<='9') return 27+c-'0';
for (int8_t i=0;;i++) {
char cc = specialCharsTab[i];
if (cc==0) return 0;
if (cc==c) return 37+i;
}
}
#define ZCHAR_MAX 40
static inline char idx2char(int8_t idx)
{
if (idx == 0) return ' ';
if (idx < 0) {
if (idx > -27) return 'a' - idx - 1;
idx = -idx;
}
if (idx < 27) return 'A' + idx - 1;
if (idx < 37) return '0' + idx - 27;
if (idx <= ZCHAR_MAX) return specialCharsTab[idx-37];
return ' ';
}
template<int N>
class ZCharField: public DataField {
@@ -717,7 +746,7 @@ class ConversionField: public TransformedField {
if (table) {
if (!table->exportValue(_field, _field)) {
setError(error.isEmpty() ? QObject::tr("Conversion error on field %1").arg(name) : error);
setError(error.isEmpty() ? DataField::tr("Conversion error on field %1").arg(name) : error);
}
return;
}
+185
View File
@@ -0,0 +1,185 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "eeprominterface.h"
#include "firmwares/opentx/opentxeeprom.h"
#include "firmwareinterface.h"
#include <QtCore>
#include <QMessageBox>
#include <bitset>
float ValToTim(int value)
{
return ((value < -109 ? 129+value : (value < 7 ? (113+value)*5 : (53+value)*10))/10.0);
}
int TimToVal(float value)
{
int temp;
if (value>60) {
temp=136+round((value-60));
}
else if (value>2) {
temp=20+round((value-2.0)*2.0);
}
else {
temp=round(value*10.0);
}
return (temp-129);
}
/*
* EEpromInterface globals
*/
// TODO: No globals
QList<EEPROMInterface *> eepromInterfaces;
void unregisterEEpromInterfaces()
{
foreach(EEPROMInterface * intf, eepromInterfaces) {
// qDebug() << "UnregisterEepromInterfaces(): deleting " << QString::number( reinterpret_cast<uint64_t>(intf), 16 );
delete intf;
}
OpenTxEepromCleanup();
}
#if 0 // TODO: remove if unused, currently commented out in mdiChild.cpp
// TODO: No GUI here, e.g. return string list instead
void EEPROMInterface::showEepromErrors(QWidget *parent, const QString &title, const QString &mainMessage, unsigned long errorsFound)
{
std::bitset<NUM_ERRORS> errors((unsigned long long)errorsFound);
QStringList errorsList;
errorsList << tr("Possible causes for this:");
if (errors.test(UNSUPPORTED_NEWER_VERSION)) { errorsList << tr("- Eeprom is from a newer version of OpenTX"); }
if (errors.test(NOT_OPENTX)) { errorsList << tr("- Eeprom is not from OpenTX"); }
if (errors.test(NOT_TH9X)) { errorsList << tr("- Eeprom is not from Th9X"); }
if (errors.test(NOT_GRUVIN9X)) { errorsList << tr("- Eeprom is not from Gruvin9X"); }
if (errors.test(NOT_ERSKY9X)) { errorsList << tr("- Eeprom is not from ErSky9X"); }
if (errors.test(NOT_ER9X)) { errorsList << tr("- Eeprom is not from Er9X"); }
if (errors.test(WRONG_SIZE)) { errorsList << tr("- Eeprom size is invalid"); }
if (errors.test(WRONG_FILE_SYSTEM)) { errorsList << tr("- Eeprom file system is invalid"); }
if (errors.test(UNKNOWN_BOARD)) { errorsList << tr("- Eeprom is from a unknown board"); }
if (errors.test(WRONG_BOARD)) { errorsList << tr("- Eeprom is from the wrong board"); }
if (errors.test(BACKUP_NOT_SUPPORTED)) { errorsList << tr("- Eeprom backup not supported"); }
if (errors.test(UNKNOWN_ERROR)) { errorsList << tr("- Something that couldn't be guessed, sorry"); }
if (errors.test(HAS_WARNINGS)) {
errorsList << tr("Warning:");
if (errors.test(WARNING_WRONG_FIRMWARE)) { errorsList << tr("- 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::Critical);
msgBox.setText(mainMessage);
msgBox.setInformativeText(errorsList.join("\n"));
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.exec();
}
#endif
// TODO: No GUI here, e.g. return string list instead
void EEPROMInterface::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 << tr("- Your radio probably uses a wrong firmware,\n eeprom size is 4096 but only the first 2048 are used"); }
if (errors.test(OLD_VERSION)) { warningsList << tr("- Your eeprom is from an old version of OpenTX, upgrading!\n To keep your original file as a backup, please choose File -> Save As specifying a different name."); }
QMessageBox msgBox(parent);
msgBox.setWindowTitle(title);
msgBox.setIcon(QMessageBox::Warning);
msgBox.setText(tr("Warnings!"));
msgBox.setInformativeText(warningsList.join("\n"));
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.exec();
}
/*
* Firmware
*/
// static
QVector<Firmware *> Firmware::registeredFirmwares;
Firmware * Firmware::defaultVariant = NULL;
Firmware * Firmware::currentVariant = NULL;
// static
Firmware * Firmware::getFirmwareForId(const QString & id)
{
foreach(Firmware * firmware, registeredFirmwares) {
Firmware * result = firmware->getFirmwareVariant(id);
if (result) {
return result;
}
}
return defaultVariant;
}
unsigned int Firmware::getVariantNumber()
{
unsigned int result = 0;
const Firmware * base = getFirmwareBase();
QStringList options = id.mid(base->getId().length()+1).split("-", QString::SkipEmptyParts);
foreach(QString option, options) {
foreach(OptionsGroup group, base->opts) {
foreach(Option opt, group) {
if (opt.name == option) {
result += opt.variant;
}
}
}
}
return result;
}
void Firmware::addLanguage(const char * lang)
{
languages.push_back(lang);
}
//void Firmware::addTTSLanguage(const char * lang)
//{
// ttslanguages.push_back(lang);
//}
void Firmware::addOption(const char * option, const QString & tooltip, unsigned variant)
{
addOption(Option(option, tooltip, variant));
}
void Firmware::addOption(const Option & option)
{
addOptionsGroup({option});
}
void Firmware::addOptionsGroup(const OptionsGroup & options)
{
this->opts.append(options);
}
@@ -21,15 +21,19 @@
#ifndef _EEPROMINTERFACE_H_
#define _EEPROMINTERFACE_H_
#include "boards.h"
#include "macros.h"
#include "radiodata.h"
#include "../../radio/src/definitions.h"
#include "simulatorinterface.h"
#include <QtCore>
#include <QStringList>
#include <QList>
#include <iostream>
#include <QDebug>
#include <iostream>
const uint8_t modn12x3[4][4]= {
{1, 2, 3, 4},
{1, 3, 2, 4},
@@ -103,6 +107,8 @@ enum Capability {
HasFailsafe,
HasSoundMixer,
NumModules,
HasModuleR9MFlex,
HasModuleR9MMini,
PPMCenter,
PPMUnitMicroseconds,
SYMLimits,
@@ -134,8 +140,6 @@ enum Capability {
EnhancedCurves,
HasFasOffset,
HasMahPersistent,
MultiposPots,
MultiposPotsPositions,
SimulatorVariant,
MavlinkTelemetry,
HasInputDiff,
@@ -145,9 +149,10 @@ enum Capability {
HasModelCategories
};
class SimulatorInterface;
class EEPROMInterface
{
Q_DECLARE_TR_FUNCTIONS(EEPROMInterface)
public:
EEPROMInterface(Board::Type board):
@@ -169,6 +174,9 @@ class EEPROMInterface
virtual int getSize(const GeneralSettings &) = 0;
//static void showEepromErrors(QWidget *parent, const QString &title, const QString &mainMessage, unsigned long errorsFound);
static void showEepromWarnings(QWidget *parent, const QString &title, unsigned long errorsFound);
protected:
Board::Type board;
@@ -179,13 +187,20 @@ class EEPROMInterface
};
/* EEPROM string conversion functions */
void setEEPROMString(char *dst, const char *src, int size);
void getEEPROMString(char *dst, const char *src, int size);
float ValToTim(int value);
int TimToVal(float value);
/* EEPROM string conversion function (used only by er9xeeprom and ersky9xeeprom) */
inline void getEEPROMString(char *dst, const char *src, int size)
{
memcpy(dst, src, size);
dst[size] = '\0';
for (int i=size-1; i>=0; i--) {
if (dst[i] == ' ')
dst[i] = '\0';
else
break;
}
}
// (used only by er9xeeprom and ersky9xeeprom)
inline int applyStickMode(int stick, unsigned int mode)
{
if (mode == 0 || mode > 4) {
@@ -199,6 +214,9 @@ inline int applyStickMode(int stick, unsigned int mode)
return stick;
}
float ValToTim(int value);
int TimToVal(float value);
void registerEEpromInterfaces();
void unregisterEEpromInterfaces();
void registerOpenTxFirmwares();
@@ -226,42 +244,37 @@ enum EepromLoadErrors {
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);
struct Option {
const char * name;
QString tooltip;
uint32_t variant;
};
class Firmware {
class Firmware
{
Q_DECLARE_TR_FUNCTIONS(Firmware)
public:
Firmware(const QString & id, const QString & name, Board::Type board):
id(id),
name(name),
board(board),
variantBase(0),
base(NULL),
eepromInterface(NULL)
{
}
struct Option {
const char * name = nullptr;
QString tooltip;
unsigned variant = 0;
Firmware(Firmware * base, const QString & id, const QString & name, Board::Type board):
explicit Option(const char * name, const QString & description, unsigned variant = 0) :
name(name), tooltip(description), variant(variant) { }
};
typedef QList<Option> OptionsGroup;
typedef QList<OptionsGroup> OptionsList;
explicit Firmware(const QString & id, const QString & name, Board::Type board) :
Firmware(nullptr, id, name, board)
{ }
explicit Firmware(Firmware * base, const QString & id, const QString & name, Board::Type board) :
id(id),
name(name),
board(board),
variantBase(0),
base(base),
eepromInterface(NULL)
{
}
eepromInterface(nullptr)
{ }
virtual ~Firmware()
{
}
virtual ~Firmware() { }
inline const Firmware * getFirmwareBase() const
{
@@ -272,13 +285,15 @@ class Firmware {
unsigned int getVariantNumber();
virtual void addLanguage(const char *lang);
virtual void addLanguage(const char * lang);
virtual void addTTSLanguage(const char *lang);
//virtual void addTTSLanguage(const char * lang);
virtual void addOption(const char *option, QString tooltip="", uint32_t variant=0);
virtual void addOption(const char * option, const QString & tooltip = QString(), unsigned variant = 0);
virtual void addOptions(Option options[]);
virtual void addOption(const Option & option);
virtual void addOptionsGroup(const OptionsGroup & options);
virtual QString getStampUrl() = 0;
@@ -311,6 +326,16 @@ class Firmware {
return id;
}
QList<const char *> languageList() const
{
return languages;
}
OptionsList optionGroups() const
{
return opts;
}
virtual int getCapability(Capability) = 0;
virtual QString getAnalogInputName(unsigned int index) = 0;
@@ -327,6 +352,7 @@ class Firmware {
{
return registeredFirmwares;
}
static void addRegisteredFirmware(Firmware * fw)
{
registeredFirmwares.append(fw);
@@ -345,17 +371,12 @@ class Firmware {
{
return currentVariant;
}
static void setCurrentVariant(Firmware * value)
{
currentVariant = value;
}
public:
QList<const char *> languages;
QList<const char *> ttslanguages;
QList< QList<Option> > opts;
protected:
QString id;
QString name;
@@ -363,14 +384,13 @@ class Firmware {
unsigned int variantBase;
Firmware * base;
EEPROMInterface * eepromInterface;
QList<const char *> languages;
//QList<const char *> ttslanguages;
OptionsList opts;
static QVector<Firmware *> registeredFirmwares;
static Firmware * defaultVariant;
static Firmware * currentVariant;
private:
Firmware();
};
inline Firmware * getCurrentFirmware()
@@ -398,11 +418,7 @@ inline int calcRESXto100(int x)
return divRoundClosest(x*100, 1024);
}
#define CHECK_IN_ARRAY(T, index) ((unsigned int)index < DIM(T) ? T[(unsigned int)index] : "???")
extern QList<EEPROMInterface *> eepromInterfaces;
bool loadFile(RadioData & radioData, const QString & filename);
#endif // _EEPROMINTERFACE_H_
+353
View File
@@ -0,0 +1,353 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "generalsettings.h"
#include "appdata.h"
#include "eeprominterface.h"
#include "radiodataconversionstate.h"
const uint8_t chout_ar[] = { // First number is 0..23 -> template setup, Second is relevant channel out
1,2,3,4 , 1,2,4,3 , 1,3,2,4 , 1,3,4,2 , 1,4,2,3 , 1,4,3,2,
2,1,3,4 , 2,1,4,3 , 2,3,1,4 , 2,3,4,1 , 2,4,1,3 , 2,4,3,1,
3,1,2,4 , 3,1,4,2 , 3,2,1,4 , 3,2,4,1 , 3,4,1,2 , 3,4,2,1,
4,1,2,3 , 4,1,3,2 , 4,2,1,3 , 4,2,3,1 , 4,3,1,2 , 4,3,2,1
};
bool GeneralSettings::switchPositionAllowedTaranis(int index) const
{
if (index == 0)
return true;
div_t qr = div(abs(index)-1, 3);
if (index < 0 && switchConfig[qr.quot] != Board::SWITCH_3POS)
return false;
else if (qr.rem == 1)
return switchConfig[qr.quot] == Board::SWITCH_3POS;
else
return switchConfig[qr.quot] != Board::SWITCH_NOT_AVAILABLE;
}
bool GeneralSettings::switchSourceAllowedTaranis(int index) const
{
return switchConfig[index] != Board::SWITCH_NOT_AVAILABLE;
}
bool GeneralSettings::isPotAvailable(int index) const
{
if (index<0 || index>getBoardCapability(getCurrentBoard(), Board::Pots)) return false;
return potConfig[index] != Board::POT_NONE;
}
bool GeneralSettings::isSliderAvailable(int index) const
{
if (index<0 || index>getBoardCapability(getCurrentBoard(), Board::Sliders)) return false;
return sliderConfig[index] != Board::SLIDER_NONE;
}
GeneralSettings::GeneralSettings()
{
memset(this, 0, sizeof(GeneralSettings));
contrast = 25;
for (int i=0; i < CPN_MAX_ANALOGS; ++i) {
calibMid[i] = 0x200;
calibSpanNeg[i] = 0x180;
calibSpanPos[i] = 0x180;
}
Firmware * firmware = Firmware::getCurrentVariant();
Board::Type board = firmware->getBoard();
// vBatWarn is voltage in 100mV, vBatMin is in 100mV but with -9V offset, vBatMax has a -12V offset
vBatWarn = 90;
if (IS_TARANIS_X9E(board) || IS_HORUS_X12S(board)) {
// NI-MH 9.6V
vBatWarn = 87;
vBatMin = -5; //8,5V
vBatMax = -5; //11,5V
}
else if (IS_TARANIS_XLITE(board) || IS_HORUS_X10(board)) {
// Lipo 2S
vBatWarn = 66;
vBatMin = -23; // 6.7V
vBatMax = -37; // 8.3V
}
else if (IS_TARANIS(board)) {
// NI-MH 7.2V, X9D, X9D+ and X7
vBatWarn = 65;
vBatMin = -30; //6V
vBatMax = -40; //8V
}
setDefaultControlTypes(board);
backlightMode = 3; // keys and sticks
// backlightBright = 0; // 0 = 100%
if (IS_HORUS(board)) {
backlightOffBright = 20;
}
if (IS_ARM(board)) {
speakerVolume = 12;
}
if (IS_HORUS(board)) {
strcpy(bluetoothName, "Horus");
}
else if (IS_TARANIS_X9E(board) || IS_TARANIS_SMALL(board)) {
strcpy(bluetoothName, "Taranis");
}
templateSetup = g.profile[g.sessionId()].channelOrder();
stickMode = g.profile[g.sessionId()].defaultMode();
QString t_calib = g.profile[g.sessionId()].stickPotCalib();
int potsnum = getBoardCapability(getCurrentBoard(), Board::Pots);
if (!t_calib.isEmpty()) {
QString t_trainercalib=g.profile[g.sessionId()].trainerCalib();
int8_t t_txVoltageCalibration=(int8_t)g.profile[g.sessionId()].txVoltageCalibration();
int8_t t_txCurrentCalibration=(int8_t)g.profile[g.sessionId()].txCurrentCalibration();
int8_t t_PPM_Multiplier=(int8_t)g.profile[g.sessionId()].ppmMultiplier();
uint8_t t_stickMode=(uint8_t)g.profile[g.sessionId()].gsStickMode();
uint8_t t_vBatWarn=(uint8_t)g.profile[g.sessionId()].vBatWarn();
QString t_DisplaySet=g.profile[g.sessionId()].display();
QString t_BeeperSet=g.profile[g.sessionId()].beeper();
QString t_HapticSet=g.profile[g.sessionId()].haptic();
QString t_SpeakerSet=g.profile[g.sessionId()].speaker();
QString t_CountrySet=g.profile[g.sessionId()].countryCode();
if ((t_calib.length()==(CPN_MAX_STICKS+potsnum)*12) && (t_trainercalib.length()==16)) {
QString Byte;
int16_t byte16;
bool ok;
for (int i=0; i<(CPN_MAX_STICKS+potsnum); i++) {
Byte=t_calib.mid(i*12,4);
byte16=(int16_t)Byte.toInt(&ok,16);
if (ok)
calibMid[i]=byte16;
Byte=t_calib.mid(4+i*12,4);
byte16=(int16_t)Byte.toInt(&ok,16);
if (ok)
calibSpanNeg[i]=byte16;
Byte=t_calib.mid(8+i*12,4);
byte16=(int16_t)Byte.toInt(&ok,16);
if (ok)
calibSpanPos[i]=byte16;
}
for (int i=0; i<4; i++) {
Byte=t_trainercalib.mid(i*4,4);
byte16=(int16_t)Byte.toInt(&ok,16);
if (ok)
trainer.calib[i]=byte16;
}
txCurrentCalibration=t_txCurrentCalibration;
txVoltageCalibration=t_txVoltageCalibration;
vBatWarn=t_vBatWarn;
PPM_Multiplier=t_PPM_Multiplier;
stickMode = t_stickMode;
}
if ((t_DisplaySet.length()==6) && (t_BeeperSet.length()==4) && (t_HapticSet.length()==6) && (t_SpeakerSet.length()==6)) {
uint8_t byte8u;
int8_t byte8;
bool ok;
byte8=(int8_t)t_DisplaySet.mid(0,2).toInt(&ok,16);
if (ok)
optrexDisplay=(byte8==1 ? true : false);
byte8u=(uint8_t)t_DisplaySet.mid(2,2).toUInt(&ok,16);
if (ok)
contrast=byte8u;
byte8u=(uint8_t)t_DisplaySet.mid(4,2).toUInt(&ok,16);
if (ok)
backlightBright=byte8u;
byte8=(int8_t)t_BeeperSet.mid(0,2).toUInt(&ok,16);
if (ok)
beeperMode=(BeeperMode)byte8;
byte8=(int8_t)t_BeeperSet.mid(2,2).toInt(&ok,16);
if (ok)
beeperLength=byte8;
byte8=(int8_t)t_HapticSet.mid(0,2).toUInt(&ok,16);
if (ok)
hapticMode=(BeeperMode)byte8;
byte8=(int8_t)t_HapticSet.mid(2,2).toInt(&ok,16);
if (ok)
hapticStrength=byte8;
byte8=(int8_t)t_HapticSet.mid(4,2).toInt(&ok,16);
if (ok)
hapticLength=byte8;
byte8u=(uint8_t)t_SpeakerSet.mid(0,2).toUInt(&ok,16);
if (ok)
speakerMode=byte8u;
byte8u=(uint8_t)t_SpeakerSet.mid(2,2).toUInt(&ok,16);
if (ok)
speakerPitch=byte8u;
byte8u=(uint8_t)t_SpeakerSet.mid(4,2).toUInt(&ok,16);
if (ok)
speakerVolume=byte8u;
if (t_CountrySet.length()==6) {
byte8u=(uint8_t)t_CountrySet.mid(0,2).toUInt(&ok,16);
if (ok)
countryCode=byte8u;
byte8u=(uint8_t)t_CountrySet.mid(2,2).toUInt(&ok,16);
if (ok)
imperial=byte8u;
QString chars = t_CountrySet.mid(4, 2);
ttsLanguage[0] = chars[0].toLatin1();
ttsLanguage[1] = chars[1].toLatin1();
}
}
}
strcpy(themeName, "default");
ThemeOptionData option1 = { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0 };
memcpy(&themeOptionValue[0], option1, sizeof(ThemeOptionData));
ThemeOptionData option2 = { 0x03, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0 };
memcpy(&themeOptionValue[1], option2, sizeof(ThemeOptionData));
}
void GeneralSettings::setDefaultControlTypes(Board::Type board)
{
for (int i=0; i<getBoardCapability(board, Board::FactoryInstalledSwitches); i++) {
switchConfig[i] = Boards::getSwitchInfo(board, i).config;
}
// TODO: move to Boards, like with switches
if (IS_HORUS(board)) {
potConfig[0] = Board::POT_WITH_DETENT;
potConfig[1] = Board::POT_MULTIPOS_SWITCH;
potConfig[2] = Board::POT_WITH_DETENT;
}
else if (IS_TARANIS_XLITE(board)) {
potConfig[0] = Board::POT_WITHOUT_DETENT;
potConfig[1] = Board::POT_WITHOUT_DETENT;
}
else if (IS_TARANIS_X7(board)) {
potConfig[0] = Board::POT_WITHOUT_DETENT;
potConfig[1] = Board::POT_WITH_DETENT;
}
else if (IS_TARANIS(board)) {
potConfig[0] = Board::POT_WITH_DETENT;
potConfig[1] = Board::POT_WITH_DETENT;
}
else {
potConfig[0] = Board::POT_WITHOUT_DETENT;
potConfig[1] = Board::POT_WITHOUT_DETENT;
potConfig[2] = Board::POT_WITHOUT_DETENT;
}
if (IS_HORUS_X12S(board) || IS_TARANIS_X9E(board)) {
sliderConfig[0] = Board::SLIDER_WITH_DETENT;
sliderConfig[1] = Board::SLIDER_WITH_DETENT;
sliderConfig[2] = Board::SLIDER_WITH_DETENT;
sliderConfig[3] = Board::SLIDER_WITH_DETENT;
}
else if (IS_TARANIS_X9(board) || IS_HORUS_X10(board)) {
sliderConfig[0] = Board::SLIDER_WITH_DETENT;
sliderConfig[1] = Board::SLIDER_WITH_DETENT;
}
}
int GeneralSettings::getDefaultStick(unsigned int channel) const
{
if (channel >= CPN_MAX_STICKS)
return -1;
else
return chout_ar[4*templateSetup + channel] - 1;
}
RawSource GeneralSettings::getDefaultSource(unsigned int channel) const
{
int stick = getDefaultStick(channel);
if (stick >= 0)
return RawSource(SOURCE_TYPE_STICK, stick);
else
return RawSource(SOURCE_TYPE_NONE);
}
int GeneralSettings::getDefaultChannel(unsigned int stick) const
{
for (int i=0; i<4; i++){
if (getDefaultStick(i) == (int)stick)
return i;
}
return -1;
}
void GeneralSettings::convert(RadioDataConversionState & cstate)
{
// Here we can add explicit conversions when moving from one board to another
cstate.setOrigin(tr("Radio Settings"));
setDefaultControlTypes(cstate.toType); // start with default switches/pots/sliders
// Try to intelligently copy any custom control names
// SE and SG are skipped on X7 board
if (IS_TARANIS_X7(cstate.toType)) {
if (IS_TARANIS_X9(cstate.fromType) || IS_HORUS(cstate.fromType)) {
strncpy(switchName[4], switchName[5], sizeof(switchName[4]));
strncpy(switchName[5], switchName[7], sizeof(switchName[5]));
}
}
else if (IS_TARANIS_X7(cstate.fromType)) {
if (IS_TARANIS_X9(cstate.toType) || IS_HORUS(cstate.toType)) {
strncpy(switchName[5], switchName[4], sizeof(switchName[5]));
strncpy(switchName[7], switchName[5], sizeof(switchName[7]));
}
}
// LS and RS sliders are after 2 aux sliders on X12 and X9E
if ((IS_HORUS_X12S(cstate.toType) || IS_TARANIS_X9E(cstate.toType)) && !IS_HORUS_X12S(cstate.fromType) && !IS_TARANIS_X9E(cstate.fromType)) {
strncpy(sliderName[0], sliderName[2], sizeof(sliderName[0]));
strncpy(sliderName[1], sliderName[3], sizeof(sliderName[1]));
}
else if (!IS_TARANIS_X9E(cstate.toType) && !IS_HORUS_X12S(cstate.toType) && (IS_HORUS_X12S(cstate.fromType) || IS_TARANIS_X9E(cstate.fromType))) {
strncpy(sliderName[2], sliderName[0], sizeof(sliderName[2]));
strncpy(sliderName[3], sliderName[1], sizeof(sliderName[3]));
}
if (IS_HORUS(cstate.toType)) {
// 6P switch is only on Horus (by default)
if (cstate.fromBoard.getCapability(Board::FactoryInstalledPots) == 2) {
strncpy(potName[2], potName[1], sizeof(potName[2]));
potName[1][0] = '\0';
}
}
if (IS_TARANIS(cstate.toType)) {
// No S3 pot on Taranis boards by default
if (cstate.fromBoard.getCapability(Board::FactoryInstalledPots) > 2)
strncpy(potName[1], potName[2], sizeof(potName[1]));
contrast = qBound<int>(getCurrentFirmware()->getCapability(MinContrast), contrast, getCurrentFirmware()->getCapability(MaxContrast));
}
// TODO: Would be nice at this point to have GUI pause and ask the user to set up any custom hardware they have on the destination radio.
// Convert all global functions (do this after HW adjustments)
for (int i=0; i<CPN_MAX_SPECIAL_FUNCTIONS; i++) {
customFn[i].convert(cstate.withComponentIndex(i));
}
}
+177
View File
@@ -0,0 +1,177 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef GENERALSETTINGS_H
#define GENERALSETTINGS_H
#include "boards.h"
#include "constants.h"
#include "customfunctiondata.h"
#include "rawsource.h"
#include <QtCore>
class Firmware;
class ModelData;
class GeneralSettings;
class RadioDataConversionState;
enum UartModes {
UART_MODE_NONE,
UART_MODE_TELEMETRY_MIRROR,
UART_MODE_TELEMETRY,
UART_MODE_SBUS_TRAINER,
UART_MODE_DEBUG
};
class TrainerMix {
public:
TrainerMix() { clear(); }
unsigned int src; // 0-7 = ch1-8
RawSwitch swtch;
int weight;
unsigned int mode; // off, add-mode, subst-mode
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(TrainerMix)); }
};
class TrainerData {
public:
TrainerData() { clear(); }
int calib[4];
TrainerMix mix[4];
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(TrainerData)); }
};
class GeneralSettings {
Q_DECLARE_TR_FUNCTIONS(GeneralSettings)
public:
enum BeeperMode {
BEEPER_QUIET = -2,
BEEPER_ALARMS_ONLY = -1,
BEEPER_NOKEYS = 0,
BEEPER_ALL = 1
};
GeneralSettings();
void convert(RadioDataConversionState & cstate);
void setDefaultControlTypes(Board::Type board);
int getDefaultStick(unsigned int channel) const;
RawSource getDefaultSource(unsigned int channel) const;
int getDefaultChannel(unsigned int stick) const;
unsigned int version;
unsigned int variant;
int calibMid[CPN_MAX_ANALOGS];
int calibSpanNeg[CPN_MAX_ANALOGS];
int calibSpanPos[CPN_MAX_ANALOGS];
unsigned int currModelIndex;
char currModelFilename[16+1];
unsigned int contrast;
unsigned int vBatWarn;
int txVoltageCalibration;
int txCurrentCalibration;
int vBatMin;
int vBatMax;
int backlightMode;
TrainerData trainer;
unsigned int view; // main screen view // TODO enum
bool disableThrottleWarning;
bool fai;
bool disableMemoryWarning;
BeeperMode beeperMode;
bool disableAlarmWarning;
bool disableRssiPoweroffAlarm;
unsigned int usbMode;
BeeperMode hapticMode;
unsigned int stickMode; // TODO enum
int timezone;
bool adjustRTC;
bool optrexDisplay;
unsigned int inactivityTimer;
bool minuteBeep;
bool preBeep;
bool flashBeep;
unsigned int splashMode;
int splashDuration;
unsigned int backlightDelay;
unsigned int templateSetup; //RETA order according to chout_ar array
int PPM_Multiplier;
int hapticLength;
unsigned int reNavigation;
unsigned int stickReverse;
unsigned int speakerPitch;
int hapticStrength;
unsigned int speakerMode;
char ownerName[10+1];
int beeperLength;
unsigned int gpsFormat;
int speakerVolume;
unsigned int backlightBright;
unsigned int backlightOffBright;
int switchesDelay;
int temperatureCalib;
int temperatureWarn;
unsigned int mAhWarn;
unsigned int mAhUsed;
unsigned int globalTimer;
char bluetoothName[10+1];
unsigned int bluetoothBaudrate;
unsigned int bluetoothMode;
unsigned int sticksGain;
unsigned int rotarySteps;
unsigned int countryCode;
bool jitterFilter;
unsigned int imperial;
char ttsLanguage[2+1];
int beepVolume;
int wavVolume;
int varioVolume;
int varioPitch;
int varioRange;
int varioRepeat;
int backgroundVolume;
unsigned int mavbaud;
unsigned int switchUnlockStates;
unsigned int hw_uartMode; // UartModes
unsigned int backlightColor;
CustomFunctionData customFn[CPN_MAX_SPECIAL_FUNCTIONS];
char switchName[CPN_MAX_SWITCHES][3+1];
unsigned int switchConfig[CPN_MAX_SWITCHES];
char stickName[CPN_MAX_STICKS][3+1];
char potName[CPN_MAX_KNOBS][3+1];
unsigned int potConfig[CPN_MAX_KNOBS];
char sliderName[CPN_MAX_SLIDERS][3+1];
unsigned int sliderConfig[CPN_MAX_SLIDERS];
char themeName[8+1];
typedef uint8_t ThemeOptionData[8+1];
ThemeOptionData themeOptionValue[5];
bool switchPositionAllowedTaranis(int index) const;
bool switchSourceAllowedTaranis(int index) const;
bool isPotAvailable(int index) const;
bool isSliderAvailable(int index) const;
};
#endif // GENERALSETTINGS_H
+92
View File
@@ -0,0 +1,92 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "gvardata.h"
#include "radiodata.h"
QString GVarData::unitToString() const
{
switch (unit) {
case GVAR_UNIT_NUMBER:
return tr("");
case GVAR_UNIT_PERCENT:
return tr("%");
default:
return tr("?"); // highlight unknown value
}
}
QString GVarData::precToString() const
{
switch (prec) {
case GVAR_PREC_MUL10:
return tr("0._");
case GVAR_PREC_MUL1:
return tr("0.0");
default:
return tr("?.?"); // highlight unknown value
}
}
QString GVarData::nameToString(int index) const
{
return RadioData::getElementName(tr("GV"), index + 1, name);
}
int GVarData::multiplierSet()
{
return (prec == 0 ? 1 : 10);
}
float GVarData::multiplierGet() const
{
return (prec == 0 ? 1 : 0.1);
}
void GVarData::setMin(float val)
{
min = (val * multiplierSet()) - GVAR_MIN_VALUE;
}
void GVarData::setMax(float val)
{
max = GVAR_MAX_VALUE - (val * multiplierSet());
}
int GVarData::getMin() const
{
return GVAR_MIN_VALUE + min;
}
int GVarData::getMax() const
{
return GVAR_MAX_VALUE - max;
}
float GVarData::getMinPrec() const
{
return getMin() * multiplierGet();
}
float GVarData::getMaxPrec() const
{
return getMax() * multiplierGet();
}
+68
View File
@@ -0,0 +1,68 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef GVARDATA_H
#define GVARDATA_H
#include <QtCore>
#define GVAR_NAME_LEN 3
#define GVAR_MAX_VALUE 1024
#define GVAR_MIN_VALUE -GVAR_MAX_VALUE
class GVarData {
Q_DECLARE_TR_FUNCTIONS(GVarData)
public:
GVarData() { clear(); }
enum {
GVAR_UNIT_NUMBER,
GVAR_UNIT_PERCENT
};
enum {
GVAR_PREC_MUL10,
GVAR_PREC_MUL1
};
char name[GVAR_NAME_LEN+1];
int min;
int max;
bool popup;
unsigned int prec; // 0 0._ 1 0.0
unsigned int unit; // 0 _ 1 %
void clear() {memset(this, 0, sizeof(GVarData)); }
QString unitToString() const;
QString precToString() const;
QString nameToString(int index) const;
int multiplierSet();
float multiplierGet() const;
void setMin(float val);
void setMax(float val);
int getMin() const;
int getMax() const;
float getMinPrec() const;
float getMaxPrec() const;
};
#endif // GVARDATA_H
+147
View File
@@ -0,0 +1,147 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "io_data.h"
#include "radiodata.h" // for RadioData::getElementName
#include "radiodataconversionstate.h"
/*
* ExpoData
*/
void ExpoData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("INP"), 3);
cstate.setSubComp(RawSource(SOURCE_TYPE_VIRTUAL_INPUT, chn).toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType) % tr(" (@%1)").arg(cstate.subCompIdx));
srcRaw.convert(cstate);
swtch.convert(cstate);
}
/*
* MixData
*/
void MixData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("MIX"), 4);
cstate.setSubComp(RawSource(SOURCE_TYPE_CH, destCh-1).toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType) % tr(" (@%1)").arg(cstate.subCompIdx));
srcRaw.convert(cstate);
swtch.convert(cstate);
}
/*
* LimitData
*/
QString LimitData::minToString() const
{
return QString::number((qreal)min/10);
}
QString LimitData::maxToString() const
{
return QString::number((qreal)max/10);
}
QString LimitData::revertToString() const
{
return revert ? tr("INV") : tr("NOR");
}
QString LimitData::nameToString(int index) const
{
return RadioData::getElementName(tr("CH"), index + 1, name);
}
QString LimitData::offsetToString() const
{
return QString::number((qreal)offset/10, 'f', 1);
}
void LimitData::clear()
{
memset(reinterpret_cast<void *>(this), 0, sizeof(LimitData));
min = -1000;
max = +1000;
}
/*
* CurveData
*/
CurveData::CurveData()
{
clear(5);
}
void CurveData::clear(int count)
{
memset(this, 0, sizeof(CurveData));
this->count = count;
}
bool CurveData::isEmpty() const
{
for (int i=0; i<count; i++) {
if (points[i].y != 0) {
return false;
}
}
return true;
}
QString CurveData::nameToString(const int idx) const
{
return RadioData::getElementName(tr("CV"), idx + 1, name);
}
/*
* FlightModeData
*/
void FlightModeData::clear(const int phase)
{
memset(reinterpret_cast<void *>(this), 0, sizeof(FlightModeData));
if (phase != 0) {
for (int idx=0; idx<CPN_MAX_GVARS; idx++) {
gvars[idx] = 1025;
}
for (int idx=0; idx<CPN_MAX_ENCODERS; idx++) {
rotaryEncoders[idx] = 1025;
}
}
}
QString FlightModeData::nameToString(int index) const
{
return RadioData::getElementName(tr("FM"), index, name); // names are zero-based, FM0, FM1, etc
}
void FlightModeData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent("FMD", 2);
cstate.setSubComp(nameToString(cstate.subCompIdx));
swtch.convert(cstate);
}
+179
View File
@@ -0,0 +1,179 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef IO_DATA_H
#define IO_DATA_H
#include "constants.h"
#include "curvereference.h"
#include "rawsource.h"
#include "rawswitch.h"
#include <QtCore>
class RadioDataConversionState;
enum InputMode {
INPUT_MODE_NONE,
INPUT_MODE_POS,
INPUT_MODE_NEG,
INPUT_MODE_BOTH
};
class ExpoData {
Q_DECLARE_TR_FUNCTIONS(ExpoData)
public:
ExpoData() { clear(); }
RawSource srcRaw;
unsigned int scale;
unsigned int mode; // InputMode
unsigned int chn;
RawSwitch swtch;
unsigned int flightModes; // -5=!FP4, 0=normal, 5=FP4
int weight;
int offset;
CurveReference curve;
int carryTrim;
char name[10+1];
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(ExpoData)); }
void convert(RadioDataConversionState & cstate);
};
enum MltpxValue {
MLTPX_ADD=0,
MLTPX_MUL=1,
MLTPX_REP=2
};
#define MIXDATA_NAME_LEN 10
class MixData {
Q_DECLARE_TR_FUNCTIONS(MixData)
public:
MixData() { clear(); }
void convert(RadioDataConversionState & cstate);
unsigned int destCh; // 1..CPN_MAX_CHNOUT
RawSource srcRaw;
int weight;
RawSwitch swtch;
CurveReference curve; //0=symmetrisch
unsigned int delayUp;
unsigned int delayDown;
unsigned int speedUp; // Servogeschwindigkeit aus Tabelle (10ms Cycle)
unsigned int speedDown; // 0 nichts
int carryTrim;
bool noExpo;
MltpxValue mltpx; // multiplex method 0=+ 1=* 2=replace
unsigned int mixWarn; // mixer warning
unsigned int flightModes; // -5=!FP4, 0=normal, 5=FP4
int sOffset;
char name[MIXDATA_NAME_LEN+1];
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(MixData)); }
};
class LimitData {
Q_DECLARE_TR_FUNCTIONS(LimitData)
public:
LimitData() { clear(); }
int min;
int max;
bool revert;
int offset;
int ppmCenter;
bool symetrical;
char name[6+1];
CurveReference curve;
QString minToString() const;
QString maxToString() const;
QString offsetToString() const;
QString revertToString() const;
QString nameToString(int index) const;
void clear();
};
class CurvePoint {
public:
int8_t x;
int8_t y;
};
class CurveData {
Q_DECLARE_TR_FUNCTIONS(CurveData)
public:
enum CurveType {
CURVE_TYPE_STANDARD,
CURVE_TYPE_CUSTOM,
CURVE_TYPE_LAST = CURVE_TYPE_CUSTOM
};
CurveData();
void clear(int count);
bool isEmpty() const;
QString nameToString(const int idx) const;
CurveType type;
bool smooth;
int count;
CurvePoint points[CPN_MAX_POINTS];
char name[6+1];
};
class FlightModeData {
Q_DECLARE_TR_FUNCTIONS(FlightModeData)
public:
FlightModeData() { clear(0); }
int trimMode[CPN_MAX_TRIMS];
int trimRef[CPN_MAX_TRIMS];
int trim[CPN_MAX_TRIMS];
RawSwitch swtch;
char name[10+1];
unsigned int fadeIn;
unsigned int fadeOut;
int rotaryEncoders[CPN_MAX_ENCODERS];
int gvars[CPN_MAX_GVARS];
void clear(const int phase);
QString nameToString(int index) const;
void convert(RadioDataConversionState & cstate);
};
class SwashRingData {
Q_DECLARE_TR_FUNCTIONS(SwashRingData)
public:
SwashRingData() { clear(); }
int elevatorWeight;
int aileronWeight;
int collectiveWeight;
unsigned int type;
RawSource collectiveSource;
RawSource aileronSource;
RawSource elevatorSource;
unsigned int value;
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(SwashRingData)); }
};
#endif // IO_DATA_H
@@ -0,0 +1,143 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "logicalswitchdata.h"
#include "radiodata.h"
#include "radiodataconversionstate.h"
#include "rawsource.h"
#include "rawswitch.h"
bool LogicalSwitchData::isEmpty() const
{
return (func == 0);
}
CSFunctionFamily LogicalSwitchData::getFunctionFamily() const
{
if (func == LS_FN_EDGE)
return LS_FAMILY_EDGE;
else if (func == LS_FN_TIMER)
return LS_FAMILY_TIMER;
else if (func == LS_FN_STICKY)
return LS_FAMILY_STICKY;
else if (func < LS_FN_AND || func > LS_FN_ELESS)
return LS_FAMILY_VOFS;
else if (func < LS_FN_EQUAL)
return LS_FAMILY_VBOOL;
else
return LS_FAMILY_VCOMP;
}
unsigned int LogicalSwitchData::getRangeFlags() const
{
int f = 0;
if (func == LS_FN_DPOS || func == LS_FN_DAPOS)
f |= RANGE_DELTA_FUNCTION;
if (func == LS_FN_DAPOS || func == LS_FN_APOS || func == LS_FN_ANEG)
f |= RANGE_ABS_FUNCTION;
return f;
}
QString LogicalSwitchData::funcToString() const
{
switch (func) {
case LS_FN_OFF:
return tr("---");
case LS_FN_VPOS:
return tr("a>x");
case LS_FN_VNEG:
return tr("a<x");
case LS_FN_APOS:
return tr("|a|>x");
case LS_FN_ANEG:
return tr("|a|<x");
case LS_FN_AND:
return tr("AND");
case LS_FN_OR:
return tr("OR");
case LS_FN_XOR:
return tr("XOR");
case LS_FN_EQUAL:
return tr("a=b");
case LS_FN_NEQUAL:
return tr("a!=b");
case LS_FN_GREATER:
return tr("a>b");
case LS_FN_LESS:
return tr("a<b");
case LS_FN_EGREATER:
return tr("a>=b");
case LS_FN_ELESS:
return tr("a<=b");
case LS_FN_DPOS:
return tr("d>=x");
case LS_FN_DAPOS:
return tr("|d|>=x");
case LS_FN_VEQUAL:
return tr("a=x");
case LS_FN_VALMOSTEQUAL:
return tr("a~x");
case LS_FN_TIMER:
return tr("Timer");
case LS_FN_STICKY:
return tr("Sticky");
case LS_FN_EDGE:
return tr("Edge");
default:
return tr("Unknown");
}
}
QString LogicalSwitchData::nameToString(int index) const
{
return RadioData::getElementName(tr("L"), index + 1, NULL, true);
}
void LogicalSwitchData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("LSW"), 7);
cstate.setSubComp(RawSwitch(SWITCH_TYPE_VIRTUAL, cstate.subCompIdx + 1).toString(cstate.fromType, cstate.fromGS(), cstate.fromModel()));
CSFunctionFamily family = getFunctionFamily();
switch(family) {
case LS_FAMILY_VOFS:
val1 = RawSource(val1).convert(cstate.withComponentField("V1")).toValue();
break;
case LS_FAMILY_STICKY:
case LS_FAMILY_VBOOL:
val1 = RawSwitch(val1).convert(cstate.withComponentField("V1")).toValue();
val2 = RawSwitch(val2).convert(cstate.withComponentField("V2")).toValue();
break;
case LS_FAMILY_EDGE:
val1 = RawSwitch(val1).convert(cstate.withComponentField("V1")).toValue();
break;
case LS_FAMILY_VCOMP:
val1 = RawSource(val1).convert(cstate.withComponentField("V1")).toValue();
val2 = RawSource(val2).convert(cstate.withComponentField("V2")).toValue();
break;
default:
break;
}
andsw = RawSwitch(andsw).convert(cstate.withComponentField("AND")).toValue();
}
@@ -0,0 +1,89 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef LOGICALSWITCHDATA_H
#define LOGICALSWITCHDATA_H
#include <QtCore>
class RadioDataConversionState;
enum CSFunction {
LS_FN_OFF,
LS_FN_VPOS,
LS_FN_VNEG,
LS_FN_APOS,
LS_FN_ANEG,
LS_FN_AND,
LS_FN_OR,
LS_FN_XOR,
LS_FN_EQUAL,
LS_FN_NEQUAL,
LS_FN_GREATER,
LS_FN_LESS,
LS_FN_EGREATER,
LS_FN_ELESS,
LS_FN_DPOS,
LS_FN_DAPOS,
LS_FN_VEQUAL, // added at the end to avoid everything renumbered
LS_FN_VALMOSTEQUAL,
LS_FN_TIMER,
LS_FN_STICKY,
LS_FN_EDGE,
// later ... LS_FN_RANGE,
LS_FN_MAX
};
enum CSFunctionFamily {
LS_FAMILY_VOFS,
LS_FAMILY_VBOOL,
LS_FAMILY_VCOMP,
LS_FAMILY_TIMER,
LS_FAMILY_STICKY,
LS_FAMILY_EDGE,
};
class LogicalSwitchData {
Q_DECLARE_TR_FUNCTIONS(LogicalSwitchData)
public:
LogicalSwitchData(unsigned int func=0)
{
clear();
this->func = func;
}
unsigned int func;
int val1;
int val2;
int val3;
unsigned int delay;
unsigned int duration;
int andsw;
void clear() { memset(this, 0, sizeof(LogicalSwitchData)); }
bool isEmpty() const;
CSFunctionFamily getFunctionFamily() const;
unsigned int getRangeFlags() const;
QString funcToString() const;
QString nameToString(int index) const;
void convert(RadioDataConversionState & cstate);
};
#endif // LOGICALSWITCHDATA_H
+444
View File
@@ -0,0 +1,444 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "modeldata.h"
#include "eeprominterface.h"
#include "generalsettings.h"
#include "macros.h"
#include "radiodataconversionstate.h"
QString removeAccents(const QString & str)
{
// UTF-8 ASCII Table
static const QHash<QString, QVariant> map = {
{"a", QRegularExpression("[áâãàä]")},
{"A", QRegularExpression("[ÁÂÃÀÄ]")},
{"e", QRegularExpression("[éèêě]")},
{"E", QRegularExpression("[ÉÈÊĚ]")},
{"o", QRegularExpression("[óôõö]")},
{"O", QRegularExpression("[ÓÔÕÖ]")},
{"u", QRegularExpression("[úü]")},
{"U", QRegularExpression("[ÚÜ]")},
{"i", "í"}, {"I", "Í"},
{"c", "ç"}, {"C", "Ç"},
{"y", "ý"}, {"Y", "Ý"},
{"s", "š"}, {"S", "Š"},
{"r", "ř"}, {"R", "Ř"}
};
QString result(str);
for (QHash<QString, QVariant>::const_iterator it = map.cbegin(), en = map.cend(); it != en; ++it) {
if (it.value().canConvert<QRegularExpression>())
result.replace(it.value().toRegularExpression(), it.key());
else
result.replace(it.value().toString(), it.key());
}
return result;
}
/*
* TimerData
*/
void TimerData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("TMR"), 1);
cstate.setSubComp(tr("Timer %1").arg(cstate.subCompIdx + 1));
mode.convert(cstate);
}
/*
* ModelData
*/
ModelData::ModelData()
{
clear();
}
ModelData::ModelData(const ModelData & src)
{
*this = src;
}
ModelData & ModelData::operator = (const ModelData & src)
{
memcpy(reinterpret_cast<void *>(this), &src, sizeof(ModelData));
return *this;
}
ExpoData * ModelData::insertInput(const int idx)
{
memmove(&expoData[idx+1], &expoData[idx], (CPN_MAX_EXPOS-(idx+1))*sizeof(ExpoData));
expoData[idx].clear();
return &expoData[idx];
}
bool ModelData::isInputValid(const unsigned int idx) const
{
for (int i=0; i<CPN_MAX_EXPOS; i++) {
const ExpoData * expo = &expoData[i];
if (expo->mode == 0) break;
if (expo->chn == idx)
return true;
}
return false;
}
bool ModelData::hasExpos(uint8_t inputIdx) const
{
for (int i=0; i<CPN_MAX_EXPOS; i++) {
const ExpoData & expo = expoData[i];
if (expo.chn==inputIdx && expo.mode!=0) {
return true;
}
}
return false;
}
bool ModelData::hasMixes(uint8_t channelIdx) const
{
channelIdx += 1;
for (int i=0; i<CPN_MAX_MIXERS; i++) {
if (mixData[i].destCh == channelIdx) {
return true;
}
}
return false;
}
QVector<const ExpoData *> ModelData::expos(int input) const
{
QVector<const ExpoData *> result;
for (int i=0; i<CPN_MAX_EXPOS; i++) {
const ExpoData * ed = &expoData[i];
if ((int)ed->chn==input && ed->mode!=0) {
result << ed;
}
}
return result;
}
QVector<const MixData *> ModelData::mixes(int channel) const
{
QVector<const MixData *> result;
for (int i=0; i<CPN_MAX_MIXERS; i++) {
const MixData * md = &mixData[i];
if ((int)md->destCh == channel+1) {
result << md;
}
}
return result;
}
void ModelData::removeInput(const int idx, bool clearName)
{
unsigned int chn = expoData[idx].chn;
memmove(&expoData[idx], &expoData[idx+1], (CPN_MAX_EXPOS-(idx+1))*sizeof(ExpoData));
expoData[CPN_MAX_EXPOS-1].clear();
//also remove input name if removing last line for this input
if (clearName && !expos(chn).size())
inputNames[chn][0] = 0;
}
void ModelData::clearInputs()
{
for (int i=0; i<CPN_MAX_EXPOS; i++)
expoData[i].clear();
//clear all input names
if (getCurrentFirmware()->getCapability(VirtualInputs)) {
for (int i=0; i<CPN_MAX_INPUTS; i++) {
inputNames[i][0] = 0;
}
}
}
void ModelData::clearMixes()
{
for (int i=0; i<CPN_MAX_MIXERS; i++)
mixData[i].clear();
}
void ModelData::clear()
{
memset(reinterpret_cast<void *>(this), 0, sizeof(ModelData));
modelIndex = -1; // an invalid index, this is managed by the TreeView data model
moduleData[0].protocol = PULSES_OFF;
moduleData[1].protocol = PULSES_OFF;
moduleData[0].channelsCount = 8;
moduleData[1].channelsStart = 0;
moduleData[1].channelsCount = 8;
moduleData[0].ppm.delay = 300;
moduleData[1].ppm.delay = 300;
moduleData[2].ppm.delay = 300; // Trainer PPM
for (int i=0; i<CPN_MAX_FLIGHT_MODES; i++) {
flightModeData[i].clear(i);
}
for (int i=0; i<CPN_MAX_GVARS; i++) {
gvarData[i].clear();
}
clearInputs();
clearMixes();
for (int i=0; i<CPN_MAX_CHNOUT; i++)
limitData[i].clear();
for (int i=0; i<CPN_MAX_STICKS; i++)
expoData[i].clear();
for (int i=0; i<CPN_MAX_LOGICAL_SWITCHES; i++)
logicalSw[i].clear();
for (int i=0; i<CPN_MAX_SPECIAL_FUNCTIONS; i++)
customFn[i].clear();
for (int i=0; i<CPN_MAX_CURVES; i++)
curves[i].clear(5);
for (int i=0; i<CPN_MAX_TIMERS; i++)
timers[i].clear();
swashRingData.clear();
frsky.clear();
rssiAlarms.clear();
for (int i=0; i<CPN_MAX_SENSORS; i++)
sensorData[i].clear();
static const uint8_t blob[] = { 0x4c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x32, 0x50, 0x31, 0x00, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x42, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
memcpy(customScreenData[0], blob, sizeof(blob));
}
bool ModelData::isEmpty() const
{
return !used;
}
void ModelData::setDefaultInputs(const GeneralSettings & settings)
{
Board::Type board = getCurrentBoard();
if (IS_ARM(board)) {
for (int i=0; i<CPN_MAX_STICKS; i++) {
ExpoData * expo = &expoData[i];
expo->chn = i;
expo->mode = INPUT_MODE_BOTH;
expo->srcRaw = settings.getDefaultSource(i);
expo->weight = 100;
strncpy(inputNames[i], removeAccents(expo->srcRaw.toString(this)).toLatin1().constData(), sizeof(inputNames[i])-1);
}
}
}
void ModelData::setDefaultMixes(const GeneralSettings & settings)
{
Board::Type board = getCurrentBoard();
if (IS_ARM(board)) {
setDefaultInputs(settings);
}
for (int i=0; i<CPN_MAX_STICKS; i++) {
MixData * mix = &mixData[i];
mix->destCh = i+1;
mix->weight = 100;
if (IS_ARM(board)) {
mix->srcRaw = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, i);
}
else {
mix->srcRaw = RawSource(SOURCE_TYPE_STICK, i);
}
}
}
void ModelData::setDefaultValues(unsigned int id, const GeneralSettings & settings)
{
clear();
used = true;
sprintf(name, "MODEL%02d", id+1);
for (int i=0; i<CPN_MAX_MODULES; i++) {
moduleData[i].modelId = id+1;
}
setDefaultMixes(settings);
}
int ModelData::getTrimValue(int phaseIdx, int trimIdx)
{
int result = 0;
for (int i=0; i<CPN_MAX_FLIGHT_MODES; i++) {
FlightModeData & phase = flightModeData[phaseIdx];
if (phase.trimMode[trimIdx] < 0) {
return result;
}
else {
if (phase.trimRef[trimIdx] == phaseIdx || phaseIdx == 0) {
return result + phase.trim[trimIdx];
}
else {
phaseIdx = phase.trimRef[trimIdx];
if (phase.trimMode[trimIdx] != 0)
result += phase.trim[trimIdx];
}
}
}
return 0;
}
bool ModelData::isGVarLinked(int phaseIdx, int gvarIdx)
{
return flightModeData[phaseIdx].gvars[gvarIdx] > 1024;
}
int ModelData::getGVarFieldValue(int phaseIdx, int gvarIdx)
{
int idx = flightModeData[phaseIdx].gvars[gvarIdx];
for (int i=0; idx>GVAR_MAX_VALUE && i<CPN_MAX_FLIGHT_MODES; i++) {
int nextPhase = idx - GVAR_MAX_VALUE - 1;
if (nextPhase >= phaseIdx) nextPhase += 1;
phaseIdx = nextPhase;
idx = flightModeData[phaseIdx].gvars[gvarIdx];
}
return idx;
}
void ModelData::setTrimValue(int phaseIdx, int trimIdx, int value)
{
for (uint8_t i=0; i<CPN_MAX_FLIGHT_MODES; i++) {
FlightModeData & phase = flightModeData[phaseIdx];
int mode = phase.trimMode[trimIdx];
int p = phase.trimRef[trimIdx];
int & trim = phase.trim[trimIdx];
if (mode < 0)
return;
if (p == phaseIdx || phaseIdx == 0) {
trim = value;
break;;
}
else if (mode == 0) {
phaseIdx = p;
}
else {
trim = value - getTrimValue(p, trimIdx);
if (trim < -500)
trim = -500;
if (trim > 500)
trim = 500;
break;
}
}
}
void ModelData::removeGlobalVar(int & var)
{
if (var >= 126 && var <= 130)
var = flightModeData[0].gvars[var-126];
else if (var <= -126 && var >= -130)
var = - flightModeData[0].gvars[-126-var];
}
ModelData ModelData::removeGlobalVars()
{
ModelData result = *this;
for (int i=0; i<CPN_MAX_MIXERS; i++) {
removeGlobalVar(mixData[i].weight);
removeGlobalVar(mixData[i].curve.value);
removeGlobalVar(mixData[i].sOffset);
}
for (int i=0; i<CPN_MAX_EXPOS; i++) {
removeGlobalVar(expoData[i].weight);
removeGlobalVar(expoData[i].curve.value);
}
return result;
}
int ModelData::getChannelsMax(bool forceExtendedLimits) const
{
if (forceExtendedLimits || extendedLimits)
return IS_HORUS_OR_TARANIS(getCurrentBoard()) ? 150 : 125;
else
return 100;
}
bool ModelData::isAvailable(const RawSwitch & swtch) const
{
unsigned index = abs(swtch.index) - 1;
if (swtch.type == SWITCH_TYPE_VIRTUAL) {
return logicalSw[index].func != LS_FN_OFF;
}
else if (swtch.type == SWITCH_TYPE_FLIGHT_MODE) {
return index == 0 || flightModeData[index].swtch.type != SWITCH_TYPE_NONE;
}
else if (swtch.type == SWITCH_TYPE_SENSOR) {
return strlen(sensorData[index].label) > 0;
}
else {
return true;
}
}
float ModelData::getGVarFieldValuePrec(int phaseIdx, int gvarIdx)
{
return getGVarFieldValue(phaseIdx, gvarIdx) * gvarData[gvarIdx].multiplierGet();
}
void ModelData::convert(RadioDataConversionState & cstate)
{
// Here we can add explicit conversions when moving from one board to another
QString origin = QString(name);
if (origin.isEmpty())
origin = QString::number(cstate.modelIdx+1);
cstate.setOrigin(tr("Model: ") % origin);
cstate.setComponent("SET", 0);
if (thrTraceSrc && (int)thrTraceSrc < cstate.fromBoard.getCapability(Board::Pots) + cstate.fromBoard.getCapability(Board::Sliders)) {
cstate.setSubComp(tr("Throttle Source"));
thrTraceSrc = RawSource(SOURCE_TYPE_STICK, (int)thrTraceSrc + 3).convert(cstate).index - 3;
}
for (int i=0; i<CPN_MAX_TIMERS; i++) {
timers[i].convert(cstate.withComponentIndex(i));
}
for (int i=0; i<CPN_MAX_MIXERS; i++) {
mixData[i].convert(cstate.withComponentIndex(i));
}
for (int i=0; i<CPN_MAX_EXPOS; i++) {
expoData[i].convert(cstate.withComponentIndex(i));
}
for (int i=0; i<CPN_MAX_LOGICAL_SWITCHES; i++) {
logicalSw[i].convert(cstate.withComponentIndex(i));
}
for (int i=0; i<CPN_MAX_SPECIAL_FUNCTIONS; i++) {
customFn[i].convert(cstate.withComponentIndex(i));
}
for (int i=0; i<CPN_MAX_FLIGHT_MODES; i++) {
flightModeData[i].convert(cstate.withComponentIndex(i));
}
for (int i=0; i<CPN_MAX_MODULES; i++) {
moduleData[i].convert(cstate.withComponentIndex(i));
}
}
+232
View File
@@ -0,0 +1,232 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef MODELDATA_H
#define MODELDATA_H
#include "constants.h"
#include "customfunctiondata.h"
#include "gvardata.h"
#include "io_data.h"
#include "logicalswitchdata.h"
#include "moduledata.h"
#include "sensordata.h"
#include "telem_data.h"
#include <QtCore>
class GeneralSettings;
class RadioDataConversionState;
#define CHAR_FOR_NAMES " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-."
#define CHAR_FOR_NAMES_REGEX "[ A-Za-z0-9_.-,]*"
class RSSIAlarmData {
public:
RSSIAlarmData() { clear(); }
unsigned int level[2]; // AVR Only
int warning;
int critical;
bool disabled;
void clear() {
this->level[0] = 2;
this->level[1] = 3;
this->warning = 45;
this->critical = 42;
this->disabled = false;
}
};
#define TIMER_NAME_LEN 8
class TimerData {
Q_DECLARE_TR_FUNCTIONS(TimerData)
public:
enum CountDownMode {
COUNTDOWN_SILENT,
COUNTDOWN_BEEPS,
COUNTDOWN_VOICE,
COUNTDOWN_HAPTIC
};
TimerData() { clear(); }
RawSwitch mode;
char name[TIMER_NAME_LEN+1];
bool minuteBeep;
unsigned int countdownBeep;
unsigned int val;
unsigned int persistent;
int pvalue;
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(TimerData)); mode = RawSwitch(SWITCH_TYPE_TIMER_MODE, 0); }
void convert(RadioDataConversionState & cstate);
};
#define CPN_MAX_SCRIPTS 9
#define CPN_MAX_SCRIPT_INPUTS 10
class ScriptData {
public:
ScriptData() { clear(); }
char filename[10+1];
char name[10+1];
int inputs[CPN_MAX_SCRIPT_INPUTS];
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(ScriptData)); }
};
/*
* TODO ...
*/
#if 0
class CustomScreenOptionData {
public:
};
class CustomScreenZoneData {
public:
char widgetName[10+1];
WidgetOptionData widgetOptions[5];
};
class CustomScreenData {
public:
CustomScreenData();
char layoutName[10+1];
CustomScreenZoneData zones[];
CustomScreenOptionData options[];
};
#else
typedef char CustomScreenData[610+1];
typedef char TopbarData[216+1];
#endif
enum TrainerMode {
TRAINER_MODE_MASTER_TRAINER_JACK,
TRAINER_MODE_SLAVE,
TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE,
TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE,
TRAINER_MODE_MASTER_BATTERY_COMPARTMENT,
};
class ModelData {
Q_DECLARE_TR_FUNCTIONS(ModelData)
public:
ModelData();
ModelData(const ModelData & src);
ModelData & operator = (const ModelData & src);
void convert(RadioDataConversionState & cstate);
ExpoData * insertInput(const int idx);
void removeInput(const int idx, bool clearName = true);
bool isInputValid(const unsigned int idx) const;
bool hasExpos(uint8_t inputIdx) const;
bool hasMixes(uint8_t output) const;
QVector<const ExpoData *> expos(int input) const;
QVector<const MixData *> mixes(int channel) const;
bool used;
int category;
char name[15+1];
char filename[16+1];
int modelIndex; // Companion only, temporary index position managed by data model.
TimerData timers[CPN_MAX_TIMERS];
bool noGlobalFunctions;
bool thrTrim; // Enable Throttle Trim
int trimInc; // Trim Increments
unsigned int trimsDisplay;
bool disableThrottleWarning;
unsigned int beepANACenter; // 1<<0->A1.. 1<<6->A7
bool extendedLimits; // TODO xml
bool extendedTrims;
bool throttleReversed;
FlightModeData flightModeData[CPN_MAX_FLIGHT_MODES];
MixData mixData[CPN_MAX_MIXERS];
LimitData limitData[CPN_MAX_CHNOUT];
char inputNames[CPN_MAX_INPUTS][4+1];
ExpoData expoData[CPN_MAX_EXPOS];
CurveData curves[CPN_MAX_CURVES];
LogicalSwitchData logicalSw[CPN_MAX_LOGICAL_SWITCHES];
CustomFunctionData customFn[CPN_MAX_SPECIAL_FUNCTIONS];
SwashRingData swashRingData;
unsigned int thrTraceSrc;
uint64_t switchWarningStates;
unsigned int switchWarningEnable;
unsigned int potsWarningMode;
bool potsWarningEnabled[CPN_MAX_POTS];
int potPosition[CPN_MAX_POTS];
bool displayChecklist;
GVarData gvarData[CPN_MAX_GVARS];
MavlinkData mavlink;
unsigned int telemetryProtocol;
FrSkyData frsky;
RSSIAlarmData rssiAlarms;
char bitmap[10+1];
unsigned int trainerMode; // TrainerMode
ModuleData moduleData[CPN_MAX_MODULES+1/*trainer*/];
ScriptData scriptData[CPN_MAX_SCRIPTS];
SensorData sensorData[CPN_MAX_SENSORS];
unsigned int toplcdTimer;
CustomScreenData customScreenData[5];
TopbarData topbarData;
void clear();
bool isEmpty() const;
void setDefaultInputs(const GeneralSettings & settings);
void setDefaultMixes(const GeneralSettings & settings);
void setDefaultValues(unsigned int id, const GeneralSettings & settings);
int getTrimValue(int phaseIdx, int trimIdx);
void setTrimValue(int phaseIdx, int trimIdx, int value);
bool isGVarLinked(int phaseIdx, int gvarIdx);
int getGVarFieldValue(int phaseIdx, int gvarIdx);
float getGVarFieldValuePrec(int phaseIdx, int gvarIdx);
ModelData removeGlobalVars();
void clearMixes();
void clearInputs();
int getChannelsMax(bool forceExtendedLimits=false) const;
bool isAvailable(const RawSwitch & swtch) const;
protected:
void removeGlobalVar(int & var);
};
#endif // MODELDATA_H
+128
View File
@@ -0,0 +1,128 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "moduledata.h"
#include "eeprominterface.h"
#include "multiprotocols.h"
#include "radiodataconversionstate.h"
void ModuleData::convert(RadioDataConversionState & cstate)
{
if (protocol == PULSES_PXX_R9M && (IS_TARANIS_XLITE(cstate.fromType) || IS_TARANIS_XLITE(cstate.toType))) {
clear();
}
}
QString ModuleData::rfProtocolToString() const
{
switch (protocol) {
case PULSES_MULTIMODULE:
return Multiprotocols::protocolToString((int)multi.rfProtocol, multi.customProto);
default:
return CPN_STR_UNKNOWN_ITEM;
}
}
QString ModuleData::subTypeToString(int type) const
{
static const char * strings[] = {
"FCC",
"EU",
"868MHz",
"915MHz"
};
if (type < 0)
type = subType;
switch (protocol) {
case PULSES_MULTIMODULE:
return Multiprotocols::subTypeToString(multi.customProto ? MM_RF_CUSTOM_SELECTED : (int)multi.rfProtocol, (unsigned)type);
case PULSES_PXX_R9M:
return CHECK_IN_ARRAY(strings, type);
default:
return CPN_STR_UNKNOWN_ITEM;
}
}
QString ModuleData::powerValueToString(Firmware * fw) const
{
const QStringList & strRef = powerValueStrings(subType, fw);
// EU module with telemetry can only be < 100/200mW.
if (pxx.sport_out && subType == MODULE_SUBTYPE_R9M_EU && pxx.power > 1)
return CPN_STR_UNKNOWN_ITEM;
return strRef.value(pxx.power, CPN_STR_UNKNOWN_ITEM);
}
// static
QString ModuleData::indexToString(int index, Firmware * fw)
{
if (index < 0)
return tr("Trainer Port");
if (fw->getCapability(NumModules) > 1) {
if (IS_HORUS_OR_TARANIS(fw->getBoard()))
return index == 0 ? tr("Internal Radio System") : tr("External Radio Module");
if (index > 0)
return tr("Extra Radio System");
}
return tr("Radio System");
}
// static
QString ModuleData::protocolToString(unsigned protocol)
{
static const char * strings[] = {
"OFF",
"PPM",
"Silverlit A", "Silverlit B", "Silverlit C",
"CTP1009",
"LP45", "DSM2", "DSMX",
"PPM16", "PPMsim",
"FrSky XJT (D16)", "FrSky XJT (D8)", "FrSky XJT (LR12)", "FrSky DJT",
"Crossfire",
"DIY Multiprotocol Module",
"FrSky R9M Module",
"SBUS output at VBat"
};
return CHECK_IN_ARRAY(strings, protocol);
}
// static
QStringList ModuleData::powerValueStrings(int subType, Firmware * fw)
{
static const QStringList strings[] = {
{ tr("10mW - 16CH"), tr("100mW - 16CH"), tr("500mW - 16CH"), tr("Auto <= 1W - 16CH") }, // full-size FCC
{ tr("25mW - 8CH"), tr("25mW - 16CH"), tr("200mW - 16CH (no telemetry)"), tr("500mW - 16CH (no telemetry)") }, // full-size EU
{ tr("100mW - 16CH") }, // mini FCC
{ tr("25mW - 8CH"), tr("25mW - 16CH"), tr("100mW - 16CH (no telemetry)") } // mini EU
};
int strIdx = 0;
if (subType == MODULE_SUBTYPE_R9M_EU)
strIdx += 1;
if (fw->getCapability(HasModuleR9MMini))
strIdx += 2;
return strings[strIdx];
}
+170
View File
@@ -0,0 +1,170 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef MODULEDATA_H
#define MODULEDATA_H
#include "constants.h"
#include <QtCore>
class Firmware;
class RadioDataConversionState;
enum PulsesProtocol {
PULSES_OFF,
PULSES_PPM,
PULSES_SILV_A,
PULSES_SILV_B,
PULSES_SILV_C,
PULSES_CTP1009,
PULSES_LP45,
PULSES_DSM2,
PULSES_DSMX,
PULSES_PPM16,
PULSES_PPMSIM,
PULSES_PXX_XJT_X16,
PULSES_PXX_XJT_D8,
PULSES_PXX_XJT_LR12,
PULSES_PXX_DJT,
PULSES_CROSSFIRE,
PULSES_MULTIMODULE,
PULSES_PXX_R9M,
PULSES_SBUS,
PULSES_PROTOCOL_LAST
};
enum MultiModuleRFProtocols {
MM_RF_PROTO_FLYSKY=0,
MM_RF_PROTO_FIRST=MM_RF_PROTO_FLYSKY,
MM_RF_PROTO_HUBSAN,
MM_RF_PROTO_FRSKY,
MM_RF_PROTO_HISKY,
MM_RF_PROTO_V2X2,
MM_RF_PROTO_DSM2,
MM_RF_PROTO_DEVO,
MM_RF_PROTO_YD717,
MM_RF_PROTO_KN,
MM_RF_PROTO_SYMAX,
MM_RF_PROTO_SLT,
MM_RF_PROTO_CX10,
MM_RF_PROTO_CG023,
MM_RF_PROTO_BAYANG,
MM_RF_PROTO_ESky,
MM_RF_PROTO_MT99XX,
MM_RF_PROTO_MJXQ,
MM_RF_PROTO_SHENQI,
MM_RF_PROTO_FY326,
MM_RF_PROTO_SFHSS,
MM_RF_PROTO_J6PRO,
MM_RF_PROTO_FQ777,
MM_RF_PROTO_ASSAN,
MM_RF_PROTO_HONTAI,
MM_RF_PROTO_OLRS,
MM_RF_PROTO_FS_AFHDS2A,
MM_RF_PROTO_Q2X2,
MM_RF_PROTO_WK_2X01,
MM_RF_PROTO_Q303,
MM_RF_PROTO_GW008,
MM_RF_PROTO_DM002,
MM_RF_PROTO_CABELL,
MM_RF_PROTO_ESKY150,
MM_RF_PROTO_H83D,
MM_RF_PROTO_CORONA,
MM_RF_PROTO_CFLIE,
MM_RF_PROTO_HITEC,
MM_RF_PROTO_WFLY,
MM_RF_PROTO_BUGS,
MM_RF_PROTO_BUGS_MINI,
MM_RF_PROTO_TRAXXAS,
MM_RF_PROTO_NCC1701,
MM_RF_PROTO_E01X,
MM_RF_PROTO_V911S,
MM_RF_PROTO_GD00X,
MM_RF_PROTO_LAST = MM_RF_PROTO_GD00X
};
enum TrainerProtocol {
TRAINER_MASTER_JACK,
TRAINER_SLAVE_JACK,
TRAINER_MASTER_SBUS_MODULE,
TRAINER_MASTER_CPPM_MODULE,
TRAINER_MASTER_SBUS_BATT_COMPARTMENT
};
enum R9MSubTypes {
MODULE_SUBTYPE_R9M_FCC,
MODULE_SUBTYPE_R9M_EU,
MODULE_SUBTYPE_R9M_EUPLUS,
MODULE_SUBTYPE_R9M_AUPLUS,
MODULE_SUBTYPE_R9M_LAST=MODULE_SUBTYPE_R9M_AUPLUS
};
class ModuleData {
Q_DECLARE_TR_FUNCTIONS(ModuleData)
public:
ModuleData() { clear(); }
unsigned int modelId;
int protocol;
unsigned int subType;
bool invertedSerial;
unsigned int channelsStart;
int channelsCount; // 0=8 channels
unsigned int failsafeMode;
int failsafeChannels[CPN_MAX_CHNOUT];
struct {
int delay;
bool pulsePol; // false = positive
bool outputType; // false = open drain, true = push pull
int frameLength;
} ppm;
struct {
unsigned int rfProtocol;
bool autoBindMode;
bool lowPowerMode;
bool customProto;
int optionValue;
} multi;
struct {
int power; // 0 10 mW, 1 100 mW, 2 500 mW, 3 1W
bool receiver_telem_off; // false = receiver telem enabled
bool receiver_channel_9_16; // false = pwm out 1-8, true 9-16
bool external_antenna; // false = internal antenna, true = external antenna
bool sport_out;
} pxx;
void clear() { memset(this, 0, sizeof(ModuleData)); }
void convert(RadioDataConversionState & cstate);
QString polarityToString() const { return ppm.pulsePol ? tr("Positive") : tr("Negative"); }
QString rfProtocolToString() const;
QString subTypeToString(int type = -1) const;
QString powerValueToString(Firmware * fw) const;
static QString indexToString(int index, Firmware * fw);
static QString protocolToString(unsigned protocol);
static QStringList powerValueStrings(int subType, Firmware * fw);
};
#endif // MODULEDATA_H
@@ -37,27 +37,32 @@ static const QStringList STR_SUBTYPE_CUSTOM ({
STR_MULTI_SUBTYPE " 4", STR_MULTI_SUBTYPE " 5", STR_MULTI_SUBTYPE " 6", STR_MULTI_SUBTYPE " 7"
});
static const QStringList STR_SUBTYPE_FLYSKY {"Standard", "V9x9", "V6x6", "V912", "CX20"};
static const QStringList STR_SUBTYPE_HUBSAN {"H107", "H301", "H501"};
static const QStringList STR_SUBTYPE_FRSKY {"D16", "D8", "D16 8ch", "V8", "D16 EU-LBT", "D16 EU-LBT 8ch"};
static const QStringList STR_SUBTYPE_HISKY {"HiSky", "HK310"};
static const QStringList STR_SUBTYPE_V2X2 {"V2x2", "JXD506"};
static const QStringList STR_SUBTYPE_HISKY {"Standard", "HK310"};
static const QStringList STR_SUBTYPE_V2X2 {"Standard", "JXD506"};
static const QStringList STR_SUBTYPE_DSM {"DSM2 22ms", "DSM2 11ms", "DSMX 22ms", "DSMX 11ms"};
static const QStringList STR_SUBTYPE_YD717 {"YD717", "Skywalker", "Syma X2", "XINXUN", "NIHUI"};
static const QStringList STR_SUBTYPE_SYMAX {"Standard", "Syma X5C"};
static const QStringList STR_SUBTYPE_SLT {"SLT", "Vista"};
static const QStringList STR_SUBTYPE_CX10 {"Green", "Blue", "DM007", "-", "JC3015a", "JC3015b", "MK33041", "Q242"};
static const QStringList STR_SUBTYPE_CG023 {"CG023", "YD829"};
static const QStringList STR_SUBTYPE_BAYANG {"Bayang", "H8S3D", "X16 AH", "IRDRONE"};
static const QStringList STR_SUBTYPE_YD717 {"Standard", "Skywalker", "Syma X4", "XINXUN", "NIHUI"};
static const QStringList STR_SUBTYPE_KN {"WLtoys", "FeiLun"};
static const QStringList STR_SUBTYPE_SYMAX {"Standard", "Syma X5C"};
static const QStringList STR_SUBTYPE_SLT {"V1 (6 Channel)", "V2 (8 Channel)", "Q100", "Q200", "MR100"};
static const QStringList STR_SUBTYPE_CX10 {"Green", "Blue", "DM007", "-", "JC3015a", "JC3015b", "MK33041"};
static const QStringList STR_SUBTYPE_CG023 {"Standard", "YD829"};
static const QStringList STR_SUBTYPE_BAYANG {"Standard", "H8S3D", "X16 AH", "IRDRONE"};
static const QStringList STR_SUBTYPE_MT99 {"MT99", "H7", "YZ", "LS", "FY805"};
static const QStringList STR_SUBTYPE_MJXQ {"WLH08", "X600", "X800", "H26D", "E010", "H26WH"};
static const QStringList STR_SUBTYPE_FY326 {"FY326", "FY319"};
static const QStringList STR_SUBTYPE_HONTAI {"Standard", "JJRC X1", "X5C1 Clone"};
static const QStringList STR_SUBTYPE_FY326 {"Standard", "FY319"};
static const QStringList STR_SUBTYPE_HONTAI {"Standard", "JJRC X1", "X5C1 Clone", "FQ777_951"};
static const QStringList STR_SUBTYPE_AFHDS2A {"PWM and IBUS", "PPM and IBUS", "PWM and SBUS", "PPM and SBUS"};
static const QStringList STR_SUBTYPE_Q2X2 {"Q222", "Q242", "Q282"};
static const QStringList STR_SUBTYPE_WK2x01 {"WK2801", "WK2401", "W6_5_1", "W6_6_1", "W6_HEL", "W6_HEL_I"};
static const QStringList STR_SUBTYPE_Q303 {"Q303", "CX35", "CX10D", "CX10WD"};
static const QStringList STR_SUBTYPE_CABELL {"CABELL V3","C TELEM","-","-","-","-","F_SAFE","UNBIND"};
static const QStringList STR_SUBTYPE_H83D {"H8_3D","H20H","H20Mini","H30Mini"};
static const QStringList STR_SUBTYPE_Q303 {"Standard", "CX35", "CX10D", "CX10WD"};
static const QStringList STR_SUBTYPE_CABELL {"Cabell V3", "Cab V3 Telem", "-", "-", "-", "-", "Set FailSafe", "Unbind"};
static const QStringList STR_SUBTYPE_H83D {"H8 Mini 3D", "H20H", "H20 Mini", "H30 Mini"};
static const QStringList STR_SUBTYPE_CORONA {"V1", "V2", "Flydream V3"};
static const QStringList STR_SUBTYPE_HITEC {"Optima", "Optima Hub Telem", "Minima"};
static const QStringList STR_SUBTYPE_E01X {"E012", "E015"};
static const QStringList NO_SUBTYPE {STR_MULTI_DEFAULT};
@@ -65,7 +70,7 @@ static const QStringList NO_SUBTYPE {STR_MULTI_DEFAULT};
const Multiprotocols multiProtocols {
{MM_RF_PROTO_FLYSKY, 4, false, STR_SUBTYPE_FLYSKY, nullptr},
{MM_RF_PROTO_HUBSAN, 0, false, NO_SUBTYPE, STR_MULTI_VIDFREQ},
{MM_RF_PROTO_HUBSAN, 2, false, STR_SUBTYPE_HUBSAN, STR_MULTI_VIDFREQ},
{MM_RF_PROTO_FRSKY, 5, false, STR_SUBTYPE_FRSKY, STR_MULTI_RFTUNE},
{MM_RF_PROTO_HISKY, 1, false, STR_SUBTYPE_HISKY, nullptr},
{MM_RF_PROTO_V2X2, 1, false, STR_SUBTYPE_V2X2, nullptr},
@@ -73,15 +78,15 @@ const Multiprotocols multiProtocols {
{MM_RF_PROTO_YD717, 4, false, STR_SUBTYPE_YD717, nullptr},
{MM_RF_PROTO_KN, 1, false, STR_SUBTYPE_KN, nullptr},
{MM_RF_PROTO_SYMAX, 1, false, STR_SUBTYPE_SYMAX, nullptr},
{MM_RF_PROTO_SLT, 1, false, STR_SUBTYPE_SLT, nullptr},
{MM_RF_PROTO_CX10, 7, false, STR_SUBTYPE_CX10, nullptr},
{MM_RF_PROTO_SLT, 4, false, STR_SUBTYPE_SLT, nullptr},
{MM_RF_PROTO_CX10, 6, false, STR_SUBTYPE_CX10, nullptr},
{MM_RF_PROTO_CG023, 1, false, STR_SUBTYPE_CG023, nullptr},
{MM_RF_PROTO_BAYANG, 3, false, STR_SUBTYPE_BAYANG, STR_MULTI_TELEMETRY},
{MM_RF_PROTO_MT99XX, 4, false, STR_SUBTYPE_MT99, nullptr},
{MM_RF_PROTO_MJXQ, 5, false, STR_SUBTYPE_MJXQ, nullptr},
{MM_RF_PROTO_FY326, 1, false, STR_SUBTYPE_FY326, nullptr},
{MM_RF_PROTO_SFHSS, 0, true, NO_SUBTYPE, STR_MULTI_RFTUNE},
{MM_RF_PROTO_HONTAI, 2, false, STR_SUBTYPE_HONTAI, nullptr},
{MM_RF_PROTO_HONTAI, 3, false, STR_SUBTYPE_HONTAI, nullptr},
{MM_RF_PROTO_OLRS, 0, false, NO_SUBTYPE, STR_MULTI_RFPOWER},
{MM_RF_PROTO_FS_AFHDS2A, 3, true, STR_SUBTYPE_AFHDS2A, STR_MULTI_SERVOFREQ},
{MM_RF_PROTO_Q2X2, 2, false, STR_SUBTYPE_Q2X2, nullptr},
@@ -89,6 +94,9 @@ const Multiprotocols multiProtocols {
{MM_RF_PROTO_Q303, 3, false, STR_SUBTYPE_Q303, nullptr},
{MM_RF_PROTO_CABELL, 7, false, STR_SUBTYPE_CABELL, STR_MULTI_OPTION},
{MM_RF_PROTO_H83D, 3, false, STR_SUBTYPE_H83D, nullptr},
{MM_RF_PROTO_CORONA, 2, false, STR_SUBTYPE_CORONA, STR_MULTI_RFTUNE},
{MM_RF_PROTO_HITEC, 2, false, STR_SUBTYPE_HITEC, STR_MULTI_RFTUNE},
{MM_RF_PROTO_E01X, 1, false, STR_SUBTYPE_E01X, nullptr},
{MM_RF_CUSTOM_SELECTED, 7, true, STR_SUBTYPE_CUSTOM, STR_MULTI_OPTION},
// Sentinel and default for protocols not listed above (MM_RF_CUSTOM is 0xff)
@@ -122,3 +130,25 @@ const Multiprotocols::MultiProtocolDefinition & Multiprotocols::getProtocol(int
Q_ASSERT(protocols.rbegin()->protocol == 0xfe);
return *protocols.rbegin();
}
// static
QString Multiprotocols::protocolToString(int protocol, bool custom)
{
static const QStringList strings({
"FlySky", "Hubsan", "FrSky", "Hisky", "V2x2", "DSM", "Devo", "YD717", "KN", "SymaX", "SLT", "CX10", "CG023",
"Bayang", "ESky", "MT99XX", "MJXQ", "Shenqi", "FY326", "SFHSS", "J6 PRO","FQ777","Assan","Hontai","Open LRS",
"FlySky AFHDS2A", "Q2x2", "Walkera", "Q303", "GW008", "DM002", "Cabell", "ESky 150", "H8 3D", "Corona", "CFlie",
"Hitec", "Wfly", "Bugs", "Bugs Mini", "Traxxas", "NCC-1701-A", "E01X", "V911S", "GD00X"
});
if (protocol == MM_RF_CUSTOM_SELECTED || custom)
return tr("Custom - proto %1)").arg(protocol);
else
return strings.value(protocol, CPN_STR_UNKNOWN_ITEM);
}
// static
QString Multiprotocols::subTypeToString(int protocol, unsigned subType)
{
return tr(qPrintable(multiProtocols.getProtocol(protocol).subTypeStrings.value(subType, CPN_STR_UNKNOWN_ITEM)));
}
@@ -22,14 +22,14 @@
#define OPENTX_MULTI_H
#include <vector>
#include <QString>
#include <QVector>
#include <QStringList>
#include <QtCore>
#define MM_RF_CUSTOM_SELECTED 0xff
class Multiprotocols
{
Q_DECLARE_TR_FUNCTIONS(Multiprotocols)
public:
struct radio_mm_definition {
@@ -46,7 +46,7 @@ class Multiprotocols
const QStringList subTypeStrings;
const QString optionsstr;
unsigned int numSubytes() const
unsigned int numSubTypes() const
{
return (unsigned int) subTypeStrings.length();
}
@@ -72,6 +72,8 @@ class Multiprotocols
}
const MultiProtocolDefinition &getProtocol(int protocol) const;
static QString protocolToString(int protocol, bool custom = false);
static QString subTypeToString(int protocol, unsigned subType);
private:
+28 -27
View File
@@ -18,6 +18,7 @@
* GNU General Public License for more details.
*/
#include "boards.h"
#include "helpers.h"
#include "opentxeeprom.h"
#include "customdebug.h"
@@ -32,18 +33,18 @@ using namespace Board;
#define HAS_PERSISTENT_TIMERS(board) (IS_ARM(board) || IS_2560(board))
#define MAX_VIEWS(board) (HAS_LARGE_LCD(board) ? 2 : 256)
#define MAX_POTS(board, version) (IS_HORUS(board) ? 3 : (IS_TARANIS_X7(board) ? 2 : (IS_TARANIS(board) ? (IS_TARANIS_X9E(board) ? 4 : (version >= 216 ? 3 : 2)) : 3)))
#define MAX_SLIDERS(board) (IS_HORUS(board) ? 4 : (IS_TARANIS_X7(board) ? 0 : (IS_TARANIS(board) ? (IS_TARANIS_X9E(board) ? 4 : 2) : 0)))
#define MAX_MOUSE_ANALOGS(board) (IS_HORUS(board) ? 2 : 0)
#define MAX_SWITCHES(board, version) (IS_HORUS(board) ? 8 : (IS_TARANIS_X7(board) ? 6 : (IS_TARANIS(board) ? (IS_TARANIS_X9E(board) ? 18 : 8) : 7)))
#define MAX_SWITCH_SLOTS(board, version) (IS_TARANIS_X9E(board) ? 32 : 8)
#define MAX_SWITCHES_POSITION(board, version) (IS_TARANIS_X7(board) ? 6*3 : (IS_TARANIS_X9E(board) ? 18*3 : (IS_HORUS_OR_TARANIS(board) ? 8*3 : 9)))
#define MAX_POTS(board, version) (IS_TARANIS_NOT_X9E(board) && version < 216 ? 2 : Boards::getCapability(board, Board::Pots))
#define MAX_SLIDERS(board) (IS_HORUS_X10(board) ? 4 : (Boards::getCapability(board, Board::Sliders))) //TODO need to be remove when x10 eeprom gets fixed
#define MAX_MOUSE_ANALOGS(board) (IS_HORUS_X10(board) ? 2 : (Boards::getCapability(board, Board::MouseAnalogs))) //TODO need to be remove when x10 eeprom gets fixed
#define MAX_SWITCHES(board, version) (Boards::getCapability(board, Board::Switches))
#define MAX_SWITCH_SLOTS(board, version) (IS_TARANIS_X9E(board) ? 32 : 8) // bitsize of swconfig_t / 2 (see radio/src/datastructs.h)
#define MAX_SWITCHES_POSITION(board, version) (Boards::getCapability(board, Board::SwitchPositions))
#define MAX_ROTARY_ENCODERS(board) (IS_2560(board) ? 2 : (IS_SKY9X(board) ? 1 : 0))
#define MAX_FLIGHT_MODES(board, version) (IS_ARM(board) ? 9 : (IS_DBLRAM(board, version) ? 6 : 5))
#define MAX_TIMERS(board, version) ((IS_ARM(board) && version >= 217) ? 3 : 2)
#define MAX_MIXERS(board, version) (IS_ARM(board) ? 64 : 32)
#define MAX_CHANNELS(board, version) (IS_ARM(board) ? 32 : 16)
#define MAX_TRIMS(board) (IS_HORUS(board) ? 6 : 4)
#define MAX_TRIMS(board) (Boards::getCapability(board, Board::NumTrims))
#define MAX_EXPOS(board, version) (IS_ARM(board) ? ((IS_HORUS_OR_TARANIS(board) && version >= 216) ? 64 : 32) : (IS_DBLRAM(board, version) ? 16 : 14))
#define MAX_LOGICAL_SWITCHES(board, version) (IS_ARM(board) ? (version >= 218 ? 64 : 32) : ((IS_DBLEEPROM(board, version) && version<217) ? 15 : 12))
#define MAX_CUSTOM_FUNCTIONS(board, version) (IS_ARM(board) ? (version >= 216 ? 64 : 32) : (IS_DBLEEPROM(board, version) ? 24 : 16))
@@ -348,11 +349,11 @@ class SourcesConversionTable: public ConversionTable {
for (int i=0; i<TELEMETRY_SOURCE_ACC; i++) {
if (version < 216) {
if (i==TELEMETRY_SOURCE_TX_TIME || i==TELEMETRY_SOURCE_SWR || i==TELEMETRY_SOURCE_A3 || i==TELEMETRY_SOURCE_A4 || i==TELEMETRY_SOURCE_ASPEED || i==TELEMETRY_SOURCE_DTE || i==TELEMETRY_SOURCE_CELL_MIN || i==TELEMETRY_SOURCE_CELLS_MIN || i==TELEMETRY_SOURCE_VFAS_MIN)
if (i==TELEMETRY_SOURCE_TX_TIME || i==TELEMETRY_SOURCE_RAS || i==TELEMETRY_SOURCE_A3 || i==TELEMETRY_SOURCE_A4 || i==TELEMETRY_SOURCE_ASPEED || i==TELEMETRY_SOURCE_DTE || i==TELEMETRY_SOURCE_CELL_MIN || i==TELEMETRY_SOURCE_CELLS_MIN || i==TELEMETRY_SOURCE_VFAS_MIN)
continue;
}
if (!IS_ARM(board)) {
if (i==TELEMETRY_SOURCE_TX_TIME || i==TELEMETRY_SOURCE_SWR || i==TELEMETRY_SOURCE_A3 || i==TELEMETRY_SOURCE_A4 || i==TELEMETRY_SOURCE_A3_MIN || i==TELEMETRY_SOURCE_A4_MIN)
if (i==TELEMETRY_SOURCE_TX_TIME || i==TELEMETRY_SOURCE_RAS || i==TELEMETRY_SOURCE_A3 || i==TELEMETRY_SOURCE_A4 || i==TELEMETRY_SOURCE_A3_MIN || i==TELEMETRY_SOURCE_A4_MIN)
continue;
}
addConversion(RawSource(SOURCE_TYPE_TELEMETRY, i), val++);
@@ -433,8 +434,8 @@ template <int N>
class SwitchField: public ConversionField< SignedField<N> > {
public:
SwitchField(DataField * parent, RawSwitch & sw, Board::Type board, unsigned int version, unsigned long flags=0):
ConversionField< SignedField<N> >(parent, _switch, SwitchesConversionTable::getInstance(board, version, flags), QObject::tr("Switch").toLatin1(),
QObject::tr("Switch ").toLatin1() + sw.toString(board) + QObject::tr(" cannot be exported on this board!").toLatin1()),
ConversionField< SignedField<N> >(parent, _switch, SwitchesConversionTable::getInstance(board, version, flags), DataField::tr("Switch").toLatin1(),
DataField::tr("Switch ").toLatin1() + sw.toString(board) + DataField::tr(" cannot be exported on this board!").toLatin1()),
sw(sw),
_switch(0),
board(board)
@@ -486,7 +487,7 @@ class TelemetrySourcesConversionTable: public ConversionTable {
if (IS_ARM(board) && version >= 217)
addConversion(1+TELEMETRY_SOURCE_TIMER3, val++);
if (IS_ARM(board) && version >= 216)
addConversion(1+TELEMETRY_SOURCE_SWR, val++);
addConversion(1+TELEMETRY_SOURCE_RAS, val++);
addConversion(1+TELEMETRY_SOURCE_RSSI_TX, val++);
addConversion(1+TELEMETRY_SOURCE_RSSI_RX, val++);
if (IS_ARM(board) && version >= 216)
@@ -597,7 +598,7 @@ class SourceField: public ConversionField< UnsignedField<N> > {
public:
SourceField(DataField * parent, RawSource & source, Board::Type board, unsigned int version, unsigned int variant, unsigned long flags=0):
ConversionField< UnsignedField<N> >(parent, _source, SourcesConversionTable::getInstance(board, version, variant, flags),
"Source", QObject::tr("Source %1 cannot be exported on this board!").arg(source.toString())),
DataField::tr("Source").toLatin1(), DataField::tr("Source %1 cannot be exported on this board!").arg(source.toString())),
source(source),
_source(0)
{
@@ -1569,14 +1570,14 @@ class CurvesField: public TransformedField {
if (IS_STM32(board) && version >= 216) {
offset += (curve->type == CurveData::CURVE_TYPE_CUSTOM ? curve->count * 2 - 2 : curve->count);
if (offset > maxPoints) {
setError(QObject::tr("OpenTX only accepts %1 points in all curves").arg(maxPoints));
setError(DataField::tr("OpenTX only accepts %1 points in all curves").arg(maxPoints));
break;
}
}
else {
offset += (curve->type == CurveData::CURVE_TYPE_CUSTOM ? curve->count * 2 - 2 : curve->count) - 5;
if (offset > maxPoints - 5 * maxCurves) {
setError(QObject::tr("OpenTx only accepts %1 points in all curves").arg(maxPoints));
setError(DataField::tr("OpenTx only accepts %1 points in all curves").arg(maxPoints));
break;
}
_curves[i] = offset;
@@ -2154,11 +2155,11 @@ class ArmCustomFunctionField: public TransformedField {
if (version >= 218) {
internalField.Append(new SwitchField<9>(this, fn.swtch, board, version));
internalField.Append(new ConversionField< UnsignedField<7> >(this, _func, &functionsConversionTable, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
internalField.Append(new ConversionField< UnsignedField<7> >(this, _func, &functionsConversionTable, "Function", DataField::tr("OpenTX on this board doesn't accept this function")));
}
else {
internalField.Append(new SwitchField<8>(this, fn.swtch, board, version));
internalField.Append(new ConversionField< UnsignedField<8> >(this, _func, &functionsConversionTable, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
internalField.Append(new ConversionField< UnsignedField<8> >(this, _func, &functionsConversionTable, "Function", DataField::tr("OpenTX on this board doesn't accept this function")));
}
if (IS_TARANIS(board) && version >= 216)
@@ -2394,7 +2395,7 @@ class AvrCustomFunctionField: public TransformedField {
{
if (version >= 217 && IS_2560(board)) {
internalField.Append(new SwitchField<8>(this, fn.swtch, board, version));
internalField.Append(new ConversionField< UnsignedField<8> >(this, (unsigned int &)fn.func, &functionsConversionTable, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
internalField.Append(new ConversionField< UnsignedField<8> >(this, (unsigned int &)fn.func, &functionsConversionTable, "Function", DataField::tr("OpenTX on this board doesn't accept this function")));
internalField.Append(new UnsignedField<2>(this, fn.adjustMode));
internalField.Append(new UnsignedField<4>(this, _union_param));
internalField.Append(new UnsignedField<1>(this, _active));
@@ -2402,18 +2403,18 @@ class AvrCustomFunctionField: public TransformedField {
}
else if (version >= 216) {
internalField.Append(new SwitchField<6>(this, fn.swtch, board, version));
internalField.Append(new ConversionField< UnsignedField<4> >(this, (unsigned int &)fn.func, &functionsConversionTable, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
internalField.Append(new ConversionField< UnsignedField<4> >(this, (unsigned int &)fn.func, &functionsConversionTable, "Function", DataField::tr("OpenTX on this board doesn't accept this function")));
internalField.Append(new UnsignedField<5>(this, _union_param));
internalField.Append(new UnsignedField<1>(this, _active));
}
else if (version >= 213) {
internalField.Append(new SwitchField<8>(this, fn.swtch, board, version));
internalField.Append(new UnsignedField<3>(this, _union_param));
internalField.Append(new ConversionField< UnsignedField<5> >(this, (unsigned int &)fn.func, &functionsConversionTable, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
internalField.Append(new ConversionField< UnsignedField<5> >(this, (unsigned int &)fn.func, &functionsConversionTable, "Function", DataField::tr("OpenTX on this board doesn't accept this function")));
}
else {
internalField.Append(new SwitchField<8>(this, fn.swtch, board, version));
internalField.Append(new ConversionField< UnsignedField<7> >(this, (unsigned int &)fn.func, &functionsConversionTable, "Function", ::QObject::tr("OpenTX on this board doesn't accept this function")));
internalField.Append(new ConversionField< UnsignedField<7> >(this, (unsigned int &)fn.func, &functionsConversionTable, "Function", DataField::tr("OpenTX on this board doesn't accept this function")));
internalField.Append(new BoolField<1>(this, (bool &)fn.enabled));
}
internalField.Append(new UnsignedField<8>(this, _param));
@@ -3137,7 +3138,7 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig
if (IS_ARM(board))
internalField.Append(new UnsignedField<3>(this, modelData.telemetryProtocol));
else
internalField.Append(new ConversionField< UnsignedField<3> >(this, (unsigned int &)modelData.moduleData[0].protocol, &protocolsConversionTable, "Protocol", ::QObject::tr("OpenTX doesn't accept this telemetry protocol")));
internalField.Append(new ConversionField< UnsignedField<3> >(this, (unsigned int &)modelData.moduleData[0].protocol, &protocolsConversionTable, "Protocol", DataField::tr("OpenTX doesn't accept this telemetry protocol")));
internalField.Append(new BoolField<1>(this, modelData.thrTrim));
@@ -3150,7 +3151,7 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig
internalField.Append(new SpareBitsField<4>(this));
}
else {
internalField.Append(new ConversionField< SignedField<4> >(this, modelData.moduleData[0].channelsCount, &channelsConversionTable, "Channels number", ::QObject::tr("OpenTX doesn't allow this number of channels")));
internalField.Append(new ConversionField< SignedField<4> >(this, modelData.moduleData[0].channelsCount, &channelsConversionTable, "Channels number", DataField::tr("OpenTX doesn't allow this number of channels")));
}
if (version >= 216)
@@ -3272,7 +3273,7 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig
internalField.Append(new UnsignedField<2>(this, modelData.potsWarningMode));
}
else {
internalField.Append(new ConversionField< SignedField<8> >(this, modelData.moduleData[1].protocol, &protocolsConversionTable, "Protocol", ::QObject::tr("OpenTX doesn't accept this radio protocol")));
internalField.Append(new ConversionField< SignedField<8> >(this, modelData.moduleData[1].protocol, &protocolsConversionTable, "Protocol", DataField::tr("OpenTX doesn't accept this radio protocol")));
internalField.Append(new UnsignedField<8>(this, modelData.trainerMode));
}
}
@@ -3284,14 +3285,14 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig
}
else if (version >= 216) {
modulesCount = 3;
internalField.Append(new ConversionField< SignedField<8> >(this, modelData.moduleData[0].protocol, &protocolsConversionTable, "Protocol", ::QObject::tr("OpenTX doesn't accept this radio protocol")));
internalField.Append(new ConversionField< SignedField<8> >(this, modelData.moduleData[0].protocol, &protocolsConversionTable, "Protocol", DataField::tr("OpenTX doesn't accept this radio protocol")));
}
}
if (IS_ARM(board) && version >= 215) {
for (int module=0; module<modulesCount; module++) {
if (version >= 217) {
internalField.Append(new ConversionField<SignedField<4> >(this, modelData.moduleData[module].protocol, &protocolsConversionTable, "Protocol", ::QObject::tr("OpenTX doesn't accept this radio protocol")));
internalField.Append(new ConversionField<SignedField<4> >(this, modelData.moduleData[module].protocol, &protocolsConversionTable, "Protocol", DataField::tr("OpenTX doesn't accept this radio protocol")));
internalField.Append(new SignedField<4>(this, subprotocols[module]));
}
else {
@@ -3835,7 +3836,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
internalField.Append(new ZCharField<10>(this, generalData.bluetoothName, "Bluetooth name"));
}
else if (IS_TARANIS_X9E(board) && version >= 217) {
internalField.Append(new BoolField<8>(this, generalData.bluetoothEnable));
internalField.Append(new UnsignedField<8>(this, generalData.bluetoothMode));
internalField.Append(new ZCharField<10>(this, generalData.bluetoothName, "Bluetooth name"));
}
@@ -32,6 +32,7 @@
#define M128_VARIANT 0x8000
#define TARANIS_X9E_VARIANT 0x8000
#define TARANIS_X7_VARIANT 0x4000
#define TARANIS_XLITE_VARIANT 0x2000
#define SIMU_STOCK_VARIANTS (GVARS_VARIANT|FRSKY_VARIANT)
#define SIMU_M128_VARIANTS (M128_VARIANT|SIMU_STOCK_VARIANTS)
+163 -456
View File
@@ -22,19 +22,14 @@
#include "opentxeeprom.h"
#include "rlefile.h"
#include "appdata.h"
#include "constants.h"
#include <bitset>
#include <QMessageBox>
#include <QTime>
#include <QUrl>
#include <companion/src/storage/storage.h>
using namespace Board;
const char * const OPENTX_FIRMWARE_DOWNLOAD_URL[] = {
"https://downloads.open-tx.org/2.2/release/firmware",
"https://downloads.open-tx.org/2.2/rc/firmware",
"https://downloads.open-tx.org/2.2/nightlies/firmware"
};
#include "storage.h" // does this need to be last include?
#define FILE_TYP_GENERAL 1
#define FILE_TYP_MODEL 2
@@ -44,12 +39,9 @@ const char * const OPENTX_FIRMWARE_DOWNLOAD_URL[] = {
/// convert model number 0..MAX_MODELS-1 int fileId
#define FILE_MODEL(n) (1+n)
template<typename T, size_t N>
inline
size_t SizeOfArray(T(&)[N])
{
return N;
}
using namespace Board;
QList<OpenTxEepromInterface *> opentxEEpromInterfaces;
OpenTxEepromInterface::OpenTxEepromInterface(OpenTxFirmware * firmware):
EEPROMInterface(firmware->getBoard()),
@@ -82,14 +74,14 @@ const char * OpenTxEepromInterface::getName()
return "OpenTX for FrSky Taranis X9E";
case BOARD_TARANIS_X7:
return "OpenTX for FrSky Taranis X7";
case BOARD_TARANIS_XLITE:
return "OpenTX for FrSky Taranis X-Lite";
case BOARD_SKY9X:
return "OpenTX for Sky9x board / 9X";
case BOARD_9XRPRO:
return "OpenTX for 9XR-PRO";
case BOARD_AR9X:
return "OpenTX for ar9x board / 9X";
case BOARD_FLAMENCO:
return "OpenTX for Flamenco experimental";
case BOARD_X12S:
return "OpenTX for FrSky Horus";
case BOARD_X10:
@@ -143,7 +135,7 @@ bool OpenTxEepromInterface::saveToByteArray(const T & src, QByteArray & data, ui
// manager.Dump();
manager.Export(raw);
data.resize(8);
*((uint32_t*)&data.data()[0]) = StorageFormat::getFourCC(board);
*((uint32_t*)&data.data()[0]) = Boards::getFourCC(board);
data[4] = version;
data[5] = 'M';
*((uint16_t*)&data.data()[6]) = raw.size();
@@ -166,12 +158,12 @@ template <class T, class M>
bool OpenTxEepromInterface::loadFromByteArray(T & dest, const QByteArray & data)
{
uint32_t fourcc = *((uint32_t*)&data.data()[0]);
if (StorageFormat::getFourCC(board) != fourcc) {
if (Boards::getFourCC(board) != fourcc) {
if (IS_HORUS(board) && fourcc == 0x3178396F) {
qDebug() << QString().sprintf("%s: Deprecated fourcc used %x vs %x", getName(), fourcc, StorageFormat::getFourCC(board));
qDebug() << QString().sprintf("%s: Deprecated fourcc used %x vs %x", getName(), fourcc, Boards::getFourCC(board));
}
else {
qDebug() << QString().sprintf("%s: Wrong fourcc %x vs %x", getName(), fourcc, StorageFormat::getFourCC(board));
qDebug() << QString().sprintf("%s: Wrong fourcc %x vs %x", getName(), fourcc, Boards::getFourCC(board));
return false;
}
}
@@ -236,7 +228,7 @@ unsigned long OpenTxEepromInterface::load(RadioData &radioData, const uint8_t *
if (version_error == OLD_VERSION) {
errors.set(version_error);
errors.set(HAS_WARNINGS);
ShowEepromWarnings(NULL, QObject::tr("Warning"), errors.to_ulong());
showEepromWarnings(NULL, CPN_STR_TTL_WARNING, errors.to_ulong());
}
else if (version_error == NOT_OPENTX) {
dbg << " not open9x";
@@ -287,7 +279,7 @@ void OpenTxEepromInterface::showErrors(const QString & title, const QStringList
{
QString msg;
if (errors.empty()) {
msg = QObject::tr("Unknown error");
msg = tr("Unknown error");
}
else {
int noErrorsToDisplay = std::min((int)errors.size(), 10);
@@ -295,12 +287,12 @@ void OpenTxEepromInterface::showErrors(const QString & title, const QStringList
msg += " -" + errors.at(n) + "\n";
}
if (noErrorsToDisplay < errors.size()) {
msg += QObject::tr(" ... plus %1 errors").arg(errors.size() - noErrorsToDisplay) + "\n" + msg;
msg += tr(" ... plus %1 errors").arg(errors.size() - noErrorsToDisplay) + "\n" + msg;
}
}
QMessageBox::warning(NULL,
QObject::tr("Error"),
CPN_STR_TTL_ERROR,
title + "\n" + msg);
}
@@ -325,6 +317,9 @@ int OpenTxEepromInterface::save(uint8_t * eeprom, const RadioData & radioData, u
else if (IS_TARANIS_X7(board)) {
variant |= TARANIS_X7_VARIANT;
}
else if (IS_TARANIS_XLITE(board)) {
variant |= TARANIS_XLITE_VARIANT;
}
OpenTxGeneralData generator((GeneralSettings &)radioData.generalSettings, board, version, variant);
// generator.Dump();
@@ -332,7 +327,7 @@ int OpenTxEepromInterface::save(uint8_t * eeprom, const RadioData & radioData, u
generator.Export(data);
int sz = efile->writeRlc2(FILE_GENERAL, FILE_TYP_GENERAL, (const uint8_t *)data.constData(), data.size());
if (sz == 0 || generator.errors().count() > 0) {
showErrors(QObject::tr("Cannot write radio settings"), generator.errors());
showErrors(tr("Cannot write radio settings"), generator.errors());
return 0;
}
@@ -344,7 +339,7 @@ int OpenTxEepromInterface::save(uint8_t * eeprom, const RadioData & radioData, u
generator.Export(data);
int sz = efile->writeRlc2(FILE_MODEL(i), FILE_TYP_MODEL, (const uint8_t *)data.constData(), data.size());
if (sz == 0 || generator.errors().count() > 0) {
showErrors(QObject::tr("Cannot write model %1").arg(radioData.models[i].name), generator.errors());
showErrors(tr("Cannot write model %1").arg(radioData.models[i].name), generator.errors());
return 0;
}
}
@@ -364,7 +359,8 @@ int OpenTxEepromInterface::getSize(const ModelData &model)
QByteArray tmp(Boards::getEEpromSize(Board::BOARD_UNKNOWN), 0);
efile->EeFsCreate((uint8_t *) tmp.data(), Boards::getEEpromSize(Board::BOARD_UNKNOWN), board, 255/*version max*/);
OpenTxModelData open9xModel((ModelData &) model, board, 255/*version max*/, getCurrentFirmware()->getVariantNumber());
ModelData srcCopy(model); // work on a copy of model data, because Export() may modify it!
OpenTxModelData open9xModel(srcCopy, board, 255/*version max*/, getCurrentFirmware()->getVariantNumber());
QByteArray eeprom;
open9xModel.Export(eeprom);
@@ -383,7 +379,8 @@ int OpenTxEepromInterface::getSize(const GeneralSettings &settings)
QByteArray tmp(Boards::getEEpromSize(Board::BOARD_UNKNOWN), 0);
efile->EeFsCreate((uint8_t *) tmp.data(), Boards::getEEpromSize(Board::BOARD_UNKNOWN), board, 255);
OpenTxGeneralData open9xGeneral((GeneralSettings &) settings, board, 255, getCurrentFirmware()->getVariantNumber());
GeneralSettings srcCopy(settings); // work on a copy of settings data, because Export() may modify it!
OpenTxGeneralData open9xGeneral(srcCopy, board, 255, getCurrentFirmware()->getVariantNumber());
// open9xGeneral.Dump();
QByteArray eeprom;
@@ -535,7 +532,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
case SoundPitch:
return 1;
case Haptic:
return (IS_2560(board) || IS_SKY9X(board) || IS_TARANIS_PLUS(board) || IS_TARANIS_X7(board) || IS_TARANIS_X9E(board) || IS_HORUS(board) || id.contains("haptic"));
return (IS_2560(board) || IS_SKY9X(board) || IS_TARANIS_PLUS(board) || IS_TARANIS_SMALL(board) || IS_TARANIS_X9E(board) || IS_HORUS(board) || id.contains("haptic"));
case ModelTrainerEnable:
if (IS_HORUS_OR_TARANIS(board))
return 1;
@@ -544,7 +541,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
case MaxVolume:
return (IS_ARM(board) ? 23 : 7);
case MaxContrast:
if (IS_TARANIS_X7(board))
if (IS_TARANIS_SMALL(board))
return 30;
else
return 45;
@@ -611,6 +608,10 @@ int OpenTxFirmware::getCapability(::Capability capability)
return (IS_ARM(board) ? 32 : 0);
case NumModules:
return (IS_ARM(board) ? 2 : 1);
case HasModuleR9MFlex:
return id.contains("flexr9m");
case HasModuleR9MMini:
return IS_TARANIS_XLITE(board) && !id.contains("stdr9m");
case HasPPMStart:
return (IS_ARM(board) ? true : false);
case HastxCurrentCalibration:
@@ -632,7 +633,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
case LcdWidth:
if (IS_HORUS(board))
return 480;
else if (IS_TARANIS_X7(board))
else if (IS_TARANIS_SMALL(board))
return 128;
else if (IS_TARANIS(board))
return 212;
@@ -646,7 +647,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
case LcdDepth:
if (IS_HORUS(board))
return 16;
else if (IS_TARANIS_X7(board))
else if (IS_TARANIS_SMALL(board))
return 1;
else if (IS_TARANIS(board))
return 4;
@@ -681,10 +682,6 @@ int OpenTxFirmware::getCapability(::Capability capability)
return (IS_STOCK(board) ? false : true);
case HasMahPersistent:
return (IS_ARM(board) ? true : false);
case MultiposPots:
return IS_HORUS_OR_TARANIS(board) ? 3 : 0;
case MultiposPotsPositions:
return IS_HORUS_OR_TARANIS(board) ? 6 : 0;
case SimulatorVariant:
if (board == BOARD_STOCK)
return SIMU_STOCK_VARIANTS;
@@ -694,6 +691,8 @@ int OpenTxFirmware::getCapability(::Capability capability)
return TARANIS_X9E_VARIANT;
else if (IS_TARANIS_X7(board))
return TARANIS_X7_VARIANT;
else if (IS_TARANIS_XLITE(board))
return TARANIS_XLITE_VARIANT;
else
return 0;
case MavlinkTelemetry:
@@ -716,76 +715,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
QString OpenTxFirmware::getAnalogInputName(unsigned int index)
{
if ((int)index < getBoardCapability(board, Board::Sticks)) {
const QString sticks[] = {
QObject::tr("Rud"),
QObject::tr("Ele"),
QObject::tr("Thr"),
QObject::tr("Ail")
};
return sticks[index];
}
index -= getBoardCapability(board, Board::Sticks);
if (IS_9X(board) || IS_2560(board) || IS_SKY9X(board)) {
const QString pots[] = {
QObject::tr("P1"),
QObject::tr("P2"),
QObject::tr("P3")
};
return CHECK_IN_ARRAY(pots, index);
}
else if (IS_TARANIS_X9E(board)) {
const QString pots[] = {
QObject::tr("F1"),
QObject::tr("F2"),
QObject::tr("F3"),
QObject::tr("F4"),
QObject::tr("S1"),
QObject::tr("S2"),
QObject::tr("LS"),
QObject::tr("RS")
};
return CHECK_IN_ARRAY(pots, index);
}
else if (IS_TARANIS(board)) {
const QString pots[] = {
QObject::tr("S1"),
QObject::tr("S2"),
QObject::tr("S3"),
QObject::tr("LS"),
QObject::tr("RS")
};
return CHECK_IN_ARRAY(pots, index);
}
else if (IS_HORUS_X12S(board)) {
const QString pots[] = {
QObject::tr("S1"),
QObject::tr("6P"),
QObject::tr("S2"),
QObject::tr("L1"),
QObject::tr("L2"),
QObject::tr("LS"),
QObject::tr("RS"),
QObject::tr("JSx"),
QObject::tr("JSy")
};
return CHECK_IN_ARRAY(pots, index);
}
else if (IS_HORUS_X10(board)) {
const QString pots[] = {
QObject::tr("S1"),
QObject::tr("6P"),
QObject::tr("S2"),
QObject::tr("LS"),
QObject::tr("RS")
};
return CHECK_IN_ARRAY(pots, index);
}
else {
return "???";
}
return Boards::getAnalogInputName(board, index);
}
QTime OpenTxFirmware::getMaxTimerStart()
@@ -947,9 +877,14 @@ EepromLoadErrors OpenTxEepromInterface::checkVersion(unsigned int version)
// M128 revert because too much RAM used!
case 216:
// A lot of things (first github release)
if (IS_2560(board) || IS_M128(board)) {
return OLD_VERSION;
}
case 217:
// 3 logical switches removed on M128 / gruvin9x boards
return OLD_VERSION;
if (IS_ARM(board)) {
return OLD_VERSION;
}
case 218:
break;
default:
@@ -961,6 +896,7 @@ EepromLoadErrors OpenTxEepromInterface::checkVersion(unsigned int version)
bool OpenTxEepromInterface::checkVariant(unsigned int version, unsigned int variant)
{
bool variantError = false;
if (board == BOARD_M128 && !(variant & M128_VARIANT)) {
if (version == 212) {
uint8_t tmp[1000];
@@ -973,28 +909,34 @@ bool OpenTxEepromInterface::checkVariant(unsigned int version, unsigned int vari
}
}
}
qWarning() << " wrong variant (" << variant << ")";
return false;
variantError = true;
}
else if (IS_TARANIS_X9E(board)) {
if (variant != TARANIS_X9E_VARIANT) {
qWarning() << " wrong variant (" << variant << ")";
return false;
variantError = true;
}
}
else if (IS_TARANIS_X7(board)) {
if (variant != TARANIS_X7_VARIANT) {
qWarning() << " wrong variant (" << variant << ")";
return false;
variantError = true;
}
}
else if (IS_TARANIS_XLITE(board)) {
if (variant != TARANIS_XLITE_VARIANT) {
variantError = true;
}
}
else if (IS_TARANIS(board)) {
if (variant != 0) {
qWarning() << " wrong variant (" << variant << ")";
return false;
variantError = true;
}
}
if (variantError) {
qWarning() << " wrong variant (" << variant << ")";
return false;
}
return true;
}
@@ -1100,405 +1042,170 @@ unsigned long OpenTxEepromInterface::loadBackup(RadioData &radioData, const uint
QString OpenTxFirmware::getFirmwareBaseUrl()
{
return OPENTX_FIRMWARE_DOWNLOAD_URL[g.boundedOpenTxBranch()];
return g.openTxCurrentDownloadBranchUrl() % QStringLiteral("firmware/");
}
QString OpenTxFirmware::getFirmwareUrl()
{
QString url = getFirmwareBaseUrl();
QByteArray data = QUrl::toPercentEncoding(id);
if (IS_ARM(board))
url.append(QString("/getfw.php?fw=%1.bin").arg((QString) data));
else
url.append(QString("/getfw.php?fw=%1.hex").arg((QString) data));
return url;
return getFirmwareBaseUrl() % QString("getfw.php?fw=%1.bin").arg(QString(QUrl::toPercentEncoding(id)));
}
QString OpenTxFirmware::getReleaseNotesUrl()
{
QString url = getFirmwareBaseUrl();
url.append("/releasenotes.txt");
return url;
return getFirmwareBaseUrl() % QStringLiteral("releasenotes.txt");
}
QString OpenTxFirmware::getStampUrl()
{
QString url = getFirmwareBaseUrl();
url.append("/stamp-opentx.txt");
return url;
return getFirmwareBaseUrl() % QStringLiteral("stamp-opentx.txt");
}
void addOpenTxCommonOptions(OpenTxFirmware * firmware)
{
firmware->addOption("ppmus", QObject::tr("Channel values displayed in us"));
firmware->addOption("nooverridech", QObject::tr("No OverrideCH functions available"));
Option fai_options[] = {{"faichoice", QObject::tr("Possibility to enable FAI MODE (no telemetry) at field")},
{"faimode", QObject::tr("FAI MODE (no telemetry) always enabled")},
{NULL}};
firmware->addOptions(fai_options);
}
void addOpenTxArmOptions(OpenTxFirmware * firmware)
{
firmware->addOption("multimodule", QObject::tr("Support for the DIY-Multiprotocol-TX-Module"));
firmware->addOption("eu", QObject::tr("Removes D8 FrSky protocol support which is not legal for use in the EU on radios sold after Jan 1st, 2015"));
}
// Firmware registrations
// NOTE: "recognized" build options are defined in /radio/util/fwoptions.py
void addOpenTxFrskyOptions(OpenTxFirmware * firmware)
{
addOpenTxCommonOptions(firmware);
addOpenTxArmOptions(firmware);
firmware->addOption("noheli", QObject::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", QObject::tr("Disable Global variables"));
firmware->addOption("lua", QObject::tr("Enable Lua custom scripts screen"));
firmware->addOption("luac", QObject::tr("Enable Lua compiler"));
}
void addOpenTxTaranisOptions(OpenTxFirmware * firmware)
{
addOpenTxFrskyOptions(firmware);
firmware->addOption("internalppm", QObject::tr("Support for PPM internal module hack"));
firmware->addOption("sqt5font", QObject::tr("Use alternative SQT5 font"));
}
void addOpenTxLcdOptions(OpenTxFirmware * firmware)
{
Option lcd_options[] = {
{"ST7565P", QObject::tr("ST7565P LCD or compatible")},
{"ST7565R", QObject::tr("ST7565R LCD or compatible")},
{"ERC12864FSF", QObject::tr("ERC12864FSF LCD")},
{"ST7920", QObject::tr("ST7920 LCD")},
{"KS108", QObject::tr("KS108 LCD")},
{NULL}
};
firmware->addOptions(lcd_options);
}
void addOpenTxVoiceOptions(OpenTxFirmware * firmware)
{
Option voice_options[] = {
{"WTV20", QObject::tr("WTV20 voice module")},
{"JQ6500", QObject::tr("JQ6500 voice module")},
{NULL}
};
firmware->addOptions(voice_options);
}
QList<OpenTxEepromInterface *> opentxEEpromInterfaces;
void registerOpenTxFirmware(OpenTxFirmware * firmware)
void registerOpenTxFirmware(OpenTxFirmware * firmware, bool deprecated = false)
{
OpenTxEepromInterface * eepromInterface = new OpenTxEepromInterface(firmware);
firmware->setEEpromInterface(eepromInterface);
opentxEEpromInterfaces.push_back(eepromInterface);
eepromInterfaces.push_back(eepromInterface);
Firmware::addRegisteredFirmware(firmware);
if (!deprecated)
Firmware::addRegisteredFirmware(firmware);
}
void addOpenTxCommonOptions(OpenTxFirmware * firmware)
{
static const Firmware::OptionsGroup fai_options = {
Firmware::Option("faichoice", Firmware::tr("Possibility to enable FAI MODE (no telemetry) at field")),
Firmware::Option("faimode", Firmware::tr("FAI MODE (no telemetry) always enabled"))
};
firmware->addOption("ppmus", Firmware::tr("Channel values displayed in us"));
firmware->addOptionsGroup(fai_options);
firmware->addOption("nooverridech", Firmware::tr("No OverrideCH functions available"));
}
void addOpenTxRfOptions(OpenTxFirmware * firmware, bool flex = true)
{
static const Firmware::Option opt_eu("eu", Firmware::tr("Removes D8 FrSky protocol support which is not legal for use in the EU on radios sold after Jan 1st, 2015"));
static const Firmware::Option opt_fl("flexr9m", Firmware::tr("Enable non certified firmwares"));
firmware->addOption("multimodule", Firmware::tr("Support for the DIY-Multiprotocol-TX-Module"));
if (flex)
firmware->addOptionsGroup({opt_eu, opt_fl});
else
firmware->addOption(opt_eu);
}
void addOpenTxFontOptions(OpenTxFirmware * firmware)
{
firmware->addOption("sqt5font", Firmware::tr("Use alternative SQT5 font"));
}
void addOpenTxFrskyOptions(OpenTxFirmware * firmware)
{
addOpenTxCommonOptions(firmware);
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
firmware->addOption("lua", Firmware::tr("Enable Lua custom scripts screen"));
firmware->addOption("luac", Firmware::tr("Enable Lua compiler"));
addOpenTxRfOptions(firmware);
}
void addOpenTxTaranisOptions(OpenTxFirmware * firmware, bool intppm = true)
{
addOpenTxFrskyOptions(firmware);
if (intppm)
firmware->addOption("internalppm", Firmware::tr("Support for PPM internal module hack"));
addOpenTxFontOptions(firmware);
}
void addOpenTxArm9xOptions(OpenTxFirmware * firmware, bool dblkeys = true)
{
addOpenTxCommonOptions(firmware);
firmware->addOption("heli", Firmware::tr("Enable HELI menu and cyclic mix support"));
firmware->addOption("gvars", Firmware::tr("Global variables"), GVARS_VARIANT);
firmware->addOption("potscroll", Firmware::tr("Pots use in menus navigation"));
firmware->addOption("autosource", Firmware::tr("In model setup menus automatically set source by moving the control"));
firmware->addOption("autoswitch", Firmware::tr("In model setup menus automatically set switch by moving the control"));
firmware->addOption("nographics", Firmware::tr("No graphical check boxes and sliders"));
firmware->addOption("battgraph", Firmware::tr("Battery graph"));
firmware->addOption("nobold", Firmware::tr("Don't use bold font for highlighting active items"));
//firmware->addOption("bluetooth", Firmware::tr("Bluetooth interface"));
if (dblkeys)
firmware->addOption("dblkeys", Firmware::tr("Enable resetting values by pressing up and down at the same time"));
addOpenTxFontOptions(firmware);
addOpenTxRfOptions(firmware, true);
}
void registerOpenTxFirmwares()
{
OpenTxFirmware * firmware;
Option ext_options[] = {{"frsky", QObject::tr("Support for frsky telemetry mod"), FRSKY_VARIANT},
{"telemetrez", QObject::tr("Support for telemetry easy board"), FRSKY_VARIANT},
{"jeti", QObject::tr("Support for jeti telemetry mod"), 0},
{"ardupilot", QObject::tr("Support for receiving ardupilot data"), 0},
{"nmea", QObject::tr("Support for receiving NMEA data"), 0},
{"mavlink", QObject::tr("Support for MAVLINK devices"), MAVLINK_VARIANT},
{NULL}};
Option extr_options[] = {{"frsky", QObject::tr("Support for frsky telemetry mod"), FRSKY_VARIANT},
{"jeti", QObject::tr("Support for jeti telemetry mod"), 0},
{"ardupilot", QObject::tr("Support for receiving ardupilot data"), 0},
{"nmea", QObject::tr("Support for receiving NMEA data"), 0},
{"mavlink", QObject::tr("Support for MAVLINK devices"), MAVLINK_VARIANT},
{NULL}};
Option nav_options[] = {{"rotenc", QObject::tr("Rotary Encoder use in menus navigation")},
{"potscroll", QObject::tr("Pots use in menus navigation")},
{NULL}};
Option dsm2_options[] = {{"DSM2", QObject::tr("Support for DSM2 modules"), 0},
{"DSM2PPM", QObject::tr("Support for DSM2 modules using ppm instead of true serial"), 0},
{NULL}};
/* FrSky Taranis X9D+ board */
firmware = new OpenTxFirmware("opentx-x9d+", QObject::tr("FrSky Taranis X9D+"), BOARD_TARANIS_X9DP);
firmware = new OpenTxFirmware("opentx-x9d+", Firmware::tr("FrSky Taranis X9D+"), BOARD_TARANIS_X9DP);
firmware->addOption("noras", Firmware::tr("Disable RAS (SWR)"));
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
/* FrSky Taranis X9D board */
firmware = new OpenTxFirmware("opentx-x9d", QObject::tr("FrSky Taranis X9D"), BOARD_TARANIS_X9D);
firmware->addOption("haptic", QObject::tr("Haptic module installed"));
firmware = new OpenTxFirmware("opentx-x9d", Firmware::tr("FrSky Taranis X9D"), BOARD_TARANIS_X9D);
firmware->addOption("haptic", Firmware::tr("Haptic module installed"));
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
/* FrSky Taranis X9E board */
firmware = new OpenTxFirmware("opentx-x9e", QObject::tr("FrSky Taranis X9E"), BOARD_TARANIS_X9E);
firmware->addOption("shutdownconfirm", QObject::tr("Confirmation before radio shutdown"));
firmware->addOption("horussticks", QObject::tr("Horus gimbals installed (Hall sensors)"));
firmware = new OpenTxFirmware("opentx-x9e", Firmware::tr("FrSky Taranis X9E"), BOARD_TARANIS_X9E);
firmware->addOption("shutdownconfirm", Firmware::tr("Confirmation before radio shutdown"));
firmware->addOption("horussticks", Firmware::tr("Horus gimbals installed (Hall sensors)"));
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
/* FrSky X7 board */
firmware = new OpenTxFirmware("opentx-x7", QObject::tr("FrSky Taranis X7 / X7S"), BOARD_TARANIS_X7);
// No mixersmon for now
addOpenTxFrskyOptions(firmware);
firmware->addOption("internalppm", QObject::tr("Support for PPM internal module hack"));
firmware->addOption("sqt5font", QObject::tr("Use alternative SQT5 font"));
firmware = new OpenTxFirmware("opentx-x7", Firmware::tr("FrSky Taranis X7 / X7S"), BOARD_TARANIS_X7);
addOpenTxTaranisOptions(firmware, false);
registerOpenTxFirmware(firmware);
/* FrSky X-Lite board */
firmware = new OpenTxFirmware("opentx-xlite", Firmware::tr("FrSky Taranis X-Lite"), BOARD_TARANIS_XLITE);
// firmware->addOption("stdr9m", Firmware::tr("Use JR-sized R9M module"));
addOpenTxTaranisOptions(firmware, false);
registerOpenTxFirmware(firmware);
/* FrSky X10 board */
firmware = new OpenTxFirmware("opentx-x10", QObject::tr("FrSky Horus X10 / X10S"), BOARD_X10);
firmware = new OpenTxFirmware("opentx-x10", Firmware::tr("FrSky Horus X10 / X10S"), BOARD_X10);
addOpenTxFrskyOptions(firmware);
registerOpenTxFirmware(firmware);
/* FrSky Horus board */
firmware = new OpenTxFirmware("opentx-x12s", QObject::tr("FrSky Horus X12S"), BOARD_X12S);
/* FrSky X12 (Horus) board */
firmware = new OpenTxFirmware("opentx-x12s", Firmware::tr("FrSky Horus X12S"), BOARD_X12S);
addOpenTxFrskyOptions(firmware);
firmware->addOption("pcbdev", QObject::tr("Use ONLY with first DEV pcb version"));
firmware->addOption("pcbdev", Firmware::tr("Use ONLY with first DEV pcb version"));
registerOpenTxFirmware(firmware);
/* 9XR-Pro */
firmware = new OpenTxFirmware("opentx-9xrpro", QObject::tr("Turnigy 9XR-PRO"), BOARD_9XRPRO);
firmware->addOption("heli", QObject::tr("Enable HELI menu and cyclic mix support"));
firmware->addOption("nofp", QObject::tr("No flight modes"));
firmware->addOption("gvars", QObject::tr("Global variables"), GVARS_VARIANT);
firmware->addOption("potscroll", QObject::tr("Pots use in menus navigation"));
firmware->addOption("autosource", QObject::tr("In model setup menus automatically set source by moving the control"));
firmware->addOption("autoswitch", QObject::tr("In model setup menus automatically set switch by moving the control"));
firmware->addOption("nographics", QObject::tr("No graphical check boxes and sliders"));
firmware->addOption("battgraph", QObject::tr("Battery graph"));
firmware->addOption("nobold", QObject::tr("Don't use bold font for highlighting active items"));
firmware->addOption("bluetooth", QObject::tr("Bluetooth interface"));
firmware->addOption("sqt5font", QObject::tr("Use alternative SQT5 font"));
addOpenTxArmOptions(firmware);
addOpenTxCommonOptions(firmware);
registerOpenTxFirmware(firmware);
/* 9XR board with M128 chip */
firmware = new OpenTxFirmware("opentx-9xr128", QObject::tr("Turnigy 9XR with m128 chip"), BOARD_M128);
firmware->addOptions(extr_options);
firmware->addOption("heli", QObject::tr("Enable heli menu and cyclic mix support"));
firmware->addOption("templates", QObject::tr("Enable TEMPLATES menu"));
firmware->addOption("nosplash", QObject::tr("No splash screen"));
firmware->addOption("nofp", QObject::tr("No flight modes"));
firmware->addOption("nocurves", QObject::tr("Disable curves menus"));
firmware->addOption("audio", QObject::tr("Support for radio modified with regular speaker"));
firmware->addOption("voice", QObject::tr("Used if you have modified your radio with voice mode"));
firmware->addOption("haptic", QObject::tr("Used if you have modified your radio with haptic mode"));
// NOT TESTED firmware->addOption("PXX", QObject::tr("Support of FrSky PXX protocol"));
firmware->addOption("DSM2", QObject::tr("Support for DSM2 modules"));
firmware->addOption("ppmca", QObject::tr("PPM center adjustment in limits"));
firmware->addOption("gvars", QObject::tr("Global variables"), GVARS_VARIANT);
firmware->addOption("symlimits", QObject::tr("Symetrical Limits"));
firmware->addOption("potscroll", QObject::tr("Pots use in menus navigation"));
firmware->addOption("autosource", QObject::tr("In model setup menus automatically set source by moving the control"));
firmware->addOption("autoswitch", QObject::tr("In model setup menus automatically set switch by moving the control"));
firmware->addOption("nographics", QObject::tr("No graphical check boxes and sliders"));
firmware->addOption("battgraph", QObject::tr("Battery graph"));
firmware->addOption("nobold", QObject::tr("Don't use bold font for highlighting active items"));
firmware->addOption("thrtrace", QObject::tr("Enable the throttle trace in Statistics"));
firmware->addOption("pgbar", QObject::tr("EEprom write Progress bar"));
firmware->addOption("imperial", QObject::tr("Imperial units"));
firmware->addOption("sqt5font", QObject::tr("Use alternative SQT5 font"));
addOpenTxCommonOptions(firmware);
registerOpenTxFirmware(firmware);
/* 9XR board */
firmware = new OpenTxFirmware("opentx-9xr", QObject::tr("Turnigy 9XR"), BOARD_STOCK);
firmware->addOptions(extr_options);
firmware->addOption("heli", QObject::tr("Enable heli menu and cyclic mix support"));
firmware->addOption("templates", QObject::tr("Enable TEMPLATES menu"));
firmware->addOption("nosplash", QObject::tr("No splash screen"));
firmware->addOption("nofp", QObject::tr("No flight modes"));
firmware->addOption("nocurves", QObject::tr("Disable curves menus"));
firmware->addOption("audio", QObject::tr("Support for radio modified with regular speaker"));
firmware->addOption("voice", QObject::tr("Used if you have modified your radio with voice mode"));
firmware->addOption("haptic", QObject::tr("Used if you have modified your radio with haptic mode"));
// NOT TESTED firmware->addOption("PXX", QObject::tr("Support of FrSky PXX protocol"));
firmware->addOption("DSM2", QObject::tr("Support for DSM2 modules"));
firmware->addOption("ppmca", QObject::tr("PPM center adjustment in limits"));
firmware->addOption("gvars", QObject::tr("Global variables"), GVARS_VARIANT);
firmware->addOption("symlimits", QObject::tr("Symetrical Limits"));
firmware->addOption("potscroll", QObject::tr("Pots use in menus navigation"));
firmware->addOption("autosource", QObject::tr("In model setup menus automatically set source by moving the control"));
firmware->addOption("autoswitch", QObject::tr("In model setup menus automatically set switch by moving the control"));
firmware->addOption("nographics", QObject::tr("No graphical check boxes and sliders"));
firmware->addOption("battgraph", QObject::tr("Battery graph"));
firmware->addOption("nobold", QObject::tr("Don't use bold font for highlighting active items"));
firmware->addOption("thrtrace", QObject::tr("Enable the throttle trace in Statistics"));
firmware->addOption("pgbar", QObject::tr("EEprom write Progress bar"));
firmware->addOption("imperial", QObject::tr("Imperial units"));
firmware->addOption("nowshh", QObject::tr("No Winged Shadow How High support"));
firmware->addOption("novario", QObject::tr("No vario support"));
firmware->addOption("nogps", QObject::tr("No GPS support"));
firmware->addOption("nogauges", QObject::tr("No gauges in the custom telemetry screen"));
firmware->addOption("stickrev", QObject::tr("Add support for reversing stick inputs (e.g. needed for FrSky gimbals)"));
firmware->addOption("sqt5font", QObject::tr("Use alternative SQT5 font"));
addOpenTxCommonOptions(firmware);
registerOpenTxFirmware(firmware);
/* 9x board */
firmware = new OpenTxFirmware("opentx-9x", QObject::tr("9X with stock board"), BOARD_STOCK);
firmware->addOptions(ext_options);
firmware->addOption("heli", QObject::tr("Enable heli menu and cyclic mix support"));
firmware->addOption("templates", QObject::tr("Enable TEMPLATES menu"));
firmware->addOption("nosplash", QObject::tr("No splash screen"));
firmware->addOption("nofp", QObject::tr("No flight modes"));
firmware->addOption("nocurves", QObject::tr("Disable curves menus"));
firmware->addOption("audio", QObject::tr("Support for radio modified with regular speaker"));
firmware->addOption("voice", QObject::tr("Used if you have modified your radio with voice mode"));
firmware->addOption("haptic", QObject::tr("Used if you have modified your radio with haptic mode"));
// NOT TESTED firmware->addOption("PXX", QObject::tr("Support of FrSky PXX protocol"));
firmware->addOption("DSM2", QObject::tr("Support for DSM2 modules"));
firmware->addOption("ppmca", QObject::tr("PPM center adjustment in limits"));
firmware->addOption("gvars", QObject::tr("Global variables"), GVARS_VARIANT);
firmware->addOption("symlimits", QObject::tr("Symetrical Limits"));
firmware->addOptions(nav_options);
firmware->addOption("sp22", QObject::tr("SmartieParts 2.2 Backlight support"));
firmware->addOption("autosource", QObject::tr("In model setup menus automatically set source by moving the control"));
firmware->addOption("autoswitch", QObject::tr("In model setup menus automatically set switch by moving the control"));
firmware->addOption("dblkeys", QObject::tr("Enable resetting values by pressing up and down at the same time"));
firmware->addOption("nographics", QObject::tr("No graphical check boxes and sliders"));
firmware->addOption("battgraph", QObject::tr("Battery graph"));
firmware->addOption("nobold", QObject::tr("Don't use bold font for highlighting active items"));
firmware->addOption("thrtrace", QObject::tr("Enable the throttle trace in Statistics"));
firmware->addOption("pgbar", QObject::tr("EEprom write progress bar"));
firmware->addOption("imperial", QObject::tr("Imperial units"));
firmware->addOption("nowshh", QObject::tr("No Winged Shadow How High support"));
firmware->addOption("novario", QObject::tr("No vario support"));
firmware->addOption("nogps", QObject::tr("No GPS support"));
firmware->addOption("nogauges", QObject::tr("No gauges in the custom telemetry screen"));
firmware->addOption("fasoffset", QObject::tr("Allow compensating for offset errors in FrSky FAS current sensors"));
firmware->addOption("stickrev", QObject::tr("Add support for reversing stick inputs (e.g. needed for FrSky gimbals)"));
firmware->addOption("sqt5font", QObject::tr("Use alternative SQT5 font"));
addOpenTxCommonOptions(firmware);
registerOpenTxFirmware(firmware);
/* 9x board with M128 chip */
firmware = new OpenTxFirmware("opentx-9x128", QObject::tr("9X with stock board and m128 chip"), BOARD_M128);
firmware->addOptions(ext_options);
firmware->addOption("heli", QObject::tr("Enable heli menu and cyclic mix support"));
firmware->addOption("templates", QObject::tr("Enable TEMPLATES menu"));
firmware->addOption("nosplash", QObject::tr("No splash screen"));
firmware->addOption("nofp", QObject::tr("No flight modes"));
firmware->addOption("nocurves", QObject::tr("Disable curves menus"));
firmware->addOption("audio", QObject::tr("Support for radio modified with regular speaker"));
firmware->addOption("voice", QObject::tr("Used if you have modified your radio with voice mode"));
firmware->addOption("haptic", QObject::tr("Used if you have modified your radio with haptic mode"));
// NOT TESTED firmware->addOption("PXX", QObject::tr("Support of FrSky PXX protocol"));
firmware->addOption("DSM2", QObject::tr("Support for DSM2 modules"));
firmware->addOption("ppmca", QObject::tr("PPM center adjustment in limits"));
firmware->addOption("gvars", QObject::tr("Global variables"), GVARS_VARIANT);
firmware->addOption("symlimits", QObject::tr("Symetrical Limits"));
firmware->addOptions(nav_options);
firmware->addOption("sp22", QObject::tr("SmartieParts 2.2 Backlight support"));
firmware->addOption("autosource", QObject::tr("In model setup menus automatically set source by moving the control"));
firmware->addOption("autoswitch", QObject::tr("In model setup menus automatically set switch by moving the control"));
firmware->addOption("dblkeys", QObject::tr("Enable resetting values by pressing up and down at the same time"));
firmware->addOption("nographics", QObject::tr("No graphical check boxes and sliders"));
firmware->addOption("battgraph", QObject::tr("Battery graph"));
firmware->addOption("nobold", QObject::tr("Don't use bold font for highlighting active items"));
firmware->addOption("thrtrace", QObject::tr("Enable the throttle trace in Statistics"));
firmware->addOption("pgbar", QObject::tr("EEprom write Progress bar"));
firmware->addOption("imperial", QObject::tr("Imperial units"));
firmware->addOption("sqt5font", QObject::tr("Use alternative SQT5 font"));
addOpenTxCommonOptions(firmware);
firmware = new OpenTxFirmware("opentx-9xrpro", Firmware::tr("Turnigy 9XR-PRO"), BOARD_9XRPRO);
addOpenTxArm9xOptions(firmware, false);
registerOpenTxFirmware(firmware);
/* ar9x board */
firmware = new OpenTxFirmware("opentx-ar9x", QObject::tr("9X with AR9X board"), BOARD_AR9X);
firmware->addOption("heli", QObject::tr("Enable HELI menu and cyclic mix support"));
firmware->addOption("nofp", QObject::tr("No flight modes"));
firmware->addOption("gvars", QObject::tr("Global variables"), GVARS_VARIANT);
firmware->addOption("potscroll", QObject::tr("Pots use in menus navigation"));
firmware->addOption("autosource", QObject::tr("In model setup menus automatically set source by moving the control"));
firmware->addOption("autoswitch", QObject::tr("In model setup menus automatically set switch by moving the control"));
firmware->addOption("dblkeys", QObject::tr("Enable resetting values by pressing up and down at the same time"));
firmware->addOption("nographics", QObject::tr("No graphical check boxes and sliders"));
firmware->addOption("battgraph", QObject::tr("Battery graph"));
firmware->addOption("nobold", QObject::tr("Don't use bold font for highlighting active items"));
firmware->addOption("bluetooth", QObject::tr("Bluetooth interface"));
firmware->addOption("sqt5font", QObject::tr("Use alternative SQT5 font"));
// firmware->addOption("rtc", QObject::tr("Optional RTC added"));
// firmware->addOption("volume", QObject::tr("i2c volume control added"));
addOpenTxArmOptions(firmware);
addOpenTxCommonOptions(firmware);
firmware = new OpenTxFirmware("opentx-ar9x", Firmware::tr("9X with AR9X board"), BOARD_AR9X);
addOpenTxArm9xOptions(firmware);
//firmware->addOption("rtc", Firmware::tr("Optional RTC added"));
//firmware->addOption("volume", Firmware::tr("i2c volume control added"));
registerOpenTxFirmware(firmware);
/* Sky9x board */
firmware = new OpenTxFirmware("opentx-sky9x", QObject::tr("9X with Sky9x board"), BOARD_SKY9X);
firmware->addOption("heli", QObject::tr("Enable HELI menu and cyclic mix support"));
firmware->addOption("nofp", QObject::tr("No flight modes"));
firmware->addOption("gvars", QObject::tr("Global variables"), GVARS_VARIANT);
firmware->addOption("potscroll", QObject::tr("Pots use in menus navigation"));
firmware->addOption("autosource", QObject::tr("In model setup menus automatically set source by moving the control"));
firmware->addOption("autoswitch", QObject::tr("In model setup menus automatically set switch by moving the control"));
firmware->addOption("dblkeys", QObject::tr("Enable resetting values by pressing up and down at the same time"));
firmware->addOption("nographics", QObject::tr("No graphical check boxes and sliders"));
firmware->addOption("battgraph", QObject::tr("Battery graph"));
firmware->addOption("nobold", QObject::tr("Don't use bold font for highlighting active items"));
firmware->addOption("bluetooth", QObject::tr("Bluetooth interface"));
firmware->addOption("sqt5font", QObject::tr("Use alternative SQT5 font"));
addOpenTxArmOptions(firmware);
addOpenTxCommonOptions(firmware);
firmware = new OpenTxFirmware("opentx-sky9x", Firmware::tr("9X with Sky9x board"), BOARD_SKY9X);
addOpenTxArm9xOptions(firmware);
registerOpenTxFirmware(firmware);
/* Gruvin9x board */
firmware = new OpenTxFirmware("opentx-gruvin9x", QObject::tr("9X with Gruvin9x board"), BOARD_GRUVIN9X);
firmware->addOption("heli", QObject::tr("Enable heli menu and cyclic mix support"));
firmware->addOption("templates", QObject::tr("Enable TEMPLATES menu"));
firmware->addOption("nofp", QObject::tr("No flight modes"));
firmware->addOption("nocurves", QObject::tr("Disable curves menus"));
firmware->addOption("sdcard", QObject::tr("Support for SD memory card"));
firmware->addOption("voice", QObject::tr("Used if you have modified your radio with voice mode"));
firmware->addOption("PXX", QObject::tr("Support of FrSky PXX protocol"));
firmware->addOptions(dsm2_options);
firmware->addOption("ppmca", QObject::tr("PPM center adjustment in limits"));
firmware->addOption("gvars", QObject::tr("Global variables"), GVARS_VARIANT);
firmware->addOption("symlimits", QObject::tr("Symetrical Limits"));
firmware->addOption("potscroll", QObject::tr("Pots use in menus navigation"));
firmware->addOption("autosource", QObject::tr("In model setup menus automatically set source by moving the control"));
firmware->addOption("autoswitch", QObject::tr("In model setup menus automatically set switch by moving the control"));
firmware->addOption("dblkeys", QObject::tr("Enable resetting values by pressing up and down at the same time"));
firmware->addOption("nographics", QObject::tr("No graphical check boxes and sliders"));
firmware->addOption("battgraph", QObject::tr("Battery graph"));
firmware->addOption("nobold", QObject::tr("Don't use bold font for highlighting active items"));
firmware->addOption("pgbar", QObject::tr("EEprom write Progress bar"));
firmware->addOption("imperial", QObject::tr("Imperial units"));
firmware->addOption("sqt5font", QObject::tr("Use alternative SQT5 font"));
addOpenTxCommonOptions(firmware);
registerOpenTxFirmware(firmware);
/* MEGA2560 board */
firmware = new OpenTxFirmware("opentx-mega2560", QObject::tr("DIY MEGA2560 radio"), BOARD_MEGA2560);
addOpenTxLcdOptions(firmware);
firmware->addOption("PWR", QObject::tr("Power management by soft-off circuitry"));
firmware->addOptions(ext_options);
firmware->addOption("PXX", QObject::tr("Support of FrSky PXX protocol"));
firmware->addOptions(dsm2_options);
firmware->addOption("heli", QObject::tr("Enable heli menu and cyclic mix support"));
firmware->addOption("templates", QObject::tr("Enable TEMPLATES menu"));
firmware->addOption("nofp", QObject::tr("No flight modes"));
firmware->addOption("nocurves", QObject::tr("Disable curves menus"));
firmware->addOption("sdcard", QObject::tr("Support for SD memory card"));
firmware->addOption("audio", QObject::tr("Support for radio modified with regular speaker"));
//firmware->addOption("voice", QObject::tr("Used if you have modified your radio with voice mode"));
addOpenTxVoiceOptions(firmware);
firmware->addOption("haptic", QObject::tr("Used if you have modified your radio with haptic mode"));
firmware->addOption("ppmca", QObject::tr("PPM center adjustment in limits"));
firmware->addOption("gvars", QObject::tr("Global variables"), GVARS_VARIANT);
firmware->addOption("symlimits", QObject::tr("Symetrical Limits"));
firmware->addOption("autosource", QObject::tr("In model setup menus automatically set source by moving the control"));
firmware->addOption("autoswitch", QObject::tr("In model setup menus automatically set switch by moving the control"));
firmware->addOption("dblkeys", QObject::tr("Enable resetting values by pressing up and down at the same time"));
firmware->addOption("nographics", QObject::tr("No graphical check boxes and sliders"));
firmware->addOption("battgraph", QObject::tr("Battery graph"));
firmware->addOption("nobold", QObject::tr("Don't use bold font for highlighting active items"));
firmware->addOption("pgbar", QObject::tr("EEprom write Progress bar"));
firmware->addOption("imperial", QObject::tr("Imperial units"));
firmware->addOption("sqt5font", QObject::tr("Use alternative SQT5 font"));
addOpenTxCommonOptions(firmware);
registerOpenTxFirmware(firmware);
// These are kept only for import purposes, marked as deprecated to hide from UI.
registerOpenTxFirmware(new OpenTxFirmware("opentx-9xr", Firmware::tr("Turnigy 9XR"), BOARD_STOCK), true);
registerOpenTxFirmware(new OpenTxFirmware("opentx-9xr128", Firmware::tr("Turnigy 9XR with m128 chip"), BOARD_M128), true);
registerOpenTxFirmware(new OpenTxFirmware("opentx-9x", Firmware::tr("9X with stock board"), BOARD_STOCK), true);
registerOpenTxFirmware(new OpenTxFirmware("opentx-9x128", Firmware::tr("9X with stock board and m128 chip"), BOARD_M128), true);
registerOpenTxFirmware(new OpenTxFirmware("opentx-gruvin9x", Firmware::tr("9X with Gruvin9x board"), BOARD_GRUVIN9X), true);
registerOpenTxFirmware(new OpenTxFirmware("opentx-mega2560", Firmware::tr("DIY MEGA2560 radio"), BOARD_MEGA2560), true);
Firmware::setDefaultVariant(Firmware::getFirmwareForId("opentx-x9d+"));
Firmware::setCurrentVariant(Firmware::getDefaultVariant());
@@ -23,11 +23,15 @@
#include "eeprominterface.h"
#include <QtCore>
class RleFile;
class OpenTxFirmware;
class OpenTxEepromInterface : public EEPROMInterface
{
Q_DECLARE_TR_FUNCTIONS(OpenTxEepromInterface)
public:
OpenTxEepromInterface(OpenTxFirmware * firmware);
@@ -35,17 +39,17 @@ class OpenTxEepromInterface : public EEPROMInterface
virtual ~OpenTxEepromInterface();
virtual unsigned long load(RadioData &, const uint8_t * eeprom, int size);
bool loadModelFromBackup(ModelData & model, const uint8_t * data, unsigned int size, uint8_t version, uint32_t variant);
virtual unsigned long loadBackup(RadioData &, const uint8_t * eeprom, int esize, int index);
virtual int save(uint8_t * eeprom, const RadioData & radioData, uint8_t version=0, uint32_t variant=0);
virtual int getSize(const ModelData &);
virtual int getSize(const GeneralSettings &);
protected:
const char * getName();
@@ -53,33 +57,35 @@ class OpenTxEepromInterface : public EEPROMInterface
EepromLoadErrors checkVersion(unsigned int version);
bool checkVariant(unsigned int version, unsigned int variant);
template <class T, class M>
bool loadFromByteArray(T & dest, const QByteArray & data, uint8_t version, uint32_t variant=0);
public:
template <class T, class M>
bool loadFromByteArray(T & dest, const QByteArray & data);
template <class T, class M>
bool saveToByteArray(const T & src, QByteArray & data, uint8_t version=0);
bool loadRadioSettingsFromRLE(GeneralSettings & settings, RleFile * rleFile, uint8_t version);
bool loadModelFromRLE(ModelData & model, RleFile * rleFile, unsigned int index, uint8_t version, uint32_t variant);
void showErrors(const QString & title, const QStringList & errors);
uint8_t getLastDataVersion(Board::Type board);
RleFile * efile;
OpenTxFirmware * firmware;
};
class OpenTxFirmware: public Firmware
{
Q_DECLARE_TR_FUNCTIONS(OpenTxFirmware)
public:
OpenTxFirmware(const QString & id, OpenTxFirmware * parent):
Firmware(parent, id, parent->getName(), parent->getBoard())
@@ -100,19 +106,6 @@ class OpenTxFirmware: public Firmware
addLanguage("pl");
addLanguage("pt");
addLanguage("se");
addTTSLanguage("en");
addTTSLanguage("cz");
addTTSLanguage("de");
addTTSLanguage("es");
addTTSLanguage("fr");
addTTSLanguage("hu");
addTTSLanguage("it");
addTTSLanguage("nl");
addTTSLanguage("pl");
addTTSLanguage("pt");
addTTSLanguage("se");
addTTSLanguage("sk");
}
virtual Firmware * getFirmwareVariant(const QString & id);
@@ -124,9 +117,9 @@ class OpenTxFirmware: public Firmware
virtual QString getFirmwareUrl();
virtual int getCapability(Capability);
virtual QString getAnalogInputName(unsigned int index);
virtual QTime getMaxTimerStart();
virtual int isAvailable(PulsesProtocol proto, int port=0);
+127
View File
@@ -0,0 +1,127 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "radiodata.h"
#include "radiodataconversionstate.h"
#include "eeprominterface.h"
// static
QString RadioData::getElementName(const QString & prefix, unsigned int index, const char * name, bool padding)
{
QString result = prefix;
if (padding)
result += QString("%1").arg(index, 2, 10, QChar('0'));
else
result += QString("%1").arg(index);
if (name) {
QString trimmed = QString(name).trimmed();
if (trimmed.length() > 0) {
result += ":" + QString(name).trimmed();
}
}
return result;
}
RadioData::RadioData()
{
models.resize(getCurrentFirmware()->getCapability(Models));
}
void RadioData::setCurrentModel(unsigned int index)
{
generalSettings.currModelIndex = index;
if (index < models.size()) {
strcpy(generalSettings.currModelFilename, models[index].filename);
}
}
void RadioData::fixModelFilename(unsigned int index)
{
ModelData & model = models[index];
QString filename(model.filename);
bool ok = filename.endsWith(".bin");
if (ok) {
if (filename.startsWith("model") && filename.mid(5, filename.length()-9).toInt() > 0) {
ok = false;
}
}
if (ok) {
for (unsigned i=0; i<index; i++) {
if (strcmp(models[i].filename, model.filename) == 0) {
ok = false;
break;
}
}
}
if (!ok) {
sprintf(model.filename, "model%d.bin", index+1);
}
}
void RadioData::fixModelFilenames()
{
for (unsigned int i=0; i<models.size(); i++) {
fixModelFilename(i);
}
setCurrentModel(generalSettings.currModelIndex);
}
QString RadioData::getNextModelFilename()
{
char filename[sizeof(ModelData::filename)];
int index = 0;
bool found = true;
while (found) {
sprintf(filename, "model%d.bin", ++index);
found = false;
for (unsigned int i=0; i<models.size(); i++) {
if (strcmp(filename, models[i].filename) == 0) {
found = true;
break;
}
}
}
return filename;
}
void RadioData::convert(RadioDataConversionState & cstate)
{
generalSettings.convert(cstate.withModelIndex(-1));
for (unsigned i=0; i<models.size(); i++) {
models[i].convert(cstate.withModelIndex(i));
}
if (categories.size() == 0) {
categories.push_back(CategoryData(qPrintable(tr("Models"))));
for (unsigned i=0; i<models.size(); i++) {
models[i].category = 0;
}
}
if (IS_HORUS(cstate.toType)) {
fixModelFilenames();
}
// ensure proper number of model slots
if (getCurrentFirmware()->getCapability(Models) && getCurrentFirmware()->getCapability(Models) != (int)models.size()) {
models.resize(getCurrentFirmware()->getCapability(Models));
}
}
+41
View File
@@ -0,0 +1,41 @@
#ifndef _RADIODATA_H_
#define _RADIODATA_H_
#include "generalsettings.h"
#include "modeldata.h"
#include <QtCore>
class RadioDataConversionState;
class CategoryData {
public:
CategoryData(const char * name) {
strncpy(this->name, name, sizeof(CategoryData::name));
}
char name[15+1];
};
class RadioData {
Q_DECLARE_TR_FUNCTIONS(RadioData)
public:
RadioData();
GeneralSettings generalSettings;
std::vector<CategoryData> categories;
std::vector<ModelData> models;
void convert(RadioDataConversionState & cstate);
void setCurrentModel(unsigned int index);
void fixModelFilenames();
QString getNextModelFilename();
static QString getElementName(const QString & prefix, unsigned int index, const char * name = 0, bool padding = false);
protected:
void fixModelFilename(unsigned int index);
};
#endif // _RADIODATA_H_
@@ -0,0 +1,223 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "radiodataconversionstate.h"
#include "radiodata.h"
#include <QStandardItemModel>
RadioDataConversionState::RadioDataConversionState(Board::Type before, Board::Type after, RadioData * rdata) :
fromType(before),
toType(after),
fromBoard(Boards(before)),
toBoard(Boards(after)),
rd(NULL),
rdCopy(NULL),
maxEventType(EVT_NONE),
modelIdx(-1),
subCompIdx(-1)
{
setRadioData(rdata);
}
RadioDataConversionState::~RadioDataConversionState()
{
if (rdCopy)
delete rdCopy;
}
RadioDataConversionState & RadioDataConversionState::withModelIndex(int index)
{
modelIdx = index;
subCompIdx = -1;
setLogField(FLD_ORIGIN);
return *this;
}
RadioDataConversionState & RadioDataConversionState::withComponentIndex(int index)
{
subCompIdx = index;
setLogField(FLD_SUB_COMP);
return *this;
}
RadioDataConversionState &RadioDataConversionState::withComponentField(const QString & name)
{
setLogField(FLD_COMP_FIELD, LogField(0, name));
return *this;
}
bool RadioDataConversionState::convert()
{
if (rd) {
rd->convert(*this);
return true;
}
setErr(("No radio data to convert."));
return false;
}
void RadioDataConversionState::setRadioData(RadioData * rdata)
{
rd = rdata;
if (rdCopy)
delete rdCopy;
rdCopy = new RadioData(*rdata);
logCache = LogRecord();
}
void RadioDataConversionState::setLogField(LogFieldType type, const LogField & data, bool clearRest)
{
if (type >= FLD_ENUM_COUNT)
return;
logCache.fields[type].id = data.id;
logCache.fields[type].name = data.name;
if (clearRest && type + 1 < FLD_ENUM_COUNT)
setLogField(LogFieldType(type + 1));
}
void RadioDataConversionState::addLogEntry(EventType event, const QString & msg)
{
if (event != EVT_NONE) {
setLogField(FLD_EVT_TYPE, LogField(event, eventTypeToString(event)), false);
setLogField(FLD_MSG, LogField(event, msg), false);
log.append(logCache);
}
maxEventType = qMax(event, maxEventType);
logCache.fields[FLD_MSG].clear();
}
void RadioDataConversionState::setInvalid(const LogField & item)
{
setLogField(FLD_ITM_BEFORE, item);
addLogEntry(EVT_INV, tr("is invalid"));
}
void RadioDataConversionState::setConverted(const LogField & from, const LogField & to)
{
setLogField(FLD_ITM_BEFORE, from);
setLogField(FLD_ITM_AFTER, to);
addLogEntry(EVT_CVRT, tr("converted to"));
}
void RadioDataConversionState::setMoved(const LogField & from, const LogField & to)
{
setLogField(FLD_ITM_BEFORE, from);
setLogField(FLD_ITM_AFTER, to);
addLogEntry(EVT_INF, tr("verify is"));
}
const ModelData * RadioDataConversionState::toModel() const
{
if (rd && modelIdx > -1 && modelIdx < (int)rd->models.size())
return &rd->models[modelIdx];
return NULL;
}
const ModelData *RadioDataConversionState::fromModel() const
{
if (rdCopy && modelIdx > -1 && modelIdx < (int)rdCopy->models.size())
return &rdCopy->models[modelIdx];
return NULL;
}
const GeneralSettings * RadioDataConversionState::toGS() const
{
if (rd)
return &rd->generalSettings;
return NULL;
}
const GeneralSettings *RadioDataConversionState::fromGS() const
{
if (rdCopy)
return &rdCopy->generalSettings;
return NULL;
}
bool RadioDataConversionState::hasLogEntries(EventType logLevel) const
{
return (maxEventType >= logLevel);
}
QString RadioDataConversionState::eventTypeToString(int type) const
{
// enum EventType { EVT_NONE, EVT_DBG, EVT_INF, EVT_WRN, EVT_CVRT, EVT_ERR, EVT_INV
static const QStringList evtTypes = QStringList() << "" << tr("[DBG]") << tr("[NFO]") << tr("[WRN]") << tr("[CVT]") << tr("[ERR]") << tr("[INV]");
return (type < evtTypes.size() ? evtTypes.at(type) : "");
}
QString RadioDataConversionState::eventTypeToColor(int type) const
{
// enum EventType { EVT_NONE, EVT_DBG, EVT_INF, EVT_WRN, EVT_CVRT, EVT_ERR, EVT_INV
static const QStringList evtColors = QStringList() << "black" << "dimgrey" << "black" << "#ea7104" << "#ea7104" << "red" << "red";
return (type < evtColors.size() ? evtColors.at(type) : "black");
}
QString RadioDataConversionState::getFieldName(int field) const
{
static const QStringList dataFields = QStringList() << tr("Event") << tr("Origin") << tr("Comp") << tr("Sub-Component") << tr("Field") << tr("Type") << tr("Old") << tr("Action") << tr("New");
return (field < dataFields.size() ? dataFields.at(field) : "");
}
QStandardItemModel * RadioDataConversionState::getLogModel(RadioDataConversionState::EventType logLevel, QObject * parent) const
{
QStandardItemModel * stdmdl = new QStandardItemModel(parent);
const QString tooltip = "%1: %2 (ID: %3)";
const int sortRole = Qt::UserRole + 1;
const int seqdigits = floorf(logf(log.size()) / logf(10.0f)) + 1;
stdmdl->setSortRole(sortRole);
QStringList header;
header << tr("Seq");
for (int i=0; i < FLD_ENUM_COUNT; ++i)
header << getFieldName(i);
stdmdl->setHorizontalHeaderLabels(header);
QFont fnt("Courier");
fnt.setStyleHint(QFont::TypeWriter);
//fnt.setPointSize(fnt.pointSize()+1);
int row = 0;
foreach (const LogRecord & lr, log) {
if (lr.fields.at(FLD_EVT_TYPE).id < logLevel)
continue;
QBrush fg(QColor(eventTypeToColor(lr.fields.at(FLD_EVT_TYPE).id)));
stdmdl->setItem(row, 0, new QStandardItem(QString("%1").arg(row+1, seqdigits, 10, QChar('0'))));
stdmdl->item(row, 0)->setData(row, sortRole);
stdmdl->item(row, 0)->setData(fnt, Qt::FontRole);
for (int i=0; i < FLD_ENUM_COUNT; ++i) {
QStandardItem * itm = new QStandardItem(lr.fields.at(i).name);
itm->setData(lr.fields.at(i).id, sortRole);
itm->setData(fnt, Qt::FontRole);
itm->setData(tooltip.arg(getFieldName(i)).arg(lr.fields.at(i).name).arg(lr.fields.at(i).id), Qt::ToolTipRole);
itm->setEditable(false);
if (i == FLD_EVT_TYPE || i == FLD_MSG)
itm->setForeground(fg);
stdmdl->setItem(row, i+1, itm);
}
++row;
}
return stdmdl;
}
@@ -0,0 +1,121 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef RADIODATACONVERSIONSTATE_H
#define RADIODATACONVERSIONSTATE_H
#include "boards.h"
#include <QtCore>
class ModelData;
class GeneralSettings;
class RadioData;
class QStandardItemModel;
class RadioDataConversionState
{
Q_DECLARE_TR_FUNCTIONS(RadioDataConversionState)
public:
enum EventType {
EVT_NONE, // does not get logged
EVT_DBG, // debug
EVT_INF, // misc. info
EVT_WRN, // misc. warning, place warning-level events after this and before EVT_ERR
EVT_CVRT, // something was converted (A->B)
EVT_ERR, // misc. error, place error-level events after this
EVT_INV, // invalid, control/etc not available on destination radio
};
enum LogFieldType {
FLD_EVT_TYPE, // EventType
FLD_ORIGIN, // General Settings or Model with name
FLD_COMP, // Input/Mix/LS/CF/etc
FLD_SUB_COMP, // Mix channel/Input line/LS number/etc
FLD_COMP_FIELD, // optional item within subcomponent, eg. LS V1/V2/AND, etc
FLD_ITM_TYPE, // Source/Switch
FLD_ITM_BEFORE, // item before conversion
FLD_MSG, // conversion details
FLD_ITM_AFTER, // item after conversion
FLD_ENUM_COUNT
};
struct LogField {
LogField(int id = 0, const QString & name = QString()) : id(id), name(name) {}
void clear() { id = 0; name.clear(); }
int id;
QString name;
};
struct LogRecord
{
LogRecord() { fields.resize(FLD_ENUM_COUNT); }
QVector<LogField> fields; // collected data fields indexed by LogColumn value
};
RadioDataConversionState(Board::Type before = Board::BOARD_UNKNOWN, Board::Type after = Board::BOARD_UNKNOWN, RadioData * rdata = NULL);
~RadioDataConversionState();
RadioDataConversionState & withModelIndex(int index);
RadioDataConversionState & withComponentIndex(int index);
RadioDataConversionState & withComponentField(const QString & name);
bool convert();
void setRadioData(RadioData * rdata);
void setLogField(LogFieldType type, const LogField & data = LogField(), bool clearRest = true);
inline void setOrigin(const QString & name = QString()) { setLogField(FLD_ORIGIN, LogField(modelIdx, name)); }
inline void setSubComp(const QString & name = QString()) { setLogField(FLD_SUB_COMP, LogField(subCompIdx, name)); }
inline void setComponent(const QString & name = QString(), int id = 0) { setLogField(FLD_COMP, LogField(id, name)); }
inline void setItemType(const QString & name = QString(), int id = 0) { setLogField(FLD_ITM_TYPE, LogField(id, name)); }
void addLogEntry(EventType event, const QString & msg = QString());
void setInvalid(const LogField & item);
void setConverted(const LogField & from, const LogField & to);
void setMoved(const LogField & from, const LogField & to);
inline void setDbg(const QString & msg) { addLogEntry(EVT_DBG, msg); }
inline void setInf(const QString & msg) { addLogEntry(EVT_INF, msg); }
inline void setWrn(const QString & msg) { addLogEntry(EVT_WRN, msg); }
inline void setErr(const QString & msg) { addLogEntry(EVT_ERR, msg); }
const ModelData * toModel() const;
const ModelData * fromModel() const;
const GeneralSettings * toGS() const;
const GeneralSettings * fromGS() const;
bool hasLogEntries(EventType logLevel = EVT_INF) const;
QString eventTypeToString(int type) const;
QString eventTypeToColor(int type) const;
QString getFieldName(int field) const;
QStandardItemModel * getLogModel(EventType logLevel = EVT_INF, QObject *parent = Q_NULLPTR) const;
Board::Type fromType; // board type before conversion
Board::Type toType; // board type after
Boards fromBoard;
Boards toBoard;
RadioData * rd; // pointer to data struct being converted
RadioData * rdCopy; // copy of original radio data before conversion
QVector<LogRecord> log; // logged events
LogRecord logCache; // buffer for holding event data before logging
EventType maxEventType; // most severe event type recorded
int modelIdx; // model index in radio data array, -1 if none
int subCompIdx; // current row index within component (eg. model.mixData[componentIdx]), -1 if none
};
#endif // RADIODATACONVERSIONSTATE_H
+644
View File
@@ -0,0 +1,644 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "rawsource.h"
#include "eeprominterface.h"
#include "radiodata.h"
#include "radiodataconversionstate.h"
#include <float.h>
/*
* RawSourceRange
*/
float RawSourceRange::getValue(int value)
{
if (IS_ARM(getCurrentBoard()))
return float(value) * step;
else
return min + float(value) * step;
}
/*
* RawSource
*/
RawSourceRange RawSource::getRange(const ModelData * model, const GeneralSettings & settings, unsigned int flags) const
{
RawSourceRange result;
Firmware * firmware = Firmware::getCurrentVariant();
int board = firmware->getBoard();
switch (type) {
case SOURCE_TYPE_TELEMETRY:
if (IS_ARM(board)) {
div_t qr = div(index, 3);
const SensorData & sensor = model->sensorData[qr.quot];
if (sensor.prec == 2)
result.step = 0.01;
else if (sensor.prec == 1)
result.step = 0.1;
else
result.step = 1;
result.min = -30000 * result.step;
result.max = +30000 * result.step;
result.decimals = sensor.prec;
result.unit = sensor.unitString();
}
else {
result.offset = -DBL_MAX;
switch (index) {
case TELEMETRY_SOURCE_TX_BATT:
result.step = 0.1;
result.decimals = 1;
result.max = 25.5;
result.unit = tr("V");
break;
case TELEMETRY_SOURCE_TX_TIME:
result.step = 60;
result.max = 24 * 60 * result.step - 60; // 23:59:00 with 1-minute resolution
result.unit = tr("s");
break;
case TELEMETRY_SOURCE_TIMER1:
case TELEMETRY_SOURCE_TIMER2:
case TELEMETRY_SOURCE_TIMER3:
result.step = 5;
result.max = 255 * result.step;
result.unit = tr("s");
break;
case TELEMETRY_SOURCE_RSSI_TX:
case TELEMETRY_SOURCE_RSSI_RX:
result.max = 100;
result.offset = 128;
break;
case TELEMETRY_SOURCE_A1_MIN:
case TELEMETRY_SOURCE_A2_MIN:
case TELEMETRY_SOURCE_A3_MIN:
case TELEMETRY_SOURCE_A4_MIN:
if (model) result = model->frsky.channels[index-TELEMETRY_SOURCE_A1_MIN].getRange();
break;
case TELEMETRY_SOURCE_A1:
case TELEMETRY_SOURCE_A2:
case TELEMETRY_SOURCE_A3:
case TELEMETRY_SOURCE_A4:
if (model) result = model->frsky.channels[index-TELEMETRY_SOURCE_A1].getRange();
break;
case TELEMETRY_SOURCE_ALT:
case TELEMETRY_SOURCE_ALT_MIN:
case TELEMETRY_SOURCE_ALT_MAX:
case TELEMETRY_SOURCE_GPS_ALT:
result.step = 8;
result.min = -500;
result.max = 1540;
if (firmware->getCapability(Imperial) || settings.imperial) {
result.step = (result.step * 105) / 32;
result.min = (result.min * 105) / 32;
result.max = (result.max * 105) / 32;
result.unit = tr("ft");
}
else {
result.unit = tr("m");
}
break;
case TELEMETRY_SOURCE_T1:
case TELEMETRY_SOURCE_T1_MAX:
case TELEMETRY_SOURCE_T2:
case TELEMETRY_SOURCE_T2_MAX:
result.min = -30;
result.max = 225;
result.unit = trUtf8("°C");
break;
case TELEMETRY_SOURCE_HDG:
result.step = 2;
result.max = 360;
result.offset = 256;
result.unit = trUtf8("°");
break;
case TELEMETRY_SOURCE_RPM:
case TELEMETRY_SOURCE_RPM_MAX:
result.step = 50;
result.max = 12750;
break;
case TELEMETRY_SOURCE_FUEL:
result.max = 100;
result.unit = tr("%");
break;
case TELEMETRY_SOURCE_ASPEED:
case TELEMETRY_SOURCE_ASPEED_MAX:
result.decimals = 1;
result.step = 2.0;
result.max = (2*255);
if (firmware->getCapability(Imperial) || settings.imperial) {
result.step *= 1.150779;
result.max *= 1.150779;
result.unit = tr("mph");
}
else {
result.step *= 1.852;
result.max *= 1.852;
result.unit = tr("km/h");
}
break;
case TELEMETRY_SOURCE_SPEED:
case TELEMETRY_SOURCE_SPEED_MAX:
result.step = 2;
result.max = (2*255);
if (firmware->getCapability(Imperial) || settings.imperial) {
result.step *= 1.150779;
result.max *= 1.150779;
result.unit = tr("mph");
}
else {
result.step *= 1.852;
result.max *= 1.852;
result.unit = tr("km/h");
}
break;
case TELEMETRY_SOURCE_VERTICAL_SPEED:
result.step = 0.1;
result.min = -12.5;
result.max = 13.0;
result.decimals = 1;
result.unit = tr("m/s");
break;
case TELEMETRY_SOURCE_DTE:
result.max = 30000;
break;
case TELEMETRY_SOURCE_DIST:
case TELEMETRY_SOURCE_DIST_MAX:
result.step = 8;
result.max = 2040;
result.unit = tr("m");
break;
case TELEMETRY_SOURCE_CELL:
case TELEMETRY_SOURCE_CELL_MIN:
result.step = 0.02;
result.max = 5.1;
result.decimals = 2;
result.unit = tr("V");
break;
case TELEMETRY_SOURCE_CELLS_SUM:
case TELEMETRY_SOURCE_CELLS_MIN:
case TELEMETRY_SOURCE_VFAS:
case TELEMETRY_SOURCE_VFAS_MIN:
result.step = 0.1;
result.max = 25.5;
result.decimals = 1;
result.unit = tr("V");
break;
case TELEMETRY_SOURCE_CURRENT:
case TELEMETRY_SOURCE_CURRENT_MAX:
result.step = 0.5;
result.max = 127.5;
result.decimals = 1;
result.unit = tr("A");
break;
case TELEMETRY_SOURCE_CONSUMPTION:
result.step = 100;
result.max = 25500;
result.unit = tr("mAh");
break;
case TELEMETRY_SOURCE_POWER:
case TELEMETRY_SOURCE_POWER_MAX:
result.step = 5;
result.max = 1275;
result.unit = tr("W");
break;
case TELEMETRY_SOURCE_ACCX:
case TELEMETRY_SOURCE_ACCY:
case TELEMETRY_SOURCE_ACCZ:
result.step = 0.01;
result.decimals = 2;
result.max = 2.55;
result.min = 0;
result.unit = tr("g");
break;
default:
result.max = 125;
break;
}
if (result.offset == -DBL_MAX) {
result.offset = result.max - (127*result.step);
}
if (flags & (RANGE_DELTA_FUNCTION | RANGE_ABS_FUNCTION)) {
result.offset = 0;
result.min = result.step * -127;
result.max = result.step * 127;
}
}
break;
case SOURCE_TYPE_LUA_OUTPUT:
result.max = 30000;
result.min = -result.max;
break;
case SOURCE_TYPE_TRIM:
result.max = (model && model->extendedTrims ? firmware->getCapability(ExtendedTrimsRange) : firmware->getCapability(TrimsRange));
result.min = -result.max;
break;
case SOURCE_TYPE_GVAR: {
GVarData gv = model->gvarData[index];
result.step = gv.multiplierGet();
result.decimals = gv.prec;
result.max = gv.getMaxPrec();
result.min = gv.getMinPrec();
result.unit = gv.unitToString();
break;
}
case SOURCE_TYPE_SPECIAL:
if (index == 0) { //Batt
result.step = 0.1;
result.decimals = 1;
result.max = 25.5;
result.unit = tr("V");
}
else if (index == 1) { //Time
result.step = 60;
result.max = 24 * 60 * result.step - 60; // 23:59:00 with 1-minute resolution
result.unit = tr("s");
}
else { // Timers 1 - 3
result.step = 1;
result.max = 9 * 60 * 60 - 1; // 8:59:59 (to match firmware)
result.min = -result.max;
result.unit = tr("s");
}
break;
case SOURCE_TYPE_CH:
result.max = model->getChannelsMax(false);
result.min = -result.max;
break;
default:
result.max = 100;
result.min = -result.max;
break;
}
if (flags & RANGE_ABS_FUNCTION) {
result.min = 0;
}
return result;
}
QString RawSource::toString(const ModelData * model, const GeneralSettings * const generalSettings, Board::Type board) const
{
if (board == Board::BOARD_UNKNOWN) {
board = getCurrentBoard();
}
static const QString trims[] = {
tr("TrmR"), tr("TrmE"), tr("TrmT"), tr("TrmA"), tr("Trm5"), tr("Trm6")
};
static const QString trims2[] = {
tr("TrmH"), tr("TrmV")
};
static const QString special[] = {
tr("Batt"), tr("Time"), tr("Timer1"), tr("Timer2"), tr("Timer3"),
};
static const QString telemetry[] = {
tr("Batt"), tr("Time"), tr("Timer1"), tr("Timer2"), tr("Timer3"),
tr("RAS"), tr("RSSI Tx"), tr("RSSI Rx"),
tr("A1"), tr("A2"), tr("A3"), tr("A4"),
tr("Alt"), tr("Rpm"), tr("Fuel"), tr("T1"), tr("T2"),
tr("Speed"), tr("Dist"), tr("GPS Alt"),
tr("Cell"), tr("Cells"), tr("Vfas"), tr("Curr"), tr("Cnsp"), tr("Powr"),
tr("AccX"), tr("AccY"), tr("AccZ"),
tr("Hdg "), tr("VSpd"), tr("AirSpeed"), tr("dTE"),
tr("A1-"), tr("A2-"), tr("A3-"), tr("A4-"),
tr("Alt-"), tr("Alt+"), tr("Rpm+"), tr("T1+"), tr("T2+"), tr("Speed+"), tr("Dist+"), tr("AirSpeed+"),
tr("Cell-"), tr("Cells-"), tr("Vfas-"), tr("Curr+"), tr("Powr+"),
tr("ACC"), tr("GPS Time"),
};
static const QString rotary[] = { tr("REa"), tr("REb") };
if (index<0) {
return tr("???");
}
QString result;
int genAryIdx = 0;
switch (type) {
case SOURCE_TYPE_NONE:
return tr("----");
case SOURCE_TYPE_VIRTUAL_INPUT:
{
const char * name = NULL;
if (model)
name = model->inputNames[index];
return RadioData::getElementName(tr("I", "as in Input"), index + 1, name);
}
case SOURCE_TYPE_LUA_OUTPUT:
return tr("LUA%1%2").arg(index/16+1).arg(QChar('a'+index%16));
case SOURCE_TYPE_STICK:
if (generalSettings) {
if (isPot(&genAryIdx))
result = QString(generalSettings->potName[genAryIdx]);
else if (isSlider(&genAryIdx))
result = QString(generalSettings->sliderName[genAryIdx]);
else if (isStick(&genAryIdx))
result = QString(generalSettings->stickName[genAryIdx]);
}
if (result.isEmpty())
result = Boards::getAnalogInputName(board, index);
return result;
case SOURCE_TYPE_TRIM:
return (Boards::getCapability(board, Board::NumTrims) == 2 ? CHECK_IN_ARRAY(trims2, index) : CHECK_IN_ARRAY(trims, index));
case SOURCE_TYPE_ROTARY_ENCODER:
return CHECK_IN_ARRAY(rotary, index);
case SOURCE_TYPE_MAX:
return tr("MAX");
case SOURCE_TYPE_SWITCH:
if (generalSettings)
result = QString(generalSettings->switchName[index]);
if (result.isEmpty())
result = Boards::getSwitchInfo(board, index).name;
return result;
case SOURCE_TYPE_CUSTOM_SWITCH:
return RawSwitch(SWITCH_TYPE_VIRTUAL, index+1).toString();
case SOURCE_TYPE_CYC:
return tr("CYC%1").arg(index+1);
case SOURCE_TYPE_PPM:
return RadioData::getElementName(tr("TR", "as in Trainer"), index + 1);
case SOURCE_TYPE_CH:
if (model)
return model->limitData[index].nameToString(index);
else
return LimitData().nameToString(index);
case SOURCE_TYPE_SPECIAL:
return CHECK_IN_ARRAY(special, index);
case SOURCE_TYPE_TELEMETRY:
if (IS_ARM(board)) {
div_t qr = div(index, 3);
if (model)
result = model->sensorData[qr.quot].nameToString(qr.quot);
else
result = SensorData().nameToString(qr.quot);
if (qr.rem)
result += (qr.rem == 1 ? "-" : "+");
return result;
}
else {
return CHECK_IN_ARRAY(telemetry, index);
}
case SOURCE_TYPE_GVAR:
if (model)
return model->gvarData[index].nameToString(index);
else
return GVarData().nameToString(index);
default:
return tr("???");
}
}
bool RawSource::isStick(int * stickIndex, Board::Type board) const
{
if (board == Board::BOARD_UNKNOWN)
board = getCurrentBoard();
if (type == SOURCE_TYPE_STICK && index < Boards::getCapability(board, Board::Sticks)) {
if (stickIndex)
*stickIndex = index;
return true;
}
return false;
}
bool RawSource::isPot(int * potsIndex, Board::Type board) const
{
if (board == Board::BOARD_UNKNOWN)
board = getCurrentBoard();
Boards b(board);
if (type == SOURCE_TYPE_STICK &&
index >= b.getCapability(Board::Sticks) &&
index < b.getCapability(Board::Sticks) + b.getCapability(Board::Pots)) {
if (potsIndex)
*potsIndex = index - b.getCapability(Board::Sticks);
return true;
}
return false;
}
bool RawSource::isSlider(int * sliderIndex, Board::Type board) const
{
if (board == Board::BOARD_UNKNOWN)
board = getCurrentBoard();
Boards b(board);
if (type == SOURCE_TYPE_STICK &&
index >= b.getCapability(Board::Sticks) + b.getCapability(Board::Pots) &&
index < b.getCapability(Board::Sticks) + b.getCapability(Board::Pots) + b.getCapability(Board::Sliders)) {
if (sliderIndex)
*sliderIndex = index - b.getCapability(Board::Sticks) - b.getCapability(Board::Pots);
return true;
}
return false;
}
bool RawSource::isTimeBased(Board::Type board) const
{
if (board == Board::BOARD_UNKNOWN)
board = getCurrentBoard();
if (IS_ARM(board))
return (type == SOURCE_TYPE_SPECIAL && index > 0);
else
return (type==SOURCE_TYPE_TELEMETRY && (index==TELEMETRY_SOURCE_TX_TIME || index==TELEMETRY_SOURCE_TIMER1 || index==TELEMETRY_SOURCE_TIMER2 || index==TELEMETRY_SOURCE_TIMER3));
}
bool RawSource::isAvailable(const ModelData * const model, const GeneralSettings * const gs, Board::Type board) const
{
if (board == Board::BOARD_UNKNOWN)
board = getCurrentBoard();
Boards b(board);
if (type == SOURCE_TYPE_STICK && index >= b.getCapability(Board::MaxAnalogs))
return false;
if (type == SOURCE_TYPE_SWITCH && index >= b.getCapability(Board::Switches))
return false;
if (model) {
if (type == SOURCE_TYPE_VIRTUAL_INPUT && !model->isInputValid(index))
return false;
if (type == SOURCE_TYPE_CUSTOM_SWITCH && model->logicalSw[index].isEmpty())
return false;
if (type == SOURCE_TYPE_TELEMETRY) {
if (IS_ARM(board) && !model->sensorData[div(index, 3).quot].isAvailable()) {
return false;
}
else if (!IS_ARM(board)) {
Firmware * fw = getCurrentFirmware();
if (type == (int)TELEMETRY_SOURCE_TX_TIME && !fw->getCapability(RtcTime))
return false;
if (type == (int)TELEMETRY_SOURCE_RAS && !fw->getCapability(SportTelemetry))
return false;
if (type == (int)TELEMETRY_SOURCE_TIMER3 && fw->getCapability(Timers) < 3)
return false;
}
}
}
if (gs) {
int gsIdx = 0;
if (type == SOURCE_TYPE_STICK && ((isPot(&gsIdx) && !gs->isPotAvailable(gsIdx)) || (isSlider(&gsIdx) && !gs->isSliderAvailable(gsIdx))))
return false;
if (type == SOURCE_TYPE_SWITCH && IS_HORUS_OR_TARANIS(board) && !gs->switchSourceAllowedTaranis(index))
return false;
}
if (type == SOURCE_TYPE_TRIM && index >= b.getCapability(Board::NumTrims))
return false;
return true;
}
RawSource RawSource::convert(RadioDataConversionState & cstate)
{
cstate.setItemType(tr("SRC"), 1);
RadioDataConversionState::EventType evt = RadioDataConversionState::EVT_NONE;
RadioDataConversionState::LogField oldData(index, toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType));
if (type == SOURCE_TYPE_STICK) {
if (cstate.toBoard.getCapability(Board::Sliders)) {
if (index >= cstate.fromBoard.getCapability(Board::Sticks) + cstate.fromBoard.getCapability(Board::Pots)) {
// 1st slider alignment
index += cstate.toBoard.getCapability(Board::Pots) - cstate.fromBoard.getCapability(Board::Pots);
}
if (isSlider(0, cstate.fromType)) {
// LS and RS sliders are after 2 aux sliders on X12 and X9E
if ((IS_HORUS_X12S(cstate.toType) || IS_TARANIS_X9E(cstate.toType)) && !IS_HORUS_X12S(cstate.fromType) && !IS_TARANIS_X9E(cstate.fromType)) {
if (index >= 7) {
index += 2; // LS/RS to LS/RS
}
}
else if (!IS_TARANIS_X9E(cstate.toType) && !IS_HORUS_X12S(cstate.toType) && (IS_HORUS_X12S(cstate.fromType) || IS_TARANIS_X9E(cstate.fromType))) {
if (index >= 7 && index <= 8) {
index += 2; // aux sliders to spare analogs (which may not exist, this is validated later)
evt = RadioDataConversionState::EVT_CVRT;
}
else if (index >= 9 && index <= 10) {
index -= 2; // LS/RS to LS/RS
}
}
}
}
if (IS_TARANIS(cstate.toType) && IS_HORUS(cstate.fromType)) {
if (index == 6)
index = 5; // pot S2 to S2
else if (index == 5)
index = -1; // 6P on Horus doesn't exist on Taranis
}
else if (IS_HORUS(cstate.toType) && IS_TARANIS(cstate.fromType) && index == 5)
{
index = 6; // pot S2 to S2
}
} // SOURCE_TYPE_STICK
if (type == SOURCE_TYPE_SWITCH) {
// SWI to SWR don't exist on !X9E board
if (!IS_TARANIS_X9E(cstate.toType) && IS_TARANIS_X9E(cstate.fromType)) {
if (index >= 8) {
index = index % 8;
evt = RadioDataConversionState::EVT_CVRT;
}
}
if (IS_TARANIS_X7(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_HORUS(cstate.fromType))) {
// No SE and SG on X7 board
if (index == 4 || index == 6) {
index = 3; // SG and SE to SD
evt = RadioDataConversionState::EVT_CVRT;
}
else if (index == 5) {
index = 4; // SF to SF
}
else if (index == 7) {
index = 5; // SH to SH
}
}
// Compensate for SE and SG on X9/Horus board if converting from X7
else if ((IS_TARANIS_X9(cstate.toType) || IS_HORUS(cstate.toType)) && IS_TARANIS_X7(cstate.fromType)) {
if (index == 4) {
index = 5; // SF to SF
}
else if (index == 5) {
index = 7; // SH to SH
}
}
} // SOURCE_TYPE_SWITCH
// final validation (we do not pass model to isAvailable() because we don't know what has or hasn't been converted)
if (!isAvailable(NULL, cstate.toGS(), cstate.toType)) {
cstate.setInvalid(oldData);
index = -1; // TODO: better way to flag invalid sources?
type = MAX_SOURCE_TYPE;
}
else if (evt == RadioDataConversionState::EVT_CVRT) {
cstate.setConverted(oldData, RadioDataConversionState::LogField(index, toString(cstate.toModel(), cstate.toGS(), cstate.toType)));
}
else if (oldData.id != index) {
// provide info by default if anything changed
cstate.setMoved(oldData, RadioDataConversionState::LogField(index, toString(cstate.toModel(), cstate.toGS(), cstate.toType)));
}
return *this;
}
+274
View File
@@ -0,0 +1,274 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef RAWSOURCE_H
#define RAWSOURCE_H
#include "boards.h"
#include "constants.h"
#include <QtCore>
class Firmware;
class ModelData;
class GeneralSettings;
class RadioDataConversionState;
enum Switches {
SWITCH_NONE,
SWITCH_THR = SWITCH_NONE+1,
SWITCH_RUD,
SWITCH_ELE,
SWITCH_ID0,
SWITCH_ID1,
SWITCH_ID2,
SWITCH_AIL,
SWITCH_GEA,
SWITCH_TRN,
SWITCH_SA0 = SWITCH_NONE+1,
SWITCH_SA1,
SWITCH_SA2,
SWITCH_SB0,
SWITCH_SB1,
SWITCH_SB2,
SWITCH_SC0,
SWITCH_SC1,
SWITCH_SC2,
SWITCH_SD0,
SWITCH_SD1,
SWITCH_SD2,
SWITCH_SE0,
SWITCH_SE1,
SWITCH_SE2,
SWITCH_SF0,
SWITCH_SF1,
SWITCH_SG0,
SWITCH_SG1,
SWITCH_SG2,
SWITCH_SH0,
SWITCH_SH2,
SWITCH_SI0,
SWITCH_SI2,
SWITCH_SJ0,
SWITCH_SJ2,
SWITCH_SK0,
SWITCH_SK2,
};
enum TimerModes {
TMRMODE_NONE,
TMRMODE_ABS,
TMRMODE_THR,
TMRMODE_THR_REL,
TMRMODE_THR_TRG,
TMRMODE_FIRST_SWITCH
};
enum FailsafeModes {
FAILSAFE_NOT_SET,
FAILSAFE_HOLD,
FAILSAFE_CUSTOM,
FAILSAFE_NOPULSES,
FAILSAFE_RECEIVER,
FAILSAFE_LAST = FAILSAFE_RECEIVER
};
enum HeliSwashTypes {
HELI_SWASH_TYPE_NONE=0,
HELI_SWASH_TYPE_120,
HELI_SWASH_TYPE_120X,
HELI_SWASH_TYPE_140,
HELI_SWASH_TYPE_90
};
enum TelemetrySource {
TELEMETRY_SOURCE_TX_BATT,
TELEMETRY_SOURCE_TX_TIME,
TELEMETRY_SOURCE_TIMER1,
TELEMETRY_SOURCE_TIMER2,
TELEMETRY_SOURCE_TIMER3,
TELEMETRY_SOURCE_RAS,
TELEMETRY_SOURCE_RSSI_TX,
TELEMETRY_SOURCE_RSSI_RX,
TELEMETRY_SOURCE_A1,
TELEMETRY_SOURCE_A2,
TELEMETRY_SOURCE_A3,
TELEMETRY_SOURCE_A4,
TELEMETRY_SOURCE_ALT,
TELEMETRY_SOURCE_RPM,
TELEMETRY_SOURCE_FUEL,
TELEMETRY_SOURCE_T1,
TELEMETRY_SOURCE_T2,
TELEMETRY_SOURCE_SPEED,
TELEMETRY_SOURCE_DIST,
TELEMETRY_SOURCE_GPS_ALT,
TELEMETRY_SOURCE_CELL,
TELEMETRY_SOURCE_CELLS_SUM,
TELEMETRY_SOURCE_VFAS,
TELEMETRY_SOURCE_CURRENT,
TELEMETRY_SOURCE_CONSUMPTION,
TELEMETRY_SOURCE_POWER,
TELEMETRY_SOURCE_ACCX,
TELEMETRY_SOURCE_ACCY,
TELEMETRY_SOURCE_ACCZ,
TELEMETRY_SOURCE_HDG,
TELEMETRY_SOURCE_VERTICAL_SPEED,
TELEMETRY_SOURCE_ASPEED,
TELEMETRY_SOURCE_DTE,
TELEMETRY_SOURCE_A1_MIN,
TELEMETRY_SOURCE_A2_MIN,
TELEMETRY_SOURCE_A3_MIN,
TELEMETRY_SOURCE_A4_MIN,
TELEMETRY_SOURCE_ALT_MIN,
TELEMETRY_SOURCE_ALT_MAX,
TELEMETRY_SOURCE_RPM_MAX,
TELEMETRY_SOURCE_T1_MAX,
TELEMETRY_SOURCE_T2_MAX,
TELEMETRY_SOURCE_SPEED_MAX,
TELEMETRY_SOURCE_DIST_MAX,
TELEMETRY_SOURCE_ASPEED_MAX,
TELEMETRY_SOURCE_CELL_MIN,
TELEMETRY_SOURCE_CELLS_MIN,
TELEMETRY_SOURCE_VFAS_MIN,
TELEMETRY_SOURCE_CURRENT_MAX,
TELEMETRY_SOURCE_POWER_MAX,
TELEMETRY_SOURCE_ACC,
TELEMETRY_SOURCE_GPS_TIME,
TELEMETRY_SOURCES_STATUS_COUNT = TELEMETRY_SOURCE_GPS_TIME+1,
TELEMETRY_SOURCES_DISPLAY_COUNT = TELEMETRY_SOURCE_POWER_MAX+1,
TELEMETRY_SOURCES_COUNT = TELEMETRY_SOURCE_POWER_MAX+1,
TELEMETRY_SOURCE_RESERVE = -1
};
#define TM_HASTELEMETRY 0x01
#define TM_HASOFFSET 0x02
#define TM_HASWSHH 0x04
enum RawSourceType {
SOURCE_TYPE_NONE,
SOURCE_TYPE_VIRTUAL_INPUT,
SOURCE_TYPE_LUA_OUTPUT,
SOURCE_TYPE_STICK, // and POTS
SOURCE_TYPE_ROTARY_ENCODER,
SOURCE_TYPE_TRIM,
SOURCE_TYPE_MAX,
SOURCE_TYPE_SWITCH,
SOURCE_TYPE_CUSTOM_SWITCH,
SOURCE_TYPE_CYC,
SOURCE_TYPE_PPM,
SOURCE_TYPE_CH,
SOURCE_TYPE_GVAR,
SOURCE_TYPE_SPECIAL,
SOURCE_TYPE_TELEMETRY,
MAX_SOURCE_TYPE
};
class RawSourceRange
{
Q_DECLARE_TR_FUNCTIONS(RawSourceRange)
public:
RawSourceRange():
decimals(0),
min(0.0),
max(0.0),
step(1.0),
offset(0.0)
{
}
float getValue(int value);
int decimals;
double min;
double max;
double step;
double offset;
QString unit;
};
#define RANGE_DELTA_FUNCTION 1
#define RANGE_ABS_FUNCTION 2
class RawSource {
Q_DECLARE_TR_FUNCTIONS(RawSource)
public:
enum SourceGroups {
NoneGroup = 0x001,
SourcesGroup = 0x002,
TrimsGroup = 0x004,
SwitchesGroup = 0x008,
GVarsGroup = 0x010,
TelemGroup = 0x020,
InputsGroup = 0x040,
ScriptsGroup = 0x080,
InputSourceGroups = NoneGroup | SourcesGroup | TrimsGroup | SwitchesGroup | InputsGroup,
AllSourceGroups = InputSourceGroups | GVarsGroup | TelemGroup | ScriptsGroup
};
RawSource():
type(SOURCE_TYPE_NONE),
index(0)
{
}
explicit RawSource(int value):
type(RawSourceType(abs(value)/65536)),
index(value >= 0 ? abs(value)%65536 : -(abs(value)%65536))
{
}
RawSource(RawSourceType type, int index=0):
type(type),
index(index)
{
}
inline const int toValue() const
{
return index >= 0 ? (type * 65536 + index) : -(type * 65536 - index);
}
RawSource convert(RadioDataConversionState & cstate);
QString toString(const ModelData * model = NULL, const GeneralSettings * const generalSettings = NULL, Board::Type board = Board::BOARD_UNKNOWN) const;
RawSourceRange getRange(const ModelData * model, const GeneralSettings & settings, unsigned int flags=0) const;
bool isStick(int * potsIndex = NULL, Board::Type board = Board::BOARD_UNKNOWN) const;
bool isPot(int * potsIndex = NULL, Board::Type board = Board::BOARD_UNKNOWN) const;
bool isSlider(int * sliderIndex = NULL, Board::Type board = Board::BOARD_UNKNOWN) const;
bool isTimeBased(Board::Type board = Board::BOARD_UNKNOWN) const;
bool isAvailable(const ModelData * const model = NULL, const GeneralSettings * const gs = NULL, Board::Type board = Board::BOARD_UNKNOWN) const;
bool operator == ( const RawSource & other) {
return (this->type == other.type) && (this->index == other.index);
}
bool operator != ( const RawSource & other) {
return (this->type != other.type) || (this->index != other.index);
}
RawSourceType type;
int index;
};
#endif // RAWSOURCE_H
+243
View File
@@ -0,0 +1,243 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "rawswitch.h"
#include "eeprominterface.h"
#include "radiodata.h"
#include "radiodataconversionstate.h"
QString RawSwitch::toString(Board::Type board, const GeneralSettings * const generalSettings, const ModelData * const modelData) const
{
if (board == Board::BOARD_UNKNOWN) {
board = getCurrentBoard();
}
static const QString switches9X[] = {
QString("THR"), QString("RUD"), QString("ELE"),
QString("ID0"), QString("ID1"), QString("ID2"),
QString("AIL"), QString("GEA"), QString("TRN")
};
static const QString trimsSwitches[] = {
tr("RudTrim Left"), tr("RudTrim Right"),
tr("EleTrim Down"), tr("EleTrim Up"),
tr("ThrTrim Down"), tr("ThrTrim Up"),
tr("AilTrim Left"), tr("AilTrim Right"),
tr("Trim 5 Down"), tr("Trim 5 Up"),
tr("Trim 6 Down"), tr("Trim 6 Up")
};
static const QString trimsSwitches2[] = {
tr("TrmH Left"), tr("TrmH Right"),
tr("TrmV Down"), tr("TrmV Up")
};
static const QString rotaryEncoders[] = {
tr("REa"), tr("REb")
};
static const QString timerModes[] = {
tr("OFF"), tr("ON"),
tr("THs"), tr("TH%"), tr("THt")
};
const QStringList directionIndicators = QStringList()
<< CPN_STR_SW_INDICATOR_UP
<< CPN_STR_SW_INDICATOR_NEUT
<< CPN_STR_SW_INDICATOR_DN;
if (index < 0) {
return CPN_STR_SW_INDICATOR_REV % RawSwitch(type, -index).toString(board, generalSettings, modelData);
}
else {
QString swName;
div_t qr;
switch(type) {
case SWITCH_TYPE_SWITCH:
if (IS_HORUS_OR_TARANIS(board)) {
qr = div(index-1, 3);
if (generalSettings)
swName = QString(generalSettings->switchName[qr.quot]);
if (swName.isEmpty())
swName = Boards::getSwitchInfo(board, qr.quot).name;
return swName + directionIndicators.at(qr.rem > -1 && qr.rem < directionIndicators.size() ? qr.rem : 1);
}
else {
return CHECK_IN_ARRAY(switches9X, index - 1);
}
case SWITCH_TYPE_VIRTUAL:
if (modelData)
return modelData->logicalSw[index].nameToString(index-1);
else
return LogicalSwitchData().nameToString(index-1);
case SWITCH_TYPE_MULTIPOS_POT:
if (!Boards::getCapability(board, Board::MultiposPotsPositions))
return tr("???");
qr = div(index - 1, Boards::getCapability(board, Board::MultiposPotsPositions));
if (generalSettings && qr.quot < (int)DIM(generalSettings->potConfig))
swName = QString(generalSettings->potName[qr.quot]);
if (swName.isEmpty())
swName = Boards::getAnalogInputName(board, qr.quot + Boards::getCapability(board, Board::Sticks));
return swName + "_" + QString::number(qr.rem + 1);
case SWITCH_TYPE_TRIM:
return (Boards::getCapability(board, Board::NumTrims) == 2 ? CHECK_IN_ARRAY(trimsSwitches2, index-1) : CHECK_IN_ARRAY(trimsSwitches, index-1));
case SWITCH_TYPE_ROTARY_ENCODER:
return CHECK_IN_ARRAY(rotaryEncoders, index-1);
case SWITCH_TYPE_ON:
return tr("ON");
case SWITCH_TYPE_OFF:
return tr("OFF");
case SWITCH_TYPE_ONE:
return tr("One");
case SWITCH_TYPE_FLIGHT_MODE:
if (modelData)
return modelData->flightModeData[index-1].nameToString(index - 1);
else
return FlightModeData().nameToString(index - 1);
case SWITCH_TYPE_NONE:
return tr("----");
case SWITCH_TYPE_TIMER_MODE:
return CHECK_IN_ARRAY(timerModes, index);
case SWITCH_TYPE_SENSOR:
if (modelData)
return modelData->sensorData[index-1].nameToString(index-1);
else
return SensorData().nameToString(index-1);
case SWITCH_TYPE_TELEMETRY:
return tr("Telemetry");
default:
return tr("???");
}
}
}
bool RawSwitch::isAvailable(const ModelData * const model, const GeneralSettings * const gs, Board::Type board) const
{
if (board == Board::BOARD_UNKNOWN)
board = getCurrentBoard();
Boards b(board);
if (type == SWITCH_TYPE_SWITCH && abs(index) > b.getCapability(Board::SwitchPositions))
return false;
if (type == SWITCH_TYPE_TRIM && abs(index) > b.getCapability(Board::NumTrimSwitches))
return false;
if (gs) {
if (type == SWITCH_TYPE_SWITCH && IS_HORUS_OR_TARANIS(board) && !gs->switchPositionAllowedTaranis(abs(index)))
return false;
if (type == SWITCH_TYPE_MULTIPOS_POT) {
int pot = div(abs(index) - 1, b.getCapability(Board::MultiposPotsPositions)).quot;
if (!gs->isPotAvailable(pot) || gs->potConfig[pot] != Board::POT_MULTIPOS_SWITCH)
return false;
}
}
if (model && !model->isAvailable(*this))
return false;
return true;
}
RawSwitch RawSwitch::convert(RadioDataConversionState & cstate)
{
if (!index)
return *this;
cstate.setItemType(tr("SW"), 2);
RadioDataConversionState::EventType evt = RadioDataConversionState::EVT_NONE;
RadioDataConversionState::LogField oldData(index, toString(cstate.fromType, cstate.fromGS(), cstate.fromModel()));
if (type == SWITCH_TYPE_SWITCH) {
int srcIdx = div(abs(index)-1, 3).quot; // raw source index
int delta = 0;
// SWI to SWR don't exist on !X9E board
if (!IS_TARANIS_X9E(cstate.toType) && IS_TARANIS_X9E(cstate.fromType)) {
if (srcIdx > 7) {
index %= 24;
evt = RadioDataConversionState::EVT_CVRT;
}
}
// No SE and SG on X7 board
if (IS_TARANIS_X7(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_HORUS(cstate.fromType))) {
if (srcIdx == 4 || srcIdx == 5) {
delta = 3; // SE to SD & SF to SF
if (srcIdx == 4)
evt = RadioDataConversionState::EVT_CVRT;
}
else if (srcIdx == 6) {
delta = 9; // SG to SD
evt = RadioDataConversionState::EVT_CVRT;
}
else if (srcIdx == 7) {
delta = 6; // SH to SH
}
}
// Compensate for SE and SG on X9/Horus board if converting from X7
else if ((IS_TARANIS_X9(cstate.toType) || IS_HORUS(cstate.toType)) && IS_TARANIS_X7(cstate.fromType)) {
if (srcIdx == 4) {
delta = -3; // SF to SF
}
else if (srcIdx == 5) {
delta = -6; // SH to SH
}
}
if (index < 0) {
delta = -delta; // invert for !switch
}
index -= delta;
} // SWITCH_TYPE_SWITCH
// final validation (we do not pass model to isAvailable() because we don't know what has or hasn't been converted)
if (!isAvailable(NULL, cstate.toGS(), cstate.toType)) {
cstate.setInvalid(oldData);
type = MAX_SWITCH_TYPE; // TODO: better way to flag invalid switches?
}
else if (evt == RadioDataConversionState::EVT_CVRT) {
cstate.setConverted(oldData, RadioDataConversionState::LogField(index, toString(cstate.toType, cstate.toGS(), cstate.toModel())));
}
else if (oldData.id != index) {
// provide info by default if anything changed
cstate.setMoved(oldData, RadioDataConversionState::LogField(index, toString(cstate.toType, cstate.toGS(), cstate.toModel())));
}
return *this;
}
+107
View File
@@ -0,0 +1,107 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef RAWSWITCH_H
#define RAWSWITCH_H
#include "boards.h"
#include "constants.h"
#include <QtCore>
class Firmware;
class ModelData;
class GeneralSettings;
class RadioDataConversionState;
enum RawSwitchType {
SWITCH_TYPE_NONE,
SWITCH_TYPE_SWITCH,
SWITCH_TYPE_VIRTUAL,
SWITCH_TYPE_MULTIPOS_POT,
SWITCH_TYPE_TRIM,
SWITCH_TYPE_ROTARY_ENCODER,
SWITCH_TYPE_ON,
SWITCH_TYPE_OFF,
SWITCH_TYPE_ONE,
SWITCH_TYPE_FLIGHT_MODE,
SWITCH_TYPE_TIMER_MODE,
SWITCH_TYPE_TELEMETRY,
SWITCH_TYPE_SENSOR,
MAX_SWITCH_TYPE
};
class RawSwitch {
Q_DECLARE_TR_FUNCTIONS(RawSwitch)
public:
enum SwitchContext
{
LogicalSwitchesContext = 0x01,
SpecialFunctionsContext = 0x02,
GlobalFunctionsContext = 0x04,
TimersContext = 0x08,
MixesContext = 0x10,
AllModelContexts = SpecialFunctionsContext | LogicalSwitchesContext | TimersContext | MixesContext,
AllSwitchContexts = AllModelContexts | GlobalFunctionsContext
};
RawSwitch():
type(SWITCH_TYPE_NONE),
index(0)
{
}
explicit RawSwitch(int value):
type(RawSwitchType(abs(value)/256)),
index(value >= 0 ? abs(value)%256 : -(abs(value)%256))
{
}
RawSwitch(RawSwitchType type, int index=0):
type(type),
index(index)
{
}
inline const int toValue() const
{
return index >= 0 ? (type * 256 + index) : -(type * 256 - index);
}
RawSwitch convert(RadioDataConversionState & cstate);
QString toString(Board::Type board = Board::BOARD_UNKNOWN, const GeneralSettings * const generalSettings = NULL, const ModelData * const modelData = NULL) const;
bool isAvailable(const ModelData * const model = NULL, const GeneralSettings * const gs = NULL, Board::Type board = Board::BOARD_UNKNOWN) const;
bool operator== ( const RawSwitch& other) {
return (this->type == other.type) && (this->index == other.index);
}
bool operator!= ( const RawSwitch& other) {
return (this->type != other.type) || (this->index != other.index);
}
RawSwitchType type;
int index;
};
#endif // RAWSWITCH_H
+92
View File
@@ -0,0 +1,92 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "sensordata.h"
#include "radiodata.h"
void SensorData::updateUnit()
{
if (type == TELEM_TYPE_CALCULATED) {
if (formula == TELEM_FORMULA_CONSUMPTION)
unit = UNIT_MAH;
}
}
QString SensorData::unitString() const
{
switch (unit) {
case UNIT_VOLTS:
return tr("V");
case UNIT_AMPS:
return tr("A");
case UNIT_MILLIAMPS:
return tr("mA");
case UNIT_KTS:
return tr("kts");
case UNIT_METERS_PER_SECOND:
return tr("m/s");
case UNIT_KMH:
return tr("km/h");
case UNIT_MPH:
return tr("mph");
case UNIT_METERS:
return tr("m");
case UNIT_FEET:
return tr("f");
case UNIT_CELSIUS:
return trUtf8("°C");
case UNIT_FAHRENHEIT:
return trUtf8("°F");
case UNIT_PERCENT:
return tr("%");
case UNIT_MAH:
return tr("mAh");
case UNIT_WATTS:
return tr("W");
case UNIT_MILLIWATTS:
return tr("mW");
case UNIT_DB:
return tr("dB");
case UNIT_RPMS:
return tr("rpms");
case UNIT_G:
return tr("g");
case UNIT_DEGREE:
return trUtf8("°");
case UNIT_RADIANS:
return trUtf8("Rad");
case UNIT_HOURS:
return tr("hours");
case UNIT_MINUTES:
return tr("minutes");
case UNIT_SECONDS:
return tr("seconds");
case UNIT_CELLS:
return tr("V");
default:
return "";
}
}
QString SensorData::nameToString(int index) const
{
return RadioData::getElementName(tr("TELE"), index + 1, label);
}
+150
View File
@@ -0,0 +1,150 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef SENSORDATA_H
#define SENSORDATA_H
#include <QtCore>
#define CPN_MAX_SENSORS 32
class SensorData {
Q_DECLARE_TR_FUNCTIONS(SensorData)
public:
enum
{
TELEM_TYPE_CUSTOM,
TELEM_TYPE_CALCULATED
};
enum
{
TELEM_FORMULA_ADD,
TELEM_FORMULA_AVERAGE,
TELEM_FORMULA_MIN,
TELEM_FORMULA_MAX,
TELEM_FORMULA_MULTIPLY,
TELEM_FORMULA_TOTALIZE,
TELEM_FORMULA_CELL,
TELEM_FORMULA_CONSUMPTION,
TELEM_FORMULA_DIST,
TELEM_FORMULA_LAST = TELEM_FORMULA_DIST
};
enum {
TELEM_CELL_INDEX_LOWEST,
TELEM_CELL_INDEX_1,
TELEM_CELL_INDEX_2,
TELEM_CELL_INDEX_3,
TELEM_CELL_INDEX_4,
TELEM_CELL_INDEX_5,
TELEM_CELL_INDEX_6,
TELEM_CELL_INDEX_HIGHEST,
TELEM_CELL_INDEX_DELTA,
};
enum
{
UNIT_RAW,
UNIT_VOLTS,
UNIT_AMPS,
UNIT_MILLIAMPS,
UNIT_KTS,
UNIT_METERS_PER_SECOND,
UNIT_FEET_PER_SECOND,
UNIT_KMH,
UNIT_MPH,
UNIT_METERS,
UNIT_FEET,
UNIT_CELSIUS,
UNIT_FAHRENHEIT,
UNIT_PERCENT,
UNIT_MAH,
UNIT_WATTS,
UNIT_MILLIWATTS,
UNIT_DB,
UNIT_RPMS,
UNIT_G,
UNIT_DEGREE,
UNIT_RADIANS,
UNIT_MILLILITERS,
UNIT_FLOZ,
UNIT_HOURS,
UNIT_MINUTES,
UNIT_SECONDS,
// FrSky format used for these fields, could be another format in the future
UNIT_FIRST_VIRTUAL,
UNIT_CELLS = UNIT_FIRST_VIRTUAL,
UNIT_DATETIME,
UNIT_GPS,
UNIT_GPS_LONGITUDE,
UNIT_GPS_LATITUDE,
UNIT_GPS_LONGITUDE_EW,
UNIT_GPS_LATITUDE_NS,
UNIT_DATETIME_YEAR,
UNIT_DATETIME_DAY_MONTH,
UNIT_DATETIME_HOUR_MIN,
UNIT_DATETIME_SEC
};
SensorData() { clear(); }
unsigned int type; // custom / formula
unsigned int id;
unsigned int subid;
unsigned int instance;
unsigned int persistentValue;
unsigned int formula;
char label[4+1];
unsigned int unit;
unsigned int prec;
bool autoOffset;
bool filter;
bool logs;
bool persistent;
bool onlyPositive;
// for custom sensors
unsigned int ratio;
int offset;
// for consumption
unsigned int amps;
// for cell
unsigned int source;
unsigned int index;
// for calculations
int sources[4];
// for GPS dist
unsigned int gps;
unsigned int alt;
bool isAvailable() const { return strlen(label) > 0; }
void updateUnit();
QString unitString() const;
QString nameToString(int index) const;
void clear() { memset(this, 0, sizeof(SensorData)); }
};
#endif // SENSORDATA_H
+74
View File
@@ -0,0 +1,74 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "telem_data.h"
#include "eeprominterface.h" // for getCurrentBoard()
float FrSkyChannelData::getRatio() const
{
if (type==0 || type==1 || type==2)
return float(ratio << multiplier) / 10.0;
else
return ratio << multiplier;
}
RawSourceRange FrSkyChannelData::getRange() const
{
RawSourceRange result;
float ratio = getRatio();
if (type==0 || type==1 || type==2)
result.decimals = 2;
else
result.decimals = 0;
result.step = ratio / 255;
result.min = offset * result.step;
result.max = ratio + result.min;
result.unit = tr("V");
return result;
}
void FrSkyScreenData::clear()
{
memset(reinterpret_cast<void *>(this), 0, sizeof(FrSkyScreenData));
if (!IS_ARM(getCurrentBoard())) {
type = TELEMETRY_SCREEN_NUMBERS;
}
}
void FrSkyData::clear()
{
usrProto = 0;
voltsSource = 0;
altitudeSource = 0;
currentSource = 0;
varioMin = 0;
varioCenterMin = 0; // if increment in 0.2m/s = 3.0m/s max
varioCenterMax = 0;
varioMax = 0;
mAhPersistent = 0;
storedMah = 0;
fasOffset = 0;
for (int i=0; i<4; i++)
screens[i].clear();
varioSource = 2/*VARIO*/;
blades = 2;
}
+176
View File
@@ -0,0 +1,176 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef TELEMETRYDATA_H
#define TELEMETRYDATA_H
#include "rawsource.h"
#include <QtCore>
class FrSkyAlarmData {
Q_DECLARE_TR_FUNCTIONS(FrSkyAlarmData)
public:
FrSkyAlarmData() { clear(); }
unsigned int level; // 0=none, 1=Yellow, 2=Orange, 3=Red
unsigned int greater; // 0=LT(<), 1=GT(>)
unsigned int value; // 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc.
void clear() { memset(this, 0, sizeof(FrSkyAlarmData)); }
static QString alarmLevelName(int alarm)
{
switch (alarm) {
case 1:
return tr("Yellow");
case 2:
return tr("Orange");
case 3:
return tr("Red");
default:
return "----";
}
}
};
class FrSkyChannelData {
Q_DECLARE_TR_FUNCTIONS(FrSkyChannelData)
public:
FrSkyChannelData() { clear(); }
unsigned int ratio; // 0.0 means not used, 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc.
unsigned int type; // future use: 0=volts, 1=ml...
int offset;
unsigned int multiplier;
FrSkyAlarmData alarms[2];
float getRatio() const;
RawSourceRange getRange() const;
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(FrSkyChannelData)); }
static QString unitString(int units)
{
switch(units) {
case 1:
return QCoreApplication::translate("FrSkyChannelData", "---");
default:
return QCoreApplication::translate("FrSkyChannelData", "V");
}
}
};
struct FrSkyBarData {
RawSource source;
int barMin; // minimum for bar display
int barMax; // ditto for max display (would usually = ratio)
};
struct FrSkyLineData {
RawSource source[3];
};
struct TelemetryScriptData {
char filename[8+1];
};
enum TelemetryScreenEnum {
TELEMETRY_SCREEN_NONE,
TELEMETRY_SCREEN_NUMBERS,
TELEMETRY_SCREEN_BARS,
TELEMETRY_SCREEN_SCRIPT
};
class FrSkyScreenData {
public:
FrSkyScreenData() { clear(); }
typedef struct {
FrSkyBarData bars[4];
FrSkyLineData lines[4];
TelemetryScriptData script;
} FrSkyScreenBody;
unsigned int type;
FrSkyScreenBody body;
void clear();
};
enum TelemetryVarioSources {
TELEMETRY_VARIO_SOURCE_ALTI,
TELEMETRY_VARIO_SOURCE_ALTI_PLUS,
TELEMETRY_VARIO_SOURCE_VSPEED,
TELEMETRY_VARIO_SOURCE_A1,
TELEMETRY_VARIO_SOURCE_A2,
TELEMETRY_VARIO_SOURCE_DTE,
};
enum TelemetryVoltsSources {
TELEMETRY_VOLTS_SOURCE_A1,
TELEMETRY_VOLTS_SOURCE_A2,
TELEMETRY_VOLTS_SOURCE_A3,
TELEMETRY_VOLTS_SOURCE_A4,
TELEMETRY_VOLTS_SOURCE_FAS,
TELEMETRY_VOLTS_SOURCE_CELLS
};
enum TelemetryCurrentSources {
TELEMETRY_CURRENT_SOURCE_NONE,
TELEMETRY_CURRENT_SOURCE_A1,
TELEMETRY_CURRENT_SOURCE_A2,
TELEMETRY_CURRENT_SOURCE_A3,
TELEMETRY_CURRENT_SOURCE_A4,
TELEMETRY_CURRENT_SOURCE_FAS
};
class FrSkyData {
public:
FrSkyData() { clear(); }
FrSkyChannelData channels[4];
unsigned int usrProto;
int blades;
unsigned int voltsSource;
unsigned int altitudeSource;
unsigned int currentSource;
FrSkyScreenData screens[4];
unsigned int varioSource;
bool varioCenterSilent;
int varioMin;
int varioCenterMin; // if increment in 0.2m/s = 3.0m/s max
int varioCenterMax;
int varioMax;
bool mAhPersistent;
unsigned int storedMah;
int fasOffset;
bool ignoreSensorIds;
void clear();
};
class MavlinkData {
public:
MavlinkData() { clear();}
unsigned int rc_rssi_scale;
unsigned int pc_rssi_en;
void clear() { memset(this, 0, sizeof(MavlinkData)); }
};
#endif // TELEMETRYDATA_H
+8 -8
View File
@@ -118,7 +118,7 @@ int FlashEEpromDialog::getEEpromVersion(const QString & filename)
result = radioData->generalSettings.version;
}
else {
QMessageBox::warning(this, tr("Error"), storage.error());
QMessageBox::warning(this, CPN_STR_TTL_ERROR, storage.error());
}
return result;
}
@@ -163,7 +163,7 @@ bool FlashEEpromDialog::patchCalibration()
return true;
}
else {
QMessageBox::critical(this, tr("Warning"), tr("Wrong radio calibration data in profile, Settings not patched"));
QMessageBox::critical(this, CPN_STR_TTL_WARNING, tr("Wrong radio calibration data in profile, Settings not patched"));
return false;
}
}
@@ -208,7 +208,7 @@ bool FlashEEpromDialog::patchHardwareSettings()
return true;
}
else {
QMessageBox::critical(this, tr("Warning"), tr("Wrong radio setting data in profile, Settings not patched"));
QMessageBox::critical(this, CPN_STR_TTL_WARNING, tr("Wrong radio setting data in profile, Settings not patched"));
return false;
}
}
@@ -233,13 +233,13 @@ void FlashEEpromDialog::on_burnButton_clicked()
return;
}
if (!file.open(QIODevice::WriteOnly)) {
QMessageBox::warning(this, tr("Error"), tr("Cannot write file %1:\n%2.").arg(filename).arg(file.errorString()));
QMessageBox::warning(this, CPN_STR_TTL_ERROR, tr("Cannot write file %1:\n%2.").arg(filename).arg(file.errorString()));
return;
}
QTextStream outputStream(&file);
long result = file.write((char*)eeprom, eeprom_size);
if (result != eeprom_size) {
QMessageBox::warning(this, tr("Error"), tr("Error writing file %1:\n%2.").arg(filename).arg(file.errorString()));
QMessageBox::warning(this, CPN_STR_TTL_ERROR, tr("Error writing file %1:\n%2.").arg(filename).arg(file.errorString()));
return;
}
}
@@ -277,16 +277,16 @@ void FlashEEpromDialog::on_burnButton_clicked()
if (convertEEprom(filename, compatEEprom, firmwareFilename)) {
int compatVersion = getEEpromVersion(compatEEprom);
if ((compatVersion / 100) != (eepromVersion / 100)) {
QMessageBox::warning(this, tr("Warning"), tr("The radio firmware belongs to another product family, check file and preferences!"));
QMessageBox::warning(this, CPN_STR_TTL_WARNING, tr("The radio firmware belongs to another product family, check file and preferences!"));
return;
}
else if (compatVersion < eepromVersion) {
QMessageBox::warning(this, tr("Warning"), tr("The radio firmware is outdated, please upgrade!"));
QMessageBox::warning(this, CPN_STR_TTL_WARNING, tr("The radio firmware is outdated, please upgrade!"));
return;
}
filename = compatEEprom;
}
else if (QMessageBox::question(this, "Error", tr("Cannot check Models and Settings compatibility! Continue anyway?"), QMessageBox::Yes|QMessageBox::No) == QMessageBox::No) {
else if (QMessageBox::question(this, CPN_STR_TTL_ERROR, tr("Cannot check Models and Settings compatibility! Continue anyway?"), QMessageBox::Yes|QMessageBox::No) == QMessageBox::No) {
return;
}
qunlink(firmwareFilename);
+10 -10
View File
@@ -142,7 +142,7 @@ void FlashFirmwareDialog::on_firmwareLoad_clicked()
if (!fileName.isEmpty()) {
fwName = fileName;
if (!fwName.isEmpty() && !fwName.endsWith(".dfu") && !FirmwareInterface(fwName).isValid()) {
QMessageBox::warning(this, tr("Warning"), tr("%1 may not be a valid firmware file").arg(fwName));
QMessageBox::warning(this, CPN_STR_TTL_WARNING, tr("%1 may not be a valid firmware file").arg(fwName));
}
updateUI();
}
@@ -152,10 +152,10 @@ void FlashFirmwareDialog::on_useFirmwareSplash_clicked()
{
FirmwareInterface firmware(fwName);
if (!firmware.isValid()) {
QMessageBox::warning(this, tr("Error"), tr( "The firmware file is not valid." ));
QMessageBox::warning(this, CPN_STR_TTL_ERROR, tr( "The firmware file is not valid." ));
}
else if (!firmware.hasSplash()) {
QMessageBox::warning(this, tr("Error"), tr( "There is no start screen image in the firmware file." ));
QMessageBox::warning(this, CPN_STR_TTL_ERROR, tr( "There is no start screen image in the firmware file." ));
}
else {
imageSource = FIRMWARE;
@@ -169,7 +169,7 @@ void FlashFirmwareDialog::on_useProfileSplash_clicked()
if (!fileName.isEmpty()) {
QImage image(fileName);
if (image.isNull()) {
QMessageBox::critical(this, tr("Error"), tr("Profile image %1 is invalid.").arg(fileName));
QMessageBox::critical(this, CPN_STR_TTL_ERROR, tr("Profile image %1 is invalid.").arg(fileName));
}
else {
imageSource = PROFILE;
@@ -189,12 +189,12 @@ void FlashFirmwareDialog::on_useExternalSplash_clicked()
g.imagesDir( QFileInfo(fileName).dir().absolutePath() );
QImage image(fileName);
if (image.isNull()) {
QMessageBox::critical(this, tr("Error"), tr("Image could not be loaded from %1").arg(fileName));
QMessageBox::critical(this, CPN_STR_TTL_ERROR, tr("Image could not be loaded from %1").arg(fileName));
}
else{
imageSource = EXTERNAL;
imageFile = fileName;
}
}
}
updateUI();
}
@@ -207,7 +207,7 @@ void FlashFirmwareDialog::on_useLibrarySplash_clicked()
if (!fileName.isEmpty()) {
QImage image(fileName);
if (image.isNull()) {
QMessageBox::critical(this, tr("Error"), tr("The library image could not be loaded"));
QMessageBox::critical(this, CPN_STR_TTL_ERROR, tr("The library image could not be loaded"));
}
else {
imageSource = LIBRARY;
@@ -234,7 +234,7 @@ void FlashFirmwareDialog::on_burnButton_clicked()
image = pixmap->toImage().scaled(ui->splash->width(), ui->splash->height());
}
if (image.isNull()) {
QMessageBox::critical(this, tr("Warning"), tr("Splash image not found"));
QMessageBox::critical(this, CPN_STR_TTL_WARNING, tr("Splash image not found"));
return;
}
// write the customized firmware
@@ -247,7 +247,7 @@ void FlashFirmwareDialog::on_burnButton_clicked()
FirmwareInterface firmware(fwName);
firmware.setSplash(image);
if (firmware.save(tempFile) <= 0) {
QMessageBox::critical(this, tr("Warning"), tr("Cannot save customized firmware"));
QMessageBox::critical(this, CPN_STR_TTL_WARNING, tr("Cannot save customized firmware"));
return;
}
startFlash(tempFile);
@@ -304,7 +304,7 @@ void FlashFirmwareDialog::startFlash(const QString &filename)
backupPath = g.profile[g.id()].pBackupDir();
if (backupPath.isEmpty()) {
backupPath=g.backupDir();
}
}
backupFilename = backupPath + "/backup-" + QDateTime().currentDateTime().toString("yyyy-MM-dd-HHmmss") + ".bin";
result = readEeprom(backupFilename, progressDialog.progress());
sleep(2);
+14 -16
View File
@@ -24,12 +24,6 @@
#include "helpers.h"
#include "appdata.h"
const char * const OPENTX_SDCARD_DOWNLOAD_URL[] = {
"https://downloads.open-tx.org/2.2/release/sdcard/",
"https://downloads.open-tx.org/2.2/rc/sdcard/",
"https://downloads.open-tx.org/2.2/nightlies/sdcard/"
};
FirmwarePreferencesDialog::FirmwarePreferencesDialog(QWidget * parent) :
QDialog(parent),
ui(new Ui::FirmwarePreferencesDialog)
@@ -37,6 +31,9 @@ FirmwarePreferencesDialog::FirmwarePreferencesDialog(QWidget * parent) :
ui->setupUi(this);
setWindowIcon(CompanionIcon("fwpreferences.png"));
initSettings();
MainWindow * mw = qobject_cast<MainWindow *>(this->parent());
if (mw)
connect(mw, &MainWindow::firmwareDownloadCompleted, this, &FirmwarePreferencesDialog::initSettings);
}
FirmwarePreferencesDialog::~FirmwarePreferencesDialog()
@@ -46,34 +43,35 @@ FirmwarePreferencesDialog::~FirmwarePreferencesDialog()
void FirmwarePreferencesDialog::initSettings()
{
ui->fwTypeLbl->setText(g.profile[g.id()].fwType());
int version = g.fwRev.get(g.profile[g.id()].fwType());
if (version > 0) {
ui->fwTypeLbl->setText(g.currentProfile().fwType());
int version = g.fwRev.get(g.currentProfile().fwType());
if (version > 0)
ui->lastRevisionLbl->setText(index2version(version));
}
else
ui->lastRevisionLbl->setText(tr("Unknown"));
}
void FirmwarePreferencesDialog::on_checkFWUpdates_clicked()
{
MainWindow * mw = qobject_cast<MainWindow *>(this->parent());
mw->checkForFirmwareUpdate();
initSettings();
if (mw)
mw->checkForFirmwareUpdate();
}
void FirmwarePreferencesDialog::on_fw_dnld_clicked()
{
MainWindow * mw = qobject_cast<MainWindow *>(this->parent());
mw->dowloadLastFirmwareUpdate();
initSettings();
if (mw)
mw->dowloadLastFirmwareUpdate();
}
void FirmwarePreferencesDialog::on_sd_dnld_clicked()
{
QString url = OPENTX_SDCARD_DOWNLOAD_URL[g.boundedOpenTxBranch()];
QString url = g.openTxCurrentDownloadBranchUrl() % QStringLiteral("sdcard/");
QString fwType = g.profile[g.id()].fwType();
QStringList list = fwType.split("-");
QString firmware = QString("%1-%2").arg(list[0]).arg(list[1]);
if (g.boundedOpenTxBranch() != BRANCH_NIGHTLY_UNSTABLE) {
if (g.boundedOpenTxBranch() != AppData::BRANCH_NIGHTLY_UNSTABLE) {
url.append(QString("%1/").arg(firmware));
}
QDesktopServices::openUrl(url);
+1 -2
View File
@@ -28,5 +28,4 @@ qt5_wrap_ui(generaledit_SRCS ${generaledit_UIS})
qt5_wrap_cpp(generaledit_SRCS ${generaledit_HDRS})
add_library(generaledit ${generaledit_SRCS})
qt5_use_modules(generaledit Widgets Xml Multimedia)
target_link_libraries(generaledit PRIVATE ${CPN_COMMON_LIB})
target_link_libraries(generaledit PRIVATE ${CPN_COMMON_LIB} Qt5::Multimedia)
+1 -1
View File
@@ -41,7 +41,7 @@ CalibrationPanel::CalibrationPanel(QWidget * parent, GeneralSettings & generalSe
tableWidget->setFrameStyle(QFrame::NoFrame | QFrame::Plain);
tableWidget->setStyleSheet("QTableWidget {background-color: transparent;}");
QStringList headerLabels;
headerLabels << QObject::tr("Negative span") << QObject::tr("Mid value") << QObject::tr("Positive span");
headerLabels << tr("Negative span") << tr("Mid value") << tr("Positive span");
tableWidget->setHorizontalHeaderLabels(headerLabels);
int rows = CPN_MAX_STICKS + getBoardCapability(getCurrentBoard(), Board::Pots) + getBoardCapability(getCurrentBoard(), Board::Sliders) + getBoardCapability(getCurrentBoard(), Board::MouseAnalogs);
+5 -5
View File
@@ -151,7 +151,7 @@ void GeneralEdit::on_calretrieve_PB_clicked()
}
generalSettings.PPM_Multiplier=PPM_Multiplier;
} else {
QMessageBox::critical(this, tr("Warning"), tr("Wrong data in profile, radio calibration was not retrieved"));
QMessageBox::critical(this, CPN_STR_TTL_WARNING, tr("Wrong data in profile, radio calibration was not retrieved"));
}
if (hwtypes.length()==numSwPots) {
QString Byte;
@@ -193,7 +193,7 @@ void GeneralEdit::on_calretrieve_PB_clicked()
}
}
} else {
QMessageBox::critical(this, tr("Warning"), tr("Wrong data in profile, Switch/pot config not retrieved"));
QMessageBox::critical(this, CPN_STR_TTL_WARNING, tr("Wrong data in profile, Switch/pot config not retrieved"));
}
if ((DisplaySet.length()==6) && (BeeperSet.length()==4) && (HapticSet.length()==6) && (SpeakerSet.length()==6)) {
generalSettings.stickMode=GSStickMode;
@@ -234,7 +234,7 @@ void GeneralEdit::on_calretrieve_PB_clicked()
}
}
else {
QMessageBox::critical(this, tr("Warning"), tr("Wrong data in profile, hw related parameters were not retrieved"));
QMessageBox::critical(this, CPN_STR_TTL_WARNING, tr("Wrong data in profile, hw related parameters were not retrieved"));
}
}
@@ -256,7 +256,7 @@ void GeneralEdit::on_calstore_PB_clicked()
QString hwtypes=g.profile[profile_id].controlTypes();
QString controlNames=g.profile[profile_id].controlNames();
if (!(calib.isEmpty())) {
int ret = QMessageBox::question(this, "Companion",
int ret = QMessageBox::question(this, CPN_STR_APP_NAME,
tr("Do you want to store calibration in %1 profile<br>overwriting existing calibration?").arg(name) ,
QMessageBox::Yes | QMessageBox::No);
if (ret == QMessageBox::No) {
@@ -311,6 +311,6 @@ void GeneralEdit::on_calstore_PB_clicked()
QDateTime dateTime = QDateTime::currentDateTime();
g.profile[profile_id].timeStamp(dateTime.toString("yyyy-MM-dd hh:mm"));
QMessageBox::information(this, "Companion", tr("Calibration and HW parameters saved."));
QMessageBox::information(this, CPN_STR_APP_NAME, tr("Calibration and HW parameters saved."));
}
}
+7 -7
View File
@@ -182,7 +182,7 @@ ui(new Ui::GeneralSetup)
ui->BLBright_SB->setDisabled(true);
ui->label_BLBright->hide();
}
if (!IS_HORUS(firmware->getBoard())) {
ui->OFFBright_SB->hide();
ui->OFFBright_SB->setDisabled(true);
@@ -311,7 +311,7 @@ GeneralSetupPanel::~GeneralSetupPanel()
void GeneralSetupPanel::populateBacklightCB()
{
QComboBox * b = ui->backlightswCB;
QString strings[] = { QObject::tr("OFF"), QObject::tr("Keys"), QObject::tr("Sticks"), QObject::tr("Keys + Sticks"), QObject::tr("ON"), NULL };
QString strings[] = { tr("OFF"), tr("Keys"), tr("Sticks"), tr("Keys + Sticks"), tr("ON"), NULL };
b->clear();
for (int i=0; !strings[i].isNull(); i++) {
@@ -325,8 +325,8 @@ void GeneralSetupPanel::populateBacklightCB()
void GeneralSetupPanel::populateVoiceLangCB()
{
QComboBox * b = ui->voiceLang_CB;
QString strings[] = { QObject::tr("English"), QObject::tr("Dutch"), QObject::tr("French"), QObject::tr("Italian"), QObject::tr("German"), QObject::tr("Czech"), QObject::tr("Slovak"), QObject::tr("Spanish"), QObject::tr("Polish"), QObject::tr("Portuguese"), QObject::tr("Swedish"), QObject::tr("Hungarian"), NULL};
QString langcode[] = { "en", "nl","fr", "it", "de", "cz", "sk", "es", "pl", "pt", "se", "hu", NULL};
QString strings[] = { tr("English"), tr("Dutch"), tr("French"), tr("Italian"), tr("German"), tr("Czech"), tr("Slovak"), tr("Spanish"), tr("Polish"), tr("Portuguese"), tr("Russian"), tr("Swedish"), tr("Hungarian"), NULL};
QString langcode[] = { "en", "nl","fr", "it", "de", "cz", "sk", "es", "pl", "pt", "ru", "se", "hu", NULL};
b->clear();
for (int i=0; strings[i]!=NULL; i++) {
@@ -389,7 +389,7 @@ void GeneralSetupPanel::updateVarioPitchRange()
void GeneralSetupPanel::populateRotEncCB(int reCount)
{
QString strings[] = { QObject::tr("No"), QObject::tr("RotEnc A"), QObject::tr("Rot Enc B"), QObject::tr("Rot Enc C"), QObject::tr("Rot Enc D"), QObject::tr("Rot Enc E")};
QString strings[] = { tr("No"), tr("RotEnc A"), tr("Rot Enc B"), tr("Rot Enc C"), tr("Rot Enc D"), tr("Rot Enc E")};
QComboBox * b = ui->re_CB;
b->clear();
@@ -429,8 +429,8 @@ void GeneralSetupPanel::setValues()
void GeneralSetupPanel::on_faimode_CB_stateChanged(int)
{
if (ui->faimode_CB->isChecked()) {
int ret = QMessageBox::question(this, "Companion",
tr("If you enable FAI, you loose the vario, the play functions, the telemetry screen.\nThis function cannot be disabled by the radio.\nAre you sure ?") ,
int ret = QMessageBox::question(this, CPN_STR_APP_NAME,
tr("If you enable FAI, only RSSI and RxBt sensors will keep working.\nThis function cannot be disabled by the radio.\nAre you sure ?") ,
QMessageBox::Yes | QMessageBox::No);
if (ret==QMessageBox::Yes) {
generalSettings.fai = true;
+1 -1
View File
@@ -577,7 +577,7 @@
<item row="15" column="1">
<widget class="QCheckBox" name="faimode_CB">
<property name="toolTip">
<string>If you enable FAI, you loose the vario, the play functions, the telemetry screen. This function cannot be disabled by the radio.</string>
<string>If you enable FAI, only RSSI and RxBt sensors will keep working. This function cannot be disabled by the radio.</string>
</property>
<property name="text">
<string/>
+11 -9
View File
@@ -143,7 +143,7 @@ HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings
setupSwitchType(16, ui->sqLabel, ui->sqName, ui->sqType);
setupSwitchType(17, ui->srLabel, ui->srName, ui->srType);
if (IS_TARANIS(board) && !IS_TARANIS_X7(board)) {
if (IS_TARANIS(board) && !IS_TARANIS_SMALL(board)) {
ui->serialPortMode->setCurrentIndex(generalSettings.hw_uartMode);
}
else {
@@ -157,8 +157,16 @@ HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings
ui->txCurrentCalibrationLabel->hide();
}
if (IS_TARANIS_X9E(board) || IS_HORUS(board)) {
ui->bluetoothEnable->setChecked(generalSettings.bluetoothEnable);
if (IS_TARANIS_X7(board) || IS_TARANIS_XLITE(board)|| IS_TARANIS_X9E(board) || IS_HORUS(board)) {
ui->bluetoothMode->addItem(tr("OFF"), 0);
if (IS_TARANIS_X9E(board)) {
ui->bluetoothMode->addItem(tr("Enabled"), 1);
}
else {
ui->bluetoothMode->addItem(tr("Telemetry"), 1);
ui->bluetoothMode->addItem(tr("Trainer"), 2);
}
ui->bluetoothMode->setField(generalSettings.bluetoothMode, this);
ui->bluetoothName->setField(generalSettings.bluetoothName, 10, this);
}
else {
@@ -238,12 +246,6 @@ void HardwarePanel::on_txCurrentCalibration_editingFinished()
}
}
void HardwarePanel::on_bluetoothEnable_stateChanged(int)
{
generalSettings.bluetoothEnable = ui->bluetoothEnable->isChecked();
emit modified();
}
void HardwarePanel::setValues()
{
ui->txVoltageCalibration->setValue((double)generalSettings.txVoltageCalibration/10);
-1
View File
@@ -48,7 +48,6 @@ class HardwarePanel : public GeneralPanel
void on_txCurrentCalibration_editingFinished();
void on_txVoltageCalibration_editingFinished();
void on_bluetoothEnable_stateChanged(int);
void on_filterEnable_stateChanged();
void on_serialPortMode_currentIndexChanged(int index);
+3 -93
View File
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>470</width>
<height>1095</height>
<height>1419</height>
</rect>
</property>
<property name="sizePolicy">
@@ -149,15 +149,6 @@
<property name="statusTip">
<string/>
</property>
<property name="whatsThis">
<string>Beeper volume
0 - Quiet. No beeps at all.
1 - No Keys. Normal beeps but menu keys do not beep.
2 - Normal.
3 - Loud.
4 - Extra loud.</string>
</property>
</widget>
</item>
<item row="13" column="2">
@@ -168,15 +159,6 @@
<property name="statusTip">
<string/>
</property>
<property name="whatsThis">
<string>Beeper volume
0 - Quiet. No beeps at all.
1 - No Keys. Normal beeps but menu keys do not beep.
2 - Normal.
3 - Loud.
4 - Extra loud.</string>
</property>
</widget>
</item>
<item row="34" column="1">
@@ -899,15 +881,6 @@
<property name="statusTip">
<string/>
</property>
<property name="whatsThis">
<string>Beeper volume
0 - Quiet. No beeps at all.
1 - No Keys. Normal beeps but menu keys do not beep.
2 - Normal.
3 - Loud.
4 - Extra loud.</string>
</property>
</widget>
</item>
<item row="10" column="2">
@@ -918,15 +891,6 @@
<property name="statusTip">
<string/>
</property>
<property name="whatsThis">
<string>Beeper volume
0 - Quiet. No beeps at all.
1 - No Keys. Normal beeps but menu keys do not beep.
2 - Normal.
3 - Loud.
4 - Extra loud.</string>
</property>
</widget>
</item>
<item row="9" column="2">
@@ -937,15 +901,6 @@
<property name="statusTip">
<string/>
</property>
<property name="whatsThis">
<string>Beeper volume
0 - Quiet. No beeps at all.
1 - No Keys. Normal beeps but menu keys do not beep.
2 - Normal.
3 - Loud.
4 - Extra loud.</string>
</property>
</widget>
</item>
<item row="8" column="2">
@@ -956,15 +911,6 @@
<property name="statusTip">
<string/>
</property>
<property name="whatsThis">
<string>Beeper volume
0 - Quiet. No beeps at all.
1 - No Keys. Normal beeps but menu keys do not beep.
2 - Normal.
3 - Loud.
4 - Extra loud.</string>
</property>
</widget>
</item>
<item row="7" column="2">
@@ -975,15 +921,6 @@
<property name="statusTip">
<string/>
</property>
<property name="whatsThis">
<string>Beeper volume
0 - Quiet. No beeps at all.
1 - No Keys. Normal beeps but menu keys do not beep.
2 - Normal.
3 - Loud.
4 - Extra loud.</string>
</property>
</widget>
</item>
<item row="6" column="2">
@@ -994,15 +931,6 @@
<property name="statusTip">
<string/>
</property>
<property name="whatsThis">
<string>Beeper volume
0 - Quiet. No beeps at all.
1 - No Keys. Normal beeps but menu keys do not beep.
2 - Normal.
3 - Loud.
4 - Extra loud.</string>
</property>
</widget>
</item>
<item row="5" column="2">
@@ -1013,15 +941,6 @@
<property name="statusTip">
<string/>
</property>
<property name="whatsThis">
<string>Beeper volume
0 - Quiet. No beeps at all.
1 - No Keys. Normal beeps but menu keys do not beep.
2 - Normal.
3 - Loud.
4 - Extra loud.</string>
</property>
</widget>
</item>
<item row="4" column="2">
@@ -1032,15 +951,6 @@
<property name="statusTip">
<string/>
</property>
<property name="whatsThis">
<string>Beeper volume
0 - Quiet. No beeps at all.
1 - No Keys. Normal beeps but menu keys do not beep.
2 - Normal.
3 - Loud.
4 - Extra loud.</string>
</property>
</widget>
</item>
<item row="32" column="0">
@@ -1099,8 +1009,8 @@
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="bluetoothEnable">
<property name="text">
<widget class="AutoComboBox" name="bluetoothMode">
<property name="text" stdset="0">
<string/>
</property>
</widget>
+107 -261
View File
@@ -29,9 +29,11 @@
#include "appdata.h"
#include "macros.h"
#include "helpers.h"
#include "simulatorinterface.h"
#include "simulatormainwindow.h"
#include "storage/sdcard.h"
#include <QFileDialog>
#include <QLabel>
#include <QMessageBox>
@@ -74,6 +76,42 @@ const QColor colors[CPN_MAX_CURVES] = {
QColor(255,127,0),
};
/*
* CompanionIcon
*/
static QString iconThemeFolder(int theme_set)
{
switch(theme_set) {
case 0:
return QStringLiteral("classic");
case 2:
return QStringLiteral("monowhite");
case 3:
return QStringLiteral("monochrome");
case 4:
return QStringLiteral("monoblue");
default:
return QStringLiteral("yerico");
}
}
CompanionIcon::CompanionIcon(const QString &baseimage)
{
addImage(baseimage);
}
void CompanionIcon::addImage(const QString & baseimage, Mode mode, State state)
{
const QString theme = iconThemeFolder(g.theme());
addFile(":/themes/"+theme+"/16/"+baseimage, QSize(16,16), mode, state);
addFile(":/themes/"+theme+"/24/"+baseimage, QSize(24,24), mode, state);
addFile(":/themes/"+theme+"/32/"+baseimage, QSize(32,32), mode, state);
addFile(":/themes/"+theme+"/48/"+baseimage, QSize(48,48), mode, state);
}
/*
* GVarGroup
*/
@@ -86,6 +124,9 @@ GVarGroup::GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBo
dsb(dynamic_cast<QDoubleSpinBox *>(weightSB)),
weightCB(weightCB),
weight(weight),
deflt(deflt),
mini(mini),
maxi(maxi),
step(step),
lock(true)
{
@@ -101,31 +142,7 @@ GVarGroup::GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBo
}
}
int val;
if (weight>maxi || weight<mini) {
val = deflt;
weightGV->setChecked(true);
weightSB->hide();
weightCB->show();
}
else {
val = weight;
weightGV->setChecked(false);
weightSB->show();
weightCB->hide();
}
if (sb) {
sb->setMinimum(mini);
sb->setMaximum(maxi);
sb->setValue(val);
}
else {
dsb->setMinimum(mini*step);
dsb->setMaximum(maxi*step);
dsb->setValue(val*step);
}
setWeight(weight);
connect(weightSB, SIGNAL(editingFinished()), this, SLOT(valuesChanged()));
@@ -156,6 +173,43 @@ void GVarGroup::valuesChanged()
}
}
void GVarGroup::setWeight(int val)
{
lock = true;
int tval;
if (val>maxi || val<mini) {
tval = deflt;
weightGV->setChecked(true);
weightSB->hide();
weightCB->setCurrentIndex(weightCB->findData(val));
if (weightCB->currentIndex() == -1)
weightCB->setCurrentIndex(getCurrentFirmware()->getCapability(Gvars));
weightCB->show();
}
else {
tval = val;
weightGV->setChecked(false);
weightSB->show();
weightCB->hide();
}
if (sb) {
sb->setMinimum(mini);
sb->setMaximum(maxi);
sb->setValue(tval);
}
else {
dsb->setMinimum(mini*step);
dsb->setMaximum(maxi*step);
dsb->setValue(tval*step);
}
lock = false;
}
/*
* CurveGroup
*/
@@ -318,6 +372,7 @@ void CurveGroup::valuesChanged()
}
}
/*
* Helpers namespace functions
*/
@@ -363,16 +418,22 @@ QString Helpers::getAdjustmentString(int16_t val, const ModelData * model, bool
return ret;
}
// TODO: Move lookup to GVarData class (w/out combobox)
void Helpers::populateGvarUseCB(QComboBox * b, unsigned int phase)
{
b->addItem(QObject::tr("Own value"));
b->addItem(QCoreApplication::translate("GVarData", "Own value"));
for (int i=0; i<getCurrentFirmware()->getCapability(FlightModes); i++) {
if (i != (int)phase) {
b->addItem(QObject::tr("Flight mode %1 value").arg(i));
b->addItem(QCoreApplication::translate("GVarData", "Flight mode %1 value").arg(i));
}
}
}
static bool caseInsensitiveLessThan(const QString &s1, const QString &s2)
{
return s1.toLower() < s2.toLower();
}
void Helpers::populateFileComboBox(QComboBox * b, const QSet<QString> & set, const QString & current)
{
b->clear();
@@ -404,232 +465,22 @@ void Helpers::getFileComboBoxValue(QComboBox * b, char * dest, int length)
}
}
void Helpers::addRawSourceItems(QStandardItemModel * itemModel, const RawSourceType & type, int count, const GeneralSettings * const generalSettings,
const ModelData * const model, const int start, const QList<int> exclude)
void Helpers::exportAppSettings(QWidget * dlgParent)
{
for (int i = start; i < start + count; i++) {
if (exclude.contains(i))
continue;
static QString lastExpFile = CPN_SETTINGS_INI_PATH.arg(QDateTime::currentDateTime().toString("dd-MMM-yy"));
const QString expFile = QFileDialog::getSaveFileName(dlgParent, QCoreApplication::translate("Companion", "Select or create a file for exported Settings:"), lastExpFile, CPN_STR_APP_SETTINGS_FILTER);
if (expFile.isEmpty())
return;
RawSource src = RawSource(type, i);
if (model) {
if (type == SOURCE_TYPE_VIRTUAL_INPUT && !model->isInputValid(i))
continue;
}
if (generalSettings) {
int genAryIdx = 0;
if (type == SOURCE_TYPE_STICK && ((src.isPot(&genAryIdx) && !generalSettings->isPotAvailable(genAryIdx)) || (src.isSlider(&genAryIdx) && !generalSettings->isSliderAvailable(genAryIdx))))
continue;
}
QStandardItem * modelItem = new QStandardItem(src.toString(model, generalSettings));
modelItem->setData(src.toValue(), Qt::UserRole);
itemModel->appendRow(modelItem);
if (type == SOURCE_TYPE_SWITCH && generalSettings && IS_HORUS_OR_TARANIS(getCurrentBoard()) && !generalSettings->switchSourceAllowedTaranis(i)) {
modelItem->setData(0, Qt::UserRole - 1); // trick to disable an item
}
lastExpFile = expFile;
QString resultMsg;
if (g.exportSettingsToFile(expFile, resultMsg)) {
QMessageBox::information(dlgParent, CPN_STR_APP_NAME, resultMsg);
return;
}
}
QStandardItemModel * Helpers::getRawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const model, unsigned int flags)
{
QStandardItemModel * itemModel = new QStandardItemModel();
Boards board = Boards(getCurrentBoard());
Firmware * fw = getCurrentFirmware();
if (flags & POPULATE_NONE) {
addRawSourceItems(itemModel, SOURCE_TYPE_NONE, 1, generalSettings, model);
}
if (flags & POPULATE_SCRIPT_OUTPUTS) {
for (int i=0; i < getCurrentFirmware()->getCapability(LuaScripts); i++) {
addRawSourceItems(itemModel, SOURCE_TYPE_LUA_OUTPUT, fw->getCapability(LuaOutputsPerScript), generalSettings, model, i * 16);
}
}
if (model && (flags & POPULATE_VIRTUAL_INPUTS)) {
addRawSourceItems(itemModel, SOURCE_TYPE_VIRTUAL_INPUT, fw->getCapability(VirtualInputs), generalSettings, model);
}
if (flags & POPULATE_SOURCES) {
int totalSources = CPN_MAX_STICKS + board.getCapability(Board::Pots) + board.getCapability(Board::Sliders) + board.getCapability(Board::MouseAnalogs);
addRawSourceItems(itemModel, SOURCE_TYPE_STICK, totalSources, generalSettings, model);
addRawSourceItems(itemModel, SOURCE_TYPE_ROTARY_ENCODER, fw->getCapability(RotaryEncoders), generalSettings, model);
}
if (flags & POPULATE_TRIMS) {
addRawSourceItems(itemModel, SOURCE_TYPE_TRIM, board.getCapability(Board::NumTrims), generalSettings, model);
}
if (flags & POPULATE_SOURCES) {
addRawSourceItems(itemModel, SOURCE_TYPE_MAX, 1, generalSettings, model);
}
if (flags & POPULATE_SWITCHES) {
addRawSourceItems(itemModel, SOURCE_TYPE_SWITCH, board.getCapability(Board::Switches), generalSettings, model);
addRawSourceItems(itemModel, SOURCE_TYPE_CUSTOM_SWITCH, fw->getCapability(LogicalSwitches), generalSettings, model);
}
if (flags & POPULATE_SOURCES) {
addRawSourceItems(itemModel, SOURCE_TYPE_CYC, CPN_MAX_CYC, generalSettings, model);
addRawSourceItems(itemModel, SOURCE_TYPE_PPM, fw->getCapability(TrainerInputs), generalSettings, model);
addRawSourceItems(itemModel, SOURCE_TYPE_CH, fw->getCapability(Outputs), generalSettings, model);
}
if (flags & POPULATE_TELEMETRY) {
if (IS_ARM(board.getBoardType())) {
addRawSourceItems(itemModel, SOURCE_TYPE_SPECIAL, 5, generalSettings, model);
if (model) {
QList<int> exclude;
for (int i=0; i < CPN_MAX_SENSORS * 3; ++i) {
//this conditon must be false if we populate Global Functions where model = 0
if (!model->sensorData[div(i, 3).quot].isAvailable())
exclude << i;
}
if (exclude.size() < CPN_MAX_SENSORS * 3)
addRawSourceItems(itemModel, SOURCE_TYPE_TELEMETRY, CPN_MAX_SENSORS * 3, generalSettings, model, 0, exclude);
}
}
else {
QList<int> exclude;
if (!fw->getCapability(RtcTime))
exclude << TELEMETRY_SOURCE_TX_TIME;
if (!fw->getCapability(SportTelemetry))
exclude << TELEMETRY_SOURCE_SWR;
if (!IS_ARM(board.getBoardType()))
exclude << TELEMETRY_SOURCE_TIMER3;
int count = ((flags & POPULATE_TELEMETRYEXT) ? TELEMETRY_SOURCES_STATUS_COUNT : TELEMETRY_SOURCES_COUNT);
addRawSourceItems(itemModel, SOURCE_TYPE_TELEMETRY, count, generalSettings, model, 0, exclude);
}
}
if (flags & POPULATE_GVARS) {
addRawSourceItems(itemModel, SOURCE_TYPE_GVAR, fw->getCapability(Gvars), generalSettings, model);
}
return itemModel;
}
QString image2qstring(QImage image)
{
if (image.isNull())
return "";
QBuffer buffer;
image.save(&buffer, "PNG");
QString ImageStr;
int b=0;
int size=buffer.data().size();
for (int j = 0; j < size; j++) {
b=buffer.data().at(j);
ImageStr += QString("%1").arg(b&0xff, 2, 16, QChar('0'));
}
return ImageStr;
}
int findmult(float value, float base)
{
int vvalue = value*10;
int vbase = base*10;
vvalue--;
int mult = 0;
for (int i=8; i>=0; i--) {
if (vvalue/vbase >= (1<<i)) {
mult = i+1;
break;
}
}
return mult;
}
QString getFrSkyAlarmType(int alarm)
{
switch (alarm) {
case 1:
return QObject::tr("Yellow");
case 2:
return QObject::tr("Orange");
case 3:
return QObject::tr("Red");
default:
return "----";
}
}
QString getFrSkyUnits(int units)
{
switch(units) {
case 1:
return QObject::tr("---");
default:
return "V";
}
}
QString getFrSkyProtocol(int protocol)
{
switch(protocol) {
case 2:
if ((getCurrentFirmware()->getCapability(Telemetry) & TM_HASWSHH))
return QObject::tr("Winged Shadow How High");
else
return QObject::tr("Winged Shadow How High (not supported)");
case 1:
return QObject::tr("FrSky Sensor Hub");
default:
return QObject::tr("None");
}
}
QString getFrSkyMeasure(int units)
{
switch(units) {
case 1:
return QObject::tr("Imperial");
default:
return QObject::tr("Metric");
}
}
QString getFrSkySrc(int index)
{
return RawSource(SOURCE_TYPE_TELEMETRY, index-1).toString();
}
QString getTheme()
{
int theme_set = g.theme();
QString Theme;
switch(theme_set) {
case 0:
Theme="classic";
break;
case 2:
Theme="monowhite";
break;
case 3:
Theme="monochrome";
break;
case 4:
Theme="monoblue";
break;
default:
Theme="yerico";
break;
}
return Theme;
}
CompanionIcon::CompanionIcon(const QString &baseimage)
{
static QString theme = getTheme();
addFile(":/themes/"+theme+"/16/"+baseimage, QSize(16,16));
addFile(":/themes/"+theme+"/24/"+baseimage, QSize(24,24));
addFile(":/themes/"+theme+"/32/"+baseimage, QSize(32,32));
addFile(":/themes/"+theme+"/48/"+baseimage, QSize(48,48));
resultMsg.append("\n" % QCoreApplication::translate("Companion", "Press the 'Retry' button to choose another file."));
if (QMessageBox::warning(dlgParent, CPN_STR_APP_NAME, resultMsg, QMessageBox::Cancel, QMessageBox::Retry) == QMessageBox::Retry)
exportAppSettings(dlgParent);
}
void startSimulation(QWidget * parent, RadioData & radioData, int modelIdx)
@@ -637,8 +488,8 @@ void startSimulation(QWidget * parent, RadioData & radioData, int modelIdx)
QString fwId = SimulatorLoader::findSimulatorByFirmwareName(getCurrentFirmware()->getId());
if (fwId.isEmpty()) {
QMessageBox::warning(NULL,
QObject::tr("Warning"),
QObject::tr("Simulator for this firmware is not yet available"));
CPN_STR_TTL_WARNING,
QCoreApplication::translate("Companion", "Simulator for this firmware is not yet available"));
return;
}
@@ -662,15 +513,15 @@ void startSimulation(QWidget * parent, RadioData & radioData, int modelIdx)
QString resultMsg;
if (dialog->getExitStatus(&resultMsg)) {
if (resultMsg.isEmpty())
resultMsg = QObject::tr("Uknown error during Simulator startup.");
QMessageBox::critical(NULL, QObject::tr("Simulator Error"), resultMsg);
resultMsg = QCoreApplication::translate("Companion", "Uknown error during Simulator startup.");
QMessageBox::critical(NULL, QCoreApplication::translate("Companion", "Simulator Error"), resultMsg);
dialog->deleteLater();
}
else if (dialog->setRadioData(simuData)) {
dialog->show();
}
else {
QMessageBox::critical(NULL, QObject::tr("Data Load Error"), QObject::tr("Error occurred while starting simulator."));
QMessageBox::critical(NULL, QCoreApplication::translate("Companion", "Data Load Error"), QCoreApplication::translate("Companion", "Error occurred while starting simulator."));
dialog->deleteLater();
}
}
@@ -737,7 +588,7 @@ const QString index2version(int index)
if (nightly > 0 && nightly < 900) {
result += "N" + QString::number(nightly);
}
else if (nightly >= 900 && nightly < 1000) {
else if (nightly >= 900 && nightly < 999) {
result += "RC" + QString::number(nightly-900);
}
}
@@ -794,11 +645,6 @@ QSet<QString> getFilesSet(const QString &path, const QStringList &filter, int ma
return result;
}
bool caseInsensitiveLessThan(const QString &s1, const QString &s2)
{
return s1.toLower() < s2.toLower();
}
bool GpsGlitchFilter::isGlitch(GpsCoord coord)
{
if ((fabs(coord.latitude) < 0.1) && (fabs(coord.longitude) < 0.1)) {
+17 -40
View File
@@ -52,11 +52,10 @@ extern const QColor colors[CPN_MAX_CURVES];
#define TRIM_MODE_NONE 0x1F // 0b11111
QString getTheme();
class CompanionIcon: public QIcon {
public:
CompanionIcon(const QString &baseimage);
void addImage(const QString &baseimage, Mode mode = Normal, State state = Off);
};
class GVarGroup: public QObject {
@@ -66,6 +65,8 @@ class GVarGroup: public QObject {
public:
GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBox * weightCB, int & weight, const ModelData & model, const int deflt, const int mini, const int maxi, const double step=1.0, bool allowGVars=true);
void setWeight(int val);
signals:
void valueChanged();
@@ -80,6 +81,9 @@ class GVarGroup: public QObject {
QDoubleSpinBox *dsb;
QComboBox *weightCB;
int & weight;
int deflt;
int mini;
int maxi;
double step;
bool lock;
};
@@ -113,45 +117,20 @@ class CurveGroup : public QObject {
int lastType;
};
#define POPULATE_NONE (1<<0)
#define POPULATE_SOURCES (1<<1)
#define POPULATE_TRIMS (1<<2)
#define POPULATE_SWITCHES (1<<3)
#define POPULATE_GVARS (1<<4)
#define POPULATE_TELEMETRY (1<<5)
#define POPULATE_TELEMETRYEXT (1<<6)
#define POPULATE_VIRTUAL_INPUTS (1<<7)
#define POPULATE_SCRIPT_OUTPUTS (1<<8)
#define GVARS_VARIANT 0x0001
#define FRSKY_VARIANT 0x0002
namespace Helpers
{
void addRawSourceItems(QStandardItemModel * itemModel, const RawSourceType & type, int count, const GeneralSettings * const generalSettings = NULL,
const ModelData * const model = NULL, const int start = 0, const QList<int> exclude = QList<int>());
QStandardItemModel * getRawSourceItemModel(const GeneralSettings * const generalSettings = NULL, const ModelData * const model = NULL, unsigned int flags = 0);
void populateGvarUseCB(QComboBox *b, unsigned int phase);
void populateGVCB(QComboBox & b, int value, const ModelData & model);
QString getAdjustmentString(int16_t val, const ModelData * model = NULL, bool sign = false);
void populateFileComboBox(QComboBox * b, const QSet<QString> & set, const QString & current);
void getFileComboBoxValue(QComboBox * b, char * dest, int length);
void exportAppSettings(QWidget * dlgParent = nullptr);
} // namespace Helpers
// TODO : move to Helpers namespace
QString image2qstring(QImage image);
int findmult(float value, float base);
/* FrSky helpers */
QString getFrSkyAlarmType(int alarm);
QString getFrSkyUnits(int units);
QString getFrSkyProtocol(int protocol);
QString getFrSkyMeasure(int units);
QString getFrSkySrc(int index);
// TODO : move globals to Helpers namespace
void startSimulation(QWidget * parent, RadioData & radioData, int modelIdx);
@@ -161,14 +140,6 @@ QPixmap makePixMap(const QImage & image);
int version2index(const QString & version);
const QString index2version(int index);
class QTimeS : public QTime
{
public:
QTimeS(int s) { int h = s/3600; s %= 3600; int m = s/60; s %=60; setHMS(h, m, s); }
QTimeS(const QTime & q) : QTime(q) {}
int seconds() const { return hour()*3600 + minute()*60 + second(); }
};
bool qunlink(const QString & fileName);
QString generateProcessUniqueTempFileName(const QString & fileName);
@@ -177,8 +148,14 @@ bool isTempFileName(const QString & fileName);
QString getSoundsPath(const GeneralSettings &generalSettings);
QSet<QString> getFilesSet(const QString &path, const QStringList &filter, int maxLen);
bool caseInsensitiveLessThan(const QString &s1, const QString &s2);
class QTimeS : public QTime
{
public:
QTimeS(int s) { int h = s/3600; s %= 3600; int m = s/60; s %=60; setHMS(h, m, s); }
QTimeS(const QTime & q) : QTime(q) {}
int seconds() const { return hour()*3600 + minute()*60 + second(); }
};
class GpsCoord
{
+186 -8
View File
@@ -18,34 +18,212 @@
* GNU General Public License for more details.
*/
#include "helpers.h"
#include "helpers_html.h"
#include <QStringList>
#include <QDir>
#include <QFile>
#include <QTextStream>
QString tdAlign(const QString &s, const QString &align, const QString &color, bool bold)
QString tdAlign(const QString & s, const QString & align, const QString & color, bool bold)
{
QString str = s;
if (bold) str = "<b>" + str + "</b>";
if (!color.isEmpty()) str = "<font color=" + color + ">" + str + "</font>";
return "<td align=" + align + ">" + str + "</td>";
if (!color.isEmpty()) str = "<font color='" + color + "'>" + str + "</font>";
return "<td align='" + align + "'>" + str + "</td>";
}
QString doTC(const QString &s, const QString &color, bool bold)
QString doTC(const QString & s, const QString & color, bool bold)
{
return tdAlign(s, "center", color, bold);
}
QString doTR(const QString &s, const QString &color, bool bold)
QString doTR(const QString & s, const QString & color, bool bold)
{
return tdAlign(s, "right", color, bold);
}
QString doTL(const QString &s, const QString &color, bool bold)
QString doTL(const QString & s, const QString & color, bool bold)
{
return tdAlign(s, "left", color, bold);
}
QString fv(const QString &name, const QString &value, const QString &color)
QString fv(const QString & name, const QString & value, const QString & color)
{
return "<b>" + name + ": </b><font color=" +color + ">" + value + "</font><br>";
return "<b>" + name + ": </b><font color='" + color + "'>" + value + "</font><br>";
}
QString doTableCell(const QString & s, const unsigned int width, const QString & align, const QString & color, bool bold)
{
QString prfx = "<td";
if (width)
prfx.append(QString(" width='%1%'").arg(QString::number(width)));
if (!align.isEmpty())
prfx.append(QString(" align='%1'").arg(align));
prfx.append(">");
QString str = s;
if (bold)
str = "<b>" + str + "</b>";
if (!color.isEmpty())
str = QString("<font color='%1'>%2</font>").arg(color).arg(str);
str = prfx + str + "</td>";
return str;
}
QString doTableRow(const QStringList & strl, const unsigned int width, const QString & align, const QString & color, bool bold)
{
QString str;
for (int i=0; i<strl.count(); i++) {
str.append(doTableCell(strl.at(i), width, align, color, bold));
}
return "<tr>" + str + "</tr>";
}
QString doTableBlankRow()
{
return "<tr></tr>";
}
Stylesheet::Stylesheet(const QString & name):
mName(name)
{
init();
}
Stylesheet::Stylesheet(const QString & name, const StyleType styleType):
mName(name)
{
init();
mResult = load(styleType);
}
Stylesheet::~Stylesheet()
{
}
void Stylesheet::init()
{
mResult = false;
mErrormsg = "";
mText = "";
QStringList p = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation);
mCustomPath = p[0];
mCustomFile = p[0] + "/" + mName;
mDefaultFile = THEMES_DEFAULT_PATH + mName;
}
bool Stylesheet::load(const StyleType styleType)
{
mResult = false;
switch (styleType) {
case STYLE_TYPE_NONE:
case STYLE_TYPE_DEFAULT:
mResult = read(mDefaultFile);
case STYLE_TYPE_CUSTOM:
mResult = read(mCustomFile);
case STYLE_TYPE_EFFECTIVE:
mResult = read(mCustomFile);
if(!mResult)
mResult = read(mDefaultFile);
}
return mResult;
}
bool Stylesheet::read(const QString & path)
{
mResult = false;
mText = "";
QFile file(path);
if (file.exists()) {
if (file.open(QFile::ReadOnly | QFile::Text)) {
QTextStream in(&file);
if (in.status()==QTextStream::Ok) {
mText = in.readAll();
if (in.status()==QTextStream::Ok)
mResult = true;
else
mText = "";
}
file.close();
}
}
if (mResult)
mErrormsg = tr("Style sheet data read from '%1'").arg(QDir::toNativeSeparators(path));
else
mErrormsg = tr("Style sheet data unable to be read from '%1'").arg(QDir::toNativeSeparators(path));
qDebug() << mErrormsg;
return mResult;
}
bool Stylesheet::update()
{
mResult = false;
mErrormsg = "";
QDir path(mCustomPath);
if (!path.exists()) {
QDir dir;
if (!dir.mkpath(mCustomPath))
mErrormsg = tr("Cannot create folder '%1'").arg(QDir::toNativeSeparators(mCustomPath));
}
if (path.exists()) {
QFile file(mCustomFile);
if (!file.open(QFile::WriteOnly | QFile::Text)) {
mErrormsg = tr("Cannot open file for writing '%1': Error: %2").arg(QDir::toNativeSeparators(mCustomFile), file.errorString());
}
else {
QTextStream out(&file);
if (out.status()==QTextStream::Ok) {
out << mText;
if (!(out.status()==QTextStream::Ok)) {
mErrormsg = tr("Cannot write to file '%1': Error: %2").arg(QDir::toNativeSeparators(mCustomFile), file.errorString());
if (!file.flush()) {
mErrormsg = tr("Cannot flush buffer for file '%1': Error: %2").arg(QDir::toNativeSeparators(mCustomFile), file.errorString());
}
}
else {
mResult = true;
mErrormsg = tr("Style sheet written to '%1'").arg(QDir::toNativeSeparators(mCustomFile));
}
}
}
file.close();
}
qDebug() << mErrormsg;
return mResult;
}
bool Stylesheet::deleteCustom()
{
QFile file(mCustomFile);
mResult = file.remove();
if (mResult)
mErrormsg = tr("Custom style sheet deleted: '%1'").arg(QDir::toNativeSeparators(mCustomFile));
else
mErrormsg = tr("Unable to delete custom style sheet: '%1'").arg(QDir::toNativeSeparators(mCustomFile));
qDebug() << mErrormsg;
return mResult;
}
QString Stylesheet::name()
{
return mName;
}
QString Stylesheet::text()
{
return mText;
}
void Stylesheet::setText(const QString & text)
{
mText = text;
}
QString Stylesheet::errormsg()
{
return mErrormsg;
}
+47 -4
View File
@@ -21,11 +21,54 @@
#ifndef _HELPERS_HTML_H_
#define _HELPERS_HTML_H_
#include <QObject>
#include <QString>
QString doTC(const QString &s, const QString &color="", bool bold=false);
QString doTR(const QString &s, const QString &color="", bool bold=false);
QString doTL(const QString &s, const QString &color="", bool bold=false);
QString fv(const QString &name, const QString &value, const QString &color="green");
#define THEMES_DEFAULT_PATH ":/themes/default/"
#define MODEL_PRINT_CSS "modelprt.css"
QString tdAlign(const QString & s, const QString & align, const QString & color, bool bold);
QString doTC(const QString & s, const QString & color = "", bool bold = false);
QString doTR(const QString & s, const QString & color = "", bool bold = false);
QString doTL(const QString & s, const QString & color = "", bool bold = false);
QString fv(const QString & name, const QString & value, const QString & color = "green");
QString doTableCell(const QString & s, const unsigned int width = 0, const QString & align = "", const QString & color = "", bool bold = false);
QString doTableRow(const QStringList & strl, const unsigned int width = 0, const QString & align = "", const QString & color = "", bool bold = false);
QString doTableBlankRow();
class Stylesheet: public QObject
{
Q_OBJECT
public:
enum StyleType {
STYLE_TYPE_NONE,
STYLE_TYPE_DEFAULT,
STYLE_TYPE_CUSTOM,
STYLE_TYPE_EFFECTIVE
};
Stylesheet(const QString & name);
Stylesheet(const QString & name, const StyleType styleType);
~Stylesheet();
bool load(const StyleType styleType);
bool update();
bool deleteCustom();
QString name();
QString text();
QString errormsg();
void setText(const QString & text);
private:
bool mResult;
QString mErrormsg;
QString mName;
QString mText;
QString mCustomFile;
QString mCustomPath;
QString mDefaultFile;
void init();
bool read(const QString & filepath);
};
#endif // _HELPERS_HTML_H_
Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

-1
View File
@@ -1 +0,0 @@
IDI_ICON1 ICON DISCARDABLE "icon.ico"

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Some files were not shown because too many files have changed in this diff Show More