From 366c286e73317ac17086e2f1dd846ab5569428ff Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 8 Feb 2016 20:51:47 +0100 Subject: [PATCH] [Horus] UI continued --- .../firmwares/opentx/simulator/CMakeLists.txt | 4 +- .../opentx/simulator/opentxsimulator.cpp | 9 + radio/src/CMakeLists.txt | 13 +- radio/src/audio_arm.cpp | 10 +- radio/src/bitmaps/horus/mask_mainviews.png | Bin 0 -> 674 bytes .../src/bitmaps/horus/mask_mainviews_add.png | Bin 0 -> 545 bytes .../bitmaps/horus/mask_mainviews_item_in.png | Bin 0 -> 257 bytes .../bitmaps/horus/mask_mainviews_item_out.png | Bin 0 -> 312 bytes .../bitmaps/horus/mask_mainviews_topbar.png | Bin 0 -> 425 bytes radio/src/fonts/horus/font_dblsize.specs | 2 +- radio/src/fonts/horus/font_midsize.specs | 2 +- radio/src/fonts/horus/font_smlsize.specs | 2 +- radio/src/fonts/horus/font_tinsize.specs | 2 +- radio/src/fonts/horus/font_xxlsize.specs | 2 +- radio/src/gui/horus/bitmaps.cpp | 16 +- radio/src/gui/horus/bitmaps.h | 13 +- radio/src/gui/horus/gui.h | 3 + radio/src/gui/horus/layout.cpp | 101 +++++ radio/src/gui/horus/layout.h | 153 +++++++ radio/src/gui/horus/layouts/layout2+1.cpp | 103 +++++ radio/src/gui/horus/layouts/layout2x2.cpp | 86 ++++ radio/src/gui/horus/layouts/layout2x4.cpp | 119 ++++++ radio/src/gui/horus/lcd.cpp | 215 +++++----- radio/src/gui/horus/lcd.h | 20 +- radio/src/gui/horus/menu_general_calib.cpp | 2 +- .../src/gui/horus/menu_general_sdmanager.cpp | 2 +- radio/src/gui/horus/menu_model_curves.cpp | 4 +- .../gui/horus/menu_model_custom_scripts.cpp | 2 +- radio/src/gui/horus/menu_model_inputs.cpp | 2 +- radio/src/gui/horus/menu_model_mixes.cpp | 2 +- radio/src/gui/horus/menu_model_setup.cpp | 12 +- radio/src/gui/horus/menu_model_telemetry.cpp | 2 +- radio/src/gui/horus/menus.h | 18 +- radio/src/gui/horus/screens_setup.cpp | 393 ++++++++---------- radio/src/gui/horus/view_main.cpp | 79 +--- radio/src/gui/horus/view_statistics.cpp | 4 +- radio/src/gui/horus/widget.cpp | 59 +++ radio/src/gui/horus/widget.h | 172 ++++++++ radio/src/gui/horus/widgets.cpp | 111 ++--- radio/src/gui/horus/widgets.h | 10 +- radio/src/gui/horus/widgets/gauge.cpp | 79 ++++ radio/src/gui/horus/widgets/modelpanel.cpp | 56 +++ radio/src/gui/horus/widgets/text.cpp | 57 +++ radio/src/gui/horus/widgets/timer.cpp | 61 +++ radio/src/myeeprom.h | 38 +- radio/src/opentx.cpp | 42 +- radio/src/opentx.h | 4 +- radio/src/translations.cpp | 3 + radio/src/translations.h | 9 +- radio/src/translations/cz.h.txt | 3 + radio/src/translations/de.h.txt | 3 + radio/src/translations/en.h.txt | 3 + radio/src/translations/es.h.txt | 3 + radio/src/translations/fi.h.txt | 3 + radio/src/translations/fr.h.txt | 3 + radio/src/translations/it.h.txt | 3 + radio/src/translations/nl.h.txt | 3 + radio/src/translations/pl.h.txt | 3 + radio/src/translations/pt.h.txt | 3 + radio/src/translations/se.h.txt | 3 + radio/util/font2png.py | 6 +- 61 files changed, 1575 insertions(+), 562 deletions(-) create mode 100644 radio/src/bitmaps/horus/mask_mainviews.png create mode 100644 radio/src/bitmaps/horus/mask_mainviews_add.png create mode 100644 radio/src/bitmaps/horus/mask_mainviews_item_in.png create mode 100644 radio/src/bitmaps/horus/mask_mainviews_item_out.png create mode 100644 radio/src/bitmaps/horus/mask_mainviews_topbar.png create mode 100644 radio/src/gui/horus/layout.cpp create mode 100644 radio/src/gui/horus/layout.h create mode 100644 radio/src/gui/horus/layouts/layout2+1.cpp create mode 100644 radio/src/gui/horus/layouts/layout2x2.cpp create mode 100644 radio/src/gui/horus/layouts/layout2x4.cpp create mode 100644 radio/src/gui/horus/widget.cpp create mode 100644 radio/src/gui/horus/widget.h create mode 100644 radio/src/gui/horus/widgets/gauge.cpp create mode 100644 radio/src/gui/horus/widgets/modelpanel.cpp create mode 100644 radio/src/gui/horus/widgets/text.cpp create mode 100644 radio/src/gui/horus/widgets/timer.cpp diff --git a/companion/src/firmwares/opentx/simulator/CMakeLists.txt b/companion/src/firmwares/opentx/simulator/CMakeLists.txt index 58416f866..347c714e7 100644 --- a/companion/src/firmwares/opentx/simulator/CMakeLists.txt +++ b/companion/src/firmwares/opentx/simulator/CMakeLists.txt @@ -84,6 +84,8 @@ add_dependencies(opentx-taranisx9e${SUFFIX}-simulator ${dependencies_taranis} lu add_dependencies(opentx-horus${SUFFIX}-simulator horus_bitmaps horus_fonts firmware_translations lua_export_horus) +add_definitions(-std=c++11) + set(OPENTX_LIBRARIES opentx-9x${SUFFIX}-simulator opentx-9xr${SUFFIX}-simulator @@ -165,7 +167,7 @@ target_compile_definitions(opentx-taranisx9e${SUFFIX}-simulator PRIVATE PCBTARAN target_link_libraries(opentx-taranisx9e${SUFFIX}-simulator PRIVATE ${COMMON_LIBRARIES}) # Horus -target_include_directories(opentx-horus${SUFFIX}-simulator PRIVATE ${RADIO_SRC_DIRECTORY}/targets/horus PRIVATE ${RADIO_SRC_DIRECTORY}/fonts/horus PRIVATE ${CMAKE_BINARY_DIR}/radio/src/bitmaps/horus) +target_include_directories(opentx-horus${SUFFIX}-simulator PRIVATE ${RADIO_SRC_DIRECTORY}/targets/horus PRIVATE ${RADIO_SRC_DIRECTORY}/gui/horus PRIVATE ${RADIO_SRC_DIRECTORY}/fonts/horus PRIVATE ${CMAKE_BINARY_DIR}/radio/src/bitmaps/horus) target_compile_definitions(opentx-horus${SUFFIX}-simulator PRIVATE PCBHORUS CPUARM CPUSTM32 STM32F40_41xxx COLORLCD VOICE SDCARD ${COMMON_DEFINITIONS}) target_link_libraries(opentx-horus${SUFFIX}-simulator PRIVATE ${COMMON_LIBRARIES}) diff --git a/companion/src/firmwares/opentx/simulator/opentxsimulator.cpp b/companion/src/firmwares/opentx/simulator/opentxsimulator.cpp index ed68b2cd9..73e21329d 100644 --- a/companion/src/firmwares/opentx/simulator/opentxsimulator.cpp +++ b/companion/src/firmwares/opentx/simulator/opentxsimulator.cpp @@ -172,6 +172,15 @@ namespace NAMESPACE { #include "radio/src/gui/horus/view_about.cpp" #include "radio/src/gui/horus/lcd.cpp" #include "radio/src/gui/horus/splash.cpp" +#include "radio/src/gui/horus/widget.cpp" +#include "radio/src/gui/horus/layout.cpp" +#include "radio/src/gui/horus/layouts/layout2+1.cpp" +#include "radio/src/gui/horus/layouts/layout2x2.cpp" +#include "radio/src/gui/horus/layouts/layout2x4.cpp" +#include "radio/src/gui/horus/widgets/gauge.cpp" +#include "radio/src/gui/horus/widgets/modelpanel.cpp" +#include "radio/src/gui/horus/widgets/text.cpp" +#include "radio/src/gui/horus/widgets/timer.cpp" #elif defined(PCBFLAMENCO) #include "radio/src/gui/Flamenco/fonts.cpp" #include "radio/src/gui/Flamenco/widgets.cpp" diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index 5fe4712a6..a9a323215 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -21,6 +21,7 @@ option(JITTER_FILTER "Enable ADC jitter filtering" ON) enable_language(ASM) set(OPT s) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") set(THIRDPARTY_DIR thirdparty) set(LUA_DIR ${THIRDPARTY_DIR}/Lua/src) @@ -64,7 +65,9 @@ if(PCB STREQUAL HORUS) add_definitions(-DPCBHORUS -DCOLORLCD -DSTM32F429_439xx -DPPM_PIN_HW_SERIAL) add_definitions(-DEEPROM_VARIANT=0 -DAUDIO -DVOICE -DRTCLOCK) add_definitions(-DLUAINPUTS -DXCURVES -DVARIO) - include_directories(${RADIO_SRC_DIRECTORY}/fonts/horus) + include_directories(${RADIO_SRC_DIRECTORY}/fonts/horus gui/${GUI_DIR}) + file(GLOB LAYOUTS_SRC RELATIVE ${RADIO_SRC_DIRECTORY}/gui/horus ${RADIO_SRC_DIRECTORY}/gui/horus/layouts/*.cpp) + file(GLOB WIDGETS_SRC RELATIVE ${RADIO_SRC_DIRECTORY}/gui/horus ${RADIO_SRC_DIRECTORY}/gui/horus/widgets/*.cpp) set(GUI_SRC ${GUI_SRC} curves.cpp @@ -76,6 +79,10 @@ if(PCB STREQUAL HORUS) view_about.cpp view_text.cpp screens_setup.cpp + widget.cpp + layout.cpp + ${LAYOUTS_SRC} + ${WIDGETS_SRC} ) set(SRC ${SRC} bmp.cpp targets/taranis/rtc_driver.cpp) set(TARGET_SRC ${TARGET_SRC} board_horus.cpp) @@ -777,7 +784,7 @@ set(CMAKE_CXX_LINK_EXECUTABLE " leb$uqoOFRIn5-B(o=i^T%l?bb1AHk(B-7(DggC3mLo|L34(AJ zUoMvyciQjwPfgDm*VUP(dH23ntHCe~9FIo~1_KC!aL0H3A9K!;NF?ljKA(rCX?Hx= z6B~wsR4Rq(bZW{T5Ohlz7ePG~lp1b}p1Cn6%(uD7jL3#zI<BWWgoxdOkeq;DB913LIHvxK$0ZLvW#xG`&fJaiexhRRJ9(D zhuZD7U4f=)2w$l zhbW2?N!rKb!E`!hJRVc8*D*~qm^how3Lv&^OVqmEZURUqlkvS!ajB{rNz&hyPNzd& zY*qaY{s#Zs;MHnHtJQiv*tTsBhr{c^pHcj6@fq#+`@s5qKI6J>$k#NDLZR^YP5x{W zj^n)h!*^Zx!)*MTrLOJ z+wGQQG8yvU)Bji1k$^Q#qgJau_mEd*xm->Fxm+&M%{;$!yhM(9UZviaJVm6y`I-Md(>#0~Q((QJs jR4Tp~0KZbPeNI0CQvBVqgcfMy00000NkvXXu0mjfv;*xn literal 0 HcmV?d00001 diff --git a/radio/src/bitmaps/horus/mask_mainviews_item_in.png b/radio/src/bitmaps/horus/mask_mainviews_item_in.png new file mode 100644 index 0000000000000000000000000000000000000000..d7a1ad4c8cd52ce50ca7a58481c00372ecb74163 GIT binary patch literal 257 zcmeAS@N?(olHy`uVBq!ia0vp^av;pX1|+Qw)-3{3EX7WqAsj$Z!;#Vf2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4b1+3-ADuyKP34adlTnB tUbpPjl%NaM=Ca?CdaT~tcium&9(X0>oqS^33ZP3EJYD@<);T3K0RY39SH=JU literal 0 HcmV?d00001 diff --git a/radio/src/bitmaps/horus/mask_mainviews_item_out.png b/radio/src/bitmaps/horus/mask_mainviews_item_out.png new file mode 100644 index 0000000000000000000000000000000000000000..6929b4aa37e2a6bf9b6aaa9189b55604a44e3386 GIT binary patch literal 312 zcmeAS@N?(olHy`uVBq!ia0vp^av;pX1|+Qw)-3{3EX7WqAsj$Z!;#Vf2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR41~C%{~8vU@jnz_ ztmIj8Vl_J#!~0@qq2q-K_sgHmk#}8|+4NoR^)4sPP{&CrJrfybt&@0sa^s3O^A z6N}DqC@z@t>4o?4!Xw*q4US#et^Z^GOS7x;5?Ytf|NpJ|4Cny{Pgg&ebxsLQ0GHc( Ag8%>k literal 0 HcmV?d00001 diff --git a/radio/src/bitmaps/horus/mask_mainviews_topbar.png b/radio/src/bitmaps/horus/mask_mainviews_topbar.png new file mode 100644 index 0000000000000000000000000000000000000000..2a39d1e4028f9e4b89da1e026743bf5685b7b41b GIT binary patch literal 425 zcmeAS@N?(olHy`uVBq!ia0vp^av;pX1|+Qw)-3{3EX7WqAsj$Z!;#Vf2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4f>32+({X{1V#nN?%nb~$I0z~W+ctMTVBFKV_v9CD_}Gq|3;PUG6es-$#Bp^ROG!EW31Wtjr5g1gpPizG>~*_>y7{^#}*{i&&* z41Ttmv-B*4rrB@Hm5!XI$m49$SDbOYa^B(ZwFTz_uYcW_>>9|y;CtD{J$sfKlfxvH zwfCgfX&>5~`lmmHxnbSwgf};;o>l&nwds4j@WT8rY}ZWQPU-u-@BVD>Qz?;lwpSNv z>|6dT%k}~Lp9c94%>S$_W_qOOD4m{td*$}Nqt{=zs(1>pFzTGP5{VIEWjJ7RHrCX| z<;pf)!()EYxvY*0R;{|WamTvt3mdKI;Vst0Hsc(*Z=?k literal 0 HcmV?d00001 diff --git a/radio/src/fonts/horus/font_dblsize.specs b/radio/src/fonts/horus/font_dblsize.specs index 8129cf4ed..ad91b19dc 100644 --- a/radio/src/fonts/horus/font_dblsize.specs +++ b/radio/src/fonts/horus/font_dblsize.specs @@ -1 +1 @@ -{ 0,4,14,28,54,76,110,139,146,160,173,193,217,228,242,251,266,289,310,331,352,375,397,420,441,464,487,497,508,532,556,580,598,613,641,665,689,715,736,757,783,808,818,832,859,880,910,935,963,987,1015,1040,1062,1087,1112,1140,1178,1206,1234,1258,1272,1287,1300,1324,1343,1356,1378,1401,1420,1443,1466,1484,1507,1529,1539,1553,1576,1586,1618,1640,1663,1686,1709,1726,1746,1764,1786,1810,1841,1865,1889,1909,1933,1936,1960,1988,2015,2033,2051,2074,2097,2120,2143,2171 } \ No newline at end of file +{ 0,4,14,28,54,76,110,139,146,160,173,193,217,228,242,251,266,289,310,331,352,375,397,420,441,464,487,497,508,532,556,580,598,613,641,665,689,715,736,757,783,808,818,832,859,880,910,935,963,987,1015,1040,1062,1087,1112,1140,1178,1206,1234,1258,1272,1287,1300,1324,1343,1356,1378,1401,1420,1443,1466,1484,1507,1529,1539,1553,1576,1586,1618,1640,1663,1686,1709,1726,1746,1764,1786,1810,1841,1865,1889,1909,1933,1936,1960,1988,2015,2033,2051,2074,2097,2120,2143,2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171 } \ No newline at end of file diff --git a/radio/src/fonts/horus/font_midsize.specs b/radio/src/fonts/horus/font_midsize.specs index 7244eaedd..3b0bd0cc7 100644 --- a/radio/src/fonts/horus/font_midsize.specs +++ b/radio/src/fonts/horus/font_midsize.specs @@ -1 +1 @@ -{ 0,4,10,20,41,56,80,100,106,115,125,140,159,167,177,184,196,212,227,242,258,274,290,306,322,338,354,361,369,388,407,426,440,451,471,487,505,524,539,553,572,589,595,605,623,638,658,675,695,710,730,747,763,782,799,819,845,864,883,901,910,922,931,950,967,976,991,1006,1020,1036,1052,1064,1080,1095,1101,1110,1125,1131,1154,1169,1185,1200,1216,1227,1241,1253,1268,1285,1306,1323,1340,1354,1373,1376,1395,1416,1437,1452,1467,1484,1501,1518,1535,1557 } \ No newline at end of file +{ 0,4,10,20,41,56,80,100,106,115,125,140,159,167,177,184,196,212,227,242,258,274,290,306,322,338,354,361,369,388,407,426,440,451,471,487,505,524,539,553,572,589,595,605,623,638,658,675,695,710,730,747,763,782,799,819,845,864,883,901,910,922,931,950,967,976,991,1006,1020,1036,1052,1064,1080,1095,1101,1110,1125,1131,1154,1169,1185,1200,1216,1227,1241,1253,1268,1285,1306,1323,1340,1354,1373,1376,1395,1416,1437,1452,1467,1484,1501,1518,1535,1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1557 } \ No newline at end of file diff --git a/radio/src/fonts/horus/font_smlsize.specs b/radio/src/fonts/horus/font_smlsize.specs index 3e3184a10..726016a97 100644 --- a/radio/src/fonts/horus/font_smlsize.specs +++ b/radio/src/fonts/horus/font_smlsize.specs @@ -1 +1 @@ -{ 0,4,8,13,23,31,44,55,58,63,67,75,85,88,94,97,103,112,120,128,137,146,154,163,171,180,189,192,195,205,215,225,232,238,248,256,266,276,284,291,301,310,313,318,327,335,345,354,365,373,384,393,402,412,421,431,445,455,465,475,479,485,489,499,508,513,521,529,537,546,555,561,570,578,581,586,594,597,609,617,626,634,643,649,657,663,671,680,692,701,710,718,728,729,739,751,763,771,779,789,799,809,819,830 } \ No newline at end of file +{ 0,4,8,13,23,31,44,55,58,63,67,75,85,88,94,97,103,112,120,128,137,146,154,163,171,180,189,192,195,205,215,225,232,238,248,256,266,276,284,291,301,310,313,318,327,335,345,354,365,373,384,393,402,412,421,431,445,455,465,475,479,485,489,499,508,513,521,529,537,546,555,561,570,578,581,586,594,597,609,617,626,634,643,649,657,663,671,680,692,701,710,718,728,729,739,751,763,771,779,789,799,809,819,830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830 } \ No newline at end of file diff --git a/radio/src/fonts/horus/font_tinsize.specs b/radio/src/fonts/horus/font_tinsize.specs index 2fbef2d86..b1482da70 100644 --- a/radio/src/fonts/horus/font_tinsize.specs +++ b/radio/src/fonts/horus/font_tinsize.specs @@ -1 +1 @@ -{ 0,4,7,12,20,26,36,44,47,51,55,61,69,72,76,79,84,91,97,103,109,116,122,129,135,142,149,151,154,162,170,178,184,189,197,204,211,219,226,232,240,247,250,254,262,268,276,283,291,298,306,313,320,328,335,343,353,360,368,375,379,384,388,396,403,407,413,420,426,432,439,444,450,456,459,463,470,473,482,488,495,502,508,513,519,524,530,537,545,552,559,565,573,574,582,591,600,606,612,619,626,633,640,648 } \ No newline at end of file +{ 0,4,7,12,20,26,36,44,47,51,55,61,69,72,76,79,84,91,97,103,109,116,122,129,135,142,149,151,154,162,170,178,184,189,197,204,211,219,226,232,240,247,250,254,262,268,276,283,291,298,306,313,320,328,335,343,353,360,368,375,379,384,388,396,403,407,413,420,426,432,439,444,450,456,459,463,470,473,482,488,495,502,508,513,519,524,530,537,545,552,559,565,573,574,582,591,600,606,612,619,626,633,640,648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648 } \ No newline at end of file diff --git a/radio/src/fonts/horus/font_xxlsize.specs b/radio/src/fonts/horus/font_xxlsize.specs index b3c0b02d3..fd3f7bb0d 100644 --- a/radio/src/fonts/horus/font_xxlsize.specs +++ b/radio/src/fonts/horus/font_xxlsize.specs @@ -1 +1 @@ -{ 0,4,12,29,66,93,137,173,181,195,210,235,269,280,296,305,325,353,378,404,431,460,487,515,542,570,598,607,618,652,686,720,743,762,798,827,859,893,920,944,979,1010,1019,1035,1067,1093,1129,1160,1197,1224,1261,1292,1320,1354,1384,1420,1468,1502,1536,1568,1582,1602,1616,1650,1679,1695,1722,1749,1774,1802,1830,1850,1878,1904,1912,1925,1952,1960,2002,2028,2056,2083,2111,2130,2154,2174,2200,2229,2268,2297,2326,2351,2385,2388,2422,2461,2500,2525,2550,2581,2612,2643,2674,2714 } \ No newline at end of file +{ 0,4,12,29,66,93,137,173,181,195,210,235,269,280,296,305,325,353,378,404,431,460,487,515,542,570,598,607,618,652,686,720,743,762,798,827,859,893,920,944,979,1010,1019,1035,1067,1093,1129,1160,1197,1224,1261,1292,1320,1354,1384,1420,1468,1502,1536,1568,1582,1602,1616,1650,1679,1695,1722,1749,1774,1802,1830,1850,1878,1904,1912,1925,1952,1960,2002,2028,2056,2083,2111,2130,2154,2174,2200,2229,2268,2297,2326,2351,2385,2388,2422,2461,2500,2525,2550,2581,2612,2643,2674,2714, 2714, 2714, 2714, 2714, 2714, 2714, 2714, 2714, 2714, 2714, 2714, 2714, 2714 } \ No newline at end of file diff --git a/radio/src/gui/horus/bitmaps.cpp b/radio/src/gui/horus/bitmaps.cpp index a507546ca..aa141b294 100644 --- a/radio/src/gui/horus/bitmaps.cpp +++ b/radio/src/gui/horus/bitmaps.cpp @@ -182,6 +182,10 @@ const uint8_t LBM_TELEMETRY_ICON[] = { #include "mask_telemetry.lbm" }; +const uint8_t LBM_MAINVIEWS_ICON[] = { +#include "mask_mainviews.lbm" +}; + const uint8_t * const LBM_MODEL_ICONS[] = { LBM_MODEL_ICON, LBM_MODEL_SETUP_ICON, @@ -303,15 +307,3 @@ const uint8_t LBM_SLIDER_POINT_MID[] __DMA = { const uint8_t LBM_SLIDER_POINT_IN[] __DMA = { #include "point_in.lbm" }; - -const uint8_t LBM_BUTTON_LEFT[] __DMA = { -#include "bmp_left.lbm" -}; - -const uint8_t LBM_BUTTON_MID[] __DMA = { -#include "bmp_mid.lbm" -}; - -const uint8_t LBM_BUTTON_RIGHT[] __DMA = { -#include "bmp_right.lbm" -}; diff --git a/radio/src/gui/horus/bitmaps.h b/radio/src/gui/horus/bitmaps.h index 14fb0c2a6..fc5270f6f 100644 --- a/radio/src/gui/horus/bitmaps.h +++ b/radio/src/gui/horus/bitmaps.h @@ -44,6 +44,14 @@ extern const uint8_t LBM_RSCALE[]; // Menu icons extern const uint8_t * const LBM_RADIO_ICONS[]; extern const uint8_t * const LBM_MODEL_ICONS[]; +extern const uint8_t LBM_RADIO_ICON[]; +extern const uint8_t LBM_SD_BROWSER_ICON[]; +extern const uint8_t LBM_CALIBRATION_ICON[]; +extern const uint8_t LBM_INPUTS_ICON[]; +extern const uint8_t LBM_MIXER_ICON[]; +extern const uint8_t LBM_CURVES_ICON[]; +extern const uint8_t LBM_TELEMETRY_ICON[]; +extern const uint8_t LBM_MAINVIEWS_ICON[]; // Model selection icons extern const uint8_t LBM_LIBRARY_ICON[]; @@ -70,11 +78,6 @@ extern const uint8_t LBM_SHUTDOWN[]; extern const uint8_t LBM_SLEEP[]; extern const uint8_t LBM_SHUTDOWN_CIRCLE[]; -// Button bitmaps -extern const uint8_t LBM_BUTTON_LEFT[]; -extern const uint8_t LBM_BUTTON_MID[]; -extern const uint8_t LBM_BUTTON_RIGHT[]; - // Slider bitmaps extern const uint8_t LBM_SLIDER_BAR_LEFT[]; extern const uint8_t LBM_SLIDER_BAR_RIGHT[]; diff --git a/radio/src/gui/horus/gui.h b/radio/src/gui/horus/gui.h index e44c1698c..1007c9ae1 100644 --- a/radio/src/gui/horus/gui.h +++ b/radio/src/gui/horus/gui.h @@ -79,3 +79,6 @@ void drawCurveVerticalScale(int x); void drawCurveHorizontalScale(); void drawCurveCoord(int x, int y, const char * text, bool active=false); void drawCurvePoint(int x, int y, LcdFlags color); + +// TODO one screen for now +extern Layout * customScreens[MAX_CUSTOM_SCREENS]; diff --git a/radio/src/gui/horus/layout.cpp b/radio/src/gui/horus/layout.cpp new file mode 100644 index 000000000..888a2b104 --- /dev/null +++ b/radio/src/gui/horus/layout.cpp @@ -0,0 +1,101 @@ +/* + * 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 "opentx.h" + +void Layout::setWidget(unsigned int index, const char * name) +{ + memset(persistentData->zones[index].widgetName, 0, sizeof(persistentData->zones[index].widgetName)); + if (name) { + strncpy(persistentData->zones[index].widgetName, name, sizeof(persistentData->zones[index].widgetName)); + widgets[index] = createWidget(name, getZone(index), &persistentData->zones[index].widgetData); + } + else { + widgets[index] = NULL; + } +} + +void Layout::create() +{ + memset(persistentData, 0, sizeof(PersistentData)); +} + +void Layout::load() +{ + unsigned int count = getZonesCount(); + for (unsigned int i=0; izones[i].widgetName)+1]; + memset(name, 0, sizeof(name)); + strncpy(name, persistentData->zones[i].widgetName, sizeof(persistentData->zones[i].widgetName)); + widgets[i] = loadWidget(name, getZone(i), &persistentData->zones[i].widgetData); + } +} + +void Layout::refresh(bool setup) +{ + if (setup) { + lcdDrawBlackOverlay(); + } + + for (int i = 0; i < MAX_LAYOUT_ZONES; i++) { + if (widgets[i]) { + widgets[i]->refresh(); + } + } +} + +const LayoutFactory * registeredLayouts[MAX_REGISTERED_LAYOUTS]; // TODO dynamic +unsigned int countRegisteredLayouts = 0; +void registerLayout(const LayoutFactory * factory) +{ + if (countRegisteredLayouts < MAX_REGISTERED_LAYOUTS) { + registeredLayouts[countRegisteredLayouts++] = factory; + } +} + +const LayoutFactory * getLayoutFactory(const char * name) +{ + for (unsigned int i=0; igetName())) { + return factory; + } + } + return NULL; +} + +Layout * createLayout(const char * name, Layout::PersistentData * persistentData) +{ + const LayoutFactory * factory = getLayoutFactory(name); + if (factory) { + return factory->create(persistentData); + } + return NULL; +} + +Layout * loadLayout(const char * name, Layout::PersistentData * persistentData) +{ + const LayoutFactory * factory = getLayoutFactory(name); + if (factory) { + return factory->load(persistentData); + } + return NULL; +} + diff --git a/radio/src/gui/horus/layout.h b/radio/src/gui/horus/layout.h new file mode 100644 index 000000000..e5a876e34 --- /dev/null +++ b/radio/src/gui/horus/layout.h @@ -0,0 +1,153 @@ +/* + * 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 _LAYOUT_H_ +#define _LAYOUT_H_ + +#include "widget.h" + +#define MAX_LAYOUT_ZONES 10 +#define MAX_LAYOUT_OPTIONS 10 + +class LayoutFactory; +class Layout +{ + friend class LayoutFactory; + + public: + struct ZonePersistentData + { + char widgetName[10]; + Widget::PersistentData widgetData; + }; + + struct PersistentData { + ZonePersistentData zones[MAX_LAYOUT_ZONES]; + ZoneOptionValue options[MAX_LAYOUT_OPTIONS]; + }; + + public: + Layout(const LayoutFactory * factory, PersistentData * persistentData): + factory(factory), + persistentData(persistentData) + { + memset(widgets, 0, sizeof(widgets)); + } + + const LayoutFactory * getFactory() const + { + return factory; + } + + Widget * getWidget(unsigned int index) + { + return widgets[index]; + } + + void setWidget(unsigned int index, const char * name); + + virtual void create(); + + virtual void load(); + + ZoneOptionValue getOptionValue(unsigned int index) const + { + return persistentData->options[index]; + } + + void setOptionValue(unsigned int index, ZoneOptionValue value) const + { + persistentData->options[index] = value; + } + + virtual unsigned int getZonesCount() const = 0; + virtual Zone getZone(unsigned int index) const = 0; + + virtual void refresh(bool setup=false); + + protected: + const LayoutFactory * factory; + Widget * widgets[MAX_LAYOUT_ZONES]; + PersistentData * persistentData; +}; + +void registerLayout(const LayoutFactory * factory); + +class LayoutFactory +{ + public: + LayoutFactory(const char * name, const char * bitmap): + name(name), + bitmap(bitmap) + { + registerLayout(this); + } + const char * getName() const { return name; } + const char * getBitmap() const { return bitmap; } + virtual const ZoneOption * getOptions() const = 0; + virtual Layout * create(Layout::PersistentData * persistentData) const = 0; + virtual Layout * load(Layout::PersistentData * persistentData) const = 0; + + protected: + const char * name; + const char * bitmap; +}; + +template +class BaseLayoutFactory: public LayoutFactory +{ + public: + BaseLayoutFactory(const char * name, const char * bitmap, const ZoneOption * options): + LayoutFactory(name, bitmap), + options(options) + { + } + + virtual const ZoneOption * getOptions() const + { + return options; + } + + virtual Layout * create(Layout::PersistentData * persistentData) const + { + Layout * layout = new T(this, persistentData); + layout->create(); + return layout; + } + + virtual Layout * load(Layout::PersistentData * persistentData) const + { + Layout * layout = new T(this, persistentData); + layout->load(); + return layout; + } + + protected: + const ZoneOption * options; +}; + +#define MAX_REGISTERED_LAYOUTS 10 + +extern unsigned int countRegisteredLayouts; +extern const LayoutFactory * registeredLayouts[MAX_REGISTERED_LAYOUTS]; +Layout * createLayout(const char * name, Layout::PersistentData * persistentData); +Layout * loadLayout(const char * name, Layout::PersistentData * persistentData); + +#endif // _LAYOUT_H_ diff --git a/radio/src/gui/horus/layouts/layout2+1.cpp b/radio/src/gui/horus/layouts/layout2+1.cpp new file mode 100644 index 000000000..9969ef34a --- /dev/null +++ b/radio/src/gui/horus/layouts/layout2+1.cpp @@ -0,0 +1,103 @@ +/* + * 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 "opentx.h" + +class Layout2P1: public Layout +{ + public: + Layout2P1(const LayoutFactory * factory, Layout::PersistentData * persistentData): + Layout(factory, persistentData) + { + } + + virtual void create() + { + persistentData->options[0].boolValue = true; + persistentData->options[1].boolValue = true; + persistentData->options[2].boolValue = true; + persistentData->options[3].boolValue = true; + } + + virtual unsigned int getZonesCount() const + { + return 3; + } + + virtual Zone getZone(unsigned int index) const + { + return zones[index]; + } + + virtual void refresh(bool setup=false); + + static const ZoneOption options[]; + + protected: + static const Zone zones[3]; +}; + +const Zone Layout2P1::zones[3] = { + { 240, 60, 192, 145 }, + { 46, 60, 192, 70 }, + { 46, 135, 192, 70 } +}; + +const ZoneOption Layout2P1::options[] = { + { "Top bar", ZoneOption::Bool }, + { "Flight mode", ZoneOption::Bool }, + { "Sliders", ZoneOption::Bool }, + { "Trims", ZoneOption::Bool }, + { NULL, ZoneOption::Bool } +}; + +void Layout2P1::refresh(bool setup) +{ + lcdDrawBitmap(0, 0, LBM_MAINVIEW_BACKGROUND); + + if (persistentData->options[0].boolValue) { + // Top Bar + drawMainViewTopBar(); + } + + if (persistentData->options[1].boolValue) { + // Flight mode + lcdDrawSizedText(LCD_W / 2 - getTextWidth(g_model.flightModeData[mixerCurrentFlightMode].name, + sizeof(g_model.flightModeData[mixerCurrentFlightMode].name), + ZCHAR | SMLSIZE) / 2, + 237, + g_model.flightModeData[mixerCurrentFlightMode].name, + sizeof(g_model.flightModeData[mixerCurrentFlightMode].name), ZCHAR | SMLSIZE); + } + + if (persistentData->options[2].boolValue) { + // Pots and rear sliders positions + drawMainPots(); + } + + if (persistentData->options[3].boolValue) { + // Trims + drawTrims(mixerCurrentFlightMode); + } + + Layout::refresh(setup); +} + +BaseLayoutFactory layout2P1("Layout2P1", "", Layout2P1::options); diff --git a/radio/src/gui/horus/layouts/layout2x2.cpp b/radio/src/gui/horus/layouts/layout2x2.cpp new file mode 100644 index 000000000..f362c3f48 --- /dev/null +++ b/radio/src/gui/horus/layouts/layout2x2.cpp @@ -0,0 +1,86 @@ +/* + * 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 "opentx.h" + +class Layout2x2: public Layout +{ + public: + Layout2x2(const LayoutFactory * factory, Layout::PersistentData * persistentData): + Layout(factory, persistentData) + { + } + + virtual void create() + { + persistentData->options[0].boolValue = true; + persistentData->options[1].boolValue = true; + persistentData->options[2].boolValue = true; + persistentData->options[3].boolValue = true; + } + + virtual unsigned int getZonesCount() const + { + return 4; + } + + virtual Zone getZone(unsigned int index) const + { + Zone zone; + zone.w = (LCD_W-3*10) / 2; + zone.x = (index & 1) ? 20 + zone.w : 10; + if (persistentData->options[0].boolValue) { + zone.h = (LCD_H-MENU_HEADER_HEIGHT-3*10) / 2; + zone.y = MENU_HEADER_HEIGHT + 10; + } + else { + zone.h = (LCD_H-3*10) / 2; + zone.y = 10; + } + if (index >= 2) { + zone.y += 10 + zone.h; + } + return zone; + } + + virtual void refresh(bool setup=false); + + static const ZoneOption options[]; + +}; + +const ZoneOption Layout2x2::options[] = { + { "Top bar", ZoneOption::Bool }, + { NULL, ZoneOption::Bool } +}; + +void Layout2x2::refresh(bool setup) +{ + lcdDrawBitmap(0, 0, LBM_MAINVIEW_BACKGROUND); + + if (persistentData->options[0].boolValue) { + // Top Bar + drawMainViewTopBar(); + } + + Layout::refresh(setup); +} + +BaseLayoutFactory layout2x2("Layout2x2", "", Layout2x2::options); diff --git a/radio/src/gui/horus/layouts/layout2x4.cpp b/radio/src/gui/horus/layouts/layout2x4.cpp new file mode 100644 index 000000000..942c9f4c8 --- /dev/null +++ b/radio/src/gui/horus/layouts/layout2x4.cpp @@ -0,0 +1,119 @@ +/* + * 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 "opentx.h" + +class Layout2x4: public Layout +{ + public: + Layout2x4(const LayoutFactory * factory, Layout::PersistentData * persistentData): + Layout(factory, persistentData) + { + } + + virtual void create() + { + TRACE("create"); + persistentData->options[0].boolValue = true; + persistentData->options[1].boolValue = true; + persistentData->options[2].boolValue = true; + persistentData->options[3].boolValue = true; + persistentData->options[4].boolValue = true; + persistentData->options[5].unsignedValue = RGB(77, 112, 203); + persistentData->options[6].boolValue = false; + persistentData->options[7].unsignedValue = RGB(77, 112, 203); + } + + virtual unsigned int getZonesCount() const + { + return 8; + } + + virtual Zone getZone(unsigned int index) const + { + Zone zone; + zone.x = (index >= 4) ? 260 : 60; + zone.y = 55 + (index % 4) * 40; + zone.w = 160; + zone.h = 40; + return zone; + } + + virtual void refresh(bool setup=false); + + static const ZoneOption options[]; + +}; + +const ZoneOption Layout2x4::options[] = { + { "Top bar", ZoneOption::Bool }, + { "Flight mode", ZoneOption::Bool }, + { "Sliders", ZoneOption::Bool }, + { "Trims", ZoneOption::Bool }, + { "Panel1 background", ZoneOption::Bool }, + { " Color", ZoneOption::Color }, + { "Panel2 background", ZoneOption::Bool }, + { " Color", ZoneOption::Color }, + { NULL, ZoneOption::Bool } +}; + +void Layout2x4::refresh(bool setup) +{ + lcdDrawBitmap(0, 0, LBM_MAINVIEW_BACKGROUND); + + if (persistentData->options[0].boolValue) { + // Top Bar + drawMainViewTopBar(); + } + + if (persistentData->options[1].boolValue) { + // Flight mode + lcdDrawSizedText(LCD_W / 2 - getTextWidth(g_model.flightModeData[mixerCurrentFlightMode].name, + sizeof(g_model.flightModeData[mixerCurrentFlightMode].name), + ZCHAR | SMLSIZE) / 2, + 237, + g_model.flightModeData[mixerCurrentFlightMode].name, + sizeof(g_model.flightModeData[mixerCurrentFlightMode].name), ZCHAR | SMLSIZE); + } + + if (persistentData->options[2].boolValue) { + // Pots and rear sliders positions + drawMainPots(); + } + + if (persistentData->options[3].boolValue) { + // Trims + drawTrims(mixerCurrentFlightMode); + } + + if (persistentData->options[4].boolValue) { + lcdSetColor(persistentData->options[5].unsignedValue); + lcdDrawSolidFilledRect(50, 50, 180, 170, CUSTOM_COLOR); + } + + if (persistentData->options[6].boolValue) { + lcdSetColor(persistentData->options[7].unsignedValue); + lcdDrawSolidFilledRect(250, 50, 180, 170, CUSTOM_COLOR); + } + + Layout::refresh(setup); +} + +BaseLayoutFactory layout2x4("Layout2x4", "", Layout2x4::options); diff --git a/radio/src/gui/horus/lcd.cpp b/radio/src/gui/horus/lcd.cpp index 1d1407c05..4450e63d7 100644 --- a/radio/src/gui/horus/lcd.cpp +++ b/radio/src/gui/horus/lcd.cpp @@ -104,7 +104,7 @@ void lcdPutFontPattern(coord_t x, coord_t y, const uint8_t * font, const uint16_ { coord_t offset = spec[index]; coord_t width = spec[index+1] - offset; - lcdDrawBitmapPattern(x, y, font, flags, offset, width); + if (width > 0) lcdDrawBitmapPattern(x, y, font, flags, offset, width); lcdNextPos = x + width; } @@ -152,9 +152,10 @@ int getBitmapScale(const uint8_t * bmp, int dstWidth, int dstHeight) return min(widthScale, heightScale); } -int getTextWidth(const pm_char * s, int len, LcdFlags flags) +int getTextWidth(const char * s, int len, LcdFlags flags) { const uint16_t * specs = fontspecsTable[FONTSIZE(flags) >> 8]; + int result = 0; for (int i=0; len==0 || i= MIXSRC_FIRST_SWITCH && idx < MIXSRC_FIRST_LOGICAL_SWITCH) { - idx = idx-MIXSRC_FIRST_SWITCH; - if (ZEXIST(g_eeGeneral.switchNames[idx])) - lcdDrawSizedText(x, y, g_eeGeneral.switchNames[idx], LEN_SWITCH_NAME, ZCHAR|att); - else - lcdDrawTextAtIndex(x, y, STR_VSRCRAW, idx+MIXSRC_FIRST_SWITCH-MIXSRC_Rud+1, att); - } - else if (idx < MIXSRC_SW1) - lcdDrawTextAtIndex(x, y, STR_VSRCRAW, idx-MIXSRC_Rud+1, att); - else if (idx <= MIXSRC_LAST_LOGICAL_SWITCH) - putsSwitches(x, y, SWSRC_SW1+idx-MIXSRC_SW1, att); - else if (idx < MIXSRC_CH1) - drawStringWithIndex(x, y, STR_PPM_TRAINER, idx-MIXSRC_FIRST_TRAINER+1, att); - else if (idx <= MIXSRC_LAST_CH) { - drawStringWithIndex(x, y, STR_CH, idx-MIXSRC_CH1+1, att); -#if 0 - if (ZEXIST(g_model.limitData[idx-MIXSRC_CH1].name) && (att & STREXPANDED)) { - lcdDrawChar(lcdNextPos, y, ' ', att); - lcdDrawSizedText(lcdNextPos+3, y, g_model.limitData[idx-MIXSRC_CH1].name, LEN_CHANNEL_NAME, ZCHAR|att); - } -#endif - } - else if (idx <= MIXSRC_LAST_GVAR) - drawStringWithIndex(x, y, STR_GV, idx-MIXSRC_GVAR1+1, att); - else if (idx < MIXSRC_FIRST_TELEM) { - lcdDrawTextAtIndex(x, y, STR_VSRCRAW, idx-MIXSRC_Rud+1-NUM_LOGICAL_SWITCH-NUM_TRAINER-NUM_CHNOUT-MAX_GVARS, att); - } - else { - idx -= MIXSRC_FIRST_TELEM; - div_t qr = div(idx, 3); - char s[32]; - s[0] = '\321'; - int pos = 1 + zchar2str(&s[1], g_model.telemetrySensors[qr.quot].label, sizeof(g_model.telemetrySensors[qr.quot].label)); - if (qr.rem) s[pos++] = (qr.rem==2 ? '+' : '-'); - s[pos] = '\0'; - lcdDrawText(x, y, s, att); - } -} - -void putsChnLetter(coord_t x, coord_t y, uint8_t idx, LcdFlags att) -{ - lcdDrawTextAtIndex(x, y, STR_RETA123, idx-1, att); -} - -void putsModelName(coord_t x, coord_t y, char *name, uint8_t id, LcdFlags att) -{ - uint8_t len = sizeof(g_model.header.name); - while (len>0 && !name[len-1]) --len; - if (len==0) { - drawStringWithIndex(x, y, STR_MODEL, id+1, att|LEADING0); - } - else { - lcdDrawSizedText(x, y, name, sizeof(g_model.header.name), ZCHAR|att); - } -} - char * getStringAtIndex(char * dest, const char * s, int idx) { uint8_t len = s[0]; @@ -603,6 +511,104 @@ char * getSwitchString(char * dest, swsrc_t idx) return dest; } +char * getSourceString(char * dest, mixsrc_t idx) +{ + if (idx == MIXSRC_NONE) { + return getStringAtIndex(dest, STR_VSRCRAW, 0); + } + else if (idx <= MIXSRC_LAST_INPUT) { + idx -= MIXSRC_FIRST_INPUT; + *dest++ = '\314'; + if (ZEXIST(g_model.inputNames[idx])) { + zchar2str(dest, g_model.inputNames[idx], LEN_INPUT_NAME); + dest[LEN_INPUT_NAME] = '\0'; + } + else { + strAppendUnsigned(dest, idx, 2); + } + } + else if (idx <= MIXSRC_LAST_LUA) { +#if defined(LUA_MODEL_SCRIPTS) + div_t qr = div(idx-MIXSRC_FIRST_LUA, MAX_SCRIPT_OUTPUTS); + if (qr.quot < MAX_SCRIPTS && qr.rem < scriptInputsOutputs[qr.quot].outputsCount) { + *dest++ = '\322'; + // *dest++ = '1'+qr.quot; + strncpy(dest, scriptInputsOutputs[qr.quot].outputs[qr.rem].name, sizeof(scriptInputsOutputs[qr.quot].outputs[qr.rem].name)); + dest[sizeof(scriptInputsOutputs[qr.quot].outputs[qr.rem].name)] = '\0'; + } +#endif + } + else if (idx <= MIXSRC_LAST_POT) { + idx -= MIXSRC_Rud; + if (ZEXIST(g_eeGeneral.anaNames[idx])) { + zchar2str(dest, g_eeGeneral.anaNames[idx], LEN_ANA_NAME); + dest[LEN_ANA_NAME] = '\0'; + } + else { + getStringAtIndex(dest, STR_VSRCRAW, idx + 1); + } + } + else if (idx >= MIXSRC_FIRST_SWITCH && idx <= MIXSRC_LAST_SWITCH) { + idx -= MIXSRC_FIRST_SWITCH; + if (ZEXIST(g_eeGeneral.switchNames[idx])) { + zchar2str(dest, g_eeGeneral.switchNames[idx], LEN_SWITCH_NAME); + dest[LEN_SWITCH_NAME] = '\0'; + } + else { + getStringAtIndex(dest, STR_VSRCRAW, idx + MIXSRC_FIRST_SWITCH - MIXSRC_Rud + 1); + } + } + else if (idx <= MIXSRC_LAST_LOGICAL_SWITCH) { + getSwitchString(dest, SWSRC_SW1 + idx - MIXSRC_SW1); + } + else if (idx <= MIXSRC_LAST_TRAINER) { + getStringWithIndex(dest, STR_PPM_TRAINER, idx - MIXSRC_FIRST_TRAINER + 1); + } + else if (idx <= MIXSRC_LAST_CH) { + getStringWithIndex(dest, STR_CH, idx - MIXSRC_CH1 + 1); + } + else if (idx <= MIXSRC_LAST_GVAR) { + getStringWithIndex(dest, STR_GV, idx - MIXSRC_GVAR1 + 1); + } + else if (idx < MIXSRC_FIRST_TELEM) { + getStringAtIndex(dest, STR_VSRCRAW, idx-MIXSRC_Rud+1-NUM_LOGICAL_SWITCH-NUM_TRAINER-NUM_CHNOUT-MAX_GVARS); + } + else { + idx -= MIXSRC_FIRST_TELEM; + div_t qr = div(idx, 3); + dest[0] = '\321'; + int pos = 1 + zchar2str(&dest[1], g_model.telemetrySensors[qr.quot].label, sizeof(g_model.telemetrySensors[qr.quot].label)); + if (qr.rem) dest[pos++] = (qr.rem==2 ? '+' : '-'); + dest[pos] = '\0'; + } + + return dest; +} + +void putsMixerSource(coord_t x, coord_t y, uint8_t idx, LcdFlags flags) +{ + char s[16]; + getSourceString(s, idx); + lcdDrawText(x, y, s, flags); +} + +void putsChnLetter(coord_t x, coord_t y, uint8_t idx, LcdFlags att) +{ + lcdDrawTextAtIndex(x, y, STR_RETA123, idx-1, att); +} + +void putsModelName(coord_t x, coord_t y, char *name, uint8_t id, LcdFlags att) +{ + uint8_t len = sizeof(g_model.header.name); + while (len>0 && !name[len-1]) --len; + if (len==0) { + drawStringWithIndex(x, y, STR_MODEL, id+1, att|LEADING0); + } + else { + lcdDrawSizedText(x, y, name, sizeof(g_model.header.name), ZCHAR|att); + } +} + void putsSwitches(coord_t x, coord_t y, swsrc_t idx, LcdFlags flags) { char s[8]; @@ -785,6 +791,21 @@ void lcdSetContrast() lcdSetRefVolt(g_eeGeneral.contrast); } +void lcdInvertRect(coord_t x, scoord_t y, coord_t w, coord_t h, LcdFlags att) +{ + display_t color = lcdColorTable[COLOR_IDX(att)]; + COLOR_SPLIT(color, red, green, blue); + + for (int i=y; i> 4) /* rect, square flags */ -#define ROUND 0x02 +#define ROUND 0x04 /* telemetry flags */ #define NO_UNIT 0x40 @@ -112,6 +111,7 @@ enum LcdColorIndex CURVE_CURSOR_COLOR_INDEX, HEADER_BGCOLOR_INDEX, TITLE_BGCOLOR_INDEX, + CUSTOM_COLOR_INDEX, LCD_COLOR_COUNT }; @@ -141,6 +141,7 @@ void lcdColorsInit(); #define CURVE_CURSOR_COLOR COLOR(CURVE_CURSOR_COLOR_INDEX) #define TITLE_BGCOLOR COLOR(TITLE_BGCOLOR_INDEX) #define HEADER_BGCOLOR COLOR(HEADER_BGCOLOR_INDEX) +#define CUSTOM_COLOR COLOR(CUSTOM_COLOR_INDEX) #define COLOR_IDX(att) uint8_t((att) >> 16) @@ -233,19 +234,26 @@ inline void lcdDrawAlphaPixel(coord_t x, coord_t y, uint8_t opacity, uint16_t co } #if !defined(SIMU) -inline void lcdDrawSolidFilledRect(coord_t x, scoord_t y, coord_t w, coord_t h, LcdFlags att) +inline void lcdDrawSolidFilledRect(coord_t x, scoord_t y, coord_t w, coord_t h, LcdFlags flags) { - lcdDrawSolidFilledRectDMA(x, y, w, h, lcdColorTable[COLOR_IDX(att)]); + lcdDrawSolidFilledRectDMA(x, y, w, h, lcdColorTable[COLOR_IDX(flags)]); } #else -void lcdDrawSolidFilledRect(coord_t x, scoord_t y, coord_t w, coord_t h, LcdFlags att); +void lcdDrawSolidFilledRect(coord_t x, scoord_t y, coord_t w, coord_t h, LcdFlags flags); #endif +inline void lcdSetColor(uint16_t color) +{ + lcdColorTable[CUSTOM_COLOR_INDEX] = color; +} + inline void lcdClear() { lcdDrawSolidFilledRect(0, 0, LCD_W, LCD_H, 0); } +void lcdInvertRect(coord_t x, scoord_t y, coord_t w, coord_t h, LcdFlags flags); + inline void lcdDrawSolidHorizontalLine(coord_t x, scoord_t y, coord_t w, LcdFlags att) { lcdDrawSolidFilledRect(x, y, w, 1, att); @@ -265,7 +273,7 @@ inline void lcdDrawSolidRect(coord_t x, scoord_t y, coord_t w, coord_t h, LcdFla lcdDrawSolidHorizontalLine(x, y+h-1, w, att); } -void lcdDrawFilledRect(coord_t x, scoord_t y, coord_t w, coord_t h, uint8_t pat, LcdFlags att); +void lcdDrawFilledRect(coord_t x, scoord_t y, coord_t w, coord_t h, uint8_t pat, LcdFlags att=0); void lcdDrawBlackOverlay(); void lcdDrawRect(coord_t x, coord_t y, coord_t w, coord_t h, uint8_t pat=SOLID, LcdFlags att=0); void lcdDrawCircle(int x0, int y0, int radius); diff --git a/radio/src/gui/horus/menu_general_calib.cpp b/radio/src/gui/horus/menu_general_calib.cpp index 91c62e7fe..50c0a37db 100644 --- a/radio/src/gui/horus/menu_general_calib.cpp +++ b/radio/src/gui/horus/menu_general_calib.cpp @@ -57,7 +57,7 @@ void drawPots() bool menuCommonCalib(evt_t event) { - drawSubmenuTemplate(NULL, 0, OPTION_MENU_NO_FOOTER); + drawScreenTemplate(NULL, LBM_CALIBRATION_ICON, OPTION_MENU_NO_FOOTER); for (uint8_t i=0; i> 1; diff --git a/radio/src/gui/horus/menu_general_sdmanager.cpp b/radio/src/gui/horus/menu_general_sdmanager.cpp index 3fdeea74d..95cebd4e2 100644 --- a/radio/src/gui/horus/menu_general_sdmanager.cpp +++ b/radio/src/gui/horus/menu_general_sdmanager.cpp @@ -30,7 +30,7 @@ int lastBitmap; bool menuGeneralSdManagerInfo(evt_t event) { - SIMPLE_SUBMENU(STR_SD_INFO_TITLE, 1, DEFAULT_SCROLLBAR_X); + SIMPLE_SUBMENU(STR_SD_INFO_TITLE, LBM_SD_BROWSER_ICON, 1); lcdDrawText(MENUS_MARGIN_LEFT, 2*FH, STR_SD_TYPE); lcdDrawText(100, 2*FH, SD_IS_HC() ? STR_SDHC_CARD : STR_SD_CARD); diff --git a/radio/src/gui/horus/menu_model_curves.cpp b/radio/src/gui/horus/menu_model_curves.cpp index 6f79c6c7a..e1941026c 100644 --- a/radio/src/gui/horus/menu_model_curves.cpp +++ b/radio/src/gui/horus/menu_model_curves.cpp @@ -98,7 +98,7 @@ void displayPresetChoice(evt_t event) } } -void onCurveOneMenu(const char *result) +void onCurveOneMenu(const char * result) { if (result == STR_CURVE_PRESET) { POPUP_INPUT(STR_PRESET, displayPresetChoice, 0, -4, 4); @@ -138,7 +138,7 @@ bool menuModelCurveOne(evt_t event) CurveData & crv = g_model.curves[s_curveChan]; int8_t * points = curveAddress(s_curveChan); - SUBMENU_WITH_OPTIONS(STR_MENUCURVE, crv.type==CURVE_TYPE_CUSTOM ? 6 : 5, OPTION_MENU_NO_FOOTER, 0, { 0, 0, 0, 0, uint8_t(5+crv.points-1), uint8_t(5+crv.points-1) }); + SUBMENU_WITH_OPTIONS(STR_MENUCURVE, LBM_CURVES_ICON, crv.type==CURVE_TYPE_CUSTOM ? 6 : 5, OPTION_MENU_NO_FOOTER, { 0, 0, 0, 0, uint8_t(5+crv.points-1), uint8_t(5+crv.points-1) }); drawStringWithIndex(50, 3+FH, STR_CV, s_curveChan+1, MENU_TITLE_COLOR); lcdDrawSolidFilledRect(0, MENU_FOOTER_TOP, 250, MENU_FOOTER_HEIGHT, HEADER_BGCOLOR); diff --git a/radio/src/gui/horus/menu_model_custom_scripts.cpp b/radio/src/gui/horus/menu_model_custom_scripts.cpp index 27a84f301..e86b37ac9 100644 --- a/radio/src/gui/horus/menu_model_custom_scripts.cpp +++ b/radio/src/gui/horus/menu_model_custom_scripts.cpp @@ -53,7 +53,7 @@ bool menuModelCustomScriptOne(evt_t event) // drawStringWithIndex(lcdLastPos+FW, 0, "LUA", s_currIdx+1, 0); - SUBMENU(STR_MENUCUSTOMSCRIPTS, 3+scriptInputsOutputs[s_currIdx].inputsCount, 0, { 0, 0, LABEL(inputs), 0/*repeated*/ }); + SUBMENU(STR_MENUCUSTOMSCRIPTS, LBM_LUA_SCRIPTS_ICON, 3+scriptInputsOutputs[s_currIdx].inputsCount, { 0, 0, LABEL(inputs), 0/*repeated*/ }); int8_t sub = menuVerticalPosition; diff --git a/radio/src/gui/horus/menu_model_inputs.cpp b/radio/src/gui/horus/menu_model_inputs.cpp index 40bb714f7..ef2be1e89 100644 --- a/radio/src/gui/horus/menu_model_inputs.cpp +++ b/radio/src/gui/horus/menu_model_inputs.cpp @@ -175,7 +175,7 @@ bool menuModelExpoOne(evt_t event) { ExpoData * ed = expoAddress(s_currIdx); - SUBMENU_WITH_OPTIONS(STR_MENUINPUTS, EXPO_FIELD_MAX, OPTION_MENU_NO_FOOTER, 0, { 0, 0, (ed->srcRaw >= MIXSRC_FIRST_TELEM ? (uint8_t)1 : (uint8_t)0), 0, 0, CASE_CURVES(CURVE_ROWS) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/}); + SUBMENU_WITH_OPTIONS(STR_MENUINPUTS, LBM_INPUTS_ICON, EXPO_FIELD_MAX, OPTION_MENU_NO_FOOTER|OPTION_MENU_NO_SCROLLBAR, { 0, 0, (ed->srcRaw >= MIXSRC_FIRST_TELEM ? (uint8_t)1 : (uint8_t)0), 0, 0, CASE_CURVES(CURVE_ROWS) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/}); lcdDrawSizedText(50, 3+FH, g_model.inputNames[ed->chn], LEN_INPUT_NAME, ZCHAR|MENU_TITLE_COLOR); lcdDrawSolidFilledRect(0, MENU_FOOTER_TOP, 230, MENU_FOOTER_HEIGHT, HEADER_BGCOLOR); diff --git a/radio/src/gui/horus/menu_model_mixes.cpp b/radio/src/gui/horus/menu_model_mixes.cpp index d940b6c0a..cc2adc260 100644 --- a/radio/src/gui/horus/menu_model_mixes.cpp +++ b/radio/src/gui/horus/menu_model_mixes.cpp @@ -174,7 +174,7 @@ bool menuModelMixOne(evt_t event) { MixData * md2 = mixAddress(s_currIdx) ; - SUBMENU(STR_MIXER, MIX_FIELD_COUNT, 0, { 0, 0, 0, 0, 0, CASE_CURVES(1) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/ }); + SUBMENU_WITH_OPTIONS(STR_MIXER, LBM_MIXER_ICON, MIX_FIELD_COUNT, OPTION_MENU_NO_SCROLLBAR, { 0, 0, 0, 0, 0, CASE_CURVES(1) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/ }); putsChn(50, 3+FH, md2->destCh+1, MENU_TITLE_COLOR); // The separation line between 2 columns diff --git a/radio/src/gui/horus/menu_model_setup.cpp b/radio/src/gui/horus/menu_model_setup.cpp index c8f988d8b..4e9c28f44 100644 --- a/radio/src/gui/horus/menu_model_setup.cpp +++ b/radio/src/gui/horus/menu_model_setup.cpp @@ -80,8 +80,8 @@ enum menuModelSetupItems { #define FIELD_PROTOCOL_MAX 1 #define MODEL_SETUP_2ND_COLUMN 200 -#define MODEL_SETUP_BIND_OFS 40 -#define MODEL_SETUP_RANGE_OFS 80 +#define MODEL_SETUP_BIND_OFS 30 +#define MODEL_SETUP_RANGE_OFS 60 #define MODEL_SETUP_SET_FAILSAFE_OFS 100 void onModelSetupBitmapMenu(const char *result) @@ -615,8 +615,8 @@ bool menuModelSetup(evt_t event) if (IS_MODULE_PPM(moduleIdx)) { lcdDrawText(MENUS_MARGIN_LEFT, y, STR_PPMFRAME); lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, (int16_t)moduleData.ppmFrameLength*5 + 225, (menuHorizontalPosition<=0 ? attr : 0) | PREC1|LEFT, 0, NULL, STR_MS); - lcdDrawNumber(MODEL_SETUP_2ND_COLUMN+70, y, (moduleData.ppmDelay*50)+300, (CURSOR_ON_LINE() || menuHorizontalPosition==1) ? attr : 0, 0, NULL, "us"); - lcdDrawText(MODEL_SETUP_2ND_COLUMN+90, y, moduleData.ppmPulsePol ? "+" : "-", (CURSOR_ON_LINE() || menuHorizontalPosition==2) ? attr : 0); + lcdDrawNumber(MODEL_SETUP_2ND_COLUMN+90, y, (moduleData.ppmDelay*50)+300, (CURSOR_ON_LINE() || menuHorizontalPosition==1) ? attr : 0, 0, NULL, "us"); + lcdDrawText(MODEL_SETUP_2ND_COLUMN+120, y, moduleData.ppmPulsePol ? "+" : "-", (CURSOR_ON_LINE() || menuHorizontalPosition==2) ? attr : 0); if (attr && s_editMode>0) { switch (menuHorizontalPosition) { @@ -648,8 +648,8 @@ bool menuModelSetup(evt_t event) if (attr && l_posHorz==0 && s_editMode>0) { CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId[moduleIdx], IS_MODULE_DSM2(moduleIdx) ? 20 : 63); } - drawButton(MODEL_SETUP_2ND_COLUMN+xOffsetBind, y-2, STR_MODULE_BIND, l_posHorz==1 ? attr : 0); - drawButton(MODEL_SETUP_2ND_COLUMN+MODEL_SETUP_RANGE_OFS+xOffsetBind, y-2, STR_MODULE_RANGE, l_posHorz==2 ? attr : 0); + drawButton(MODEL_SETUP_2ND_COLUMN+xOffsetBind, y, STR_MODULE_BIND, l_posHorz==1 ? attr : 0); + drawButton(MODEL_SETUP_2ND_COLUMN+MODEL_SETUP_RANGE_OFS+xOffsetBind, y, STR_MODULE_RANGE, l_posHorz==2 ? attr : 0); uint8_t newFlag = 0; if (attr && l_posHorz>0 && s_editMode>0) { if (l_posHorz == 1) diff --git a/radio/src/gui/horus/menu_model_telemetry.cpp b/radio/src/gui/horus/menu_model_telemetry.cpp index b67f0658e..74c505b7f 100644 --- a/radio/src/gui/horus/menu_model_telemetry.cpp +++ b/radio/src/gui/horus/menu_model_telemetry.cpp @@ -127,7 +127,7 @@ bool menuModelSensor(evt_t event) { TelemetrySensor * sensor = &g_model.telemetrySensors[s_currIdx]; - SUBMENU("SENSOR", SENSOR_FIELD_MAX, DEFAULT_SCROLLBAR_X, { 0, 0, sensor->type == TELEM_TYPE_CALCULATED ? (uint8_t)0 : (uint8_t)1, SENSOR_UNIT_ROWS, SENSOR_PREC_ROWS, SENSOR_PARAM1_ROWS, SENSOR_PARAM2_ROWS, SENSOR_PARAM3_ROWS, SENSOR_PARAM4_ROWS, 0, 0, 0, 0, 0 }); + SUBMENU("SENSOR", LBM_TELEMETRY_ICON, SENSOR_FIELD_MAX, { 0, 0, sensor->type == TELEM_TYPE_CALCULATED ? (uint8_t)0 : (uint8_t)1, SENSOR_UNIT_ROWS, SENSOR_PREC_ROWS, SENSOR_PARAM1_ROWS, SENSOR_PARAM2_ROWS, SENSOR_PARAM3_ROWS, SENSOR_PARAM4_ROWS, 0, 0, 0, 0, 0 }); lcdDrawNumber(lcdNextPos, 3, s_currIdx+1, MENU_TITLE_COLOR|LEFT); putsTelemetryChannelValue(50, 3+FH, s_currIdx, getValue(MIXSRC_FIRST_TELEM+3*s_currIdx), MENU_TITLE_COLOR|LEFT); diff --git a/radio/src/gui/horus/menus.h b/radio/src/gui/horus/menus.h index 6b8b2265a..b18988402 100644 --- a/radio/src/gui/horus/menus.h +++ b/radio/src/gui/horus/menus.h @@ -266,12 +266,6 @@ bool check_submenu_simple(check_event_t event, uint8_t maxrow); #define MENU_TAB(...) const uint8_t mstate_tab[] = __VA_ARGS__ -#define MENU_ONE_PAGE(title, lines_count, scrollbar_X, ...) \ - MENU_TAB(__VA_ARGS__); \ - if (event == EVT_ENTRY || event == EVT_ENTRY_UP) TRACE("Menu %s displayed ...", title); \ - if (!check(event, 0, NULL, 0, mstate_tab, DIM(mstate_tab)-1, lines_count)) return false; \ - drawSubmenuTemplate(title, scrollbar_X); \ - #define MENU(title, tab, menu, lines_count, scrollbar_X, ...) \ MENU_TAB(__VA_ARGS__); \ if (event == EVT_ENTRY || event == EVT_ENTRY_UP) TRACE("Menu %s displayed ...", title); \ @@ -283,22 +277,22 @@ bool check_submenu_simple(check_event_t event, uint8_t maxrow); if (!check_simple(event, menu, tab, DIM(tab), lines_count)) return false; \ drawMenuTemplate(title, scrollbar_X); \ -#define SUBMENU(title, lines_count, scrollbar_X, ...) \ +#define SUBMENU(title, icon, lines_count, ...) \ MENU_TAB(__VA_ARGS__); \ if (!check(event, 0, NULL, 0, mstate_tab, DIM(mstate_tab)-1, lines_count)) return false; \ - drawSubmenuTemplate(title, scrollbar_X); + drawScreenTemplate(title, icon); -#define SUBMENU_WITH_OPTIONS(title, lines_count, options, scrollbar_X, ...) \ +#define SUBMENU_WITH_OPTIONS(title, icon, lines_count, options, ...) \ MENU_TAB(__VA_ARGS__); \ if (!check(event, 0, NULL, 0, mstate_tab, DIM(mstate_tab)-1, lines_count)) return false; \ - drawSubmenuTemplate(title, scrollbar_X, options); + drawScreenTemplate(title, icon, options); #define SIMPLE_SUBMENU_NOTITLE(lines_count) \ if (!check_submenu_simple(event, lines_count)) return false -#define SIMPLE_SUBMENU(title, lines_count, scrollbar_X) \ +#define SIMPLE_SUBMENU(title, icon, lines_count) \ SIMPLE_SUBMENU_NOTITLE(lines_count); \ - drawSubmenuTemplate(title, scrollbar_X) + drawScreenTemplate(title, icon) typedef int select_menu_value_t; diff --git a/radio/src/gui/horus/screens_setup.cpp b/radio/src/gui/horus/screens_setup.cpp index 1a51e377b..1280afc0e 100644 --- a/radio/src/gui/horus/screens_setup.cpp +++ b/radio/src/gui/horus/screens_setup.cpp @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -18,249 +18,196 @@ * GNU General Public License for more details. */ -#include "../../opentx.h" +#include "opentx.h" -#define SETUP_SCREEN_COLUMN2 200 -#define SETUP_SCREEN_COLUMN3 275 -#define SETUP_SCREEN_COLUMN4 350 +Layout * currentScreen; +Widget * currentWidget; -enum menuSetupScreensViewItems +#define SCREENS_SETUP_2ND_COLUMN 200 + +void onWidgetChoiceMenu(const char * result) { - ITEM_SETUP_TOP_BAR_LABEL, - ITEM_SETUP_TOP_BAR_VOLTAGE, - ITEM_SETUP_TOP_BAR_ALTITUDE, - ITEM_SETUP_SCREEN_LABEL1, - ITEM_SETUP_SCREEN_LINE1, - ITEM_SETUP_SCREEN_LINE2, - ITEM_SETUP_SCREEN_LINE3, - ITEM_SETUP_SCREEN_LINE4, - ITEM_SETUP_SCREEN_LABEL2, - ITEM_SETUP_SCREEN_LINE5, - ITEM_SETUP_SCREEN_LINE6, - ITEM_SETUP_SCREEN_LINE7, - ITEM_SETUP_SCREEN_LINE8, - ITEM_SETUP_SCREEN_LABEL3, - ITEM_SETUP_SCREEN_LINE9, - ITEM_SETUP_SCREEN_LINE10, - ITEM_SETUP_SCREEN_LINE11, - ITEM_SETUP_SCREEN_LINE12, - ITEM_SETUP_SCREEN_LABEL4, - ITEM_SETUP_SCREEN_LINE13, - ITEM_SETUP_SCREEN_LINE14, - ITEM_SETUP_SCREEN_LINE15, - ITEM_SETUP_SCREEN_LINE16, - ITEM_SETUP_SCREEN_MAX -}; + customScreens[0]->setWidget(menuVerticalPosition, result); +} -#if defined(LUA) - #define SCREEN_TYPE_ROWS 1 - #define SETUP_SCREEN_LINE(x) ((TELEMETRY_SCREEN_TYPE(x) == TELEMETRY_SCREEN_TYPE_NONE || TELEMETRY_SCREEN_TYPE(x) == TELEMETRY_SCREEN_TYPE_SCRIPT) ? HIDDEN_ROW : (uint8_t)2) -#else - #define SCREEN_TYPE_ROWS 0 - #define SETUP_SCREEN_LINE(x) (TELEMETRY_SCREEN_TYPE(x) == TELEMETRY_SCREEN_TYPE_NONE ? HIDDEN_ROW : (uint8_t)2) -#endif - -#define SETUP_SCREEN_ROWS(x) SCREEN_TYPE_ROWS, SETUP_SCREEN_LINE(x), SETUP_SCREEN_LINE(x), SETUP_SCREEN_LINE(x), SETUP_SCREEN_LINE(x) -#define TELEMETRY_CURRENT_SCREEN(k) (k < ITEM_SETUP_SCREEN_LABEL2 ? 0 : (k < ITEM_SETUP_SCREEN_LABEL3 ? 1 : (k < ITEM_SETUP_SCREEN_LABEL4 ? 2 : 3))) - -#if defined(LUA) -void onSetupScriptFileSelectionMenu(const char * result) +ZoneOptionValue editZoneOption(coord_t y, const ZoneOption * option, ZoneOptionValue value, LcdFlags attr, evt_t event) { - int screenIndex = TELEMETRY_CURRENT_SCREEN(menuVerticalPosition); + lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, option->name); - if (result == STR_UPDATE_LIST) { - if (!sdListFiles(SCRIPTS_TELEM_PATH, SCRIPTS_EXT, sizeof(g_model.frsky.screens[screenIndex].script.file), NULL)) { - POPUP_WARNING(STR_NO_SCRIPTS_ON_SD); + if (option->type == ZoneOption::Bool) { + value.boolValue = editCheckBox(value.boolValue, SCREENS_SETUP_2ND_COLUMN, y, attr, event); + } + else if (option->type == ZoneOption::Integer) { + lcdDrawNumber(SCREENS_SETUP_2ND_COLUMN, y, value.signedValue, attr | LEFT); + if (attr) { + CHECK_INCDEC_MODELVAR(event, value.signedValue, -30000, 30000); } } - else { - // The user choosed a file in the list - memcpy(g_model.frsky.screens[screenIndex].script.file, result, sizeof(g_model.frsky.screens[screenIndex].script.file)); - storageDirty(EE_MODEL); - LUA_LOAD_MODEL_SCRIPTS(); + else if (option->type == ZoneOption::String) { + editName(SCREENS_SETUP_2ND_COLUMN, y, value.stringValue, sizeof(value.stringValue), event, attr|EE_MODEL); + } + else if (option->type == ZoneOption::TextSize) { + lcdDrawTextAtIndex(SCREENS_SETUP_2ND_COLUMN, y, "\010StandardTiny\0 Small\0 Mid\0 Double", value.unsignedValue, attr); + if (attr) { + value.unsignedValue = checkIncDec(event, value.unsignedValue, 0, 4, EE_MODEL); + } + } + else if (option->type == ZoneOption::Timer) { + drawStringWithIndex(SCREENS_SETUP_2ND_COLUMN, y, STR_TIMER, value.unsignedValue + 1, attr); + if (attr) { + value.unsignedValue = checkIncDec(event, value.unsignedValue, 0, MAX_TIMERS - 1, EE_MODEL); + } + } + else if (option->type == ZoneOption::Source) { + putsMixerSource(SCREENS_SETUP_2ND_COLUMN, y, value.unsignedValue, attr); + if (attr) { + CHECK_INCDEC_MODELSOURCE(event, value.unsignedValue, 1, MIXSRC_LAST); + } + } + else if (option->type == ZoneOption::Color) { + lcdSetColor(value.unsignedValue); + lcdDrawSolidRect(SCREENS_SETUP_2ND_COLUMN, y, 40, 15, attr ? TEXT_INVERTED_BGCOLOR : TEXT_COLOR); + lcdDrawSolidFilledRect(SCREENS_SETUP_2ND_COLUMN + 1, y + 1, 38, 13, CUSTOM_COLOR); + if (attr) { + CHECK_INCDEC_MODELVAR(event, value.unsignedValue, 0, 65535); + } + } + return value; +} + +bool menuWidgetSettings(evt_t event) +{ + linesCount = 0; + const ZoneOption * options = currentWidget->getFactory()->getOptions(); + for (const ZoneOption * option = options; option->name; option++) { + linesCount++; + } + + SUBMENU_WITH_OPTIONS("Widget settings", LBM_MAINVIEWS_ICON, linesCount, OPTION_MENU_TITLE_BAR, { 0, 0, 0 }); + + for (int i=0; i0) ? BLINK|INVERS : INVERS); + LcdFlags attr = (menuVerticalPosition == k ? blink : 0); + if (k < linesCount) { + const ZoneOption * option = &options[k]; + ZoneOptionValue value = currentWidget->getOptionValue(k); + value = editZoneOption(y, option, value, attr, event); + if (attr) { + currentWidget->setOptionValue(k, value); + } + } + } + + return true; +} + +void onZoneMenu(const char * result) +{ + if (result == STR_SELECT_WIDGET) { + for (unsigned int i=0; igetName()); + } + popupMenuHandler = onWidgetChoiceMenu; + } + else if (result == STR_WIDGET_SETTINGS) { + currentWidget = currentScreen->getWidget(menuVerticalPosition); + pushMenu(menuWidgetSettings); + } + else if (result == STR_REMOVE_WIDGET) { + currentScreen->setWidget(menuVerticalPosition, NULL); } } -#endif + +bool menuSetupWidgets(evt_t event) +{ + switch (event) { + case EVT_ENTRY: + menuVerticalPosition = 0; + break; + case EVT_KEY_BREAK(KEY_EXIT): + popMenu(); + return false; + } + + currentScreen->refresh(true); + + for (int i=currentScreen->getZonesCount()-1; i>=0; i--) { + Zone zone = currentScreen->getZone(i); + if (menuVerticalPosition == i) { + lcdDrawSolidRect(zone.x, zone.y, zone.w, zone.h, TEXT_INVERTED_COLOR); + lcdDrawSolidRect(zone.x-1, zone.y-1, zone.w+2, zone.h+2, TEXT_INVERTED_COLOR); + if (event == EVT_KEY_BREAK(KEY_ENTER)) { + Widget * widget = currentScreen->getWidget(i); + if (widget) { + POPUP_MENU_ADD_ITEM(STR_SELECT_WIDGET); + if (widget->getFactory()->getOptions()) + POPUP_MENU_ADD_ITEM(STR_WIDGET_SETTINGS); + POPUP_MENU_ADD_ITEM(STR_REMOVE_WIDGET); + popupMenuHandler = onZoneMenu; + } + else { + onZoneMenu(STR_SELECT_WIDGET); + } + } + } + else { + lcdDrawRect(zone.x, zone.y, zone.w, zone.h, DOTTED, TEXT_INVERTED_COLOR); + } + } + navigate(event, currentScreen->getZonesCount(), currentScreen->getZonesCount(), 1); + return true; +} bool menuSetupScreensView(evt_t event) { - MENU_ONE_PAGE("Setup screens", ITEM_SETUP_SCREEN_MAX, DEFAULT_SCROLLBAR_X, { LABEL(TopBar), 0, 0, SETUP_SCREEN_ROWS(0), SETUP_SCREEN_ROWS(1), SETUP_SCREEN_ROWS(2), SETUP_SCREEN_ROWS(3) }); + currentScreen = customScreens[0]; + + unsigned int layoutIndex = 0; + for (unsigned int i=0; igetFactory()) { + layoutIndex = i; + break; + } + } + + linesCount = 1; + const ZoneOption * options = currentScreen->getFactory()->getOptions(); + for (const ZoneOption * option = options; option->name; option++) { + linesCount++; + } + + SUBMENU_WITH_OPTIONS("Main views setup", LBM_MAINVIEWS_ICON, linesCount, OPTION_MENU_TITLE_BAR, { 0, 0, 0 }); for (int i=0; i= (int) DIM(mstate_tab)) { - return true; + LcdFlags blink = ((s_editMode>0) ? BLINK|INVERS : INVERS); + LcdFlags attr = (menuVerticalPosition == k ? blink : 0); + if (k == 0) { + lcdDrawText(MENUS_MARGIN_LEFT, y, "Layout"); + lcdDrawText(SCREENS_SETUP_2ND_COLUMN, y, currentScreen->getFactory()->getName(), attr); + if (attr) { + layoutIndex = checkIncDec(event, layoutIndex, 0, countRegisteredLayouts-1, EE_MODEL); + if (checkIncDec_Ret) { + customScreens[0] = registeredLayouts[layoutIndex]->create(&g_model.screenData[0].layoutData); + strncpy(g_model.screenData[0].layoutName, customScreens[0]->getFactory()->getName(), sizeof(g_model.screenData[0].layoutName)); + } + else if (event == EVT_KEY_LONG(KEY_ENTER)) { + pushMenu(menuSetupWidgets); } } } - - LcdFlags blink = ((s_editMode > 0) ? BLINK | INVERS : INVERS); - LcdFlags attr = (menuVerticalPosition == k ? blink : 0); - - switch (k) { - case ITEM_SETUP_TOP_BAR_LABEL: - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_TOP_BAR); - break; - - case ITEM_SETUP_TOP_BAR_VOLTAGE: - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_VOLTAGE); - putsMixerSource(SETUP_SCREEN_COLUMN2, y, g_model.frsky.voltsSource ? MIXSRC_FIRST_TELEM+3*(g_model.frsky.voltsSource-1) : 0, attr); - if (attr) { - g_model.frsky.voltsSource = checkIncDec(event, g_model.frsky.voltsSource, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isVoltsSensor); - } - break; - - case ITEM_SETUP_TOP_BAR_ALTITUDE: - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_ALTITUDE); - putsMixerSource(SETUP_SCREEN_COLUMN2, y, g_model.frsky.altitudeSource ? MIXSRC_FIRST_TELEM+3*(g_model.frsky.altitudeSource-1) : 0, attr); - if (attr) { - g_model.frsky.altitudeSource = checkIncDec(event, g_model.frsky.altitudeSource, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isAltSensor); - } - break; - - case ITEM_SETUP_SCREEN_LABEL1: - case ITEM_SETUP_SCREEN_LABEL2: - case ITEM_SETUP_SCREEN_LABEL3: - case ITEM_SETUP_SCREEN_LABEL4: - { - uint8_t screenIndex = TELEMETRY_CURRENT_SCREEN(k); - drawStringWithIndex(MENUS_MARGIN_LEFT, y, STR_SCREEN, screenIndex+1); - TelemetryScreenType oldScreenType = TELEMETRY_SCREEN_TYPE(screenIndex); - TelemetryScreenType newScreenType = (TelemetryScreenType)selectMenuItem(SETUP_SCREEN_COLUMN2, y, STR_VTELEMSCREENTYPE, oldScreenType, 0, TELEMETRY_SCREEN_TYPE_MAX, (menuHorizontalPosition==0 ? attr : 0), event); - if (newScreenType != oldScreenType) { - g_model.frsky.screensType = (g_model.frsky.screensType & (~(0x03 << (2*screenIndex)))) | (newScreenType << (2*screenIndex)); - memset(&g_model.frsky.screens[screenIndex], 0, sizeof(g_model.frsky.screens[screenIndex])); - } -#if defined(LUA) - if (newScreenType == TELEMETRY_SCREEN_TYPE_SCRIPT) { - TelemetryScriptData & scriptData = g_model.frsky.screens[screenIndex].script; - - // TODO better function name for --- - // TODO function for these lines - if (ZEXIST(scriptData.file)) - lcdDrawSizedText(SETUP_SCREEN_COLUMN3, y, scriptData.file, sizeof(scriptData.file), (menuHorizontalPosition==1 ? attr : 0)); - else - lcdDrawTextAtIndex(SETUP_SCREEN_COLUMN3, y, STR_VCSWFUNC, 0, (menuHorizontalPosition==1 ? attr : 0)); - - if (menuHorizontalPosition==1 && attr && event==EVT_KEY_BREAK(KEY_ENTER) && READ_ONLY_UNLOCKED()) { - s_editMode = 0; - if (sdListFiles(SCRIPTS_TELEM_PATH, SCRIPTS_EXT, sizeof(g_model.frsky.screens[screenIndex].script.file), g_model.frsky.screens[screenIndex].script.file)) { - popupMenuHandler = onSetupScriptFileSelectionMenu; - } - else { - POPUP_WARNING(STR_NO_SCRIPTS_ON_SD); - } - } - } - else if (attr) { - MOVE_CURSOR_FROM_HERE(); - } -#endif - break; - } - - case ITEM_SETUP_SCREEN_LINE1: - case ITEM_SETUP_SCREEN_LINE2: - case ITEM_SETUP_SCREEN_LINE3: - case ITEM_SETUP_SCREEN_LINE4: - case ITEM_SETUP_SCREEN_LINE5: - case ITEM_SETUP_SCREEN_LINE6: - case ITEM_SETUP_SCREEN_LINE7: - case ITEM_SETUP_SCREEN_LINE8: - case ITEM_SETUP_SCREEN_LINE9: - case ITEM_SETUP_SCREEN_LINE10: - case ITEM_SETUP_SCREEN_LINE11: - case ITEM_SETUP_SCREEN_LINE12: - case ITEM_SETUP_SCREEN_LINE13: - case ITEM_SETUP_SCREEN_LINE14: - case ITEM_SETUP_SCREEN_LINE15: - case ITEM_SETUP_SCREEN_LINE16: { - uint8_t screenIndex, lineIndex; - if (k < ITEM_SETUP_SCREEN_LABEL2) { - screenIndex = 0; - lineIndex = k - ITEM_SETUP_SCREEN_LINE1; - } - else if (k >= ITEM_SETUP_SCREEN_LABEL4) { - screenIndex = 3; - lineIndex = k - ITEM_SETUP_SCREEN_LINE13; - } - else if (k >= ITEM_SETUP_SCREEN_LABEL3) { - screenIndex = 2; - lineIndex = k - ITEM_SETUP_SCREEN_LINE9; - } - else { - screenIndex = 1; - lineIndex = k - ITEM_SETUP_SCREEN_LINE5; - } - -#if defined(GAUGES) - if (IS_BARS_SCREEN(screenIndex)) { - FrSkyBarData & bar = g_model.frsky.screens[screenIndex].bars[lineIndex]; - source_t barSource = bar.source; - putsMixerSource(MENUS_MARGIN_LEFT+INDENT_WIDTH, y, barSource, (menuHorizontalPosition==0 ? attr : 0)); - int barMax = getMaximumValue(barSource); - int barMin = -barMax; - if (barSource) { - if (barSource <= MIXSRC_LAST_CH) { - putsChannelValue(SETUP_SCREEN_COLUMN2, y, barSource, calc100toRESX(bar.barMin), (menuHorizontalPosition==1 ? attr : 0) | LEFT); - putsChannelValue(SETUP_SCREEN_COLUMN4, y, barSource, calc100toRESX(bar.barMax), (menuHorizontalPosition==2 ? attr : 0) | LEFT); - } - else { - putsChannelValue(SETUP_SCREEN_COLUMN2, y, barSource, bar.barMin, (menuHorizontalPosition==1 ? attr : 0) | LEFT); - putsChannelValue(SETUP_SCREEN_COLUMN4, y, barSource, bar.barMax, (menuHorizontalPosition==2 ? attr : 0) | LEFT); - } - } - else if (attr) { - MOVE_CURSOR_FROM_HERE(); - } - if (attr && s_editMode>0) { - switch (menuHorizontalPosition) { - case 0: - bar.source = checkIncDec(event, barSource, 0, MIXSRC_LAST_TELEM, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailable); - if (checkIncDec_Ret) { - if (barSource <= MIXSRC_LAST_CH) { - bar.barMin = -100; - bar.barMax = 100; - } - else { - bar.barMin = 0; - bar.barMax = 0; - } - } - break; - case 1: - bar.barMin = checkIncDec(event, bar.barMin, barMin, bar.barMax, EE_MODEL|NO_INCDEC_MARKS); - break; - case 2: - bar.barMax = checkIncDec(event, bar.barMax, bar.barMin, barMax, EE_MODEL|NO_INCDEC_MARKS); - break; - } - } - } - else -#endif - { - for (int c = 0; c < NUM_LINE_ITEMS; c++) { - LcdFlags cellAttr = (menuHorizontalPosition == c ? attr : 0); - source_t &value = g_model.frsky.screens[screenIndex].lines[lineIndex].sources[c]; - const coord_t pos[] = {MENUS_MARGIN_LEFT + INDENT_WIDTH, SETUP_SCREEN_COLUMN2, SETUP_SCREEN_COLUMN4}; - putsMixerSource(pos[c], y, value, cellAttr); - if (cellAttr && s_editMode > 0) { - value = checkIncDec(event, value, 0, MIXSRC_LAST_TELEM, EE_MODEL | INCDEC_SOURCE | NO_INCDEC_MARKS, - isSourceAvailable); - } - } - if (attr && menuHorizontalPosition == NUM_LINE_ITEMS) { - REPEAT_LAST_CURSOR_MOVE(0); - } - } - break; + else if (k < linesCount) { + const ZoneOption * option = &options[k-1]; + ZoneOptionValue value = currentScreen->getOptionValue(k-1); + value = editZoneOption(y, option, value, attr, event); + if (attr) { + currentScreen->setOptionValue(k-1, value); } } } + return true; } diff --git a/radio/src/gui/horus/view_main.cpp b/radio/src/gui/horus/view_main.cpp index a649f9880..be9b842f5 100644 --- a/radio/src/gui/horus/view_main.cpp +++ b/radio/src/gui/horus/view_main.cpp @@ -29,15 +29,7 @@ #define TRIM_LEN 80 #define POTS_LINE_Y 252 -#define MODELPANEL_LEFT 240 -#define MODELPANEL_TOP 68 -#define MODELPANEL_WIDTH MODEL_BITMAP_WIDTH -#define MODELPANEL_HEIGHT 135 - -#define TIMER1PANEL_LEFT 46 -#define TIMER1PANEL_TOP 55 -#define TIMER2PANEL_LEFT TIMER1PANEL_LEFT -#define TIMER2PANEL_TOP 134 +Layout * customScreens[MAX_CUSTOM_SCREENS]; void drawMainPots() { @@ -87,25 +79,6 @@ void drawTrims(uint8_t flightMode) } } -void drawTimer(coord_t x, coord_t y, int index) -{ - TimerData & timerData = g_model.timers[index]; - TimerState & timerState = timersStates[index]; - lcdDrawBitmapPattern(x, y, LBM_TIMER_BACKGROUND, TEXT_BGCOLOR); - if (timerData.start) { - lcdDrawBitmapPatternPie(x+2, y+3, LBM_RSCALE, TITLE_BGCOLOR, 0, timerState.val <= 0 ? 360 : 360*(timerData.start-timerState.val)/timerData.start); - } - else { - lcdDrawBitmapPattern(x+3, y+4, LBM_TIMER, TITLE_BGCOLOR); - } - putsTimer(x+76, y+31, abs(timerState.val), TEXT_COLOR|DBLSIZE|LEFT); - if (ZLEN(timerData.name) > 0) { - lcdDrawSizedText(x+78, y+20, timerData.name, LEN_TIMER_NAME, ZCHAR|SMLSIZE|TEXT_COLOR); - } - drawStringWithIndex(x+137, y+17, "TMR", index+1, SMLSIZE|TEXT_COLOR); -} - - void drawMainViewTopBar() { const int ALTITUDE_Y = 16; @@ -283,55 +256,9 @@ bool menuMainView(evt_t event) break; } - // 23ms if 24bits per pixel (with transparency) 5/6/5/8 - // 6ms if 16bits per pixel 5/6/5 no DMA - // 1.2ms with the DMA - TIME_MEASURE_START(backgroundbitmap); - lcdDrawBitmap(0, 0, LBM_MAINVIEW_BACKGROUND); - TIME_MEASURE_STOP(backgroundbitmap); - - // Top Bar - drawMainViewTopBar(); - - // Flight mode - lcdDrawSizedText(LCD_W/2-getTextWidth(g_model.flightModeData[mixerCurrentFlightMode].name, sizeof(g_model.flightModeData[mixerCurrentFlightMode].name), ZCHAR|SMLSIZE)/2, 237, g_model.flightModeData[mixerCurrentFlightMode].name, sizeof(g_model.flightModeData[mixerCurrentFlightMode].name), ZCHAR|SMLSIZE); - - // Pots and rear sliders positions - drawMainPots(); - - // Trims - drawTrims(mixerCurrentFlightMode); - - // Model panel - TIME_MEASURE_START(filledRect); - lcdDrawFilledRect(MODELPANEL_LEFT, MODELPANEL_TOP, MODELPANEL_WIDTH, MODELPANEL_HEIGHT, SOLID, TEXT_BGCOLOR | OPACITY(5)); - TIME_MEASURE_STOP(filledRect); // 9ms ! - - lcdDrawBitmapPattern(MODELPANEL_LEFT+6, MODELPANEL_TOP+4, LBM_MODEL_ICON, TITLE_BGCOLOR); - lcdDrawSizedText(MODELPANEL_LEFT+45, MODELPANEL_TOP+10, g_model.header.name, LEN_MODEL_NAME, ZCHAR|SMLSIZE); - lcdDrawSolidHorizontalLine(MODELPANEL_LEFT+39, MODELPANEL_TOP+27, MODELPANEL_WIDTH-48, TITLE_BGCOLOR); - int scale = getBitmapScale(modelBitmap, MODEL_BITMAP_WIDTH, MODEL_BITMAP_HEIGHT); - int width = getBitmapScaledSize(getBitmapWidth(modelBitmap), scale); - int height = getBitmapScaledSize(getBitmapHeight(modelBitmap), scale); - lcdDrawBitmap(MODELPANEL_LEFT+(MODEL_BITMAP_WIDTH-width)/2, MODELPANEL_TOP+MODELPANEL_HEIGHT-MODEL_BITMAP_HEIGHT/2-height/2, modelBitmap, 0, 0, scale); - - // Timers - if (g_model.timers[0].mode) { - drawTimer(TIMER1PANEL_LEFT, TIMER1PANEL_TOP, 0); + if (customScreens[0]) { + customScreens[0]->refresh(); } - if (g_model.timers[1].mode) { - drawTimer(TIMER2PANEL_LEFT, TIMER2PANEL_TOP, 1); - } - -#if 0 - if (gvarDisplayTimer > 0) { - gvarDisplayTimer--; - displayMessageBox(); - drawStringWithIndex(WARNING_LINE_X, WARNING_LINE_Y, STR_GV, gvarLastChanged+1, DBLSIZE|YELLOW); - lcdDrawSizedText(WARNING_LINE_X+45, WARNING_LINE_Y, g_model.gvars[gvarLastChanged].name, LEN_GVAR_NAME, DBLSIZE|YELLOW|ZCHAR); - lcdDrawNumber(WARNING_LINE_X, WARNING_INFOLINE_Y, GVAR_VALUE(gvarLastChanged, getGVarFlightMode(mixerCurrentFlightMode, gvarLastChanged)), DBLSIZE|LEFT); - } -#endif return true; } diff --git a/radio/src/gui/horus/view_statistics.cpp b/radio/src/gui/horus/view_statistics.cpp index 0f6298153..a3b475e90 100644 --- a/radio/src/gui/horus/view_statistics.cpp +++ b/radio/src/gui/horus/view_statistics.cpp @@ -38,7 +38,7 @@ bool menuStatisticsView(evt_t event) return false; } - drawMenuTemplate("Statistics"); + drawScreenTemplate("Statistics", LBM_RADIO_ICON, OPTION_MENU_NO_SCROLLBAR); lcdDrawText( 10, MENU_CONTENT_TOP + FH*0, "\037\145TOT:\037\317BATT:", HEADER_COLOR); lcdDrawText( 10, MENU_CONTENT_TOP + FH*1, "TM1:\037\145TM2:", HEADER_COLOR); @@ -116,7 +116,7 @@ bool menuStatisticsDebug(evt_t event) return false; } - drawMenuTemplate(STR_MENUDEBUG); + drawScreenTemplate(STR_MENUDEBUG, LBM_RADIO_ICON, OPTION_MENU_NO_SCROLLBAR); lcdDrawText(MENUS_MARGIN_LEFT, MENU_DEBUG_Y_FREE_RAM, "Free Mem"); lcdDrawNumber(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_FREE_RAM, availableMemory(), LEFT, 0, NULL, "b"); diff --git a/radio/src/gui/horus/widget.cpp b/radio/src/gui/horus/widget.cpp new file mode 100644 index 000000000..573e0d5a3 --- /dev/null +++ b/radio/src/gui/horus/widget.cpp @@ -0,0 +1,59 @@ +/* + * 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 "opentx.h" + +const WidgetFactory * registeredWidgets[MAX_REGISTERED_WIDGETS]; // TODO dynamic +unsigned int countRegisteredWidgets = 0; +void registerWidget(const WidgetFactory * factory) +{ + if (countRegisteredWidgets < MAX_REGISTERED_WIDGETS) { + registeredWidgets[countRegisteredWidgets++] = factory; + } +} + +const WidgetFactory * getWidgetFactory(const char * name) +{ + for (unsigned int i=0; igetName())) { + return factory; + } + } + return NULL; +} + +Widget * createWidget(const char * name, const Zone & zone, Widget::PersistentData * persistentData) +{ + const WidgetFactory * factory = getWidgetFactory(name); + if (factory) { + return factory->create(zone, persistentData); + } + return NULL; +} + +Widget * loadWidget(const char * name, const Zone & zone, Widget::PersistentData * persistentData) +{ + const WidgetFactory * factory = getWidgetFactory(name); + if (factory) { + return factory->load(zone, persistentData); + } + return NULL; +} diff --git a/radio/src/gui/horus/widget.h b/radio/src/gui/horus/widget.h new file mode 100644 index 000000000..fa6582db3 --- /dev/null +++ b/radio/src/gui/horus/widget.h @@ -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. + */ + +#ifndef _WIDGET_H_ +#define _WIDGET_H_ + +#include + +#define MAX_WIDGET_OPTIONS 4 + +struct Zone +{ + uint16_t x, y, w, h; +}; + +struct ZoneOption +{ + enum Type { + Bool, + Integer, + String, + TextSize, + Timer, + Source, + Switch, + Color + }; + + const char * name; + Type type; +}; + +union ZoneOptionValue +{ + bool boolValue; + uint32_t unsignedValue; + int32_t signedValue; + char stringValue[8]; +}; + +class WidgetFactory; +class Widget +{ + public: + struct PersistentData { + ZoneOptionValue options[MAX_WIDGET_OPTIONS]; + }; + + Widget(const WidgetFactory * factory, const Zone & zone, PersistentData * persistentData): + factory(factory), + zone(zone), + persistentData(persistentData) + { + } + + virtual void create() + { + memset(persistentData, 0, sizeof(PersistentData)); + } + + virtual void load() + { + } + + const WidgetFactory * getFactory() const + { + return factory; + } + + virtual ZoneOptionValue getOptionValue(unsigned int index) const + { + return persistentData->options[index]; + } + + virtual void setOptionValue(unsigned int index, ZoneOptionValue value) const + { + persistentData->options[index] = value; + } + + virtual void refresh() = 0; + + protected: + const WidgetFactory * factory; + Zone zone; + PersistentData * persistentData; +}; + +void registerWidget(const WidgetFactory * factory); + +class WidgetFactory +{ + public: + WidgetFactory(const char * name, const char * bitmap): + name(name), + bitmap(bitmap) + { + registerWidget(this); + } + + const char * getName() const + { + return name; + } + + virtual const ZoneOption * getOptions() const = 0; + + virtual Widget * create(const Zone & zone, Widget::PersistentData * persistentData) const = 0; + + virtual Widget * load(const Zone & zone, Widget::PersistentData * persistentData) const = 0; + + protected: + const char * name; + const char * bitmap; +}; + +template +class BaseWidgetFactory: public WidgetFactory +{ + public: + BaseWidgetFactory(const char * name, const char * bitmap, const ZoneOption * options): + WidgetFactory(name, bitmap), + options(options) + { + } + + virtual const ZoneOption * getOptions() const + { + return options; + } + + virtual Widget * create(const Zone & zone, Widget::PersistentData * persistentData) const + { + Widget * widget = new T(this, zone, persistentData); + widget->create(); + return widget; + } + + virtual Widget * load(const Zone & zone, Widget::PersistentData * persistentData) const + { + Widget * widget = new T(this, zone, persistentData); + widget->load(); + return widget; + } + + protected: + const ZoneOption * options; +}; + +#define MAX_REGISTERED_WIDGETS 10 +extern unsigned int countRegisteredWidgets; +extern const WidgetFactory * registeredWidgets[MAX_REGISTERED_WIDGETS]; +Widget * createWidget(const char * name, const Zone & zone, Widget::PersistentData * persistentData); +Widget * loadWidget(const char * name, const Zone & zone, Widget::PersistentData * persistentData); + +#endif // _WIDGET_H_ diff --git a/radio/src/gui/horus/widgets.cpp b/radio/src/gui/horus/widgets.cpp index f9e0f9fab..bb97fd630 100644 --- a/radio/src/gui/horus/widgets.cpp +++ b/radio/src/gui/horus/widgets.cpp @@ -56,13 +56,10 @@ void drawStick(coord_t x, coord_t y, int16_t xval, int16_t yval) void drawButton(coord_t x, coord_t y, const char * label, LcdFlags attr) { - int width = getTextWidth(label, attr); - lcdDrawBitmap(x, y, LBM_BUTTON_LEFT); - for (int i=0; i 0) { + // Menu title bar + if (options & OPTION_MENU_TITLE_BAR) { + linesDisplayed = NUM_BODY_LINES; + bodyTop = MENU_BODY_TOP; lcdDrawSolidFilledRect(0, MENU_HEADER_HEIGHT, LCD_W, MENU_TITLE_TOP - MENU_HEADER_HEIGHT, TEXT_BGCOLOR); lcdDrawSolidFilledRect(0, MENU_TITLE_TOP, LCD_W, MENU_TITLE_HEIGHT, TITLE_BGCOLOR); - if (options & OPTION_MENU_NO_FOOTER) { - lcdDrawSolidFilledRect(0, MENU_BODY_TOP, LCD_W, MENU_BODY_HEIGHT+MENU_FOOTER_HEIGHT, TEXT_BGCOLOR); - } - else { - lcdDrawSolidFilledRect(0, MENU_BODY_TOP, LCD_W, MENU_BODY_HEIGHT, TEXT_BGCOLOR); - lcdDrawSolidFilledRect(0, MENU_FOOTER_TOP, LCD_W, MENU_FOOTER_HEIGHT, HEADER_BGCOLOR); - } - if (menuVerticalPosition < 0) { - lcdDrawBitmapPattern(58+menuPageIndex*MENU_ICONS_SPACING-10, 0, LBM_CURRENT_BG, TITLE_BGCOLOR); - } - else { - lcdDrawSolidFilledRect(58+menuPageIndex*MENU_ICONS_SPACING-9, 0, 32, MENU_HEADER_HEIGHT, TITLE_BGCOLOR); - lcdDrawBitmapPattern(58+menuPageIndex*MENU_ICONS_SPACING, MENU_TITLE_TOP-9, LBM_DOT, MENU_TITLE_COLOR); - } - const uint8_t * const * icons = (menuVerticalPositions[0] == 0 ? LBM_MODEL_ICONS : LBM_RADIO_ICONS); - lcdDrawBitmapPattern(5, 7, icons[0], MENU_TITLE_COLOR); - for (int i=0; i NUM_BODY_LINES) { - drawVerticalScrollbar(scrollbar_X, DEFAULT_SCROLLBAR_Y, DEFAULT_SCROLLBAR_H, menuVerticalOffset, linesCount, NUM_BODY_LINES); - } } else { - lcdDrawBitmapPattern(4, 10, LBM_TOPMENU_OPENTX, MENU_TITLE_COLOR); + linesDisplayed = NUM_BODY_LINES; + bodyTop = MENU_HEADER_HEIGHT; if (title) { - lcdDrawText(50, 3, title, MENU_TITLE_COLOR|DBLSIZE); - } - // Body and footer (depending on options) - if (options & OPTION_MENU_NO_FOOTER) { - lcdDrawSolidFilledRect(0, MENU_HEADER_HEIGHT, LCD_W, LCD_H-MENU_HEADER_HEIGHT, TEXT_BGCOLOR); - } - else { - lcdDrawSolidFilledRect(0, MENU_HEADER_HEIGHT, LCD_W, LCD_H-MENU_HEADER_HEIGHT-MENU_FOOTER_HEIGHT, TEXT_BGCOLOR); - lcdDrawSolidFilledRect(0, MENU_FOOTER_TOP, LCD_W, MENU_FOOTER_HEIGHT, HEADER_BGCOLOR); - } - if (scrollbar_X && linesCount > NUM_BODY_LINES+1) { - drawVerticalScrollbar(scrollbar_X, DEFAULT_SCROLLBAR_Y-FH, DEFAULT_SCROLLBAR_H+FH, menuVerticalOffset, linesCount, NUM_BODY_LINES+1); + lcdDrawText(50, 3, title, MENU_TITLE_COLOR); } } -} - -void drawSubmenuTemplate(const char * name, uint16_t scrollbar_X, uint32_t options) -{ - // clear the screen - lcdDrawSolidFilledRect(0, 0, LCD_W, MENU_HEADER_HEIGHT, HEADER_BGCOLOR); + // Footer if (options & OPTION_MENU_NO_FOOTER) { - lcdDrawSolidFilledRect(0, MENU_HEADER_HEIGHT, LCD_W, LCD_H-MENU_HEADER_HEIGHT, TEXT_BGCOLOR); + bodyBottom = LCD_H; } else { - lcdDrawSolidFilledRect(0, MENU_HEADER_HEIGHT, LCD_W, LCD_H-MENU_HEADER_HEIGHT-MENU_FOOTER_HEIGHT, TEXT_BGCOLOR); + bodyBottom = MENU_FOOTER_TOP; lcdDrawSolidFilledRect(0, MENU_FOOTER_TOP, LCD_W, MENU_FOOTER_HEIGHT, HEADER_BGCOLOR); } + // Body + lcdDrawSolidFilledRect(0, bodyTop, LCD_W, bodyBottom-bodyTop, TEXT_BGCOLOR); + + // Scrollbar + if (!(options & OPTION_MENU_NO_SCROLLBAR) && linesCount>linesDisplayed) { + drawVerticalScrollbar(DEFAULT_SCROLLBAR_X, bodyTop+3, bodyBottom-bodyTop-6, menuVerticalOffset, linesCount, linesDisplayed); + } +} + +void drawMenuTemplate(const char * title, uint16_t scrollbar_X, uint32_t options) +{ const uint8_t * const * icons = (menuVerticalPositions[0] == 0 ? LBM_MODEL_ICONS : LBM_RADIO_ICONS); - lcdDrawBitmapPattern(0, 0, LBM_TOPMENU_POLYGON, TITLE_BGCOLOR); - lcdDrawBitmapPattern(5, 7, icons[menuPageIndex+1], MENU_TITLE_COLOR); + drawScreenTemplate(title, icons[0], OPTION_MENU_TITLE_BAR); - drawTopmenuDatetime(); - - if (name) { - // must be done at the end so that we can write something at the right of the menu title - lcdDrawText(50, 3, name, MENU_TITLE_COLOR); + if (menuVerticalPosition < 0) { + lcdDrawBitmapPattern(58+menuPageIndex*MENU_ICONS_SPACING-10, 0, LBM_CURRENT_BG, TITLE_BGCOLOR); + } + else { + lcdDrawSolidFilledRect(58+menuPageIndex*MENU_ICONS_SPACING-9, 0, 32, MENU_HEADER_HEIGHT, TITLE_BGCOLOR); + lcdDrawBitmapPattern(58+menuPageIndex*MENU_ICONS_SPACING, MENU_TITLE_TOP-9, LBM_DOT, MENU_TITLE_COLOR); } - if (scrollbar_X && linesCount > NUM_BODY_LINES+1) { - drawVerticalScrollbar(scrollbar_X, DEFAULT_SCROLLBAR_Y-FH, DEFAULT_SCROLLBAR_H+MENU_FOOTER_HEIGHT, menuVerticalOffset, linesCount, NUM_BODY_LINES+1); + for (int i=0; i #define OPTION_MENU_NO_FOOTER 0x01 -//#define OPTION_MENU_NO_TITLE_BAR 0x02 +#define OPTION_MENU_TITLE_BAR 0x02 +#define OPTION_MENU_NO_SCROLLBAR 0x04 #define OPTION_SLIDER_INVERS INVERS #define OPTION_SLIDER_BLINK BLINK @@ -67,10 +68,15 @@ int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int #endif // Screen templates +void drawScreenTemplate(const char * title, const uint8_t * icon, uint32_t options=0); void drawMenuTemplate(const char * title, uint16_t scrollbar_X=0, uint32_t options=0); -void drawSubmenuTemplate(const char * name, uint16_t scrollbar_X=0, uint32_t options=0); void drawSplash(); void drawSleepBitmap(); void drawShutdownBitmap(uint32_t index); +// Main view standard widgets +void drawMainViewTopBar(); +void drawMainPots(); +void drawTrims(uint8_t flightMode); + #endif // _WIDGETS_H_ diff --git a/radio/src/gui/horus/widgets/gauge.cpp b/radio/src/gui/horus/widgets/gauge.cpp new file mode 100644 index 000000000..46ff52903 --- /dev/null +++ b/radio/src/gui/horus/widgets/gauge.cpp @@ -0,0 +1,79 @@ +/* + * 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 "opentx.h" + +class GaugeWidget: public Widget +{ + public: + GaugeWidget(const WidgetFactory * factory, const Zone & zone, Widget::PersistentData * persistentData): + Widget(factory, zone, persistentData) + { + } + + virtual void create() + { + persistentData->options[0].unsignedValue = 1; + persistentData->options[1].signedValue = -RESX; + persistentData->options[2].signedValue = RESX; + persistentData->options[3].unsignedValue = RED; + } + + void refresh(); + + static const ZoneOption options[]; +}; + +const ZoneOption GaugeWidget::options[] = { + { "Source", ZoneOption::Source }, + { "Min", ZoneOption::Integer }, + { "Max", ZoneOption::Integer }, + { "Color", ZoneOption::Color }, + { NULL, ZoneOption::Bool } +}; + +void GaugeWidget::refresh() +{ + mixsrc_t index = persistentData->options[0].unsignedValue; + int32_t min = persistentData->options[1].signedValue; + int32_t max = persistentData->options[2].signedValue; + uint16_t color = persistentData->options[3].unsignedValue; + + getvalue_t value = getValue(index); + getvalue_t value_in_range = value; + if (value < min) + value_in_range = min; + else if (value > max) + value_in_range; + + int w = divRoundClosest(zone.w * (value_in_range - min), (max - min)); + int percent = divRoundClosest(100 * (value_in_range - min), (max - min)); + + // Gauge label + putsMixerSource(zone.x, zone.y + 5, index, SMLSIZE | TEXT_INVERTED_COLOR); + + // Gauge + lcdSetColor(color); + lcdDrawSolidFilledRect(zone.x, zone.y + 20, zone.w, 16, TEXT_INVERTED_COLOR); + lcdDrawNumber(zone.x+zone.w/2+20, zone.y + 21, percent, SMLSIZE | CUSTOM_COLOR, 0, NULL, "%"); + lcdInvertRect(zone.x + w, zone.y + 20, zone.w - w, 16, CUSTOM_COLOR); +} + +BaseWidgetFactory gaugeWidget("Gauge", "", GaugeWidget::options); \ No newline at end of file diff --git a/radio/src/gui/horus/widgets/modelpanel.cpp b/radio/src/gui/horus/widgets/modelpanel.cpp new file mode 100644 index 000000000..c027a87e2 --- /dev/null +++ b/radio/src/gui/horus/widgets/modelpanel.cpp @@ -0,0 +1,56 @@ +/* + * 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 "opentx.h" + +class ModelPanelWidget: public Widget +{ + public: + ModelPanelWidget(const WidgetFactory * factory, const Zone & zone, Widget::PersistentData * persistentData): + Widget(factory, zone, persistentData) + { + } + + void refresh(); +}; + +void ModelPanelWidget::refresh() +{ + if (zone.h >= MODEL_BITMAP_HEIGHT) { + lcdDrawFilledRect(zone.x, zone.y, zone.w, zone.h, SOLID, TEXT_BGCOLOR | OPACITY(5)); + lcdDrawBitmapPattern(zone.x + 6, zone.y + 4, LBM_MODEL_ICON, TITLE_BGCOLOR); + lcdDrawSizedText(zone.x + 45, zone.y + 10, g_model.header.name, LEN_MODEL_NAME, ZCHAR | SMLSIZE); + lcdDrawSolidHorizontalLine(zone.x + 39, zone.y + 27, zone.w - 48, TITLE_BGCOLOR); + int scale = getBitmapScale(modelBitmap, zone.w, zone.h); + int width = getBitmapScaledSize(getBitmapWidth(modelBitmap), scale); + int height = getBitmapScaledSize(getBitmapHeight(modelBitmap), scale); + lcdDrawBitmap(zone.x + (zone.w - width) / 2, zone.y + zone.h - MODEL_BITMAP_HEIGHT / 2 - height / 2, modelBitmap, 0, 0, scale); + } + else { + int scale = getBitmapScale(modelBitmap, zone.w, zone.h); + int width = getBitmapScaledSize(getBitmapWidth(modelBitmap), scale); + int height = getBitmapScaledSize(getBitmapHeight(modelBitmap), scale); + lcdDrawFilledRect(zone.x, zone.y, zone.w, height, SOLID, TEXT_BGCOLOR | OPACITY(5)); + lcdDrawSizedText(zone.x + 5, zone.y + 10, g_model.header.name, LEN_MODEL_NAME, ZCHAR | SMLSIZE); + lcdDrawBitmap(zone.x + zone.w - width, zone.y, modelBitmap, 0, 0, scale); + } +} + +BaseWidgetFactory modelPanelWidget("ModelPanel", "", NULL); \ No newline at end of file diff --git a/radio/src/gui/horus/widgets/text.cpp b/radio/src/gui/horus/widgets/text.cpp new file mode 100644 index 000000000..21a7344f7 --- /dev/null +++ b/radio/src/gui/horus/widgets/text.cpp @@ -0,0 +1,57 @@ +/* + * 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 "opentx.h" + +class TextWidget: public Widget +{ + public: + TextWidget(const WidgetFactory * factory, const Zone & zone, Widget::PersistentData * persistentData): + Widget(factory, zone, persistentData) + { + } + + void create() + { + str2zchar(persistentData->options[0].stringValue, "Label", sizeof(persistentData->options[0].stringValue)); + persistentData->options[1].unsignedValue = RED; + persistentData->options[2].unsignedValue = 0; + } + + void refresh(); + + static const ZoneOption options[]; +}; + +const ZoneOption TextWidget::options[] = { + { "Text", ZoneOption::String }, + { "Color", ZoneOption::Color }, + { "Size", ZoneOption::TextSize }, + { NULL, ZoneOption::Bool } +}; + +void TextWidget::refresh() +{ + lcdSetColor(persistentData->options[1].unsignedValue); + LcdFlags fontsize = FONTSIZE(persistentData->options[2].unsignedValue << 8); + lcdDrawSizedText(zone.x, zone.y, persistentData->options[0].stringValue, sizeof(persistentData->options[0].stringValue), ZCHAR|fontsize|CUSTOM_COLOR); +} + +BaseWidgetFactory textWidget("Text", "", TextWidget::options); diff --git a/radio/src/gui/horus/widgets/timer.cpp b/radio/src/gui/horus/widgets/timer.cpp new file mode 100644 index 000000000..5c39d302f --- /dev/null +++ b/radio/src/gui/horus/widgets/timer.cpp @@ -0,0 +1,61 @@ +/* + * 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 "opentx.h" + +class TimerWidget: public Widget +{ + public: + TimerWidget(const WidgetFactory * factory, const Zone & zone, Widget::PersistentData * persistentData): + Widget(factory, zone, persistentData) + { + } + + void refresh(); + + static const ZoneOption options[]; +}; + +const ZoneOption TimerWidget::options[] = { + { "Timer source", ZoneOption::Timer }, + { NULL, ZoneOption::Bool } +}; + +void TimerWidget::refresh() +{ + uint32_t index = persistentData->options[0].unsignedValue; + + TimerData & timerData = g_model.timers[index]; + TimerState & timerState = timersStates[index]; + lcdDrawBitmapPattern(zone.x, zone.y, LBM_TIMER_BACKGROUND, TEXT_BGCOLOR); + if (timerData.start) { + lcdDrawBitmapPatternPie(zone.x+2, zone.y+3, LBM_RSCALE, TITLE_BGCOLOR, 0, timerState.val <= 0 ? 360 : 360*(timerData.start-timerState.val)/timerData.start); + } + else { + lcdDrawBitmapPattern(zone.x+3, zone.y+4, LBM_TIMER, TITLE_BGCOLOR); + } + putsTimer(zone.x+76, zone.y+31, abs(timerState.val), TEXT_COLOR|DBLSIZE|LEFT); + if (ZLEN(timerData.name) > 0) { + lcdDrawSizedText(zone.x+78, zone.y+20, timerData.name, LEN_TIMER_NAME, ZCHAR|SMLSIZE|TEXT_COLOR); + } + drawStringWithIndex(zone.x+137, zone.y+17, "TMR", index+1, SMLSIZE|TEXT_COLOR); +} + +BaseWidgetFactory timerWidget("Timer", "", TimerWidget::options); diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index 1ca55c4e3..e548b9096 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -27,7 +27,7 @@ #define LUA_EXPORT(...) LEXP(__VA_ARGS__) #define LUA_EXPORT_MULTIPLE(...) LEXP_MULTIPLE(__VA_ARGS__) #define LUA_EXPORT_EXTRA(...) LEXP_EXTRA(__VA_ARGS__) -#else +#else #define LUA_EXPORT(...) #define LUA_EXPORT_MULTIPLE(...) #define LUA_EXPORT_EXTRA(...) @@ -105,6 +105,7 @@ #define NUM_POTS 7 #define NUM_XPOTS 3 #define MAX_SENSORS 32 + #define MAX_CUSTOM_SCREENS 5 #elif defined(PCBFLAMENCO) #define MAX_MODELS 60 #define NUM_CHNOUT 32 // number of real output channels CH1-CH32 @@ -566,7 +567,7 @@ enum PotsWarnMode { #define MODELDATA_EXTRA uint8_t spare:6; uint8_t potsWarnMode:2; ModuleData moduleData[NUM_MODULES+1]; uint8_t potsWarnEnabled; int8_t potsWarnPosition[NUM_POTS]; uint8_t rxBattAlarms[2]; #else #define MODELDATA_BITMAP - #define MODELDATA_EXTRA + #define MODELDATA_EXTRA #endif enum BacklightMode { @@ -1154,16 +1155,16 @@ PACK(union u_gvarint_t { uint8_t hi; } bytes_t; int16_t word; - + u_gvarint_t(int8_t l, uint8_t h) {bytes_t.lo=l; bytes_t.hi=h?255:0;} // hi bit is negativ sign private: // prevent unwanted constructors, also saves program u_gvarint_t() {} u_gvarint_t(const u_gvarint_t&) {} -}); +}); #define MD_WEIGHT(md) (u_gvarint_t(md->weight,md->weightMode).word) - + PACK(union u_int8int16_t { struct { int8_t lo; @@ -1174,7 +1175,7 @@ PACK(union u_int8int16_t { #define MD_WEIGHT_TO_UNION(md, var) var.bytes_t.lo=md->weight; var.bytes_t.hi=md->weightMode?255:0 #define MD_UNION_TO_WEIGHT(var, md) md->weight=var.bytes_t.lo; if (var.word<0) md->weightMode=1; else md->weightMode=0 -// #define MD_SETWEIGHT(md, val) md->weight=val; if (val<0) md->weightMode=1; else md->weightMode=0 +// #define MD_SETWEIGHT(md, val) md->weight=val; if (val<0) md->weightMode=1; else md->weightMode=0 #define MD_OFFSET(md) (u_gvarint_t(md->offset,md->offsetMode).word) #define MD_OFFSET_TO_UNION(md, var) var.bytes_t.lo=md->offset; var.bytes_t.hi=md->offsetMode?255:0 @@ -1220,7 +1221,7 @@ enum LogicalSwitchesFunctions { typedef int16_t ls_telemetry_value_t; PACK(typedef struct { // Logical Switches data uint8_t func; - int32_t v1:10; + int32_t v1:10; int32_t v3:10; int32_t andsw:9; // TODO rename to xswtch uint32_t andswtype:1; // TODO rename to xswtchType (AND / OR) @@ -1327,7 +1328,7 @@ PACK(typedef struct { uint8_t ratio; // 0.0 means not used, 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc. int16_t offset:12; uint16_t type:4; // channel unit (0=volts, ...) - uint8_t alarms_value[2]; // 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc. + uint8_t alarms_value[2]; // 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc. uint8_t alarms_level:4; uint8_t alarms_greater:2; // 0=LT(<), 1=GT(>) uint8_t multiplier:2; // 0=no multiplier, 1=*2 multiplier @@ -1662,7 +1663,7 @@ PACK(typedef struct { uint8_t invertELE:1; uint8_t invertAIL:1; uint8_t invertCOL:1; - uint8_t type:5; + uint8_t type:5; uint8_t collectiveSource; uint8_t value; }) SwashRingData; @@ -2287,12 +2288,20 @@ enum DisplayTrims }; #if defined(COLORLCD) + #include "layout.h" #define SWITCHES_WARNING_DATA \ swarnstate_t switchWarningState; + PACK(typedef struct { + char layoutName[10]; + Layout::PersistentData layoutData; + }) CustomScreenData; + #define CUSTOM_SCREENS_DATA \ + CustomScreenData screenData[MAX_CUSTOM_SCREENS]; #else #define SWITCHES_WARNING_DATA \ swarnstate_t switchWarningState; \ swarnenable_t switchWarningEnable; + #define CUSTOM_SCREENS_DATA #endif PACK(typedef struct { @@ -2317,10 +2326,10 @@ PACK(typedef struct { MixData mixData[MAX_MIXERS]; LimitData limitData[NUM_CHNOUT]; ExpoData expoData[MAX_EXPOS]; - + CurveData curves[MAX_CURVES]; int8_t points[NUM_POINTS]; - + LogicalSwitchData logicalSw[NUM_LOGICAL_SWITCH]; CustomFunctionData customFn[NUM_CFN]; SwashRingData swashR; @@ -2339,8 +2348,11 @@ PACK(typedef struct { MODELDATA_EXTRA ARM_FIELD(TelemetrySensor telemetrySensors[MAX_SENSORS]) - + TARANIS_REV9E_FIELD(uint8_t toplcdTimer) + + CUSTOM_SCREENS_DATA + }) ModelData; extern EEGeneral g_eeGeneral; diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 45a57ed64..dadd433d5 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -1524,7 +1524,7 @@ uint16_t anaIn(uint8_t chan) return temp; #else volatile uint16_t *p = &s_anaFilt[pgm_read_byte(crossAna+chan)]; - return *p; + return *p; #endif #endif } @@ -1587,7 +1587,7 @@ void getADC() } } } - else + else #endif { s_anaFilt[x] = v; @@ -1880,7 +1880,23 @@ void doMixerCalculations() s_mixer_first_run_done = true; } +#if defined(COLORLCD) +void loadCustomScreens() +{ + for (unsigned int i=0; icreate(&g_model.screenData[0].layoutData); + } +} +#else + #define loadCustomScreens() +#endif #if defined(NAVIGATION_STICKS) uint8_t StickScrollAllowed; @@ -1914,7 +1930,7 @@ void opentxStart() #if defined(DEBUG_TRACE_BUFFER) trace_event(trace_start, 0x12345678); -#endif +#endif #if defined(PCBSKY9X) && defined(SDCARD) && !defined(SIMU) for (int i=0; i<500 && !Card_initialized; i++) { @@ -1927,6 +1943,8 @@ void opentxStart() checkAll(); #endif + loadCustomScreens(); + #if defined(GUI) if (g_eeGeneral.chkSum != evalChkSum()) { chainMenu(menuFirstCalib); @@ -1994,7 +2012,7 @@ void opentxClose() #if !defined(PCBTARANIS) && !defined(COLORLCD) if (storageDirtyMsk & EE_MODEL) { displayPopup(STR_SAVEMODEL); - } + } #endif g_eeGeneral.unexpectedShutdown = 0; @@ -2017,7 +2035,7 @@ void opentxClose() #endif #if defined(NAVIGATION_STICKS) -uint8_t getSticksNavigationEvent() +uint8_t getSticksNavigationEvent() { uint8_t evt = 0; if (StickScrollAllowed) { @@ -2198,10 +2216,10 @@ ISR(TIMER_AUDIO_VECT, ISR_NOBLOCK) #endif // Clocks every 10ms -ISR(TIMER_10MS_VECT, ISR_NOBLOCK) +ISR(TIMER_10MS_VECT, ISR_NOBLOCK) { // without correction we are 0,16% too fast; that mean in one hour we are 5,76Sek too fast; we do not like that - static uint8_t accuracyWarble; // because 16M / 1024 / 100 = 156.25. we need to correct the fault; no start value needed + static uint8_t accuracyWarble; // because 16M / 1024 / 100 = 156.25. we need to correct the fault; no start value needed #if defined(AUDIO) AUDIO_HEARTBEAT(); @@ -2235,7 +2253,7 @@ ISR(TIMER3_CAPT_vect) // G: High frequency noise can cause stack overflo with IS sei(); // enable other interrupts captureTrainerPulses(capture); - + cli(); // disable other interrupts for stack pops before this function's RETI RESUME_PPMIN_INTERRUPT(); } @@ -2553,6 +2571,8 @@ void opentxInit(OPENTX_INIT_ARGS) startPulses(); wdt_enable(WDTO_500MS); + + } #if !defined(SIMU) @@ -2571,11 +2591,11 @@ int main(void) #endif #if defined(PCBTARANIS) g_eeGeneral.contrast=30; -#endif +#endif wdt_disable(); boardInit(); - + #if defined(GUI) && !defined(PCBTARANIS) && !defined(PCBFLAMENCO) && !defined(PCBHORUS) // TODO remove this lcdInit(); diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 41ef601f4..f16a3a1a8 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -843,8 +843,8 @@ int getTrimValue(uint8_t phase, uint8_t idx); extern uint8_t gvarLastChanged; #endif #else - #define GET_GVAR(x, ...) (x) - #define GET_GVAR_PREC1(x, ...) (x*10) + #define GET_GVAR(x, ...) (x) + #define GET_GVAR_PREC1(x, ...) (x*10) #endif #if defined(CPUARM) diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp index af4eb83c0..0a5d861dc 100644 --- a/radio/src/translations.cpp +++ b/radio/src/translations.cpp @@ -575,6 +575,9 @@ const pm_char STR_MODEL_SELECT[] PROGMEM = TR_MODEL_SELECT; const pm_char STR_STOP_DISCOVER_SENSORS[] PROGMEM = TR_STOP_DISCOVER_SENSORS; const pm_char STR_DELETE_ALL_SENSORS[] PROGMEM = TR_DELETE_ALL_SENSORS; const pm_char STR_CONFIRMDELETE[] PROGMEM = TR_CONFIRMDELETE; +const pm_char STR_SELECT_WIDGET[] PROGMEM = TR_SELECT_WIDGET; +const pm_char STR_REMOVE_WIDGET[] PROGMEM = TR_REMOVE_WIDGET; +const pm_char STR_WIDGET_SETTINGS[] PROGMEM = TR_WIDGET_SETTINGS; #endif #if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS) diff --git a/radio/src/translations.h b/radio/src/translations.h index f03bf1f4e..d8cc93467 100644 --- a/radio/src/translations.h +++ b/radio/src/translations.h @@ -826,6 +826,9 @@ extern const pm_char STR_BLCOLOR[]; extern const pm_char STR_STOP_DISCOVER_SENSORS[]; extern const pm_char STR_DELETE_ALL_SENSORS[]; extern const pm_char STR_CONFIRMDELETE[]; + extern const pm_char STR_SELECT_WIDGET[]; + extern const pm_char STR_REMOVE_WIDGET[]; + extern const pm_char STR_WIDGET_SETTINGS[]; #endif #if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS) @@ -834,9 +837,9 @@ extern const pm_char STR_BLCOLOR[]; extern const pm_char STR_MODULE[]; extern const pm_char STR_ENABLE_POPUP[]; extern const pm_char STR_DISABLE_POPUP[]; -extern const pm_char STR_POPUP[]; -extern const pm_char STR_MIN[]; -extern const pm_char STR_MAX[]; + extern const pm_char STR_POPUP[]; + extern const pm_char STR_MIN[]; + extern const pm_char STR_MAX[]; extern const pm_char STR_CURVE_PRESET[]; extern const pm_char STR_PRESET[]; extern const pm_char STR_MIRROR[]; diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index 4d00e2bd2..77ca34cc8 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -1099,6 +1099,9 @@ #define TR_STOP_DISCOVER_SENSORS INDENT "Zastavit autodetekci" #define TR_DELETE_ALL_SENSORS INDENT "Odstranit všechny senzory" #define TR_CONFIRMDELETE "Opravdu odstranit vše?" +#define TR_SELECT_WIDGET "Select widget" +#define TR_REMOVE_WIDGET "Remove widget" +#define TR_WIDGET_SETTINGS "Widget settings" #define TR_MENU_INPUTS "\314Vstupy" #define TR_MENU_LUA "\322Lua skripty" diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index eff165f91..68639e5d6 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -1102,6 +1102,9 @@ #define TR_STOP_DISCOVER_SENSORS INDENT "Stop Sensorsuche" #define TR_DELETE_ALL_SENSORS INDENT "Lösche alle Sensoren" #define TR_CONFIRMDELETE "Wirklich alle löschen?" +#define TR_SELECT_WIDGET "Select widget" +#define TR_REMOVE_WIDGET "Remove widget" +#define TR_WIDGET_SETTINGS "Widget settings" // ----------------------------- Symbole für Auswahlliste---------- #define TR_MENU_INPUTS "\314Inputs" #define TR_MENU_LUA "\322Lua Scripte" diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index 08511efe8..e10c5a2fa 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -1128,6 +1128,9 @@ #define TR_STOP_DISCOVER_SENSORS INDENT "Stop discovery" #define TR_DELETE_ALL_SENSORS INDENT "Delete all sensors" #define TR_CONFIRMDELETE "Really delete all?" +#define TR_SELECT_WIDGET "Select widget" +#define TR_REMOVE_WIDGET "Remove widget" +#define TR_WIDGET_SETTINGS "Widget settings" #define TR_MENU_INPUTS "\314Inputs" #define TR_MENU_LUA "\322Lua scripts" diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index 173f72f82..0620b3db7 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -1054,6 +1054,9 @@ #define TR_STOP_DISCOVER_SENSORS INDENT "Stop discovery" #define TR_DELETE_ALL_SENSORS INDENT "Delete all sensors" #define TR_CONFIRMDELETE "Really delete all?" +#define TR_SELECT_WIDGET "Select widget" +#define TR_REMOVE_WIDGET "Remove widget" +#define TR_WIDGET_SETTINGS "Widget settings" #define TR_MENU_INPUTS "\314Inputs" #define TR_MENU_LUA "\322Lua scripts" diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index 574aff44c..1c7a97c87 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -1054,6 +1054,9 @@ #define TR_STOP_DISCOVER_SENSORS INDENT "Stop discovery" #define TR_DELETE_ALL_SENSORS INDENT "Delete all sensors" #define TR_CONFIRMDELETE "Really delete all?" +#define TR_SELECT_WIDGET "Select widget" +#define TR_REMOVE_WIDGET "Remove widget" +#define TR_WIDGET_SETTINGS "Widget settings" #define TR_MENU_INPUTS "\314Inputs" #define TR_MENU_LUA "\322Lua scripts" diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index 402a90444..fa2f477fd 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -1089,6 +1089,9 @@ #define TR_STOP_DISCOVER_SENSORS INDENT "Terminer découverte" #define TR_DELETE_ALL_SENSORS TR(INDENT "Suppr. tous capteurs",INDENT "Supprimer tous capteurs") #define TR_CONFIRMDELETE TR("Tout effacer?","Vraiment tout effacer?") +#define TR_SELECT_WIDGET "Select widget" +#define TR_REMOVE_WIDGET "Remove widget" +#define TR_WIDGET_SETTINGS "Widget settings" #define TR_MENU_INPUTS "\314Entrées" #define TR_MENU_LUA "\322Scripts Lua" diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index 659185ba3..9dc59f46d 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -1101,6 +1101,9 @@ #define TR_STOP_DISCOVER_SENSORS INDENT "Ferma ricerca.." #define TR_DELETE_ALL_SENSORS INDENT "Elimina tutti i sensori" #define TR_CONFIRMDELETE "Confermi eliminazione?" +#define TR_SELECT_WIDGET "Select widget" +#define TR_REMOVE_WIDGET "Remove widget" +#define TR_WIDGET_SETTINGS "Widget settings" #define TR_MENU_INPUTS "\314Ingressi" #define TR_MENU_LUA "\322Lua scripts" diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index fc6513ac2..6451aba44 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -1120,6 +1120,9 @@ #define TR_STOP_DISCOVER_SENSORS INDENT "Stop ontdekking" #define TR_DELETE_ALL_SENSORS INDENT "Wis alle sensors" #define TR_CONFIRMDELETE "Echt alles wissen?" +#define TR_SELECT_WIDGET "Select widget" +#define TR_REMOVE_WIDGET "Remove widget" +#define TR_WIDGET_SETTINGS "Widget settings" #define TR_MENU_INPUTS "\314Inputs" diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index d0cefde19..66f7de1c2 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -1102,6 +1102,9 @@ #define TR_STOP_DISCOVER_SENSORS INDENT "Szukanie STOP " #define TR_DELETE_ALL_SENSORS INDENT "Usuń czujniki " #define TR_CONFIRMDELETE "Usunąć wszystkie ?" +#define TR_SELECT_WIDGET "Select widget" +#define TR_REMOVE_WIDGET "Remove widget" +#define TR_WIDGET_SETTINGS "Widget settings" #define TR_MENU_INPUTS "\314Wejści" #define TR_MENU_LUA "\322SkryptyLUA" diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index c4af3e04d..ba16649a7 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -1048,6 +1048,9 @@ #define TR_STOP_DISCOVER_SENSORS INDENT "Stop discovery" #define TR_DELETE_ALL_SENSORS INDENT "Delete all sensors" #define TR_CONFIRMDELETE "Really delete all?" +#define TR_SELECT_WIDGET "Select widget" +#define TR_REMOVE_WIDGET "Remove widget" +#define TR_WIDGET_SETTINGS "Widget settings" #define TR_MENU_INPUTS "\314Inputs" #define TR_MENU_LUA "\322Lua scripts" diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index 2ebe0fe99..553e23723 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -1125,6 +1125,9 @@ #define TR_STOP_DISCOVER_SENSORS INDENT "Avbryt sökning" #define TR_DELETE_ALL_SENSORS INDENT "Ta bort alla sensorer" #define TR_CONFIRMDELETE "Ta bort alla?" +#define TR_SELECT_WIDGET "Select widget" +#define TR_REMOVE_WIDGET "Remove widget" +#define TR_WIDGET_SETTINGS "Widget settings" #define TR_MENU_INPUTS "\314Inputs" #define TR_MENU_LUA "\322Lua scripts" diff --git a/radio/util/font2png.py b/radio/util/font2png.py index 302ed6659..43482dd62 100755 --- a/radio/util/font2png.py +++ b/radio/util/font2png.py @@ -91,10 +91,8 @@ def createFontBitmap(filename, fontname, fontsize, fontbold, foreground, backgro with open(filename + ".specs", "w") as f: f.write("{ ") f.write(",".join(str(tmp) for tmp in coords)) - if extraWidth: - for i in range(1, 14): - f.write(", %d" % (int(coords[-1]) + i * (extraWidth / 12))) - # f.write(file("fonts/extra_%dpx.specs" % fontsize).read()) + for i in range(1, 14): + f.write(", %d" % (int(coords[-1]) + i * (extraWidth / 12))) f.write(" }") return coords