diff --git a/.gitignore b/.gitignore index 4d188ec..a4ab908 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,10 @@ **Debug **.user *.qtds.** -**/CMakeCache.txt \ No newline at end of file +**/CMakeCache.txt +.clangd +build/ +html/ +latex/ +.idea/** +.DS_STORE \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..d8da1e4 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "doxygen-awesome-css"] + path = doxygen-awesome-css + url = https://github.com/jothepro/doxygen-awesome-css.git diff --git a/Bolt_Dash/CMakeFiles/3.29.2/CMakeCXXCompiler.cmake b/Bolt_Dash/CMakeFiles/3.29.2/CMakeCXXCompiler.cmake new file mode 100644 index 0000000..ed88bdb --- /dev/null +++ b/Bolt_Dash/CMakeFiles/3.29.2/CMakeCXXCompiler.cmake @@ -0,0 +1,92 @@ +set(CMAKE_CXX_COMPILER "/usr/bin/c++") +set(CMAKE_CXX_COMPILER_ARG1 "") +set(CMAKE_CXX_COMPILER_ID "GNU") +set(CMAKE_CXX_COMPILER_VERSION "13.2.1") +set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "") +set(CMAKE_CXX_COMPILER_WRAPPER "") +set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "17") +set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20;cxx_std_23") +set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters") +set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") +set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") +set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17") +set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20") +set(CMAKE_CXX23_COMPILE_FEATURES "cxx_std_23") + +set(CMAKE_CXX_PLATFORM_ID "Linux") +set(CMAKE_CXX_SIMULATE_ID "") +set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_CXX_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_CXX_COMPILER_AR "/usr/bin/gcc-ar") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_CXX_COMPILER_RANLIB "/usr/bin/gcc-ranlib") +set(CMAKE_LINKER "/usr/bin/ld") +set(CMAKE_LINKER_LINK "") +set(CMAKE_LINKER_LLD "") +set(CMAKE_CXX_COMPILER_LINKER "/usr/bin/ld") +set(CMAKE_CXX_COMPILER_LINKER_ID "GNU") +set(CMAKE_CXX_COMPILER_LINKER_VERSION 2.40) +set(CMAKE_CXX_COMPILER_LINKER_FRONTEND_VARIANT GNU) +set(CMAKE_MT "") +set(CMAKE_TAPI "CMAKE_TAPI-NOTFOUND") +set(CMAKE_COMPILER_IS_GNUCXX 1) +set(CMAKE_CXX_COMPILER_LOADED 1) +set(CMAKE_CXX_COMPILER_WORKS TRUE) +set(CMAKE_CXX_ABI_COMPILED TRUE) + +set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") + +set(CMAKE_CXX_COMPILER_ID_RUN 1) +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm;ccm;cxxm;c++m) +set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) + +foreach (lang IN ITEMS C OBJC OBJCXX) + if (CMAKE_${lang}_COMPILER_ID_RUN) + foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS) + list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension}) + endforeach() + endif() +endforeach() + +set(CMAKE_CXX_LINKER_PREFERENCE 30) +set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) +set(CMAKE_CXX_LINKER_DEPFILE_SUPPORTED FALSE) + +# Save compiler ABI information. +set(CMAKE_CXX_SIZEOF_DATA_PTR "8") +set(CMAKE_CXX_COMPILER_ABI "ELF") +set(CMAKE_CXX_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_CXX_LIBRARY_ARCHITECTURE "") + +if(CMAKE_CXX_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_CXX_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") +endif() + +if(CMAKE_CXX_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/usr/include/c++/13;/usr/include/c++/13/x86_64-redhat-linux;/usr/include/c++/13/backward;/usr/lib/gcc/x86_64-redhat-linux/13/include;/usr/local/include;/usr/include") +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;gcc_s;gcc;c;gcc_s;gcc") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-redhat-linux/13;/usr/lib64;/lib64;/usr/lib") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") +set(CMAKE_CXX_COMPILER_CLANG_RESOURCE_DIR "") diff --git a/Bolt_Dash/CMakeFiles/3.29.2/CMakeDetermineCompilerABI_CXX.bin b/Bolt_Dash/CMakeFiles/3.29.2/CMakeDetermineCompilerABI_CXX.bin new file mode 100755 index 0000000..2b1817e Binary files /dev/null and b/Bolt_Dash/CMakeFiles/3.29.2/CMakeDetermineCompilerABI_CXX.bin differ diff --git a/Bolt_Dash/CMakeFiles/3.29.2/CMakeSystem.cmake b/Bolt_Dash/CMakeFiles/3.29.2/CMakeSystem.cmake new file mode 100644 index 0000000..9c79683 --- /dev/null +++ b/Bolt_Dash/CMakeFiles/3.29.2/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Linux-6.8.4-200.fc39.x86_64") +set(CMAKE_HOST_SYSTEM_NAME "Linux") +set(CMAKE_HOST_SYSTEM_VERSION "6.8.4-200.fc39.x86_64") +set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") + + + +set(CMAKE_SYSTEM "Linux-6.8.4-200.fc39.x86_64") +set(CMAKE_SYSTEM_NAME "Linux") +set(CMAKE_SYSTEM_VERSION "6.8.4-200.fc39.x86_64") +set(CMAKE_SYSTEM_PROCESSOR "x86_64") + +set(CMAKE_CROSSCOMPILING "FALSE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/Bolt_Dash/CMakeFiles/3.29.2/CompilerIdCXX/CMakeCXXCompilerId.cpp b/Bolt_Dash/CMakeFiles/3.29.2/CompilerIdCXX/CMakeCXXCompilerId.cpp new file mode 100644 index 0000000..9a5e8f8 --- /dev/null +++ b/Bolt_Dash/CMakeFiles/3.29.2/CompilerIdCXX/CMakeCXXCompilerId.cpp @@ -0,0 +1,878 @@ +/* This source file must have a .cpp extension so that all C++ compilers + recognize the extension without flags. Borland does not know .cxx for + example. */ +#ifndef __cplusplus +# error "A C compiler has been selected for C++." +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__open_xl__) && defined(__clang__) +# define COMPILER_ID "IBMClang" +# define COMPILER_VERSION_MAJOR DEC(__open_xl_version__) +# define COMPILER_VERSION_MINOR DEC(__open_xl_release__) +# define COMPILER_VERSION_PATCH DEC(__open_xl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__open_xl_ptf_fix_level__) + + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 +# define COMPILER_ID "XL" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(__clang__) && defined(__cray__) +# define COMPILER_ID "CrayClang" +# define COMPILER_VERSION_MAJOR DEC(__cray_major__) +# define COMPILER_VERSION_MINOR DEC(__cray_minor__) +# define COMPILER_VERSION_PATCH DEC(__cray_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TASKING__) +# define COMPILER_ID "Tasking" + # define COMPILER_VERSION_MAJOR DEC(__VERSION__/1000) + # define COMPILER_VERSION_MINOR DEC(__VERSION__ % 100) +# define COMPILER_VERSION_INTERNAL DEC(__VERSION__) + +#elif defined(__ORANGEC__) +# define COMPILER_ID "OrangeC" +# define COMPILER_VERSION_MAJOR DEC(__ORANGEC_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__ORANGEC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__ORANGEC_PATCHLEVEL__) + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION/100 % 100) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) && defined(__ti__) +# define COMPILER_ID "TIClang" + # define COMPILER_VERSION_MAJOR DEC(__ti_major__) + # define COMPILER_VERSION_MINOR DEC(__ti_minor__) + # define COMPILER_VERSION_PATCH DEC(__ti_patchlevel__) +# define COMPILER_VERSION_INTERNAL DEC(__ti_version__) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__)) +# define COMPILER_ID "LCC" +# define COMPILER_VERSION_MAJOR DEC(__LCC__ / 100) +# define COMPILER_VERSION_MINOR DEC(__LCC__ % 100) +# if defined(__LCC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__) +# endif +# if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define SIMULATE_ID "GNU" +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif +# endif + +#elif defined(__GNUC__) || defined(__GNUG__) +# define COMPILER_ID "GNU" +# if defined(__GNUC__) +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# else +# define COMPILER_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(_ADI_COMPILER) +# define COMPILER_ID "ADSP" +#if defined(__VERSIONNUM__) + /* __VERSIONNUM__ = 0xVVRRPPTT */ +# define COMPILER_VERSION_MAJOR DEC(__VERSIONNUM__ >> 24 & 0xFF) +# define COMPILER_VERSION_MINOR DEC(__VERSIONNUM__ >> 16 & 0xFF) +# define COMPILER_VERSION_PATCH DEC(__VERSIONNUM__ >> 8 & 0xFF) +# define COMPILER_VERSION_TWEAK DEC(__VERSIONNUM__ & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +# elif defined(_ADI_COMPILER) +# define PLATFORM_ID "ADSP" + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__clang__) && defined(__ti__) +# if defined(__ARM_ARCH) +# define ARCHITECTURE_ID "Arm" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +# elif defined(__ADSPSHARC__) +# define ARCHITECTURE_ID "SHARC" + +# elif defined(__ADSPBLACKFIN__) +# define ARCHITECTURE_ID "Blackfin" + +#elif defined(__TASKING__) + +# if defined(__CTC__) || defined(__CPTC__) +# define ARCHITECTURE_ID "TriCore" + +# elif defined(__CMCS__) +# define ARCHITECTURE_ID "MCS" + +# elif defined(__CARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__CARC__) +# define ARCHITECTURE_ID "ARC" + +# elif defined(__C51__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__CPCP__) +# define ARCHITECTURE_ID "PCP" + +# else +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L +# if defined(__INTEL_CXX11_MODE__) +# if defined(__cpp_aggregate_nsdmi) +# define CXX_STD 201402L +# else +# define CXX_STD 201103L +# endif +# else +# define CXX_STD 199711L +# endif +#elif defined(_MSC_VER) && defined(_MSVC_LANG) +# define CXX_STD _MSVC_LANG +#else +# define CXX_STD __cplusplus +#endif + +const char* info_language_standard_default = "INFO" ":" "standard_default[" +#if CXX_STD > 202002L + "23" +#elif CXX_STD > 201703L + "20" +#elif CXX_STD >= 201703L + "17" +#elif CXX_STD >= 201402L + "14" +#elif CXX_STD >= 201103L + "11" +#else + "98" +#endif +"]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +#if (defined(__clang__) || defined(__GNUC__) || defined(__xlC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} diff --git a/Bolt_Dash/CMakeFiles/3.29.2/CompilerIdCXX/a.out b/Bolt_Dash/CMakeFiles/3.29.2/CompilerIdCXX/a.out new file mode 100755 index 0000000..35b2045 Binary files /dev/null and b/Bolt_Dash/CMakeFiles/3.29.2/CompilerIdCXX/a.out differ diff --git a/Bolt_Dash/CMakeFiles/CMakeConfigureLog.yaml b/Bolt_Dash/CMakeFiles/CMakeConfigureLog.yaml new file mode 100644 index 0000000..30c820f --- /dev/null +++ b/Bolt_Dash/CMakeFiles/CMakeConfigureLog.yaml @@ -0,0 +1,275 @@ + +--- +events: + - + kind: "message-v1" + backtrace: + - "/home/mason/.local/lib/python3.12/site-packages/cmake/data/share/cmake-3.29/Modules/CMakeDetermineSystem.cmake:205 (message)" + - "CMakeLists.txt:6 (project)" + message: | + The system is: Linux - 6.8.4-200.fc39.x86_64 - x86_64 + - + kind: "message-v1" + backtrace: + - "/home/mason/.local/lib/python3.12/site-packages/cmake/data/share/cmake-3.29/Modules/CMakeDetermineCompilerId.cmake:17 (message)" + - "/home/mason/.local/lib/python3.12/site-packages/cmake/data/share/cmake-3.29/Modules/CMakeDetermineCompilerId.cmake:64 (__determine_compiler_id_test)" + - "/home/mason/.local/lib/python3.12/site-packages/cmake/data/share/cmake-3.29/Modules/CMakeDetermineCXXCompiler.cmake:126 (CMAKE_DETERMINE_COMPILER_ID)" + - "CMakeLists.txt:6 (project)" + message: | + Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded. + Compiler: /usr/bin/c++ + Build flags: + Id flags: + + The output was: + 0 + + + Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "a.out" + + The CXX compiler identification is GNU, found in: + /home/mason/git/bolt-dash-cpp/Bolt_Dash/CMakeFiles/3.29.2/CompilerIdCXX/a.out + + - + kind: "try_compile-v1" + backtrace: + - "/home/mason/.local/lib/python3.12/site-packages/cmake/data/share/cmake-3.29/Modules/CMakeDetermineCompilerABI.cmake:64 (try_compile)" + - "/home/mason/.local/lib/python3.12/site-packages/cmake/data/share/cmake-3.29/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:6 (project)" + checks: + - "Detecting CXX compiler ABI info" + directories: + source: "/home/mason/git/bolt-dash-cpp/Bolt_Dash/CMakeFiles/CMakeScratch/TryCompile-4IIrPn" + binary: "/home/mason/git/bolt-dash-cpp/Bolt_Dash/CMakeFiles/CMakeScratch/TryCompile-4IIrPn" + cmakeVariables: + CMAKE_CXX_FLAGS: "" + CMAKE_CXX_FLAGS_DEBUG: "-g" + CMAKE_EXE_LINKER_FLAGS: "" + buildResult: + variable: "CMAKE_CXX_ABI_COMPILED" + cached: true + stdout: | + Change Dir: '/home/mason/git/bolt-dash-cpp/Bolt_Dash/CMakeFiles/CMakeScratch/TryCompile-4IIrPn' + + Run Build Command(s): /home/mason/.local/lib/python3.12/site-packages/cmake/data/bin/cmake -E env VERBOSE=1 /usr/bin/gmake -f Makefile cmTC_69b58/fast + /usr/bin/gmake -f CMakeFiles/cmTC_69b58.dir/build.make CMakeFiles/cmTC_69b58.dir/build + gmake[1]: Entering directory '/home/mason/git/bolt-dash-cpp/Bolt_Dash/CMakeFiles/CMakeScratch/TryCompile-4IIrPn' + Building CXX object CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.o + /usr/bin/c++ -v -o CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.o -c /home/mason/.local/lib/python3.12/site-packages/cmake/data/share/cmake-3.29/Modules/CMakeCXXCompilerABI.cpp + Using built-in specs. + COLLECT_GCC=/usr/bin/c++ + OFFLOAD_TARGET_NAMES=nvptx-none + OFFLOAD_TARGET_DEFAULT=1 + Target: x86_64-redhat-linux + Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,m2,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --enable-libstdcxx-backtrace --with-libstdcxx-zoneinfo=/usr/share/zoneinfo --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl=/builddir/build/BUILD/gcc-13.2.1-20240316/obj-x86_64-redhat-linux/isl-install --enable-offload-targets=nvptx-none --without-cuda-driver --enable-offload-defaulted --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux --with-build-config=bootstrap-lto --enable-link-serialization=1 + Thread model: posix + Supported LTO compression algorithms: zlib zstd + gcc version 13.2.1 20240316 (Red Hat 13.2.1-7) (GCC) + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_69b58.dir/' + /usr/libexec/gcc/x86_64-redhat-linux/13/cc1plus -quiet -v -D_GNU_SOURCE /home/mason/.local/lib/python3.12/site-packages/cmake/data/share/cmake-3.29/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpdir CMakeFiles/cmTC_69b58.dir/ -dumpbase CMakeCXXCompilerABI.cpp.cpp -dumpbase-ext .cpp -mtune=generic -march=x86-64 -version -o /tmp/cceMdFSa.s + GNU C++17 (GCC) version 13.2.1 20240316 (Red Hat 13.2.1-7) (x86_64-redhat-linux) + compiled by GNU C version 13.2.1 20240316 (Red Hat 13.2.1-7), GMP version 6.2.1, MPFR version 4.2.0-p12, MPC version 1.3.1, isl version isl-0.24-GMP + + GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 + ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/13/include-fixed" + ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include" + #include "..." search starts here: + #include <...> search starts here: + /usr/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13 + /usr/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/x86_64-redhat-linux + /usr/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/backward + /usr/lib/gcc/x86_64-redhat-linux/13/include + /usr/local/include + /usr/include + End of search list. + Compiler executable checksum: 1597859996ad5af9a6269f983f6a2e78 + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_69b58.dir/' + as -v --64 -o CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.o /tmp/cceMdFSa.s + GNU assembler version 2.40 (x86_64-redhat-linux) using BFD version version 2.40-14.fc39 + COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/13/:/usr/libexec/gcc/x86_64-redhat-linux/13/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/13/:/usr/lib/gcc/x86_64-redhat-linux/ + LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/13/:/usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/13/../../../:/lib/:/usr/lib/ + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.' + Linking CXX executable cmTC_69b58 + /home/mason/.local/lib/python3.12/site-packages/cmake/data/bin/cmake -E cmake_link_script CMakeFiles/cmTC_69b58.dir/link.txt --verbose=1 + /usr/bin/c++ -v -Wl,-v CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_69b58 + Using built-in specs. + COLLECT_GCC=/usr/bin/c++ + COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/13/lto-wrapper + OFFLOAD_TARGET_NAMES=nvptx-none + OFFLOAD_TARGET_DEFAULT=1 + Target: x86_64-redhat-linux + Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,m2,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --enable-libstdcxx-backtrace --with-libstdcxx-zoneinfo=/usr/share/zoneinfo --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl=/builddir/build/BUILD/gcc-13.2.1-20240316/obj-x86_64-redhat-linux/isl-install --enable-offload-targets=nvptx-none --without-cuda-driver --enable-offload-defaulted --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux --with-build-config=bootstrap-lto --enable-link-serialization=1 + Thread model: posix + Supported LTO compression algorithms: zlib zstd + gcc version 13.2.1 20240316 (Red Hat 13.2.1-7) (GCC) + COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/13/:/usr/libexec/gcc/x86_64-redhat-linux/13/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/13/:/usr/lib/gcc/x86_64-redhat-linux/ + LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/13/:/usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/13/../../../:/lib/:/usr/lib/ + COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_69b58' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'cmTC_69b58.' + /usr/libexec/gcc/x86_64-redhat-linux/13/collect2 -plugin /usr/libexec/gcc/x86_64-redhat-linux/13/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/x86_64-redhat-linux/13/lto-wrapper -plugin-opt=-fresolution=/tmp/cc1p67YA.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o cmTC_69b58 /usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/13/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/13 -L/usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/13/../../.. -v CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-redhat-linux/13/crtend.o /usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crtn.o + collect2 version 13.2.1 20240316 (Red Hat 13.2.1-7) + /usr/bin/ld -plugin /usr/libexec/gcc/x86_64-redhat-linux/13/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/x86_64-redhat-linux/13/lto-wrapper -plugin-opt=-fresolution=/tmp/cc1p67YA.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o cmTC_69b58 /usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/13/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/13 -L/usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/13/../../.. -v CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-redhat-linux/13/crtend.o /usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crtn.o + GNU ld version 2.40-14.fc39 + COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_69b58' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'cmTC_69b58.' + gmake[1]: Leaving directory '/home/mason/git/bolt-dash-cpp/Bolt_Dash/CMakeFiles/CMakeScratch/TryCompile-4IIrPn' + + exitCode: 0 + - + kind: "message-v1" + backtrace: + - "/home/mason/.local/lib/python3.12/site-packages/cmake/data/share/cmake-3.29/Modules/CMakeDetermineCompilerABI.cmake:134 (message)" + - "/home/mason/.local/lib/python3.12/site-packages/cmake/data/share/cmake-3.29/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:6 (project)" + message: | + Parsed CXX implicit include dir info: rv=done + found start of include info + found start of implicit include info + add: [/usr/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13] + add: [/usr/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/x86_64-redhat-linux] + add: [/usr/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/backward] + add: [/usr/lib/gcc/x86_64-redhat-linux/13/include] + add: [/usr/local/include] + add: [/usr/include] + end of search list found + collapse include dir [/usr/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13] ==> [/usr/include/c++/13] + collapse include dir [/usr/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/x86_64-redhat-linux] ==> [/usr/include/c++/13/x86_64-redhat-linux] + collapse include dir [/usr/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/backward] ==> [/usr/include/c++/13/backward] + collapse include dir [/usr/lib/gcc/x86_64-redhat-linux/13/include] ==> [/usr/lib/gcc/x86_64-redhat-linux/13/include] + collapse include dir [/usr/local/include] ==> [/usr/local/include] + collapse include dir [/usr/include] ==> [/usr/include] + implicit include dirs: [/usr/include/c++/13;/usr/include/c++/13/x86_64-redhat-linux;/usr/include/c++/13/backward;/usr/lib/gcc/x86_64-redhat-linux/13/include;/usr/local/include;/usr/include] + + + - + kind: "message-v1" + backtrace: + - "/home/mason/.local/lib/python3.12/site-packages/cmake/data/share/cmake-3.29/Modules/CMakeDetermineCompilerABI.cmake:170 (message)" + - "/home/mason/.local/lib/python3.12/site-packages/cmake/data/share/cmake-3.29/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:6 (project)" + message: | + Parsed CXX implicit link information: + link line regex: [^( *|.*[/\\])(ld[0-9]*(\\.[a-z]+)?|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\\]+-)?ld|collect2)[^/\\]*( |$)] + linker tool regex: [^[ ]*(->|")?[ ]*(([^"]*[/\\])?(ld[0-9]*(\\.[a-z]+)?))("|,| |$)] + ignore line: [Change Dir: '/home/mason/git/bolt-dash-cpp/Bolt_Dash/CMakeFiles/CMakeScratch/TryCompile-4IIrPn'] + ignore line: [] + ignore line: [Run Build Command(s): /home/mason/.local/lib/python3.12/site-packages/cmake/data/bin/cmake -E env VERBOSE=1 /usr/bin/gmake -f Makefile cmTC_69b58/fast] + ignore line: [/usr/bin/gmake -f CMakeFiles/cmTC_69b58.dir/build.make CMakeFiles/cmTC_69b58.dir/build] + ignore line: [gmake[1]: Entering directory '/home/mason/git/bolt-dash-cpp/Bolt_Dash/CMakeFiles/CMakeScratch/TryCompile-4IIrPn'] + ignore line: [Building CXX object CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.o] + ignore line: [/usr/bin/c++ -v -o CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.o -c /home/mason/.local/lib/python3.12/site-packages/cmake/data/share/cmake-3.29/Modules/CMakeCXXCompilerABI.cpp] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/c++] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-redhat-linux] + ignore line: [Configured with: ../configure --enable-bootstrap --enable-languages=c c++ fortran objc obj-c++ ada go d m2 lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --enable-libstdcxx-backtrace --with-libstdcxx-zoneinfo=/usr/share/zoneinfo --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl=/builddir/build/BUILD/gcc-13.2.1-20240316/obj-x86_64-redhat-linux/isl-install --enable-offload-targets=nvptx-none --without-cuda-driver --enable-offload-defaulted --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux --with-build-config=bootstrap-lto --enable-link-serialization=1] + ignore line: [Thread model: posix] + ignore line: [Supported LTO compression algorithms: zlib zstd] + ignore line: [gcc version 13.2.1 20240316 (Red Hat 13.2.1-7) (GCC) ] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_69b58.dir/'] + ignore line: [ /usr/libexec/gcc/x86_64-redhat-linux/13/cc1plus -quiet -v -D_GNU_SOURCE /home/mason/.local/lib/python3.12/site-packages/cmake/data/share/cmake-3.29/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpdir CMakeFiles/cmTC_69b58.dir/ -dumpbase CMakeCXXCompilerABI.cpp.cpp -dumpbase-ext .cpp -mtune=generic -march=x86-64 -version -o /tmp/cceMdFSa.s] + ignore line: [GNU C++17 (GCC) version 13.2.1 20240316 (Red Hat 13.2.1-7) (x86_64-redhat-linux)] + ignore line: [ compiled by GNU C version 13.2.1 20240316 (Red Hat 13.2.1-7) GMP version 6.2.1 MPFR version 4.2.0-p12 MPC version 1.3.1 isl version isl-0.24-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/13/include-fixed"] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include"] + ignore line: [#include "..." search starts here:] + ignore line: [#include <...> search starts here:] + ignore line: [ /usr/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13] + ignore line: [ /usr/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/x86_64-redhat-linux] + ignore line: [ /usr/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/backward] + ignore line: [ /usr/lib/gcc/x86_64-redhat-linux/13/include] + ignore line: [ /usr/local/include] + ignore line: [ /usr/include] + ignore line: [End of search list.] + ignore line: [Compiler executable checksum: 1597859996ad5af9a6269f983f6a2e78] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_69b58.dir/'] + ignore line: [ as -v --64 -o CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.o /tmp/cceMdFSa.s] + ignore line: [GNU assembler version 2.40 (x86_64-redhat-linux) using BFD version version 2.40-14.fc39] + ignore line: [COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/13/:/usr/libexec/gcc/x86_64-redhat-linux/13/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/13/:/usr/lib/gcc/x86_64-redhat-linux/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/13/:/usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/13/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.'] + ignore line: [Linking CXX executable cmTC_69b58] + ignore line: [/home/mason/.local/lib/python3.12/site-packages/cmake/data/bin/cmake -E cmake_link_script CMakeFiles/cmTC_69b58.dir/link.txt --verbose=1] + ignore line: [/usr/bin/c++ -v -Wl -v CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_69b58] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/c++] + ignore line: [COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/13/lto-wrapper] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-redhat-linux] + ignore line: [Configured with: ../configure --enable-bootstrap --enable-languages=c c++ fortran objc obj-c++ ada go d m2 lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --enable-libstdcxx-backtrace --with-libstdcxx-zoneinfo=/usr/share/zoneinfo --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl=/builddir/build/BUILD/gcc-13.2.1-20240316/obj-x86_64-redhat-linux/isl-install --enable-offload-targets=nvptx-none --without-cuda-driver --enable-offload-defaulted --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux --with-build-config=bootstrap-lto --enable-link-serialization=1] + ignore line: [Thread model: posix] + ignore line: [Supported LTO compression algorithms: zlib zstd] + ignore line: [gcc version 13.2.1 20240316 (Red Hat 13.2.1-7) (GCC) ] + ignore line: [COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/13/:/usr/libexec/gcc/x86_64-redhat-linux/13/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/13/:/usr/lib/gcc/x86_64-redhat-linux/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/13/:/usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/13/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_69b58' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'cmTC_69b58.'] + link line: [ /usr/libexec/gcc/x86_64-redhat-linux/13/collect2 -plugin /usr/libexec/gcc/x86_64-redhat-linux/13/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/x86_64-redhat-linux/13/lto-wrapper -plugin-opt=-fresolution=/tmp/cc1p67YA.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o cmTC_69b58 /usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/13/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/13 -L/usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/13/../../.. -v CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-redhat-linux/13/crtend.o /usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crtn.o] + arg [/usr/libexec/gcc/x86_64-redhat-linux/13/collect2] ==> ignore + arg [-plugin] ==> ignore + arg [/usr/libexec/gcc/x86_64-redhat-linux/13/liblto_plugin.so] ==> ignore + arg [-plugin-opt=/usr/libexec/gcc/x86_64-redhat-linux/13/lto-wrapper] ==> ignore + arg [-plugin-opt=-fresolution=/tmp/cc1p67YA.res] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [--build-id] ==> ignore + arg [--no-add-needed] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib64/ld-linux-x86-64.so.2] ==> ignore + arg [-o] ==> ignore + arg [cmTC_69b58] ==> ignore + arg [/usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crt1.o] ==> obj [/usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crt1.o] + arg [/usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crti.o] ==> obj [/usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crti.o] + arg [/usr/lib/gcc/x86_64-redhat-linux/13/crtbegin.o] ==> obj [/usr/lib/gcc/x86_64-redhat-linux/13/crtbegin.o] + arg [-L/usr/lib/gcc/x86_64-redhat-linux/13] ==> dir [/usr/lib/gcc/x86_64-redhat-linux/13] + arg [-L/usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64] ==> dir [/usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64] + arg [-L/lib/../lib64] ==> dir [/lib/../lib64] + arg [-L/usr/lib/../lib64] ==> dir [/usr/lib/../lib64] + arg [-L/usr/lib/gcc/x86_64-redhat-linux/13/../../..] ==> dir [/usr/lib/gcc/x86_64-redhat-linux/13/../../..] + arg [-v] ==> ignore + arg [CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore + arg [-lstdc++] ==> lib [stdc++] + arg [-lm] ==> lib [m] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [-lc] ==> lib [c] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [/usr/lib/gcc/x86_64-redhat-linux/13/crtend.o] ==> obj [/usr/lib/gcc/x86_64-redhat-linux/13/crtend.o] + arg [/usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crtn.o] ==> obj [/usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crtn.o] + ignore line: [collect2 version 13.2.1 20240316 (Red Hat 13.2.1-7)] + ignore line: [/usr/bin/ld -plugin /usr/libexec/gcc/x86_64-redhat-linux/13/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/x86_64-redhat-linux/13/lto-wrapper -plugin-opt=-fresolution=/tmp/cc1p67YA.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o cmTC_69b58 /usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/13/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/13 -L/usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/13/../../.. -v CMakeFiles/cmTC_69b58.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-redhat-linux/13/crtend.o /usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crtn.o] + linker tool for 'CXX': /usr/bin/ld + collapse obj [/usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crt1.o] ==> [/usr/lib64/crt1.o] + collapse obj [/usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crti.o] ==> [/usr/lib64/crti.o] + collapse obj [/usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64/crtn.o] ==> [/usr/lib64/crtn.o] + collapse library dir [/usr/lib/gcc/x86_64-redhat-linux/13] ==> [/usr/lib/gcc/x86_64-redhat-linux/13] + collapse library dir [/usr/lib/gcc/x86_64-redhat-linux/13/../../../../lib64] ==> [/usr/lib64] + collapse library dir [/lib/../lib64] ==> [/lib64] + collapse library dir [/usr/lib/../lib64] ==> [/usr/lib64] + collapse library dir [/usr/lib/gcc/x86_64-redhat-linux/13/../../..] ==> [/usr/lib] + implicit libs: [stdc++;m;gcc_s;gcc;c;gcc_s;gcc] + implicit objs: [/usr/lib64/crt1.o;/usr/lib64/crti.o;/usr/lib/gcc/x86_64-redhat-linux/13/crtbegin.o;/usr/lib/gcc/x86_64-redhat-linux/13/crtend.o;/usr/lib64/crtn.o] + implicit dirs: [/usr/lib/gcc/x86_64-redhat-linux/13;/usr/lib64;/lib64;/usr/lib] + implicit fwks: [] + + + - + kind: "message-v1" + backtrace: + - "/home/mason/.local/lib/python3.12/site-packages/cmake/data/share/cmake-3.29/Modules/Internal/CMakeDetermineLinkerId.cmake:40 (message)" + - "/home/mason/.local/lib/python3.12/site-packages/cmake/data/share/cmake-3.29/Modules/CMakeDetermineCompilerABI.cmake:207 (cmake_determine_linker_id)" + - "/home/mason/.local/lib/python3.12/site-packages/cmake/data/share/cmake-3.29/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:6 (project)" + message: | + Running the CXX compiler's linker: "/usr/bin/ld" "-v" + GNU ld version 2.40-14.fc39 +... diff --git a/Bolt_Dash/CMakeFiles/cmake.check_cache b/Bolt_Dash/CMakeFiles/cmake.check_cache new file mode 100644 index 0000000..3dccd73 --- /dev/null +++ b/Bolt_Dash/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/Bolt_Dash/CMakeLists.txt b/Bolt_Dash/CMakeLists.txt index b522e7a..b55bcf0 100644 --- a/Bolt_Dash/CMakeLists.txt +++ b/Bolt_Dash/CMakeLists.txt @@ -13,7 +13,21 @@ if (Qt6_VERSION VERSION_GREATER_EQUAL 6.3) qt_standard_project_setup() endif() -qt_add_executable(Bolt_DashApp src/main.cpp) +qt_add_executable(Bolt_DashApp src/main.cpp + backend.h backend.cpp + can.cpp + can.h + web.h + web.cpp + gpsprocessing.cpp gpsprocessing.h + src/includes/source/NMEAParser.cpp + src/includes/source/GPSService.cpp + src/includes/source/GPSFix.cpp + src/includes/source/NMEACommand.cpp + src/includes/source/NumberConversion.cpp + nmea_decoder.cpp nmea_decoder.h + +) qt_add_resources(Bolt_DashApp "configuration" PREFIX "/" @@ -21,6 +35,8 @@ qt_add_resources(Bolt_DashApp "configuration" qtquickcontrols2.conf ) +target_include_directories(Bolt_DashApp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/includes/headers) + target_link_libraries(Bolt_DashApp PRIVATE Qt6::Core Qt6::Gui @@ -29,10 +45,20 @@ target_link_libraries(Bolt_DashApp PRIVATE pigpio ) -if (BUILD_QDS_COMPONENTS) - include(${CMAKE_CURRENT_SOURCE_DIR}/qmlcomponents) +find_library(PIGPIO_LIBRARY pigpio) +if (PIGPIO_LIBRARY) + target_link_libraries(Bolt_DashApp PRIVATE ${PIGPIO_LIBRARY}) endif() +find_library(GPS_LIBRARY gps) +if (GPS_LIBRARY) + target_link_libraries(Bolt_DashApp PRIVATE ${GPS_LIBRARY}) +endif() + +# if (BUILD_QDS_COMPONENTS) +# include(${CMAKE_CURRENT_SOURCE_DIR}/qmlcomponents) +# endif() + include(${CMAKE_CURRENT_SOURCE_DIR}/qmlmodules) if (LINK_INSIGHT) diff --git a/Bolt_Dash/FaultMotorStatus.qml b/Bolt_Dash/FaultMotorStatus.qml new file mode 100644 index 0000000..68c2108 --- /dev/null +++ b/Bolt_Dash/FaultMotorStatus.qml @@ -0,0 +1,5 @@ +import QtQuick 2.15 + +Item { + +} diff --git a/Bolt_Dash/backend.cpp b/Bolt_Dash/backend.cpp new file mode 100644 index 0000000..f830d80 --- /dev/null +++ b/Bolt_Dash/backend.cpp @@ -0,0 +1,397 @@ +#include "backend.h" +#include "can.h" +#include "constants.h" +#include "gpsprocessing.h" +#include "web.h" +#include +#include +#include +#include +#include +#include +#include +#include + +// Create Backend class which can be included in QML +Backend::Backend(QObject *parent) : QObject(parent), m_motorTemp{}, m_auxVoltage{}, m_auxPercent{}, + m_packSOC{}, m_highCellTemp{}, m_lowCellTemp{}, m_bmsTemp{}, m_motorSpeed{}, m_bikeSpeed{}, m_mcTemp{}, + m_bmsFault{}, m_packVoltage{}, m_motorOn{}, m_mcFault{}, m_bikeStatus{}, m_packCurrent{}, m_bmsErrorCodes{}, + m_bmsErrorCodesString{}, m_bmsError{}, m_bmsWarning{}, m_lat{}, m_lon{} { + std::thread update_vars(&Backend::updateVars, this); + update_vars.detach(); + + std::thread run_app(&web::runApp); + run_app.detach(); + + std::thread run_gps(&gpsMain); + run_gps.detach(); +} + +// Calls the set functions with the values from data +void Backend::updateVars() { + while (true) { + m.lock(); + // The only scaling here is to put the value into the right unit + // all scaling defined in constants.h + setMotorTemp(data.motor_temperature * MOTOR_TEMPERATURE_SCALE); // celsius + setAuxVoltage(data.aux_voltage * AUX_VOLTAGE_SCALE); // volts + setAuxPercent(data.aux_percent * AUX_PERCENT_SCALE); // percent + setPackSOC(data.pack_state_of_charge * PACK_STATE_OF_CHARGE_SCALE); // percent + setPackVoltage(data.pack_voltage * PACK_VOLTAGE_SCALE); // Voltage + setPackCurrent(data.pack_current * PACK_CURRENT_SCALE); // amps + setHighCellTemp(data.high_cell_temp * HIGH_CELL_TEMP_SCALE); // celsius + setLowCellTemp(data.low_cell_temp * LOW_CELL_TEMP_SCALE); // celsius + setBmsTemp(data.bms_temperature * BMS_TEMPERATURE_SCALE); // celsius + setMotorSpeed(data.motor_speed * MOTOR_SPEED_SCALE); // rpm + setBikeSpeed(data.motor_speed * BIKE_SPEED_SCALE); // mph + setMcTemp(data.mc_temperature * MC_TEMPERATURE_SCALE); // celsius + setBmsFault(data.bms_fault); + setMotorOn(data.motor_on); + setMcFault(data.mc_fault); + setBikeStatus(data.bike_status); + setBmsErrorCodes(data.bms_error_codes); + setBmsError(data.bms_error); + setBmsWarning(data.bms_warning); + std::vector warnings = getErrorCodeStrings(data.bms_error_codes); + setBmsErrorCodesString(warnings); + m.unlock(); + + gps_m.lock(); + setLat(gps_lat); + setLon(gps_lon); + // std::cout << "Lat: " << lat() << " Lon: " << lon() << std::endl; + gps_m.unlock(); + // Debug Message + // std::cout << "MotorTemp: " << motorTemp() << " AuxVoltage: " << auxVoltage() << " AuxPercent: " << auxPercent() << " PackSOC: " << packSOC() << " HighCellTemp: " << highCellTemp() << " LowCellTemp: " << lowCellTemp() << " BmsTemp: " << bmsTemp() << " MotorSpeed: " << motorSpeed() << " BikeSpeed: " << bikeSpeed() << std::endl; + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } +} + +std::vector Backend::getErrorCodeStrings(uint32_t errorCodes) { + std::vector warnings; + // Warnings + if (errorCodes & bms_warnings.discharge_limit_enforcement) { + warnings.push_back("Discharge Limit Enforcement"); + } + if (errorCodes & bms_warnings.cell_balancing_stuck_off) { + warnings.push_back("Cell Balancing Stuck Off"); + } + if (errorCodes & bms_warnings.weak_cell) { + warnings.push_back("Weak Cell"); + } + if (errorCodes & bms_warnings.current_sensor) { + warnings.push_back("Current Sensor"); + } + if (errorCodes & bms_warnings.weak_pack) { + warnings.push_back("Weak Pack"); + } + if (errorCodes & bms_warnings.fan_monitor) { + warnings.push_back("Fan Monitor"); + } + // Errors + if (errorCodes & bms_warnings.charger_safety_relay) { + warnings.push_back("Charger Safety Relay"); + } + if (errorCodes & bms_errors.internal_hardware) { + warnings.push_back("Internal Hardware"); + } + if (errorCodes & bms_warnings.internal_heatsink_thermistor) { + warnings.push_back("Internal Heatsink Thermistor"); + } + if (errorCodes & bms_errors.internal_software) { + warnings.push_back("Internal Software"); + } + if (errorCodes & bms_errors.highest_cell_voltage_too_high) { + warnings.push_back("Highest Cell Voltage Too Low"); + } + if (errorCodes & bms_errors.lowest_cell_voltage_too_low) { + warnings.push_back("Lowest Cell Voltage Too Low"); + } + if (errorCodes & bms_errors.pack_too_hot) { + warnings.push_back("Pack Too Hot"); + } + if (errorCodes & bms_errors.internal_communication) { + warnings.push_back("Internal Communication"); + } + if (errorCodes & bms_errors.low_cell_voltage) { + warnings.push_back("Low Cell Voltage"); + } + if (errorCodes & bms_warnings.open_wiring) { + warnings.push_back("Open Wiring"); + } + if (errorCodes & bms_errors.highest_cell_voltage_over_5v) { + warnings.push_back("Highest Cell Voltage Over 5v"); + } + if (errorCodes & bms_errors.cell_asic_fault) { + warnings.push_back("Cell ASIC Fault"); + } + if (errorCodes & bms_warnings.thermistor_fault) { + warnings.push_back("Thermistor Fault"); + } + if (errorCodes & bms_warnings.external_communication) { + warnings.push_back("External Communication"); + } + if (errorCodes & bms_errors.redundant_power_supply) { + warnings.push_back("Redundant Power Supply"); + } + if (errorCodes & bms_errors.high_voltage_isolation) { + warnings.push_back("High Voltage Isolation"); + } + if (errorCodes & bms_errors.input_power_supply) { + warnings.push_back("Input Power Supply"); + } + if (errorCodes & bms_warnings.charge_limit_enforcement) { + warnings.push_back("Charge Limit Enforcement"); + } + return warnings; +} + +// Functions to get variable values +// { // Brackets for collapsability +double Backend::motorTemp() const { + return m_motorTemp; +} + +double Backend::auxVoltage() const { + return m_auxVoltage; +} + +double Backend::auxPercent() const { + return m_auxPercent; +} + +double Backend::packSOC() const { + return m_packSOC; +} + +double Backend::packVoltage() const { + return m_packVoltage; +} + +double Backend::highCellTemp() const { + return m_highCellTemp; +} + +double Backend::lowCellTemp() const { + return m_lowCellTemp; +} + +double Backend::bmsTemp() const { + return m_bmsTemp; +} + +double Backend::motorSpeed() const { + return m_motorSpeed; +} + +double Backend::bikeSpeed() const { + return m_bikeSpeed; +} + +double Backend::mcTemp() const { + return m_mcTemp; +} + +bool Backend::bmsFault() const { + return m_bmsFault; +} + +bool Backend::mcFault() const { + return m_mcFault; +} + +bool Backend::motorOn() const { + return m_motorOn; +} + +int Backend::bikeStatus() const { + return m_bikeStatus; +} + +double Backend::packCurrent() const { + return m_packCurrent; +} + +bool Backend::bmsError() const { + return m_bmsError; +} + +bool Backend::bmsWarning() const { + return m_bmsWarning; +} + +uint32_t Backend::bmsErrorCodes() const { + return m_bmsErrorCodes; +} + +std::vector Backend::bmsErrorCodesString() const { + return m_bmsErrorCodesString; +} + +double Backend::lat() const { + return m_lat; +} + +double Backend::lon() const { + return m_lon; +} +// } + +// Setter Functions +// { // Brackets for collapsability +void Backend::setMotorTemp(const double temp) { + if (m_motorTemp != temp) { + m_motorTemp = temp; + emit motorTempChanged(); + } +} + +void Backend::setAuxVoltage(const double cap) { + if (m_auxVoltage != cap) { + m_auxVoltage = cap; + emit auxVoltageChanged(); + } +} + +void Backend::setAuxPercent(const double cap) { + if (m_auxPercent != cap) { + m_auxPercent = cap; + emit auxPercentChanged(); + } +} + +void Backend::setPackSOC(const double soc) { + if (m_packSOC != soc) { + m_packSOC = soc; + emit packSOCChanged(); + } +} + +void Backend::setPackVoltage(const double voltage) { + if (m_packVoltage != voltage) { + m_packVoltage = voltage; + emit packVoltageChanged(); + } +} + +void Backend::setHighCellTemp(const double temp) { + if (m_highCellTemp != temp) { + m_highCellTemp = temp; + emit highCellTempChanged(); + } +} + +void Backend::setLowCellTemp(const double temp) { + if (m_lowCellTemp != temp) { + m_lowCellTemp = temp; + emit lowCellTempChanged(); + } +} + +void Backend::setBmsTemp(const double temp) { + if (m_bmsTemp != temp) { + m_bmsTemp = temp; + emit bmsTempChanged(); + } +} + +void Backend::setMotorSpeed(const double speed) { + if (m_motorSpeed != speed) { + m_motorSpeed = speed; + emit motorSpeedChanged(); + } +} + +void Backend::setBikeSpeed(const double speed) { + if (m_bikeSpeed != speed) { + m_bikeSpeed = speed; + emit bikeSpeedChanged(); + } +} + +void Backend::setMcTemp(const double temp) { + if (m_mcTemp != temp) { + m_mcTemp = temp; + emit mcTempChanged(); + } +} + +void Backend::setBmsFault(const bool fault) { + if (m_bmsFault != fault) { + m_bmsFault = fault; + emit bmsFaultChanged(); + } +} + +void Backend::setMcFault(const bool fault) { + if (m_mcFault != fault) { + m_mcFault = fault; + emit mcFaultChanged(); + } +} + +void Backend::setMotorOn(const bool on) { + if (m_motorOn != on) { + m_motorOn = on; + emit motorOnChanged(); + } +} + +void Backend::setBikeStatus(const int status) { + if (m_bikeStatus != status) { + m_bikeStatus = status; + emit bikeStatusChanged(); + } +} + +void Backend::setPackCurrent(const double current) { + if (m_packCurrent != current) { + m_packCurrent = current; + emit packCurrentChanged(); + } +} + +void Backend::setBmsError(const bool error) { + if (m_bmsError != error) { + m_bmsError = error; + emit bmsErrorChanged(); + } +} + +void Backend::setBmsWarning(const bool warning) { + if (m_bmsWarning != warning) { + m_bmsWarning = warning; + emit bmsWarningChanged(); + } +} + +void Backend::setBmsErrorCodes(const uint32_t warnings) { + if (m_bmsErrorCodes != warnings) { + m_bmsErrorCodes = warnings; + emit bmsErrorCodesChanged(); + } +} + +void Backend::setBmsErrorCodesString(const std::vector warnings) { + if (m_bmsErrorCodesString != warnings) { + m_bmsErrorCodesString = warnings; + emit bmsErrorCodesStringChanged(); + } +} + +void Backend::setLat(const double lat) { + if (m_lat != lat) { + m_lat = lat; + emit latChanged(); + } +} + +void Backend::setLon(const double lon) { + if (m_lon != lon) { + m_lon = lon; + emit lonChanged(); + } +} +// } + +std::thread can_thread(can::run); diff --git a/Bolt_Dash/backend.h b/Bolt_Dash/backend.h new file mode 100644 index 0000000..d1c2133 --- /dev/null +++ b/Bolt_Dash/backend.h @@ -0,0 +1,418 @@ +#ifndef BACKEND_H +#define BACKEND_H + +#include "qtmetamacros.h" +#include +#include +#include +#include + +/** + * @brief A class to represent the C++ backend of the dash which can + * be included in QML to give the frontend access. + * + */ +class Backend : public QObject { + Q_OBJECT + QML_ELEMENT + Q_PROPERTY(double motorTemp READ motorTemp WRITE setMotorTemp NOTIFY motorTempChanged); + Q_PROPERTY(double auxVoltage READ auxVoltage WRITE setAuxVoltage NOTIFY auxVoltageChanged); + Q_PROPERTY(double auxPercent READ auxPercent WRITE setAuxPercent NOTIFY auxPercentChanged); + Q_PROPERTY(double packSOC READ packSOC WRITE setPackSOC NOTIFY packSOCChanged); + Q_PROPERTY(double packVoltage READ packVoltage WRITE setPackVoltage NOTIFY packVoltageChanged); + Q_PROPERTY(double highCellTemp READ highCellTemp WRITE setHighCellTemp NOTIFY highCellTempChanged); + Q_PROPERTY(double lowCellTemp READ lowCellTemp WRITE setLowCellTemp NOTIFY lowCellTempChanged); + Q_PROPERTY(double bmsTemp READ bmsTemp WRITE setBmsTemp NOTIFY bmsTempChanged); + Q_PROPERTY(double motorSpeed READ motorSpeed WRITE setMotorSpeed NOTIFY motorSpeedChanged); + Q_PROPERTY(double bikeSpeed READ bikeSpeed WRITE setBikeSpeed NOTIFY bikeSpeedChanged); + Q_PROPERTY(double mcTemp READ mcTemp WRITE setMcTemp NOTIFY mcTempChanged); + Q_PROPERTY(bool bmsFault READ bmsFault WRITE setBmsFault NOTIFY bmsFaultChanged); + Q_PROPERTY(bool mcFault READ mcFault WRITE setMcFault NOTIFY mcFaultChanged); + Q_PROPERTY(bool motorOn READ motorOn WRITE setMotorOn NOTIFY motorOnChanged); + Q_PROPERTY(int bikeStatus READ bikeStatus WRITE setBikeStatus NOTIFY bikeStatusChanged); + Q_PROPERTY(double packCurrent READ packCurrent WRITE setPackCurrent NOTIFY packCurrentChanged); + Q_PROPERTY(uint32_t bmsErrorCodes READ bmsErrorCodes WRITE setBmsErrorCodes NOTIFY bmsErrorCodesChanged); + Q_PROPERTY(bool bmsError READ bmsError WRITE setBmsError NOTIFY bmsErrorChanged); + Q_PROPERTY(bool bmsWarning READ bmsWarning WRITE setBmsWarning NOTIFY bmsWarningChanged); + Q_PROPERTY(std::vector bmsErrorCodesString READ bmsErrorCodesString NOTIFY bmsErrorCodesStringChanged); + Q_PROPERTY(double lat READ lat WRITE setLat NOTIFY latChanged); + Q_PROPERTY(double lon READ lon WRITE setLon NOTIFY lonChanged); + +public: + /** + * @brief Create Backend class which can be included in QML + * + * @param parent the QObject parent above the Backend + */ + explicit Backend(QObject *parent = nullptr); + + /** + * @brief Get the motor temperature + * + * @return The temperature in degrees Celsius + */ + double motorTemp() const; + + /** + * @brief Get the voltage of the aux pack + * + * @return The voltage in volts + */ + double auxVoltage() const; + + /** + * @brief Get the percent charge of the aux pack + * + * @return The percentage as a percent (e.g. 87.3) + */ + double auxPercent() const; + + /** + * @brief Get the state of charge of the main battery + * + * @return The percentage as a percent (e.g. 87.3) + */ + double packSOC() const; + + /** + * @brief Get the voltage of the main battery + * + * @return The voltage in volts + */ + double packVoltage() const; + + /** + * @brief Get the highest cell temperature in the pack + * + * @return The temperature in degrees Celsius + */ + double highCellTemp() const; + + /** + * @brief Get the lowest cell temperature in the pack + * + * @return The temperature in degrees Celsius + */ + double lowCellTemp() const; + + /** + * @brief Get the temeprature of the BMS + * + * @return The temperature in degrees Celsius + */ + double bmsTemp() const; + + /** + * @brief Get the speed of the motor + * + * @return The motor speed in RPM + */ + double motorSpeed() const; + + /** + * @brief Get the speed of the bike + * + * @return The speed in mph + */ + double bikeSpeed() const; + + /** + * @brief Get the temperature of the motor controller + * + * @return The highest temperature of the three sensors in degrees Celsius + */ + double mcTemp() const; + + /** + * @brief Get whether or not there is a BMS fault + * + * @return true if there is a fault + * @return false if all is good + */ + bool bmsFault() const; + + /** + * @brief Get whether or not there is a motor controller fault + * + * @return true if there is a fault + * @return false if all is good + */ + bool mcFault() const; + + /** + * @brief Get whether or not the motor is currently active + * + * @return true if the motor can be moved with the throttle + * @return false if it cannot be moved electrically + */ + bool motorOn() const; + + /** + * @brief Get the current status of the bike. + * 1. Idle + * 2. Precharge + * 3. Ready + * 4. Active + * 5. There is a fault somewhere + * + * @return An integer representing the status as shown above + */ + int bikeStatus() const; + + /** + * @brief Get the current flowing from the main pack + * + * @return The current in amps + */ + double packCurrent() const; + + /** + * @brief Get whether or not there is a BMS error + * + * @return true if there is any major error + * @return false if there is not + */ + bool bmsError() const; + + /** + * @brief Get whether or not there is a BMS warning + * + * @return true if there is a minor error/warning + * @return false if there is not + */ + bool bmsWarning() const; + + /** + * @brief Get the BMS error codes as a bitfield + * + * @return A 32-bit integer with each bit representing a different error + */ + uint32_t bmsErrorCodes() const; + + /** + * @brief Get the BMS error codes as a vector of strings + * + * @return A Vector of Qt-Strings with each string representing a different error + */ + std::vector bmsErrorCodesString() const; + + /** + * @brief Get the latitude of the bike + * + * @return The latitude in degrees + */ + double lat() const; + + /** + * @brief Get the longitude of the bike + * + * @return The longitude in degrees + */ + double lon() const; + + /** + * @brief Set the Motor Temperature parameter, will get overwritten internally + * + * @param temp The temperature to set in degrees Celsius + */ + void setMotorTemp(const double temp); + + /** + * @brief Set the Aux Voltage parameter, will get overwritten internally + * + * @param cap The temperature to set in degrees Celsius + */ + void setAuxVoltage(const double cap); + + /** + * @brief Set the Aux Percent parameter, will get overwritten internally + * + * @param cap The percent to set + */ + void setAuxPercent(const double cap); + + /** + * @brief Set the Pack SOC parameter, will get overwritten internally + * + * @param soc The percent to set + */ + void setPackSOC(const double soc); + + /** + * @brief Set the Pack Voltage parameter, will get overwritten internally + * + * @param voltage The voltage to set in volts + */ + void setPackVoltage(const double voltage); + + /** + * @brief Set the High Cell Temp parameter, will get overwritten internally + * + * @param temp The temperature to set in degrees Celsius + */ + void setHighCellTemp(const double temp); + + /** + * @brief Set the Low Cell Temp parameter, will get overwritten internally + * + * @param temp The temperature to set in degrees Celsius + */ + void setLowCellTemp(const double temp); + + /** + * @brief Set the BMS Temp parameter, will get overwritten internally + * + * @param temp The temperature to set in degrees Celsius + */ + void setBmsTemp(const double temp); + + /** + * @brief Set the Motor Speed parameter, will get overwritten internally + * + * @param speed The speed to set in RPM + */ + void setMotorSpeed(const double speed); + + /** + * @brief Set the Bike Speed parameter, will get overwritten internally + * + * @param speed The speed to set in mph + */ + void setBikeSpeed(const double speed); + + /** + * @brief Set the MC Temp parameter, will get overwritten internally + * + * @param temp The temperature to set in degrees Celsius + */ + void setMcTemp(const double temp); + + /** + * @brief Set the BMS Fault parameter, will get overwritten internally + * + * @param fault Whether or not there is a fault + */ + void setBmsFault(const bool fault); + + /** + * @brief Set the MC Fault parameter, will get overwritten internally + * + * @param fault Whether or not there is a fault + */ + void setMcFault(const bool fault); + + /** + * @brief Set the Motor On parameter, will get overwritten internally + * + * @param on Whether or not the motor is on + */ + void setMotorOn(const bool on); + + /** + * @brief Set the Bike Status parameter, will get overwritten internally + * + * @param status The status of the bike + */ + void setBikeStatus(const int status); + + /** + * @brief Set the Pack Current parameter, will get overwritten internally + * + * @param current The current to set in amps + */ + void setPackCurrent(const double current); + + /** + * @brief Set the BMS Error parameter, will get overwritten internally + * + * @param error Whether or not there is an error + */ + void setBmsError(const bool error); + + /** + * @brief Set the BMS Warning parameter, will get overwritten internally + * + * @param warning Whether or not there is a warning + */ + void setBmsWarning(const bool warning); + + /** + * @brief Set the BMS Error Codes parameter, will get overwritten internally + * + * @param warnings The error codes to set + */ + void setBmsErrorCodes(const uint32_t warnings); + + /** + * @brief Set the BMS Error Codes String parameter, will get overwritten internally + * + * @param warnings The error codes to set + */ + void setBmsErrorCodesString(const std::vector warnings); + + /** + * @brief Set the Latitude parameter, will get overwritten internally + * + * @param lat The latitude to set in degrees + */ + void setLat(const double lat); + + /** + * @brief Set the Longitude parameter, will get overwritten internally + * + * @param lon The longitude to set in degrees + */ + void setLon(const double lon); + +signals: + void motorTempChanged(); + void auxVoltageChanged(); + void auxPercentChanged(); + void packSOCChanged(); + void packVoltageChanged(); + void highCellTempChanged(); + void lowCellTempChanged(); + void bmsTempChanged(); + void motorSpeedChanged(); + void bikeSpeedChanged(); + void mcTempChanged(); + void bmsFaultChanged(); + void mcFaultChanged(); + void motorOnChanged(); + void bikeStatusChanged(); + void packCurrentChanged(); + void bmsErrorChanged(); + void bmsWarningChanged(); + void bmsErrorCodesChanged(); + void bmsErrorCodesStringChanged(); + void latChanged(); + void lonChanged(); + +private: + void updateVars(); + std::vector getErrorCodeStrings(uint32_t errorCodes); + double m_motorTemp; + double m_auxVoltage; + double m_auxPercent; + double m_packSOC; + double m_packVoltage; + double m_highCellTemp; + double m_lowCellTemp; + double m_bmsTemp; + double m_motorSpeed; + double m_bikeSpeed; + double m_mcTemp; + bool m_bmsFault; + bool m_mcFault; + bool m_motorOn; + int m_bikeStatus; + double m_packCurrent; + bool m_bmsError; + bool m_bmsWarning; + uint32_t m_bmsErrorCodes; + std::vector m_bmsErrorCodesString; + double m_lat; + double m_lon; +}; + +#endif // BACKEND_H diff --git a/Bolt_Dash/can.cpp b/Bolt_Dash/can.cpp new file mode 100644 index 0000000..6d2d74b --- /dev/null +++ b/Bolt_Dash/can.cpp @@ -0,0 +1,235 @@ +#include "can.h" + +#include +#include +#include + +using namespace std::chrono_literals; + +#define FRAMES_TO_AVERAGE 10 +#define CELL_VOLTAGE_SCALING 0.0001 +#define SAFEST_HIGH_CELL_VOLTAGE 4.25 +#define SAFEST_LOW_CELL_VOLTAGE 3.0 + +std::mutex m; +our_candata data{}; + +namespace can { + // Circular buffers to store the last 10 values of the highest and lowest cell voltages + int lastLowestCellVoltages[FRAMES_TO_AVERAGE]{}; + int lastHighestCellVoltages[FRAMES_TO_AVERAGE]{}; + int lastLowestCellVoltageIndex = 0; + int lastHighestCellVoltageIndex = 0; + + // Average lowest and highest cell voltages + int getAverageLowestCellVoltage() { + int sum = 0; + for (int i = 0; i < FRAMES_TO_AVERAGE; i++) { + sum += lastLowestCellVoltages[i]; + } + return sum / FRAMES_TO_AVERAGE; + } + int getAverageHighestCellVoltage() { + int sum = 0; + for (int i = 0; i < FRAMES_TO_AVERAGE; i++) { + sum += lastHighestCellVoltages[i]; + } + return sum / FRAMES_TO_AVERAGE; + } + +#ifdef CAN_LIB_FOUND + int run() { + // Where the data will be stored to be send to the front end + int s, i; + int nbytes; + struct sockaddr_can addr; + struct ifreq ifr; + struct can_frame frame; + int8_t *unknown_data = nullptr; + + printf("CAN Sockets Receive Demo\r\n"); + + // Create a new socket of type CAN using data CAN_RAW + if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) { + perror("Socket"); + return 1; + } + + // Setting the name of the physical can interface (ip a) + strcpy(ifr.ifr_name, "can0"); + // Converts if name to actual interface index + ioctl(s, SIOCGIFINDEX, &ifr); + + // Reserve memory for CAN frames + memset(&addr, 0, sizeof(addr)); + addr.can_family = AF_CAN; // Use CAN sockets specifically + addr.can_ifindex = ifr.ifr_ifindex; + + // Connects to the socket and it locks + if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + perror("Bind"); + return 1; + } + + while (true) { + // Actually reads from the socket + nbytes = read(s, &frame, sizeof(struct can_frame)); + + // Make sure it exists + if (nbytes < 0) { + perror("Read"); + return 1; + } + m.lock(); + switch (frame.can_id) { + case can_ids.aux_battery: + data.aux_voltage = frame.data[0] + (frame.data[1] << 8); + data.aux_percent = data.aux_voltage / 2.5; + break; + case can_ids.info: + data.pack_state_of_charge = frame.data[4]; + data.bms_fault = frame.data[5] & BMS_FAULT_MASK; + data.pack_current = frame.data[0] + (frame.data[1] << 8); + data.pack_voltage = frame.data[2] + (frame.data[3] << 8); + break; + case can_ids.main_pack_temp: + data.high_cell_temp = frame.data[0] + (frame.data[1] << 8); + data.low_cell_temp = frame.data[2] + (frame.data[3] << 8); + break; + case can_ids.cell_max_min_voltages: + data.highest_cell_voltage = frame.data[2] + (frame.data[3] << 8); + data.lowest_cell_voltage = frame.data[4] + (frame.data[5] << 8); + // Update circular buffers + lastLowestCellVoltages[lastLowestCellVoltageIndex] = data.lowest_cell_voltage; + lastHighestCellVoltages[lastHighestCellVoltageIndex] = data.highest_cell_voltage; + lastLowestCellVoltageIndex = (lastLowestCellVoltageIndex + 1) % FRAMES_TO_AVERAGE; + lastHighestCellVoltageIndex = (lastHighestCellVoltageIndex + 1) % FRAMES_TO_AVERAGE; + break; + case can_ids.motor_temp: + data.motor_temperature = frame.data[4] + (frame.data[5] << 8); + break; + case can_ids.bms_temp: + data.bms_temperature = frame.data[4] + (frame.data[5] << 8); + break; + case can_ids.rpm: + data.motor_speed = frame.data[2] + (frame.data[3] << 8); + data.bike_speed = frame.data[2] + (frame.data[3] << 8); + break; + case can_ids.speed: + data.bike_speed = frame.data[2] + (frame.data[3] << 8); + break; + case can_ids.mc_temp: { + uint16_t r1 = frame.data[0] + (frame.data[1] << 8); + uint16_t r2 = frame.data[2] + (frame.data[3] << 8); + uint16_t r3 = frame.data[4] + (frame.data[5] << 8); + data.mc_temperature = r1 > r2 ? r1 : (r2 > r3 ? r2 : r3); + break; + }; + case can_ids.mc_faults: + data.mc_fault = frame.data[0] || frame.data[1] || frame.data[2] || frame.data[3] || frame.data[4] || frame.data[5] || frame.data[6] || frame.data[7]; + break; + case can_ids.internal_states: { + // Get state of bike + uint16_t status = frame.data[0] + (frame.data[1] << 8); + switch (status) { + // I don't actually think this does anything, but this may be when accessories exist + case 0: + data.bike_status = 1; + break; + // If 1, 2, or 3, VSM is in one of the precharge states + case 1: + case 2: + case 3: + data.bike_status = 2; + break; + // 4 or 5, MC is ready but not active yet + case 4: + case 5: + data.bike_status = 3; + break; + // 6, Motor is on an can be moved + case 6: + data.bike_status = 4; + break; + // Kind of obsolete b/c this is not a visible status, but if 7, there is a fault + case 7: + data.bike_status = 5; + break; + default: + break; + } + data.motor_on = frame.data[0] == 6; + break; + }; + case can_ids.bms_error_codes: + // aaaaaaaabbbbbbbbccccccc + // a: DTC codes 2 bits 9-16 + // b: DTC codes 2 bits 1-8 + // c: DTC codes 1 bits 1-8 + data.bms_error_codes = (frame.data[2]) + (frame.data[0] << 8) + (frame.data[1] << 16); + data.bms_error = data.bms_error_codes & ALL_BMS_ERRORS; + data.bms_warning = data.bms_error_codes & ALL_BMS_WARNINGS; + + // Clear warnings if they are no longer relevant + if (data.bms_error_codes & bms_errors.highest_cell_voltage_too_high && (getAverageHighestCellVoltage() * CELL_VOLTAGE_SCALING) <= SAFEST_HIGH_CELL_VOLTAGE) { + data.bms_warning &= ~bms_errors.highest_cell_voltage_too_high; + } + if (data.bms_error_codes & bms_errors.lowest_cell_voltage_too_low && (getAverageLowestCellVoltage() * CELL_VOLTAGE_SCALING) >= SAFEST_LOW_CELL_VOLTAGE) { + data.bms_warning &= ~bms_errors.lowest_cell_voltage_too_low; + } + break; + case can_ids.acc_signal: + if (frame.data[0] == 0) { + data.bike_status = 0; + } else if (data.bike_status == 0) { + data.bike_status = frame.data[0]; + } + break; + default: + unknown_data = new int8_t[frame.can_dlc]; + for (int i{}; i < frame.can_dlc; i++) { + unknown_data[i] = frame.data[i]; + } + } + m.unlock(); + + // Print the can ID and len of data + // printf("0x%03X [%d] ", frame.can_id, frame.can_dlc); // switch (status) { + // case 0: + // break; + // // If 1, 2, or 3, VSM is in one of the precharge states + // case 1: + // case 2: + // case 3: + // data.bike_status = 0; + // break; + // case 5: + // data.bike_status = 1; + // break; + // default: + // break; + // } + + // Print the data in the CAN message + // for (i = 0; i < frame.can_dlc; i++) + // printf("%02X ", frame.data[i]); + + // printf("\r\n"); + } + + // Close socket + if (close(s) < 0) { + perror("Close"); + return 1; + } + + return 0; + } + +#else + int run() { + // If no CAN library is found, just return 0 + return 0; + } +#endif // CAN_LIB_FOUND +} diff --git a/Bolt_Dash/can.h b/Bolt_Dash/can.h new file mode 100644 index 0000000..3cf5b76 --- /dev/null +++ b/Bolt_Dash/can.h @@ -0,0 +1,182 @@ +#ifndef CAN_H +#define CAN_H + +#include +#include + +#include +#include +#include + +#if __has_include() && __has_include() +#include +#include +#define CAN_LIB_FOUND 1 +#endif + +#define BMS_FAULT_MASK 0b0010000 + +/** + * @brief This is a struct that contains all the data that we get from the CAN bus + * and is used in the dash project. + * + */ +struct our_candata { + /** + * @brief The voltage of the aux pack + */ + uint8_t aux_voltage{}; + /** + * @brief The battery percentage of the aux pack + */ + uint8_t aux_percent{}; + /** + * @brief The state of charge of the main pack as a percentage + */ + uint8_t pack_state_of_charge{}; + /** + * @brief The voltage of the main pack + */ + uint16_t pack_voltage{}; + /** + * @brief The current of the main pack + */ + int16_t pack_current{}; + /** + * @brief The temperature of the hottest cell group in the main pack + */ + uint16_t high_cell_temp{}; + /** + * @brief The temperature of the coldest cell group in the main pack + */ + uint16_t low_cell_temp{}; + /** + * @brief The temperature of the motor + */ + int16_t motor_temperature{}; + /** + * @brief The temperature of the BMS + */ + uint16_t bms_temperature{}; + /** + * @brief The temperature of the motor controller + */ + uint16_t mc_temperature{}; + /** + * @brief The RPM of the motor + */ + int16_t motor_speed{}; + /** + * @brief The speed of the bike in mph + */ + int16_t bike_speed{}; + /** + * @brief The fault status of the BMS + */ + uint8_t bms_fault{}; + /** + * @brief Whether the BMS has any errors + */ + uint8_t bms_error{}; + /** + * @brief Whether the BMS has any warnings + */ + uint8_t bms_warning{}; + /** + * @brief The actual error codes of the BMS concatenated together + */ + uint32_t bms_error_codes{}; + /** + * @brief Whether or no the MC has a fault + */ + uint8_t mc_fault{}; + /** + * @brief Whether or not the motor is active + */ + uint8_t motor_on{}; + /** + * @brief The internal state of the bike, not used rn + */ + uint8_t bike_status{}; + /** + * @brief The highest cell voltage in the main pack + */ + uint16_t highest_cell_voltage{}; + /** + * @brief The lowest cell voltage in the main pack + */ + uint16_t lowest_cell_voltage{}; +}; + +// ID's for each CAN thing +#ifdef CAN_LIB_FOUND +constexpr struct { + canid_t aux_battery{0x700}; + canid_t info{0x6B0}; + canid_t cell_max_min_voltages{0x6B3}; + canid_t main_pack_temp{0x6B4}; + canid_t bms_error_codes{0x6B6}; + canid_t motor_temp{0xA2}; + canid_t bms_temp{0x6B1}; + canid_t mc_temp{0xA0}; + canid_t rpm{0xA5}; + canid_t speed{0x00}; + canid_t mc_faults{0x0AB}; + canid_t internal_states{0x0AA}; + canid_t acc_signal{0x706}; +} can_ids; +#else +constexpr struct { + +} can_ids; +#endif // CAN_LIB_FOUND + +constexpr struct { + uint32_t discharge_limit_enforcement{1 << 0}; + uint32_t charger_safety_relay{1 << 1}; + uint32_t internal_heatsink_thermistor{1 << 3}; + uint32_t cell_balancing_stuck_off{1 << 9}; + uint32_t weak_cell{1 << 10}; + uint32_t open_wiring{1 << 12}; + uint32_t current_sensor{1 << 13}; + uint32_t weak_pack{1 << 16}; + uint32_t fan_monitor{1 << 17}; + uint32_t thermistor_fault{1 << 18}; + uint32_t external_communication{1 << 19}; + uint32_t charge_limit_enforcement{1 << 23}; +} bms_warnings; + +constexpr struct { + uint32_t internal_hardware{1 << 2}; + uint32_t internal_software{1 << 4}; + uint32_t highest_cell_voltage_too_high{1 << 5}; + uint32_t lowest_cell_voltage_too_low{1 << 6}; + uint32_t pack_too_hot{1 << 7}; + uint32_t internal_communication{1 << 8}; + uint32_t low_cell_voltage{1 << 11}; + uint32_t highest_cell_voltage_over_5v{1 << 14}; + uint32_t cell_asic_fault{1 << 15}; + uint32_t redundant_power_supply{1 << 20}; + uint32_t high_voltage_isolation{1 << 21}; + uint32_t input_power_supply{1 << 22}; +} bms_errors; + +const uint32_t ALL_BMS_ERRORS = bms_errors.internal_hardware | bms_errors.internal_software | + bms_errors.highest_cell_voltage_too_high | bms_errors.lowest_cell_voltage_too_low | + bms_errors.pack_too_hot | bms_errors.internal_communication | bms_errors.low_cell_voltage | + bms_errors.highest_cell_voltage_over_5v | bms_errors.cell_asic_fault | + bms_errors.redundant_power_supply | bms_errors.high_voltage_isolation | + bms_errors.input_power_supply; +const uint32_t ALL_BMS_WARNINGS = bms_warnings.charger_safety_relay | bms_warnings.discharge_limit_enforcement | + bms_warnings.cell_balancing_stuck_off | bms_warnings.internal_heatsink_thermistor | bms_warnings.weak_cell | + bms_warnings.current_sensor | bms_warnings.weak_pack | bms_warnings.fan_monitor | + bms_warnings.thermistor_fault | bms_warnings.external_communication | + bms_warnings.open_wiring | bms_warnings.charge_limit_enforcement; +extern std::mutex m; +extern our_candata data; + +namespace can { + int run(); +} + +#endif // CAN_H diff --git a/Bolt_Dash/constants.h b/Bolt_Dash/constants.h new file mode 100644 index 0000000..b46b8aa --- /dev/null +++ b/Bolt_Dash/constants.h @@ -0,0 +1,15 @@ +#define RPM_TO_SPEED (19.0 / 45.0 * 27.63 * M_PI / 1056) + +// Scaling for CAN data +#define MOTOR_TEMPERATURE_SCALE (1.0 / 10.0) +#define AUX_VOLTAGE_SCALE (1.0 / 10.0) +#define AUX_PERCENT_SCALE (1.0 / 100.0) +#define PACK_STATE_OF_CHARGE_SCALE (1.0 / 200.0) +#define PACK_VOLTAGE_SCALE (1.0 / 10.0) +#define PACK_CURRENT_SCALE (1.0 / 10.0) +#define HIGH_CELL_TEMP_SCALE (1) +#define LOW_CELL_TEMP_SCALE (1) +#define BMS_TEMPERATURE_SCALE (1) +#define MOTOR_SPEED_SCALE (1) +#define BIKE_SPEED_SCALE (RPM_TO_SPEED) +#define MC_TEMPERATURE_SCALE (1.0 / 10.0) \ No newline at end of file diff --git a/Bolt_Dash/content/App.qml b/Bolt_Dash/content/App.qml index 112fa4f..b1c7381 100644 --- a/Bolt_Dash/content/App.qml +++ b/Bolt_Dash/content/App.qml @@ -3,14 +3,13 @@ import QtQuick 6.2 import Bolt_Dash -import Backend import IO Window { width: mainScreen.width height: mainScreen.height property bool debugMode: false - + visible: true title: "Bolt_Dash" @@ -32,5 +31,14 @@ Window { debugMode = !debugMode } } + + Rectangle { + visible: true + color: "transparent" + border.color: "red" + border.width: 1 + height: Constants.height + width: Constants.width + } } diff --git a/Bolt_Dash/content/BMSFaultDetails.qml b/Bolt_Dash/content/BMSFaultDetails.qml new file mode 100644 index 0000000..0a72595 --- /dev/null +++ b/Bolt_Dash/content/BMSFaultDetails.qml @@ -0,0 +1,93 @@ +import QtQuick 2.15 +import QtQuick.Controls +import QtQuick.Shapes + +Window{ + x: 0 + y: 0 + width: 400 + height: 400 + + Rectangle { + border.color: "black" + border.width: 2 + width: 350 + height: 300 + x: 20 + y: 5 + ScrollView { + x: 5 + y: 5 + width: parent.width - 10 + height: parent.height - 10 + ScrollBar.horizontal.policy: ScrollBar.AlwaysOff + ScrollBar.vertical.policy: ScrollBar.AlwaysOn + ScrollBar.horizontal.interactive: false + ScrollBar.vertical.interactive: true + Column { + Repeater { + model: getBMSWarnings() + Text { + required property string modelData + text: modelData + } + } + } + } + } + + Rectangle { + border.color: "black" + border.width: 2 + width: 350 + height: 85 + x: 20 + y: 310 + + Text { + x: 5 + y: 5 + width: parent.width - 10 + text: "Clear BMS Fault Codes?" + horizontalAlignment: Text.AlignHCenter + font.bold: true + font.italic: true + } + + Row { + x: 10 + y: 25 + width: parent.width - 20 + spacing: 10 + Button { + width: parent.width / 2 - 5 + text: "Yes" + + Rectangle { + width: parent.width + height: parent.height + color: "grey" + } + } + + Button { + width: parent.width / 2 - 5 + text: "No" + + Rectangle { + width: parent.width + height: parent.height + color: "grey" + } + } + } + } + + function getBMSWarnings() { + var myText = [] + for (var i = 0; i < backend.bmsErrorCodesString.length; i++) { + myText.push(backend.bmsErrorCodesString[i]) + } + return myText + } +} \ No newline at end of file diff --git a/Bolt_Dash/content/BatteryReadout.qml b/Bolt_Dash/content/BatteryReadout.qml new file mode 100644 index 0000000..13b8910 --- /dev/null +++ b/Bolt_Dash/content/BatteryReadout.qml @@ -0,0 +1,87 @@ +import QtQuick +import QtQuick.Shapes + +Item { + readonly property int batteryBorder: 5 + readonly property string red: "#e80c0c" + readonly property string green: "#54c45e" + property int soc + property double voltage + + Rectangle { + radius: 15 + width: 175 + height: 125 + color: "black" + + Image { + x: 15 + y: 15 + id: batterySVG + source: "Pictures/battery.svg" + sourceSize.width: 150 + sourceSize.height: 75 + rotation: 270 + transformOrigin: Item.Center + + Rectangle { + x: batteryBorder + y: batteryBorder + color: "transparent" + width: parent.sourceSize.width - batteryBorder * 2 - 16 + height: parent.sourceSize.height - batteryBorder * 2 + + Rectangle { + radius: 8 + width: parent.width + height: parent.height + color: "black" + } + + Rectangle { + radius: 8 + width: soc/100 * parent.width + height: parent.height + color: soc < 20 ? red : green + } + } + } + + Text { + id: percentLabel + x: batterySVG.x + batterySVG.width - 37 + y: parent.height/2 - 2*height/3 + horizontalAlignment: Text.AlignHLeft + verticalAlignment: Text.AlignBottom + color: "white" + text: qsTr("%1\%").arg(soc) + font.pixelSize: 60 + } + + Shape { + ShapePath { + id: coolLine + strokeColor: "white" + strokeWidth: 4 + fillColor: "transparent" + // strokeStyle: ShapePath.DashLine + dashPattern: [ 1, 4 ] + startX: percentLabel.x + startY: percentLabel.y+percentLabel.height - 10 + PathLine { x: coolLine.startX + 140; y: coolLine.startY } + } + } + + // Voltage Text + Text { + id: voltageText + x: percentLabel.x + batteryBorder + y: batterySVG.y + batterySVG.height - height/2 + batteryBorder + text: qsTr("%1V").arg(voltage) + color: "white" + font.pixelSize: 20 + font.italic: true + } + } + +} diff --git a/Bolt_Dash/content/BatterySlider.qml b/Bolt_Dash/content/BatterySlider.qml index 4b66f6d..458af7e 100644 --- a/Bolt_Dash/content/BatterySlider.qml +++ b/Bolt_Dash/content/BatterySlider.qml @@ -1,5 +1,6 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 +import Bolt_Dash Item { width: 60 @@ -18,6 +19,7 @@ Item { Rectangle { id: enclosing + radius: 15 x: 0 y: 0 width: 60 @@ -28,6 +30,7 @@ Item { Rectangle { id: level + radius: 15 x: 0 y: 0 width: 60 diff --git a/Bolt_Dash/content/BikeStatus.qml b/Bolt_Dash/content/BikeStatus.qml new file mode 100644 index 0000000..21a9d4d --- /dev/null +++ b/Bolt_Dash/content/BikeStatus.qml @@ -0,0 +1,102 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Shapes +import QtQuick.Layouts + +Item { + readonly property color staticBG: "#5F5F5F" + readonly property string green: "#54c45e" + property list texts: ["STDBY", "ACC", "PREP", "IDLE", "DRIVE"] + property int status: BikeStatus.Status.STANDBY + + width: 800 + height: 40 + id: root + + enum Status { + STANDBY, + ACCESSORY, + CHECKING, + READY, + DRIVE, + FAULT + } + + Rectangle { + visible: false + id: rect + anchors.centerIn: parent + width: parent.width + height: parent.height + radius: 15 + color: { + switch(status) { + case BikeStatus.Status.STANDBY: + case BikeStatus.Status.ACCESSORY: + case BikeStatus.Status.CHECKING: + case BikeStatus.Status.READY: + return staticBG + case BikeStatus.Status.FAULT: + return "red" + case BikeStatus.Status.DRIVE: + return green + } + } + + Text { + anchors.centerIn: parent + text: { + switch (status) { + case BikeStatus.Status.STANDBY: + return "STANDBY" + case BikeStatus.Status.ACCESSORY: + return "ACC" + case BikeStatus.Status.CHECKING: + return "WAITING" + case BikeStatus.Status.FAULT: + return "FAULT" + case BikeStatus.Status.READY: + return "READY" + case BikeStatus.Status.DRIVE: + return "DRIVE" + } + } + color: "white" + font.bold: true + font.pixelSize: 0.75*parent.height + } + } + + Rectangle { + height: parent.height + width: parent.width + color: "white" + + GridLayout { + id: grid + columns: 5 + x: 0 + y: columnSpacing + height: parent.height + width: parent.width + columnSpacing: 2 + + Repeater { + model: 5 + Rectangle { + required property int index + color: root.status === index ? (root.status === BikeStatus.Status.DRIVE ? root.green : "white") : "black" + Layout.preferredWidth: parent.width / parent.columns - parent.columnSpacing + height: parent.height + Text { + anchors.centerIn: parent + text: root.texts[index] + color: root.status == index ? "black": "white" + font.bold: true + font.pixelSize: 25 + } + } + } + } + } +} diff --git a/Bolt_Dash/content/BoltLeanAngle.qml b/Bolt_Dash/content/BoltLeanAngle.qml index ba65f3b..99ba38e 100644 --- a/Bolt_Dash/content/BoltLeanAngle.qml +++ b/Bolt_Dash/content/BoltLeanAngle.qml @@ -1,9 +1,13 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 -import QtQuick.Studio.Components +// import QtQuick.Studio.Components import QtCharts +import QtQuick.Shapes Item { + property int ang: 60 + width: 500 + height: 500 Image { id: image x: -(295/2) @@ -13,4 +17,14 @@ Item { source: "Pictures/leanAngleBack.png" fillMode: Image.PreserveAspectFit } + + Rectangle { + id: correctDial + width: 5 + height: 150 + x: -width/2 + y: 60 + transformOrigin: Item.Bottom + rotation: ang + } } diff --git a/Bolt_Dash/content/CMakeLists.txt b/Bolt_Dash/content/CMakeLists.txt index 5e54de5..38e237b 100644 --- a/Bolt_Dash/content/CMakeLists.txt +++ b/Bolt_Dash/content/CMakeLists.txt @@ -11,12 +11,33 @@ qt6_add_qml_module(content Speedometer.qml BatterySlider.qml TempSlider.qml - WarningSymbol.qml Debug1.qml BoltLeanAngle.qml + BikeStatus.qml + BatteryReadout.qml + FullBatterySlider.qml + TemperatureIsland.qml + FullSlider.qml + BMSFaultDetails.qml RESOURCES fonts/fonts.txt fonts/nasalization-rg.otf + fonts/MesloLGSDZNerdFontMono-Regular.ttf Pictures/leanAngleBack.png + Pictures/motorcycleIcon.png + Pictures/battery-twotone-0-svgrepo-com.svg + Pictures/battery.svg + Pictures/battery_temp.svg + Pictures/controller_temp.svg + Pictures/motor_temp.svg + Pictures/Virginia_Tech_Hokies_logo.svg QML_FILES DebugItem1.ui.qml + QML_FILES FaultMotorStatus.qml + QML_FILES SpeedometerDecorations.qml + QML_FILES DebugMain.qml + QML_FILES DebugMotor.qml + QML_FILES DebugOverview.qml + QML_FILES DebugBMS.qml + QML_FILES DebugPDU.qml + QML_FILES DebugOther.qml ) diff --git a/Bolt_Dash/content/Debug1.qml b/Bolt_Dash/content/Debug1.qml index f6f4140..b5ab6e9 100644 --- a/Bolt_Dash/content/Debug1.qml +++ b/Bolt_Dash/content/Debug1.qml @@ -1,30 +1,76 @@ import QtQuick 2.15 -import Backend +import QtQuick.Shapes Item { - Backend { - id: backend - motorTemp: 0 - auxVoltage: 0 - auxPercent: 0 - packSOC: 0 - highCellTemp: 0 - lowCellTemp: 0 - bmsTemp: 0 - motorSpeed: 0 - bikeSpeed: 0 - } - DebugItem1 { + visible: menu.selected == DebugMain.Selected.OVERVIEW + width: 650 id: debug1 motorTemp: backend.motorTemp auxVoltage: backend.auxVoltage auxPercent: backend.auxPercent packSOC: backend.packSOC + packVoltage: backend.packVoltage highCellTemp: backend.highCellTemp lowCellTemp: backend.lowCellTemp bmsTemp: backend.bmsTemp motorSpeed: backend.motorSpeed bikeSpeed: backend.bikeSpeed + longitude: backend.lon + latitude: backend.lat + } + + DebugMotor { + visible: menu.selected == DebugMain.Selected.MOTOR + width: 650 + id: debugMotor + motorTemp: backend.motorTemp + motorSpeed: backend.motorSpeed + bikeSpeed: backend.bikeSpeed + mcTemp: backend.mcTemp + mcFault: backend.mcFault + motorOn: backend.motorOn + } + + DebugBMS { + visible: menu.selected == DebugMain.Selected.BMS + width: 650 + id: debugBMS + packSOC: backend.packSOC + highCellTemp: backend.highCellTemp + lowCellTemp: backend.lowCellTemp + bmsTemp: backend.bmsTemp + packVoltage: backend.packVoltage + packCurrent: backend.packCurrent + bmsFault: backend.bmsFault + bmsErrorCodes: bmsErrorCodes + bmsError: backend.bmsError + bmsWarning: backend.bmsWarning + bmsErrorCodesString: backend.bmsErrorCodesString + } + + DebugPDU { + visible: menu.selected == DebugMain.Selected.PDU + width: 650 + id: debugPDU + auxVoltage: backend.auxVoltage + auxPercent: backend.auxPercent + bikeStatus: backend.bikeStatus + } + + DebugOther { + visible: menu.selected == DebugMain.Selected.OTHER + width: 650 + id: debugOther + gpsLat: backend.lat + gpsLong: backend.lon + } + + DebugMain { + id: menu + x: 650 + y: 0 + width: 150 + selected: DebugMain.Selected.OVERVIEW } } diff --git a/Bolt_Dash/content/DebugBMS.qml b/Bolt_Dash/content/DebugBMS.qml new file mode 100644 index 0000000..b56c57e --- /dev/null +++ b/Bolt_Dash/content/DebugBMS.qml @@ -0,0 +1,69 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Bolt_Dash + +Item { + width: Constants.width + height: Constants.height + + // Properties, all defined as doubles + property double packSOC: 0.0 + property double highCellTemp: 0.0 + property double lowCellTemp: 0.0 + property double bmsTemp: 0.0 + property double packVoltage: 0.0 + property bool bmsFault: false + property double packCurrent: 0.0 + property int bmsErrorCodes: 0 + property bool bmsError: false + property bool bmsWarning: false + property var bmsErrorCodesString: [] + + // Using grid layout for organized display + GridLayout { + y: 30 + columns: 2 + columnSpacing: 10 + rowSpacing: 10 + width: parent.width + height: parent.height - y + + // Labels and dynamic text for each data item, converting double to string for display + Text { text: "Pack State of Charge (SOC):" } + Text { text: qsTr("%1\%").arg(packSOC*100) } + + Text { text: "PackVoltage:" } + Text { text: qsTr("%1V").arg(packVoltage) } + + Text { text: "Pack Current:" } + Text { text: qsTr("%1A").arg(packCurrent) } + + Text { text: "High Cell Temperature:" } + Text { text: qsTr("%1°C").arg(highCellTemp) } + + Text { text: "Low Cell Temperature:" } + Text { text: qsTr("%1°C").arg(lowCellTemp) } + + Text { text: "BMS Temperature:" } + Text { text: qsTr("%1°C").arg(bmsTemp) } + + Text { text: "Any BMS Fault:" } + Text { text: bmsFault ? "Yes" : "No" } + + Text { text: "BMS Error:" } + Text { text: bmsError ? "Yes" : "No" } + + Text { text: "BMS Warning:" } + Text { text: bmsWarning ? "Yes" : "No" } + + Text { text: "BMS Error Codes:" } + Text { text: bmsErrorCodesString.length != 0 ? bmsErrorCodesString.join(", ") : "None" } + } + + Text { + text: "BMS" + color: "blue" + font.pixelSize: 24 + } +} diff --git a/Bolt_Dash/content/DebugItem1.ui.qml b/Bolt_Dash/content/DebugItem1.ui.qml index 521fe7b..894aee6 100644 --- a/Bolt_Dash/content/DebugItem1.ui.qml +++ b/Bolt_Dash/content/DebugItem1.ui.qml @@ -17,6 +17,9 @@ Item { property double bmsTemp: 0.0 property double motorSpeed: 0.0 property double bikeSpeed: 0.0 + property double packVoltage: 0.0 + property double latitude: 0.0 + property double longitude: 0.0 // Using grid layout for organized display GridLayout { @@ -27,31 +30,40 @@ Item { height: parent.height // Labels and dynamic text for each data item, converting double to string for display - Label { text: "Motor Temperature:" } + Text { text: "Motor Temperature:" } Text { text: qsTr("%1°C").arg(backend.motorTemp) } - Label { text: "Aux Voltage:" } + Text { text: "Aux Voltage:" } Text { text: qsTr("%1V").arg(auxVoltage) } - Label { text: "Aux Percent:" } + Text { text: "Aux Percent:" } Text { text: qsTr("%1\%").arg(auxPercent*100) } - Label { text: "Pack State of Charge (SOC):" } + Text { text: "Pack State of Charge (SOC):" } Text { text: qsTr("%1\%").arg(packSOC*100) } - Label { text: "High Cell Temperature:" } + Text { text: "PackVoltage:" } + Text { text: qsTr("%1V").arg(packVoltage) } + + Text { text: "High Cell Temperature:" } Text { text: qsTr("%1°C").arg(highCellTemp) } - Label { text: "Low Cell Temperature:" } + Text { text: "Low Cell Temperature:" } Text { text: qsTr("%1°C").arg(lowCellTemp) } - Label { text: "BMS Temperature:" } + Text { text: "BMS Temperature:" } Text { text: qsTr("%1°C").arg(bmsTemp) } - Label { text: "Motor Speed:" } + Text { text: "Motor Speed:" } Text { text: qsTr("%1 RPM").arg(motorSpeed) } - Label { text: "Bike Speed:" } + Text { text: "Bike Speed:" } Text { text: qsTr("%1 mph").arg(bikeSpeed) } + + Text { text: "Longitude:" } + Text { text: qsTr("%1").arg(longitude) } + + Text { text: "Latitude:" } + Text { text: qsTr("%1").arg(latitude) } } } diff --git a/Bolt_Dash/content/DebugMain.qml b/Bolt_Dash/content/DebugMain.qml new file mode 100644 index 0000000..8c0fa03 --- /dev/null +++ b/Bolt_Dash/content/DebugMain.qml @@ -0,0 +1,68 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 + +Item { + width: 100 + height: 480 + property int selected: DebugMain.Selected.OVERVIEW + + enum Selected { + OVERVIEW, + MOTOR, + BMS, + PDU, + OTHER + } + + Column { + id: column + property int numButtons: 5 + y: spacing + spacing: 3 + width: parent.width + height: parent.height + Repeater { + model: column.numButtons + Rectangle { + radius: 2 + height: parent.height / column.numButtons - parent.spacing - 1 + width: parent.width + color: selected === modelData ? "lightgrey" : "grey" + + Text { + height: parent.height + width: parent.width + text: { + switch (modelData) { + case DebugMain.Selected.OVERVIEW: + return "Overview" + case DebugMain.Selected.MOTOR: + return "Motor" + case DebugMain.Selected.BMS: + return "BMS" + case DebugMain.Selected.PDU: + return "PDU" + case DebugMain.Selected.OTHER: + return "Other" + default: + return "Unknown" + } + } + color: "black" + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } + Button { + flat: true + width: parent.width + height: parent.height + onClicked: { + selected = modelData + } + } + } + + } + } +} diff --git a/Bolt_Dash/content/DebugMotor.qml b/Bolt_Dash/content/DebugMotor.qml new file mode 100644 index 0000000..675e643 --- /dev/null +++ b/Bolt_Dash/content/DebugMotor.qml @@ -0,0 +1,52 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Bolt_Dash + +Item { + width: Constants.width + height: Constants.height + + // Properties, all defined as doubles + property double motorTemp: 0.0 + property double motorSpeed: 0.0 + property double bikeSpeed: 0.0 + property double mcTemp: 0.0 + property bool mcFault: false + property bool motorOn: false + + Text { + text: "Motor" + color: "blue" + font.pixelSize: 24 + } + + // Using grid layout for organized display + GridLayout { + y: 30 + columns: 2 + columnSpacing: 10 + rowSpacing: 10 + width: parent.width + height: parent.height - 30 + + // Labels and dynamic text for each data item, converting double to string for display + Text { text: "Motor Temperature:" } + Text { text: qsTr("%1°C").arg(backend.motorTemp) } + + Text { text: "Motor Controller Temperature:" } + Text { text: qsTr("%1°C").arg(backend.mcTemp) } + + Text { text: "Motor Speed:" } + Text { text: qsTr("%1 RPM").arg(motorSpeed) } + + Text { text: "Bike Speed:" } + Text { text: qsTr("%1 mph").arg(bikeSpeed) } + + Text { text: "Motor Controller Fault:" } + Text { text: mcFault ? "Yes" : "No" } + + Text { text: "Motor On:" } + Text { text: motorOn ? "Yes" : "No" } + } +} diff --git a/Bolt_Dash/content/DebugOther.qml b/Bolt_Dash/content/DebugOther.qml new file mode 100644 index 0000000..70c3bfc --- /dev/null +++ b/Bolt_Dash/content/DebugOther.qml @@ -0,0 +1,36 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Bolt_Dash + +Item { + width: Constants.width + height: Constants.height + + // Properties, all defined as doubles + property double gpsLat: 0.0 + property double gpsLong: 0.0 + + // Using grid layout for organized display + GridLayout { + y: 30 + columns: 2 + columnSpacing: 10 + rowSpacing: 5 + width: parent.width + height: parent.height - y + + // Labels and dynamic text for each data item, converting double to string for display + Text { text: "Latitude:" } + Text { text: qsTr("%1").arg(gpsLat) } + + Text { text: "Longitude:" } + Text { text: qsTr("%1").arg(gpsLong) } + } + + Text { + text: "Other Information" + color: "blue" + font.pixelSize: 24 + } +} diff --git a/Bolt_Dash/content/DebugOverview.qml b/Bolt_Dash/content/DebugOverview.qml new file mode 100644 index 0000000..68c2108 --- /dev/null +++ b/Bolt_Dash/content/DebugOverview.qml @@ -0,0 +1,5 @@ +import QtQuick 2.15 + +Item { + +} diff --git a/Bolt_Dash/content/DebugPDU.qml b/Bolt_Dash/content/DebugPDU.qml new file mode 100644 index 0000000..98dad5c --- /dev/null +++ b/Bolt_Dash/content/DebugPDU.qml @@ -0,0 +1,53 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Bolt_Dash + +Item { + width: Constants.width + height: Constants.height + + // Properties, all defined as doubles + property double auxVoltage: 0.0 + property double auxPercent: 0.0 + property int bikeStatus: 0 + + // Using grid layout for organized display + GridLayout { + y: 30 + columns: 2 + columnSpacing: 10 + rowSpacing: 10 + width: parent.width + height: parent.height - y + + // Labels and dynamic text for each data item, converting double to string for display + Text { text: "Aux Voltage:" } + Text { text: auxVoltage.toFixed(2) + " V" } + + Text { text: "Aux Percent:" } + Text { text: auxPercent.toFixed(2) + " %" } + + Text { text: "Bike Status:" } + Text { text: switch (bikeStatus) { + case BikeStatus.Status.STANDBY: + return "Standby" + case BikeStatus.Status.ACCESSORY: + return "Accessory" + case BikeStatus.Status.CHECKING: + return "Checking" + case BikeStatus.Status.READY: + return "Ready" + case BikeStatus.Status.DRIVE: + return "Drive" + case BikeStatus.Status.FAULT: + return "Fault" + } } + } + + Text { + text: "PDU" + color: "blue" + font.pixelSize: 24 + } +} diff --git a/Bolt_Dash/content/FaultMotorStatus.qml b/Bolt_Dash/content/FaultMotorStatus.qml new file mode 100644 index 0000000..2bc1a7f --- /dev/null +++ b/Bolt_Dash/content/FaultMotorStatus.qml @@ -0,0 +1,227 @@ +import QtQuick 2.15 +import QtQuick.Controls +import QtQuick.Shapes + +Item { + width: 400 + height: 150 + property bool motorOn: false + property bool bmsError: false + property bool bmsWarning: false + property bool mcFault: false + readonly property string red: "#e80c0c" + readonly property string green: "#54c45e" + readonly property int padding: 10 + readonly property color good: green + readonly property color bad: red + readonly property color warn: "orange" + readonly property color off: "black" + id: root + + // Motor On + Rectangle { + id: motorOnIndicator + x: width + y: 0 + width: 100 + height: width + radius: width/2 + color: "transparent" + border.width: 5 + border.color: "white" + + // Indicator circle + Rectangle { + readonly property int offset: 15 + x: offset + y: offset + width: parent.width - offset*2 + height: width + radius: width/2 + color: motorOn ? good : off + } + } + + // Motor On Indicator text + Rectangle { + x: 0 + y: motorOnIndicator.y + motorOnIndicator.height + id: motorOnIndicatorRect + width: motorOnIndicatorText.width + padding*2 + height: motorOnIndicatorText.height + padding + color: "transparent" + border.width: 2 + border.color: "white" + radius: 10 + + Text { + id: motorOnIndicatorText + anchors.centerIn: parent + text: "Motor On" + font.pixelSize: 20 + color: "white" + verticalAlignment: Text.AlignVCenter + } + } + + Shape { + ShapePath { + id: motorOnIndicatorConnector + strokeColor: "white" + strokeWidth: 2 + fillColor: "transparent" + startX: motorOnIndicatorRect.x + motorOnIndicatorRect.width/2 + startY: motorOnIndicatorRect.y + PathCurve { + x: motorOnIndicatorConnector.startX+10; y: motorOnIndicator.y+4*motorOnIndicator.height/5 + } + PathCurve { + x: motorOnIndicator.x+5; y: motorOnIndicator.y+2*motorOnIndicator.height/3 + } + } + } + + // BMS Fault + Button { + id: bmsFaultIndicator + x: motorOnIndicator.x + motorOnIndicator.width + padding + y: 7 + width: 50 + height: width + onClicked: { + bmsError = !bmsError + bmsFaultDetails.show() + } + flat: true + indicator: Rectangle { + // id: bmsFaultIndicator + // x: motorOnIndicator.x + motorOnIndicator.width + padding + // y: 7 + x: 0 + y: 0 + width: 50 + height: width + radius: width/2 + color: "transparent" + border.width: 5 + border.color: "white" + + // Indicator circle + Rectangle { + readonly property int offset: 12 + x: offset + y: offset + width: parent.width - offset*2 + height: width + radius: width/2 + color: bmsError ? bad : (bmsWarning ? warn : off) + } + } + } + + // BMS Fault Indicator text + Rectangle { + x: bmsFaultIndicator.x + bmsFaultIndicator.width + padding + y: bmsFaultIndicator.y - 2*bmsFaultIndicator.height/5 + id: bmsFaultIndicatorRect + width: bmsFaultIndicatorText.width + padding*2 + height: bmsFaultIndicatorText.height + padding + color: "transparent" + border.width: 2 + border.color: "white" + radius: 10 + + Text { + id: bmsFaultIndicatorText + anchors.centerIn: parent + text: "BMS Fault" + font.pixelSize: 20 + color: "white" + verticalAlignment: Text.AlignVCenter + } + } + + Shape { + ShapePath { + id: bmsFaultIndicatorConnector + strokeColor: "white" + strokeWidth: 2 + fillColor: "transparent" + startX: bmsFaultIndicatorRect.x + bmsFaultIndicatorRect.width/2 + startY: bmsFaultIndicatorRect.y + bmsFaultIndicatorRect.height + PathCurve { + x: bmsFaultIndicatorConnector.startX-10; y: bmsFaultIndicator.y+3*bmsFaultIndicator.height/5 + } + PathCurve { + x: bmsFaultIndicator.x+bmsFaultIndicator.width - 1; y: bmsFaultIndicator.y+2*bmsFaultIndicator.height/3 + } + } + } + + // MC Fault + Rectangle { + id: mcFaultIndicator + x: bmsFaultIndicator.x + y: bmsFaultIndicator.y + bmsFaultIndicator.height + padding + width: 75 + height: width + radius: width/2 + color: "transparent" + border.width: 5 + border.color: "white" + + // Indicator circle + Rectangle { + readonly property int offset: 13 + x: offset + y: offset + width: parent.width - offset*2 + height: width + radius: width/2 + color: mcFault ? bad : off + } + } + + // MC Fault Indicator Text + Rectangle { + x: bmsFaultIndicatorRect.x + padding + y: mcFaultIndicator.y - 1*mcFaultIndicator.height/5 + id: mcFaultIndicatorRect + width: mcFaultIndicatorText.width + padding*2 + height: mcFaultIndicatorText.height + padding + color: "transparent" + border.width: 2 + border.color: "white" + radius: 10 + + Text { + id: mcFaultIndicatorText + anchors.centerIn: parent + text: "MC Fault" + font.pixelSize: 20 + color: "white" + verticalAlignment: Text.AlignVCenter + } + } + + Shape { + ShapePath { + id: mcFaultIndicatorConnector + strokeColor: "white" + strokeWidth: 2 + fillColor: "transparent" + startX: mcFaultIndicatorRect.x + mcFaultIndicatorRect.width/2 + startY: mcFaultIndicatorRect.y + mcFaultIndicatorRect.height + PathCurve { + x: mcFaultIndicatorConnector.startX-10; y: mcFaultIndicator.y+3*mcFaultIndicator.height/5 + } + PathCurve { + x: mcFaultIndicator.x + mcFaultIndicator.width - 2; y: mcFaultIndicator.y+2*mcFaultIndicator.height/3 + } + } + } + + BMSFaultDetails { + id: bmsFaultDetails + } +} diff --git a/Bolt_Dash/content/FullBatterySlider.qml b/Bolt_Dash/content/FullBatterySlider.qml new file mode 100644 index 0000000..ed48d01 --- /dev/null +++ b/Bolt_Dash/content/FullBatterySlider.qml @@ -0,0 +1,37 @@ +import QtQuick +import Bolt_Dash + +Item { + property int soc + readonly property int textLabelY: 260 + readonly property int valueLabelY: textLabelY+25 + + + BatterySlider { + id: packSlider + x: 0 + y: 0 + scale: 0.5 + fullness: soc // Percent to decimal + } + + // Max battery percentages + Text { + x: packSlider.x + packSlider.width/2 - width/2 + y: valueLabelY + horizontalAlignment: Text.AignHCenter + text: qsTr("%1\%").arg(soc) + color: Constants.textColor + font.pixelSize: valueLabelTextSize + } + + Text { + id: packLabel + horizontalAlignment: Text.AlignHCenter + x: packSlider.x + packSlider.width/2 - width/2 + y: textLabelY + text: qsTr("PACK") + color: Constants.textColor + font.pixelSize: labelTextSize + } +} \ No newline at end of file diff --git a/Bolt_Dash/content/FullSlider.qml b/Bolt_Dash/content/FullSlider.qml new file mode 100644 index 0000000..7e793aa --- /dev/null +++ b/Bolt_Dash/content/FullSlider.qml @@ -0,0 +1,56 @@ +import QtQuick + +Item { + property string label: "" + property string imageUrl: "" + property color textColor: "white" + property double fullness: 0.5 + property int value: 0 + property int imageWidth: 50 + property int imageHeight: 50 + readonly property int padding: 5 + readonly property int valueLabelTextSize: 30 + + + height: packTempSlider.height*packTempSlider.scale + packTempLabel.height + valueLabel.height + width: packTempSlider.width*packTempSlider.scale + padding + + TempSlider { + id: packTempSlider + x: 0 + y: -(height*scale)/2 + padding + scale: 0.5 + fullness: parent.fullness > 1 ? 1 : parent.fullness < 0 ? 0 : parent.fullness // Abosulte max of 100C and divide by 2 for avg + } + + // current temp label + Text { + id: valueLabel + x: packTempSlider.width + y: height/2 + text: qsTr("%1").arg(value) + font.bold: true + font.pixelSize: valueLabelTextSize + color: textColor + } + + Text { + id: unitLabel + x: valueLabel.x + y: valueLabel.y + valueLabel.height + text: qsTr("°C") + font.bold: true + color: textColor + font.pixelSize: 20 + + } + + Image { + id: packTempLabel + x: packTempSlider.x - width/2 + packTempSlider.width/2 + y: packTempSlider.height*packTempSlider.scale - height - padding + source: imageUrl + width: imageWidth + height: imageHeight + } +} \ No newline at end of file diff --git a/Bolt_Dash/content/Pictures/Virginia_Tech_Hokies_logo.svg b/Bolt_Dash/content/Pictures/Virginia_Tech_Hokies_logo.svg new file mode 100644 index 0000000..024f390 --- /dev/null +++ b/Bolt_Dash/content/Pictures/Virginia_Tech_Hokies_logo.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Bolt_Dash/content/Pictures/battery-twotone-0-svgrepo-com.svg b/Bolt_Dash/content/Pictures/battery-twotone-0-svgrepo-com.svg new file mode 100644 index 0000000..71a49e1 --- /dev/null +++ b/Bolt_Dash/content/Pictures/battery-twotone-0-svgrepo-com.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Bolt_Dash/content/Pictures/battery.svg b/Bolt_Dash/content/Pictures/battery.svg new file mode 100644 index 0000000..567f0a4 --- /dev/null +++ b/Bolt_Dash/content/Pictures/battery.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Bolt_Dash/content/Pictures/battery_temp.svg b/Bolt_Dash/content/Pictures/battery_temp.svg new file mode 100644 index 0000000..7c63355 --- /dev/null +++ b/Bolt_Dash/content/Pictures/battery_temp.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Bolt_Dash/content/Pictures/controller_temp.svg b/Bolt_Dash/content/Pictures/controller_temp.svg new file mode 100644 index 0000000..3efeac5 --- /dev/null +++ b/Bolt_Dash/content/Pictures/controller_temp.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Bolt_Dash/content/Pictures/lightning-bolt-filled-shape.svg b/Bolt_Dash/content/Pictures/lightning-bolt-filled-shape.svg new file mode 100644 index 0000000..f8e1ce3 --- /dev/null +++ b/Bolt_Dash/content/Pictures/lightning-bolt-filled-shape.svg @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/Bolt_Dash/content/Pictures/motor_temp.svg b/Bolt_Dash/content/Pictures/motor_temp.svg new file mode 100644 index 0000000..4515bb9 --- /dev/null +++ b/Bolt_Dash/content/Pictures/motor_temp.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/Bolt_Dash/content/Pictures/motorcycleIcon.png b/Bolt_Dash/content/Pictures/motorcycleIcon.png new file mode 100644 index 0000000..5a3a004 Binary files /dev/null and b/Bolt_Dash/content/Pictures/motorcycleIcon.png differ diff --git a/Bolt_Dash/content/Screen01.ui.qml b/Bolt_Dash/content/Screen01.ui.qml index 0ff340b..be8881d 100644 --- a/Bolt_Dash/content/Screen01.ui.qml +++ b/Bolt_Dash/content/Screen01.ui.qml @@ -8,209 +8,94 @@ Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on import QtQuick 6.2 import QtQuick.Controls 6.2 import Bolt_Dash -import Backend Rectangle { - id: rectangle - width: Constants.width - height: Constants.height - - color: Constants.backgroundColor - - readonly property int sliderY: 160 - readonly property int textLabelY: sliderY + 260 - readonly property int valueLabelY: textLabelY+25 - readonly property int labelTextSize: 25 - readonly property int valueLabelTextSize: 20 - - Speedometer { - id: speedometer - fullness: backend.motorSpeed / 5500 // Expected max speed of 5500 RPM - x: 50 - y: 24 - } - - Backend { - id: backend - motorTemp: 0 - auxVoltage: 0 - auxPercent: 0 - packSOC: 0 - highCellTemp: 0 - lowCellTemp: 0 - bmsTemp: 0 - motorSpeed: 0 - bikeSpeed: 0 - } - - // Remove for production - // Slider { - // id: slider - // x: -274 - // y: 209 - // width: 600 - // height: 48 - // scale: 0.5 - // rotation: -90 - // value: 0.5 - // } - - BatterySlider { - id: packSlider - x: 28 - y: 175 - scale: 0.5 - fullness: backend.packSOC / 100 // Percent to decimal - } - - BatterySlider { - id: auxSlider - x: 98 - y: 175 - scale: 0.5 - fullness: backend.auxPercent // Percent to decimal - } - - // Max battery percentages - Text { - x: packSlider.x + (packSlider.width/4) - y: valueLabelY - text: qsTr("%1\%").arg(backend.packSOC) - horizontalAlignment: Text.AlignHCenter - font.pixelSize: valueLabelTextSize - } - Text { - x: auxSlider.x + (auxSlider.width/4) - y: valueLabelY - text: qsTr("%1\%").arg(backend.auxPercent) - horizontalAlignment: Text.AlignHCenter - font.pixelSize: valueLabelTextSize - } - - Text { - id: packLabel - x: 36 - y: 444 - width: 48 - height: 29 - text: qsTr("PACK") - font.pixelSize: 20 - horizontalAlignment: Text.AlignHCenter - } - - Text { - id: auxLabel - x: 104 - y: 443 - width: 48 - height: 29 - text: qsTr("AUX") - font.pixelSize: 20 - horizontalAlignment: Text.AlignHCenter - } - - TempSlider { - id: packTempSlider - x: 715 - y: 175 - scale: 0.5 - fullness: (backend.highCellTemp+backend.lowCellTemp) / 200 // Abosulte max of 100C and divide by 2 for avg - } - - Text { - id: packTempLabel - x: 723 - y: 444 - width: 48 - height: 29 - text: qsTr("PACK") - font.pixelSize: 20 - horizontalAlignment: Text.AlignHCenter - } - - // Pack max temp label - Text { - x: packTempSlider.x + (packTempSlider.width/4) - y: valueLabelY - text: qsTr("%1°C").arg(backend.highCellTemp) - font.pixelSize: valueLabelTextSize - } - - TempSlider { - id: mCTempSlider - x: 644 - y: 175 - scale: 0.5 - fullness: backend.bmsTemp / 100 // Abosulte max of 100C - } - - Text { - id: mcTempLabel - x: 652 - y: 444 - width: 48 - height: 29 - text: qsTr("MC") - font.pixelSize: 20 - horizontalAlignment: Text.AlignHCenter - } - - // MC max temp label - Text { - x: mCTempSlider.x + (mCTempSlider.width/4) - y: valueLabelY - text: qsTr("%1°C").arg(backend.mcTemp) - font.pixelSize: valueLabelTextSize - } - - TempSlider { - id: motorTempSlider - x: 568 - y: 175 - scale: 0.5 - fullness: backend.motorTemp / 115 // Abosulte max of 115C - } - - Text { - id: motorTempLabel - x: 572 - y: 444 - width: 48 - height: 29 - text: qsTr("MOTOR") - font.pixelSize: 20 - horizontalAlignment: Text.AlignHCenter - } - - // Motor max temp label - Text { - x: motorTempSlider.x + (motorTempSlider.width/4) - y: valueLabelY - text: qsTr("%1°C").arg(backend.motorTemp) - font.pixelSize: valueLabelTextSize - } - - Text { - id: speedoLabel - x: 263 - y: 105 - width: 274 - height: 160 - text: qsTr(backend.bikeSpeed) - font.pixelSize: 125 - horizontalAlignment: Text.AlignHCenter - font.family: "Nasalization" - } - - WarningSymbol { - id: warningSymbol - x: 626 - y: 127 - } - - BoltLeanAngle { - id: leanAngle - x: Constants.width / 2 - y: Constants.height / 2 - } + id: rectangle + width: Constants.width + height: Constants.height + + color: backend.bmsFault ? Constants.errColor : Constants.backgroundColor + + readonly property int maxCurrent: 350 + + readonly property int sliderY: 160 + readonly property int textLabelY: sliderY + 260 + readonly property int valueLabelY: textLabelY+25 + readonly property int labelTextSize: 25 + readonly property int valueLabelTextSize: 20 + readonly property int mphLabelTextSize: 150 + readonly property int mphLabelX: 50 + readonly property int mphLabelY: 80 + readonly property int bikeStatusX: 0 + readonly property int verticalSpacing: 10 + readonly property int temperatureIslandY: 290 + + Speedometer { + id: speedometer + // fullness: backend.motorSpeed / 6000 // Expected max speed of 5500 RPM + fullness: Math.abs(backend.packCurrent) / maxCurrent + x: 50 + y: 25 + } + + SpeedometerDecorations { + x: speedometer.x + y: speedometer.y + } + + BatteryReadout { + id: batteryReadout + x: 0 + y: 300 + // soc: 50 + // voltage: 541.2 + soc: backend.packSOC * 100 + voltage: backend.packVoltage + } + + TemperatureIsland { + id: temps + x: 500 + y: temperatureIslandY + packTemp: backend.highCellTemp + mcTemp: backend.mcTemp + motorTemp: backend.motorTemp + // packTemp: 0.89*70 + // mcTemp: 91 + // motorTemp: 0.9*115 + } + Text { + id: speedoLabel + x: mphLabelX + y: speedometer.y + speedometer.height/2 + 7 +verticalSpacing + text: qsTr("%1").arg(Math.round(backend.bikeSpeed)) + color: Constants.textColor + font.pixelSize: mphLabelTextSize // For showing speed in mph + horizontalAlignment: Text.AlignHLeft + } + + // :( + // BoltLeanAngle { + // id: leanAngle + // ang: 39 + // x: ((Constants.width - width*scale/1.5) / 2) + // y: (Constants.height - height/2*scale) / 2 + // scale: 0.6 + // } + + BikeStatus { + id: bikeStatus + x: bikeStatusX + y: Constants.height - height + status: backend.bikeStatus + } + + FaultMotorStatus { + x: Constants.width - width + y: speedometer.y + speedometer.height + 40 + motorOn: backend.motorOn + mcFault: backend.mcFault + bmsError: backend.bmsError + bmsWarning: backend.bmsWarning + } } diff --git a/Bolt_Dash/content/Speedometer.qml b/Bolt_Dash/content/Speedometer.qml index 00506ea..3bb7277 100644 --- a/Bolt_Dash/content/Speedometer.qml +++ b/Bolt_Dash/content/Speedometer.qml @@ -8,7 +8,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Shapes 2.15 import Bolt_Dash 1.0 -import QtQuick.Studio.Components +// import QtQuick.Components Item { @@ -18,28 +18,22 @@ Item { height: 75 property double fullness: 0.5; - Connections { - target: container - onSpeedoPercentChanged: { - curveCanvas.requestPaint(); - } - } - Rectangle { id: root width: parent.width height: parent.height - radius: 10 - border.color: "#616161" + radius: 0 + border.color: "#000000" border.width: 10 Rectangle { id: rectangle + radius: 0 x: 10 y: 10 width: 680*fullness height: 55 - color: "#0c00ff" + color: "#E5751F" } } } diff --git a/Bolt_Dash/content/SpeedometerDecorations.qml b/Bolt_Dash/content/SpeedometerDecorations.qml new file mode 100644 index 0000000..4147727 --- /dev/null +++ b/Bolt_Dash/content/SpeedometerDecorations.qml @@ -0,0 +1,65 @@ +import QtQuick 2.15 +import QtQuick.Shapes + +Item { + id: root + readonly property int leftLineWidth: 200 + readonly property int rightLineWidth: 125 + + Shape { + id: leftLine + ShapePath { + id: leftLinePath + strokeColor: "white" + strokeWidth: 2 + fillColor: "transparent" + startX: -100 + startY: 225 + PathLine { x: leftLinePath.startX + root.leftLineWidth; y: leftLinePath.startY } + } + } + + Text { + id: leftText + text: "mph" + color: "white" + font.italic: true + font.pixelSize: 20 + x: leftLinePath.startX + leftLine.width + root.leftLineWidth + 10 + y: leftLinePath.startY - 15 + } + + Shape { + id: rightLine + ShapePath { + id: rightLinePath + strokeColor: "white" + strokeWidth: 2 + fillColor: "transparent" + startX: leftText.x + leftText.width + 10 + startY: 225 + PathLine { x: rightLinePath.startX + root.rightLineWidth; y: rightLinePath.startY } + PathLine { x: rightLinePath.startX + root.rightLineWidth + 75; y: 85 } + PathLine { x: 1000; y: 85 } + } + } + + Rectangle { + x: rightLinePath.startX + root.rightLineWidth + y: 120 + color: "black" + radius: 10 + border.width: 2 + border.color: "white" + width: 85 + height: 60 + + Image { + id: packTempLabel + anchors.centerIn: parent + source: "Pictures/Virginia_Tech_Hokies_logo.svg" + width: 70 + height: 35 + } + } +} diff --git a/Bolt_Dash/content/TempSlider.qml b/Bolt_Dash/content/TempSlider.qml index bca903b..3882ad1 100644 --- a/Bolt_Dash/content/TempSlider.qml +++ b/Bolt_Dash/content/TempSlider.qml @@ -2,8 +2,8 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 Item { - width: 60 - height: 350 + width: 40 + height: 250 readonly property string red: "#e80c0c" readonly property string green: "#09bd0f" property double fullness: 0.5; @@ -18,21 +18,48 @@ Item { Rectangle { id: enclosing + radius: 10 x: 0 y: 0 - width: 60 - height: 350 + width: parent.width + height: parent.height - bubble.height + color: "black"; border.width: 3 - color: `#${integerToHex(9 + (fullness * 223))}${integerToHex(189-(fullness*177))}${integerToHex(15+(fullness*-3))}`; + border.color: "white" } Rectangle { id: level + radius: 10 x: 0 - y: 0 - width: 60 - height: 350-(350*fullness) - color: "white" + y: enclosing.height-(enclosing.height*fullness) > 0 ? enclosing.height-(enclosing.height*fullness) : 0 + width: parent.width + height: (enclosing.height*fullness) + // color: `#${integerToHex(9 + (fullness * 223))}${integerToHex(189-(fullness*177))}${integerToHex(15+(fullness*-3))}`; + color: fullness > 0.9 ? red : "white"; + border.width: 3 + border.color: "white" + } + + Rectangle { + id: bubble + x: -(width-enclosing.width)/2 + y: enclosing.height + height: 100 + width: 100 + radius: width/2 + color: fullness > 0.9 ? red : "white" border.width: 3 } + + + Rectangle { + id: bubblebg + x: enclosing.x + y: bubble.y - enclosing.radius/2 - 1 + // radius: level.radius + height: 50 + width: enclosing.width + color: bubble.color + } } diff --git a/Bolt_Dash/content/TemperatureIsland.qml b/Bolt_Dash/content/TemperatureIsland.qml new file mode 100644 index 0000000..97c4c46 --- /dev/null +++ b/Bolt_Dash/content/TemperatureIsland.qml @@ -0,0 +1,70 @@ +import QtQuick + +Item { + width: 500 + height: 250 + + property int packTemp: 0 + property int mcTemp: 0 + property int motorTemp: 0 + readonly property int padding: 10 + readonly property int horizSpacing: 35 + readonly property int sliderWidth: 55 + + + Rectangle { + x: 0 + y: 0 + radius: 0 + width: parent.width + height: parent.height + color: "transparent" + border.width: 2 + border.color: "white" + + FullSlider { + id: packSlider + x: 3*padding + y: 15 + label: "PACK" + fullness: packTemp / 70 + value: packTemp + imageUrl: "Pictures/battery_temp.svg" + imageWidth: 35 + imageHeight: 30 + } + + FullSlider { + id: mcSlider + x: packSlider.x + horizSpacing + sliderWidth + y: packSlider.y + label: "MC" + fullness: mcTemp / 100 + value: mcTemp + imageUrl: "Pictures/controller_temp.svg" + imageWidth: 30 + imageHeight: 30 + } + + FullSlider { + id: motorSlider + x: mcSlider.x + horizSpacing + sliderWidth + y: packSlider.y + label: "MOTOR" + fullness: motorTemp / 115 + value: motorTemp + imageUrl: "Pictures/motor_temp.svg" + imageWidth: 30 + imageHeight: 25 + } + + // Redline + // Rectangle { + // x: 25 + // y: 13 + // width: 200 + // height: 3 + // color: "red" + // } + } +} \ No newline at end of file diff --git a/Bolt_Dash/content/WarningSymbol.qml b/Bolt_Dash/content/WarningSymbol.qml deleted file mode 100644 index 3cf02f4..0000000 --- a/Bolt_Dash/content/WarningSymbol.qml +++ /dev/null @@ -1,19 +0,0 @@ -import QtQuick 2.15 -import QtQuick.Controls 2.15 - -Item { - width: 100 - height: 100 - - Rectangle { - id: rectangle - x: 0 - y: 0 - width: 100 - height: 100 - color: "red" - border.color: "black" - border.width: 7 - radius: 15 - } -} diff --git a/Bolt_Dash/content/fonts/MesloLGSDZNerdFontMono-Regular.ttf b/Bolt_Dash/content/fonts/MesloLGSDZNerdFontMono-Regular.ttf new file mode 100755 index 0000000..a26a052 Binary files /dev/null and b/Bolt_Dash/content/fonts/MesloLGSDZNerdFontMono-Regular.ttf differ diff --git a/Bolt_Dash/gpsprocessing.cpp b/Bolt_Dash/gpsprocessing.cpp new file mode 100644 index 0000000..cb7a204 --- /dev/null +++ b/Bolt_Dash/gpsprocessing.cpp @@ -0,0 +1,67 @@ +#include "gpsprocessing.h" + +std::mutex gps_m; +double gps_lat; +double gps_lon; + +#ifdef GPS_LIB_FOUND + +int gpsMain() { + gpsmm gps_rec("localhost", DEFAULT_GPSD_PORT); + + if (!gps_rec.stream(WATCH_ENABLE | WATCH_JSON)) { + std::cerr << "No GPSD running." << std::endl; + return 1; + } + + while (true) { + struct gps_data_t *gpsd_data; + + if (!gps_rec.waiting(5000000)) { + continue; + } + + gpsd_data = gps_rec.read(); + + if (gpsd_data == nullptr) { + std::cerr << "Read error." << std::endl; + continue; + } + + if ((gpsd_data->fix.mode == MODE_2D || gpsd_data->fix.mode == MODE_3D) && + !std::isnan(gpsd_data->fix.latitude) && + !std::isnan(gpsd_data->fix.longitude)) { + + // std::cout << std::fixed << std::setprecision(6); + // std::cout << "Latitude: " << gpsd_data->fix.latitude << std::endl; + // std::cout << "Longitude: " << gpsd_data->fix.longitude << std::endl; + // std::cout << "Altitude: " << gpsd_data->fix.altitude << " m" << std::endl; + // std::cout << "Speed: " << gpsd_data->fix.speed * 3.6 << " km/h" << std::endl; + + // // Use timespec_t for time + // std::cout << "Timestamp: " + // << gpsd_data->fix.time.tv_sec << "." + // << std::setfill('0') << std::setw(9) + // << gpsd_data->fix.time.tv_nsec << std::endl; + + // std::cout << std::endl; + + gps_m.lock(); + gps_lat = gpsd_data->fix.latitude; + gps_lon = gpsd_data->fix.longitude; + gps_m.unlock(); + } + + sleep(1); + } + + return 0; +} + +#else +int gpsMain() { + gps_lat = 0.0; + gps_lon = 0.0; + return 0; +} +#endif \ No newline at end of file diff --git a/Bolt_Dash/gpsprocessing.h b/Bolt_Dash/gpsprocessing.h new file mode 100644 index 0000000..7b2556b --- /dev/null +++ b/Bolt_Dash/gpsprocessing.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include +#include +#if __has_include() +#include +#define GPS_LIB_FOUND 1 +#endif +#include +#include + +extern std::mutex gps_m; +extern double gps_lat; +extern double gps_lon; + +int gpsMain(); \ No newline at end of file diff --git a/Bolt_Dash/imports/Backend/CMakeLists.txt b/Bolt_Dash/imports/Backend/CMakeLists.txt deleted file mode 100644 index 575b479..0000000 --- a/Bolt_Dash/imports/Backend/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -### This file is automatically generated by Qt Design Studio. -### Do not change - -qt_add_library(Backend STATIC) - -qt6_add_qml_module(BackendPlugin - URI "Backend" - VERSION 1.0 - SOURCES - can.cpp - can.h - backend.h - backend.cpp - RESOURCE_PREFIX "/" -) - diff --git a/Bolt_Dash/imports/Backend/backend.cpp b/Bolt_Dash/imports/Backend/backend.cpp deleted file mode 100644 index 8e426c0..0000000 --- a/Bolt_Dash/imports/Backend/backend.cpp +++ /dev/null @@ -1,147 +0,0 @@ -#include "backend.h" -#include "can.h" - -// Create Backend class which can be included in QML -Backend::Backend(QObject *parent) : QObject(parent), m_motorTemp{}, m_auxVoltage{}, m_auxPercent{}, - m_packSOC{}, m_highCellTemp{}, m_lowCellTemp{}, m_bmsTemp{}, m_motorSpeed{}, m_bikeSpeed{} { - std::thread update_vars(&Backend::updateVars, this); - update_vars.detach(); -} - -// Calls the set functions with the values from data -void Backend::updateVars() { - while (true) { - m.lock(); - // The only scaling here is to put the value into the right unit - setMotorTemp(data.motor_temperature / 10.0); // celsius - setAuxVoltage(data.aux_voltage / 10); // volts - setAuxPercent(data.aux_percent / 255.0); // percent - setPackSOC(data.pack_state_of_charge / 255.0); // percent - setHighCellTemp(data.high_cell_temp); // celsius - setLowCellTemp(data.low_cell_temp); // celsius - setBmsTemp(data.bms_temperature); // celsius - setMotorSpeed(data.motor_speed); // rpm - setBikeSpeed(data.bike_speed / 100.0); // mph - setBmsFault(data.bms_error); - setMcTemp(data.mc_temperature / 10.0); // celsius - m.unlock(); - // Debug Message - // std::cout << "MotorTemp: " << motorTemp() << " AuxVoltage: " << auxVoltage() << " AuxPercent: " << auxPercent() << " PackSOC: " << packSOC() << " HighCellTemp: " << highCellTemp() << " LowCellTemp: " << lowCellTemp() << " BmsTemp: " << bmsTemp() << " MotorSpeed: " << motorSpeed() << " BikeSpeed: " << bikeSpeed() << std::endl; - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - } -} - -// Functions to get variable values -// { // Brackets for collapsability -double Backend::motorTemp() const { - return m_motorTemp; -} - -double Backend::auxVoltage() const { - return m_auxVoltage; -} - -double Backend::auxPercent() const { - return m_auxPercent; -} - -double Backend::packSOC() const { - return m_packSOC; -} - -double Backend::highCellTemp() const { - return m_highCellTemp; -} - -double Backend::lowCellTemp() const { - return m_lowCellTemp; -} - -double Backend::bmsTemp() const { - return m_bmsTemp; -} - -double Backend::motorSpeed() const { - return m_motorSpeed; -} - -double Backend::bikeSpeed() const { - return m_bikeSpeed; -} - -double Backend::mcTemp() const { - return m_mcTemp; -} - -bool Backend::bmsFault() const { - return m_bmsFault; -} -// } - -// Setter Functions -// { // Brackets for collapsability -void Backend::setMotorTemp(const double temp) { - if (m_motorTemp != temp) { - m_motorTemp = temp; - emit motorTempChanged(); - } -} - -void Backend::setAuxVoltage(const double cap) { - if (m_auxVoltage != cap) { - m_auxVoltage = cap; - emit auxVoltageChanged(); - } -} - -void Backend::setAuxPercent(const double cap) { - if (m_auxPercent != cap) { - m_auxPercent = cap; - emit auxPercentChanged(); - } -} - -void Backend::setPackSOC(const double soc) { - if (m_packSOC != soc) { - m_packSOC = soc; - emit packSOCChanged(); - } -} - -void Backend::setHighCellTemp(const double temp) { - if (m_highCellTemp != temp) { - m_highCellTemp = temp; - emit highCellTempChanged(); - } -} - -void Backend::setLowCellTemp(const double temp) { - if (m_lowCellTemp != temp) { - m_lowCellTemp = temp; - emit lowCellTempChanged(); - } -} - -void Backend::setBmsTemp(const double temp) { - if (m_bmsTemp != temp) { - m_bmsTemp = temp; - emit bmsTempChanged(); - } -} - -void Backend::setMotorSpeed(const double speed) { - if (m_motorSpeed != speed) { - m_motorSpeed = speed; - emit motorSpeedChanged(); - } -} - -void Backend::setBikeSpeed(const double speed) { - if (m_bikeSpeed != speed) { - m_bikeSpeed = speed; - emit bikeSpeedChanged(); - } -} -// } - -std::thread can_thread(can::run); diff --git a/Bolt_Dash/imports/Backend/backend.h b/Bolt_Dash/imports/Backend/backend.h deleted file mode 100644 index d5e96ed..0000000 --- a/Bolt_Dash/imports/Backend/backend.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef BACKEND_H -#define BACKEND_H - -#include -#include -#include -#include -#include -#include - -class Backend : public QObject { - Q_OBJECT - QML_ELEMENT - Q_PROPERTY(double motorTemp READ motorTemp WRITE setMotorTemp NOTIFY motorTempChanged); - Q_PROPERTY(double auxVoltage READ auxVoltage WRITE setAuxVoltage NOTIFY auxVoltageChanged); - Q_PROPERTY(double auxPercent READ auxPercent WRITE setAuxPercent NOTIFY auxPercentChanged); - Q_PROPERTY(double packSOC READ packSOC WRITE setPackSOC NOTIFY packSOCChanged); - Q_PROPERTY(double highCellTemp READ highCellTemp WRITE setHighCellTemp NOTIFY highCellTempChanged); - Q_PROPERTY(double lowCellTemp READ lowCellTemp WRITE setLowCellTemp NOTIFY lowCellTempChanged); - Q_PROPERTY(double bmsTemp READ bmsTemp WRITE setBmsTemp NOTIFY bmsTempChanged); - Q_PROPERTY(double motorSpeed READ motorSpeed WRITE setMotorSpeed NOTIFY motorSpeedChanged); - Q_PROPERTY(double bikeSpeed READ bikeSpeed WRITE setBikeSpeed NOTIFY bikeSpeedChanged); - Q_PROPERTY(double mcTemp READ mcTemp WRITE setMcTemp NOTIFY mcTempChanged); - Q_PROPERTY(bool bmsFault READ bmsFault WRITE setBmsFault NOTIFY bmsFaultChanged); - -public: - explicit Backend(QObject *parent = nullptr); - double motorTemp() const; - double auxVoltage() const; - double auxPercent() const; - double packSOC() const; - double highCellTemp() const; - double lowCellTemp() const; - double bmsTemp() const; - double motorSpeed() const; - double bikeSpeed() const; - double mcTemp() const; - bool bmsFault() const; - - void setMotorTemp(const double temp); - void setAuxVoltage(const double cap); - void setAuxPercent(const double cap); - void setPackSOC(const double soc); - void setHighCellTemp(const double temp); - void setLowCellTemp(const double temp); - void setBmsTemp(const double temp); - void setMotorSpeed(const double speed); - void setBikeSpeed(const double speed); - void setMcTemp(const double temp); - void setBmsFault(const bool fault); - -signals: - void motorTempChanged(); - void auxVoltageChanged(); - void auxPercentChanged(); - void packSOCChanged(); - void highCellTempChanged(); - void lowCellTempChanged(); - void bmsTempChanged(); - void motorSpeedChanged(); - void bikeSpeedChanged(); - void mcTempChanged(); - void bmsFaultChanged(); - -private: - void updateVars(); - double m_motorTemp; - double m_auxVoltage; - double m_auxPercent; - double m_packSOC; - double m_highCellTemp; - double m_lowCellTemp; - double m_bmsTemp; - double m_motorSpeed; - double m_bikeSpeed; - double m_mcTemp; - bool m_bmsFault; -}; - -#endif // BACKEND_H diff --git a/Bolt_Dash/imports/Backend/can.cpp b/Bolt_Dash/imports/Backend/can.cpp deleted file mode 100644 index 43054f5..0000000 --- a/Bolt_Dash/imports/Backend/can.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include "can.h" - -using namespace std::chrono_literals; - -std::mutex m; -our_candata data{}; - -namespace can { - int run() { - // Where the data will be stored to be send to the front end - int s, i; - int nbytes; - struct sockaddr_can addr; - struct ifreq ifr; - struct can_frame frame; - int8_t *unknown_data = nullptr; - - printf("CAN Sockets Receive Demo\r\n"); - - // Create a new socket of type CAN using data CAN_RAW - if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) { - perror("Socket"); - return 1; - } - - // Setting the name of the physical can interface (ip a) - strcpy(ifr.ifr_name, "can0"); - // Converts if name to actual interface index - ioctl(s, SIOCGIFINDEX, &ifr); - - // Reserve memory for CAN frames - memset(&addr, 0, sizeof(addr)); - addr.can_family = AF_CAN; // Use CAN sockets specifically - addr.can_ifindex = ifr.ifr_ifindex; - - // Connects to the socket and it locks - if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - perror("Bind"); - return 1; - } - - while (true) { - // Actually reads from the socket - nbytes = read(s, &frame, sizeof(struct can_frame)); - - // Make sure it exists - if (nbytes < 0) { - perror("Read"); - return 1; - } - m.lock(); - switch (frame.can_id) { - case can_ids.aux_battery: - data.aux_voltage = frame.data[0]; - data.aux_percent = frame.data[1]; - break; - case can_ids.info_1: - data.pack_state_of_charge = frame.data[4]; - data.bms_error = frame.data[5] & BMS_FAULT_MASK; - break; - case can_ids.main_pack_temp: - data.high_cell_temp = frame.data[0]; - data.low_cell_temp = frame.data[1]; - break; - case can_ids.motor_temp: - data.motor_temperature = frame.data[0]; - data.motor_temperature += frame.data[1]; - break; - case can_ids.bms_temp: - data.bms_temperature = frame.data[0] << 8; - data.bms_temperature += frame.data[1]; - break; - case can_ids.rpm: - data.motor_speed = frame.data[0] << 8; - data.motor_speed += frame.data[1]; - break; - case can_ids.speed: - data.bike_speed = frame.data[0] << 8; - data.bike_speed += frame.data[1]; - break; - default: - unknown_data = new int8_t[frame.can_dlc]; - for (int i{}; i < frame.can_dlc; i++) { - unknown_data[i] = frame.data[i]; - } - } - m.unlock(); - - // Print the can ID and len of data - // printf("0x%03X [%d] ", frame.can_id, frame.can_dlc); - - // Print the data in the CAN message - // for (i = 0; i < frame.can_dlc; i++) - // printf("%02X ", frame.data[i]); - - // printf("\r\n"); - } - - // Close socket - if (close(s) < 0) { - perror("Close"); - return 1; - } - - return 0; - } -} diff --git a/Bolt_Dash/imports/Backend/can.h b/Bolt_Dash/imports/Backend/can.h deleted file mode 100644 index 7a0bd07..0000000 --- a/Bolt_Dash/imports/Backend/can.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef CAN_H -#define CAN_H - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#define BMS_FAULT_MASK 0b0010000 - -struct our_candata { - uint8_t aux_voltage{}; - uint8_t aux_percent{}; - uint8_t pack_state_of_charge{}; - uint16_t high_cell_temp{}; - uint16_t low_cell_temp{}; - int16_t motor_temperature{}; - uint16_t bms_temperature{}; - int16_t motor_speed{}; - int16_t bike_speed{}; - uint8_t bms_error{}; -}; - -// ID's for each CAN thing -constexpr struct { - canid_t aux_battery{0xB1}; - canid_t main_battery{0xB2}; - canid_t main_pack_temp{0xF1}; - canid_t motor_temp{0xF2}; - canid_t bms_temp{0xF3}; - canid_t rpm{0xA1}; - canid_t speed{0xA2}; -} can_ids; - -extern std::mutex m; -extern our_candata data; - -namespace can { - int run(); -} - -#endif // CAN_H diff --git a/Bolt_Dash/imports/Bolt_Dash/Constants.qml b/Bolt_Dash/imports/Bolt_Dash/Constants.qml index cb27244..6c20441 100644 --- a/Bolt_Dash/imports/Bolt_Dash/Constants.qml +++ b/Bolt_Dash/imports/Bolt_Dash/Constants.qml @@ -1,6 +1,6 @@ pragma Singleton import QtQuick 6.2 -import QtQuick.Studio.Application +// import QtQuick.Studio.Application QtObject { readonly property int width: 800 @@ -18,10 +18,12 @@ QtObject { pixelSize: Qt.application.font.pixelSize * 1.6 }) - readonly property color backgroundColor: "#c2c2c2" + readonly property color backgroundColor: "#000000" + readonly property color textColor: "#ffffff" + readonly property color errColor: "#ff0000" - property StudioApplication application: StudioApplication { + /*property StudioApplication application: StudioApplication { fontPath: Qt.resolvedUrl("../../content/" + relativeFontDirectory) - } + }*/ } diff --git a/Bolt_Dash/imports/CMakeLists.txt b/Bolt_Dash/imports/CMakeLists.txt index 43c175f..35b1948 100644 --- a/Bolt_Dash/imports/CMakeLists.txt +++ b/Bolt_Dash/imports/CMakeLists.txt @@ -2,5 +2,4 @@ ### Do not change add_subdirectory(Bolt_Dash) -add_subdirectory(Backend) add_subdirectory(IO) diff --git a/Bolt_Dash/imports/IO/io.cpp b/Bolt_Dash/imports/IO/io.cpp index 9afd9b2..aa0369a 100644 --- a/Bolt_Dash/imports/IO/io.cpp +++ b/Bolt_Dash/imports/IO/io.cpp @@ -1,5 +1,10 @@ #include "io.h" +#if __has_include() #include +#define PIGPIO_FOUND 1 +#endif + +#ifdef PIGPIO_FOUND // Create IO class which can be included in QML IO::IO(QObject *parent) : QObject(parent), m_buttonStatus{} { @@ -39,3 +44,27 @@ void IO::setButtonStatus(const bool status) { } } } + +#else // PIGPIO_FOUND + +IO::IO(QObject *parent) : QObject(parent), m_buttonStatus{} { + setButtonStatus(false); +} + +// Functions to get variable values +bool IO::buttonStatus() const { + return m_buttonStatus; +} + +// Setter Functions +void IO::setButtonStatus(const bool status) { + if (m_buttonStatus != status) { + m_buttonStatus = status; + emit buttonStatusChanged(); + if (m_buttonStatus == PRESSED) { + emit buttonTapped(); + } + } +} + +#endif // PIGPIO_FOUND \ No newline at end of file diff --git a/Bolt_Dash/main.qml b/Bolt_Dash/main.qml index 2c4f857..14ce61a 100644 --- a/Bolt_Dash/main.qml +++ b/Bolt_Dash/main.qml @@ -5,4 +5,5 @@ import QtQuick import content App { + visibility: "FullScreen" } diff --git a/Bolt_Dash/nmea_decoder.cpp b/Bolt_Dash/nmea_decoder.cpp new file mode 100644 index 0000000..0b450f8 --- /dev/null +++ b/Bolt_Dash/nmea_decoder.cpp @@ -0,0 +1,80 @@ +#include "nmea_decoder.h" + +std::vector split(const std::string &s, char delimiter) { + std::vector tokens; + std::string token; + std::istringstream tokenStream(s); + while (std::getline(tokenStream, token, delimiter)) { + tokens.push_back(token); + } + return tokens; +} + +double convertToDecimalDegrees(const std::string &value, const std::string &direction) { + double degree = std::stod(value.substr(0, value.find('.') - 2)); + double minutes = std::stod(value.substr(value.find('.') - 2)); + double decimalDegrees = degree + (minutes / 60.0); + + if (direction == "S" || direction == "W") { + decimalDegrees = -decimalDegrees; + } + + return decimalDegrees; +} + +GPSData decodeNMEA(const std::string &nmea) { + GPSData data; + std::vector parts = split(nmea, ','); + + if (parts[0] == "$GPGGA") { + if (parts.size() >= 15) { + data.time = parts[1].substr(0, 2) + ":" + parts[1].substr(2, 2) + ":" + parts[1].substr(4, 2); + if (!parts[2].empty() && !parts[3].empty()) { + data.latitude = convertToDecimalDegrees(parts[2], parts[3]); + } + if (!parts[4].empty() && !parts[5].empty()) { + data.longitude = convertToDecimalDegrees(parts[4], parts[5]); + } + data.fix = (parts[6] == "1" || parts[6] == "2") ? "Valid" : "Invalid"; + data.satellites = std::stoi(parts[7]); + // data.altitude = std::stod(parts[9]); + data.altitude = 0; + } + } else if (parts[0] == "$GPRMC") { + if (parts.size() >= 12) { + data.time = parts[1].substr(0, 2) + ":" + parts[1].substr(2, 2) + ":" + parts[1].substr(4, 2); + if (!parts[3].empty() && !parts[4].empty()) { + data.latitude = convertToDecimalDegrees(parts[3], parts[4]); + } + if (!parts[5].empty() && !parts[6].empty()) { + data.longitude = convertToDecimalDegrees(parts[5], parts[6]); + } + data.date = parts[9].substr(0, 2) + "/" + parts[9].substr(2, 2) + "/" + parts[9].substr(4, 2); + data.fix = (parts[2] == "A") ? "Valid" : "Invalid"; + } + } + + return data; +} + +void printGPSData(const GPSData &data) { + std::cout << "Time: " << data.time << std::endl; + std::cout << "Date: " << data.date << std::endl; + std::cout << "Latitude: " << data.latitude << std::endl; + std::cout << "Longitude: " << data.longitude << std::endl; + std::cout << "Altitude: " << data.altitude << " m" << std::endl; + std::cout << "Satellites: " << data.satellites << std::endl; + std::cout << "Fix: " << data.fix << std::endl; + std::cout << "------------------------" << std::endl; +} + +int nmmeaMain() { + std::string nmea; + while (std::getline(std::cin, nmea)) { + if (nmea.substr(0, 6) == "$GPGGA" || nmea.substr(0, 6) == "$GPRMC") { + GPSData data = decodeNMEA(nmea); + printGPSData(data); + } + } + return 0; +} diff --git a/Bolt_Dash/nmea_decoder.h b/Bolt_Dash/nmea_decoder.h new file mode 100644 index 0000000..2eb1c33 --- /dev/null +++ b/Bolt_Dash/nmea_decoder.h @@ -0,0 +1,25 @@ +#include +#include +#include +#include +#include + +struct GPSData { + double latitude = 0.0; + double longitude = 0.0; + std::string time = ""; + std::string date = ""; + double altitude = 0.0; + int satellites = 0; + std::string fix = "Invalid"; +}; + +std::vector split(const std::string &s, char delimiter); + +double convertToDecimalDegrees(const std::string &value, const std::string &direction); + +GPSData decodeNMEA(const std::string &nmea); + +void printGPSData(const GPSData &data); + +int nmmeaMain(); \ No newline at end of file diff --git a/Bolt_Dash/qmlmodules b/Bolt_Dash/qmlmodules index ca9bc8c..34bda49 100644 --- a/Bolt_Dash/qmlmodules +++ b/Bolt_Dash/qmlmodules @@ -14,4 +14,5 @@ add_subdirectory(imports) target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE contentplugin Bolt_Dashplugin + IOPlugin ) diff --git a/Bolt_Dash/qtquickcontrols2.conf b/Bolt_Dash/qtquickcontrols2.conf index 6f0d6fe..99e7698 100644 --- a/Bolt_Dash/qtquickcontrols2.conf +++ b/Bolt_Dash/qtquickcontrols2.conf @@ -6,7 +6,7 @@ Style=Material [Material] -Theme=Light +Theme=Dark ;Accent=BlueGrey ;Primary=BlueGray ;Foreground=Brown diff --git a/Bolt_Dash/src/includes/headers/nmeaparse/Event.h b/Bolt_Dash/src/includes/headers/nmeaparse/Event.h new file mode 100644 index 0000000..b6bbd97 --- /dev/null +++ b/Bolt_Dash/src/includes/headers/nmeaparse/Event.h @@ -0,0 +1,217 @@ +/* + * Event.h + * + * Created on: Sep 5, 2014 + * Author: Cameron Karlsson + * + * See the license file included with this source. + */ + +#ifndef EVENT_H_ +#define EVENT_H_ + +#include +#include +#include + + + +namespace nmea { + + + template class EventHandler; + template class Event; + + + template + class EventHandler + { + friend Event; + private: + // Typenames + typename Event::ListIterator _iterator; + + // Static members + static uint64_t LastID; + + // Properties + uint64_t ID; + std::function handler; + + // Functions + void _copy(const EventHandler& ref){ + if (&ref != this){ + _iterator = ref._iterator; + handler = ref.handler; + ID = ref.ID; + } + } + + public: + // Typenames + typedef void(*CFunctionPointer)(Args...); + + // Static members + // (none) + + // Properties + // (none) + + // Functions + EventHandler(std::function h) : _iterator(), handler(h), ID(++LastID) + {} + + EventHandler(const EventHandler& ref){ + _copy(ref); + } + + virtual ~EventHandler(){}; + + EventHandler& operator=(const EventHandler& ref){ + _copy(ref); + return *this; + } + + void operator() (Args... args){ + handler(args...); + } + + bool operator==(const EventHandler& ref){ + return ID == ref.ID; + } + + bool operator!=(const EventHandler& ref){ + return ID != ref.ID; + } + + uint64_t getID(){ + return ID; + } + + // Returns function pointer to the underlying function + // or null if it's not a function but implements operator() + CFunctionPointer* getFunctionPointer(){ + CFunctionPointer* ptr = handler.template target(); + return ptr; + } + }; + + template + uint64_t EventHandler::LastID = 0; + + + template + class Event + { + friend EventHandler; + private: + // Typenames + typedef typename std::list>::iterator ListIterator; + + // Static members + // (none) + + // Properties + std::list> handlers; + + //Functions + void _copy(const Event& ref){ + if (&ref != this){ + handlers = ref.handlers; + } + }; + + bool removeHandler(ListIterator handlerIter) { + if (handlerIter == handlers.end()){ + return false; + } + + handlers.erase(handlerIter); + return true; + }; + + public: + // Typenames + // (none) + + // Static members + // (none) + + // Properties + bool enabled; + + // Functions + Event() : enabled(true) + {} + + virtual ~Event() + {} + + Event(const Event& ref) { + _copy(ref); + } + + void call(Args... args) { + if (!enabled) { return; } + for (auto h = handlers.begin(); h != handlers.end(); h++) + { + (*h)(args...); + } + } + + EventHandler registerHandler(EventHandler handler) { + bool found = false; + for (auto h = handlers.begin(); h != handlers.end(); h++) + { + if ((*h) == handler) { + found = true; + break; + } + } + if (!found) + { + ListIterator itr = handlers.insert(handlers.end(), handler); + handler._iterator = itr; + } + return handler; + } + + EventHandler registerHandler(std::function handler) { + EventHandler wrapper(handler); + ListIterator itr = handlers.insert(handlers.end(), wrapper); + wrapper._iterator = itr; + return wrapper; + } + + bool removeHandler(EventHandler& handler) { + bool sts = removeHandler(handler._iterator); + handler._iterator = handlers.end(); + return sts; + }; + + void clear(){ + for (auto h = handlers.begin(); h != handlers.end(); h++) + { + (*h)._iterator = handlers.end(); + } + handlers.clear(); + }; + + void operator ()(Args... args) { return call(args...); }; + EventHandler operator +=(EventHandler handler) { return registerHandler(handler); }; + EventHandler operator +=(std::function handler) { return registerHandler(handler); }; + bool operator -=(EventHandler& handler) { return removeHandler(handler); }; + bool operator -=(uint64_t handlerID) { return removeHandler(handlerID); }; + + EventHandler& operator =(const EventHandler& ref){ + _copy(ref); + return *this; + }; + + }; + + + +} + +#endif /* EVENT_H_ */ diff --git a/Bolt_Dash/src/includes/headers/nmeaparse/GPSFix.h b/Bolt_Dash/src/includes/headers/nmeaparse/GPSFix.h new file mode 100644 index 0000000..da891ba --- /dev/null +++ b/Bolt_Dash/src/includes/headers/nmeaparse/GPSFix.h @@ -0,0 +1,182 @@ +/* + * GPSFix.h + * + * Created on: Jul 23, 2014 + * Author: Cameron Karlsson + * + * See the license file included with this source. + */ + +#ifndef GPSFIX_H_ +#define GPSFIX_H_ + +#include +#include +#include +#include +#include +#include +#include + +namespace nmea { + + class GPSSatellite; + class GPSAlmanac; + class GPSFix; + class GPSService; + + + // =========================== GPS SATELLITE ===================================== + + class GPSSatellite { + public: + GPSSatellite() : + snr(0), + prn(0), + elevation(0), + azimuth(0) + {}; + + //satellite data + double snr; // 0-99 dB + uint32_t prn; // id - 0-32 + double elevation; // 0-90 deg + double azimuth; // 0-359 deg + std::string toString(); + operator std::string(); + }; + + + + + + + // =========================== GPS ALMANAC ===================================== + + + class GPSAlmanac { + friend GPSService; + private: + uint32_t visibleSize; + uint32_t lastPage; + uint32_t totalPages; + uint32_t processedPages; + void clear(); //will remove all information from the satellites + void updateSatellite(GPSSatellite sat); + public: + GPSAlmanac() : + lastPage(0), + totalPages(0), + processedPages(0) + {}; + + //mapped by prn + std::vector satellites; + double averageSNR(); + double minSNR(); + double maxSNR(); + double percentComplete(); + + }; + + + + + // =========================== GPS TIMESTAMP ===================================== + + // UTC time + class GPSTimestamp { + private: + std::string monthName(uint32_t index); + public: + GPSTimestamp(); + + int32_t hour; + int32_t min; + double sec; + + int32_t month; + int32_t day; + int32_t year; + + // Values collected directly from the GPS + double rawTime; + int32_t rawDate; + + time_t getTime(); + + // Set directly from the NMEA time stamp + // hhmmss.sss + void setTime(double raw_ts); + + // Set directly from the NMEA date stamp + // ddmmyy + void setDate(int32_t raw_date); + + std::string toString(); + }; + + + + + + + // =========================== GPS FIX ===================================== + + class GPSFix { + friend GPSService; + + private: + + bool haslock; + bool setlock(bool b); //returns true if lock status **changed***, false otherwise. + + + public: + + GPSFix(); + virtual ~GPSFix(); + + + GPSAlmanac almanac; + GPSTimestamp timestamp; + + char status; // Status: A=active, V=void (not locked) + uint8_t type; // Type: 1=none, 2=2d, 3=3d + uint8_t quality; // Quality: + // 0 = invalid + // 1 = GPS fix (SPS) + // 2 = DGPS fix + // 3 = PPS fix + // 4 = Real Time Kinematic (RTK) + // 5 = Float RTK + // 6 = estimated (dead reckoning) (2.3 feature) + + double dilution; // Combination of Vertical & Horizontal + double horizontalDilution; // Horizontal dilution of precision, initialized to 100, best =1, worst = >20 + double verticalDilution; // Vertical is less accurate + + double altitude; // meters + double latitude; // degrees N + double longitude; // degrees E + double speed; // km/h + double travelAngle; // degrees true north (0-360) + int32_t trackingSatellites; + int32_t visibleSatellites; + + bool locked(); + double horizontalAccuracy(); + double verticalAccuracy(); + bool hasEstimate(); + + std::chrono::seconds timeSinceLastUpdate(); // Returns seconds difference from last timestamp and right now. + + std::string toString(); + operator std::string(); + + static std::string travelAngleToCompassDirection(double deg, bool abbrev = false); + }; + +} + +#endif /* GPSFIX_H_ */ diff --git a/Bolt_Dash/src/includes/headers/nmeaparse/GPSService.h b/Bolt_Dash/src/includes/headers/nmeaparse/GPSService.h new file mode 100644 index 0000000..8b9e291 --- /dev/null +++ b/Bolt_Dash/src/includes/headers/nmeaparse/GPSService.h @@ -0,0 +1,47 @@ +/* + * GPSService.h + * + * Created on: Aug 14, 2014 + * Author: Cameron Karlsson + * + * See the license file included with this source. + */ + +#ifndef GPSSERVICE_H_ +#define GPSSERVICE_H_ + +#include +#include +#include +#include +#include +#include + +namespace nmea { + +class GPSService { +private: + + void read_PSRF150(const NMEASentence& nmea); + void read_GPGGA (const NMEASentence& nmea); + void read_GPGSA (const NMEASentence& nmea); + void read_GPGSV (const NMEASentence& nmea); + void read_GPRMC (const NMEASentence& nmea); + void read_GPVTG (const NMEASentence& nmea); + +public: + GPSFix fix; + + GPSService(NMEAParser& parser); + virtual ~GPSService(); + + Event onLockStateChanged; // user assignable handler, called whenever lock changes + Event onUpdate; // user assignable handler, called whenever fix changes + + void attachToParser(NMEAParser& parser); // will attach to this parser's nmea sentence events +}; + + +} + +#endif /* GPSSERVICE_H_ */ diff --git a/Bolt_Dash/src/includes/headers/nmeaparse/NMEACommand.h b/Bolt_Dash/src/includes/headers/nmeaparse/NMEACommand.h new file mode 100644 index 0000000..1719687 --- /dev/null +++ b/Bolt_Dash/src/includes/headers/nmeaparse/NMEACommand.h @@ -0,0 +1,117 @@ +/* + * NMEACommand.h + * + * Created on: Sep 8, 2014 + * Author: Cameron Karlsson + * + * See the license file included with this source. + */ + +#ifndef NMEACOMMAND_H_ +#define NMEACOMMAND_H_ + +#include +#include + +namespace nmea { + + class NMEACommand { + public: + std::string message; + std::string name; + char checksum; + NMEACommand(); + virtual ~NMEACommand(); + virtual std::string toString(); + std::string addChecksum(std::string s); + }; + + + + class NMEACommandSerialConfiguration : public NMEACommand { + public: + /* + // $PSRF100,0,9600,8,1,0*0C + + Table 2-4 Set Serial Port Data Format + Name Example Unit Description + Message ID $PSRF100 PSRF100 protocol header + Protocol 0 0=SiRF binary, 1=NMEA + Baud 9600 1200, 2400, 4800, 9600, 19200, 38400, 57600, and 115200 + DataBits 8 8,71 + + StopBits 1 0,1 1. SiRF protocol is only valid for 8 data bits, 1stop bit, and no parity. + Parity 0 0=None, 1=Odd, 2=Even + Checksum *0C + End of message termination + */ + int32_t baud; //4800, 9600, 19200, 38400 + int32_t databits; //7, 8 Databits + int32_t stopbits; //0, 1 Stopbits + int32_t parity; //0=none, 1=odd, 2=even Parity + + NMEACommandSerialConfiguration(){ + name = "PSRF100"; + baud = 4800; + databits = 8; + stopbits = 1; + parity = 0; + }; + virtual std::string toString(); + }; + + class NMEACommandQueryRate : public NMEACommand { + public: + // data fields that will be stringed. + + + // $PSRF103,00,01,00,01*25 + /* + * Table 2-9 Query/Rate Control Data Format + Name Example Unit Description + Message ID $PSRF103 PSRF103 protocol header + Msg 00 See Table 2-10 + Mode 01 0=SetRate, 1=Query + Rate 00 sec Output—off=0, max=255 + CksumEnable 01 0=Disable Checksum, 1=Enable Checksum + Checksum *25 + End of message termination + */ + /* + * Table 2-10 Messages + Value Description + 0 GGA + 1 GLL + 2 GSA + 3 GSV + 4 RMC + 5 VTG + 6 MSS (If internal beacon is supported) + 7 Not defined + 8 ZDA (if 1PPS output is supported) + 9 Not defined + */ + + enum QueryRateMode { + SETRATE = 0, + QUERY = 1 + }; + + NMEASentence::MessageID messageID; + QueryRateMode mode; + int rate; + int checksumEnable; + NMEACommandQueryRate(){ + name = "PSRF103"; + messageID = NMEASentence::Unknown; + mode = QueryRateMode::SETRATE; + rate = 0; + checksumEnable = 1; + }; + virtual std::string toString(); + }; + + +} + +#endif /* NMEACOMMAND_H_ */ diff --git a/Bolt_Dash/src/includes/headers/nmeaparse/NMEAParser.h b/Bolt_Dash/src/includes/headers/nmeaparse/NMEAParser.h new file mode 100644 index 0000000..d57bb20 --- /dev/null +++ b/Bolt_Dash/src/includes/headers/nmeaparse/NMEAParser.h @@ -0,0 +1,123 @@ +/* + * NMEAParser.h + * + * Created on: Aug 12, 2014 + * Author: Cameron Karlsson + * + * See the license file included with this source. + */ + +#ifndef NMEAPARSER_H_ +#define NMEAPARSER_H_ + + +#include +#include +#include +#include +#include +#include +#include + + + +//read class definition for info +#define NMEA_PARSER_MAX_BUFFER_SIZE 2000 + + + + + +namespace nmea { + +class NMEAParser; + + +class NMEASentence { + friend NMEAParser; +private: + bool isvalid; +public: + std::string text; //whole plaintext of the received command + std::string name; //name of the command + std::vector parameters; //list of parameters from the command + std::string checksum; + bool checksumIsCalculated; + uint8_t parsedChecksum; + uint8_t calculatedChecksum; + + enum MessageID { // These ID's are according to NMEA standard. + Unknown = -1, + GGA = 0, + GLL = 1, + GSA = 2, + GSV = 3, + RMC = 4, + VTG = 5, // notice missing 6,7 + ZDA = 8 + }; +public: + NMEASentence(); + virtual ~NMEASentence(); + + bool checksumOK() const; + bool valid() const; + +}; + + + + +class NMEAParseError : public std::exception { +public: + std::string message; + NMEASentence nmea; + + NMEAParseError(std::string msg); + NMEAParseError(std::string msg, NMEASentence n); + virtual ~NMEAParseError(); + + std::string what(); +}; + + + + +class NMEAParser { +private: + std::unordered_map> eventTable; + std::string buffer; + bool fillingbuffer; + uint32_t maxbuffersize; //limit the max size if no newline ever comes... Prevents huge buffer string internally + + void parseText (NMEASentence& nmea, std::string s); //fills the given NMEA sentence with the results of parsing the string. + + void onInfo (NMEASentence& n, std::string s); + void onWarning (NMEASentence& n, std::string s); + void onError (NMEASentence& n, std::string s); +public: + + NMEAParser(); + virtual ~NMEAParser(); + + bool log; + + Event onSentence; // called every time parser receives any NMEA sentence + void setSentenceHandler(std::string cmdKey, std::function handler); //one handler called for any named sentence where name is the "cmdKey" + std::string getRegisteredSentenceHandlersCSV(); // show a list of message names that currently have handlers. + + // Byte streaming functions + void readByte (uint8_t b); + void readBuffer (uint8_t* b, uint32_t size); + void readLine (std::string line); + + // This function expects the data to be a single line with an actual sentence in it, else it throws an error. + void readSentence (std::string cmd); // called when parser receives a sentence from the byte stream. Can also be called by user to inject sentences. + + static uint8_t calculateChecksum(std::string); // returns checksum of string -- XOR + +}; + +} + +#endif /* NMEAPARSER_H_ */ diff --git a/Bolt_Dash/src/includes/headers/nmeaparse/NumberConversion.h b/Bolt_Dash/src/includes/headers/nmeaparse/NumberConversion.h new file mode 100644 index 0000000..342d200 --- /dev/null +++ b/Bolt_Dash/src/includes/headers/nmeaparse/NumberConversion.h @@ -0,0 +1,49 @@ +/* + * NumberConversion.h + * + * Created on: Aug 14, 2014 + * Author: Cameron Karlsson + * + * See the license file included with this source. + */ + +#ifndef NUMBERCONVERSION_H_ +#define NUMBERCONVERSION_H_ + + +#include +#include +#include +#include + + +namespace nmea { + +class NumberConversionError : public std::exception { +public: + std::string message; + NumberConversionError(std::string msg) + : message(msg) + {}; + + virtual ~NumberConversionError() + {}; + + std::string what(){ + return message; + } +}; + + + + +double parseDouble(std::string s); +int64_t parseInt(std::string s, int radix = 10); + +//void NumberConversion_test(); + +} + + + +#endif /* NUMBERCONVERSION_H_ */ diff --git a/Bolt_Dash/src/includes/headers/nmeaparse/nmea.h b/Bolt_Dash/src/includes/headers/nmeaparse/nmea.h new file mode 100644 index 0000000..811126e --- /dev/null +++ b/Bolt_Dash/src/includes/headers/nmeaparse/nmea.h @@ -0,0 +1,30 @@ +/* +* nmea.h +* +* Created on: March 23, 2014 +* Author: Cameron Karlsson +* +* See the license file included with this source. +*/ + + +// The implementation of a NMEA 0183 parser. +// The implementation of a NMEA 0183 sentence generator. +// The implementation of a GPS data service. + + +#ifndef NMEA_H_ +#define NMEA_H_ + + + +#include +#include +#include + +#include + + + + +#endif //NMEA_H_ diff --git a/Bolt_Dash/src/includes/source/GPSFix.cpp b/Bolt_Dash/src/includes/source/GPSFix.cpp new file mode 100644 index 0000000..20fe275 --- /dev/null +++ b/Bolt_Dash/src/includes/source/GPSFix.cpp @@ -0,0 +1,414 @@ +/* + * GPSFix.cpp + * + * Created on: Jul 23, 2014 + * Author: Cameron Karlsson + * + * See the license file included with this source. + */ + +#include +#include +#include +#include +#include + +using namespace std; +using namespace std::chrono; + +using namespace nmea; + + + +// =========================================================== +// ======================== GPS SATELLITE ==================== +// =========================================================== + +string GPSSatellite::toString(){ + stringstream ss; + + ss << "[PRN: " << setw(3) << setfill(' ') << prn << " " + << " SNR: " << setw(3) << setfill(' ') << snr << " dB " + << " Azimuth: " << setw(3) << setfill(' ') << azimuth << " deg " + << " Elevation: " << setw(3) << setfill(' ') << elevation << " deg " + << "]"; + + return ss.str(); +} +GPSSatellite::operator std::string(){ + return toString(); +} + + + +// ========================================================= +// ======================== GPS ALMANAC ==================== +// ========================================================= + +void GPSAlmanac::clear(){ + lastPage = 0; + totalPages = 0; + processedPages = 0; + visibleSize = 0; + satellites.clear(); +} +void GPSAlmanac::updateSatellite(GPSSatellite sat){ + if (satellites.size() > visibleSize) + { //we missed the new almanac start page, start over. + clear(); + } + + satellites.push_back(sat); +} +double GPSAlmanac::percentComplete(){ + if (totalPages == 0){ + return 0.0; + } + + return ((double)processedPages) / ((double)totalPages) * 100.0; +} +double GPSAlmanac::averageSNR(){ + + double avg = 0; + double relevant = 0; + for (const auto& satellite : satellites){ + if (satellite.snr > 0){ + relevant += 1.0; + } + } + + for (const auto& satellite : satellites){ + if (satellite.snr > 0){ + avg += satellite.snr / relevant; + } + } + + return avg; +} +double GPSAlmanac::minSNR(){ + double min = 9999999; + if (satellites.empty()){ + return 0; + } + int32_t num_over_zero = 0; + for (const auto& satellite : satellites){ + if (satellite.snr > 0){ + num_over_zero++; + if (satellite.snr < min){ + min = satellite.snr; + } + } + } + if (num_over_zero == 0){ + return 0; + } + return min; +} + +double GPSAlmanac::maxSNR(){ + double max = 0; + for (const auto& satellite : satellites){ + if (satellite.snr > 0){ + if (satellite.snr > max){ + max = satellite.snr; + } + } + } + return max; +} + + + + +// =========================================================== +// ======================== GPS TIMESTAMP ==================== +// =========================================================== + + +GPSTimestamp::GPSTimestamp(){ + hour = 0; + min = 0; + sec = 0; + + month = 1; + day = 1; + year = 1970; + + rawTime = 0; + rawDate = 0; +}; + +// indexed from 1! +std::string GPSTimestamp::monthName(uint32_t index){ + if (index < 1 || index > 12){ + std::stringstream ss; + ss << "[month:" << index << "]"; + return ss.str(); + } + + std::string names[] = { + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" + }; + return names[index - 1]; +}; + +// Returns seconds since Jan 1, 1970. Classic Epoch time. +time_t GPSTimestamp::getTime() { + struct tm t = { 0 }; + t.tm_year = year - 1900; // This is year-1900, so 112 = 2012 + t.tm_mon = month; // month from 0:Jan + t.tm_mday = day; + t.tm_hour = hour; + t.tm_min = min; + t.tm_sec = (int)sec; + return mktime(&t); +} + +void GPSTimestamp::setTime(double raw_ts){ + rawTime = raw_ts; + + hour = (int32_t)trunc(raw_ts / 10000.0); + min = (int32_t)trunc((raw_ts - hour * 10000) / 100.0); + sec = raw_ts - min * 100 - hour * 10000; +} + +//ddmmyy +void GPSTimestamp::setDate(int32_t raw_date){ + rawDate = raw_date; + // If uninitialized, use posix time. + if(rawDate == 0) { + month = 1; + day = 1; + year = 1970; + } + else { + day = (int32_t)trunc(raw_date / 10000.0); + month = (int32_t)trunc((raw_date - 10000 * day) / 100.0); + year = raw_date - 10000 * day - 100 * month + 2000; + } +} + +std::string GPSTimestamp::toString(){ + std::stringstream ss; + ss << hour << "h " << min << "m " << sec << "s" << " " << monthName(month) << " " << day << " " << year; + return ss.str(); +}; + + + + + + + +// ===================================================== +// ======================== GPS FIX ==================== +// ===================================================== + +GPSFix::GPSFix() { + + quality = 0; // Searching... + status = 'V'; // Void + type = 1; // 1=none, 2=2d, 3=3d + + haslock = 0; + + dilution = 0; + horizontalDilution = 0; // Horizontal - Best is 1, >20 is terrible, so 0 means uninitialized + verticalDilution = 0; + latitude = 0; + longitude = 0; + speed = 0; + travelAngle = 0; + altitude = 0; + trackingSatellites = 0; + visibleSatellites = 0; + + +} + +GPSFix::~GPSFix() { + // TODO Auto-generated destructor stub +} + +// Returns the duration since the Host has received information +seconds GPSFix::timeSinceLastUpdate(){ + time_t now = time(NULL); + struct tm stamp = { 0 }; + + stamp.tm_hour = timestamp.hour; + stamp.tm_min = timestamp.min; + stamp.tm_sec = (int)timestamp.sec; + stamp.tm_year = timestamp.year-1900; + stamp.tm_mon = timestamp.month-1; + stamp.tm_mday = timestamp.day; + + time_t then = mktime(&stamp); + uint64_t secs = (uint64_t)difftime(now,then); + return seconds((uint64_t)secs); +} + +bool GPSFix::hasEstimate(){ + return (latitude != 0 && longitude != 0) || (quality == 6); +} + +bool GPSFix::setlock(bool locked){ + if (haslock != locked){ + haslock = locked; + return true; + } + return false; +} + +bool GPSFix::locked(){ + return haslock; +} + +// Returns meters +double GPSFix::horizontalAccuracy(){ + // horizontal 2drms 95% = 4.0 -- from GPS CHIP datasheets + return 4.0 * horizontalDilution; +} + +// Returns meters +double GPSFix::verticalAccuracy(){ + // Vertical 2drms 95% = 6.0 -- from GPS CHIP datasheets + return 6.0 * verticalDilution; +} + +// Takes a degree travel heading (0-360') and returns the name +std::string GPSFix::travelAngleToCompassDirection(double deg, bool abbrev){ + + //normalize, just in case + int32_t c = (int32_t)round(deg / 360.0 * 8.0); + int32_t r = c % 8; + if (r < 0){ + r = 8 + r; + } + + if (abbrev){ + std::string dirs[] = { + "N", + "NE", + "E", + "SE", + "S", + "SW", + "W", + "NW", + "N" + }; + return dirs[r]; + } + else { + std::string dirs[] = { + "North", + "North East", + "East", + "South East", + "South", + "South West", + "West", + "North West", + "North" + }; + return dirs[r]; + } + +}; + + +std::string fixStatusToString(char status){ + switch (status){ + case 'A': + return "Active"; + case 'V': + return "Void"; + default: + return "Unknown"; + } +} +std::string fixTypeToString(uint8_t type){ + switch (type){ + case 1: + return "None"; + case 2: + return "2D"; + case 3: + return "3D"; + default: + return "Unknown"; + } +} +std::string fixQualityToString(uint8_t quality){ + switch (quality){ + case 0: + return "Invalid"; + case 1: + return "Standard"; + case 2: + return "DGPS"; + case 3: + return "PPS fix"; + case 4: + return "Real Time Kinetic"; + case 5: + return "Real Time Kinetic (float)"; + case 6: + return "Estimate"; + default: + return "Unknown"; + } +} + +std::string GPSFix::toString(){ + stringstream ss; + ios_base::fmtflags oldflags = ss.flags(); + + ss << "========================== GPS FIX ================================" << endl + << " Status: \t\t" << ((haslock) ? "LOCK!" : "SEARCHING...") << endl + << " Satellites: \t\t" << trackingSatellites << " (tracking) of " << visibleSatellites << " (visible)" << endl + << " < Fix Details >" << endl + << " Age: " << timeSinceLastUpdate().count() << " s" << endl + << " Timestamp: " << timestamp.toString() << " UTC \n\t\t\t(raw: " << timestamp.rawTime << " time, " << timestamp.rawDate << " date)" << endl + << " Raw Status: " << status << " (" << fixStatusToString(status) << ")" << endl + << " Type: " << (int)type << " (" << fixTypeToString(type) << ")" << endl + << " Quality: " << (int)quality << " (" << fixQualityToString(quality) << ")" << endl + << " Lat/Lon (N,E): " << setprecision(6) << fixed << latitude << "' N, " << longitude << "' E" << endl; + + ss.flags(oldflags); //reset + + ss << " DOP (P,H,V): " << dilution << ", " << horizontalDilution << ", " << verticalDilution << endl + << " Accuracy(H,V): " << horizontalAccuracy() << " m, " << verticalAccuracy() << " m" << endl; + + ss << " Altitude: " << altitude << " m" << endl + << " Speed: " << speed << " km/h" << endl + << " Travel Dir: " << travelAngle << " deg [" << travelAngleToCompassDirection(travelAngle) << "]" << endl + << " SNR: avg: " << almanac.averageSNR() << " dB [min: " << almanac.minSNR() << " dB, max:" << almanac.maxSNR() << " dB]" << endl; + + ss << " < Almanac (" << almanac.percentComplete() << "%) >" << endl; + if (almanac.satellites.empty()){ + ss << " > No satellite info in almanac." << endl; + } + for (size_t i = 0; i < almanac.satellites.size(); i++){ + ss << " [" << setw(2) << setfill(' ') << (i + 1) << "] " << almanac.satellites[i].toString() << endl; + } + + return ss.str(); +} +GPSFix::operator std::string(){ + return toString(); +} + + + diff --git a/Bolt_Dash/src/includes/source/GPSService.cpp b/Bolt_Dash/src/includes/source/GPSService.cpp new file mode 100644 index 0000000..65bf79f --- /dev/null +++ b/Bolt_Dash/src/includes/source/GPSService.cpp @@ -0,0 +1,511 @@ +/* + * GPSService.cpp + * + * Created on: Aug 14, 2014 + * Author: Cameron Karlsson + * + * See the license file included with this source. + */ + + +#include +#include + +#include +#include + +using namespace std; +using namespace std::chrono; + +using namespace nmea; + + +// ------ Some helpers ---------- +// Takes the NMEA lat/long format (dddmm.mmmm, [N/S,E/W]) and converts to degrees N,E only +double convertLatLongToDeg(string llstr, string dir){ + + double pd = parseDouble(llstr); + double deg = trunc(pd / 100); //get ddd from dddmm.mmmm + double mins = pd - deg * 100; + + deg = deg + mins / 60.0; + + char hdg = 'x'; + if (!dir.empty()){ + hdg = dir[0]; + } + + //everything should be N/E, so flip S,W + if (hdg == 'S' || hdg == 'W'){ + deg *= -1.0; + } + + return deg; +} +double convertKnotsToKilometersPerHour(double knots){ + return knots * 1.852; +} + + + +// ------------- GPSSERVICE CLASS ------------- + + + + +GPSService::GPSService(NMEAParser& parser) { + attachToParser(parser); // attach to parser in the GPS object +} + +GPSService::~GPSService() { + // TODO Auto-generated destructor stub +} + +void GPSService::attachToParser(NMEAParser& _parser){ + + // http://www.gpsinformation.org/dale/nmea.htm + /* used sentences... + $GPGGA - time,position,fix data + $GPGSA - gps receiver operating mode, satellites used in position and DOP values + $GPGSV - number of gps satellites in view, satellite ID, elevation,azimuth, and SNR + $GPRMC - time,date, position,course, and speed data + $GPVTG - course and speed information relative to the ground + $GPZDA - 1pps timing message + $PSRF150 - gps module "ok to send" + */ + _parser.setSentenceHandler("PSRF150", [this](const NMEASentence& nmea){ + this->read_PSRF150(nmea); + }); + _parser.setSentenceHandler("GPGGA", [this](const NMEASentence& nmea){ + this->read_GPGGA(nmea); + }); + _parser.setSentenceHandler("GPGSA", [this](const NMEASentence& nmea){ + this->read_GPGSA(nmea); + }); + _parser.setSentenceHandler("GPGSV", [this](const NMEASentence& nmea){ + this->read_GPGSV(nmea); + }); + _parser.setSentenceHandler("GPRMC", [this](const NMEASentence& nmea){ + this->read_GPRMC(nmea); + }); + _parser.setSentenceHandler("GPVTG", [this](const NMEASentence& nmea){ + this->read_GPVTG(nmea); + }); + +} + + + + +void GPSService::read_PSRF150(const NMEASentence& nmea){ + // nothing right now... + // Called with checksum 3E (valid) for GPS turning ON + // Called with checksum 3F (invalid) for GPS turning OFF +} + +void GPSService::read_GPGGA(const NMEASentence& nmea){ + /* -- EXAMPLE -- + $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47 + + $GPGGA,205630.945,3346.1070,N,08423.6687,W,0,03,,30.8,M,-30.8,M,,0000*73 // ATLANTA!!!! + + Where: + GGA Global Positioning System Fix Data + index: + [0] 123519 Fix taken at 12:35:19 UTC + [1-2] 4807.038,N Latitude 48 deg 07.038' N + [3-4] 1131.000,E Longitude 11 deg 31.000' E + [5] 1 Fix quality: 0 = invalid + 1 = GPS fix (SPS) + 2 = DGPS fix + 3 = PPS fix + 4 = Real Time Kinematic + 5 = Float RTK + 6 = estimated (dead reckoning) (2.3 feature) + 7 = Manual input mode + 8 = Simulation mode + [6] 08 Number of satellites being tracked + [7] 0.9 Horizontal dilution of position + [8-9] 545.4,M Altitude, Meters, above mean sea level + [10-11] 46.9,M Height of geoid (mean sea level) above WGS84 + ellipsoid + [12] (empty field) time in seconds since last DGPS update + [13] (empty field) DGPS station ID number + [13] *47 the checksum data, always begins with * + */ + try + { + if (!nmea.checksumOK()){ + throw NMEAParseError("Checksum is invalid!"); + } + + if (nmea.parameters.size() < 14){ + throw NMEAParseError("GPS data is missing parameters."); + } + + + // TIMESTAMP + this->fix.timestamp.setTime(parseDouble(nmea.parameters[0])); + + string sll; + string dir; + // LAT + sll = nmea.parameters[1]; + dir = nmea.parameters[2]; + if (!sll.empty()){ + this->fix.latitude = convertLatLongToDeg(sll, dir); + } + + // LONG + sll = nmea.parameters[3]; + dir = nmea.parameters[4]; + if (!sll.empty()){ + this->fix.longitude = convertLatLongToDeg(sll, dir); + } + + + // FIX QUALITY + bool lockupdate = false; + this->fix.quality = (uint8_t)parseInt(nmea.parameters[5]); + if (this->fix.quality == 0){ + lockupdate = this->fix.setlock(false); + } + else if (this->fix.quality == 1){ + lockupdate = this->fix.setlock(true); + } + else {} + + + // TRACKING SATELLITES + this->fix.trackingSatellites = (int32_t)parseInt(nmea.parameters[6]); + if (this->fix.visibleSatellites < this->fix.trackingSatellites){ + this->fix.visibleSatellites = this->fix.trackingSatellites; // the visible count is in another sentence. + } + + // ALTITUDE + if (!nmea.parameters[8].empty()){ + this->fix.altitude = parseDouble(nmea.parameters[8]); + } + else { + // leave old value + } + + //calling handlers + if (lockupdate){ + this->onLockStateChanged(this->fix.haslock); + } + this->onUpdate(); + } + catch (NumberConversionError& ex) + { + NMEAParseError pe("GPS Number Bad Format [$GPGGA] :: " + ex.message, nmea); + throw pe; + } + catch (NMEAParseError& ex) + { + NMEAParseError pe("GPS Data Bad Format [$GPGGA] :: " + ex.message, nmea); + throw pe; + } +} + +void GPSService::read_GPGSA(const NMEASentence& nmea){ + /* -- EXAMPLE -- + $GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39 + + $GPGSA,A,3,18,21,22,14,27,19,,,,,,,4.4,2.7,3.4*32 + + Where: + GSA Satellite status + [0] A Auto selection of 2D or 3D fix (M = manual) + [1] 3 3D fix - values include: 1 = no fix + 2 = 2D fix + 3 = 3D fix + [2-13] 04,05... PRNs of satellites used for fix (space for 12) + [14] 2.5 PDOP (dilution of precision) + [15] 1.3 Horizontal dilution of precision (HDOP) + [16] 2.1 Vertical dilution of precision (VDOP) + [16] *39 the checksum data, always begins with * + */ + + + try + { + if (!nmea.checksumOK()){ + throw NMEAParseError("Checksum is invalid!"); + } + + if (nmea.parameters.size() < 17){ + throw NMEAParseError("GPS data is missing parameters."); + } + + + // FIX TYPE + bool lockupdate = false; + uint64_t fixtype = parseInt(nmea.parameters[1]); + this->fix.type = (int8_t)fixtype; + if (fixtype == 1){ + lockupdate = this->fix.setlock(false); + } + else if (fixtype == 3) { + lockupdate = this->fix.setlock(true); + } + else {} + + + // DILUTION OF PRECISION -- PDOP + double dop = parseDouble(nmea.parameters[14]); + this->fix.dilution = dop; + + // HORIZONTAL DILUTION OF PRECISION -- HDOP + double hdop = parseDouble(nmea.parameters[15]); + this->fix.horizontalDilution = hdop; + + // VERTICAL DILUTION OF PRECISION -- VDOP + double vdop = parseDouble(nmea.parameters[16]); + this->fix.verticalDilution = vdop; + + //calling handlers + if (lockupdate){ + this->onLockStateChanged(this->fix.haslock); + } + this->onUpdate(); + } + catch (NumberConversionError& ex) + { + NMEAParseError pe("GPS Number Bad Format [$GPGSA] :: " + ex.message, nmea); + throw pe; + } + catch (NMEAParseError& ex) + { + NMEAParseError pe("GPS Data Bad Format [$GPGSA] :: " + ex.message, nmea); + throw pe; + } +} + +void GPSService::read_GPGSV(const NMEASentence& nmea){ + /* -- EXAMPLE -- + $GPGSV,2,1,08,01,40,083,46,02,17,308,41,12,07,344,39,14,22,228,45*75 + + + $GPGSV,3,1,12,01,00,000,,02,00,000,,03,00,000,,04,00,000,*7C + $GPGSV,3,2,12,05,00,000,,06,00,000,,07,00,000,,08,00,000,*77 + $GPGSV,3,3,12,09,00,000,,10,00,000,,11,00,000,,12,00,000,*71 + + Where: + GSV Satellites in view + [0] 2 Number of sentences for full data + [1] 1 sentence 1 of 2 + [2] 08 Number of satellites in view + + [3] 01 Satellite PRN number + [4] 40 Elevation, degrees + [5] 083 Azimuth, degrees + [6] 46 SNR - higher is better + [...] for up to 4 satellites per sentence + [17] *75 the checksum data, always begins with * + */ + + try + { + if (!nmea.checksumOK()){ + throw NMEAParseError("Checksum is invalid!"); + } + + // can't do this check because the length varies depending on satallites... + //if(nmea.parameters.size() < 18){ + // throw NMEAParseError("GPS data is missing parameters."); + //} + + // VISIBLE SATELLITES + this->fix.visibleSatellites = (int32_t)parseInt(nmea.parameters[2]); + if (this->fix.trackingSatellites == 0){ + this->fix.visibleSatellites = 0; // if no satellites are tracking, then none are visible! + } // Also NMEA defaults to 12 visible when chip powers on. Obviously not right. + + uint32_t totalPages = (uint32_t)parseInt(nmea.parameters[0]); + uint32_t currentPage = (uint32_t)parseInt(nmea.parameters[1]); + + + //if this is the first page, then reset the almanac + if (currentPage == 1){ + this->fix.almanac.clear(); + //cout << "CLEARING ALMANAC" << endl; + } + + this->fix.almanac.lastPage = currentPage; + this->fix.almanac.totalPages = totalPages; + this->fix.almanac.visibleSize = this->fix.visibleSatellites; + + int entriesInPage = (nmea.parameters.size() - 3) >> 2; //first 3 are not satellite info + //- entries come in 4-ples, and truncate, so used shift + GPSSatellite sat; + for (int i = 0; i < entriesInPage; i++){ + int prop = 3 + i * 4; + + // PRN, ELEVATION, AZIMUTH, SNR + sat.prn = (uint32_t)parseInt(nmea.parameters[prop]); + sat.elevation = (uint32_t)parseInt(nmea.parameters[prop + 1]); + sat.azimuth = (uint32_t)parseInt(nmea.parameters[prop + 2]); + sat.snr = (uint32_t)parseInt(nmea.parameters[prop + 3]); + + //cout << "ADDING SATELLITE ::" << sat.toString() << endl; + this->fix.almanac.updateSatellite(sat); + } + + this->fix.almanac.processedPages++; + + // + if (this->fix.visibleSatellites == 0){ + this->fix.almanac.clear(); + } + + + //cout << "ALMANAC FINISHED page " << this->fix.almanac.processedPages << " of " << this->fix.almanac.totalPages << endl; + this->onUpdate(); + + } + catch (NumberConversionError& ex) + { + NMEAParseError pe("GPS Number Bad Format [$GPGSV] :: " + ex.message, nmea); + throw pe; + } + catch (NMEAParseError& ex) + { + NMEAParseError pe("GPS Data Bad Format [$GPGSV] :: " + ex.message, nmea); + throw pe; + } +} + +void GPSService::read_GPRMC(const NMEASentence& nmea){ + /* -- EXAMPLE --- + $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A + $GPRMC,235957.025,V,,,,,,,070810,,,N*4B + $GPRMC,061425.000,A,3346.2243,N,08423.4706,W,0.45,18.77,060914,,,A*47 + + Where: + RMC Recommended Minimum sentence C + [0] 123519 Fix taken at 12:35:19 UTC + [1] A Status A=active or V=Void. + [2-3] 4807.038,N Latitude 48 deg 07.038' N + [4-5] 01131.000,E Longitude 11 deg 31.000' E + [6] 022.4 Speed over the ground in knots + [7] 084.4 Track angle in degrees True + [8] 230394 Date - 23rd of March 1994 + [9-10] 003.1,W Magnetic Variation + [10] *6A The checksum data, always begins with * + // NMEA 2.3 includes another field after + */ + + try + { + if (!nmea.checksumOK()){ + throw NMEAParseError("Checksum is invalid!"); + } + + if (nmea.parameters.size() < 11){ + throw NMEAParseError("GPS data is missing parameters."); + } + + // TIMESTAMP + this->fix.timestamp.setTime(parseDouble(nmea.parameters[0])); + + string sll; + string dir; + // LAT + sll = nmea.parameters[2]; + dir = nmea.parameters[3]; + if (!sll.empty()){ + this->fix.latitude = convertLatLongToDeg(sll, dir); + } + + // LONG + sll = nmea.parameters[4]; + dir = nmea.parameters[5]; + if (!sll.empty()){ + this->fix.longitude = convertLatLongToDeg(sll, dir); + } + + + // ACTIVE + bool lockupdate = false; + char status = 'V'; + if (!nmea.parameters[1].empty()){ + status = nmea.parameters[1][0]; + } + this->fix.status = status; + if (status == 'V'){ + lockupdate = this->fix.setlock(false); + } + else if (status == 'A') { + lockupdate = this->fix.setlock(true); + } + else { + lockupdate = this->fix.setlock(false); //not A or V, so must be wrong... no lock + } + + + this->fix.speed = convertKnotsToKilometersPerHour(parseDouble(nmea.parameters[6])); // received as knots, convert to km/h + this->fix.travelAngle = parseDouble(nmea.parameters[7]); + this->fix.timestamp.setDate((int32_t)parseInt(nmea.parameters[8])); + + + //calling handlers + if (lockupdate){ + this->onLockStateChanged(this->fix.haslock); + } + this->onUpdate(); + } + catch (NumberConversionError& ex) + { + NMEAParseError pe("GPS Number Bad Format [$GPRMC] :: " + ex.message, nmea); + throw pe; + } + catch (NMEAParseError& ex) + { + NMEAParseError pe("GPS Data Bad Format [$GPRMC] :: " + ex.message, nmea); + throw pe; + } +} + +void GPSService::read_GPVTG(const NMEASentence& nmea){ + /* + $GPVTG,054.7,T,034.4,M,005.5,N,010.2,K*48 + + where: + VTG Track made good and ground speed + [0-1] 054.7,T True track made good (degrees) + [2-3] 034.4,M Magnetic track made good + [4-5] 005.5,N Ground speed, knots + [6-7] 010.2,K Ground speed, Kilometers per hour + [7] *48 Checksum + */ + + try + { + if (!nmea.checksumOK()){ + throw NMEAParseError("Checksum is invalid!"); + } + + if (nmea.parameters.size() < 8){ + throw NMEAParseError("GPS data is missing parameters."); + } + + // SPEED + // if empty, is converted to 0 + this->fix.speed = parseDouble(nmea.parameters[6]); //km/h + + + this->onUpdate(); + } + catch (NumberConversionError& ex) + { + NMEAParseError pe("GPS Number Bad Format [$GPVTG] :: " + ex.message, nmea); + throw pe; + } + catch (NMEAParseError& ex) + { + NMEAParseError pe("GPS Data Bad Format [$GPVTG] :: " + ex.message, nmea); + throw pe; + } +} + diff --git a/Bolt_Dash/src/includes/source/NMEACommand.cpp b/Bolt_Dash/src/includes/source/NMEACommand.cpp new file mode 100644 index 0000000..0319f99 --- /dev/null +++ b/Bolt_Dash/src/includes/source/NMEACommand.cpp @@ -0,0 +1,110 @@ +/* + * NMEACommand.cpp + * + * Created on: Sep 8, 2014 + * Author: Cameron Karlsson + * + * See the license file included with this source. + */ + +#include +#include +#include + +using namespace std; +using namespace nmea; + + +NMEACommand::NMEACommand(){}; + +NMEACommand::~NMEACommand(){}; + +string NMEACommand::toString(){ + return addChecksum(message); +} + +string NMEACommand::addChecksum(std::string s){ + stringstream zz; + zz << name << "," << s; + checksum = NMEAParser::calculateChecksum(zz.str()); + + stringstream ss; + ios_base::fmtflags oldflags = ss.flags(); + ss << "$" << zz.str() << "*" << hex << uppercase << internal << setfill('0') << setw(2) << (int)checksum << "\r\n"; + ss.flags(oldflags); //reset + + return ss.str(); +}; + + + + /* + // $PSRF100,0,9600,8,1,0*0C + + Table 2-4 Set Serial Port Data Format + Name Example Unit Description + Message ID $PSRF100 PSRF100 protocol header + Protocol 0 0=SiRF binary, 1=NMEA + Baud 9600 1200, 2400, 4800, 9600, 19200, 38400, 57600, and 115200 + DataBits 8 8,71 + + StopBits 1 0,1 1. SiRF protocol is only valid for 8 data bits, 1stop bit, and no parity. + Parity 0 0=None, 1=Odd, 2=Even + Checksum *0C + End of message termination + */ +std::string NMEACommandSerialConfiguration::toString(){ + stringstream ss; + + ss << "1," << baud << "," << databits << "," << stopbits << "," << parity; + message = ss.str(); + + return NMEACommand::addChecksum(message); +} + + + + // $PSRF103,00,01,00,01*25 + /* + * Table 2-9 Query/Rate Control Data Format + Name Example Unit Description + Message ID $PSRF103 PSRF103 protocol header + Msg 00 See Table 2-10 + Mode 01 0=SetRate, 1=Query + Rate 00 sec Output—off=0, max=255 + CksumEnable 01 0=Disable Checksum, 1=Enable Checksum + Checksum *25 + End of message termination + */ + /* + * Table 2-10 Messages + Value Description + 0 GGA + 1 GLL + 2 GSA + 3 GSV + 4 RMC + 5 VTG + 6 MSS (If internal beacon is supported) + 7 Not defined + 8 ZDA (if 1PPS output is supported) + 9 Not defined + */ +// Data Members: +// int messageID; +// int mode; +// int rate; +// int checksumEnable; +// Creates a valid NMEA $PSRF103 command sentence. +std::string NMEACommandQueryRate::toString(){ + stringstream ss; + + ss << setfill('0') << setw(2) << messageID << "," + << setfill('0') << setw(2) << mode << "," + << setfill('0') << setw(2) << rate << "," + << setfill('0') << setw(2) << checksumEnable; + message = ss.str(); + + return NMEACommand::addChecksum(message); +} + diff --git a/Bolt_Dash/src/includes/source/NMEAParser.cpp b/Bolt_Dash/src/includes/source/NMEAParser.cpp new file mode 100644 index 0000000..d0a52ed --- /dev/null +++ b/Bolt_Dash/src/includes/source/NMEAParser.cpp @@ -0,0 +1,492 @@ +/* + * NMEAParser.cpp + * + * Created on: Aug 12, 2014 + * Author: Cameron Karlsson + * + * See the license file included with this source. + */ + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace nmea; + + + +// --------- NMEA PARSE ERROR-------------- + +NMEAParseError::NMEAParseError(std::string msg) + : message(msg) +{} +NMEAParseError::NMEAParseError(std::string msg, NMEASentence n) + : message(msg), nmea(n) +{} + +NMEAParseError::~NMEAParseError() +{} + +std::string NMEAParseError::what(){ + return message; +} + + + + +// --------- NMEA SENTENCE -------------- + +NMEASentence::NMEASentence() +: isvalid(false) +, checksumIsCalculated(false) +, calculatedChecksum(0) +, parsedChecksum(0) +{ } + +NMEASentence::~NMEASentence() +{ } + +bool NMEASentence::valid() const { + return isvalid; +} + +bool NMEASentence::checksumOK() const { + return (checksumIsCalculated) + && + (parsedChecksum == calculatedChecksum); +} + + + +// true if the text contains a non-alpha numeric value +bool hasNonAlphaNum(string txt){ + for (const char i : txt){ + if ( !isalnum(i) ){ + return true; + } + } + return false; +} + +// true if alphanumeric or '-' +bool validParamChars(string txt){ + for (const char i : txt){ + if (!isalnum(i)){ + if (i != '-' && i != '.'){ + return false; + } + } + } + return true; +} + +// remove all whitespace +void squish(string& str){ + + char chars[] = {'\t',' '}; + for (const char i : chars) + { + // needs include + str.erase(std::remove(str.begin(), str.end(), i), str.end()); + } +} + +// remove side whitespace +void trim(string& str){ + stringstream trimmer; + trimmer << str; + str.clear(); + trimmer >> str; +} + + +// --------- NMEA PARSER -------------- + + + +NMEAParser::NMEAParser() +: log(false) +, maxbuffersize(NMEA_PARSER_MAX_BUFFER_SIZE) +, fillingbuffer(false) +{ } + +NMEAParser::~NMEAParser() +{ } + + +void NMEAParser::setSentenceHandler(std::string cmdKey, std::function handler){ + eventTable.erase(cmdKey); + eventTable.insert({ cmdKey, handler }); +} +string NMEAParser::getRegisteredSentenceHandlersCSV() +{ + if(eventTable.empty()){ + return ""; + } + + ostringstream ss; + for(const auto& table : eventTable){ + ss << table.first; + + if( ! table.second ){ + ss << "(not callable)"; + } + ss << ","; + } + string s = ss.str(); + if( ! s.empty() ){ + s.resize(s.size()-1); // chop off comma + } + return s; +} + +void NMEAParser::readByte(uint8_t b){ + uint8_t startbyte = '$'; + + if (fillingbuffer){ + if (b == '\n'){ + buffer.push_back(b); + try { + readSentence(buffer); + buffer.clear(); + fillingbuffer = false; + } + catch (exception&){ + // If anything happens, let it pass through, but reset the buffer first. + buffer.clear(); + fillingbuffer = false; + throw; + } + } + else{ + if (buffer.size() < maxbuffersize){ + buffer.push_back(b); + } + else { + buffer.clear(); //clear the host buffer so it won't overflow. + fillingbuffer = false; + } + } + } + else { + if (b == startbyte){ // only start filling when we see the start byte. + fillingbuffer = true; + buffer.push_back(b); + } + } +} + +void NMEAParser::readBuffer(uint8_t* b, uint32_t size){ + for (uint32_t i = 0; i < size; ++i){ + readByte(b[i]); + } +} + +void NMEAParser::readLine(string cmd){ + cmd += "\r\n"; + for (const char i : cmd){ + readByte(i); + } +} + +// Loggers +void NMEAParser::onInfo(NMEASentence& nmea, string txt){ + if (log){ + cout << "[Info] " << txt << endl; + } +} +void NMEAParser::onWarning(NMEASentence& nmea, string txt){ + if (log){ + cout << "[Warning] " << txt << endl; + } +} +void NMEAParser::onError(NMEASentence& nmea, string txt){ + throw NMEAParseError("[ERROR] " + txt); +} + +// takes a complete NMEA string and gets the data bits from it, +// calls the corresponding handler in eventTable, based on the 5 letter sentence code +void NMEAParser::readSentence(std::string cmd){ + + NMEASentence nmea; + + onInfo(nmea, "Processing NEW string..."); + + if (cmd.empty()){ + onWarning(nmea, "Blank string -- Skipped processing."); + return; + } + + // If there is a newline at the end (we are coming from the byte reader + if ( *(cmd.end()-1) == '\n'){ + if (*(cmd.end() - 2) == '\r'){ // if there is a \r before the newline, remove it. + cmd = cmd.substr(0, cmd.size() - 2); + } + else + { + onWarning(nmea, "Malformed newline, missing carriage return (\\r) "); + cmd = cmd.substr(0, cmd.size()-1); + } + } + + ios_base::fmtflags oldflags = cout.flags(); + + // Remove all whitespace characters. + size_t beginsize = cmd.size(); + squish(cmd); + if (cmd.size() != beginsize){ + stringstream ss; + ss << "New NMEA string was full of " << (beginsize - cmd.size()) << " whitespaces!"; + onWarning(nmea, ss.str()); + } + + + onInfo(nmea, string("NMEA string: (\"") + cmd + "\")"); + + + // Seperates the data now that everything is formatted + try{ + parseText(nmea, cmd); + } + catch (NMEAParseError&){ + throw; + } + catch (std::exception& e){ + string s = " >> NMEA Parser Internal Error: Indexing error?... "; + throw std::runtime_error(s + e.what()); + } + cout.flags(oldflags); //reset + + // Handle/Throw parse errors + if (!nmea.valid()){ + + size_t linewidth = 35; + stringstream ss; + if (nmea.text.size() > linewidth){ + ss << "Invalid text. (\"" << nmea.text.substr(0, linewidth) << "...\")"; + } + else{ + ss << "Invalid text. (\"" << nmea.text << "\")"; + } + + onError(nmea, ss.str()); + return; + } + + + // Call the "any sentence" event handler, even if invalid checksum, for possible logging elsewhere. + onInfo(nmea, "Calling generic onSentence()."); + onSentence(nmea); + + + // Call event handlers based on map entries + function handler = eventTable[nmea.name]; + if (handler){ + onInfo(nmea, string("Calling specific handler for sentence named \"") + nmea.name + "\""); + handler(nmea); + } + else + { + onWarning(nmea, string("Null event handler for type (name: \"") + nmea.name + "\")"); + } + + + + + + cout.flags(oldflags); //reset + +} + +// takes the string *between* the '$' and '*' in nmea sentence, +// then calculates a rolling XOR on the bytes +uint8_t NMEAParser::calculateChecksum(string s){ + uint8_t checksum = 0; + for (const char i : s){ + checksum = checksum ^ i; + } + + // will display the calculated checksum in hex + //if(log) + //{ + // ios_base::fmtflags oldflags = cout.flags(); + // cout << "NMEA parser Info: calculated CHECKSUM for \"" << s << "\": 0x" << std::hex << (int)checksum << endl; + // cout.flags(oldflags); //reset + //} + return checksum; +} + + +void NMEAParser::parseText(NMEASentence& nmea, string txt){ + + if (txt.empty()){ + nmea.isvalid = false; + return; + } + + nmea.isvalid = false; // assume it's invalid first + nmea.text = txt; // save the received text of the sentence + + // Looking for index of last '$' + size_t startbyte = 0; + size_t dollar = txt.find_last_of('$'); + if (dollar == string::npos){ + // No dollar sign... INVALID! + return; + } + else + { + startbyte = dollar; + } + + + // Get rid of data up to last'$' + txt = txt.substr(startbyte + 1); + + + // Look for checksum + size_t checkstri = txt.find_last_of('*'); + bool haschecksum = checkstri != string::npos; + if (haschecksum){ + // A checksum was passed in the message, so calculate what we expect to see + nmea.calculatedChecksum = calculateChecksum(txt.substr(0, checkstri)); + } + else + { + // No checksum is only a warning because some devices allow sending data with no checksum. + onWarning(nmea, "No checksum information provided. Could not find '*'."); + } + + // Handle comma edge cases + size_t comma = txt.find(','); + if (comma == string::npos){ //comma not found, but there is a name... + if (!txt.empty()) + { // the received data must just be the name + if ( hasNonAlphaNum(txt) ){ + nmea.isvalid = false; + return; + } + nmea.name = txt; + nmea.isvalid = true; + return; + } + else + { //it is a '$' with no information + nmea.isvalid = false; + return; + } + } + + //"$," case - no name + if (comma == 0){ + nmea.isvalid = false; + return; + } + + + //name should not include first comma + nmea.name = txt.substr(0, comma); + if ( hasNonAlphaNum(nmea.name) ){ + nmea.isvalid = false; + return; + } + + + //comma is the last character/only comma + if (comma + 1 == txt.size()){ + nmea.parameters.push_back(""); + nmea.isvalid = true; + return; + } + + + //move to data after first comma + txt = txt.substr(comma + 1, txt.size() - (comma + 1)); + + //parse parameters according to csv + istringstream f(txt); + string s; + while (getline(f, s, ',')) { + //cout << s << endl; + nmea.parameters.push_back(s); + } + + + //above line parsing does not add a blank parameter if there is a comma at the end... + // so do it here. + if (*(txt.end() - 1) == ','){ + + // supposed to have checksum but there is a comma at the end... invalid + if (haschecksum){ + nmea.isvalid = false; + return; + } + + //cout << "NMEA parser Warning: extra comma at end of sentence, but no information...?" << endl; // it's actually standard, if checksum is disabled + nmea.parameters.push_back(""); + + stringstream sz; + sz << "Found " << nmea.parameters.size() << " parameters."; + onInfo(nmea, sz.str()); + + } + else + { + stringstream sz; + sz << "Found " << nmea.parameters.size() << " parameters."; + onInfo(nmea, sz.str()); + + //possible checksum at end... + size_t endi = nmea.parameters.size() - 1; + size_t checki = nmea.parameters[endi].find_last_of('*'); + if (checki != string::npos){ + string last = nmea.parameters[endi]; + nmea.parameters[endi] = last.substr(0, checki); + if (checki == last.size() - 1){ + onError(nmea, "Checksum '*' character at end, but no data."); + } + else{ + nmea.checksum = last.substr(checki + 1, last.size() - checki); //extract checksum without '*' + + onInfo(nmea, string("Found checksum. (\"*") + nmea.checksum + "\")"); + + try + { + nmea.parsedChecksum = (uint8_t)parseInt(nmea.checksum, 16); + nmea.checksumIsCalculated = true; + } + catch( NumberConversionError& ) + { + onError(nmea, string("parseInt() error. Parsed checksum string was not readable as hex. (\"") + nmea.checksum + "\")"); + } + + onInfo(nmea, string("Checksum ok? ") + (nmea.checksumOK() ? "YES" : "NO") + "!"); + + + } + } + } + + + for (size_t i = 0; i < nmea.parameters.size(); i++){ + if (!validParamChars(nmea.parameters[i])){ + nmea.isvalid = false; + stringstream ss; + ss << "Invalid character (non-alpha-num) in parameter " << i << " (from 0): \"" << nmea.parameters[i] << "\""; + onError(nmea, ss.str() ); + break; + } + } + + + nmea.isvalid = true; + + return; + +} + + diff --git a/Bolt_Dash/src/includes/source/NumberConversion.cpp b/Bolt_Dash/src/includes/source/NumberConversion.cpp new file mode 100644 index 0000000..9638b88 --- /dev/null +++ b/Bolt_Dash/src/includes/source/NumberConversion.cpp @@ -0,0 +1,147 @@ +/* + * NumberConversion.cpp + * + * Created on: Sep 2, 2014 + * Author: Cameron Karlsson + * + * See the license file included with this source. + */ + +#include +#include + +using namespace std; + +namespace nmea { +// Note: both parseDouble and parseInt return 0 with "" input. + + double parseDouble(std::string s){ + + char* p; + double d = ::strtod(s.c_str(), &p); + if (*p != 0){ + std::stringstream ss; + ss << "NumberConversionError: parseDouble() error in argument \"" << s << "\", '" + << *p << "' is not a number."; + throw NumberConversionError(ss.str()); + } + return d; + } + int64_t parseInt(std::string s, int radix){ + char* p; + + int64_t d = ::strtoll(s.c_str(), &p, radix); + + if (*p != 0) { + std::stringstream ss; + ss << "NumberConversionError: parseInt() error in argument \"" << s << "\", '" + << *p << "' is not a number."; + throw NumberConversionError(ss.str()); + } + return d; + } + +} + +/* +#include +void NumberConversion_test(){ + string s; + float f; + long long k; + + try{ + s = "-1.345"; + f = parseDouble(s); + cout << s << ": " << f << endl; + } + catch(NumberConversionError& ex){ + cout << ex.message << endl; + } + + + try{ + s = "-1.23e-2"; + f = parseDouble(s); + cout << s << ": " << f << endl; + } + catch(NumberConversionError& ex){ + cout << ex.message << endl; + } + + + try{ + s = ""; + f = parseDouble(s); + cout << s << ": " << f << endl; + } + catch(NumberConversionError& ex){ + cout << ex.message << endl; + } + + + + try{ + // -- fails, ok + s = "asd"; + f = parseDouble(s); + cout << s << ": " << f << endl; + } + catch(NumberConversionError& ex){ + cout << ex.message << endl; + } + + try{ + s = "-1234.123"; + k = parseInt(s); + cout << s << ": " << k << endl; + } + catch(NumberConversionError& ex){ + cout << ex.message << endl; + } + + + + try{ + s = "01234"; + k = parseInt(s); + cout << s << ": " << k << endl; + } + catch(NumberConversionError& ex){ + cout << ex.message << endl; + } + + + try{ + // -- converts to 0 + s = ""; + k = parseInt(s); + cout << s << ": " << k << endl; + } + catch(NumberConversionError& ex){ + cout << ex.message << endl; + } + + + try{ + // -- fails, ok + s = "asd"; + k = parseInt(s); + cout << s << ": " << k << endl; + } + catch(NumberConversionError& ex){ + cout << ex.message << endl; + } + + try{ + // -- fails, ok + s = "-16"; + k = parseInt(s); + cout << s << ": " << k << endl; + } + catch(NumberConversionError& ex){ + cout << ex.message << endl; + } + + } + */ \ No newline at end of file diff --git a/Bolt_Dash/src/main.cpp b/Bolt_Dash/src/main.cpp index 53c355b..8991f42 100644 --- a/Bolt_Dash/src/main.cpp +++ b/Bolt_Dash/src/main.cpp @@ -3,18 +3,27 @@ #include #include +#include #include "app_environment.h" +#include "backend.h" +#include "can.h" #include "import_qml_components_plugins.h" #include "import_qml_plugins.h" +#include "qfont.h" -int main(int argc, char *argv[]) -{ +int main(int argc, char *argv[]) { set_qt_environment(); QGuiApplication app(argc, argv); - + QFont font; + font.setFamily("MesloLGSDZ Nerd Font Mono"); + app.setFont(font); QQmlApplicationEngine engine; + + Backend *backend = new Backend(); + engine.rootContext()->setContextProperty("backend", backend); + const QUrl url(u"qrc:Main/main.qml"_qs); QObject::connect( &engine, &QQmlApplicationEngine::objectCreated, &app, diff --git a/Bolt_Dash/web.cpp b/Bolt_Dash/web.cpp new file mode 100644 index 0000000..ba781ca --- /dev/null +++ b/Bolt_Dash/web.cpp @@ -0,0 +1,53 @@ +#if __has_include() +#define CROW_FOUND 1 +#include "web.h" +#include "can.h" +#include "constants.h" +#include "gpsprocessing.h" +#include +#include +#include +#include + +namespace web { + + void runApp() { + crow::SimpleApp app; + + CROW_ROUTE(app, "/") + ([]() { + auto now = std::chrono::system_clock::now().time_since_epoch(); + crow::json::wvalue response({{"timestamp", std::chrono::duration_cast(now).count()}}); + m.lock(); + response["pack_state_of_charge"] = data.pack_state_of_charge * PACK_STATE_OF_CHARGE_SCALE; + response["pack_current"] = data.pack_current * PACK_CURRENT_SCALE; + response["high_cell_temp"] = data.high_cell_temp * HIGH_CELL_TEMP_SCALE; + response["low_cell_temp"] = data.low_cell_temp * LOW_CELL_TEMP_SCALE; + response["motor_temperature"] = data.motor_temperature * MOTOR_TEMPERATURE_SCALE; + response["bms_temperature"] = data.bms_temperature * BMS_TEMPERATURE_SCALE; + response["mc_temperature"] = data.mc_temperature * MC_TEMPERATURE_SCALE; + response["motor_speed"] = data.motor_speed * MOTOR_SPEED_SCALE; + response["bike_speed"] = data.bike_speed * BIKE_SPEED_SCALE; + response["bms_error"] = data.bms_error; + response["mc_fault"] = data.mc_fault; + response["motor_on"] = data.motor_on; + response["bike_status"] = data.bike_status; + m.unlock(); + gps_m.lock(); + response["lat"] = gps_lat; + response["lon"] = gps_lon; + gps_m.unlock(); + return response; + }); + + app.port(18080).multithreaded().run_async(); + } +} + +#else // crow.h not found; do nothing +namespace web { + void runApp() { + // No web server functionality + } +} +#endif diff --git a/Bolt_Dash/web.h b/Bolt_Dash/web.h new file mode 100644 index 0000000..dd9b42e --- /dev/null +++ b/Bolt_Dash/web.h @@ -0,0 +1,10 @@ +#ifndef WEB_H +#define WEB_H + +#define RPM_TO_SPEED (19.0 / 45.0 * 27.63 * M_PI / 1056) + +namespace web { + void runApp(); +} + +#endif // !WEB)H diff --git a/README.md b/README.md index a578b36..8ca116a 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Then, we install Qt by running `sudo apt install qt6-base-dev` ## Usage -Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. +To run this, open [QT Creator](https://www.qt.io/download-qt-installer-oss?utm_referrer=https%3A%2F%2Fwww.qt.io%2F). Click on file->Open File or Project and select the top-level CMakeLists.txt in the Bolt_Dash folder. If a screen comes up asking what you want to do, select configure project at the bottom right. Then, press the run button on the bottom right and the application should run. ## Roadmap diff --git a/docs/annotated.html b/docs/annotated.html new file mode 100644 index 0000000..d607f58 --- /dev/null +++ b/docs/annotated.html @@ -0,0 +1,119 @@ + + + + + + + +BOLT Dash (C++): Class List + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
BOLT Dash (C++) +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Class List
+
+
+
Here are the classes, structs, unions and interfaces with brief descriptions:
+ + + + +
 CBackendA class to represent the C++ backend of the dash which can be included in QML to give the frontend access
 CGPSData
 Cour_candataThis is a struct that contains all the data that we get from the CAN bus and is used in the dash project
+
+
+
+ + + + diff --git a/docs/annotated_dup.js b/docs/annotated_dup.js new file mode 100644 index 0000000..430e108 --- /dev/null +++ b/docs/annotated_dup.js @@ -0,0 +1,6 @@ +var annotated_dup = +[ + [ "Backend", "class_backend.html", "class_backend" ], + [ "GPSData", "struct_g_p_s_data.html", null ], + [ "our_candata", "structour__candata.html", "structour__candata" ] +]; \ No newline at end of file diff --git a/docs/backend_8h_source.html b/docs/backend_8h_source.html new file mode 100644 index 0000000..3e19d2b --- /dev/null +++ b/docs/backend_8h_source.html @@ -0,0 +1,317 @@ + + + + + + + +BOLT Dash (C++): Bolt_Dash/backend.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
BOLT Dash (C++) +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
backend.h
+
+
+
1#ifndef BACKEND_H
+
2#define BACKEND_H
+
3
+
4#include "qtmetamacros.h"
+
5#include <QObject>
+
6#include <QString>
+
7#include <qqml.h>
+
8#include <vector>
+
9
+
+
15class Backend : public QObject {
+
16 Q_OBJECT
+
17 QML_ELEMENT
+
18 Q_PROPERTY(double motorTemp READ motorTemp WRITE setMotorTemp NOTIFY motorTempChanged);
+
19 Q_PROPERTY(double auxVoltage READ auxVoltage WRITE setAuxVoltage NOTIFY auxVoltageChanged);
+
20 Q_PROPERTY(double auxPercent READ auxPercent WRITE setAuxPercent NOTIFY auxPercentChanged);
+
21 Q_PROPERTY(double packSOC READ packSOC WRITE setPackSOC NOTIFY packSOCChanged);
+
22 Q_PROPERTY(double packVoltage READ packVoltage WRITE setPackVoltage NOTIFY packVoltageChanged);
+
23 Q_PROPERTY(double highCellTemp READ highCellTemp WRITE setHighCellTemp NOTIFY highCellTempChanged);
+
24 Q_PROPERTY(double lowCellTemp READ lowCellTemp WRITE setLowCellTemp NOTIFY lowCellTempChanged);
+
25 Q_PROPERTY(double bmsTemp READ bmsTemp WRITE setBmsTemp NOTIFY bmsTempChanged);
+
26 Q_PROPERTY(double motorSpeed READ motorSpeed WRITE setMotorSpeed NOTIFY motorSpeedChanged);
+
27 Q_PROPERTY(double bikeSpeed READ bikeSpeed WRITE setBikeSpeed NOTIFY bikeSpeedChanged);
+
28 Q_PROPERTY(double mcTemp READ mcTemp WRITE setMcTemp NOTIFY mcTempChanged);
+
29 Q_PROPERTY(bool bmsFault READ bmsFault WRITE setBmsFault NOTIFY bmsFaultChanged);
+
30 Q_PROPERTY(bool mcFault READ mcFault WRITE setMcFault NOTIFY mcFaultChanged);
+
31 Q_PROPERTY(bool motorOn READ motorOn WRITE setMotorOn NOTIFY motorOnChanged);
+
32 Q_PROPERTY(int bikeStatus READ bikeStatus WRITE setBikeStatus NOTIFY bikeStatusChanged);
+
33 Q_PROPERTY(double packCurrent READ packCurrent WRITE setPackCurrent NOTIFY packCurrentChanged);
+
34 Q_PROPERTY(uint32_t bmsErrorCodes READ bmsErrorCodes WRITE setBmsErrorCodes NOTIFY bmsErrorCodesChanged);
+
35 Q_PROPERTY(bool bmsError READ bmsError WRITE setBmsError NOTIFY bmsErrorChanged);
+
36 Q_PROPERTY(bool bmsWarning READ bmsWarning WRITE setBmsWarning NOTIFY bmsWarningChanged);
+
37 Q_PROPERTY(std::vector<QString> bmsErrorCodesString READ bmsErrorCodesString NOTIFY bmsErrorCodesStringChanged);
+
38 Q_PROPERTY(double lat READ lat WRITE setLat NOTIFY latChanged);
+
39 Q_PROPERTY(double lon READ lon WRITE setLon NOTIFY lonChanged);
+
40
+
41public:
+
47 explicit Backend(QObject *parent = nullptr);
+
48
+
54 double motorTemp() const;
+
55
+
61 double auxVoltage() const;
+
62
+
68 double auxPercent() const;
+
69
+
75 double packSOC() const;
+
76
+
82 double packVoltage() const;
+
83
+
89 double highCellTemp() const;
+
90
+
96 double lowCellTemp() const;
+
97
+
103 double bmsTemp() const;
+
104
+
110 double motorSpeed() const;
+
111
+
117 double bikeSpeed() const;
+
118
+
124 double mcTemp() const;
+
125
+
132 bool bmsFault() const;
+
133
+
140 bool mcFault() const;
+
141
+
148 bool motorOn() const;
+
149
+
160 int bikeStatus() const;
+
161
+
167 double packCurrent() const;
+
168
+
175 bool bmsError() const;
+
176
+
183 bool bmsWarning() const;
+
184
+
190 uint32_t bmsErrorCodes() const;
+
191
+
197 std::vector<QString> bmsErrorCodesString() const;
+
198
+
204 double lat() const;
+
205
+
211 double lon() const;
+
212
+
218 void setMotorTemp(const double temp);
+
219
+
225 void setAuxVoltage(const double cap);
+
226
+
232 void setAuxPercent(const double cap);
+
233
+
239 void setPackSOC(const double soc);
+
240
+
246 void setPackVoltage(const double voltage);
+
247
+
253 void setHighCellTemp(const double temp);
+
254
+
260 void setLowCellTemp(const double temp);
+
261
+
267 void setBmsTemp(const double temp);
+
268
+
274 void setMotorSpeed(const double speed);
+
275
+
281 void setBikeSpeed(const double speed);
+
282
+
288 void setMcTemp(const double temp);
+
289
+
295 void setBmsFault(const bool fault);
+
296
+
302 void setMcFault(const bool fault);
+
303
+
309 void setMotorOn(const bool on);
+
310
+
316 void setBikeStatus(const int status);
+
317
+
323 void setPackCurrent(const double current);
+
324
+
330 void setBmsError(const bool error);
+
331
+
337 void setBmsWarning(const bool warning);
+
338
+
344 void setBmsErrorCodes(const uint32_t warnings);
+
345
+
351 void setBmsErrorCodesString(const std::vector<QString> warnings);
+
352
+
358 void setLat(const double lat);
+
359
+
365 void setLon(const double lon);
+
366
+
367signals:
+
368 void motorTempChanged();
+
369 void auxVoltageChanged();
+
370 void auxPercentChanged();
+
371 void packSOCChanged();
+
372 void packVoltageChanged();
+
373 void highCellTempChanged();
+
374 void lowCellTempChanged();
+
375 void bmsTempChanged();
+
376 void motorSpeedChanged();
+
377 void bikeSpeedChanged();
+
378 void mcTempChanged();
+
379 void bmsFaultChanged();
+
380 void mcFaultChanged();
+
381 void motorOnChanged();
+
382 void bikeStatusChanged();
+
383 void packCurrentChanged();
+
384 void bmsErrorChanged();
+
385 void bmsWarningChanged();
+
386 void bmsErrorCodesChanged();
+
387 void bmsErrorCodesStringChanged();
+
388 void latChanged();
+
389 void lonChanged();
+
390
+
391private:
+
392 void updateVars();
+
393 std::vector<QString> getErrorCodeStrings(uint32_t errorCodes);
+
394 double m_motorTemp;
+
395 double m_auxVoltage;
+
396 double m_auxPercent;
+
397 double m_packSOC;
+
398 double m_packVoltage;
+
399 double m_highCellTemp;
+
400 double m_lowCellTemp;
+
401 double m_bmsTemp;
+
402 double m_motorSpeed;
+
403 double m_bikeSpeed;
+
404 double m_mcTemp;
+
405 bool m_bmsFault;
+
406 bool m_mcFault;
+
407 bool m_motorOn;
+
408 int m_bikeStatus;
+
409 double m_packCurrent;
+
410 bool m_bmsError;
+
411 bool m_bmsWarning;
+
412 uint32_t m_bmsErrorCodes;
+
413 std::vector<QString> m_bmsErrorCodesString;
+
414 double m_lat;
+
415 double m_lon;
+
416};
+
+
417
+
418#endif // BACKEND_H
+
A class to represent the C++ backend of the dash which can be included in QML to give the frontend ac...
Definition backend.h:15
+
void setMcTemp(const double temp)
Set the MC Temp parameter, will get overwritten internally.
Definition backend.cpp:312
+
void setAuxPercent(const double cap)
Set the Aux Percent parameter, will get overwritten internally.
Definition backend.cpp:256
+
void setHighCellTemp(const double temp)
Set the High Cell Temp parameter, will get overwritten internally.
Definition backend.cpp:277
+
void setBmsWarning(const bool warning)
Set the BMS Warning parameter, will get overwritten internally.
Definition backend.cpp:361
+
void setLon(const double lon)
Set the Longitude parameter, will get overwritten internally.
Definition backend.cpp:389
+
void setMotorSpeed(const double speed)
Set the Motor Speed parameter, will get overwritten internally.
Definition backend.cpp:298
+
void setBikeSpeed(const double speed)
Set the Bike Speed parameter, will get overwritten internally.
Definition backend.cpp:305
+
void setBmsTemp(const double temp)
Set the BMS Temp parameter, will get overwritten internally.
Definition backend.cpp:291
+
Backend(QObject *parent=nullptr)
Create Backend class which can be included in QML.
Definition backend.cpp:16
+
void setPackCurrent(const double current)
Set the Pack Current parameter, will get overwritten internally.
Definition backend.cpp:347
+
void setBmsError(const bool error)
Set the BMS Error parameter, will get overwritten internally.
Definition backend.cpp:354
+
void setMotorTemp(const double temp)
Set the Motor Temperature parameter, will get overwritten internally.
Definition backend.cpp:242
+
void setBikeStatus(const int status)
Set the Bike Status parameter, will get overwritten internally.
Definition backend.cpp:340
+
void setBmsErrorCodes(const uint32_t warnings)
Set the BMS Error Codes parameter, will get overwritten internally.
Definition backend.cpp:368
+
void setMotorOn(const bool on)
Set the Motor On parameter, will get overwritten internally.
Definition backend.cpp:333
+
void setLowCellTemp(const double temp)
Set the Low Cell Temp parameter, will get overwritten internally.
Definition backend.cpp:284
+
void setMcFault(const bool fault)
Set the MC Fault parameter, will get overwritten internally.
Definition backend.cpp:326
+
void setBmsFault(const bool fault)
Set the BMS Fault parameter, will get overwritten internally.
Definition backend.cpp:319
+
void setLat(const double lat)
Set the Latitude parameter, will get overwritten internally.
Definition backend.cpp:382
+
void setPackVoltage(const double voltage)
Set the Pack Voltage parameter, will get overwritten internally.
Definition backend.cpp:270
+
void setAuxVoltage(const double cap)
Set the Aux Voltage parameter, will get overwritten internally.
Definition backend.cpp:249
+
void setPackSOC(const double soc)
Set the Pack SOC parameter, will get overwritten internally.
Definition backend.cpp:263
+
void setBmsErrorCodesString(const std::vector< QString > warnings)
Set the BMS Error Codes String parameter, will get overwritten internally.
Definition backend.cpp:375
+
+
+ + + + diff --git a/docs/bc_s.png b/docs/bc_s.png new file mode 100644 index 0000000..224b29a Binary files /dev/null and b/docs/bc_s.png differ diff --git a/docs/bc_sd.png b/docs/bc_sd.png new file mode 100644 index 0000000..31ca888 Binary files /dev/null and b/docs/bc_sd.png differ diff --git a/docs/can_8h_source.html b/docs/can_8h_source.html new file mode 100644 index 0000000..0667fab --- /dev/null +++ b/docs/can_8h_source.html @@ -0,0 +1,241 @@ + + + + + + + +BOLT Dash (C++): Bolt_Dash/can.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
BOLT Dash (C++) +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
can.h
+
+
+
1#ifndef CAN_H
+
2#define CAN_H
+
3
+
4#include <mutex>
+
5#include <unistd.h>
+
6
+
7#include <net/if.h>
+
8#include <sys/ioctl.h>
+
9#include <sys/socket.h>
+
10
+
11#include <linux/can.h>
+
12#include <linux/can/raw.h>
+
13
+
14#define BMS_FAULT_MASK 0b0010000
+
15
+
+ +
25 uint8_t aux_voltage{};
+
29 uint8_t aux_percent{};
+ +
37 uint16_t pack_voltage{};
+
41 int16_t pack_current{};
+
45 uint16_t high_cell_temp{};
+
49 uint16_t low_cell_temp{};
+ +
57 uint16_t bms_temperature{};
+
61 uint16_t mc_temperature{};
+
65 int16_t motor_speed{};
+
69 int16_t bike_speed{};
+
73 uint8_t bms_fault{};
+
77 uint8_t bms_error{};
+
81 uint8_t bms_warning{};
+
85 uint32_t bms_error_codes{};
+
89 uint8_t mc_fault{};
+
93 uint8_t motor_on{};
+
97 uint8_t bike_status{};
+ + +
106};
+
+
107
+
108// ID's for each CAN thing
+
109constexpr struct {
+
110 canid_t aux_battery{0x700};
+
111 canid_t info{0x6B0};
+
112 canid_t cell_max_min_voltages{0x6B3};
+
113 canid_t main_pack_temp{0x6B4};
+
114 canid_t bms_error_codes{0x6B6};
+
115 canid_t motor_temp{0xA2};
+
116 canid_t bms_temp{0x6B1};
+
117 canid_t mc_temp{0xA0};
+
118 canid_t rpm{0xA5};
+
119 canid_t speed{0x00};
+
120 canid_t mc_faults{0x0AB};
+
121 canid_t internal_states{0x0AA};
+
122} can_ids;
+
123
+
124constexpr struct {
+
125 uint32_t discharge_limit_enforcement{1 << 0};
+
126 uint32_t charger_safety_relay{1 << 1};
+
127 uint32_t internal_heatsink_thermistor{1 << 3};
+
128 uint32_t cell_balancing_stuck_off{1 << 9};
+
129 uint32_t weak_cell{1 << 10};
+
130 uint32_t open_wiring{1 << 12};
+
131 uint32_t current_sensor{1 << 13};
+
132 uint32_t weak_pack{1 << 16};
+
133 uint32_t fan_monitor{1 << 17};
+
134 uint32_t thermistor_fault{1 << 18};
+
135 uint32_t external_communication{1 << 19};
+
136 uint32_t charge_limit_enforcement{1 << 23};
+
137} bms_warnings;
+
138
+
139constexpr struct {
+
140 uint32_t internal_hardware{1 << 2};
+
141 uint32_t internal_software{1 << 4};
+
142 uint32_t highest_cell_voltage_too_high{1 << 5};
+
143 uint32_t lowest_cell_voltage_too_low{1 << 6};
+
144 uint32_t pack_too_hot{1 << 7};
+
145 uint32_t internal_communication{1 << 8};
+
146 uint32_t low_cell_voltage{1 << 11};
+
147 uint32_t highest_cell_voltage_over_5v{1 << 14};
+
148 uint32_t cell_asic_fault{1 << 15};
+
149 uint32_t redundant_power_supply{1 << 20};
+
150 uint32_t high_voltage_isolation{1 << 21};
+
151 uint32_t input_power_supply{1 << 22};
+
152} bms_errors;
+
153
+
154const uint32_t ALL_BMS_ERRORS = bms_errors.internal_hardware | bms_errors.internal_software |
+
155 bms_errors.highest_cell_voltage_too_high | bms_errors.lowest_cell_voltage_too_low |
+
156 bms_errors.pack_too_hot | bms_errors.internal_communication | bms_errors.low_cell_voltage |
+
157 bms_errors.highest_cell_voltage_over_5v | bms_errors.cell_asic_fault |
+
158 bms_errors.redundant_power_supply | bms_errors.high_voltage_isolation |
+
159 bms_errors.input_power_supply;
+
160const uint32_t ALL_BMS_WARNINGS = bms_warnings.charger_safety_relay | bms_warnings.discharge_limit_enforcement |
+
161 bms_warnings.cell_balancing_stuck_off | bms_warnings.internal_heatsink_thermistor | bms_warnings.weak_cell |
+
162 bms_warnings.current_sensor | bms_warnings.weak_pack | bms_warnings.fan_monitor |
+
163 bms_warnings.thermistor_fault | bms_warnings.external_communication |
+
164 bms_warnings.open_wiring | bms_warnings.charge_limit_enforcement;
+
165extern std::mutex m;
+
166extern our_candata data;
+
167
+
168namespace can {
+
169 int run();
+
170}
+
171
+
172#endif // CAN_H
+
This is a struct that contains all the data that we get from the CAN bus and is used in the dash proj...
Definition can.h:21
+
int16_t motor_speed
The RPM of the motor.
Definition can.h:65
+
uint16_t mc_temperature
The temperature of the motor controller.
Definition can.h:61
+
uint8_t aux_percent
The battery percentage of the aux pack.
Definition can.h:29
+
uint16_t lowest_cell_voltage
The lowest cell voltage in the main pack.
Definition can.h:105
+
uint8_t mc_fault
Whether or no the MC has a fault.
Definition can.h:89
+
uint8_t bms_warning
Whether the BMS has any warnings.
Definition can.h:81
+
uint8_t bms_error
Whether the BMS has any errors.
Definition can.h:77
+
uint16_t pack_voltage
The voltage of the main pack.
Definition can.h:37
+
uint8_t motor_on
Whether or not the motor is active.
Definition can.h:93
+
int16_t bike_speed
The speed of the bike in mph.
Definition can.h:69
+
uint8_t bms_fault
The fault status of the BMS.
Definition can.h:73
+
uint16_t low_cell_temp
The temperature of the coldest cell group in the main pack.
Definition can.h:49
+
uint32_t bms_error_codes
The actual error codes of the BMS concatenated together.
Definition can.h:85
+
uint16_t highest_cell_voltage
The highest cell voltage in the main pack.
Definition can.h:101
+
uint8_t aux_voltage
The voltage of the aux pack.
Definition can.h:25
+
uint8_t pack_state_of_charge
The state of charge of the main pack as a percentage.
Definition can.h:33
+
uint16_t bms_temperature
The temperature of the BMS.
Definition can.h:57
+
int16_t pack_current
The current of the main pack.
Definition can.h:41
+
int16_t motor_temperature
The temperature of the motor.
Definition can.h:53
+
uint8_t bike_status
The internal state of the bike, not used rn.
Definition can.h:97
+
uint16_t high_cell_temp
The temperature of the hottest cell group in the main pack.
Definition can.h:45
+
+
+ + + + diff --git a/docs/class_backend-members.html b/docs/class_backend-members.html new file mode 100644 index 0000000..b6d3732 --- /dev/null +++ b/docs/class_backend-members.html @@ -0,0 +1,204 @@ + + + + + + + +BOLT Dash (C++): Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
BOLT Dash (C++) +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Backend Member List
+
+
+ +

This is the complete list of members for Backend, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
auxPercent (defined in Backend)Backend
auxPercent() constBackend
auxPercentChanged() (defined in Backend)Backendsignal
auxVoltage (defined in Backend)Backend
auxVoltage() constBackend
auxVoltageChanged() (defined in Backend)Backendsignal
Backend(QObject *parent=nullptr)Backendexplicit
bikeSpeed (defined in Backend)Backend
bikeSpeed() constBackend
bikeSpeedChanged() (defined in Backend)Backendsignal
bikeStatus (defined in Backend)Backend
bikeStatus() constBackend
bikeStatusChanged() (defined in Backend)Backendsignal
bmsError (defined in Backend)Backend
bmsError() constBackend
bmsErrorChanged() (defined in Backend)Backendsignal
bmsErrorCodes (defined in Backend)Backend
bmsErrorCodes() constBackend
bmsErrorCodesChanged() (defined in Backend)Backendsignal
bmsErrorCodesString (defined in Backend)Backend
bmsErrorCodesString() constBackend
bmsErrorCodesStringChanged() (defined in Backend)Backendsignal
bmsFault (defined in Backend)Backend
bmsFault() constBackend
bmsFaultChanged() (defined in Backend)Backendsignal
bmsTemp (defined in Backend)Backend
bmsTemp() constBackend
bmsTempChanged() (defined in Backend)Backendsignal
bmsWarning (defined in Backend)Backend
bmsWarning() constBackend
bmsWarningChanged() (defined in Backend)Backendsignal
highCellTemp (defined in Backend)Backend
highCellTemp() constBackend
highCellTempChanged() (defined in Backend)Backendsignal
lat (defined in Backend)Backend
lat() constBackend
latChanged() (defined in Backend)Backendsignal
lon (defined in Backend)Backend
lon() constBackend
lonChanged() (defined in Backend)Backendsignal
lowCellTemp (defined in Backend)Backend
lowCellTemp() constBackend
lowCellTempChanged() (defined in Backend)Backendsignal
mcFault (defined in Backend)Backend
mcFault() constBackend
mcFaultChanged() (defined in Backend)Backendsignal
mcTemp (defined in Backend)Backend
mcTemp() constBackend
mcTempChanged() (defined in Backend)Backendsignal
motorOn (defined in Backend)Backend
motorOn() constBackend
motorOnChanged() (defined in Backend)Backendsignal
motorSpeed (defined in Backend)Backend
motorSpeed() constBackend
motorSpeedChanged() (defined in Backend)Backendsignal
motorTemp (defined in Backend)Backend
motorTemp() constBackend
motorTempChanged() (defined in Backend)Backendsignal
packCurrent (defined in Backend)Backend
packCurrent() constBackend
packCurrentChanged() (defined in Backend)Backendsignal
packSOC (defined in Backend)Backend
packSOC() constBackend
packSOCChanged() (defined in Backend)Backendsignal
packVoltage (defined in Backend)Backend
packVoltage() constBackend
packVoltageChanged() (defined in Backend)Backendsignal
setAuxPercent(const double cap)Backend
setAuxVoltage(const double cap)Backend
setBikeSpeed(const double speed)Backend
setBikeStatus(const int status)Backend
setBmsError(const bool error)Backend
setBmsErrorCodes(const uint32_t warnings)Backend
setBmsErrorCodesString(const std::vector< QString > warnings)Backend
setBmsFault(const bool fault)Backend
setBmsTemp(const double temp)Backend
setBmsWarning(const bool warning)Backend
setHighCellTemp(const double temp)Backend
setLat(const double lat)Backend
setLon(const double lon)Backend
setLowCellTemp(const double temp)Backend
setMcFault(const bool fault)Backend
setMcTemp(const double temp)Backend
setMotorOn(const bool on)Backend
setMotorSpeed(const double speed)Backend
setMotorTemp(const double temp)Backend
setPackCurrent(const double current)Backend
setPackSOC(const double soc)Backend
setPackVoltage(const double voltage)Backend
+
+ + + + diff --git a/docs/class_backend.html b/docs/class_backend.html new file mode 100644 index 0000000..d089da1 --- /dev/null +++ b/docs/class_backend.html @@ -0,0 +1,1454 @@ + + + + + + + +BOLT Dash (C++): Backend Class Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
BOLT Dash (C++) +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+ +
Backend Class Reference
+
+
+ +

A class to represent the C++ backend of the dash which can be included in QML to give the frontend access. + More...

+ +

#include <backend.h>

+
+Inheritance diagram for Backend:
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Signals

+void motorTempChanged ()
 
+void auxVoltageChanged ()
 
+void auxPercentChanged ()
 
+void packSOCChanged ()
 
+void packVoltageChanged ()
 
+void highCellTempChanged ()
 
+void lowCellTempChanged ()
 
+void bmsTempChanged ()
 
+void motorSpeedChanged ()
 
+void bikeSpeedChanged ()
 
+void mcTempChanged ()
 
+void bmsFaultChanged ()
 
+void mcFaultChanged ()
 
+void motorOnChanged ()
 
+void bikeStatusChanged ()
 
+void packCurrentChanged ()
 
+void bmsErrorChanged ()
 
+void bmsWarningChanged ()
 
+void bmsErrorCodesChanged ()
 
+void bmsErrorCodesStringChanged ()
 
+void latChanged ()
 
+void lonChanged ()
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Backend (QObject *parent=nullptr)
 Create Backend class which can be included in QML.
 
double motorTemp () const
 Get the motor temperature.
 
double auxVoltage () const
 Get the voltage of the aux pack.
 
double auxPercent () const
 Get the percent charge of the aux pack.
 
double packSOC () const
 Get the state of charge of the main battery.
 
double packVoltage () const
 Get the voltage of the main battery.
 
double highCellTemp () const
 Get the highest cell temperature in the pack.
 
double lowCellTemp () const
 Get the lowest cell temperature in the pack.
 
double bmsTemp () const
 Get the temeprature of the BMS.
 
double motorSpeed () const
 Get the speed of the motor.
 
double bikeSpeed () const
 Get the speed of the bike.
 
double mcTemp () const
 Get the temperature of the motor controller.
 
bool bmsFault () const
 Get whether or not there is a BMS fault.
 
bool mcFault () const
 Get whether or not there is a motor controller fault.
 
bool motorOn () const
 Get whether or not the motor is currently active.
 
int bikeStatus () const
 Get the current status of the bike.
 
double packCurrent () const
 Get the current flowing from the main pack.
 
bool bmsError () const
 Get whether or not there is a BMS error.
 
bool bmsWarning () const
 Get whether or not there is a BMS warning.
 
uint32_t bmsErrorCodes () const
 Get the BMS error codes as a bitfield.
 
std::vector< QString > bmsErrorCodesString () const
 Get the BMS error codes as a vector of strings.
 
double lat () const
 Get the latitude of the bike.
 
double lon () const
 Get the longitude of the bike.
 
void setMotorTemp (const double temp)
 Set the Motor Temperature parameter, will get overwritten internally.
 
void setAuxVoltage (const double cap)
 Set the Aux Voltage parameter, will get overwritten internally.
 
void setAuxPercent (const double cap)
 Set the Aux Percent parameter, will get overwritten internally.
 
void setPackSOC (const double soc)
 Set the Pack SOC parameter, will get overwritten internally.
 
void setPackVoltage (const double voltage)
 Set the Pack Voltage parameter, will get overwritten internally.
 
void setHighCellTemp (const double temp)
 Set the High Cell Temp parameter, will get overwritten internally.
 
void setLowCellTemp (const double temp)
 Set the Low Cell Temp parameter, will get overwritten internally.
 
void setBmsTemp (const double temp)
 Set the BMS Temp parameter, will get overwritten internally.
 
void setMotorSpeed (const double speed)
 Set the Motor Speed parameter, will get overwritten internally.
 
void setBikeSpeed (const double speed)
 Set the Bike Speed parameter, will get overwritten internally.
 
void setMcTemp (const double temp)
 Set the MC Temp parameter, will get overwritten internally.
 
void setBmsFault (const bool fault)
 Set the BMS Fault parameter, will get overwritten internally.
 
void setMcFault (const bool fault)
 Set the MC Fault parameter, will get overwritten internally.
 
void setMotorOn (const bool on)
 Set the Motor On parameter, will get overwritten internally.
 
void setBikeStatus (const int status)
 Set the Bike Status parameter, will get overwritten internally.
 
void setPackCurrent (const double current)
 Set the Pack Current parameter, will get overwritten internally.
 
void setBmsError (const bool error)
 Set the BMS Error parameter, will get overwritten internally.
 
void setBmsWarning (const bool warning)
 Set the BMS Warning parameter, will get overwritten internally.
 
void setBmsErrorCodes (const uint32_t warnings)
 Set the BMS Error Codes parameter, will get overwritten internally.
 
void setBmsErrorCodesString (const std::vector< QString > warnings)
 Set the BMS Error Codes String parameter, will get overwritten internally.
 
void setLat (const double lat)
 Set the Latitude parameter, will get overwritten internally.
 
void setLon (const double lon)
 Set the Longitude parameter, will get overwritten internally.
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Properties

+QML_ELEMENTdouble motorTemp
 
+double auxVoltage
 
+double auxPercent
 
+double packSOC
 
+double packVoltage
 
+double highCellTemp
 
+double lowCellTemp
 
+double bmsTemp
 
+double motorSpeed
 
+double bikeSpeed
 
+double mcTemp
 
+bool bmsFault
 
+bool mcFault
 
+bool motorOn
 
+int bikeStatus
 
+double packCurrent
 
+uint32_t bmsErrorCodes
 
+bool bmsError
 
+bool bmsWarning
 
+std::vector< QString > bmsErrorCodesString
 
+double lat
 
+double lon
 
+

Detailed Description

+

A class to represent the C++ backend of the dash which can be included in QML to give the frontend access.

+

Constructor & Destructor Documentation

+ +

◆ Backend()

+ +
+
+ + + + + +
+ + + + + + + +
Backend::Backend (QObject * parent = nullptr)
+
+explicit
+
+ +

Create Backend class which can be included in QML.

+
Parameters
+ + +
parentthe QObject parent above the Backend
+
+
+ +
+
+

Member Function Documentation

+ +

◆ auxPercent()

+ +
+
+ + + + + + + +
double Backend::auxPercent () const
+
+ +

Get the percent charge of the aux pack.

+
Returns
The percentage as a percent (e.g. 87.3)
+ +
+
+ +

◆ auxVoltage()

+ +
+
+ + + + + + + +
double Backend::auxVoltage () const
+
+ +

Get the voltage of the aux pack.

+
Returns
The voltage in volts
+ +
+
+ +

◆ bikeSpeed()

+ +
+
+ + + + + + + +
double Backend::bikeSpeed () const
+
+ +

Get the speed of the bike.

+
Returns
The speed in mph
+ +
+
+ +

◆ bikeStatus()

+ +
+
+ + + + + + + +
int Backend::bikeStatus () const
+
+ +

Get the current status of the bike.

+
    +
  1. Idle
  2. +
  3. Precharge
  4. +
  5. Ready
  6. +
  7. Active
  8. +
  9. There is a fault somewhere
  10. +
+
Returns
An integer representing the status as shown above
+ +
+
+ +

◆ bmsError()

+ +
+
+ + + + + + + +
bool Backend::bmsError () const
+
+ +

Get whether or not there is a BMS error.

+
Returns
true if there is any major error
+
+false if there is not
+ +
+
+ +

◆ bmsErrorCodes()

+ +
+
+ + + + + + + +
uint32_t Backend::bmsErrorCodes () const
+
+ +

Get the BMS error codes as a bitfield.

+
Returns
A 32-bit integer with each bit representing a different error
+ +
+
+ +

◆ bmsErrorCodesString()

+ +
+
+ + + + + + + +
std::vector< QString > Backend::bmsErrorCodesString () const
+
+ +

Get the BMS error codes as a vector of strings.

+
Returns
A Vector of Qt-Strings with each string representing a different error
+ +
+
+ +

◆ bmsFault()

+ +
+
+ + + + + + + +
bool Backend::bmsFault () const
+
+ +

Get whether or not there is a BMS fault.

+
Returns
true if there is a fault
+
+false if all is good
+ +
+
+ +

◆ bmsTemp()

+ +
+
+ + + + + + + +
double Backend::bmsTemp () const
+
+ +

Get the temeprature of the BMS.

+
Returns
The temperature in degrees Celsius
+ +
+
+ +

◆ bmsWarning()

+ +
+
+ + + + + + + +
bool Backend::bmsWarning () const
+
+ +

Get whether or not there is a BMS warning.

+
Returns
true if there is a minor error/warning
+
+false if there is not
+ +
+
+ +

◆ highCellTemp()

+ +
+
+ + + + + + + +
double Backend::highCellTemp () const
+
+ +

Get the highest cell temperature in the pack.

+
Returns
The temperature in degrees Celsius
+ +
+
+ +

◆ lat()

+ +
+
+ + + + + + + +
double Backend::lat () const
+
+ +

Get the latitude of the bike.

+
Returns
The latitude in degrees
+ +
+
+ +

◆ lon()

+ +
+
+ + + + + + + +
double Backend::lon () const
+
+ +

Get the longitude of the bike.

+
Returns
The longitude in degrees
+ +
+
+ +

◆ lowCellTemp()

+ +
+
+ + + + + + + +
double Backend::lowCellTemp () const
+
+ +

Get the lowest cell temperature in the pack.

+
Returns
The temperature in degrees Celsius
+ +
+
+ +

◆ mcFault()

+ +
+
+ + + + + + + +
bool Backend::mcFault () const
+
+ +

Get whether or not there is a motor controller fault.

+
Returns
true if there is a fault
+
+false if all is good
+ +
+
+ +

◆ mcTemp()

+ +
+
+ + + + + + + +
double Backend::mcTemp () const
+
+ +

Get the temperature of the motor controller.

+
Returns
The highest temperature of the three sensors in degrees Celsius
+ +
+
+ +

◆ motorOn()

+ +
+
+ + + + + + + +
bool Backend::motorOn () const
+
+ +

Get whether or not the motor is currently active.

+
Returns
true if the motor can be moved with the throttle
+
+false if it cannot be moved electrically
+ +
+
+ +

◆ motorSpeed()

+ +
+
+ + + + + + + +
double Backend::motorSpeed () const
+
+ +

Get the speed of the motor.

+
Returns
The motor speed in RPM
+ +
+
+ +

◆ motorTemp()

+ +
+
+ + + + + + + +
double Backend::motorTemp () const
+
+ +

Get the motor temperature.

+
Returns
The temperature in degrees Celsius
+ +
+
+ +

◆ packCurrent()

+ +
+
+ + + + + + + +
double Backend::packCurrent () const
+
+ +

Get the current flowing from the main pack.

+
Returns
The current in amps
+ +
+
+ +

◆ packSOC()

+ +
+
+ + + + + + + +
double Backend::packSOC () const
+
+ +

Get the state of charge of the main battery.

+
Returns
The percentage as a percent (e.g. 87.3)
+ +
+
+ +

◆ packVoltage()

+ +
+
+ + + + + + + +
double Backend::packVoltage () const
+
+ +

Get the voltage of the main battery.

+
Returns
The voltage in volts
+ +
+
+ +

◆ setAuxPercent()

+ +
+
+ + + + + + + +
void Backend::setAuxPercent (const double cap)
+
+ +

Set the Aux Percent parameter, will get overwritten internally.

+
Parameters
+ + +
capThe percent to set
+
+
+ +
+
+ +

◆ setAuxVoltage()

+ +
+
+ + + + + + + +
void Backend::setAuxVoltage (const double cap)
+
+ +

Set the Aux Voltage parameter, will get overwritten internally.

+
Parameters
+ + +
capThe temperature to set in degrees Celsius
+
+
+ +
+
+ +

◆ setBikeSpeed()

+ +
+
+ + + + + + + +
void Backend::setBikeSpeed (const double speed)
+
+ +

Set the Bike Speed parameter, will get overwritten internally.

+
Parameters
+ + +
speedThe speed to set in mph
+
+
+ +
+
+ +

◆ setBikeStatus()

+ +
+
+ + + + + + + +
void Backend::setBikeStatus (const int status)
+
+ +

Set the Bike Status parameter, will get overwritten internally.

+
Parameters
+ + +
statusThe status of the bike
+
+
+ +
+
+ +

◆ setBmsError()

+ +
+
+ + + + + + + +
void Backend::setBmsError (const bool error)
+
+ +

Set the BMS Error parameter, will get overwritten internally.

+
Parameters
+ + +
errorWhether or not there is an error
+
+
+ +
+
+ +

◆ setBmsErrorCodes()

+ +
+
+ + + + + + + +
void Backend::setBmsErrorCodes (const uint32_t warnings)
+
+ +

Set the BMS Error Codes parameter, will get overwritten internally.

+
Parameters
+ + +
warningsThe error codes to set
+
+
+ +
+
+ +

◆ setBmsErrorCodesString()

+ +
+
+ + + + + + + +
void Backend::setBmsErrorCodesString (const std::vector< QString > warnings)
+
+ +

Set the BMS Error Codes String parameter, will get overwritten internally.

+
Parameters
+ + +
warningsThe error codes to set
+
+
+ +
+
+ +

◆ setBmsFault()

+ +
+
+ + + + + + + +
void Backend::setBmsFault (const bool fault)
+
+ +

Set the BMS Fault parameter, will get overwritten internally.

+
Parameters
+ + +
faultWhether or not there is a fault
+
+
+ +
+
+ +

◆ setBmsTemp()

+ +
+
+ + + + + + + +
void Backend::setBmsTemp (const double temp)
+
+ +

Set the BMS Temp parameter, will get overwritten internally.

+
Parameters
+ + +
tempThe temperature to set in degrees Celsius
+
+
+ +
+
+ +

◆ setBmsWarning()

+ +
+
+ + + + + + + +
void Backend::setBmsWarning (const bool warning)
+
+ +

Set the BMS Warning parameter, will get overwritten internally.

+
Parameters
+ + +
warningWhether or not there is a warning
+
+
+ +
+
+ +

◆ setHighCellTemp()

+ +
+
+ + + + + + + +
void Backend::setHighCellTemp (const double temp)
+
+ +

Set the High Cell Temp parameter, will get overwritten internally.

+
Parameters
+ + +
tempThe temperature to set in degrees Celsius
+
+
+ +
+
+ +

◆ setLat()

+ +
+
+ + + + + + + +
void Backend::setLat (const double lat)
+
+ +

Set the Latitude parameter, will get overwritten internally.

+
Parameters
+ + +
latThe latitude to set in degrees
+
+
+ +
+
+ +

◆ setLon()

+ +
+
+ + + + + + + +
void Backend::setLon (const double lon)
+
+ +

Set the Longitude parameter, will get overwritten internally.

+
Parameters
+ + +
lonThe longitude to set in degrees
+
+
+ +
+
+ +

◆ setLowCellTemp()

+ +
+
+ + + + + + + +
void Backend::setLowCellTemp (const double temp)
+
+ +

Set the Low Cell Temp parameter, will get overwritten internally.

+
Parameters
+ + +
tempThe temperature to set in degrees Celsius
+
+
+ +
+
+ +

◆ setMcFault()

+ +
+
+ + + + + + + +
void Backend::setMcFault (const bool fault)
+
+ +

Set the MC Fault parameter, will get overwritten internally.

+
Parameters
+ + +
faultWhether or not there is a fault
+
+
+ +
+
+ +

◆ setMcTemp()

+ +
+
+ + + + + + + +
void Backend::setMcTemp (const double temp)
+
+ +

Set the MC Temp parameter, will get overwritten internally.

+
Parameters
+ + +
tempThe temperature to set in degrees Celsius
+
+
+ +
+
+ +

◆ setMotorOn()

+ +
+
+ + + + + + + +
void Backend::setMotorOn (const bool on)
+
+ +

Set the Motor On parameter, will get overwritten internally.

+
Parameters
+ + +
onWhether or not the motor is on
+
+
+ +
+
+ +

◆ setMotorSpeed()

+ +
+
+ + + + + + + +
void Backend::setMotorSpeed (const double speed)
+
+ +

Set the Motor Speed parameter, will get overwritten internally.

+
Parameters
+ + +
speedThe speed to set in RPM
+
+
+ +
+
+ +

◆ setMotorTemp()

+ +
+
+ + + + + + + +
void Backend::setMotorTemp (const double temp)
+
+ +

Set the Motor Temperature parameter, will get overwritten internally.

+
Parameters
+ + +
tempThe temperature to set in degrees Celsius
+
+
+ +
+
+ +

◆ setPackCurrent()

+ +
+
+ + + + + + + +
void Backend::setPackCurrent (const double current)
+
+ +

Set the Pack Current parameter, will get overwritten internally.

+
Parameters
+ + +
currentThe current to set in amps
+
+
+ +
+
+ +

◆ setPackSOC()

+ +
+
+ + + + + + + +
void Backend::setPackSOC (const double soc)
+
+ +

Set the Pack SOC parameter, will get overwritten internally.

+
Parameters
+ + +
socThe percent to set
+
+
+ +
+
+ +

◆ setPackVoltage()

+ +
+
+ + + + + + + +
void Backend::setPackVoltage (const double voltage)
+
+ +

Set the Pack Voltage parameter, will get overwritten internally.

+
Parameters
+ + +
voltageThe voltage to set in volts
+
+
+ +
+
+
The documentation for this class was generated from the following files:
    +
  • Bolt_Dash/backend.h
  • +
  • Bolt_Dash/backend.cpp
  • +
+
+
+ + + + diff --git a/docs/class_backend.js b/docs/class_backend.js new file mode 100644 index 0000000..5805478 --- /dev/null +++ b/docs/class_backend.js @@ -0,0 +1,48 @@ +var class_backend = +[ + [ "Backend", "class_backend.html#a5bc0e9ea135112c07e021ebde56ec44f", null ], + [ "auxPercent", "class_backend.html#a2b9deb50de11a2fde07ef6589a31b7a0", null ], + [ "auxVoltage", "class_backend.html#a41e2e287304215732af6f9d6273792bb", null ], + [ "bikeSpeed", "class_backend.html#adf1e224769b6c96c359475583e5dc159", null ], + [ "bikeStatus", "class_backend.html#ad7c06e20ccfa73a5bd52187f39b97054", null ], + [ "bmsError", "class_backend.html#a3875076145e97af7fde2a1c37f543293", null ], + [ "bmsErrorCodes", "class_backend.html#a15330410228d1397f3bd0fb01a97f412", null ], + [ "bmsErrorCodesString", "class_backend.html#a177b020eecbfbec86fa331f146420021", null ], + [ "bmsFault", "class_backend.html#a0bc7373b61657730a31b121851d26f99", null ], + [ "bmsTemp", "class_backend.html#a6d30b487c228843a22da6fe82bc96003", null ], + [ "bmsWarning", "class_backend.html#a7150ddb151a1f8c62ef3f2ac762b5fbe", null ], + [ "highCellTemp", "class_backend.html#a338d6ee091433158a4a82ec6c60cbde9", null ], + [ "lat", "class_backend.html#a8f93242ca98779058d3947e318b8944a", null ], + [ "lon", "class_backend.html#a21bc64c24fe21d47fde74754d4772c08", null ], + [ "lowCellTemp", "class_backend.html#a2551568902d423cd2d6e7456fb68f218", null ], + [ "mcFault", "class_backend.html#a1cd3fc891b7d02f4abd62fc117bdca83", null ], + [ "mcTemp", "class_backend.html#a06ee9247c3f51b6e56ae40564100f73a", null ], + [ "motorOn", "class_backend.html#aff3f0f82e71ca4c549fb8c6a61be2310", null ], + [ "motorSpeed", "class_backend.html#af248999c9a205fab70f7263943337b71", null ], + [ "motorTemp", "class_backend.html#a256e55ad5e78b997c6bc217c9decb29d", null ], + [ "packCurrent", "class_backend.html#a96cce8014d840e2e9e565849fd4d6f1c", null ], + [ "packSOC", "class_backend.html#a4c923e3177a05d7a235eef43c64dc3f4", null ], + [ "packVoltage", "class_backend.html#aa114119bb0c61c19789114e85d0f9aec", null ], + [ "setAuxPercent", "class_backend.html#a181d4ef7a800a59f30970aff81935ff9", null ], + [ "setAuxVoltage", "class_backend.html#aea1988760e23d3a71c8e59d3fbd629a3", null ], + [ "setBikeSpeed", "class_backend.html#a41f530c3353b3090ecb5e5be8cc285b6", null ], + [ "setBikeStatus", "class_backend.html#aa4dd42516324c53f45594ebfde561937", null ], + [ "setBmsError", "class_backend.html#a5fb55f0d084b1526cd7722e9536367f3", null ], + [ "setBmsErrorCodes", "class_backend.html#aa9a795644028d3c7e77563034dcbc20a", null ], + [ "setBmsErrorCodesString", "class_backend.html#af2fcdd85b15e60d1ddbc2bc48391a6f9", null ], + [ "setBmsFault", "class_backend.html#abc484080dc62f7f36a96c72586b25799", null ], + [ "setBmsTemp", "class_backend.html#a4d63556bfd846e2f327a766620e8b8df", null ], + [ "setBmsWarning", "class_backend.html#a1ed8e3394afa439f9f16710f7896649c", null ], + [ "setHighCellTemp", "class_backend.html#a1e83e3ce8504f024857446e12b8845b7", null ], + [ "setLat", "class_backend.html#ac6479865cb1424e3db4420da0877e215", null ], + [ "setLon", "class_backend.html#a23d341fe68297b82782e786210022585", null ], + [ "setLowCellTemp", "class_backend.html#aba6f3cfe6aa6137dc7351bb44dfa45a7", null ], + [ "setMcFault", "class_backend.html#abaf8de6f691d2259eb872b72537f7058", null ], + [ "setMcTemp", "class_backend.html#a157a36598b32143e812533cf87dd272f", null ], + [ "setMotorOn", "class_backend.html#ab4699e9d0f3fd20c7bf325e412d02031", null ], + [ "setMotorSpeed", "class_backend.html#a3ae0f65b4936686f6e41154c2ea9b7f8", null ], + [ "setMotorTemp", "class_backend.html#aa2bf5fa75e4d89a37ff1310fb1d88aa2", null ], + [ "setPackCurrent", "class_backend.html#a5ef79b5db160853a21fc658c662f99ce", null ], + [ "setPackSOC", "class_backend.html#af059700e1da309edb7e8e50d76141077", null ], + [ "setPackVoltage", "class_backend.html#adb6236eaa2d963d07cf80154e84f0f59", null ] +]; \ No newline at end of file diff --git a/docs/class_backend.png b/docs/class_backend.png new file mode 100644 index 0000000..b3f9960 Binary files /dev/null and b/docs/class_backend.png differ diff --git a/docs/classes.html b/docs/classes.html new file mode 100644 index 0000000..1a35d0e --- /dev/null +++ b/docs/classes.html @@ -0,0 +1,124 @@ + + + + + + + +BOLT Dash (C++): Class Index + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
BOLT Dash (C++) +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Class Index
+
+
+
B | G | O
+
+
+
B
+
Backend
+
+
G
+
GPSData
+
+
O
+
our_candata
+
+
+
+ + + + diff --git a/docs/clipboard.js b/docs/clipboard.js new file mode 100644 index 0000000..42c1fb0 --- /dev/null +++ b/docs/clipboard.js @@ -0,0 +1,61 @@ +/** + +The code below is based on the Doxygen Awesome project, see +https://github.com/jothepro/doxygen-awesome-css + +MIT License + +Copyright (c) 2021 - 2022 jothepro + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +let clipboard_title = "Copy to clipboard" +let clipboard_icon = `` +let clipboard_successIcon = `` +let clipboard_successDuration = 1000 + +$(function() { + if(navigator.clipboard) { + const fragments = document.getElementsByClassName("fragment") + for(const fragment of fragments) { + const clipboard_div = document.createElement("div") + clipboard_div.classList.add("clipboard") + clipboard_div.innerHTML = clipboard_icon + clipboard_div.title = clipboard_title + $(clipboard_div).click(function() { + const content = this.parentNode.cloneNode(true) + // filter out line number and folded fragments from file listings + content.querySelectorAll(".lineno, .ttc, .foldclosed").forEach((node) => { node.remove() }) + let text = content.textContent + // remove trailing newlines and trailing spaces from empty lines + text = text.replace(/^\s*\n/gm,'\n').replace(/\n*$/,'') + navigator.clipboard.writeText(text); + this.classList.add("success") + this.innerHTML = clipboard_successIcon + window.setTimeout(() => { // switch back to normal icon after timeout + this.classList.remove("success") + this.innerHTML = clipboard_icon + }, clipboard_successDuration); + }) + fragment.insertBefore(clipboard_div, fragment.firstChild) + } + } +}) diff --git a/docs/closed.png b/docs/closed.png new file mode 100644 index 0000000..98cc2c9 Binary files /dev/null and b/docs/closed.png differ diff --git a/docs/constants_8h_source.html b/docs/constants_8h_source.html new file mode 100644 index 0000000..bf1df0c --- /dev/null +++ b/docs/constants_8h_source.html @@ -0,0 +1,128 @@ + + + + + + + +BOLT Dash (C++): Bolt_Dash/constants.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
BOLT Dash (C++) +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
constants.h
+
+
+
1#define RPM_TO_SPEED (19.0 / 45.0 * 27.63 * M_PI / 1056)
+
2
+
3// Scaling for CAN data
+
4#define MOTOR_TEMPERATURE_SCALE (1.0 / 10.0)
+
5#define AUX_VOLTAGE_SCALE (1.0 / 10.0)
+
6#define AUX_PERCENT_SCALE (1.0 / 100.0)
+
7#define PACK_STATE_OF_CHARGE_SCALE (1.0 / 200.0)
+
8#define PACK_VOLTAGE_SCALE (1.0 / 10.0)
+
9#define PACK_CURRENT_SCALE (1.0 / 10.0)
+
10#define HIGH_CELL_TEMP_SCALE (1)
+
11#define LOW_CELL_TEMP_SCALE (1)
+
12#define BMS_TEMPERATURE_SCALE (1)
+
13#define MOTOR_SPEED_SCALE (1)
+
14#define BIKE_SPEED_SCALE (RPM_TO_SPEED)
+
15#define MC_TEMPERATURE_SCALE (1.0 / 10.0)
+
+
+ + + + diff --git a/docs/cookie.js b/docs/cookie.js new file mode 100644 index 0000000..53ad21d --- /dev/null +++ b/docs/cookie.js @@ -0,0 +1,58 @@ +/*! + Cookie helper functions + Copyright (c) 2023 Dimitri van Heesch + Released under MIT license. +*/ +let Cookie = { + cookie_namespace: 'doxygen_', + + readSetting(cookie,defVal) { + if (window.chrome) { + const val = localStorage.getItem(this.cookie_namespace+cookie) || + sessionStorage.getItem(this.cookie_namespace+cookie); + if (val) return val; + } else { + let myCookie = this.cookie_namespace+cookie+"="; + if (document.cookie) { + const index = document.cookie.indexOf(myCookie); + if (index != -1) { + const valStart = index + myCookie.length; + let valEnd = document.cookie.indexOf(";", valStart); + if (valEnd == -1) { + valEnd = document.cookie.length; + } + return document.cookie.substring(valStart, valEnd); + } + } + } + return defVal; + }, + + writeSetting(cookie,val,days=10*365) { // default days='forever', 0=session cookie, -1=delete + if (window.chrome) { + if (days==0) { + sessionStorage.setItem(this.cookie_namespace+cookie,val); + } else { + localStorage.setItem(this.cookie_namespace+cookie,val); + } + } else { + let date = new Date(); + date.setTime(date.getTime()+(days*24*60*60*1000)); + const expiration = days!=0 ? "expires="+date.toGMTString()+";" : ""; + document.cookie = this.cookie_namespace + cookie + "=" + + val + "; SameSite=Lax;" + expiration + "path=/"; + } + }, + + eraseSetting(cookie) { + if (window.chrome) { + if (localStorage.getItem(this.cookie_namespace+cookie)) { + localStorage.removeItem(this.cookie_namespace+cookie); + } else if (sessionStorage.getItem(this.cookie_namespace+cookie)) { + sessionStorage.removeItem(this.cookie_namespace+cookie); + } + } else { + this.writeSetting(cookie,'',-1); + } + }, +} diff --git a/docs/dir_9003ff251f894a0ca67807a78c4dd8f8.html b/docs/dir_9003ff251f894a0ca67807a78c4dd8f8.html new file mode 100644 index 0000000..cc14eff --- /dev/null +++ b/docs/dir_9003ff251f894a0ca67807a78c4dd8f8.html @@ -0,0 +1,129 @@ + + + + + + + +BOLT Dash (C++): Bolt_Dash Directory Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
BOLT Dash (C++) +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Bolt_Dash Directory Reference
+
+
+ + + + + + + + + + + + + + +

+Files

 backend.h
 
 can.h
 
 constants.h
 
 gpsprocessing.h
 
 nmea_decoder.h
 
 web.h
 
+
+
+ + + + diff --git a/docs/dir_9003ff251f894a0ca67807a78c4dd8f8.js b/docs/dir_9003ff251f894a0ca67807a78c4dd8f8.js new file mode 100644 index 0000000..51f1d8b --- /dev/null +++ b/docs/dir_9003ff251f894a0ca67807a78c4dd8f8.js @@ -0,0 +1,9 @@ +var dir_9003ff251f894a0ca67807a78c4dd8f8 = +[ + [ "backend.h", "backend_8h_source.html", null ], + [ "can.h", "can_8h_source.html", null ], + [ "constants.h", "constants_8h_source.html", null ], + [ "gpsprocessing.h", "gpsprocessing_8h_source.html", null ], + [ "nmea_decoder.h", "nmea__decoder_8h_source.html", null ], + [ "web.h", "web_8h_source.html", null ] +]; \ No newline at end of file diff --git a/docs/doc.svg b/docs/doc.svg new file mode 100644 index 0000000..0b928a5 --- /dev/null +++ b/docs/doc.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/docs/docd.svg b/docs/docd.svg new file mode 100644 index 0000000..ac18b27 --- /dev/null +++ b/docs/docd.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/docs/doxygen-awesome.css b/docs/doxygen-awesome.css new file mode 100644 index 0000000..6244a1e --- /dev/null +++ b/docs/doxygen-awesome.css @@ -0,0 +1,2681 @@ +/** + +Doxygen Awesome +https://github.com/jothepro/doxygen-awesome-css + +MIT License + +Copyright (c) 2021 - 2023 jothepro + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +html { + /* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */ + --primary-color: #1779c4; + --primary-dark-color: #335c80; + --primary-light-color: #70b1e9; + + /* page base colors */ + --page-background-color: #ffffff; + --page-foreground-color: #2f4153; + --page-secondary-foreground-color: #6f7e8e; + + /* color for all separators on the website: hr, borders, ... */ + --separator-color: #dedede; + + /* border radius for all rounded components. Will affect many components, like dropdowns, memitems, codeblocks, ... */ + --border-radius-large: 8px; + --border-radius-small: 4px; + --border-radius-medium: 6px; + + /* default spacings. Most components reference these values for spacing, to provide uniform spacing on the page. */ + --spacing-small: 5px; + --spacing-medium: 10px; + --spacing-large: 16px; + + /* default box shadow used for raising an element above the normal content. Used in dropdowns, search result, ... */ + --box-shadow: 0 2px 8px 0 rgba(0,0,0,.075); + + --odd-color: rgba(0,0,0,.028); + + /* font-families. will affect all text on the website + * font-family: the normal font for text, headlines, menus + * font-family-monospace: used for preformatted text in memtitle, code, fragments + */ + --font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif; + --font-family-monospace: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace; + + /* font sizes */ + --page-font-size: 15.6px; + --navigation-font-size: 14.4px; + --toc-font-size: 13.4px; + --code-font-size: 14px; /* affects code, fragment */ + --title-font-size: 22px; + + /* content text properties. These only affect the page content, not the navigation or any other ui elements */ + --content-line-height: 27px; + /* The content is centered and constraint in it's width. To make the content fill the whole page, set the variable to auto.*/ + --content-maxwidth: 1050px; + --table-line-height: 24px; + --toc-sticky-top: var(--spacing-medium); + --toc-width: 200px; + --toc-max-height: calc(100vh - 2 * var(--spacing-medium) - 85px); + + /* colors for various content boxes: @warning, @note, @deprecated @bug */ + --warning-color: #faf3d8; + --warning-color-dark: #f3a600; + --warning-color-darker: #5f4204; + --note-color: #e4f3ff; + --note-color-dark: #1879C4; + --note-color-darker: #274a5c; + --todo-color: #e4dafd; + --todo-color-dark: #5b2bdd; + --todo-color-darker: #2a0d72; + --deprecated-color: #ecf0f3; + --deprecated-color-dark: #5b6269; + --deprecated-color-darker: #43454a; + --bug-color: #f8d1cc; + --bug-color-dark: #b61825; + --bug-color-darker: #75070f; + --invariant-color: #d8f1e3; + --invariant-color-dark: #44b86f; + --invariant-color-darker: #265532; + + /* blockquote colors */ + --blockquote-background: #f8f9fa; + --blockquote-foreground: #636568; + + /* table colors */ + --tablehead-background: #f1f1f1; + --tablehead-foreground: var(--page-foreground-color); + + /* menu-display: block | none + * Visibility of the top navigation on screens >= 768px. On smaller screen the menu is always visible. + * `GENERATE_TREEVIEW` MUST be enabled! + */ + --menu-display: block; + + --menu-focus-foreground: var(--page-background-color); + --menu-focus-background: var(--primary-color); + --menu-selected-background: rgba(0,0,0,.05); + + + --header-background: var(--page-background-color); + --header-foreground: var(--page-foreground-color); + + /* searchbar colors */ + --searchbar-background: var(--side-nav-background); + --searchbar-foreground: var(--page-foreground-color); + + /* searchbar size + * (`searchbar-width` is only applied on screens >= 768px. + * on smaller screens the searchbar will always fill the entire screen width) */ + --searchbar-height: 33px; + --searchbar-width: 210px; + --searchbar-border-radius: var(--searchbar-height); + + /* code block colors */ + --code-background: #f5f5f5; + --code-foreground: var(--page-foreground-color); + + /* fragment colors */ + --fragment-background: #F8F9FA; + --fragment-foreground: #37474F; + --fragment-keyword: #bb6bb2; + --fragment-keywordtype: #8258b3; + --fragment-keywordflow: #d67c3b; + --fragment-token: #438a59; + --fragment-comment: #969696; + --fragment-link: #5383d6; + --fragment-preprocessor: #46aaa5; + --fragment-linenumber-color: #797979; + --fragment-linenumber-background: #f4f4f5; + --fragment-linenumber-border: #e3e5e7; + --fragment-lineheight: 20px; + + /* sidebar navigation (treeview) colors */ + --side-nav-background: #fbfbfb; + --side-nav-foreground: var(--page-foreground-color); + --side-nav-arrow-opacity: 0; + --side-nav-arrow-hover-opacity: 0.9; + + --toc-background: var(--side-nav-background); + --toc-foreground: var(--side-nav-foreground); + + /* height of an item in any tree / collapsible table */ + --tree-item-height: 30px; + + --memname-font-size: var(--code-font-size); + --memtitle-font-size: 18px; + + --webkit-scrollbar-size: 7px; + --webkit-scrollbar-padding: 4px; + --webkit-scrollbar-color: var(--separator-color); + + --animation-duration: .12s +} + +@media screen and (max-width: 767px) { + html { + --page-font-size: 16px; + --navigation-font-size: 16px; + --toc-font-size: 15px; + --code-font-size: 15px; /* affects code, fragment */ + --title-font-size: 22px; + } +} + +@media (prefers-color-scheme: dark) { + html:not(.light-mode) { + color-scheme: dark; + + --primary-color: #1982d2; + --primary-dark-color: #86a9c4; + --primary-light-color: #4779ac; + + --box-shadow: 0 2px 8px 0 rgba(0,0,0,.35); + + --odd-color: rgba(100,100,100,.06); + + --menu-selected-background: rgba(0,0,0,.4); + + --page-background-color: #1C1D1F; + --page-foreground-color: #d2dbde; + --page-secondary-foreground-color: #859399; + --separator-color: #38393b; + --side-nav-background: #252628; + + --code-background: #2a2c2f; + + --tablehead-background: #2a2c2f; + + --blockquote-background: #222325; + --blockquote-foreground: #7e8c92; + + --warning-color: #3b2e04; + --warning-color-dark: #f1b602; + --warning-color-darker: #ceb670; + --note-color: #163750; + --note-color-dark: #1982D2; + --note-color-darker: #dcf0fa; + --todo-color: #2a2536; + --todo-color-dark: #7661b3; + --todo-color-darker: #ae9ed6; + --deprecated-color: #2e323b; + --deprecated-color-dark: #738396; + --deprecated-color-darker: #abb0bd; + --bug-color: #2e1917; + --bug-color-dark: #ad2617; + --bug-color-darker: #f5b1aa; + --invariant-color: #303a35; + --invariant-color-dark: #76ce96; + --invariant-color-darker: #cceed5; + + --fragment-background: #282c34; + --fragment-foreground: #dbe4eb; + --fragment-keyword: #cc99cd; + --fragment-keywordtype: #ab99cd; + --fragment-keywordflow: #e08000; + --fragment-token: #7ec699; + --fragment-comment: #999999; + --fragment-link: #98c0e3; + --fragment-preprocessor: #65cabe; + --fragment-linenumber-color: #cccccc; + --fragment-linenumber-background: #35393c; + --fragment-linenumber-border: #1f1f1f; + } +} + +/* dark mode variables are defined twice, to support both the dark-mode without and with doxygen-awesome-darkmode-toggle.js */ +html.dark-mode { + color-scheme: dark; + + --primary-color: #1982d2; + --primary-dark-color: #86a9c4; + --primary-light-color: #4779ac; + + --box-shadow: 0 2px 8px 0 rgba(0,0,0,.30); + + --odd-color: rgba(100,100,100,.06); + + --menu-selected-background: rgba(0,0,0,.4); + + --page-background-color: #1C1D1F; + --page-foreground-color: #d2dbde; + --page-secondary-foreground-color: #859399; + --separator-color: #38393b; + --side-nav-background: #252628; + + --code-background: #2a2c2f; + + --tablehead-background: #2a2c2f; + + --blockquote-background: #222325; + --blockquote-foreground: #7e8c92; + + --warning-color: #3b2e04; + --warning-color-dark: #f1b602; + --warning-color-darker: #ceb670; + --note-color: #163750; + --note-color-dark: #1982D2; + --note-color-darker: #dcf0fa; + --todo-color: #2a2536; + --todo-color-dark: #7661b3; + --todo-color-darker: #ae9ed6; + --deprecated-color: #2e323b; + --deprecated-color-dark: #738396; + --deprecated-color-darker: #abb0bd; + --bug-color: #2e1917; + --bug-color-dark: #ad2617; + --bug-color-darker: #f5b1aa; + --invariant-color: #303a35; + --invariant-color-dark: #76ce96; + --invariant-color-darker: #cceed5; + + --fragment-background: #282c34; + --fragment-foreground: #dbe4eb; + --fragment-keyword: #cc99cd; + --fragment-keywordtype: #ab99cd; + --fragment-keywordflow: #e08000; + --fragment-token: #7ec699; + --fragment-comment: #999999; + --fragment-link: #98c0e3; + --fragment-preprocessor: #65cabe; + --fragment-linenumber-color: #cccccc; + --fragment-linenumber-background: #35393c; + --fragment-linenumber-border: #1f1f1f; +} + +body { + color: var(--page-foreground-color); + background-color: var(--page-background-color); + font-size: var(--page-font-size); +} + +body, table, div, p, dl, #nav-tree .label, .title, +.sm-dox a, .sm-dox a:hover, .sm-dox a:focus, #projectname, +.SelectItem, #MSearchField, .navpath li.navelem a, +.navpath li.navelem a:hover, p.reference, p.definition, div.toc li, div.toc h3 { + font-family: var(--font-family); +} + +h1, h2, h3, h4, h5 { + margin-top: 1em; + font-weight: 600; + line-height: initial; +} + +p, div, table, dl, p.reference, p.definition { + font-size: var(--page-font-size); +} + +p.reference, p.definition { + color: var(--page-secondary-foreground-color); +} + +a:link, a:visited, a:hover, a:focus, a:active { + color: var(--primary-color) !important; + font-weight: 500; + background: none; +} + +a.anchor { + scroll-margin-top: var(--spacing-large); + display: block; +} + +/* + Title and top navigation + */ + +#top { + background: var(--header-background); + border-bottom: 1px solid var(--separator-color); +} + +@media screen and (min-width: 768px) { + #top { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + align-items: center; + } +} + +#main-nav { + flex-grow: 5; + padding: var(--spacing-small) var(--spacing-medium); +} + +#titlearea { + width: auto; + padding: var(--spacing-medium) var(--spacing-large); + background: none; + color: var(--header-foreground); + border-bottom: none; +} + +@media screen and (max-width: 767px) { + #titlearea { + padding-bottom: var(--spacing-small); + } +} + +#titlearea table tbody tr { + height: auto !important; +} + +#projectname { + font-size: var(--title-font-size); + font-weight: 600; +} + +#projectnumber { + font-family: inherit; + font-size: 60%; +} + +#projectbrief { + font-family: inherit; + font-size: 80%; +} + +#projectlogo { + vertical-align: middle; +} + +#projectlogo img { + max-height: calc(var(--title-font-size) * 2); + margin-right: var(--spacing-small); +} + +.sm-dox, .tabs, .tabs2, .tabs3 { + background: none; + padding: 0; +} + +.tabs, .tabs2, .tabs3 { + border-bottom: 1px solid var(--separator-color); + margin-bottom: -1px; +} + +.main-menu-btn-icon, .main-menu-btn-icon:before, .main-menu-btn-icon:after { + background: var(--page-secondary-foreground-color); +} + +@media screen and (max-width: 767px) { + .sm-dox a span.sub-arrow { + background: var(--code-background); + } + + #main-menu a.has-submenu span.sub-arrow { + color: var(--page-secondary-foreground-color); + border-radius: var(--border-radius-medium); + } + + #main-menu a.has-submenu:hover span.sub-arrow { + color: var(--page-foreground-color); + } +} + +@media screen and (min-width: 768px) { + .sm-dox li, .tablist li { + display: var(--menu-display); + } + + .sm-dox a span.sub-arrow { + border-color: var(--header-foreground) transparent transparent transparent; + } + + .sm-dox a:hover span.sub-arrow { + border-color: var(--menu-focus-foreground) transparent transparent transparent; + } + + .sm-dox ul a span.sub-arrow { + border-color: transparent transparent transparent var(--page-foreground-color); + } + + .sm-dox ul a:hover span.sub-arrow { + border-color: transparent transparent transparent var(--menu-focus-foreground); + } +} + +.sm-dox ul { + background: var(--page-background-color); + box-shadow: var(--box-shadow); + border: 1px solid var(--separator-color); + border-radius: var(--border-radius-medium) !important; + padding: var(--spacing-small); + animation: ease-out 150ms slideInMenu; +} + +@keyframes slideInMenu { + from { + opacity: 0; + transform: translate(0px, -2px); + } + + to { + opacity: 1; + transform: translate(0px, 0px); + } +} + +.sm-dox ul a { + color: var(--page-foreground-color) !important; + background: var(--page-background-color); + font-size: var(--navigation-font-size); +} + +.sm-dox>li>ul:after { + border-bottom-color: var(--page-background-color) !important; +} + +.sm-dox>li>ul:before { + border-bottom-color: var(--separator-color) !important; +} + +.sm-dox ul a:hover, .sm-dox ul a:active, .sm-dox ul a:focus { + font-size: var(--navigation-font-size) !important; + color: var(--menu-focus-foreground) !important; + text-shadow: none; + background-color: var(--menu-focus-background); + border-radius: var(--border-radius-small) !important; +} + +.sm-dox a, .sm-dox a:focus, .tablist li, .tablist li a, .tablist li.current a { + text-shadow: none; + background: transparent; + background-image: none !important; + color: var(--header-foreground) !important; + font-weight: normal; + font-size: var(--navigation-font-size); + border-radius: var(--border-radius-small) !important; +} + +.sm-dox a:focus { + outline: auto; +} + +.sm-dox a:hover, .sm-dox a:active, .tablist li a:hover { + text-shadow: none; + font-weight: normal; + background: var(--menu-focus-background); + color: var(--menu-focus-foreground) !important; + border-radius: var(--border-radius-small) !important; + font-size: var(--navigation-font-size); +} + +.tablist li.current { + border-radius: var(--border-radius-small); + background: var(--menu-selected-background); +} + +.tablist li { + margin: var(--spacing-small) 0 var(--spacing-small) var(--spacing-small); +} + +.tablist a { + padding: 0 var(--spacing-large); +} + + +/* + Search box + */ + +#MSearchBox { + height: var(--searchbar-height); + background: var(--searchbar-background); + border-radius: var(--searchbar-border-radius); + border: 1px solid var(--separator-color); + overflow: hidden; + width: var(--searchbar-width); + position: relative; + box-shadow: none; + display: block; + margin-top: 0; +} + +/* until Doxygen 1.9.4 */ +.left img#MSearchSelect { + left: 0; + user-select: none; + padding-left: 8px; +} + +/* Doxygen 1.9.5 */ +.left span#MSearchSelect { + left: 0; + user-select: none; + margin-left: 8px; + padding: 0; +} + +.left #MSearchSelect[src$=".png"] { + padding-left: 0 +} + +.SelectionMark { + user-select: none; +} + +.tabs .left #MSearchSelect { + padding-left: 0; +} + +.tabs #MSearchBox { + position: absolute; + right: var(--spacing-medium); +} + +@media screen and (max-width: 767px) { + .tabs #MSearchBox { + position: relative; + right: 0; + margin-left: var(--spacing-medium); + margin-top: 0; + } +} + +#MSearchSelectWindow, #MSearchResultsWindow { + z-index: 9999; +} + +#MSearchBox.MSearchBoxActive { + border-color: var(--primary-color); + box-shadow: inset 0 0 0 1px var(--primary-color); +} + +#main-menu > li:last-child { + margin-right: 0; +} + +@media screen and (max-width: 767px) { + #main-menu > li:last-child { + height: 50px; + } +} + +#MSearchField { + font-size: var(--navigation-font-size); + height: calc(var(--searchbar-height) - 2px); + background: transparent; + width: calc(var(--searchbar-width) - 64px); +} + +.MSearchBoxActive #MSearchField { + color: var(--searchbar-foreground); +} + +#MSearchSelect { + top: calc(calc(var(--searchbar-height) / 2) - 11px); +} + +#MSearchBox span.left, #MSearchBox span.right { + background: none; + background-image: none; +} + +#MSearchBox span.right { + padding-top: calc(calc(var(--searchbar-height) / 2) - 12px); + position: absolute; + right: var(--spacing-small); +} + +.tabs #MSearchBox span.right { + top: calc(calc(var(--searchbar-height) / 2) - 12px); +} + +@keyframes slideInSearchResults { + from { + opacity: 0; + transform: translate(0, 15px); + } + + to { + opacity: 1; + transform: translate(0, 20px); + } +} + +#MSearchResultsWindow { + left: auto !important; + right: var(--spacing-medium); + border-radius: var(--border-radius-large); + border: 1px solid var(--separator-color); + transform: translate(0, 20px); + box-shadow: var(--box-shadow); + animation: ease-out 280ms slideInSearchResults; + background: var(--page-background-color); +} + +iframe#MSearchResults { + margin: 4px; +} + +iframe { + color-scheme: normal; +} + +@media (prefers-color-scheme: dark) { + html:not(.light-mode) iframe#MSearchResults { + filter: invert() hue-rotate(180deg); + } +} + +html.dark-mode iframe#MSearchResults { + filter: invert() hue-rotate(180deg); +} + +#MSearchResults .SRPage { + background-color: transparent; +} + +#MSearchResults .SRPage .SREntry { + font-size: 10pt; + padding: var(--spacing-small) var(--spacing-medium); +} + +#MSearchSelectWindow { + border: 1px solid var(--separator-color); + border-radius: var(--border-radius-medium); + box-shadow: var(--box-shadow); + background: var(--page-background-color); + padding-top: var(--spacing-small); + padding-bottom: var(--spacing-small); +} + +#MSearchSelectWindow a.SelectItem { + font-size: var(--navigation-font-size); + line-height: var(--content-line-height); + margin: 0 var(--spacing-small); + border-radius: var(--border-radius-small); + color: var(--page-foreground-color) !important; + font-weight: normal; +} + +#MSearchSelectWindow a.SelectItem:hover { + background: var(--menu-focus-background); + color: var(--menu-focus-foreground) !important; +} + +@media screen and (max-width: 767px) { + #MSearchBox { + margin-top: var(--spacing-medium); + margin-bottom: var(--spacing-medium); + width: calc(100vw - 30px); + } + + #main-menu > li:last-child { + float: none !important; + } + + #MSearchField { + width: calc(100vw - 110px); + } + + @keyframes slideInSearchResultsMobile { + from { + opacity: 0; + transform: translate(0, 15px); + } + + to { + opacity: 1; + transform: translate(0, 20px); + } + } + + #MSearchResultsWindow { + left: var(--spacing-medium) !important; + right: var(--spacing-medium); + overflow: auto; + transform: translate(0, 20px); + animation: ease-out 280ms slideInSearchResultsMobile; + width: auto !important; + } + + /* + * Overwrites for fixing the searchbox on mobile in doxygen 1.9.2 + */ + label.main-menu-btn ~ #searchBoxPos1 { + top: 3px !important; + right: 6px !important; + left: 45px; + display: flex; + } + + label.main-menu-btn ~ #searchBoxPos1 > #MSearchBox { + margin-top: 0; + margin-bottom: 0; + flex-grow: 2; + float: left; + } +} + +/* + Tree view + */ + +#side-nav { + padding: 0 !important; + background: var(--side-nav-background); + min-width: 8px; + max-width: 50vw; +} + +@media screen and (max-width: 767px) { + #side-nav { + display: none; + } + + #doc-content { + margin-left: 0 !important; + } +} + +#nav-tree { + background: transparent; + margin-right: 1px; +} + +#nav-tree .label { + font-size: var(--navigation-font-size); +} + +#nav-tree .item { + height: var(--tree-item-height); + line-height: var(--tree-item-height); + overflow: hidden; + text-overflow: ellipsis; +} + +#nav-tree .item > a:focus { + outline: none; +} + +#nav-sync { + bottom: 12px; + right: 12px; + top: auto !important; + user-select: none; +} + +#nav-tree .selected { + text-shadow: none; + background-image: none; + background-color: transparent; + position: relative; + color: var(--primary-color) !important; + font-weight: 500; +} + +#nav-tree .selected::after { + content: ""; + position: absolute; + top: 1px; + bottom: 1px; + left: 0; + width: 4px; + border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0; + background: var(--primary-color); +} + + +#nav-tree a { + color: var(--side-nav-foreground) !important; + font-weight: normal; +} + +#nav-tree a:focus { + outline-style: auto; +} + +#nav-tree .arrow { + opacity: var(--side-nav-arrow-opacity); + background: none; +} + +.arrow { + color: inherit; + cursor: pointer; + font-size: 45%; + vertical-align: middle; + margin-right: 2px; + font-family: serif; + height: auto; + text-align: right; +} + +#nav-tree div.item:hover .arrow, #nav-tree a:focus .arrow { + opacity: var(--side-nav-arrow-hover-opacity); +} + +#nav-tree .selected a { + color: var(--primary-color) !important; + font-weight: bolder; + font-weight: 600; +} + +.ui-resizable-e { + width: 4px; + background: transparent; + box-shadow: inset -1px 0 0 0 var(--separator-color); +} + +/* + Contents + */ + +div.header { + border-bottom: 1px solid var(--separator-color); + background-color: var(--page-background-color); + background-image: none; +} + +@media screen and (min-width: 1000px) { + #doc-content > div > div.contents, + .PageDoc > div.contents { + display: flex; + flex-direction: row-reverse; + flex-wrap: nowrap; + align-items: flex-start; + } + + div.contents .textblock { + min-width: 200px; + flex-grow: 1; + } +} + +div.contents, div.header .title, div.header .summary { + max-width: var(--content-maxwidth); +} + +div.contents, div.header .title { + line-height: initial; + margin: calc(var(--spacing-medium) + .2em) auto var(--spacing-medium) auto; +} + +div.header .summary { + margin: var(--spacing-medium) auto 0 auto; +} + +div.headertitle { + padding: 0; +} + +div.header .title { + font-weight: 600; + font-size: 225%; + padding: var(--spacing-medium) var(--spacing-large); + word-break: break-word; +} + +div.header .summary { + width: auto; + display: block; + float: none; + padding: 0 var(--spacing-large); +} + +td.memSeparator { + border-color: var(--separator-color); +} + +span.mlabel { + background: var(--primary-color); + border: none; + padding: 4px 9px; + border-radius: 12px; + margin-right: var(--spacing-medium); +} + +span.mlabel:last-of-type { + margin-right: 2px; +} + +div.contents { + padding: 0 var(--spacing-large); +} + +div.contents p, div.contents li { + line-height: var(--content-line-height); +} + +div.contents div.dyncontent { + margin: var(--spacing-medium) 0; +} + +@media (prefers-color-scheme: dark) { + html:not(.light-mode) div.contents div.dyncontent img, + html:not(.light-mode) div.contents center img, + html:not(.light-mode) div.contents > table img, + html:not(.light-mode) div.contents div.dyncontent iframe, + html:not(.light-mode) div.contents center iframe, + html:not(.light-mode) div.contents table iframe, + html:not(.light-mode) div.contents .dotgraph iframe { + filter: brightness(89%) hue-rotate(180deg) invert(); + } +} + +html.dark-mode div.contents div.dyncontent img, +html.dark-mode div.contents center img, +html.dark-mode div.contents > table img, +html.dark-mode div.contents div.dyncontent iframe, +html.dark-mode div.contents center iframe, +html.dark-mode div.contents table iframe, +html.dark-mode div.contents .dotgraph iframe + { + filter: brightness(89%) hue-rotate(180deg) invert(); +} + +h2.groupheader { + border-bottom: 0px; + color: var(--page-foreground-color); + box-shadow: + 100px 0 var(--page-background-color), + -100px 0 var(--page-background-color), + 100px 0.75px var(--separator-color), + -100px 0.75px var(--separator-color), + 500px 0 var(--page-background-color), + -500px 0 var(--page-background-color), + 500px 0.75px var(--separator-color), + -500px 0.75px var(--separator-color), + 900px 0 var(--page-background-color), + -900px 0 var(--page-background-color), + 900px 0.75px var(--separator-color), + -900px 0.75px var(--separator-color), + 1400px 0 var(--page-background-color), + -1400px 0 var(--page-background-color), + 1400px 0.75px var(--separator-color), + -1400px 0.75px var(--separator-color), + 1900px 0 var(--page-background-color), + -1900px 0 var(--page-background-color), + 1900px 0.75px var(--separator-color), + -1900px 0.75px var(--separator-color); +} + +blockquote { + margin: 0 var(--spacing-medium) 0 var(--spacing-medium); + padding: var(--spacing-small) var(--spacing-large); + background: var(--blockquote-background); + color: var(--blockquote-foreground); + border-left: 0; + overflow: visible; + border-radius: var(--border-radius-medium); + overflow: visible; + position: relative; +} + +blockquote::before, blockquote::after { + font-weight: bold; + font-family: serif; + font-size: 360%; + opacity: .15; + position: absolute; +} + +blockquote::before { + content: "“"; + left: -10px; + top: 4px; +} + +blockquote::after { + content: "”"; + right: -8px; + bottom: -25px; +} + +blockquote p { + margin: var(--spacing-small) 0 var(--spacing-medium) 0; +} +.paramname, .paramname em { + font-weight: 600; + color: var(--primary-dark-color); +} + +.paramname > code { + border: 0; +} + +table.params .paramname { + font-weight: 600; + font-family: var(--font-family-monospace); + font-size: var(--code-font-size); + padding-right: var(--spacing-small); + line-height: var(--table-line-height); +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px var(--primary-light-color); +} + +.alphachar a { + color: var(--page-foreground-color); +} + +.dotgraph { + max-width: 100%; + overflow-x: scroll; +} + +.dotgraph .caption { + position: sticky; + left: 0; +} + +/* Wrap Graphviz graphs with the `interactive_dotgraph` class if `INTERACTIVE_SVG = YES` */ +.interactive_dotgraph .dotgraph iframe { + max-width: 100%; +} + +/* + Table of Contents + */ + +div.contents .toc { + max-height: var(--toc-max-height); + min-width: var(--toc-width); + border: 0; + border-left: 1px solid var(--separator-color); + border-radius: 0; + background-color: var(--page-background-color); + box-shadow: none; + position: sticky; + top: var(--toc-sticky-top); + padding: 0 var(--spacing-large); + margin: var(--spacing-small) 0 var(--spacing-large) var(--spacing-large); +} + +div.toc h3 { + color: var(--toc-foreground); + font-size: var(--navigation-font-size); + margin: var(--spacing-large) 0 var(--spacing-medium) 0; +} + +div.toc li { + padding: 0; + background: none; + line-height: var(--toc-font-size); + margin: var(--toc-font-size) 0 0 0; +} + +div.toc li::before { + display: none; +} + +div.toc ul { + margin-top: 0 +} + +div.toc li a { + font-size: var(--toc-font-size); + color: var(--page-foreground-color) !important; + text-decoration: none; +} + +div.toc li a:hover, div.toc li a.active { + color: var(--primary-color) !important; +} + +div.toc li a.aboveActive { + color: var(--page-secondary-foreground-color) !important; +} + + +@media screen and (max-width: 999px) { + div.contents .toc { + max-height: 45vh; + float: none; + width: auto; + margin: 0 0 var(--spacing-medium) 0; + position: relative; + top: 0; + position: relative; + border: 1px solid var(--separator-color); + border-radius: var(--border-radius-medium); + background-color: var(--toc-background); + box-shadow: var(--box-shadow); + } + + div.contents .toc.interactive { + max-height: calc(var(--navigation-font-size) + 2 * var(--spacing-large)); + overflow: hidden; + } + + div.contents .toc > h3 { + -webkit-tap-highlight-color: transparent; + cursor: pointer; + position: sticky; + top: 0; + background-color: var(--toc-background); + margin: 0; + padding: var(--spacing-large) 0; + display: block; + } + + div.contents .toc.interactive > h3::before { + content: ""; + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 5px solid var(--primary-color); + display: inline-block; + margin-right: var(--spacing-small); + margin-bottom: calc(var(--navigation-font-size) / 4); + transform: rotate(-90deg); + transition: transform var(--animation-duration) ease-out; + } + + div.contents .toc.interactive.open > h3::before { + transform: rotate(0deg); + } + + div.contents .toc.interactive.open { + max-height: 45vh; + overflow: auto; + transition: max-height 0.2s ease-in-out; + } + + div.contents .toc a, div.contents .toc a.active { + color: var(--primary-color) !important; + } + + div.contents .toc a:hover { + text-decoration: underline; + } +} + +/* + Code & Fragments + */ + +code, div.fragment, pre.fragment { + border-radius: var(--border-radius-small); + border: 1px solid var(--separator-color); + overflow: hidden; +} + +code { + display: inline; + background: var(--code-background); + color: var(--code-foreground); + padding: 2px 6px; +} + +div.fragment, pre.fragment { + margin: var(--spacing-medium) 0; + padding: calc(var(--spacing-large) - (var(--spacing-large) / 6)) var(--spacing-large); + background: var(--fragment-background); + color: var(--fragment-foreground); + overflow-x: auto; +} + +@media screen and (max-width: 767px) { + div.fragment, pre.fragment { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + border-right: 0; + } + + .contents > div.fragment, + .textblock > div.fragment, + .textblock > pre.fragment, + .textblock > .tabbed > ul > li > div.fragment, + .textblock > .tabbed > ul > li > pre.fragment, + .contents > .doxygen-awesome-fragment-wrapper > div.fragment, + .textblock > .doxygen-awesome-fragment-wrapper > div.fragment, + .textblock > .doxygen-awesome-fragment-wrapper > pre.fragment, + .textblock > .tabbed > ul > li > .doxygen-awesome-fragment-wrapper > div.fragment, + .textblock > .tabbed > ul > li > .doxygen-awesome-fragment-wrapper > pre.fragment { + margin: var(--spacing-medium) calc(0px - var(--spacing-large)); + border-radius: 0; + border-left: 0; + } + + .textblock li > .fragment, + .textblock li > .doxygen-awesome-fragment-wrapper > .fragment { + margin: var(--spacing-medium) calc(0px - var(--spacing-large)); + } + + .memdoc li > .fragment, + .memdoc li > .doxygen-awesome-fragment-wrapper > .fragment { + margin: var(--spacing-medium) calc(0px - var(--spacing-medium)); + } + + .textblock ul, .memdoc ul { + overflow: initial; + } + + .memdoc > div.fragment, + .memdoc > pre.fragment, + dl dd > div.fragment, + dl dd pre.fragment, + .memdoc > .doxygen-awesome-fragment-wrapper > div.fragment, + .memdoc > .doxygen-awesome-fragment-wrapper > pre.fragment, + dl dd > .doxygen-awesome-fragment-wrapper > div.fragment, + dl dd .doxygen-awesome-fragment-wrapper > pre.fragment { + margin: var(--spacing-medium) calc(0px - var(--spacing-medium)); + border-radius: 0; + border-left: 0; + } +} + +code, code a, pre.fragment, div.fragment, div.fragment .line, div.fragment span, div.fragment .line a, div.fragment .line span { + font-family: var(--font-family-monospace); + font-size: var(--code-font-size) !important; +} + +div.line:after { + margin-right: var(--spacing-medium); +} + +div.fragment .line, pre.fragment { + white-space: pre; + word-wrap: initial; + line-height: var(--fragment-lineheight); +} + +div.fragment span.keyword { + color: var(--fragment-keyword); +} + +div.fragment span.keywordtype { + color: var(--fragment-keywordtype); +} + +div.fragment span.keywordflow { + color: var(--fragment-keywordflow); +} + +div.fragment span.stringliteral { + color: var(--fragment-token) +} + +div.fragment span.comment { + color: var(--fragment-comment); +} + +div.fragment a.code { + color: var(--fragment-link) !important; +} + +div.fragment span.preprocessor { + color: var(--fragment-preprocessor); +} + +div.fragment span.lineno { + display: inline-block; + width: 27px; + border-right: none; + background: var(--fragment-linenumber-background); + color: var(--fragment-linenumber-color); +} + +div.fragment span.lineno a { + background: none; + color: var(--fragment-link) !important; +} + +div.fragment > .line:first-child .lineno { + box-shadow: -999999px 0px 0 999999px var(--fragment-linenumber-background), -999998px 0px 0 999999px var(--fragment-linenumber-border); + background-color: var(--fragment-linenumber-background) !important; +} + +div.line { + border-radius: var(--border-radius-small); +} + +div.line.glow { + background-color: var(--primary-light-color); + box-shadow: none; +} + +/* + dl warning, attention, note, deprecated, bug, ... + */ + +dl.bug dt a, dl.deprecated dt a, dl.todo dt a { + font-weight: bold !important; +} + +dl.warning, dl.attention, dl.note, dl.deprecated, dl.bug, dl.invariant, dl.pre, dl.post, dl.todo, dl.remark { + padding: var(--spacing-medium); + margin: var(--spacing-medium) 0; + color: var(--page-background-color); + overflow: hidden; + margin-left: 0; + border-radius: var(--border-radius-small); +} + +dl.section dd { + margin-bottom: 2px; +} + +dl.warning, dl.attention { + background: var(--warning-color); + border-left: 8px solid var(--warning-color-dark); + color: var(--warning-color-darker); +} + +dl.warning dt, dl.attention dt { + color: var(--warning-color-dark); +} + +dl.note, dl.remark { + background: var(--note-color); + border-left: 8px solid var(--note-color-dark); + color: var(--note-color-darker); +} + +dl.note dt, dl.remark dt { + color: var(--note-color-dark); +} + +dl.todo { + background: var(--todo-color); + border-left: 8px solid var(--todo-color-dark); + color: var(--todo-color-darker); +} + +dl.todo dt a { + color: var(--todo-color-dark) !important; +} + +dl.bug dt a { + color: var(--todo-color-dark) !important; +} + +dl.bug { + background: var(--bug-color); + border-left: 8px solid var(--bug-color-dark); + color: var(--bug-color-darker); +} + +dl.bug dt a { + color: var(--bug-color-dark) !important; +} + +dl.deprecated { + background: var(--deprecated-color); + border-left: 8px solid var(--deprecated-color-dark); + color: var(--deprecated-color-darker); +} + +dl.deprecated dt a { + color: var(--deprecated-color-dark) !important; +} + +dl.section dd, dl.bug dd, dl.deprecated dd, dl.todo dd { + margin-inline-start: 0px; +} + +dl.invariant, dl.pre, dl.post { + background: var(--invariant-color); + border-left: 8px solid var(--invariant-color-dark); + color: var(--invariant-color-darker); +} + +dl.invariant dt, dl.pre dt, dl.post dt { + color: var(--invariant-color-dark); +} + +/* + memitem + */ + +div.memdoc, div.memproto, h2.memtitle { + box-shadow: none; + background-image: none; + border: none; +} + +div.memdoc { + padding: 0 var(--spacing-medium); + background: var(--page-background-color); +} + +h2.memtitle, div.memitem { + border: 1px solid var(--separator-color); + box-shadow: var(--box-shadow); +} + +h2.memtitle { + box-shadow: 0px var(--spacing-medium) 0 -1px var(--fragment-background), var(--box-shadow); +} + +div.memitem { + transition: none; +} + +div.memproto, h2.memtitle { + background: var(--fragment-background); +} + +h2.memtitle { + font-weight: 500; + font-size: var(--memtitle-font-size); + font-family: var(--font-family-monospace); + border-bottom: none; + border-top-left-radius: var(--border-radius-medium); + border-top-right-radius: var(--border-radius-medium); + word-break: break-all; + position: relative; +} + +h2.memtitle:after { + content: ""; + display: block; + background: var(--fragment-background); + height: var(--spacing-medium); + bottom: calc(0px - var(--spacing-medium)); + left: 0; + right: -14px; + position: absolute; + border-top-right-radius: var(--border-radius-medium); +} + +h2.memtitle > span.permalink { + font-size: inherit; +} + +h2.memtitle > span.permalink > a { + text-decoration: none; + padding-left: 3px; + margin-right: -4px; + user-select: none; + display: inline-block; + margin-top: -6px; +} + +h2.memtitle > span.permalink > a:hover { + color: var(--primary-dark-color) !important; +} + +a:target + h2.memtitle, a:target + h2.memtitle + div.memitem { + border-color: var(--primary-light-color); +} + +div.memitem { + border-top-right-radius: var(--border-radius-medium); + border-bottom-right-radius: var(--border-radius-medium); + border-bottom-left-radius: var(--border-radius-medium); + overflow: hidden; + display: block !important; +} + +div.memdoc { + border-radius: 0; +} + +div.memproto { + border-radius: 0 var(--border-radius-small) 0 0; + overflow: auto; + border-bottom: 1px solid var(--separator-color); + padding: var(--spacing-medium); + margin-bottom: -1px; +} + +div.memtitle { + border-top-right-radius: var(--border-radius-medium); + border-top-left-radius: var(--border-radius-medium); +} + +div.memproto table.memname { + font-family: var(--font-family-monospace); + color: var(--page-foreground-color); + font-size: var(--memname-font-size); + text-shadow: none; +} + +div.memproto div.memtemplate { + font-family: var(--font-family-monospace); + color: var(--primary-dark-color); + font-size: var(--memname-font-size); + margin-left: 2px; + text-shadow: none; +} + +table.mlabels, table.mlabels > tbody { + display: block; +} + +td.mlabels-left { + width: auto; +} + +td.mlabels-right { + margin-top: 3px; + position: sticky; + left: 0; +} + +table.mlabels > tbody > tr:first-child { + display: flex; + justify-content: space-between; + flex-wrap: wrap; +} + +.memname, .memitem span.mlabels { + margin: 0 +} + +/* + reflist + */ + +dl.reflist { + box-shadow: var(--box-shadow); + border-radius: var(--border-radius-medium); + border: 1px solid var(--separator-color); + overflow: hidden; + padding: 0; +} + + +dl.reflist dt, dl.reflist dd { + box-shadow: none; + text-shadow: none; + background-image: none; + border: none; + padding: 12px; +} + + +dl.reflist dt { + font-weight: 500; + border-radius: 0; + background: var(--code-background); + border-bottom: 1px solid var(--separator-color); + color: var(--page-foreground-color) +} + + +dl.reflist dd { + background: none; +} + +/* + Table + */ + +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname), +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody { + display: inline-block; + max-width: 100%; +} + +.contents > table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname):not(.classindex) { + margin-left: calc(0px - var(--spacing-large)); + margin-right: calc(0px - var(--spacing-large)); + max-width: calc(100% + 2 * var(--spacing-large)); +} + +table.fieldtable, +table.markdownTable tbody, +table.doxtable tbody { + border: none; + margin: var(--spacing-medium) 0; + box-shadow: 0 0 0 1px var(--separator-color); + border-radius: var(--border-radius-small); +} + +table.markdownTable, table.doxtable, table.fieldtable { + padding: 1px; +} + +table.doxtable caption { + display: block; +} + +table.fieldtable { + border-collapse: collapse; + width: 100%; +} + +th.markdownTableHeadLeft, +th.markdownTableHeadRight, +th.markdownTableHeadCenter, +th.markdownTableHeadNone, +table.doxtable th { + background: var(--tablehead-background); + color: var(--tablehead-foreground); + font-weight: 600; + font-size: var(--page-font-size); +} + +th.markdownTableHeadLeft:first-child, +th.markdownTableHeadRight:first-child, +th.markdownTableHeadCenter:first-child, +th.markdownTableHeadNone:first-child, +table.doxtable tr th:first-child { + border-top-left-radius: var(--border-radius-small); +} + +th.markdownTableHeadLeft:last-child, +th.markdownTableHeadRight:last-child, +th.markdownTableHeadCenter:last-child, +th.markdownTableHeadNone:last-child, +table.doxtable tr th:last-child { + border-top-right-radius: var(--border-radius-small); +} + +table.markdownTable td, +table.markdownTable th, +table.fieldtable td, +table.fieldtable th, +table.doxtable td, +table.doxtable th { + border: 1px solid var(--separator-color); + padding: var(--spacing-small) var(--spacing-medium); +} + +table.markdownTable td:last-child, +table.markdownTable th:last-child, +table.fieldtable td:last-child, +table.fieldtable th:last-child, +table.doxtable td:last-child, +table.doxtable th:last-child { + border-right: none; +} + +table.markdownTable td:first-child, +table.markdownTable th:first-child, +table.fieldtable td:first-child, +table.fieldtable th:first-child, +table.doxtable td:first-child, +table.doxtable th:first-child { + border-left: none; +} + +table.markdownTable tr:first-child td, +table.markdownTable tr:first-child th, +table.fieldtable tr:first-child td, +table.fieldtable tr:first-child th, +table.doxtable tr:first-child td, +table.doxtable tr:first-child th { + border-top: none; +} + +table.markdownTable tr:last-child td, +table.markdownTable tr:last-child th, +table.fieldtable tr:last-child td, +table.fieldtable tr:last-child th, +table.doxtable tr:last-child td, +table.doxtable tr:last-child th { + border-bottom: none; +} + +table.markdownTable tr, table.doxtable tr { + border-bottom: 1px solid var(--separator-color); +} + +table.markdownTable tr:last-child, table.doxtable tr:last-child { + border-bottom: none; +} + +.full_width_table table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) { + display: block; +} + +.full_width_table table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody { + display: table; + width: 100%; +} + +table.fieldtable th { + font-size: var(--page-font-size); + font-weight: 600; + background-image: none; + background-color: var(--tablehead-background); + color: var(--tablehead-foreground); +} + +table.fieldtable td.fieldtype, .fieldtable td.fieldname, .fieldtable td.fielddoc, .fieldtable th { + border-bottom: 1px solid var(--separator-color); + border-right: 1px solid var(--separator-color); +} + +table.fieldtable tr:last-child td:first-child { + border-bottom-left-radius: var(--border-radius-small); +} + +table.fieldtable tr:last-child td:last-child { + border-bottom-right-radius: var(--border-radius-small); +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: var(--primary-light-color); + box-shadow: none; +} + +table.memberdecls { + display: block; + -webkit-tap-highlight-color: transparent; +} + +table.memberdecls tr[class^='memitem'] { + font-family: var(--font-family-monospace); + font-size: var(--code-font-size); +} + +table.memberdecls tr[class^='memitem'] .memTemplParams { + font-family: var(--font-family-monospace); + font-size: var(--code-font-size); + color: var(--primary-dark-color); + white-space: normal; +} + +table.memberdecls .memItemLeft, +table.memberdecls .memItemRight, +table.memberdecls .memTemplItemLeft, +table.memberdecls .memTemplItemRight, +table.memberdecls .memTemplParams { + transition: none; + padding-top: var(--spacing-small); + padding-bottom: var(--spacing-small); + border-top: 1px solid var(--separator-color); + border-bottom: 1px solid var(--separator-color); + background-color: var(--fragment-background); +} + +table.memberdecls .memTemplItemLeft, +table.memberdecls .memTemplItemRight { + padding-top: 2px; +} + +table.memberdecls .memTemplParams { + border-bottom: 0; + border-left: 1px solid var(--separator-color); + border-right: 1px solid var(--separator-color); + border-radius: var(--border-radius-small) var(--border-radius-small) 0 0; + padding-bottom: var(--spacing-small); +} + +table.memberdecls .memTemplItemLeft { + border-radius: 0 0 0 var(--border-radius-small); + border-left: 1px solid var(--separator-color); + border-top: 0; +} + +table.memberdecls .memTemplItemRight { + border-radius: 0 0 var(--border-radius-small) 0; + border-right: 1px solid var(--separator-color); + padding-left: 0; + border-top: 0; +} + +table.memberdecls .memItemLeft { + border-radius: var(--border-radius-small) 0 0 var(--border-radius-small); + border-left: 1px solid var(--separator-color); + padding-left: var(--spacing-medium); + padding-right: 0; +} + +table.memberdecls .memItemRight { + border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0; + border-right: 1px solid var(--separator-color); + padding-right: var(--spacing-medium); + padding-left: 0; + +} + +table.memberdecls .mdescLeft, table.memberdecls .mdescRight { + background: none; + color: var(--page-foreground-color); + padding: var(--spacing-small) 0; +} + +table.memberdecls .memItemLeft, +table.memberdecls .memTemplItemLeft { + padding-right: var(--spacing-medium); +} + +table.memberdecls .memSeparator { + background: var(--page-background-color); + height: var(--spacing-large); + border: 0; + transition: none; +} + +table.memberdecls .groupheader { + margin-bottom: var(--spacing-large); +} + +table.memberdecls .inherit_header td { + padding: 0 0 var(--spacing-medium) 0; + text-indent: -12px; + color: var(--page-secondary-foreground-color); +} + +table.memberdecls img[src="closed.png"], +table.memberdecls img[src="open.png"], +div.dynheader img[src="open.png"], +div.dynheader img[src="closed.png"] { + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 5px solid var(--primary-color); + margin-top: 8px; + display: block; + float: left; + margin-left: -10px; + transition: transform var(--animation-duration) ease-out; +} + +table.memberdecls img { + margin-right: 10px; +} + +table.memberdecls img[src="closed.png"], +div.dynheader img[src="closed.png"] { + transform: rotate(-90deg); + +} + +.compoundTemplParams { + font-family: var(--font-family-monospace); + color: var(--primary-dark-color); + font-size: var(--code-font-size); +} + +@media screen and (max-width: 767px) { + + table.memberdecls .memItemLeft, + table.memberdecls .memItemRight, + table.memberdecls .mdescLeft, + table.memberdecls .mdescRight, + table.memberdecls .memTemplItemLeft, + table.memberdecls .memTemplItemRight, + table.memberdecls .memTemplParams { + display: block; + text-align: left; + padding-left: var(--spacing-large); + margin: 0 calc(0px - var(--spacing-large)) 0 calc(0px - var(--spacing-large)); + border-right: none; + border-left: none; + border-radius: 0; + white-space: normal; + } + + table.memberdecls .memItemLeft, + table.memberdecls .mdescLeft, + table.memberdecls .memTemplItemLeft { + border-bottom: 0; + padding-bottom: 0; + } + + table.memberdecls .memTemplItemLeft { + padding-top: 0; + } + + table.memberdecls .mdescLeft { + margin-bottom: calc(0px - var(--page-font-size)); + } + + table.memberdecls .memItemRight, + table.memberdecls .mdescRight, + table.memberdecls .memTemplItemRight { + border-top: 0; + padding-top: 0; + padding-right: var(--spacing-large); + overflow-x: auto; + } + + table.memberdecls tr[class^='memitem']:not(.inherit) { + display: block; + width: calc(100vw - 2 * var(--spacing-large)); + } + + table.memberdecls .mdescRight { + color: var(--page-foreground-color); + } + + table.memberdecls tr.inherit { + visibility: hidden; + } + + table.memberdecls tr[style="display: table-row;"] { + display: block !important; + visibility: visible; + width: calc(100vw - 2 * var(--spacing-large)); + animation: fade .5s; + } + + @keyframes fade { + 0% { + opacity: 0; + max-height: 0; + } + + 100% { + opacity: 1; + max-height: 200px; + } + } +} + + +/* + Horizontal Rule + */ + +hr { + margin-top: var(--spacing-large); + margin-bottom: var(--spacing-large); + height: 1px; + background-color: var(--separator-color); + border: 0; +} + +.contents hr { + box-shadow: 100px 0 var(--separator-color), + -100px 0 var(--separator-color), + 500px 0 var(--separator-color), + -500px 0 var(--separator-color), + 900px 0 var(--separator-color), + -900px 0 var(--separator-color), + 1400px 0 var(--separator-color), + -1400px 0 var(--separator-color), + 1900px 0 var(--separator-color), + -1900px 0 var(--separator-color); +} + +.contents img, .contents .center, .contents center, .contents div.image object { + max-width: 100%; + overflow: auto; +} + +@media screen and (max-width: 767px) { + .contents .dyncontent > .center, .contents > center { + margin-left: calc(0px - var(--spacing-large)); + margin-right: calc(0px - var(--spacing-large)); + max-width: calc(100% + 2 * var(--spacing-large)); + } +} + +/* + Directories + */ +div.directory { + border-top: 1px solid var(--separator-color); + border-bottom: 1px solid var(--separator-color); + width: auto; +} + +table.directory { + font-family: var(--font-family); + font-size: var(--page-font-size); + font-weight: normal; + width: 100%; +} + +table.directory td.entry, table.directory td.desc { + padding: calc(var(--spacing-small) / 2) var(--spacing-small); + line-height: var(--table-line-height); +} + +table.directory tr.even td:last-child { + border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0; +} + +table.directory tr.even td:first-child { + border-radius: var(--border-radius-small) 0 0 var(--border-radius-small); +} + +table.directory tr.even:last-child td:last-child { + border-radius: 0 var(--border-radius-small) 0 0; +} + +table.directory tr.even:last-child td:first-child { + border-radius: var(--border-radius-small) 0 0 0; +} + +table.directory td.desc { + min-width: 250px; +} + +table.directory tr.even { + background-color: var(--odd-color); +} + +table.directory tr.odd { + background-color: transparent; +} + +.icona { + width: auto; + height: auto; + margin: 0 var(--spacing-small); +} + +.icon { + background: var(--primary-color); + border-radius: var(--border-radius-small); + font-size: var(--page-font-size); + padding: calc(var(--page-font-size) / 5); + line-height: var(--page-font-size); + transform: scale(0.8); + height: auto; + width: var(--page-font-size); + user-select: none; +} + +.iconfopen, .icondoc, .iconfclosed { + background-position: center; + margin-bottom: 0; + height: var(--table-line-height); +} + +.icondoc { + filter: saturate(0.2); +} + +@media screen and (max-width: 767px) { + div.directory { + margin-left: calc(0px - var(--spacing-large)); + margin-right: calc(0px - var(--spacing-large)); + } +} + +@media (prefers-color-scheme: dark) { + html:not(.light-mode) .iconfopen, html:not(.light-mode) .iconfclosed { + filter: hue-rotate(180deg) invert(); + } +} + +html.dark-mode .iconfopen, html.dark-mode .iconfclosed { + filter: hue-rotate(180deg) invert(); +} + +/* + Class list + */ + +.classindex dl.odd { + background: var(--odd-color); + border-radius: var(--border-radius-small); +} + +.classindex dl.even { + background-color: transparent; +} + +/* + Class Index Doxygen 1.8 +*/ + +table.classindex { + margin-left: 0; + margin-right: 0; + width: 100%; +} + +table.classindex table div.ah { + background-image: none; + background-color: initial; + border-color: var(--separator-color); + color: var(--page-foreground-color); + box-shadow: var(--box-shadow); + border-radius: var(--border-radius-large); + padding: var(--spacing-small); +} + +div.qindex { + background-color: var(--odd-color); + border-radius: var(--border-radius-small); + border: 1px solid var(--separator-color); + padding: var(--spacing-small) 0; +} + +/* + Footer and nav-path + */ + +#nav-path { + width: 100%; +} + +#nav-path ul { + background-image: none; + background: var(--page-background-color); + border: none; + border-top: 1px solid var(--separator-color); + border-bottom: 1px solid var(--separator-color); + border-bottom: 0; + box-shadow: 0 0.75px 0 var(--separator-color); + font-size: var(--navigation-font-size); +} + +img.footer { + width: 60px; +} + +.navpath li.footer { + color: var(--page-secondary-foreground-color); +} + +address.footer { + color: var(--page-secondary-foreground-color); + margin-bottom: var(--spacing-large); +} + +#nav-path li.navelem { + background-image: none; + display: flex; + align-items: center; +} + +.navpath li.navelem a { + text-shadow: none; + display: inline-block; + color: var(--primary-color) !important; +} + +.navpath li.navelem b { + color: var(--primary-dark-color); + font-weight: 500; +} + +li.navelem { + padding: 0; + margin-left: -8px; +} + +li.navelem:first-child { + margin-left: var(--spacing-large); +} + +li.navelem:first-child:before { + display: none; +} + +#nav-path li.navelem:after { + content: ''; + border: 5px solid var(--page-background-color); + border-bottom-color: transparent; + border-right-color: transparent; + border-top-color: transparent; + transform: translateY(-1px) scaleY(4.2); + z-index: 10; + margin-left: 6px; +} + +#nav-path li.navelem:before { + content: ''; + border: 5px solid var(--separator-color); + border-bottom-color: transparent; + border-right-color: transparent; + border-top-color: transparent; + transform: translateY(-1px) scaleY(3.2); + margin-right: var(--spacing-small); +} + +.navpath li.navelem a:hover { + color: var(--primary-color); +} + +/* + Scrollbars for Webkit +*/ + +#nav-tree::-webkit-scrollbar, +div.fragment::-webkit-scrollbar, +pre.fragment::-webkit-scrollbar, +div.memproto::-webkit-scrollbar, +.contents center::-webkit-scrollbar, +.contents .center::-webkit-scrollbar, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar, +div.contents .toc::-webkit-scrollbar, +.contents .dotgraph::-webkit-scrollbar, +.contents .tabs-overview-container::-webkit-scrollbar { + background: transparent; + width: calc(var(--webkit-scrollbar-size) + var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); + height: calc(var(--webkit-scrollbar-size) + var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); +} + +#nav-tree::-webkit-scrollbar-thumb, +div.fragment::-webkit-scrollbar-thumb, +pre.fragment::-webkit-scrollbar-thumb, +div.memproto::-webkit-scrollbar-thumb, +.contents center::-webkit-scrollbar-thumb, +.contents .center::-webkit-scrollbar-thumb, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar-thumb, +div.contents .toc::-webkit-scrollbar-thumb, +.contents .dotgraph::-webkit-scrollbar-thumb, +.contents .tabs-overview-container::-webkit-scrollbar-thumb { + background-color: transparent; + border: var(--webkit-scrollbar-padding) solid transparent; + border-radius: calc(var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); + background-clip: padding-box; +} + +#nav-tree:hover::-webkit-scrollbar-thumb, +div.fragment:hover::-webkit-scrollbar-thumb, +pre.fragment:hover::-webkit-scrollbar-thumb, +div.memproto:hover::-webkit-scrollbar-thumb, +.contents center:hover::-webkit-scrollbar-thumb, +.contents .center:hover::-webkit-scrollbar-thumb, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody:hover::-webkit-scrollbar-thumb, +div.contents .toc:hover::-webkit-scrollbar-thumb, +.contents .dotgraph:hover::-webkit-scrollbar-thumb, +.contents .tabs-overview-container:hover::-webkit-scrollbar-thumb { + background-color: var(--webkit-scrollbar-color); +} + +#nav-tree::-webkit-scrollbar-track, +div.fragment::-webkit-scrollbar-track, +pre.fragment::-webkit-scrollbar-track, +div.memproto::-webkit-scrollbar-track, +.contents center::-webkit-scrollbar-track, +.contents .center::-webkit-scrollbar-track, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar-track, +div.contents .toc::-webkit-scrollbar-track, +.contents .dotgraph::-webkit-scrollbar-track, +.contents .tabs-overview-container::-webkit-scrollbar-track { + background: transparent; +} + +#nav-tree::-webkit-scrollbar-corner { + background-color: var(--side-nav-background); +} + +#nav-tree, +div.fragment, +pre.fragment, +div.memproto, +.contents center, +.contents .center, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody, +div.contents .toc { + overflow-x: auto; + overflow-x: overlay; +} + +#nav-tree { + overflow-x: auto; + overflow-y: auto; + overflow-y: overlay; +} + +/* + Scrollbars for Firefox +*/ + +#nav-tree, +div.fragment, +pre.fragment, +div.memproto, +.contents center, +.contents .center, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody, +div.contents .toc, +.contents .dotgraph, +.contents .tabs-overview-container { + scrollbar-width: thin; +} + +/* + Optional Dark mode toggle button +*/ + +doxygen-awesome-dark-mode-toggle { + display: inline-block; + margin: 0 0 0 var(--spacing-small); + padding: 0; + width: var(--searchbar-height); + height: var(--searchbar-height); + background: none; + border: none; + border-radius: var(--searchbar-height); + vertical-align: middle; + text-align: center; + line-height: var(--searchbar-height); + font-size: 22px; + display: flex; + align-items: center; + justify-content: center; + user-select: none; + cursor: pointer; +} + +doxygen-awesome-dark-mode-toggle > svg { + transition: transform var(--animation-duration) ease-in-out; +} + +doxygen-awesome-dark-mode-toggle:active > svg { + transform: scale(.5); +} + +doxygen-awesome-dark-mode-toggle:hover { + background-color: rgba(0,0,0,.03); +} + +html.dark-mode doxygen-awesome-dark-mode-toggle:hover { + background-color: rgba(0,0,0,.18); +} + +/* + Optional fragment copy button +*/ +.doxygen-awesome-fragment-wrapper { + position: relative; +} + +doxygen-awesome-fragment-copy-button { + opacity: 0; + background: var(--fragment-background); + width: 28px; + height: 28px; + position: absolute; + right: calc(var(--spacing-large) - (var(--spacing-large) / 2.5)); + top: calc(var(--spacing-large) - (var(--spacing-large) / 2.5)); + border: 1px solid var(--fragment-foreground); + cursor: pointer; + border-radius: var(--border-radius-small); + display: flex; + justify-content: center; + align-items: center; +} + +.doxygen-awesome-fragment-wrapper:hover doxygen-awesome-fragment-copy-button, doxygen-awesome-fragment-copy-button.success { + opacity: .28; +} + +doxygen-awesome-fragment-copy-button:hover, doxygen-awesome-fragment-copy-button.success { + opacity: 1 !important; +} + +doxygen-awesome-fragment-copy-button:active:not([class~=success]) svg { + transform: scale(.91); +} + +doxygen-awesome-fragment-copy-button svg { + fill: var(--fragment-foreground); + width: 18px; + height: 18px; +} + +doxygen-awesome-fragment-copy-button.success svg { + fill: rgb(14, 168, 14); +} + +doxygen-awesome-fragment-copy-button.success { + border-color: rgb(14, 168, 14); +} + +@media screen and (max-width: 767px) { + .textblock > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, + .textblock li > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, + .memdoc li > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, + .memdoc > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, + dl dd > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button { + right: 0; + } +} + +/* + Optional paragraph link button +*/ + +a.anchorlink { + font-size: 90%; + margin-left: var(--spacing-small); + color: var(--page-foreground-color) !important; + text-decoration: none; + opacity: .15; + display: none; + transition: opacity var(--animation-duration) ease-in-out, color var(--animation-duration) ease-in-out; +} + +a.anchorlink svg { + fill: var(--page-foreground-color); +} + +h3 a.anchorlink svg, h4 a.anchorlink svg { + margin-bottom: -3px; + margin-top: -4px; +} + +a.anchorlink:hover { + opacity: .45; +} + +h2:hover a.anchorlink, h1:hover a.anchorlink, h3:hover a.anchorlink, h4:hover a.anchorlink { + display: inline-block; +} + +/* + Optional tab feature +*/ + +.tabbed > ul { + padding-inline-start: 0px; + margin: 0; + padding: var(--spacing-small) 0; +} + +.tabbed > ul > li { + display: none; +} + +.tabbed > ul > li.selected { + display: block; +} + +.tabs-overview-container { + overflow-x: auto; + display: block; + overflow-y: visible; +} + +.tabs-overview { + border-bottom: 1px solid var(--separator-color); + display: flex; + flex-direction: row; +} + +@media screen and (max-width: 767px) { + .tabs-overview-container { + margin: 0 calc(0px - var(--spacing-large)); + } + .tabs-overview { + padding: 0 var(--spacing-large) + } +} + +.tabs-overview button.tab-button { + color: var(--page-foreground-color); + margin: 0; + border: none; + background: transparent; + padding: calc(var(--spacing-large) / 2) 0; + display: inline-block; + font-size: var(--page-font-size); + cursor: pointer; + box-shadow: 0 1px 0 0 var(--separator-color); + position: relative; + + -webkit-tap-highlight-color: transparent; +} + +.tabs-overview button.tab-button .tab-title::before { + display: block; + content: attr(title); + font-weight: 600; + height: 0; + overflow: hidden; + visibility: hidden; +} + +.tabs-overview button.tab-button .tab-title { + float: left; + white-space: nowrap; + font-weight: normal; + padding: calc(var(--spacing-large) / 2) var(--spacing-large); + border-radius: var(--border-radius-medium); + transition: background-color var(--animation-duration) ease-in-out, font-weight var(--animation-duration) ease-in-out; +} + +.tabs-overview button.tab-button:not(:last-child) .tab-title { + box-shadow: 8px 0 0 -7px var(--separator-color); +} + +.tabs-overview button.tab-button:hover .tab-title { + background: var(--separator-color); + box-shadow: none; +} + +.tabs-overview button.tab-button.active .tab-title { + font-weight: 600; +} + +.tabs-overview button.tab-button::after { + content: ''; + display: block; + position: absolute; + left: 0; + bottom: 0; + right: 0; + height: 0; + width: 0%; + margin: 0 auto; + border-radius: var(--border-radius-small) var(--border-radius-small) 0 0; + background-color: var(--primary-color); + transition: width var(--animation-duration) ease-in-out, height var(--animation-duration) ease-in-out; +} + +.tabs-overview button.tab-button.active::after { + width: 100%; + box-sizing: border-box; + height: 3px; +} + + +/* + Navigation Buttons +*/ + +.section_buttons:not(:empty) { + margin-top: calc(var(--spacing-large) * 3); +} + +.section_buttons table.markdownTable { + display: block; + width: 100%; +} + +.section_buttons table.markdownTable tbody { + display: table !important; + width: 100%; + box-shadow: none; + border-spacing: 10px; +} + +.section_buttons table.markdownTable td { + padding: 0; +} + +.section_buttons table.markdownTable th { + display: none; +} + +.section_buttons table.markdownTable tr.markdownTableHead { + border: none; +} + +.section_buttons tr th, .section_buttons tr td { + background: none; + border: none; + padding: var(--spacing-large) 0 var(--spacing-small); +} + +.section_buttons a { + display: inline-block; + border: 1px solid var(--separator-color); + border-radius: var(--border-radius-medium); + color: var(--page-secondary-foreground-color) !important; + text-decoration: none; + transition: color var(--animation-duration) ease-in-out, background-color var(--animation-duration) ease-in-out; +} + +.section_buttons a:hover { + color: var(--page-foreground-color) !important; + background-color: var(--odd-color); +} + +.section_buttons tr td.markdownTableBodyLeft a { + padding: var(--spacing-medium) var(--spacing-large) var(--spacing-medium) calc(var(--spacing-large) / 2); +} + +.section_buttons tr td.markdownTableBodyRight a { + padding: var(--spacing-medium) calc(var(--spacing-large) / 2) var(--spacing-medium) var(--spacing-large); +} + +.section_buttons tr td.markdownTableBodyLeft a::before, +.section_buttons tr td.markdownTableBodyRight a::after { + color: var(--page-secondary-foreground-color) !important; + display: inline-block; + transition: color .08s ease-in-out, transform .09s ease-in-out; +} + +.section_buttons tr td.markdownTableBodyLeft a::before { + content: '〈'; + padding-right: var(--spacing-large); +} + + +.section_buttons tr td.markdownTableBodyRight a::after { + content: '〉'; + padding-left: var(--spacing-large); +} + + +.section_buttons tr td.markdownTableBodyLeft a:hover::before { + color: var(--page-foreground-color) !important; + transform: translateX(-3px); +} + +.section_buttons tr td.markdownTableBodyRight a:hover::after { + color: var(--page-foreground-color) !important; + transform: translateX(3px); +} + +@media screen and (max-width: 450px) { + .section_buttons a { + width: 100%; + box-sizing: border-box; + } + + .section_buttons tr td:nth-of-type(1).markdownTableBodyLeft a { + border-radius: var(--border-radius-medium) 0 0 var(--border-radius-medium); + border-right: none; + } + + .section_buttons tr td:nth-of-type(2).markdownTableBodyRight a { + border-radius: 0 var(--border-radius-medium) var(--border-radius-medium) 0; + } +} diff --git a/docs/doxygen.css b/docs/doxygen.css new file mode 100644 index 0000000..3653ad2 --- /dev/null +++ b/docs/doxygen.css @@ -0,0 +1,1841 @@ +/* The standard CSS for doxygen 1.12.0*/ + +body { + background-color: white; + color: black; +} + +body, table, div, p, dl { + font-weight: 400; + font-size: 14px; + font-family: Roboto,sans-serif; + line-height: 22px; +} + +/* @group Heading Levels */ + +.title { + font-family: Roboto,sans-serif; + line-height: 28px; + font-size: 150%; + font-weight: bold; + margin: 10px 2px; +} + +h1.groupheader { + font-size: 150%; +} + +h2.groupheader { + border-bottom: 1px solid #879ECB; + color: #354C7B; + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; +} + +h3.groupheader { + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + +dt { + font-weight: bold; +} + +p.startli, p.startdd { + margin-top: 2px; +} + +th p.starttd, th p.intertd, th p.endtd { + font-size: 100%; + font-weight: 700; +} + +p.starttd { + margin-top: 0px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +p.interli { +} + +p.interdd { +} + +p.intertd { +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.navtab { + padding-right: 15px; + text-align: right; + line-height: 110%; +} + +div.navtab table { + border-spacing: 0; +} + +td.navtab { + padding-right: 6px; + padding-left: 6px; +} + +td.navtabHL { + background-image: url('tab_a.png'); + background-repeat:repeat-x; + padding-right: 6px; + padding-left: 6px; +} + +td.navtabHL a, td.navtabHL a:visited { + color: white; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); +} + +a.navtab { + font-weight: bold; +} + +div.qindex{ + text-align: center; + width: 100%; + line-height: 140%; + font-size: 130%; + color: #A0A0A0; +} + +#main-menu a:focus { + outline: auto; + z-index: 10; + position: relative; +} + +dt.alphachar{ + font-size: 180%; + font-weight: bold; +} + +.alphachar a{ + color: black; +} + +.alphachar a:hover, .alphachar a:visited{ + text-decoration: none; +} + +.classindex dl { + padding: 25px; + column-count:1 +} + +.classindex dd { + display:inline-block; + margin-left: 50px; + width: 90%; + line-height: 1.15em; +} + +.classindex dl.even { + background-color: white; +} + +.classindex dl.odd { + background-color: #F8F9FC; +} + +@media(min-width: 1120px) { + .classindex dl { + column-count:2 + } +} + +@media(min-width: 1320px) { + .classindex dl { + column-count:3 + } +} + + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: none; + background: linear-gradient(to bottom, transparent 0,transparent calc(100% - 1px), currentColor 100%); +} + +a:hover > span.arrow { + text-decoration: none; + background : #F9FAFC; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code, a.code:visited, a.line, a.line:visited { + color: #4665A2; +} + +a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { + color: #4665A2; +} + +a.code.hl_class { /* style for links to class names in code snippets */ } +a.code.hl_struct { /* style for links to struct names in code snippets */ } +a.code.hl_union { /* style for links to union names in code snippets */ } +a.code.hl_interface { /* style for links to interface names in code snippets */ } +a.code.hl_protocol { /* style for links to protocol names in code snippets */ } +a.code.hl_category { /* style for links to category names in code snippets */ } +a.code.hl_exception { /* style for links to exception names in code snippets */ } +a.code.hl_service { /* style for links to service names in code snippets */ } +a.code.hl_singleton { /* style for links to singleton names in code snippets */ } +a.code.hl_concept { /* style for links to concept names in code snippets */ } +a.code.hl_namespace { /* style for links to namespace names in code snippets */ } +a.code.hl_package { /* style for links to package names in code snippets */ } +a.code.hl_define { /* style for links to macro names in code snippets */ } +a.code.hl_function { /* style for links to function names in code snippets */ } +a.code.hl_variable { /* style for links to variable names in code snippets */ } +a.code.hl_typedef { /* style for links to typedef names in code snippets */ } +a.code.hl_enumvalue { /* style for links to enum value names in code snippets */ } +a.code.hl_enumeration { /* style for links to enumeration names in code snippets */ } +a.code.hl_signal { /* style for links to Qt signal names in code snippets */ } +a.code.hl_slot { /* style for links to Qt slot names in code snippets */ } +a.code.hl_friend { /* style for links to friend names in code snippets */ } +a.code.hl_dcop { /* style for links to KDE3 DCOP names in code snippets */ } +a.code.hl_property { /* style for links to property names in code snippets */ } +a.code.hl_event { /* style for links to event names in code snippets */ } +a.code.hl_sequence { /* style for links to sequence names in code snippets */ } +a.code.hl_dictionary { /* style for links to dictionary names in code snippets */ } + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +ul.check { + list-style:none; + text-indent: -16px; + padding-left: 38px; +} +li.unchecked:before { + content: "\2610\A0"; +} +li.checked:before { + content: "\2611\A0"; +} + +ol { + text-indent: 0px; +} + +ul { + text-indent: 0px; + overflow: visible; +} + +ul.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; + column-count: 3; + list-style-type: none; +} + +#side-nav ul { + overflow: visible; /* reset ul rule for scroll bar in GENERATE_TREEVIEW window */ +} + +#main-nav ul { + overflow: visible; /* reset ul rule for the navigation bar drop down lists */ +} + +.fragment { + text-align: left; + direction: ltr; + overflow-x: auto; + overflow-y: hidden; + position: relative; + min-height: 12px; + margin: 10px 0px; + padding: 10px 10px; + border: 1px solid #C4CFE5; + border-radius: 4px; + background-color: #FBFCFD; + color: black; +} + +pre.fragment { + word-wrap: break-word; + font-size: 10pt; + line-height: 125%; + font-family: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; +} + +.clipboard { + width: 24px; + height: 24px; + right: 5px; + top: 5px; + opacity: 0; + position: absolute; + display: inline; + overflow: auto; + fill: black; + justify-content: center; + align-items: center; + cursor: pointer; +} + +.clipboard.success { + border: 1px solid black; + border-radius: 4px; +} + +.fragment:hover .clipboard, .clipboard.success { + opacity: .28; +} + +.clipboard:hover, .clipboard.success { + opacity: 1 !important; +} + +.clipboard:active:not([class~=success]) svg { + transform: scale(.91); +} + +.clipboard.success svg { + fill: #2EC82E; +} + +.clipboard.success { + border-color: #2EC82E; +} + +div.line { + font-family: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; + font-size: 13px; + min-height: 13px; + line-height: 1.2; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -53px; + padding-left: 53px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line:after { + content:"\000A"; + white-space: pre; +} + +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + +span.fold { + margin-left: 5px; + margin-right: 1px; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; + display: inline-block; + width: 12px; + height: 12px; + background-repeat:no-repeat; + background-position:center; +} + +span.lineno { + padding-right: 4px; + margin-right: 9px; + text-align: right; + border-right: 2px solid #00FF00; + color: black; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a, span.lineno a:visited { + color: #4665A2; + background-color: #D8D8D8; +} + +span.lineno a:hover { + color: #4665A2; + background-color: #C8C8C8; +} + +.lineno { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +div.classindex ul { + list-style: none; + padding-left: 0; +} + +div.classindex span.ai { + display: inline-block; +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 8px; +} + +p.formulaDsp { + text-align: center; +} + +img.dark-mode-visible { + display: none; +} +img.light-mode-visible { + display: none; +} + +img.formulaInl, img.inline { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; + width: 104px; +} + +.compoundTemplParams { + color: #4665A2; + font-size: 80%; + line-height: 120%; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000; +} + +span.keywordtype { + color: #604020; +} + +span.keywordflow { + color: #E08000; +} + +span.comment { + color: #800000; +} + +span.preprocessor { + color: #806020; +} + +span.stringliteral { + color: #002080; +} + +span.charliteral { + color: #008080; +} + +span.xmlcdata { + color: black; +} + +span.vhdldigit { + color: #FF00FF; +} + +span.vhdlchar { + color: #000000; +} + +span.vhdlkeyword { + color: #700070; +} + +span.vhdllogic { + color: #FF0000; +} + +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +/* @end */ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #2D4068; +} + +th.dirtab { + background-color: #374F7F; + color: #FFFFFF; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memSeparator { + border-bottom: 1px solid #DEE4F0; + line-height: 1px; + margin: 0px; + padding: 0px; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memItemRight, .memTemplItemRight { + width: 100%; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; + font-size: 80%; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtitle { + padding: 8px; + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + margin-bottom: -1px; + background-image: url('nav_f.png'); + background-repeat: repeat-x; + background-color: #E2E8F2; + line-height: 1.25; + font-weight: 300; + float:left; +} + +.permalink +{ + font-size: 65%; + display: inline-block; + vertical-align: middle; +} + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 9px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + -webkit-transition: box-shadow 0.5s linear; + -moz-transition: box-shadow 0.5s linear; + -ms-transition: box-shadow 0.5s linear; + -o-transition: box-shadow 0.5s linear; + transition: box-shadow 0.5s linear; + display: table !important; + width: 100%; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; +} + +.memname { + font-weight: 400; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + background-color: #DFE5F1; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 4px; +} + +.overload { + font-family: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; + font-size: 65%; +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 10px 2px 10px; + border-top-width: 0; + background-image:url('nav_g.png'); + background-repeat:repeat-x; + background-color: white; + /* opera specific markup */ + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; + padding: 0px; + padding-bottom: 1px; +} + +.paramname { + white-space: nowrap; + padding: 0px; + padding-bottom: 1px; + margin-left: 2px; +} + +.paramname em { + color: #602020; + font-style: normal; + margin-right: 1px; +} + +.paramname .paramdefval { + font-family: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; +} + +.params .paramname, .retval .paramname, .tparams .paramname, .exception .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype, .tparams .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir, .tparams .paramdir { + font-family: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view inside a (index) page */ + +div.directory { + margin: 10px 0px; + border-top: 1px solid #9CAFD4; + border-bottom: 1px solid #9CAFD4; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.odd { + padding-left: 6px; + background-color: #F8F9FC; +} + +.directory tr.even { + padding-left: 6px; + background-color: white; +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; +} + +.arrow { + color: #9CAFD4; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + font-size: 80%; + display: inline-block; + width: 16px; + height: 22px; +} + +.icon { + font-family: Arial,Helvetica; + line-height: normal; + font-weight: bold; + font-size: 12px; + height: 14px; + width: 16px; + display: inline-block; + background-color: #728DC1; + color: white; + text-align: center; + border-radius: 4px; + margin-left: 2px; + margin-right: 2px; +} + +.icona { + width: 24px; + height: 22px; + display: inline-block; +} + +.iconfopen { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('folderopen.svg'); + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +.iconfclosed { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('folderclosed.svg'); + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +.icondoc { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('doc.svg'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +/* @end */ + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable caption { + caption-side: top; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +table.fieldtable { + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + border-radius: 4px; + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname, .fieldtable td.fieldinit { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fieldinit { + padding-top: 3px; + text-align: right; +} + + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image: url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + font-weight: 400; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image: url('tab_b.png'); + background-repeat:repeat-x; + background-position: 0 -5px; + height:30px; + line-height:30px; + color:#283A5D; + border:solid 1px #C2CDE4; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right:15px; + background-image:url('bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color: #364D7C; +} + +.navpath li.navelem a +{ + height:32px; + display:block; + outline: none; + color: #283A5D; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; +} + +.navpath li.navelem a:hover +{ + color: white; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); +} + +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color: #2A3D61; + font-size: 8pt; +} + + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +table.classindex +{ + margin: 10px; + white-space: nowrap; + margin-left: 3%; + margin-right: 3%; + width: 94%; + border: 0; + border-spacing: 0; + padding: 0; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + background-image: url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + margin: 0px; + border-bottom: 1px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +.PageDocRTL-title div.headertitle { + text-align: right; + direction: rtl; +} + +dl { + padding: 0 0 0 0; +} + +/* + +dl.section { + margin-left: 0px; + padding-left: 0px; +} + +dl.note { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #D0C000; +} + +dl.warning, dl.attention, dl.important { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #00D000; +} + +dl.deprecated { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #505050; +} + +dl.todo { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #00C0E0; +} + +dl.test { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #3030E0; +} + +dl.bug { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #C08050; +} + +*/ + +dl.bug dt a, dl.deprecated dt a, dl.todo dt a, dl.test a { + font-weight: bold !important; +} + +dl.warning, dl.attention, dl.important, dl.note, dl.deprecated, dl.bug, +dl.invariant, dl.pre, dl.post, dl.todo, dl.test, dl.remark { + padding: 10px; + margin: 10px 0px; + overflow: hidden; + margin-left: 0; + border-radius: 4px; +} + +dl.section dd { + margin-bottom: 2px; +} + +dl.warning, dl.attention, dl.important { + background: #f8d1cc; + border-left: 8px solid #b61825; + color: #75070f; +} + +dl.warning dt, dl.attention dt, dl.important dt { + color: #b61825; +} + +dl.note, dl.remark { + background: #faf3d8; + border-left: 8px solid #f3a600; + color: #5f4204; +} + +dl.note dt, dl.remark dt { + color: #f3a600; +} + +dl.todo { + background: #e4f3ff; + border-left: 8px solid #1879C4; + color: #274a5c; +} + +dl.todo dt { + color: #1879C4; +} + +dl.test { + background: #e8e8ff; + border-left: 8px solid #3939C4; + color: #1a1a5c; +} + +dl.test dt { + color: #3939C4; +} + +dl.bug dt a { + color: #5b2bdd !important; +} + +dl.bug { + background: #e4dafd; + border-left: 8px solid #5b2bdd; + color: #2a0d72; +} + +dl.bug dt a { + color: #5b2bdd !important; +} + +dl.deprecated { + background: #ecf0f3; + border-left: 8px solid #5b6269; + color: #43454a; +} + +dl.deprecated dt a { + color: #5b6269 !important; +} + +dl.note dd, dl.warning dd, dl.pre dd, dl.post dd, +dl.remark dd, dl.attention dd, dl.important dd, dl.invariant dd, +dl.bug dd, dl.deprecated dd, dl.todo dd, dl.test dd { + margin-inline-start: 0px; +} + +dl.invariant, dl.pre, dl.post { + background: #d8f1e3; + border-left: 8px solid #44b86f; + color: #265532; +} + +dl.invariant dt, dl.pre dt, dl.post dt { + color: #44b86f; +} + + +#projectrow +{ + height: 56px; +} + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectalign +{ + vertical-align: middle; + padding-left: 0.5em; +} + +#projectname +{ + font-size: 200%; + font-family: Tahoma,Arial,sans-serif; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font-size: 90%; + font-family: Tahoma,Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font-size: 50%; + font-family: 50% Tahoma,Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #5373B4; + background-color: white; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.plantumlgraph +{ + text-align: center; +} + +.diagraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; + text-align:right; + width:52px; +} + +dl.citelist dd { + margin:2px 0 2px 72px; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 8px 10px 10px; + width: 200px; +} + +div.toc li { + background: url("data:image/svg+xml;utf8,&%238595;") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,'DejaVu Sans',Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 Verdana,'DejaVu Sans',Geneva,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li[class^='level'] { + margin-left: 15px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.empty { + background-image: none; + margin-top: 0px; +} + +span.emoji { + /* font family used at the site: https://unicode.org/emoji/charts/full-emoji-list.html + * font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort; + */ +} + +span.obfuscator { + display: none; +} + +.inherit_header { + font-weight: bold; + color: gray; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0px 2px 5px; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 4px; +} + +/* tooltip related style info */ + +.ttc { + position: absolute; + display: none; +} + +#powerTip { + cursor: default; + /*white-space: nowrap;*/ + color: black; + background-color: white; + border: 1px solid gray; + border-radius: 4px 4px 4px 4px; + box-shadow: 1px 1px 7px gray; + display: none; + font-size: smaller; + max-width: 80%; + opacity: 0.9; + padding: 1ex 1em 1em; + position: absolute; + z-index: 2147483647; +} + +#powerTip div.ttdoc { + color: grey; + font-style: italic; +} + +#powerTip div.ttname a { + font-weight: bold; +} + +#powerTip a { + color: #4665A2; +} + +#powerTip div.ttname { + font-weight: bold; +} + +#powerTip div.ttdeci { + color: #006318; +} + +#powerTip div { + margin: 0px; + padding: 0px; + font-size: 12px; + font-family: Roboto,sans-serif; + line-height: 16px; +} + +#powerTip:before, #powerTip:after { + content: ""; + position: absolute; + margin: 0px; +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.s:after, #powerTip.s:before, +#powerTip.w:after, #powerTip.w:before, +#powerTip.e:after, #powerTip.e:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.nw:after, #powerTip.nw:before, +#powerTip.sw:after, #powerTip.sw:before { + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; +} + +#powerTip.n:after, #powerTip.s:after, +#powerTip.w:after, #powerTip.e:after, +#powerTip.nw:after, #powerTip.ne:after, +#powerTip.sw:after, #powerTip.se:after { + border-color: rgba(255, 255, 255, 0); +} + +#powerTip.n:before, #powerTip.s:before, +#powerTip.w:before, #powerTip.e:before, +#powerTip.nw:before, #powerTip.ne:before, +#powerTip.sw:before, #powerTip.se:before { + border-color: rgba(128, 128, 128, 0); +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.nw:after, #powerTip.nw:before { + top: 100%; +} + +#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { + border-top-color: white; + border-width: 10px; + margin: 0px -10px; +} +#powerTip.n:before, #powerTip.ne:before, #powerTip.nw:before { + border-top-color: gray; + border-width: 11px; + margin: 0px -11px; +} +#powerTip.n:after, #powerTip.n:before { + left: 50%; +} + +#powerTip.nw:after, #powerTip.nw:before { + right: 14px; +} + +#powerTip.ne:after, #powerTip.ne:before { + left: 14px; +} + +#powerTip.s:after, #powerTip.s:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.sw:after, #powerTip.sw:before { + bottom: 100%; +} + +#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { + border-bottom-color: white; + border-width: 10px; + margin: 0px -10px; +} + +#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { + border-bottom-color: gray; + border-width: 11px; + margin: 0px -11px; +} + +#powerTip.s:after, #powerTip.s:before { + left: 50%; +} + +#powerTip.sw:after, #powerTip.sw:before { + right: 14px; +} + +#powerTip.se:after, #powerTip.se:before { + left: 14px; +} + +#powerTip.e:after, #powerTip.e:before { + left: 100%; +} +#powerTip.e:after { + border-left-color: gray; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.e:before { + border-left-color: gray; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +#powerTip.w:after, #powerTip.w:before { + right: 100%; +} +#powerTip.w:after { + border-right-color: gray; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.w:before { + border-right-color: gray; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + +/* @group Markdown */ + +table.markdownTable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.markdownTable td, table.markdownTable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.markdownTable tr { +} + +th.markdownTableHeadLeft, th.markdownTableHeadRight, th.markdownTableHeadCenter, th.markdownTableHeadNone { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +th.markdownTableHeadLeft, td.markdownTableBodyLeft { + text-align: left +} + +th.markdownTableHeadRight, td.markdownTableBodyRight { + text-align: right +} + +th.markdownTableHeadCenter, td.markdownTableBodyCenter { + text-align: center +} + +tt, code, kbd, samp +{ + display: inline-block; +} +/* @end */ + +u { + text-decoration: underline; +} + +details>summary { + list-style-type: none; +} + +details > summary::-webkit-details-marker { + display: none; +} + +details>summary::before { + content: "\25ba"; + padding-right:4px; + font-size: 80%; +} + +details[open]>summary::before { + content: "\25bc"; + padding-right:4px; + font-size: 80%; +} + diff --git a/docs/doxygen.svg b/docs/doxygen.svg new file mode 100644 index 0000000..79a7635 --- /dev/null +++ b/docs/doxygen.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/doxygen_crawl.html b/docs/doxygen_crawl.html new file mode 100644 index 0000000..f8254dc --- /dev/null +++ b/docs/doxygen_crawl.html @@ -0,0 +1,134 @@ + + + +Validator / crawler helper + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/dynsections.js b/docs/dynsections.js new file mode 100644 index 0000000..3cc426a --- /dev/null +++ b/docs/dynsections.js @@ -0,0 +1,198 @@ +/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file + */ + +function toggleVisibility(linkObj) { + return dynsection.toggleVisibility(linkObj); +} + +let dynsection = { + + // helper function + updateStripes : function() { + $('table.directory tr'). + removeClass('even').filter(':visible:even').addClass('even'); + $('table.directory tr'). + removeClass('odd').filter(':visible:odd').addClass('odd'); + }, + + toggleVisibility : function(linkObj) { + const base = $(linkObj).attr('id'); + const summary = $('#'+base+'-summary'); + const content = $('#'+base+'-content'); + const trigger = $('#'+base+'-trigger'); + const src=$(trigger).attr('src'); + if (content.is(':visible')===true) { + content.hide(); + summary.show(); + $(linkObj).addClass('closed').removeClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); + } else { + content.show(); + summary.hide(); + $(linkObj).removeClass('closed').addClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); + } + return false; + }, + + toggleLevel : function(level) { + $('table.directory tr').each(function() { + const l = this.id.split('_').length-1; + const i = $('#img'+this.id.substring(3)); + const a = $('#arr'+this.id.substring(3)); + if (l'); + // add vertical lines to other rows + $('span[class=lineno]').not(':eq(0)').append(''); + // add toggle controls to lines with fold divs + $('div[class=foldopen]').each(function() { + // extract specific id to use + const id = $(this).attr('id').replace('foldopen',''); + // extract start and end foldable fragment attributes + const start = $(this).attr('data-start'); + const end = $(this).attr('data-end'); + // replace normal fold span with controls for the first line of a foldable fragment + $(this).find('span[class=fold]:first').replaceWith(''); + // append div for folded (closed) representation + $(this).after(''); + // extract the first line from the "open" section to represent closed content + const line = $(this).children().first().clone(); + // remove any glow that might still be active on the original line + $(line).removeClass('glow'); + if (start) { + // if line already ends with a start marker (e.g. trailing {), remove it + $(line).html($(line).html().replace(new RegExp('\\s*'+start+'\\s*$','g'),'')); + } + // replace minus with plus symbol + $(line).find('span[class=fold]').css('background-image',codefold.plusImg[relPath]); + // append ellipsis + $(line).append(' '+start+''+end); + // insert constructed line into closed div + $('#foldclosed'+id).html(line); + }); + }, +}; +/* @license-end */ diff --git a/docs/files.html b/docs/files.html new file mode 100644 index 0000000..31cde19 --- /dev/null +++ b/docs/files.html @@ -0,0 +1,123 @@ + + + + + + + +BOLT Dash (C++): File List + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
BOLT Dash (C++) +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
File List
+
+
+
Here is a list of all documented files with brief descriptions:
+
[detail level 12]
+ + + + + + + +
  Bolt_Dash
 backend.h
 can.h
 constants.h
 gpsprocessing.h
 nmea_decoder.h
 web.h
+
+
+
+ + + + diff --git a/docs/files_dup.js b/docs/files_dup.js new file mode 100644 index 0000000..e4fd016 --- /dev/null +++ b/docs/files_dup.js @@ -0,0 +1,4 @@ +var files_dup = +[ + [ "Bolt_Dash", "dir_9003ff251f894a0ca67807a78c4dd8f8.html", "dir_9003ff251f894a0ca67807a78c4dd8f8" ] +]; \ No newline at end of file diff --git a/docs/folderclosed.svg b/docs/folderclosed.svg new file mode 100644 index 0000000..b04bed2 --- /dev/null +++ b/docs/folderclosed.svg @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/docs/folderclosedd.svg b/docs/folderclosedd.svg new file mode 100644 index 0000000..52f0166 --- /dev/null +++ b/docs/folderclosedd.svg @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/docs/folderopen.svg b/docs/folderopen.svg new file mode 100644 index 0000000..f6896dd --- /dev/null +++ b/docs/folderopen.svg @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/docs/folderopend.svg b/docs/folderopend.svg new file mode 100644 index 0000000..2d1f06e --- /dev/null +++ b/docs/folderopend.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/docs/functions.html b/docs/functions.html new file mode 100644 index 0000000..710ad3b --- /dev/null +++ b/docs/functions.html @@ -0,0 +1,203 @@ + + + + + + + +BOLT Dash (C++): Class Members + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
BOLT Dash (C++) +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- a -

+ + +

- b -

+ + +

- h -

+ + +

- l -

+ + +

- m -

+ + +

- p -

+ + +

- s -

+
+
+ + + + diff --git a/docs/functions_func.html b/docs/functions_func.html new file mode 100644 index 0000000..79aacbc --- /dev/null +++ b/docs/functions_func.html @@ -0,0 +1,182 @@ + + + + + + + +BOLT Dash (C++): Class Members - Functions + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
BOLT Dash (C++) +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Here is a list of all documented functions with links to the class documentation for each member:
+ +

- a -

+ + +

- b -

+ + +

- h -

+ + +

- l -

+ + +

- m -

+ + +

- p -

+ + +

- s -

+
+
+ + + + diff --git a/docs/functions_vars.html b/docs/functions_vars.html new file mode 100644 index 0000000..d0cbf4b --- /dev/null +++ b/docs/functions_vars.html @@ -0,0 +1,132 @@ + + + + + + + +BOLT Dash (C++): Class Members - Variables + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
BOLT Dash (C++) +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Here is a list of all documented variables with links to the class documentation for each member:
+
+
+ + + + diff --git a/docs/gpsprocessing_8h_source.html b/docs/gpsprocessing_8h_source.html new file mode 100644 index 0000000..b6ceb93 --- /dev/null +++ b/docs/gpsprocessing_8h_source.html @@ -0,0 +1,127 @@ + + + + + + + +BOLT Dash (C++): Bolt_Dash/gpsprocessing.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
BOLT Dash (C++) +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
gpsprocessing.h
+
+
+
1#pragma once
+
2
+
3#include <cmath>
+
4#include <iomanip>
+
5#include <iostream>
+
6#include <libgpsmm.h>
+
7#include <mutex>
+
8#include <unistd.h>
+
9
+
10extern std::mutex gps_m;
+
11extern double gps_lat;
+
12extern double gps_lon;
+
13
+
14int gpsMain();
+
+
+ + + + diff --git a/docs/hierarchy.html b/docs/hierarchy.html new file mode 100644 index 0000000..d1e4066 --- /dev/null +++ b/docs/hierarchy.html @@ -0,0 +1,120 @@ + + + + + + + +BOLT Dash (C++): Class Hierarchy + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
BOLT Dash (C++) +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Class Hierarchy
+
+
+
This inheritance list is sorted roughly, but not completely, alphabetically:
+
[detail level 12]
+ + + + +
 CGPSData
 Cour_candataThis is a struct that contains all the data that we get from the CAN bus and is used in the dash project
 CQObject
 CBackendA class to represent the C++ backend of the dash which can be included in QML to give the frontend access
+
+
+
+ + + + diff --git a/docs/hierarchy.js b/docs/hierarchy.js new file mode 100644 index 0000000..9c95b81 --- /dev/null +++ b/docs/hierarchy.js @@ -0,0 +1,8 @@ +var hierarchy = +[ + [ "GPSData", "struct_g_p_s_data.html", null ], + [ "our_candata", "structour__candata.html", null ], + [ "QObject", null, [ + [ "Backend", "class_backend.html", null ] + ] ] +]; \ No newline at end of file diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..aab4af6 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,113 @@ + + + + + + + +BOLT Dash (C++): Main Page + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
BOLT Dash (C++) +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
BOLT Dash (C++) Documentation
+
+
+ +
+
+ + + + diff --git a/docs/jquery.js b/docs/jquery.js new file mode 100644 index 0000000..875ada7 --- /dev/null +++ b/docs/jquery.js @@ -0,0 +1,204 @@ +/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e} +var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp( +"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"�":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType +}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c +)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){ +return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll( +":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id") +)&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push( +"\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test( +a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null, +null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne +).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for( +var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n; +return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0, +r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r] +,C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each( +function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r, +"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})} +),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each( +"blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0",options:{classes:{},disabled:!1,create:null},_createWidget:function(t,e){e=y(e||this.defaultElement||this)[0],this.element=y(e),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=y(),this.hoverable=y(),this.focusable=y(),this.classesElementLookup={},e!==this&&(y.data(e,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t +){t.target===e&&this.destroy()}}),this.document=y(e.style?e.ownerDocument:e.document||e),this.window=y(this.document[0].defaultView||this.document[0].parentWindow)),this.options=y.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:y.noop,_create:y.noop,_init:y.noop,destroy:function(){var i=this;this._destroy(),y.each(this.classesElementLookup,function(t,e){i._removeClass(e,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:y.noop,widget:function(){return this.element},option:function(t,e){var i,s,n,o=t;if(0===arguments.length)return y.widget.extend({},this.options);if("string"==typeof t)if(o={},t=(i=t.split(".")).shift(),i.length){for(s=o[t +]=y.widget.extend({},this.options[t]),n=0;n
"),i=e.children()[0];return y("body").append(e),t=i.offsetWidth,e.css("overflow","scroll"),t===(i=i.offsetWidth)&&(i=e[0].clientWidth),e.remove(),s=t-i}, +getScrollInfo:function(t){var e=t.isWindow||t.isDocument?"":t.element.css("overflow-x"),i=t.isWindow||t.isDocument?"":t.element.css("overflow-y"),e="scroll"===e||"auto"===e&&t.widthx(D(s),D(n))?o.important="horizontal":o.important="vertical",p.using.call(this,t,o)}),h.offset(y.extend(l,{using:t}))})},y.ui.position={fit:{left:function(t,e){var i=e.within, +s=i.isWindow?i.scrollLeft:i.offset.left,n=i.width,o=t.left-e.collisionPosition.marginLeft,h=s-o,a=o+e.collisionWidth-n-s;e.collisionWidth>n?0n?0=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),y.ui.plugin={add:function(t,e,i){var s,n=y.ui[t].prototype;for(s in i)n.plugins[s]=n.plugins[s]||[],n.plugins[s].push([e,i[s]])},call:function(t,e,i,s){var n,o=t.plugins[e];if(o&&(s||t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType))for(n=0;n").css({overflow:"hidden",position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})), +this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,t={marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom"),marginLeft:this.originalElement.css("marginLeft")},this.element.css(t),this.originalElement.css("margin",0),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css(t),this._proportionallyResize()),this._setupHandles(),e.autoHide&&y(this.element).on("mouseenter",function(){e.disabled||(i._removeClass("ui-resizable-autohide"),i._handles.show())}).on("mouseleave",function(){e.disabled||i.resizing||(i._addClass("ui-resizable-autohide"),i._handles.hide())}),this._mouseInit()},_destroy:function(){this._mouseDestroy(),this._addedHandles.remove();function t(t){y(t +).removeData("resizable").removeData("ui-resizable").off(".resizable")}var e;return this.elementIsWrapper&&(t(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),t(this.originalElement),this},_setOption:function(t,e){switch(this._super(t,e),t){case"handles":this._removeHandles(),this._setupHandles();break;case"aspectRatio":this._aspectRatio=!!e}},_setupHandles:function(){var t,e,i,s,n,o=this.options,h=this;if(this.handles=o.handles||(y(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=y(),this._addedHandles=y(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),i=this.handles.split( +","),this.handles={},e=0;e"),this._addClass(n,"ui-resizable-handle "+s),n.css({zIndex:o.zIndex}),this.handles[t]=".ui-resizable-"+t,this.element.children(this.handles[t]).length||(this.element.append(n),this._addedHandles=this._addedHandles.add(n));this._renderAxis=function(t){var e,i,s;for(e in t=t||this.element,this.handles)this.handles[e].constructor===String?this.handles[e]=this.element.children(this.handles[e]).first().show():(this.handles[e].jquery||this.handles[e].nodeType)&&(this.handles[e]=y(this.handles[e]),this._on(this.handles[e],{mousedown:h._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(i=y(this.handles[e],this.element),s=/sw|ne|nw|se|n|s/.test(e)?i.outerHeight():i.outerWidth(),i=["padding",/ne|nw|n/.test(e)?"Top":/se|sw|s/.test(e)?"Bottom":/^e$/.test(e)?"Right":"Left"].join(""),t.css(i,s),this._proportionallyResize()),this._handles=this._handles.add( +this.handles[e])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.on("mouseover",function(){h.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),h.axis=n&&n[1]?n[1]:"se")}),o.autoHide&&(this._handles.hide(),this._addClass("ui-resizable-autohide"))},_removeHandles:function(){this._addedHandles.remove()},_mouseCapture:function(t){var e,i,s=!1;for(e in this.handles)(i=y(this.handles[e])[0])!==t.target&&!y.contains(i,t.target)||(s=!0);return!this.options.disabled&&s},_mouseStart:function(t){var e,i,s=this.options,n=this.element;return this.resizing=!0,this._renderProxy(),e=this._num(this.helper.css("left")),i=this._num(this.helper.css("top")),s.containment&&(e+=y(s.containment).scrollLeft()||0,i+=y(s.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:e,top:i},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{ +width:n.width(),height:n.height()},this.originalSize=this._helper?{width:n.outerWidth(),height:n.outerHeight()}:{width:n.width(),height:n.height()},this.sizeDiff={width:n.outerWidth()-n.width(),height:n.outerHeight()-n.height()},this.originalPosition={left:e,top:i},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio="number"==typeof s.aspectRatio?s.aspectRatio:this.originalSize.width/this.originalSize.height||1,s=y(".ui-resizable-"+this.axis).css("cursor"),y("body").css("cursor","auto"===s?this.axis+"-resize":s),this._addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(t){var e=this.originalMousePosition,i=this.axis,s=t.pageX-e.left||0,e=t.pageY-e.top||0,i=this._change[i];return this._updatePrevProperties(),i&&(e=i.apply(this,[t,s,e]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(e=this._updateRatio(e,t)),e=this._respectSize(e,t),this._updateCache(e),this._propagate("resize",t),e=this._applyChanges(), +!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),y.isEmptyObject(e)||(this._updatePrevProperties(),this._trigger("resize",t,this.ui()),this._applyChanges())),!1},_mouseStop:function(t){this.resizing=!1;var e,i,s,n=this.options,o=this;return this._helper&&(s=(e=(i=this._proportionallyResizeElements).length&&/textarea/i.test(i[0].nodeName))&&this._hasScroll(i[0],"left")?0:o.sizeDiff.height,i=e?0:o.sizeDiff.width,e={width:o.helper.width()-i,height:o.helper.height()-s},i=parseFloat(o.element.css("left"))+(o.position.left-o.originalPosition.left)||null,s=parseFloat(o.element.css("top"))+(o.position.top-o.originalPosition.top)||null,n.animate||this.element.css(y.extend(e,{top:s,left:i})),o.helper.height(o.size.height),o.helper.width(o.size.width),this._helper&&!n.animate&&this._proportionallyResize()),y("body").css("cursor","auto"),this._removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){ +this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var t={};return this.position.top!==this.prevPosition.top&&(t.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(t.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(t.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(t.height=this.size.height+"px"),this.helper.css(t),t},_updateVirtualBoundaries:function(t){var e,i,s=this.options,n={minWidth:this._isNumber(s.minWidth)?s.minWidth:0,maxWidth:this._isNumber(s.maxWidth)?s.maxWidth:1/0,minHeight:this._isNumber(s.minHeight)?s.minHeight:0,maxHeight:this._isNumber(s.maxHeight)?s.maxHeight:1/0};(this._aspectRatio||t)&&(e=n.minHeight*this.aspectRatio,i=n.minWidth/this.aspectRatio,s=n.maxHeight*this.aspectRatio,t=n.maxWidth/this.aspectRatio,e>n.minWidth&&(n.minWidth=e),i>n.minHeight&&(n.minHeight=i),st.width,h=this._isNumber(t.height)&&e.minHeight&&e.minHeight>t.height,a=this.originalPosition.left+this.originalSize.width,r=this.originalPosition.top+this.originalSize.height +,l=/sw|nw|w/.test(i),i=/nw|ne|n/.test(i);return o&&(t.width=e.minWidth),h&&(t.height=e.minHeight),s&&(t.width=e.maxWidth),n&&(t.height=e.maxHeight),o&&l&&(t.left=a-e.minWidth),s&&l&&(t.left=a-e.maxWidth),h&&i&&(t.top=r-e.minHeight),n&&i&&(t.top=r-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_getPaddingPlusBorderDimensions:function(t){for(var e=0,i=[],s=[t.css("borderTopWidth"),t.css("borderRightWidth"),t.css("borderBottomWidth"),t.css("borderLeftWidth")],n=[t.css("paddingTop"),t.css("paddingRight"),t.css("paddingBottom"),t.css("paddingLeft")];e<4;e++)i[e]=parseFloat(s[e])||0,i[e]+=parseFloat(n[e])||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var t,e=0,i=this.helper||this.element;e").css({overflow:"hidden"}),this._addClass(this.helper,this._helper),this.helper.css({width:this.element.outerWidth(),height:this.element.outerHeight(),position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++e.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize;return{left:this.originalPosition.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize;return{top:this.originalPosition.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(t,e,i){return y.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,e,i]))},sw:function(t,e, +i){return y.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,e,i]))},ne:function(t,e,i){return y.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,e,i]))},nw:function(t,e,i){return y.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,e,i]))}},_propagate:function(t,e){y.ui.plugin.call(this,t,[e,this.ui()]),"resize"!==t&&this._trigger(t,e,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),y.ui.plugin.add("resizable","animate",{stop:function(e){var i=y(this).resizable("instance"),t=i.options,s=i._proportionallyResizeElements,n=s.length&&/textarea/i.test(s[0].nodeName),o=n&&i._hasScroll(s[0],"left")?0:i.sizeDiff.height,h=n?0:i.sizeDiff.width,n={width:i.size.width-h,height:i.size.height-o},h=parseFloat(i.element.css("left"))+(i.position.left-i.originalPosition.left +)||null,o=parseFloat(i.element.css("top"))+(i.position.top-i.originalPosition.top)||null;i.element.animate(y.extend(n,o&&h?{top:o,left:h}:{}),{duration:t.animateDuration,easing:t.animateEasing,step:function(){var t={width:parseFloat(i.element.css("width")),height:parseFloat(i.element.css("height")),top:parseFloat(i.element.css("top")),left:parseFloat(i.element.css("left"))};s&&s.length&&y(s[0]).css({width:t.width,height:t.height}),i._updateCache(t),i._propagate("resize",e)}})}}),y.ui.plugin.add("resizable","containment",{start:function(){var i,s,n=y(this).resizable("instance"),t=n.options,e=n.element,o=t.containment,h=o instanceof y?o.get(0):/parent/.test(o)?e.parent().get(0):o;h&&(n.containerElement=y(h),/document/.test(o)||o===document?(n.containerOffset={left:0,top:0},n.containerPosition={left:0,top:0},n.parentData={element:y(document),left:0,top:0,width:y(document).width(),height:y(document).height()||document.body.parentNode.scrollHeight}):(i=y(h),s=[],y(["Top","Right","Left","Bottom"]).each(function(t,e +){s[t]=n._num(i.css("padding"+e))}),n.containerOffset=i.offset(),n.containerPosition=i.position(),n.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},t=n.containerOffset,e=n.containerSize.height,o=n.containerSize.width,o=n._hasScroll(h,"left")?h.scrollWidth:o,e=n._hasScroll(h)?h.scrollHeight:e,n.parentData={element:h,left:t.left,top:t.top,width:o,height:e}))},resize:function(t){var e=y(this).resizable("instance"),i=e.options,s=e.containerOffset,n=e.position,o=e._aspectRatio||t.shiftKey,h={top:0,left:0},a=e.containerElement,t=!0;a[0]!==document&&/static/.test(a.css("position"))&&(h=s),n.left<(e._helper?s.left:0)&&(e.size.width=e.size.width+(e._helper?e.position.left-s.left:e.position.left-h.left),o&&(e.size.height=e.size.width/e.aspectRatio,t=!1),e.position.left=i.helper?s.left:0),n.top<(e._helper?s.top:0)&&(e.size.height=e.size.height+(e._helper?e.position.top-s.top:e.position.top),o&&(e.size.width=e.size.height*e.aspectRatio,t=!1),e.position.top=e._helper?s.top:0), +i=e.containerElement.get(0)===e.element.parent().get(0),n=/relative|absolute/.test(e.containerElement.css("position")),i&&n?(e.offset.left=e.parentData.left+e.position.left,e.offset.top=e.parentData.top+e.position.top):(e.offset.left=e.element.offset().left,e.offset.top=e.element.offset().top),n=Math.abs(e.sizeDiff.width+(e._helper?e.offset.left-h.left:e.offset.left-s.left)),s=Math.abs(e.sizeDiff.height+(e._helper?e.offset.top-h.top:e.offset.top-s.top)),n+e.size.width>=e.parentData.width&&(e.size.width=e.parentData.width-n,o&&(e.size.height=e.size.width/e.aspectRatio,t=!1)),s+e.size.height>=e.parentData.height&&(e.size.height=e.parentData.height-s,o&&(e.size.width=e.size.height*e.aspectRatio,t=!1)),t||(e.position.left=e.prevPosition.left,e.position.top=e.prevPosition.top,e.size.width=e.prevSize.width,e.size.height=e.prevSize.height)},stop:function(){var t=y(this).resizable("instance"),e=t.options,i=t.containerOffset,s=t.containerPosition,n=t.containerElement,o=y(t.helper),h=o.offset(),a=o.outerWidth( +)-t.sizeDiff.width,o=o.outerHeight()-t.sizeDiff.height;t._helper&&!e.animate&&/relative/.test(n.css("position"))&&y(this).css({left:h.left-s.left-i.left,width:a,height:o}),t._helper&&!e.animate&&/static/.test(n.css("position"))&&y(this).css({left:h.left-s.left-i.left,width:a,height:o})}}),y.ui.plugin.add("resizable","alsoResize",{start:function(){var t=y(this).resizable("instance").options;y(t.alsoResize).each(function(){var t=y(this);t.data("ui-resizable-alsoresize",{width:parseFloat(t.width()),height:parseFloat(t.height()),left:parseFloat(t.css("left")),top:parseFloat(t.css("top"))})})},resize:function(t,i){var e=y(this).resizable("instance"),s=e.options,n=e.originalSize,o=e.originalPosition,h={height:e.size.height-n.height||0,width:e.size.width-n.width||0,top:e.position.top-o.top||0,left:e.position.left-o.left||0};y(s.alsoResize).each(function(){var t=y(this),s=y(this).data("ui-resizable-alsoresize"),n={},e=t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];y.each(e, +function(t,e){var i=(s[e]||0)+(h[e]||0);i&&0<=i&&(n[e]=i||null)}),t.css(n)})},stop:function(){y(this).removeData("ui-resizable-alsoresize")}}),y.ui.plugin.add("resizable","ghost",{start:function(){var t=y(this).resizable("instance"),e=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:e.height,width:e.width,margin:0,left:0,top:0}),t._addClass(t.ghost,"ui-resizable-ghost"),!1!==y.uiBackCompat&&"string"==typeof t.options.ghost&&t.ghost.addClass(this.options.ghost),t.ghost.appendTo(t.helper)},resize:function(){var t=y(this).resizable("instance");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=y(this).resizable("instance");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),y.ui.plugin.add("resizable","grid",{resize:function(){var t,e=y(this).resizable("instance"),i=e.options,s=e.size,n=e.originalSize,o=e.originalPosition,h=e.axis,a="number"==typeof i.grid?[i.grid,i.grid]:i.grid,r=a[0 +]||1,l=a[1]||1,u=Math.round((s.width-n.width)/r)*r,p=Math.round((s.height-n.height)/l)*l,d=n.width+u,c=n.height+p,f=i.maxWidth&&i.maxWidthd,s=i.minHeight&&i.minHeight>c;i.grid=a,m&&(d+=r),s&&(c+=l),f&&(d-=r),g&&(c-=l),/^(se|s|e)$/.test(h)?(e.size.width=d,e.size.height=c):/^(ne)$/.test(h)?(e.size.width=d,e.size.height=c,e.position.top=o.top-p):/^(sw)$/.test(h)?(e.size.width=d,e.size.height=c,e.position.left=o.left-u):((c-l<=0||d-r<=0)&&(t=e._getPaddingPlusBorderDimensions(this)),0=f[g]?0:Math.min(f[g],n));!a&&1-1){ +targetElements.on(evt+EVENT_NAMESPACE,function elementToggle(event){$.powerTip.toggle(this,event)})}else{targetElements.on(evt+EVENT_NAMESPACE,function elementOpen(event){$.powerTip.show(this,event)})}});$.each(options.closeEvents,function(idx,evt){if($.inArray(evt,options.openEvents)<0){targetElements.on(evt+EVENT_NAMESPACE,function elementClose(event){$.powerTip.hide(this,!isMouseEvent(event))})}});targetElements.on("keydown"+EVENT_NAMESPACE,function elementKeyDown(event){if(event.keyCode===27){$.powerTip.hide(this,true)}})}return targetElements};$.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",popupClass:null,intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false,openEvents:["mouseenter","focus"],closeEvents:["mouseleave","blur"]};$.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se", +"n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};$.powerTip={show:function apiShowTip(element,event){if(isMouseEvent(event)){trackMouse(event);session.previousX=event.pageX;session.previousY=event.pageY;$(element).data(DATA_DISPLAYCONTROLLER).show()}else{$(element).first().data(DATA_DISPLAYCONTROLLER).show(true,true)}return element},reposition:function apiResetPosition(element){$(element).first().data(DATA_DISPLAYCONTROLLER).resetPosition();return element},hide:function apiCloseTip(element,immediate){var displayController;immediate=element?immediate:true;if(element){displayController=$(element).first().data(DATA_DISPLAYCONTROLLER)}else if( +session.activeHover){displayController=session.activeHover.data(DATA_DISPLAYCONTROLLER)}if(displayController){displayController.hide(immediate)}return element},toggle:function apiToggle(element,event){if(session.activeHover&&session.activeHover.is(element)){$.powerTip.hide(element,!isMouseEvent(event))}else{$.powerTip.show(element,event)}return element}};$.powerTip.showTip=$.powerTip.show;$.powerTip.closeTip=$.powerTip.hide;function CSSCoordinates(){var me=this;me.top="auto";me.left="auto";me.right="auto";me.bottom="auto";me.set=function(property,value){if($.isNumeric(value)){me[property]=Math.round(value)}}}function DisplayController(element,options,tipController){var hoverTimer=null,myCloseDelay=null;function openTooltip(immediate,forceOpen){cancelTimer();if(!element.data(DATA_HASACTIVEHOVER)){if(!immediate){session.tipOpenImminent=true;hoverTimer=setTimeout(function intentDelay(){hoverTimer=null;checkForIntent()},options.intentPollInterval)}else{if(forceOpen){element.data(DATA_FORCEDOPEN,true)} +closeAnyDelayed();tipController.showTip(element)}}else{cancelClose()}}function closeTooltip(disableDelay){if(myCloseDelay){myCloseDelay=session.closeDelayTimeout=clearTimeout(myCloseDelay);session.delayInProgress=false}cancelTimer();session.tipOpenImminent=false;if(element.data(DATA_HASACTIVEHOVER)){element.data(DATA_FORCEDOPEN,false);if(!disableDelay){session.delayInProgress=true;session.closeDelayTimeout=setTimeout(function closeDelay(){session.closeDelayTimeout=null;tipController.hideTip(element);session.delayInProgress=false;myCloseDelay=null},options.closeDelay);myCloseDelay=session.closeDelayTimeout}else{tipController.hideTip(element)}}}function checkForIntent(){var xDifference=Math.abs(session.previousX-session.currentX),yDifference=Math.abs(session.previousY-session.currentY),totalDifference=xDifference+yDifference;if(totalDifference",{id:options.popupId});if($body.length===0){$body=$("body")}$body.append(tipElement);session.tooltips=session.tooltips?session.tooltips.add(tipElement):tipElement}if(options.followMouse){if(!tipElement.data(DATA_HASMOUSEMOVE)){$document.on("mousemove"+EVENT_NAMESPACE,positionTipOnCursor);$window.on("scroll"+EVENT_NAMESPACE,positionTipOnCursor);tipElement.data(DATA_HASMOUSEMOVE,true)}}function beginShowTip(element){element.data(DATA_HASACTIVEHOVER,true);tipElement.queue(function queueTipInit(next){showTip(element);next()})}function showTip(element){var tipContent;if(!element.data(DATA_HASACTIVEHOVER)){return}if( +session.isTipOpen){if(!session.isClosing){hideTip(session.activeHover)}tipElement.delay(100).queue(function queueTipAgain(next){showTip(element);next()});return}element.trigger("powerTipPreRender");tipContent=getTooltipContent(element);if(tipContent){tipElement.empty().append(tipContent)}else{return}element.trigger("powerTipRender");session.activeHover=element;session.isTipOpen=true;tipElement.data(DATA_MOUSEONTOTIP,options.mouseOnToPopup);tipElement.addClass(options.popupClass);if(!options.followMouse||element.data(DATA_FORCEDOPEN)){positionTipOnElement(element);session.isFixedTipOpen=true}else{positionTipOnCursor()}if(!element.data(DATA_FORCEDOPEN)&&!options.followMouse){$document.on("click"+EVENT_NAMESPACE,function documentClick(event){var target=event.target;if(target!==element[0]){if(options.mouseOnToPopup){if(target!==tipElement[0]&&!$.contains(tipElement[0],target)){$.powerTip.hide()}}else{$.powerTip.hide()}}})}if(options.mouseOnToPopup&&!options.manual){tipElement.on("mouseenter"+EVENT_NAMESPACE, +function tipMouseEnter(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).cancel()}});tipElement.on("mouseleave"+EVENT_NAMESPACE,function tipMouseLeave(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).hide()}})}tipElement.fadeIn(options.fadeInTime,function fadeInCallback(){if(!session.desyncTimeout){session.desyncTimeout=setInterval(closeDesyncedTip,500)}element.trigger("powerTipOpen")})}function hideTip(element){session.isClosing=true;session.isTipOpen=false;session.desyncTimeout=clearInterval(session.desyncTimeout);element.data(DATA_HASACTIVEHOVER,false);element.data(DATA_FORCEDOPEN,false);$document.off("click"+EVENT_NAMESPACE);tipElement.off(EVENT_NAMESPACE);tipElement.fadeOut(options.fadeOutTime,function fadeOutCallback(){var coords=new CSSCoordinates;session.activeHover=null;session.isClosing=false;session.isFixedTipOpen=false;tipElement.removeClass();coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset); +tipElement.css(coords);element.trigger("powerTipClose")})}function positionTipOnCursor(){var tipWidth,tipHeight,coords,collisions,collisionCount;if(!session.isFixedTipOpen&&(session.isTipOpen||session.tipOpenImminent&&tipElement.data(DATA_HASMOUSEMOVE))){tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=new CSSCoordinates;coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset);collisions=getViewportCollisions(coords,tipWidth,tipHeight);if(collisions!==Collision.none){collisionCount=countFlags(collisions);if(collisionCount===1){if(collisions===Collision.right){coords.set("left",session.scrollLeft+session.windowWidth-tipWidth)}else if(collisions===Collision.bottom){coords.set("top",session.scrollTop+session.windowHeight-tipHeight)}}else{coords.set("left",session.currentX-tipWidth-options.offset);coords.set("top",session.currentY-tipHeight-options.offset)}}tipElement.css(coords)}}function positionTipOnElement(element){var priorityList, +finalPlacement;if(options.smartPlacement||options.followMouse&&element.data(DATA_FORCEDOPEN)){priorityList=$.fn.powerTip.smartPlacementLists[options.placement];$.each(priorityList,function(idx,pos){var collisions=getViewportCollisions(placeTooltip(element,pos),tipElement.outerWidth(),tipElement.outerHeight());finalPlacement=pos;return collisions!==Collision.none})}else{placeTooltip(element,options.placement);finalPlacement=options.placement}tipElement.removeClass("w nw sw e ne se n s w se-alt sw-alt ne-alt nw-alt");tipElement.addClass(finalPlacement)}function placeTooltip(element,placement){var iterationCount=0,tipWidth,tipHeight,coords=new CSSCoordinates;coords.set("top",0);coords.set("left",0);tipElement.css(coords);do{tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=placementCalculator.compute(element,placement,tipWidth,tipHeight,options.offset);tipElement.css(coords)}while(++iterationCount<=5&&(tipWidth!==tipElement.outerWidth()||tipHeight!==tipElement.outerHeight())); +return coords}function closeDesyncedTip(){var isDesynced=false,hasDesyncableCloseEvent=$.grep(["mouseleave","mouseout","blur","focusout"],function(eventType){return $.inArray(eventType,options.closeEvents)!==-1}).length>0;if(session.isTipOpen&&!session.isClosing&&!session.delayInProgress&&hasDesyncableCloseEvent){if(session.activeHover.data(DATA_HASACTIVEHOVER)===false||session.activeHover.is(":disabled")){isDesynced=true}else if(!isMouseOver(session.activeHover)&&!session.activeHover.is(":focus")&&!session.activeHover.data(DATA_FORCEDOPEN)){if(tipElement.data(DATA_MOUSEONTOTIP)){if(!isMouseOver(tipElement)){isDesynced=true}}else{isDesynced=true}}if(isDesynced){hideTip(session.activeHover)}}}this.showTip=beginShowTip;this.hideTip=hideTip;this.resetPosition=positionTipOnElement}function isSvgElement(element){return Boolean(window.SVGElement&&element[0]instanceof SVGElement)}function isMouseEvent(event){return Boolean(event&&$.inArray(event.type,MOUSE_EVENTS)>-1&&typeof event.pageX==="number")} +function initTracking(){if(!session.mouseTrackingActive){session.mouseTrackingActive=true;getViewportDimensions();$(getViewportDimensions);$document.on("mousemove"+EVENT_NAMESPACE,trackMouse);$window.on("resize"+EVENT_NAMESPACE,trackResize);$window.on("scroll"+EVENT_NAMESPACE,trackScroll)}}function getViewportDimensions(){session.scrollLeft=$window.scrollLeft();session.scrollTop=$window.scrollTop();session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackResize(){session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackScroll(){var x=$window.scrollLeft(),y=$window.scrollTop();if(x!==session.scrollLeft){session.currentX+=x-session.scrollLeft;session.scrollLeft=x}if(y!==session.scrollTop){session.currentY+=y-session.scrollTop;session.scrollTop=y}}function trackMouse(event){session.currentX=event.pageX;session.currentY=event.pageY}function isMouseOver(element){var elementPosition=element.offset(),elementBox=element[0].getBoundingClientRect(), +elementWidth=elementBox.right-elementBox.left,elementHeight=elementBox.bottom-elementBox.top;return session.currentX>=elementPosition.left&&session.currentX<=elementPosition.left+elementWidth&&session.currentY>=elementPosition.top&&session.currentY<=elementPosition.top+elementHeight}function getTooltipContent(element){var tipText=element.data(DATA_POWERTIP),tipObject=element.data(DATA_POWERTIPJQ),tipTarget=element.data(DATA_POWERTIPTARGET),targetElement,content;if(tipText){if($.isFunction(tipText)){tipText=tipText.call(element[0])}content=tipText}else if(tipObject){if($.isFunction(tipObject)){tipObject=tipObject.call(element[0])}if(tipObject.length>0){content=tipObject.clone(true,true)}}else if(tipTarget){targetElement=$("#"+tipTarget);if(targetElement.length>0){content=targetElement.html()}}return content}function getViewportCollisions(coords,elementWidth,elementHeight){var viewportTop=session.scrollTop,viewportLeft=session.scrollLeft,viewportBottom=viewportTop+session.windowHeight, +viewportRight=viewportLeft+session.windowWidth,collisions=Collision.none;if(coords.topviewportBottom||Math.abs(coords.bottom-session.windowHeight)>viewportBottom){collisions|=Collision.bottom}if(coords.leftviewportRight){collisions|=Collision.left}if(coords.left+elementWidth>viewportRight||coords.right1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b, +"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery); +/*! SmartMenus jQuery Plugin - v1.1.0 - September 17, 2017 + * http://www.smartmenus.org/ + * Copyright Vasil Dinkov, Vadikom Web Ltd. http://vadikom.com; Licensed MIT */(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof module&&"object"==typeof module.exports?module.exports=t(require("jquery")):t(jQuery)})(function($){function initMouseDetection(t){var e=".smartmenus_mouse";if(mouseDetectionEnabled||t)mouseDetectionEnabled&&t&&($(document).off(e),mouseDetectionEnabled=!1);else{var i=!0,s=null,o={mousemove:function(t){var e={x:t.pageX,y:t.pageY,timeStamp:(new Date).getTime()};if(s){var o=Math.abs(s.x-e.x),a=Math.abs(s.y-e.y);if((o>0||a>0)&&2>=o&&2>=a&&300>=e.timeStamp-s.timeStamp&&(mouse=!0,i)){var n=$(t.target).closest("a");n.is("a")&&$.each(menuTrees,function(){return $.contains(this.$root[0],n[0])?(this.itemEnter({currentTarget:n[0]}),!1):void 0}),i=!1}}s=e}};o[touchEvents?"touchstart":"pointerover pointermove pointerout MSPointerOver MSPointerMove MSPointerOut"]=function(t){isTouchEvent(t.originalEvent)&&(mouse=!1)},$(document).on(getEventsNS(o,e)), +mouseDetectionEnabled=!0}}function isTouchEvent(t){return!/^(4|mouse)$/.test(t.pointerType)}function getEventsNS(t,e){e||(e="");var i={};for(var s in t)i[s.split(" ").join(e+" ")+e]=t[s];return i}var menuTrees=[],mouse=!1,touchEvents="ontouchstart"in window,mouseDetectionEnabled=!1,requestAnimationFrame=window.requestAnimationFrame||function(t){return setTimeout(t,1e3/60)},cancelAnimationFrame=window.cancelAnimationFrame||function(t){clearTimeout(t)},canAnimate=!!$.fn.animate;return $.SmartMenus=function(t,e){this.$root=$(t),this.opts=e,this.rootId="",this.accessIdPrefix="",this.$subArrow=null,this.activatedItems=[],this.visibleSubMenus=[],this.showTimeout=0,this.hideTimeout=0,this.scrollTimeout=0,this.clickActivated=!1,this.focusActivated=!1,this.zIndexInc=0,this.idInc=0,this.$firstLink=null,this.$firstSub=null,this.disabled=!1,this.$disableOverlay=null,this.$touchScrollingSub=null,this.cssTransforms3d="perspective"in t.style||"webkitPerspective"in t.style,this.wasCollapsible=!1,this.init()},$.extend( +$.SmartMenus,{hideAll:function(){$.each(menuTrees,function(){this.menuHideAll()})},destroy:function(){for(;menuTrees.length;)menuTrees[0].destroy();initMouseDetection(!0)},prototype:{init:function(t){var e=this;if(!t){menuTrees.push(this),this.rootId=((new Date).getTime()+Math.random()+"").replace(/\D/g,""),this.accessIdPrefix="sm-"+this.rootId+"-",this.$root.hasClass("sm-rtl")&&(this.opts.rightToLeftSubMenus=!0);var i=".smartmenus";this.$root.data("smartmenus",this).attr("data-smartmenus-id",this.rootId).dataSM("level",1).on(getEventsNS({"mouseover focusin":$.proxy(this.rootOver,this),"mouseout focusout":$.proxy(this.rootOut,this),keydown:$.proxy(this.rootKeyDown,this)},i)).on(getEventsNS({mouseenter:$.proxy(this.itemEnter,this),mouseleave:$.proxy(this.itemLeave,this),mousedown:$.proxy(this.itemDown,this),focus:$.proxy(this.itemFocus,this),blur:$.proxy(this.itemBlur,this),click:$.proxy(this.itemClick,this)},i),"a"),i+=this.rootId,this.opts.hideOnClick&&$(document).on(getEventsNS({touchstart:$.proxy( +this.docTouchStart,this),touchmove:$.proxy(this.docTouchMove,this),touchend:$.proxy(this.docTouchEnd,this),click:$.proxy(this.docClick,this)},i)),$(window).on(getEventsNS({"resize orientationchange":$.proxy(this.winResize,this)},i)),this.opts.subIndicators&&(this.$subArrow=$("").addClass("sub-arrow"),this.opts.subIndicatorsText&&this.$subArrow.html(this.opts.subIndicatorsText)),initMouseDetection()}if(this.$firstSub=this.$root.find("ul").each(function(){e.menuInit($(this))}).eq(0),this.$firstLink=this.$root.find("a").eq(0),this.opts.markCurrentItem){var s=/(index|default)\.[^#\?\/]*/i,o=/#.*/,a=window.location.href.replace(s,""),n=a.replace(o,"");this.$root.find("a").each(function(){var t=this.href.replace(s,""),i=$(this);(t==a||t==n)&&(i.addClass("current"),e.opts.markCurrentTree&&i.parentsUntil("[data-smartmenus-id]","ul").each(function(){$(this).dataSM("parent-a").addClass("current")}))})}this.wasCollapsible=this.isCollapsible()},destroy:function(t){if(!t){var e=".smartmenus";this.$root.removeData( +"smartmenus").removeAttr("data-smartmenus-id").removeDataSM("level").off(e),e+=this.rootId,$(document).off(e),$(window).off(e),this.opts.subIndicators&&(this.$subArrow=null)}this.menuHideAll();var i=this;this.$root.find("ul").each(function(){var t=$(this);t.dataSM("scroll-arrows")&&t.dataSM("scroll-arrows").remove(),t.dataSM("shown-before")&&((i.opts.subMenusMinWidth||i.opts.subMenusMaxWidth)&&t.css({width:"",minWidth:"",maxWidth:""}).removeClass("sm-nowrap"),t.dataSM("scroll-arrows")&&t.dataSM("scroll-arrows").remove(),t.css({zIndex:"",top:"",left:"",marginLeft:"",marginTop:"",display:""})),0==(t.attr("id")||"").indexOf(i.accessIdPrefix)&&t.removeAttr("id")}).removeDataSM("in-mega").removeDataSM("shown-before").removeDataSM("scroll-arrows").removeDataSM("parent-a").removeDataSM("level").removeDataSM("beforefirstshowfired").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeAttr("aria-expanded"),this.$root.find("a.has-submenu").each(function(){var t=$(this);0==t.attr("id" +).indexOf(i.accessIdPrefix)&&t.removeAttr("id")}).removeClass("has-submenu").removeDataSM("sub").removeAttr("aria-haspopup").removeAttr("aria-controls").removeAttr("aria-expanded").closest("li").removeDataSM("sub"),this.opts.subIndicators&&this.$root.find("span.sub-arrow").remove(),this.opts.markCurrentItem&&this.$root.find("a.current").removeClass("current"),t||(this.$root=null,this.$firstLink=null,this.$firstSub=null,this.$disableOverlay&&(this.$disableOverlay.remove(),this.$disableOverlay=null),menuTrees.splice($.inArray(this,menuTrees),1))},disable:function(t){if(!this.disabled){if(this.menuHideAll(),!t&&!this.opts.isPopup&&this.$root.is(":visible")){var e=this.$root.offset();this.$disableOverlay=$('
').css({position:"absolute",top:e.top,left:e.left,width:this.$root.outerWidth(),height:this.$root.outerHeight(),zIndex:this.getStartZIndex(!0),opacity:0}).appendTo(document.body)}this.disabled=!0}},docClick:function(t){return this.$touchScrollingSub?( +this.$touchScrollingSub=null,void 0):((this.visibleSubMenus.length&&!$.contains(this.$root[0],t.target)||$(t.target).closest("a").length)&&this.menuHideAll(),void 0)},docTouchEnd:function(){if(this.lastTouch){if(!(!this.visibleSubMenus.length||void 0!==this.lastTouch.x2&&this.lastTouch.x1!=this.lastTouch.x2||void 0!==this.lastTouch.y2&&this.lastTouch.y1!=this.lastTouch.y2||this.lastTouch.target&&$.contains(this.$root[0],this.lastTouch.target))){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0);var t=this;this.hideTimeout=setTimeout(function(){t.menuHideAll()},350)}this.lastTouch=null}},docTouchMove:function(t){if(this.lastTouch){var e=t.originalEvent.touches[0];this.lastTouch.x2=e.pageX,this.lastTouch.y2=e.pageY}},docTouchStart:function(t){var e=t.originalEvent.touches[0];this.lastTouch={x1:e.pageX,y1:e.pageY,target:e.target}},enable:function(){this.disabled&&(this.$disableOverlay&&(this.$disableOverlay.remove(),this.$disableOverlay=null),this.disabled=!1)},getClosestMenu:function(t){for( +var e=$(t).closest("ul");e.dataSM("in-mega");)e=e.parent().closest("ul");return e[0]||null},getHeight:function(t){return this.getOffset(t,!0)},getOffset:function(t,e){var i;"none"==t.css("display")&&(i={position:t[0].style.position,visibility:t[0].style.visibility},t.css({position:"absolute",visibility:"hidden"}).show());var s=t[0].getBoundingClientRect&&t[0].getBoundingClientRect(),o=s&&(e?s.height||s.bottom-s.top:s.width||s.right-s.left);return o||0===o||(o=e?t[0].offsetHeight:t[0].offsetWidth),i&&t.hide().css(i),o},getStartZIndex:function(t){var e=parseInt(this[t?"$root":"$firstSub"].css("z-index"));return!t&&isNaN(e)&&(e=parseInt(this.$root.css("z-index"))),isNaN(e)?1:e},getTouchPoint:function(t){return t.touches&&t.touches[0]||t.changedTouches&&t.changedTouches[0]||t},getViewport:function(t){var e=t?"Height":"Width",i=document.documentElement["client"+e],s=window["inner"+e];return s&&(i=Math.min(i,s)),i},getViewportHeight:function(){return this.getViewport(!0)},getViewportWidth:function(){ +return this.getViewport()},getWidth:function(t){return this.getOffset(t)},handleEvents:function(){return!this.disabled&&this.isCSSOn()},handleItemEvents:function(t){return this.handleEvents()&&!this.isLinkInMegaMenu(t)},isCollapsible:function(){return"static"==this.$firstSub.css("position")},isCSSOn:function(){return"inline"!=this.$firstLink.css("display")},isFixed:function(){var t="fixed"==this.$root.css("position");return t||this.$root.parentsUntil("body").each(function(){return"fixed"==$(this).css("position")?(t=!0,!1):void 0}),t},isLinkInMegaMenu:function(t){return $(this.getClosestMenu(t[0])).hasClass("mega-menu")},isTouchMode:function(){return!mouse||this.opts.noMouseOver||this.isCollapsible()},itemActivate:function(t,e){var i=t.closest("ul"),s=i.dataSM("level");if(s>1&&(!this.activatedItems[s-2]||this.activatedItems[s-2][0]!=i.dataSM("parent-a")[0])){var o=this;$(i.parentsUntil("[data-smartmenus-id]","ul").get().reverse()).add(i).each(function(){o.itemActivate($(this).dataSM("parent-a"))})}if(( +!this.isCollapsible()||e)&&this.menuHideSubMenus(this.activatedItems[s-1]&&this.activatedItems[s-1][0]==t[0]?s:s-1),this.activatedItems[s-1]=t,this.$root.triggerHandler("activate.smapi",t[0])!==!1){var a=t.dataSM("sub");a&&(this.isTouchMode()||!this.opts.showOnClick||this.clickActivated)&&this.menuShow(a)}},itemBlur:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&this.$root.triggerHandler("blur.smapi",e[0])},itemClick:function(t){var e=$(t.currentTarget);if(this.handleItemEvents(e)){if(this.$touchScrollingSub&&this.$touchScrollingSub[0]==e.closest("ul")[0])return this.$touchScrollingSub=null,t.stopPropagation(),!1;if(this.$root.triggerHandler("click.smapi",e[0])===!1)return!1;var i=$(t.target).is(".sub-arrow"),s=e.dataSM("sub"),o=s?2==s.dataSM("level"):!1,a=this.isCollapsible(),n=/toggle$/.test(this.opts.collapsibleBehavior),r=/link$/.test(this.opts.collapsibleBehavior),h=/^accordion/.test(this.opts.collapsibleBehavior);if(s&&!s.is(":visible")){if((!r||!a||i)&&(this.opts.showOnClick&&o&&( +this.clickActivated=!0),this.itemActivate(e,h),s.is(":visible")))return this.focusActivated=!0,!1}else if(a&&(n||i))return this.itemActivate(e,h),this.menuHide(s),n&&(this.focusActivated=!1),!1;return this.opts.showOnClick&&o||e.hasClass("disabled")||this.$root.triggerHandler("select.smapi",e[0])===!1?!1:void 0}},itemDown:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&e.dataSM("mousedown",!0)},itemEnter:function(t){var e=$(t.currentTarget);if(this.handleItemEvents(e)){if(!this.isTouchMode()){this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0);var i=this;this.showTimeout=setTimeout(function(){i.itemActivate(e)},this.opts.showOnClick&&1==e.closest("ul").dataSM("level")?1:this.opts.showTimeout)}this.$root.triggerHandler("mouseenter.smapi",e[0])}},itemFocus:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&(!this.focusActivated||this.isTouchMode()&&e.dataSM("mousedown")||this.activatedItems.length&&this.activatedItems[this.activatedItems.length-1][0]==e[0 +]||this.itemActivate(e,!0),this.$root.triggerHandler("focus.smapi",e[0]))},itemLeave:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&(this.isTouchMode()||(e[0].blur(),this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0)),e.removeDataSM("mousedown"),this.$root.triggerHandler("mouseleave.smapi",e[0]))},menuHide:function(t){if(this.$root.triggerHandler("beforehide.smapi",t[0])!==!1&&(canAnimate&&t.stop(!0,!0),"none"!=t.css("display"))){var e=function(){t.css("z-index","")};this.isCollapsible()?canAnimate&&this.opts.collapsibleHideFunction?this.opts.collapsibleHideFunction.call(this,t,e):t.hide(this.opts.collapsibleHideDuration,e):canAnimate&&this.opts.hideFunction?this.opts.hideFunction.call(this,t,e):t.hide(this.opts.hideDuration,e),t.dataSM("scroll")&&(this.menuScrollStop(t),t.css({"touch-action":"","-ms-touch-action":"","-webkit-transform":"",transform:""}).off(".smartmenus_scroll").removeDataSM("scroll").dataSM("scroll-arrows").hide()),t.dataSM("parent-a").removeClass( +"highlighted").attr("aria-expanded","false"),t.attr({"aria-expanded":"false","aria-hidden":"true"});var i=t.dataSM("level");this.activatedItems.splice(i-1,1),this.visibleSubMenus.splice($.inArray(t,this.visibleSubMenus),1),this.$root.triggerHandler("hide.smapi",t[0])}},menuHideAll:function(){this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0);for(var t=this.opts.isPopup?1:0,e=this.visibleSubMenus.length-1;e>=t;e--)this.menuHide(this.visibleSubMenus[e]);this.opts.isPopup&&(canAnimate&&this.$root.stop(!0,!0),this.$root.is(":visible")&&(canAnimate&&this.opts.hideFunction?this.opts.hideFunction.call(this,this.$root):this.$root.hide(this.opts.hideDuration))),this.activatedItems=[],this.visibleSubMenus=[],this.clickActivated=!1,this.focusActivated=!1,this.zIndexInc=0,this.$root.triggerHandler("hideAll.smapi")},menuHideSubMenus:function(t){for(var e=this.activatedItems.length-1;e>=t;e--){var i=this.activatedItems[e].dataSM("sub");i&&this.menuHide(i)}},menuInit:function(t){if(!t.dataSM("in-mega")){ +t.hasClass("mega-menu")&&t.find("ul").dataSM("in-mega",!0);for(var e=2,i=t[0];(i=i.parentNode.parentNode)!=this.$root[0];)e++;var s=t.prevAll("a").eq(-1);s.length||(s=t.prevAll().find("a").eq(-1)),s.addClass("has-submenu").dataSM("sub",t),t.dataSM("parent-a",s).dataSM("level",e).parent().dataSM("sub",t);var o=s.attr("id")||this.accessIdPrefix+ ++this.idInc,a=t.attr("id")||this.accessIdPrefix+ ++this.idInc;s.attr({id:o,"aria-haspopup":"true","aria-controls":a,"aria-expanded":"false"}),t.attr({id:a,role:"group","aria-hidden":"true","aria-labelledby":o,"aria-expanded":"false"}),this.opts.subIndicators&&s[this.opts.subIndicatorsPos](this.$subArrow.clone())}},menuPosition:function(t){var e,i,s=t.dataSM("parent-a"),o=s.closest("li"),a=o.parent(),n=t.dataSM("level"),r=this.getWidth(t),h=this.getHeight(t),u=s.offset(),l=u.left,c=u.top,d=this.getWidth(s),m=this.getHeight(s),p=$(window),f=p.scrollLeft(),v=p.scrollTop(),b=this.getViewportWidth(),S=this.getViewportHeight(),g=a.parent().is("[data-sm-horizontal-sub]" +)||2==n&&!a.hasClass("sm-vertical"),M=this.opts.rightToLeftSubMenus&&!o.is("[data-sm-reverse]")||!this.opts.rightToLeftSubMenus&&o.is("[data-sm-reverse]"),w=2==n?this.opts.mainMenuSubOffsetX:this.opts.subMenusSubOffsetX,T=2==n?this.opts.mainMenuSubOffsetY:this.opts.subMenusSubOffsetY;if(g?(e=M?d-r-w:w,i=this.opts.bottomToTopSubMenus?-h-T:m+T):(e=M?w-r:d-w,i=this.opts.bottomToTopSubMenus?m-T-h:T),this.opts.keepInViewport){var y=l+e,I=c+i;if(M&&f>y?e=g?f-y+e:d-w:!M&&y+r>f+b&&(e=g?f+b-r-y+e:w-r),g||(S>h&&I+h>v+S?i+=v+S-h-I:(h>=S||v>I)&&(i+=v-I)),g&&(I+h>v+S+.49||v>I)||!g&&h>S+.49){var x=this;t.dataSM("scroll-arrows")||t.dataSM("scroll-arrows",$([$('')[0],$('')[0]]).on({mouseenter:function(){t.dataSM("scroll").up=$(this).hasClass("scroll-up"),x.menuScroll(t)},mouseleave:function(e){x.menuScrollStop(t),x.menuScrollOut(t,e)},"mousewheel DOMMouseScroll":function(t){ +t.preventDefault()}}).insertAfter(t));var A=".smartmenus_scroll";if(t.dataSM("scroll",{y:this.cssTransforms3d?0:i-m,step:1,itemH:m,subH:h,arrowDownH:this.getHeight(t.dataSM("scroll-arrows").eq(1))}).on(getEventsNS({mouseover:function(e){x.menuScrollOver(t,e)},mouseout:function(e){x.menuScrollOut(t,e)},"mousewheel DOMMouseScroll":function(e){x.menuScrollMousewheel(t,e)}},A)).dataSM("scroll-arrows").css({top:"auto",left:"0",marginLeft:e+(parseInt(t.css("border-left-width"))||0),width:r-(parseInt(t.css("border-left-width"))||0)-(parseInt(t.css("border-right-width"))||0),zIndex:t.css("z-index")}).eq(g&&this.opts.bottomToTopSubMenus?0:1).show(),this.isFixed()){var C={};C[touchEvents?"touchstart touchmove touchend":"pointerdown pointermove pointerup MSPointerDown MSPointerMove MSPointerUp"]=function(e){x.menuScrollTouch(t,e)},t.css({"touch-action":"none","-ms-touch-action":"none"}).on(getEventsNS(C,A))}}}t.css({top:"auto",left:"0",marginLeft:e,marginTop:i-m})},menuScroll:function(t,e,i){var s,o=t.dataSM("scroll"), +a=t.dataSM("scroll-arrows"),n=o.up?o.upEnd:o.downEnd;if(!e&&o.momentum){if(o.momentum*=.92,s=o.momentum,.5>s)return this.menuScrollStop(t),void 0}else s=i||(e||!this.opts.scrollAccelerate?this.opts.scrollStep:Math.floor(o.step));var r=t.dataSM("level");if(this.activatedItems[r-1]&&this.activatedItems[r-1].dataSM("sub")&&this.activatedItems[r-1].dataSM("sub").is(":visible")&&this.menuHideSubMenus(r-1),o.y=o.up&&o.y>=n||!o.up&&n>=o.y?o.y:Math.abs(n-o.y)>s?o.y+(o.up?s:-s):n,t.css(this.cssTransforms3d?{"-webkit-transform":"translate3d(0, "+o.y+"px, 0)",transform:"translate3d(0, "+o.y+"px, 0)"}:{marginTop:o.y}),mouse&&(o.up&&o.y>o.downEnd||!o.up&&o.y0;t.dataSM("scroll-arrows").eq(i?0:1).is(":visible")&&(t.dataSM("scroll").up=i,this.menuScroll(t,!0))}e.preventDefault()},menuScrollOut:function(t,e){mouse&&(/^scroll-(up|down)/.test((e.relatedTarget||"").className)||(t[0]==e.relatedTarget||$.contains(t[0],e.relatedTarget))&&this.getClosestMenu(e.relatedTarget)==t[0]||t.dataSM("scroll-arrows").css("visibility","hidden"))},menuScrollOver:function(t,e){if(mouse&&!/^scroll-(up|down)/.test(e.target.className)&&this.getClosestMenu(e.target)==t[0]){this.menuScrollRefreshData(t);var i=t.dataSM("scroll"),s=$(window).scrollTop()-t.dataSM("parent-a").offset().top-i.itemH;t.dataSM("scroll-arrows").eq(0).css("margin-top",s).end().eq(1).css("margin-top",s+this.getViewportHeight()-i.arrowDownH).end().css("visibility","visible")}},menuScrollRefreshData:function(t){var e=t.dataSM("scroll"),i=$(window).scrollTop()-t.dataSM("parent-a").offset().top-e.itemH;this.cssTransforms3d&&(i=-(parseFloat(t.css("margin-top"))-i)),$.extend(e,{upEnd:i, +downEnd:i+this.getViewportHeight()-e.subH})},menuScrollStop:function(t){return this.scrollTimeout?(cancelAnimationFrame(this.scrollTimeout),this.scrollTimeout=0,t.dataSM("scroll").step=1,!0):void 0},menuScrollTouch:function(t,e){if(e=e.originalEvent,isTouchEvent(e)){var i=this.getTouchPoint(e);if(this.getClosestMenu(i.target)==t[0]){var s=t.dataSM("scroll");if(/(start|down)$/i.test(e.type))this.menuScrollStop(t)?(e.preventDefault(),this.$touchScrollingSub=t):this.$touchScrollingSub=null,this.menuScrollRefreshData(t),$.extend(s,{touchStartY:i.pageY,touchStartTime:e.timeStamp});else if(/move$/i.test(e.type)){var o=void 0!==s.touchY?s.touchY:s.touchStartY;if(void 0!==o&&o!=i.pageY){this.$touchScrollingSub=t;var a=i.pageY>o;void 0!==s.up&&s.up!=a&&$.extend(s,{touchStartY:i.pageY,touchStartTime:e.timeStamp}),$.extend(s,{up:a,touchY:i.pageY}),this.menuScroll(t,!0,Math.abs(i.pageY-o))}e.preventDefault()}else void 0!==s.touchY&&((s.momentum=15*Math.pow(Math.abs(i.pageY-s.touchStartY)/(e.timeStamp-s.touchStartTime),2) +)&&(this.menuScrollStop(t),this.menuScroll(t),e.preventDefault()),delete s.touchY)}}},menuShow:function(t){if((t.dataSM("beforefirstshowfired")||(t.dataSM("beforefirstshowfired",!0),this.$root.triggerHandler("beforefirstshow.smapi",t[0])!==!1))&&this.$root.triggerHandler("beforeshow.smapi",t[0])!==!1&&(t.dataSM("shown-before",!0),canAnimate&&t.stop(!0,!0),!t.is(":visible"))){var e=t.dataSM("parent-a"),i=this.isCollapsible();if((this.opts.keepHighlighted||i)&&e.addClass("highlighted"),i)t.removeClass("sm-nowrap").css({zIndex:"",width:"auto",minWidth:"",maxWidth:"",top:"",left:"",marginLeft:"",marginTop:""});else{if(t.css("z-index",this.zIndexInc=(this.zIndexInc||this.getStartZIndex())+1),(this.opts.subMenusMinWidth||this.opts.subMenusMaxWidth)&&(t.css({width:"auto",minWidth:"",maxWidth:""}).addClass("sm-nowrap"),this.opts.subMenusMinWidth&&t.css("min-width",this.opts.subMenusMinWidth),this.opts.subMenusMaxWidth)){var s=this.getWidth(t);t.css("max-width",this.opts.subMenusMaxWidth),s>this.getWidth(t +)&&t.removeClass("sm-nowrap").css("width",this.opts.subMenusMaxWidth)}this.menuPosition(t)}var o=function(){t.css("overflow","")};i?canAnimate&&this.opts.collapsibleShowFunction?this.opts.collapsibleShowFunction.call(this,t,o):t.show(this.opts.collapsibleShowDuration,o):canAnimate&&this.opts.showFunction?this.opts.showFunction.call(this,t,o):t.show(this.opts.showDuration,o),e.attr("aria-expanded","true"),t.attr({"aria-expanded":"true","aria-hidden":"false"}),this.visibleSubMenus.push(t),this.$root.triggerHandler("show.smapi",t[0])}},popupHide:function(t){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0);var e=this;this.hideTimeout=setTimeout(function(){e.menuHideAll()},t?1:this.opts.hideTimeout)},popupShow:function(t,e){if(!this.opts.isPopup)return alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'),void 0;if(this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0),this.$root.dataSM("shown-before",!0), +canAnimate&&this.$root.stop(!0,!0),!this.$root.is(":visible")){this.$root.css({left:t,top:e});var i=this,s=function(){i.$root.css("overflow","")};canAnimate&&this.opts.showFunction?this.opts.showFunction.call(this,this.$root,s):this.$root.show(this.opts.showDuration,s),this.visibleSubMenus[0]=this.$root}},refresh:function(){this.destroy(!0),this.init(!0)},rootKeyDown:function(t){if(this.handleEvents())switch(t.keyCode){case 27:var e=this.activatedItems[0];if(e){this.menuHideAll(),e[0].focus();var i=e.dataSM("sub");i&&this.menuHide(i)}break;case 32:var s=$(t.target);if(s.is("a")&&this.handleItemEvents(s)){var i=s.dataSM("sub");i&&!i.is(":visible")&&(this.itemClick({currentTarget:t.target}),t.preventDefault())}}},rootOut:function(t){if(this.handleEvents()&&!this.isTouchMode()&&t.target!=this.$root[0]&&(this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0),!this.opts.showOnClick||!this.opts.hideOnClick)){var e=this;this.hideTimeout=setTimeout(function(){e.menuHideAll()},this.opts.hideTimeout)}}, +rootOver:function(t){this.handleEvents()&&!this.isTouchMode()&&t.target!=this.$root[0]&&this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0)},winResize:function(t){if(this.handleEvents()){if(!("onorientationchange"in window)||"orientationchange"==t.type){var e=this.isCollapsible();this.wasCollapsible&&e||(this.activatedItems.length&&this.activatedItems[this.activatedItems.length-1][0].blur(),this.menuHideAll()),this.wasCollapsible=e}}else if(this.$disableOverlay){var i=this.$root.offset();this.$disableOverlay.css({top:i.top,left:i.left,width:this.$root.outerWidth(),height:this.$root.outerHeight()})}}}}),$.fn.dataSM=function(t,e){return e?this.data(t+"_smartmenus",e):this.data(t+"_smartmenus")},$.fn.removeDataSM=function(t){return this.removeData(t+"_smartmenus")},$.fn.smartmenus=function(options){if("string"==typeof options){var args=arguments,method=options;return Array.prototype.shift.call(args),this.each(function(){var t=$(this).data("smartmenus");t&&t[method]&&t[method].apply(t,args)})} +return this.each(function(){var dataOpts=$(this).data("sm-options")||null;if(dataOpts)try{dataOpts=eval("("+dataOpts+")")}catch(e){dataOpts=null,alert('ERROR\n\nSmartMenus jQuery init:\nInvalid "data-sm-options" attribute value syntax.')}new $.SmartMenus(this,$.extend({},$.fn.smartmenus.defaults,options,dataOpts))})},$.fn.smartmenus.defaults={isPopup:!1,mainMenuSubOffsetX:0,mainMenuSubOffsetY:0,subMenusSubOffsetX:0,subMenusSubOffsetY:0,subMenusMinWidth:"10em",subMenusMaxWidth:"20em",subIndicators:!0,subIndicatorsPos:"append",subIndicatorsText:"",scrollStep:30,scrollAccelerate:!0,showTimeout:250,hideTimeout:500,showDuration:0,showFunction:null,hideDuration:0,hideFunction:function(t,e){t.fadeOut(200,e)},collapsibleShowDuration:0,collapsibleShowFunction:function(t,e){t.slideDown(200,e)},collapsibleHideDuration:0,collapsibleHideFunction:function(t,e){t.slideUp(200,e)},showOnClick:!1,hideOnClick:!0,noMouseOver:!1,keepInViewport:!0,keepHighlighted:!0,markCurrentItem:!1,markCurrentTree:!0,rightToLeftSubMenus:!1, +bottomToTopSubMenus:!1,collapsibleBehavior:"default"},$}); diff --git a/docs/menu.js b/docs/menu.js new file mode 100644 index 0000000..0fd1e99 --- /dev/null +++ b/docs/menu.js @@ -0,0 +1,134 @@ +/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file + */ +function initMenu(relPath,searchEnabled,serverSide,searchPage,search,treeview) { + function makeTree(data,relPath) { + let result=''; + if ('children' in data) { + result+='
    '; + for (let i in data.children) { + let url; + const link = data.children[i].url; + if (link.substring(0,1)=='^') { + url = link.substring(1); + } else { + url = relPath+link; + } + result+='
  • '+ + data.children[i].text+''+ + makeTree(data.children[i],relPath)+'
  • '; + } + result+='
'; + } + return result; + } + let searchBoxHtml; + if (searchEnabled) { + if (serverSide) { + searchBoxHtml='
'+ + '
'+ + '
 '+ + ''+ + '
'+ + '
'+ + '
'+ + '
'; + } else { + searchBoxHtml='
'+ + ''+ + ' '+ + ''+ + ''+ + ''+ + ''+ + ''+ + '
'; + } + } + + $('#main-nav').before('
'+ + ''+ + ''+ + '
'); + $('#main-nav').append(makeTree(menudata,relPath)); + $('#main-nav').children(':first').addClass('sm sm-dox').attr('id','main-menu'); + if (searchBoxHtml) { + $('#main-menu').append('
  • '); + } + const $mainMenuState = $('#main-menu-state'); + let prevWidth = 0; + if ($mainMenuState.length) { + const initResizableIfExists = function() { + if (typeof initResizable==='function') initResizable(treeview); + } + // animate mobile menu + $mainMenuState.change(function() { + const $menu = $('#main-menu'); + let options = { duration: 250, step: initResizableIfExists }; + if (this.checked) { + options['complete'] = () => $menu.css('display', 'block'); + $menu.hide().slideDown(options); + } else { + options['complete'] = () => $menu.css('display', 'none'); + $menu.show().slideUp(options); + } + }); + // set default menu visibility + const resetState = function() { + const $menu = $('#main-menu'); + const newWidth = $(window).outerWidth(); + if (newWidth!=prevWidth) { + if ($(window).outerWidth()<768) { + $mainMenuState.prop('checked',false); $menu.hide(); + $('#searchBoxPos1').html(searchBoxHtml); + $('#searchBoxPos2').hide(); + } else { + $menu.show(); + $('#searchBoxPos1').empty(); + $('#searchBoxPos2').html(searchBoxHtml); + $('#searchBoxPos2').show(); + } + if (typeof searchBox!=='undefined') { + searchBox.CloseResultsWindow(); + } + prevWidth = newWidth; + } + } + $(window).ready(function() { resetState(); initResizableIfExists(); }); + $(window).resize(resetState); + } + $('#main-menu').smartmenus(); +} +/* @license-end */ diff --git a/docs/menudata.js b/docs/menudata.js new file mode 100644 index 0000000..d1a7a09 --- /dev/null +++ b/docs/menudata.js @@ -0,0 +1,50 @@ +/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file +*/ +var menudata={children:[ +{text:"Main Page",url:"index.html"}, +{text:"Classes",url:"annotated.html",children:[ +{text:"Class List",url:"annotated.html"}, +{text:"Class Index",url:"classes.html"}, +{text:"Class Hierarchy",url:"hierarchy.html"}, +{text:"Class Members",url:"functions.html",children:[ +{text:"All",url:"functions.html",children:[ +{text:"a",url:"functions.html#index_a"}, +{text:"b",url:"functions.html#index_b"}, +{text:"h",url:"functions.html#index_h"}, +{text:"l",url:"functions.html#index_l"}, +{text:"m",url:"functions.html#index_m"}, +{text:"p",url:"functions.html#index_p"}, +{text:"s",url:"functions.html#index_s"}]}, +{text:"Functions",url:"functions_func.html",children:[ +{text:"a",url:"functions_func.html#index_a"}, +{text:"b",url:"functions_func.html#index_b"}, +{text:"h",url:"functions_func.html#index_h"}, +{text:"l",url:"functions_func.html#index_l"}, +{text:"m",url:"functions_func.html#index_m"}, +{text:"p",url:"functions_func.html#index_p"}, +{text:"s",url:"functions_func.html#index_s"}]}, +{text:"Variables",url:"functions_vars.html"}]}]}, +{text:"Files",url:"files.html",children:[ +{text:"File List",url:"files.html"}]}]} diff --git a/docs/minus.svg b/docs/minus.svg new file mode 100644 index 0000000..f70d0c1 --- /dev/null +++ b/docs/minus.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/docs/minusd.svg b/docs/minusd.svg new file mode 100644 index 0000000..5f8e879 --- /dev/null +++ b/docs/minusd.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/docs/nav_f.png b/docs/nav_f.png new file mode 100644 index 0000000..72a58a5 Binary files /dev/null and b/docs/nav_f.png differ diff --git a/docs/nav_fd.png b/docs/nav_fd.png new file mode 100644 index 0000000..032fbdd Binary files /dev/null and b/docs/nav_fd.png differ diff --git a/docs/nav_g.png b/docs/nav_g.png new file mode 100644 index 0000000..2093a23 Binary files /dev/null and b/docs/nav_g.png differ diff --git a/docs/nav_h.png b/docs/nav_h.png new file mode 100644 index 0000000..33389b1 Binary files /dev/null and b/docs/nav_h.png differ diff --git a/docs/nav_hd.png b/docs/nav_hd.png new file mode 100644 index 0000000..de80f18 Binary files /dev/null and b/docs/nav_hd.png differ diff --git a/docs/navtree.css b/docs/navtree.css new file mode 100644 index 0000000..6b1e5e4 --- /dev/null +++ b/docs/navtree.css @@ -0,0 +1,149 @@ +#nav-tree .children_ul { + margin:0; + padding:4px; +} + +#nav-tree ul { + list-style:none outside none; + margin:0px; + padding:0px; +} + +#nav-tree li { + white-space:nowrap; + margin:0px; + padding:0px; +} + +#nav-tree .plus { + margin:0px; +} + +#nav-tree .selected { + background-image: url('tab_a.png'); + background-repeat:repeat-x; + color: white; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); +} + +#nav-tree .selected .arrow { + color: #9CAFD4; + text-shadow: none; +} + +#nav-tree img { + margin:0px; + padding:0px; + border:0px; + vertical-align: middle; +} + +#nav-tree a { + text-decoration:none; + padding:0px; + margin:0px; +} + +#nav-tree .label { + margin:0px; + padding:0px; + font: 12px 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; +} + +#nav-tree .label a { + padding:2px; +} + +#nav-tree .selected a { + text-decoration:none; + color:white; +} + +#nav-tree .children_ul { + margin:0px; + padding:0px; +} + +#nav-tree .item { + margin:0px; + padding:0px; +} + +#nav-tree { + padding: 0px 0px; + font-size:14px; + overflow:auto; +} + +#doc-content { + overflow:auto; + display:block; + padding:0px; + margin:0px; + -webkit-overflow-scrolling : touch; /* iOS 5+ */ +} + +#side-nav { + padding:0 6px 0 0; + margin: 0px; + display:block; + position: absolute; + left: 0px; + width: $width; + overflow : hidden; +} + +.ui-resizable .ui-resizable-handle { + display:block; +} + +.ui-resizable-e { + background-image:url('splitbar.png'); + background-size:100%; + background-repeat:repeat-y; + background-attachment: scroll; + cursor:ew-resize; + height:100%; + right:0; + top:0; + width:6px; +} + +.ui-resizable-handle { + display:none; + font-size:0.1px; + position:absolute; + z-index:1; +} + +#nav-tree-contents { + margin: 6px 0px 0px 0px; +} + +#nav-tree { + background-repeat:repeat-x; + background-color: #F9FAFC; + -webkit-overflow-scrolling : touch; /* iOS 5+ */ +} + +#nav-sync { + position:absolute; + top:5px; + right:24px; + z-index:0; +} + +#nav-sync img { + opacity:0.3; +} + +#nav-sync img:hover { + opacity:0.9; +} + +@media print +{ + #nav-tree { display: none; } + div.ui-resizable-handle { display: none; position: relative; } +} + diff --git a/docs/navtree.js b/docs/navtree.js new file mode 100644 index 0000000..9027ce6 --- /dev/null +++ b/docs/navtree.js @@ -0,0 +1,483 @@ +/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file + */ + +function initNavTree(toroot,relpath) { + let navTreeSubIndices = []; + const ARROW_DOWN = '▼'; + const ARROW_RIGHT = '►'; + const NAVPATH_COOKIE_NAME = ''+'navpath'; + + const getData = function(varName) { + const i = varName.lastIndexOf('/'); + const n = i>=0 ? varName.substring(i+1) : varName; + return eval(n.replace(/-/g,'_')); + } + + const stripPath = function(uri) { + return uri.substring(uri.lastIndexOf('/')+1); + } + + const stripPath2 = function(uri) { + const i = uri.lastIndexOf('/'); + const s = uri.substring(i+1); + const m = uri.substring(0,i+1).match(/\/d\w\/d\w\w\/$/); + return m ? uri.substring(i-6) : s; + } + + const hashValue = function() { + return $(location).attr('hash').substring(1).replace(/[^\w-]/g,''); + } + + const hashUrl = function() { + return '#'+hashValue(); + } + + const pathName = function() { + return $(location).attr('pathname').replace(/[^-A-Za-z0-9+&@#/%?=~_|!:,.;()]/g, ''); + } + + const storeLink = function(link) { + if (!$("#nav-sync").hasClass('sync')) { + Cookie.writeSetting(NAVPATH_COOKIE_NAME,link,0); + } + } + + const deleteLink = function() { + Cookie.eraseSetting(NAVPATH_COOKIE_NAME); + } + + const cachedLink = function() { + return Cookie.readSetting(NAVPATH_COOKIE_NAME,''); + } + + const getScript = function(scriptName,func) { + const head = document.getElementsByTagName("head")[0]; + const script = document.createElement('script'); + script.id = scriptName; + script.type = 'text/javascript'; + script.onload = func; + script.src = scriptName+'.js'; + head.appendChild(script); + } + + const createIndent = function(o,domNode,node) { + let level=-1; + let n = node; + while (n.parentNode) { level++; n=n.parentNode; } + if (node.childrenData) { + const imgNode = document.createElement("span"); + imgNode.className = 'arrow'; + imgNode.style.paddingLeft=(16*level).toString()+'px'; + imgNode.innerHTML=ARROW_RIGHT; + node.plus_img = imgNode; + node.expandToggle = document.createElement("a"); + node.expandToggle.href = "javascript:void(0)"; + node.expandToggle.onclick = function() { + if (node.expanded) { + $(node.getChildrenUL()).slideUp("fast"); + node.plus_img.innerHTML=ARROW_RIGHT; + node.expanded = false; + } else { + expandNode(o, node, false, true); + } + } + node.expandToggle.appendChild(imgNode); + domNode.appendChild(node.expandToggle); + } else { + let span = document.createElement("span"); + span.className = 'arrow'; + span.style.width = 16*(level+1)+'px'; + span.innerHTML = ' '; + domNode.appendChild(span); + } + } + + let animationInProgress = false; + + const gotoAnchor = function(anchor,aname) { + let pos, docContent = $('#doc-content'); + let ancParent = $(anchor.parent()); + if (ancParent.hasClass('memItemLeft') || ancParent.hasClass('memtitle') || + ancParent.hasClass('fieldname') || ancParent.hasClass('fieldtype') || + ancParent.is(':header')) { + pos = ancParent.position().top; + } else if (anchor.position()) { + pos = anchor.position().top; + } + if (pos) { + const dcOffset = docContent.offset().top; + const dcHeight = docContent.height(); + const dcScrHeight = docContent[0].scrollHeight + const dcScrTop = docContent.scrollTop(); + let dist = Math.abs(Math.min(pos-dcOffset,dcScrHeight-dcHeight-dcScrTop)); + animationInProgress = true; + docContent.animate({ + scrollTop: pos + dcScrTop - dcOffset + },Math.max(50,Math.min(500,dist)),function() { + animationInProgress=false; + if (anchor.parent().attr('class')=='memItemLeft') { + let rows = $('.memberdecls tr[class$="'+hashValue()+'"]'); + glowEffect(rows.children(),300); // member without details + } else if (anchor.parent().attr('class')=='fieldname') { + glowEffect(anchor.parent().parent(),1000); // enum value + } else if (anchor.parent().attr('class')=='fieldtype') { + glowEffect(anchor.parent().parent(),1000); // struct field + } else if (anchor.parent().is(":header")) { + glowEffect(anchor.parent(),1000); // section header + } else { + glowEffect(anchor.next(),1000); // normal member + } + }); + } + } + + const newNode = function(o, po, text, link, childrenData, lastNode) { + const node = { + children : [], + childrenData : childrenData, + depth : po.depth + 1, + relpath : po.relpath, + isLast : lastNode, + li : document.createElement("li"), + parentNode : po, + itemDiv : document.createElement("div"), + labelSpan : document.createElement("span"), + label : document.createTextNode(text), + expanded : false, + childrenUL : null, + getChildrenUL : function() { + if (!this.childrenUL) { + this.childrenUL = document.createElement("ul"); + this.childrenUL.className = "children_ul"; + this.childrenUL.style.display = "none"; + this.li.appendChild(node.childrenUL); + } + return node.childrenUL; + }, + }; + + node.itemDiv.className = "item"; + node.labelSpan.className = "label"; + createIndent(o,node.itemDiv,node); + node.itemDiv.appendChild(node.labelSpan); + node.li.appendChild(node.itemDiv); + + const a = document.createElement("a"); + node.labelSpan.appendChild(a); + po.getChildrenUL().appendChild(node.li); + a.appendChild(node.label); + if (link) { + let url; + if (link.substring(0,1)=='^') { + url = link.substring(1); + link = url; + } else { + url = node.relpath+link; + } + a.className = stripPath(link.replace('#',':')); + if (link.indexOf('#')!=-1) { + const aname = '#'+link.split('#')[1]; + const srcPage = stripPath(pathName()); + const targetPage = stripPath(link.split('#')[0]); + a.href = srcPage!=targetPage ? url : aname; + a.onclick = function() { + storeLink(link); + aPPar = $(a).parent().parent(); + if (!aPPar.hasClass('selected')) { + $('.item').removeClass('selected'); + $('.item').removeAttr('id'); + aPPar.addClass('selected'); + aPPar.attr('id','selected'); + } + const anchor = $(aname); + gotoAnchor(anchor,aname); + }; + } else { + a.href = url; + a.onclick = () => storeLink(link); + } + } else if (childrenData != null) { + a.className = "nolink"; + a.href = "javascript:void(0)"; + a.onclick = node.expandToggle.onclick; + } + return node; + } + + const showRoot = function() { + const headerHeight = $("#top").height(); + const footerHeight = $("#nav-path").height(); + const windowHeight = $(window).height() - headerHeight - footerHeight; + (function() { // retry until we can scroll to the selected item + try { + const navtree=$('#nav-tree'); + navtree.scrollTo('#selected',100,{offset:-windowHeight/2}); + } catch (err) { + setTimeout(arguments.callee, 0); + } + })(); + } + + const expandNode = function(o, node, imm, setFocus) { + if (node.childrenData && !node.expanded) { + if (typeof(node.childrenData)==='string') { + const varName = node.childrenData; + getScript(node.relpath+varName,function() { + node.childrenData = getData(varName); + expandNode(o, node, imm, setFocus); + }); + } else { + if (!node.childrenVisited) { + getNode(o, node); + } + $(node.getChildrenUL()).slideDown("fast"); + node.plus_img.innerHTML = ARROW_DOWN; + node.expanded = true; + if (setFocus) { + $(node.expandToggle).focus(); + } + } + } + } + + const glowEffect = function(n,duration) { + n.addClass('glow').delay(duration).queue(function(next) { + $(this).removeClass('glow');next(); + }); + } + + const highlightAnchor = function() { + const aname = hashUrl(); + const anchor = $(aname); + gotoAnchor(anchor,aname); + } + + const selectAndHighlight = function(hash,n) { + let a; + if (hash) { + const link=stripPath(pathName())+':'+hash.substring(1); + a=$('.item a[class$="'+link+'"]'); + } + if (a && a.length) { + a.parent().parent().addClass('selected'); + a.parent().parent().attr('id','selected'); + highlightAnchor(); + } else if (n) { + $(n.itemDiv).addClass('selected'); + $(n.itemDiv).attr('id','selected'); + } + let topOffset=5; + if ($('#nav-tree-contents .item:first').hasClass('selected')) { + topOffset+=25; + } + $('#nav-sync').css('top',topOffset+'px'); + showRoot(); + } + + const showNode = function(o, node, index, hash) { + if (node && node.childrenData) { + if (typeof(node.childrenData)==='string') { + const varName = node.childrenData; + getScript(node.relpath+varName,function() { + node.childrenData = getData(varName); + showNode(o,node,index,hash); + }); + } else { + if (!node.childrenVisited) { + getNode(o, node); + } + $(node.getChildrenUL()).css({'display':'block'}); + node.plus_img.innerHTML = ARROW_DOWN; + node.expanded = true; + const n = node.children[o.breadcrumbs[index]]; + if (index+11 ? '#'+parts[1].replace(/[^\w-]/g,'') : ''; + } + if (hash.match(/^#l\d+$/)) { + const anchor=$('a[name='+hash.substring(1)+']'); + glowEffect(anchor.parent(),1000); // line number + hash=''; // strip line number anchors + } + const url=root+hash; + let i=-1; + while (NAVTREEINDEX[i+1]<=url) i++; + if (i==-1) { i=0; root=NAVTREE[0][1]; } // fallback: show index + if (navTreeSubIndices[i]) { + gotoNode(o,i,root,hash,relpath) + } else { + getScript(relpath+'navtreeindex'+i,function() { + navTreeSubIndices[i] = eval('NAVTREEINDEX'+i); + if (navTreeSubIndices[i]) { + gotoNode(o,i,root,hash,relpath); + } + }); + } + } + + const showSyncOff = function(n,relpath) { + n.html(''); + } + + const showSyncOn = function(n,relpath) { + n.html(''); + } + + const o = { + toroot : toroot, + node : { + childrenData : NAVTREE, + children : [], + childrenUL : document.createElement("ul"), + getChildrenUL : function() { return this.childrenUL }, + li : document.getElementById("nav-tree-contents"), + depth : 0, + relpath : relpath, + expanded : false, + isLast : true, + plus_img : document.createElement("span"), + }, + }; + o.node.li.appendChild(o.node.childrenUL); + o.node.plus_img.className = 'arrow'; + o.node.plus_img.innerHTML = ARROW_RIGHT; + + const navSync = $('#nav-sync'); + if (cachedLink()) { + showSyncOff(navSync,relpath); + navSync.removeClass('sync'); + } else { + showSyncOn(navSync,relpath); + } + + navSync.click(() => { + const navSync = $('#nav-sync'); + if (navSync.hasClass('sync')) { + navSync.removeClass('sync'); + showSyncOff(navSync,relpath); + storeLink(stripPath2(pathName())+hashUrl()); + } else { + navSync.addClass('sync'); + showSyncOn(navSync,relpath); + deleteLink(); + } + }); + + navTo(o,toroot,hashUrl(),relpath); + showRoot(); + + $(window).bind('hashchange', () => { + if (!animationInProgress) { + if (window.location.hash && window.location.hash.length>1) { + let a; + if ($(location).attr('hash')) { + const clslink=stripPath(pathName())+':'+hashValue(); + a=$('.item a[class$="'+clslink.replace(/ + + + + + + +BOLT Dash (C++): Bolt_Dash/nmea_decoder.h Source File + + + + + + + + + + + + + + + + +
    +
    + + + + + + +
    +
    BOLT Dash (C++) +
    +
    +
    + + + + + + + + +
    +
    + +
    +
    +
    + +
    + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + +
    +
    nmea_decoder.h
    +
    +
    +
    1#include <cmath>
    +
    2#include <iostream>
    +
    3#include <sstream>
    +
    4#include <string>
    +
    5#include <vector>
    +
    6
    +
    +
    7struct GPSData {
    +
    8 double latitude = 0.0;
    +
    9 double longitude = 0.0;
    +
    10 std::string time = "";
    +
    11 std::string date = "";
    +
    12 double altitude = 0.0;
    +
    13 int satellites = 0;
    +
    14 std::string fix = "Invalid";
    +
    15};
    +
    +
    16
    +
    17std::vector<std::string> split(const std::string &s, char delimiter);
    +
    18
    +
    19double convertToDecimalDegrees(const std::string &value, const std::string &direction);
    +
    20
    +
    21GPSData decodeNMEA(const std::string &nmea);
    +
    22
    +
    23void printGPSData(const GPSData &data);
    +
    24
    +
    25int nmmeaMain();
    +
    Definition nmea_decoder.h:7
    +
    +
    + + + + diff --git a/docs/open.png b/docs/open.png new file mode 100644 index 0000000..30f75c7 Binary files /dev/null and b/docs/open.png differ diff --git a/docs/plus.svg b/docs/plus.svg new file mode 100644 index 0000000..0752016 --- /dev/null +++ b/docs/plus.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/docs/plusd.svg b/docs/plusd.svg new file mode 100644 index 0000000..0c65bfe --- /dev/null +++ b/docs/plusd.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/docs/resize.js b/docs/resize.js new file mode 100644 index 0000000..178d03b --- /dev/null +++ b/docs/resize.js @@ -0,0 +1,147 @@ +/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file + */ + +function initResizable(treeview) { + let sidenav,navtree,content,header,footer,barWidth=6; + const RESIZE_COOKIE_NAME = ''+'width'; + + function resizeWidth() { + const sidenavWidth = $(sidenav).outerWidth(); + content.css({marginLeft:parseInt(sidenavWidth)+"px"}); + if (typeof page_layout!=='undefined' && page_layout==1) { + footer.css({marginLeft:parseInt(sidenavWidth)+"px"}); + } + Cookie.writeSetting(RESIZE_COOKIE_NAME,sidenavWidth-barWidth); + } + + function restoreWidth(navWidth) { + content.css({marginLeft:parseInt(navWidth)+barWidth+"px"}); + if (typeof page_layout!=='undefined' && page_layout==1) { + footer.css({marginLeft:parseInt(navWidth)+barWidth+"px"}); + } + sidenav.css({width:navWidth + "px"}); + } + + function resizeHeight(treeview) { + const headerHeight = header.outerHeight(); + const windowHeight = $(window).height(); + let contentHeight; + if (treeview) + { + const footerHeight = footer.outerHeight(); + let navtreeHeight,sideNavHeight; + if (typeof page_layout==='undefined' || page_layout==0) { /* DISABLE_INDEX=NO */ + contentHeight = windowHeight - headerHeight - footerHeight; + navtreeHeight = contentHeight; + sideNavHeight = contentHeight; + } else if (page_layout==1) { /* DISABLE_INDEX=YES */ + contentHeight = windowHeight - footerHeight; + navtreeHeight = windowHeight - headerHeight; + sideNavHeight = windowHeight; + } + navtree.css({height:navtreeHeight + "px"}); + sidenav.css({height:sideNavHeight + "px"}); + } + else + { + contentHeight = windowHeight - headerHeight; + } + content.css({height:contentHeight + "px"}); + if (location.hash.slice(1)) { + (document.getElementById(location.hash.slice(1))||document.body).scrollIntoView(); + } + } + + function collapseExpand() { + let newWidth; + if (sidenav.width()>0) { + newWidth=0; + } else { + const width = Cookie.readSetting(RESIZE_COOKIE_NAME,250); + newWidth = (width>250 && width<$(window).width()) ? width : 250; + } + restoreWidth(newWidth); + const sidenavWidth = $(sidenav).outerWidth(); + Cookie.writeSetting(RESIZE_COOKIE_NAME,sidenavWidth-barWidth); + } + + header = $("#top"); + content = $("#doc-content"); + footer = $("#nav-path"); + sidenav = $("#side-nav"); + if (!treeview) { +// title = $("#titlearea"); +// titleH = $(title).height(); +// let animating = false; +// content.on("scroll", function() { +// slideOpts = { duration: 200, +// step: function() { +// contentHeight = $(window).height() - header.outerHeight(); +// content.css({ height : contentHeight + "px" }); +// }, +// done: function() { animating=false; } +// }; +// if (content.scrollTop()>titleH && title.css('display')!='none' && !animating) { +// title.slideUp(slideOpts); +// animating=true; +// } else if (content.scrollTop()<=titleH && title.css('display')=='none' && !animating) { +// title.slideDown(slideOpts); +// animating=true; +// } +// }); + } else { + navtree = $("#nav-tree"); + $(".side-nav-resizable").resizable({resize: function(e, ui) { resizeWidth(); } }); + $(sidenav).resizable({ minWidth: 0 }); + } + $(window).resize(function() { resizeHeight(treeview); }); + if (treeview) + { + const device = navigator.userAgent.toLowerCase(); + const touch_device = device.match(/(iphone|ipod|ipad|android)/); + if (touch_device) { /* wider split bar for touch only devices */ + $(sidenav).css({ paddingRight:'20px' }); + $('.ui-resizable-e').css({ width:'20px' }); + $('#nav-sync').css({ right:'34px' }); + barWidth=20; + } + const width = Cookie.readSetting(RESIZE_COOKIE_NAME,250); + if (width) { restoreWidth(width); } else { resizeWidth(); } + } + resizeHeight(treeview); + const url = location.href; + const i=url.indexOf("#"); + if (i>=0) window.location.hash=url.substr(i); + const _preventDefault = function(evt) { evt.preventDefault(); }; + if (treeview) + { + $("#splitbar").bind("dragstart", _preventDefault).bind("selectstart", _preventDefault); + $(".ui-resizable-handle").dblclick(collapseExpand); + // workaround for firefox + $("body").css({overflow: "hidden"}); + } + $(window).on('load',function() { resizeHeight(treeview); }); +} +/* @license-end */ diff --git a/docs/search/all_0.js b/docs/search/all_0.js new file mode 100644 index 0000000..ccb2c43 --- /dev/null +++ b/docs/search/all_0.js @@ -0,0 +1,7 @@ +var searchData= +[ + ['aux_5fpercent_0',['aux_percent',['../structour__candata.html#a2f27833c993b361dae86811cf2dc8cc1',1,'our_candata']]], + ['aux_5fvoltage_1',['aux_voltage',['../structour__candata.html#ac6a49df6ef92171d255081f4193ecaba',1,'our_candata']]], + ['auxpercent_2',['auxPercent',['../class_backend.html#a2b9deb50de11a2fde07ef6589a31b7a0',1,'Backend']]], + ['auxvoltage_3',['auxVoltage',['../class_backend.html#a41e2e287304215732af6f9d6273792bb',1,'Backend']]] +]; diff --git a/docs/search/all_1.js b/docs/search/all_1.js new file mode 100644 index 0000000..5a5e80d --- /dev/null +++ b/docs/search/all_1.js @@ -0,0 +1,19 @@ +var searchData= +[ + ['backend_0',['Backend',['../class_backend.html',1,'Backend'],['../class_backend.html#a5bc0e9ea135112c07e021ebde56ec44f',1,'Backend::Backend()']]], + ['bike_5fspeed_1',['bike_speed',['../structour__candata.html#a91da22817613daa581a1caefe1009d61',1,'our_candata']]], + ['bike_5fstatus_2',['bike_status',['../structour__candata.html#aebfe1c507bccf95524c071e9a100917f',1,'our_candata']]], + ['bikespeed_3',['bikeSpeed',['../class_backend.html#adf1e224769b6c96c359475583e5dc159',1,'Backend']]], + ['bikestatus_4',['bikeStatus',['../class_backend.html#ad7c06e20ccfa73a5bd52187f39b97054',1,'Backend']]], + ['bms_5ferror_5',['bms_error',['../structour__candata.html#a64ea5fe3164ab59c15c3c9c72700486c',1,'our_candata']]], + ['bms_5ferror_5fcodes_6',['bms_error_codes',['../structour__candata.html#ab7715b7e4d16aee41a2919163a396ecd',1,'our_candata']]], + ['bms_5ffault_7',['bms_fault',['../structour__candata.html#aaae561b9ae7cc78f5279288aa49c4d82',1,'our_candata']]], + ['bms_5ftemperature_8',['bms_temperature',['../structour__candata.html#ad6d7fd57efd9400b510993c40b2c7f34',1,'our_candata']]], + ['bms_5fwarning_9',['bms_warning',['../structour__candata.html#a5e1f2c6c156021f7679cee5e2033e96c',1,'our_candata']]], + ['bmserror_10',['bmsError',['../class_backend.html#a3875076145e97af7fde2a1c37f543293',1,'Backend']]], + ['bmserrorcodes_11',['bmsErrorCodes',['../class_backend.html#a15330410228d1397f3bd0fb01a97f412',1,'Backend']]], + ['bmserrorcodesstring_12',['bmsErrorCodesString',['../class_backend.html#a177b020eecbfbec86fa331f146420021',1,'Backend']]], + ['bmsfault_13',['bmsFault',['../class_backend.html#a0bc7373b61657730a31b121851d26f99',1,'Backend']]], + ['bmstemp_14',['bmsTemp',['../class_backend.html#a6d30b487c228843a22da6fe82bc96003',1,'Backend']]], + ['bmswarning_15',['bmsWarning',['../class_backend.html#a7150ddb151a1f8c62ef3f2ac762b5fbe',1,'Backend']]] +]; diff --git a/docs/search/all_2.js b/docs/search/all_2.js new file mode 100644 index 0000000..f28b8bb --- /dev/null +++ b/docs/search/all_2.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['gpsdata_0',['GPSData',['../struct_g_p_s_data.html',1,'']]] +]; diff --git a/docs/search/all_3.js b/docs/search/all_3.js new file mode 100644 index 0000000..7dc4755 --- /dev/null +++ b/docs/search/all_3.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['high_5fcell_5ftemp_0',['high_cell_temp',['../structour__candata.html#af0bfcceda380408a9c3e54926389316e',1,'our_candata']]], + ['highcelltemp_1',['highCellTemp',['../class_backend.html#a338d6ee091433158a4a82ec6c60cbde9',1,'Backend']]], + ['highest_5fcell_5fvoltage_2',['highest_cell_voltage',['../structour__candata.html#abaf96e8325fdab008b6a6e4079c1a299',1,'our_candata']]] +]; diff --git a/docs/search/all_4.js b/docs/search/all_4.js new file mode 100644 index 0000000..eefc9c7 --- /dev/null +++ b/docs/search/all_4.js @@ -0,0 +1,8 @@ +var searchData= +[ + ['lat_0',['lat',['../class_backend.html#a8f93242ca98779058d3947e318b8944a',1,'Backend']]], + ['lon_1',['lon',['../class_backend.html#a21bc64c24fe21d47fde74754d4772c08',1,'Backend']]], + ['low_5fcell_5ftemp_2',['low_cell_temp',['../structour__candata.html#ab09abb61d44b018a5bf2df4272e3c6ee',1,'our_candata']]], + ['lowcelltemp_3',['lowCellTemp',['../class_backend.html#a2551568902d423cd2d6e7456fb68f218',1,'Backend']]], + ['lowest_5fcell_5fvoltage_4',['lowest_cell_voltage',['../structour__candata.html#a37097ff238e8e2be3ac37666f987954c',1,'our_candata']]] +]; diff --git a/docs/search/all_5.js b/docs/search/all_5.js new file mode 100644 index 0000000..633d8e2 --- /dev/null +++ b/docs/search/all_5.js @@ -0,0 +1,13 @@ +var searchData= +[ + ['mc_5ffault_0',['mc_fault',['../structour__candata.html#a43502a87bb2da1ac2d475d625acf555d',1,'our_candata']]], + ['mc_5ftemperature_1',['mc_temperature',['../structour__candata.html#a1fc64bcb813314dce32b25a7df8664ce',1,'our_candata']]], + ['mcfault_2',['mcFault',['../class_backend.html#a1cd3fc891b7d02f4abd62fc117bdca83',1,'Backend']]], + ['mctemp_3',['mcTemp',['../class_backend.html#a06ee9247c3f51b6e56ae40564100f73a',1,'Backend']]], + ['motor_5fon_4',['motor_on',['../structour__candata.html#a72b801f88be3552f7bfa59c2c971c775',1,'our_candata']]], + ['motor_5fspeed_5',['motor_speed',['../structour__candata.html#a1bcf43881237f8eea2d89486426c15bf',1,'our_candata']]], + ['motor_5ftemperature_6',['motor_temperature',['../structour__candata.html#ae42e90da9e66b88b650ebb77da6a8523',1,'our_candata']]], + ['motoron_7',['motorOn',['../class_backend.html#aff3f0f82e71ca4c549fb8c6a61be2310',1,'Backend']]], + ['motorspeed_8',['motorSpeed',['../class_backend.html#af248999c9a205fab70f7263943337b71',1,'Backend']]], + ['motortemp_9',['motorTemp',['../class_backend.html#a256e55ad5e78b997c6bc217c9decb29d',1,'Backend']]] +]; diff --git a/docs/search/all_6.js b/docs/search/all_6.js new file mode 100644 index 0000000..9126b52 --- /dev/null +++ b/docs/search/all_6.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['our_5fcandata_0',['our_candata',['../structour__candata.html',1,'']]] +]; diff --git a/docs/search/all_7.js b/docs/search/all_7.js new file mode 100644 index 0000000..5cf5887 --- /dev/null +++ b/docs/search/all_7.js @@ -0,0 +1,9 @@ +var searchData= +[ + ['pack_5fcurrent_0',['pack_current',['../structour__candata.html#ad88dd6a1e261f8008923d40ad22f3b7c',1,'our_candata']]], + ['pack_5fstate_5fof_5fcharge_1',['pack_state_of_charge',['../structour__candata.html#acd0602ac4d45088d4dfc5bda9391129d',1,'our_candata']]], + ['pack_5fvoltage_2',['pack_voltage',['../structour__candata.html#a6bf7ed9ae2fd95eee7dfad1ba677fd52',1,'our_candata']]], + ['packcurrent_3',['packCurrent',['../class_backend.html#a96cce8014d840e2e9e565849fd4d6f1c',1,'Backend']]], + ['packsoc_4',['packSOC',['../class_backend.html#a4c923e3177a05d7a235eef43c64dc3f4',1,'Backend']]], + ['packvoltage_5',['packVoltage',['../class_backend.html#aa114119bb0c61c19789114e85d0f9aec',1,'Backend']]] +]; diff --git a/docs/search/all_8.js b/docs/search/all_8.js new file mode 100644 index 0000000..751e4a2 --- /dev/null +++ b/docs/search/all_8.js @@ -0,0 +1,25 @@ +var searchData= +[ + ['setauxpercent_0',['setAuxPercent',['../class_backend.html#a181d4ef7a800a59f30970aff81935ff9',1,'Backend']]], + ['setauxvoltage_1',['setAuxVoltage',['../class_backend.html#aea1988760e23d3a71c8e59d3fbd629a3',1,'Backend']]], + ['setbikespeed_2',['setBikeSpeed',['../class_backend.html#a41f530c3353b3090ecb5e5be8cc285b6',1,'Backend']]], + ['setbikestatus_3',['setBikeStatus',['../class_backend.html#aa4dd42516324c53f45594ebfde561937',1,'Backend']]], + ['setbmserror_4',['setBmsError',['../class_backend.html#a5fb55f0d084b1526cd7722e9536367f3',1,'Backend']]], + ['setbmserrorcodes_5',['setBmsErrorCodes',['../class_backend.html#aa9a795644028d3c7e77563034dcbc20a',1,'Backend']]], + ['setbmserrorcodesstring_6',['setBmsErrorCodesString',['../class_backend.html#af2fcdd85b15e60d1ddbc2bc48391a6f9',1,'Backend']]], + ['setbmsfault_7',['setBmsFault',['../class_backend.html#abc484080dc62f7f36a96c72586b25799',1,'Backend']]], + ['setbmstemp_8',['setBmsTemp',['../class_backend.html#a4d63556bfd846e2f327a766620e8b8df',1,'Backend']]], + ['setbmswarning_9',['setBmsWarning',['../class_backend.html#a1ed8e3394afa439f9f16710f7896649c',1,'Backend']]], + ['sethighcelltemp_10',['setHighCellTemp',['../class_backend.html#a1e83e3ce8504f024857446e12b8845b7',1,'Backend']]], + ['setlat_11',['setLat',['../class_backend.html#ac6479865cb1424e3db4420da0877e215',1,'Backend']]], + ['setlon_12',['setLon',['../class_backend.html#a23d341fe68297b82782e786210022585',1,'Backend']]], + ['setlowcelltemp_13',['setLowCellTemp',['../class_backend.html#aba6f3cfe6aa6137dc7351bb44dfa45a7',1,'Backend']]], + ['setmcfault_14',['setMcFault',['../class_backend.html#abaf8de6f691d2259eb872b72537f7058',1,'Backend']]], + ['setmctemp_15',['setMcTemp',['../class_backend.html#a157a36598b32143e812533cf87dd272f',1,'Backend']]], + ['setmotoron_16',['setMotorOn',['../class_backend.html#ab4699e9d0f3fd20c7bf325e412d02031',1,'Backend']]], + ['setmotorspeed_17',['setMotorSpeed',['../class_backend.html#a3ae0f65b4936686f6e41154c2ea9b7f8',1,'Backend']]], + ['setmotortemp_18',['setMotorTemp',['../class_backend.html#aa2bf5fa75e4d89a37ff1310fb1d88aa2',1,'Backend']]], + ['setpackcurrent_19',['setPackCurrent',['../class_backend.html#a5ef79b5db160853a21fc658c662f99ce',1,'Backend']]], + ['setpacksoc_20',['setPackSOC',['../class_backend.html#af059700e1da309edb7e8e50d76141077',1,'Backend']]], + ['setpackvoltage_21',['setPackVoltage',['../class_backend.html#adb6236eaa2d963d07cf80154e84f0f59',1,'Backend']]] +]; diff --git a/docs/search/classes_0.js b/docs/search/classes_0.js new file mode 100644 index 0000000..be6f2f2 --- /dev/null +++ b/docs/search/classes_0.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['backend_0',['Backend',['../class_backend.html',1,'']]] +]; diff --git a/docs/search/classes_1.js b/docs/search/classes_1.js new file mode 100644 index 0000000..f28b8bb --- /dev/null +++ b/docs/search/classes_1.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['gpsdata_0',['GPSData',['../struct_g_p_s_data.html',1,'']]] +]; diff --git a/docs/search/classes_2.js b/docs/search/classes_2.js new file mode 100644 index 0000000..9126b52 --- /dev/null +++ b/docs/search/classes_2.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['our_5fcandata_0',['our_candata',['../structour__candata.html',1,'']]] +]; diff --git a/docs/search/close.svg b/docs/search/close.svg new file mode 100644 index 0000000..337d6cc --- /dev/null +++ b/docs/search/close.svg @@ -0,0 +1,18 @@ + + + + + + diff --git a/docs/search/functions_0.js b/docs/search/functions_0.js new file mode 100644 index 0000000..e6317ea --- /dev/null +++ b/docs/search/functions_0.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['auxpercent_0',['auxPercent',['../class_backend.html#a2b9deb50de11a2fde07ef6589a31b7a0',1,'Backend']]], + ['auxvoltage_1',['auxVoltage',['../class_backend.html#a41e2e287304215732af6f9d6273792bb',1,'Backend']]] +]; diff --git a/docs/search/functions_1.js b/docs/search/functions_1.js new file mode 100644 index 0000000..94d23da --- /dev/null +++ b/docs/search/functions_1.js @@ -0,0 +1,12 @@ +var searchData= +[ + ['backend_0',['Backend',['../class_backend.html#a5bc0e9ea135112c07e021ebde56ec44f',1,'Backend']]], + ['bikespeed_1',['bikeSpeed',['../class_backend.html#adf1e224769b6c96c359475583e5dc159',1,'Backend']]], + ['bikestatus_2',['bikeStatus',['../class_backend.html#ad7c06e20ccfa73a5bd52187f39b97054',1,'Backend']]], + ['bmserror_3',['bmsError',['../class_backend.html#a3875076145e97af7fde2a1c37f543293',1,'Backend']]], + ['bmserrorcodes_4',['bmsErrorCodes',['../class_backend.html#a15330410228d1397f3bd0fb01a97f412',1,'Backend']]], + ['bmserrorcodesstring_5',['bmsErrorCodesString',['../class_backend.html#a177b020eecbfbec86fa331f146420021',1,'Backend']]], + ['bmsfault_6',['bmsFault',['../class_backend.html#a0bc7373b61657730a31b121851d26f99',1,'Backend']]], + ['bmstemp_7',['bmsTemp',['../class_backend.html#a6d30b487c228843a22da6fe82bc96003',1,'Backend']]], + ['bmswarning_8',['bmsWarning',['../class_backend.html#a7150ddb151a1f8c62ef3f2ac762b5fbe',1,'Backend']]] +]; diff --git a/docs/search/functions_2.js b/docs/search/functions_2.js new file mode 100644 index 0000000..af6c06b --- /dev/null +++ b/docs/search/functions_2.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['highcelltemp_0',['highCellTemp',['../class_backend.html#a338d6ee091433158a4a82ec6c60cbde9',1,'Backend']]] +]; diff --git a/docs/search/functions_3.js b/docs/search/functions_3.js new file mode 100644 index 0000000..21e8b18 --- /dev/null +++ b/docs/search/functions_3.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['lat_0',['lat',['../class_backend.html#a8f93242ca98779058d3947e318b8944a',1,'Backend']]], + ['lon_1',['lon',['../class_backend.html#a21bc64c24fe21d47fde74754d4772c08',1,'Backend']]], + ['lowcelltemp_2',['lowCellTemp',['../class_backend.html#a2551568902d423cd2d6e7456fb68f218',1,'Backend']]] +]; diff --git a/docs/search/functions_4.js b/docs/search/functions_4.js new file mode 100644 index 0000000..cf2a3bf --- /dev/null +++ b/docs/search/functions_4.js @@ -0,0 +1,8 @@ +var searchData= +[ + ['mcfault_0',['mcFault',['../class_backend.html#a1cd3fc891b7d02f4abd62fc117bdca83',1,'Backend']]], + ['mctemp_1',['mcTemp',['../class_backend.html#a06ee9247c3f51b6e56ae40564100f73a',1,'Backend']]], + ['motoron_2',['motorOn',['../class_backend.html#aff3f0f82e71ca4c549fb8c6a61be2310',1,'Backend']]], + ['motorspeed_3',['motorSpeed',['../class_backend.html#af248999c9a205fab70f7263943337b71',1,'Backend']]], + ['motortemp_4',['motorTemp',['../class_backend.html#a256e55ad5e78b997c6bc217c9decb29d',1,'Backend']]] +]; diff --git a/docs/search/functions_5.js b/docs/search/functions_5.js new file mode 100644 index 0000000..8f7efb3 --- /dev/null +++ b/docs/search/functions_5.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['packcurrent_0',['packCurrent',['../class_backend.html#a96cce8014d840e2e9e565849fd4d6f1c',1,'Backend']]], + ['packsoc_1',['packSOC',['../class_backend.html#a4c923e3177a05d7a235eef43c64dc3f4',1,'Backend']]], + ['packvoltage_2',['packVoltage',['../class_backend.html#aa114119bb0c61c19789114e85d0f9aec',1,'Backend']]] +]; diff --git a/docs/search/functions_6.js b/docs/search/functions_6.js new file mode 100644 index 0000000..751e4a2 --- /dev/null +++ b/docs/search/functions_6.js @@ -0,0 +1,25 @@ +var searchData= +[ + ['setauxpercent_0',['setAuxPercent',['../class_backend.html#a181d4ef7a800a59f30970aff81935ff9',1,'Backend']]], + ['setauxvoltage_1',['setAuxVoltage',['../class_backend.html#aea1988760e23d3a71c8e59d3fbd629a3',1,'Backend']]], + ['setbikespeed_2',['setBikeSpeed',['../class_backend.html#a41f530c3353b3090ecb5e5be8cc285b6',1,'Backend']]], + ['setbikestatus_3',['setBikeStatus',['../class_backend.html#aa4dd42516324c53f45594ebfde561937',1,'Backend']]], + ['setbmserror_4',['setBmsError',['../class_backend.html#a5fb55f0d084b1526cd7722e9536367f3',1,'Backend']]], + ['setbmserrorcodes_5',['setBmsErrorCodes',['../class_backend.html#aa9a795644028d3c7e77563034dcbc20a',1,'Backend']]], + ['setbmserrorcodesstring_6',['setBmsErrorCodesString',['../class_backend.html#af2fcdd85b15e60d1ddbc2bc48391a6f9',1,'Backend']]], + ['setbmsfault_7',['setBmsFault',['../class_backend.html#abc484080dc62f7f36a96c72586b25799',1,'Backend']]], + ['setbmstemp_8',['setBmsTemp',['../class_backend.html#a4d63556bfd846e2f327a766620e8b8df',1,'Backend']]], + ['setbmswarning_9',['setBmsWarning',['../class_backend.html#a1ed8e3394afa439f9f16710f7896649c',1,'Backend']]], + ['sethighcelltemp_10',['setHighCellTemp',['../class_backend.html#a1e83e3ce8504f024857446e12b8845b7',1,'Backend']]], + ['setlat_11',['setLat',['../class_backend.html#ac6479865cb1424e3db4420da0877e215',1,'Backend']]], + ['setlon_12',['setLon',['../class_backend.html#a23d341fe68297b82782e786210022585',1,'Backend']]], + ['setlowcelltemp_13',['setLowCellTemp',['../class_backend.html#aba6f3cfe6aa6137dc7351bb44dfa45a7',1,'Backend']]], + ['setmcfault_14',['setMcFault',['../class_backend.html#abaf8de6f691d2259eb872b72537f7058',1,'Backend']]], + ['setmctemp_15',['setMcTemp',['../class_backend.html#a157a36598b32143e812533cf87dd272f',1,'Backend']]], + ['setmotoron_16',['setMotorOn',['../class_backend.html#ab4699e9d0f3fd20c7bf325e412d02031',1,'Backend']]], + ['setmotorspeed_17',['setMotorSpeed',['../class_backend.html#a3ae0f65b4936686f6e41154c2ea9b7f8',1,'Backend']]], + ['setmotortemp_18',['setMotorTemp',['../class_backend.html#aa2bf5fa75e4d89a37ff1310fb1d88aa2',1,'Backend']]], + ['setpackcurrent_19',['setPackCurrent',['../class_backend.html#a5ef79b5db160853a21fc658c662f99ce',1,'Backend']]], + ['setpacksoc_20',['setPackSOC',['../class_backend.html#af059700e1da309edb7e8e50d76141077',1,'Backend']]], + ['setpackvoltage_21',['setPackVoltage',['../class_backend.html#adb6236eaa2d963d07cf80154e84f0f59',1,'Backend']]] +]; diff --git a/docs/search/mag.svg b/docs/search/mag.svg new file mode 100644 index 0000000..ffb6cf0 --- /dev/null +++ b/docs/search/mag.svg @@ -0,0 +1,24 @@ + + + + + + + diff --git a/docs/search/mag_d.svg b/docs/search/mag_d.svg new file mode 100644 index 0000000..4122773 --- /dev/null +++ b/docs/search/mag_d.svg @@ -0,0 +1,24 @@ + + + + + + + diff --git a/docs/search/mag_sel.svg b/docs/search/mag_sel.svg new file mode 100644 index 0000000..553dba8 --- /dev/null +++ b/docs/search/mag_sel.svg @@ -0,0 +1,31 @@ + + + + + + + + + diff --git a/docs/search/mag_seld.svg b/docs/search/mag_seld.svg new file mode 100644 index 0000000..c906f84 --- /dev/null +++ b/docs/search/mag_seld.svg @@ -0,0 +1,31 @@ + + + + + + + + + diff --git a/docs/search/search.css b/docs/search/search.css new file mode 100644 index 0000000..d7b0f90 --- /dev/null +++ b/docs/search/search.css @@ -0,0 +1,291 @@ +/*---------------- Search Box positioning */ + +#main-menu > li:last-child { + /* This
  • object is the parent of the search bar */ + display: flex; + justify-content: center; + align-items: center; + height: 36px; + margin-right: 1em; +} + +/*---------------- Search box styling */ + +.SRPage * { + font-weight: normal; + line-height: normal; +} + +dark-mode-toggle { + margin-left: 5px; + display: flex; + float: right; +} + +#MSearchBox { + display: inline-block; + white-space : nowrap; + background: white; + border-radius: 0.65em; + box-shadow: inset 0.5px 0.5px 3px 0px #555; + z-index: 102; +} + +#MSearchBox .left { + display: inline-block; + vertical-align: middle; + height: 1.4em; +} + +#MSearchSelect { + display: inline-block; + vertical-align: middle; + width: 20px; + height: 19px; + background-image: url('mag_sel.svg'); + margin: 0 0 0 0.3em; + padding: 0; +} + +#MSearchSelectExt { + display: inline-block; + vertical-align: middle; + width: 10px; + height: 19px; + background-image: url('mag.svg'); + margin: 0 0 0 0.5em; + padding: 0; +} + + +#MSearchField { + display: inline-block; + vertical-align: middle; + width: 7.5em; + height: 19px; + margin: 0 0.15em; + padding: 0; + line-height: 1em; + border:none; + color: #909090; + outline: none; + font-family: Arial,Verdana,sans-serif; + -webkit-border-radius: 0px; + border-radius: 0px; + background: none; +} + +@media(hover: none) { + /* to avoid zooming on iOS */ + #MSearchField { + font-size: 16px; + } +} + +#MSearchBox .right { + display: inline-block; + vertical-align: middle; + width: 1.4em; + height: 1.4em; +} + +#MSearchClose { + display: none; + font-size: inherit; + background : none; + border: none; + margin: 0; + padding: 0; + outline: none; + +} + +#MSearchCloseImg { + padding: 0.3em; + margin: 0; +} + +.MSearchBoxActive #MSearchField { + color: black; +} + + + +/*---------------- Search filter selection */ + +#MSearchSelectWindow { + display: none; + position: absolute; + left: 0; top: 0; + border: 1px solid #90A5CE; + background-color: #F9FAFC; + z-index: 10001; + padding-top: 4px; + padding-bottom: 4px; + -moz-border-radius: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +.SelectItem { + font: 8pt Arial,Verdana,sans-serif; + padding-left: 2px; + padding-right: 12px; + border: 0px; +} + +span.SelectionMark { + margin-right: 4px; + font-family: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; + outline-style: none; + text-decoration: none; +} + +a.SelectItem { + display: block; + outline-style: none; + color: black; + text-decoration: none; + padding-left: 6px; + padding-right: 12px; +} + +a.SelectItem:focus, +a.SelectItem:active { + color: black; + outline-style: none; + text-decoration: none; +} + +a.SelectItem:hover { + color: white; + background-color: #3D578C; + outline-style: none; + text-decoration: none; + cursor: pointer; + display: block; +} + +/*---------------- Search results window */ + +iframe#MSearchResults { + /*width: 60ex;*/ + height: 15em; +} + +#MSearchResultsWindow { + display: none; + position: absolute; + left: 0; top: 0; + border: 1px solid black; + background-color: #EEF1F7; + z-index:10000; + width: 300px; + height: 400px; + overflow: auto; +} + +/* ----------------------------------- */ + + +#SRIndex { + clear:both; +} + +.SREntry { + font-size: 10pt; + padding-left: 1ex; +} + +.SRPage .SREntry { + font-size: 8pt; + padding: 1px 5px; +} + +div.SRPage { + margin: 5px 2px; + background-color: #EEF1F7; +} + +.SRChildren { + padding-left: 3ex; padding-bottom: .5em +} + +.SRPage .SRChildren { + display: none; +} + +.SRSymbol { + font-weight: bold; + color: #425E97; + font-family: Arial,Verdana,sans-serif; + text-decoration: none; + outline: none; +} + +a.SRScope { + display: block; + color: #425E97; + font-family: Arial,Verdana,sans-serif; + font-size: 8pt; + text-decoration: none; + outline: none; +} + +a.SRSymbol:focus, a.SRSymbol:active, +a.SRScope:focus, a.SRScope:active { + text-decoration: underline; +} + +span.SRScope { + padding-left: 4px; + font-family: Arial,Verdana,sans-serif; +} + +.SRPage .SRStatus { + padding: 2px 5px; + font-size: 8pt; + font-style: italic; + font-family: Arial,Verdana,sans-serif; +} + +.SRResult { + display: none; +} + +div.searchresults { + margin-left: 10px; + margin-right: 10px; +} + +/*---------------- External search page results */ + +.pages b { + color: white; + padding: 5px 5px 3px 5px; + background-image: url("../tab_a.png"); + background-repeat: repeat-x; + text-shadow: 0 1px 1px #000000; +} + +.pages { + line-height: 17px; + margin-left: 4px; + text-decoration: none; +} + +.hl { + font-weight: bold; +} + +#searchresults { + margin-bottom: 20px; +} + +.searchpages { + margin-top: 10px; +} + diff --git a/docs/search/search.js b/docs/search/search.js new file mode 100644 index 0000000..666af01 --- /dev/null +++ b/docs/search/search.js @@ -0,0 +1,694 @@ +/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file + */ +const SEARCH_COOKIE_NAME = ''+'search_grp'; + +const searchResults = new SearchResults(); + +/* A class handling everything associated with the search panel. + + Parameters: + name - The name of the global variable that will be + storing this instance. Is needed to be able to set timeouts. + resultPath - path to use for external files +*/ +function SearchBox(name, resultsPath, extension) { + if (!name || !resultsPath) { alert("Missing parameters to SearchBox."); } + if (!extension || extension == "") { extension = ".html"; } + + function getXPos(item) { + let x = 0; + if (item.offsetWidth) { + while (item && item!=document.body) { + x += item.offsetLeft; + item = item.offsetParent; + } + } + return x; + } + + function getYPos(item) { + let y = 0; + if (item.offsetWidth) { + while (item && item!=document.body) { + y += item.offsetTop; + item = item.offsetParent; + } + } + return y; + } + + // ---------- Instance variables + this.name = name; + this.resultsPath = resultsPath; + this.keyTimeout = 0; + this.keyTimeoutLength = 500; + this.closeSelectionTimeout = 300; + this.lastSearchValue = ""; + this.lastResultsPage = ""; + this.hideTimeout = 0; + this.searchIndex = 0; + this.searchActive = false; + this.extension = extension; + + // ----------- DOM Elements + + this.DOMSearchField = () => document.getElementById("MSearchField"); + this.DOMSearchSelect = () => document.getElementById("MSearchSelect"); + this.DOMSearchSelectWindow = () => document.getElementById("MSearchSelectWindow"); + this.DOMPopupSearchResults = () => document.getElementById("MSearchResults"); + this.DOMPopupSearchResultsWindow = () => document.getElementById("MSearchResultsWindow"); + this.DOMSearchClose = () => document.getElementById("MSearchClose"); + this.DOMSearchBox = () => document.getElementById("MSearchBox"); + + // ------------ Event Handlers + + // Called when focus is added or removed from the search field. + this.OnSearchFieldFocus = function(isActive) { + this.Activate(isActive); + } + + this.OnSearchSelectShow = function() { + const searchSelectWindow = this.DOMSearchSelectWindow(); + const searchField = this.DOMSearchSelect(); + + const left = getXPos(searchField); + const top = getYPos(searchField) + searchField.offsetHeight; + + // show search selection popup + searchSelectWindow.style.display='block'; + searchSelectWindow.style.left = left + 'px'; + searchSelectWindow.style.top = top + 'px'; + + // stop selection hide timer + if (this.hideTimeout) { + clearTimeout(this.hideTimeout); + this.hideTimeout=0; + } + return false; // to avoid "image drag" default event + } + + this.OnSearchSelectHide = function() { + this.hideTimeout = setTimeout(this.CloseSelectionWindow.bind(this), + this.closeSelectionTimeout); + } + + // Called when the content of the search field is changed. + this.OnSearchFieldChange = function(evt) { + if (this.keyTimeout) { // kill running timer + clearTimeout(this.keyTimeout); + this.keyTimeout = 0; + } + + const e = evt ? evt : window.event; // for IE + if (e.keyCode==40 || e.keyCode==13) { + if (e.shiftKey==1) { + this.OnSearchSelectShow(); + const win=this.DOMSearchSelectWindow(); + for (let i=0;i do a search + this.Search(); + } + } + + this.OnSearchSelectKey = function(evt) { + const e = (evt) ? evt : window.event; // for IE + if (e.keyCode==40 && this.searchIndex0) { // Up + this.searchIndex--; + this.OnSelectItem(this.searchIndex); + } else if (e.keyCode==13 || e.keyCode==27) { + e.stopPropagation(); + this.OnSelectItem(this.searchIndex); + this.CloseSelectionWindow(); + this.DOMSearchField().focus(); + } + return false; + } + + // --------- Actions + + // Closes the results window. + this.CloseResultsWindow = function() { + this.DOMPopupSearchResultsWindow().style.display = 'none'; + this.DOMSearchClose().style.display = 'none'; + this.Activate(false); + } + + this.CloseSelectionWindow = function() { + this.DOMSearchSelectWindow().style.display = 'none'; + } + + // Performs a search. + this.Search = function() { + this.keyTimeout = 0; + + // strip leading whitespace + const searchValue = this.DOMSearchField().value.replace(/^ +/, ""); + + const code = searchValue.toLowerCase().charCodeAt(0); + let idxChar = searchValue.substr(0, 1).toLowerCase(); + if ( 0xD800 <= code && code <= 0xDBFF && searchValue > 1) { // surrogate pair + idxChar = searchValue.substr(0, 2); + } + + let jsFile; + let idx = indexSectionsWithContent[this.searchIndex].indexOf(idxChar); + if (idx!=-1) { + const hexCode=idx.toString(16); + jsFile = this.resultsPath + indexSectionNames[this.searchIndex] + '_' + hexCode + '.js'; + } + + const loadJS = function(url, impl, loc) { + const scriptTag = document.createElement('script'); + scriptTag.src = url; + scriptTag.onload = impl; + scriptTag.onreadystatechange = impl; + loc.appendChild(scriptTag); + } + + const domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow(); + const domSearchBox = this.DOMSearchBox(); + const domPopupSearchResults = this.DOMPopupSearchResults(); + const domSearchClose = this.DOMSearchClose(); + const resultsPath = this.resultsPath; + + const handleResults = function() { + document.getElementById("Loading").style.display="none"; + if (typeof searchData !== 'undefined') { + createResults(resultsPath); + document.getElementById("NoMatches").style.display="none"; + } + + if (idx!=-1) { + searchResults.Search(searchValue); + } else { // no file with search results => force empty search results + searchResults.Search('===='); + } + + if (domPopupSearchResultsWindow.style.display!='block') { + domSearchClose.style.display = 'inline-block'; + let left = getXPos(domSearchBox) + 150; + let top = getYPos(domSearchBox) + 20; + domPopupSearchResultsWindow.style.display = 'block'; + left -= domPopupSearchResults.offsetWidth; + const maxWidth = document.body.clientWidth; + const maxHeight = document.body.clientHeight; + let width = 300; + if (left<10) left=10; + if (width+left+8>maxWidth) width=maxWidth-left-8; + let height = 400; + if (height+top+8>maxHeight) height=maxHeight-top-8; + domPopupSearchResultsWindow.style.top = top + 'px'; + domPopupSearchResultsWindow.style.left = left + 'px'; + domPopupSearchResultsWindow.style.width = width + 'px'; + domPopupSearchResultsWindow.style.height = height + 'px'; + } + } + + if (jsFile) { + loadJS(jsFile, handleResults, this.DOMPopupSearchResultsWindow()); + } else { + handleResults(); + } + + this.lastSearchValue = searchValue; + } + + // -------- Activation Functions + + // Activates or deactivates the search panel, resetting things to + // their default values if necessary. + this.Activate = function(isActive) { + if (isActive || // open it + this.DOMPopupSearchResultsWindow().style.display == 'block' + ) { + this.DOMSearchBox().className = 'MSearchBoxActive'; + this.searchActive = true; + } else if (!isActive) { // directly remove the panel + this.DOMSearchBox().className = 'MSearchBoxInactive'; + this.searchActive = false; + this.lastSearchValue = '' + this.lastResultsPage = ''; + this.DOMSearchField().value = ''; + } + } +} + +// ----------------------------------------------------------------------- + +// The class that handles everything on the search results page. +function SearchResults() { + + function convertToId(search) { + let result = ''; + for (let i=0;i. + this.lastMatchCount = 0; + this.lastKey = 0; + this.repeatOn = false; + + // Toggles the visibility of the passed element ID. + this.FindChildElement = function(id) { + const parentElement = document.getElementById(id); + let element = parentElement.firstChild; + + while (element && element!=parentElement) { + if (element.nodeName.toLowerCase() == 'div' && element.className == 'SRChildren') { + return element; + } + + if (element.nodeName.toLowerCase() == 'div' && element.hasChildNodes()) { + element = element.firstChild; + } else if (element.nextSibling) { + element = element.nextSibling; + } else { + do { + element = element.parentNode; + } + while (element && element!=parentElement && !element.nextSibling); + + if (element && element!=parentElement) { + element = element.nextSibling; + } + } + } + } + + this.Toggle = function(id) { + const element = this.FindChildElement(id); + if (element) { + if (element.style.display == 'block') { + element.style.display = 'none'; + } else { + element.style.display = 'block'; + } + } + } + + // Searches for the passed string. If there is no parameter, + // it takes it from the URL query. + // + // Always returns true, since other documents may try to call it + // and that may or may not be possible. + this.Search = function(search) { + if (!search) { // get search word from URL + search = window.location.search; + search = search.substring(1); // Remove the leading '?' + search = unescape(search); + } + + search = search.replace(/^ +/, ""); // strip leading spaces + search = search.replace(/ +$/, ""); // strip trailing spaces + search = search.toLowerCase(); + search = convertToId(search); + + const resultRows = document.getElementsByTagName("div"); + let matches = 0; + + let i = 0; + while (i < resultRows.length) { + const row = resultRows.item(i); + if (row.className == "SRResult") { + let rowMatchName = row.id.toLowerCase(); + rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); // strip 'sr123_' + + if (search.length<=rowMatchName.length && + rowMatchName.substr(0, search.length)==search) { + row.style.display = 'block'; + matches++; + } else { + row.style.display = 'none'; + } + } + i++; + } + document.getElementById("Searching").style.display='none'; + if (matches == 0) { // no results + document.getElementById("NoMatches").style.display='block'; + } else { // at least one result + document.getElementById("NoMatches").style.display='none'; + } + this.lastMatchCount = matches; + return true; + } + + // return the first item with index index or higher that is visible + this.NavNext = function(index) { + let focusItem; + for (;;) { + const focusName = 'Item'+index; + focusItem = document.getElementById(focusName); + if (focusItem && focusItem.parentNode.parentNode.style.display=='block') { + break; + } else if (!focusItem) { // last element + break; + } + focusItem=null; + index++; + } + return focusItem; + } + + this.NavPrev = function(index) { + let focusItem; + for (;;) { + const focusName = 'Item'+index; + focusItem = document.getElementById(focusName); + if (focusItem && focusItem.parentNode.parentNode.style.display=='block') { + break; + } else if (!focusItem) { // last element + break; + } + focusItem=null; + index--; + } + return focusItem; + } + + this.ProcessKeys = function(e) { + if (e.type == "keydown") { + this.repeatOn = false; + this.lastKey = e.keyCode; + } else if (e.type == "keypress") { + if (!this.repeatOn) { + if (this.lastKey) this.repeatOn = true; + return false; // ignore first keypress after keydown + } + } else if (e.type == "keyup") { + this.lastKey = 0; + this.repeatOn = false; + } + return this.lastKey!=0; + } + + this.Nav = function(evt,itemIndex) { + const e = (evt) ? evt : window.event; // for IE + if (e.keyCode==13) return true; + if (!this.ProcessKeys(e)) return false; + + if (this.lastKey==38) { // Up + const newIndex = itemIndex-1; + let focusItem = this.NavPrev(newIndex); + if (focusItem) { + let child = this.FindChildElement(focusItem.parentNode.parentNode.id); + if (child && child.style.display == 'block') { // children visible + let n=0; + let tmpElem; + for (;;) { // search for last child + tmpElem = document.getElementById('Item'+newIndex+'_c'+n); + if (tmpElem) { + focusItem = tmpElem; + } else { // found it! + break; + } + n++; + } + } + } + if (focusItem) { + focusItem.focus(); + } else { // return focus to search field + document.getElementById("MSearchField").focus(); + } + } else if (this.lastKey==40) { // Down + const newIndex = itemIndex+1; + let focusItem; + const item = document.getElementById('Item'+itemIndex); + const elem = this.FindChildElement(item.parentNode.parentNode.id); + if (elem && elem.style.display == 'block') { // children visible + focusItem = document.getElementById('Item'+itemIndex+'_c0'); + } + if (!focusItem) focusItem = this.NavNext(newIndex); + if (focusItem) focusItem.focus(); + } else if (this.lastKey==39) { // Right + const item = document.getElementById('Item'+itemIndex); + const elem = this.FindChildElement(item.parentNode.parentNode.id); + if (elem) elem.style.display = 'block'; + } else if (this.lastKey==37) { // Left + const item = document.getElementById('Item'+itemIndex); + const elem = this.FindChildElement(item.parentNode.parentNode.id); + if (elem) elem.style.display = 'none'; + } else if (this.lastKey==27) { // Escape + e.stopPropagation(); + searchBox.CloseResultsWindow(); + document.getElementById("MSearchField").focus(); + } else if (this.lastKey==13) { // Enter + return true; + } + return false; + } + + this.NavChild = function(evt,itemIndex,childIndex) { + const e = (evt) ? evt : window.event; // for IE + if (e.keyCode==13) return true; + if (!this.ProcessKeys(e)) return false; + + if (this.lastKey==38) { // Up + if (childIndex>0) { + const newIndex = childIndex-1; + document.getElementById('Item'+itemIndex+'_c'+newIndex).focus(); + } else { // already at first child, jump to parent + document.getElementById('Item'+itemIndex).focus(); + } + } else if (this.lastKey==40) { // Down + const newIndex = childIndex+1; + let elem = document.getElementById('Item'+itemIndex+'_c'+newIndex); + if (!elem) { // last child, jump to parent next parent + elem = this.NavNext(itemIndex+1); + } + if (elem) { + elem.focus(); + } + } else if (this.lastKey==27) { // Escape + e.stopPropagation(); + searchBox.CloseResultsWindow(); + document.getElementById("MSearchField").focus(); + } else if (this.lastKey==13) { // Enter + return true; + } + return false; + } +} + +function createResults(resultsPath) { + + function setKeyActions(elem,action) { + elem.setAttribute('onkeydown',action); + elem.setAttribute('onkeypress',action); + elem.setAttribute('onkeyup',action); + } + + function setClassAttr(elem,attr) { + elem.setAttribute('class',attr); + elem.setAttribute('className',attr); + } + + const results = document.getElementById("SRResults"); + results.innerHTML = ''; + searchData.forEach((elem,index) => { + const id = elem[0]; + const srResult = document.createElement('div'); + srResult.setAttribute('id','SR_'+id); + setClassAttr(srResult,'SRResult'); + const srEntry = document.createElement('div'); + setClassAttr(srEntry,'SREntry'); + const srLink = document.createElement('a'); + srLink.setAttribute('id','Item'+index); + setKeyActions(srLink,'return searchResults.Nav(event,'+index+')'); + setClassAttr(srLink,'SRSymbol'); + srLink.innerHTML = elem[1][0]; + srEntry.appendChild(srLink); + if (elem[1].length==2) { // single result + srLink.setAttribute('href',resultsPath+elem[1][1][0]); + srLink.setAttribute('onclick','searchBox.CloseResultsWindow()'); + if (elem[1][1][1]) { + srLink.setAttribute('target','_parent'); + } else { + srLink.setAttribute('target','_blank'); + } + const srScope = document.createElement('span'); + setClassAttr(srScope,'SRScope'); + srScope.innerHTML = elem[1][1][2]; + srEntry.appendChild(srScope); + } else { // multiple results + srLink.setAttribute('href','javascript:searchResults.Toggle("SR_'+id+'")'); + const srChildren = document.createElement('div'); + setClassAttr(srChildren,'SRChildren'); + for (let c=0; c + + + + + + +BOLT Dash (C++): Member List + + + + + + + + + + + + + + + + +
    +
    + + + + + + +
    +
    BOLT Dash (C++) +
    +
    +
    + + + + + + + + +
    +
    + +
    +
    +
    + +
    + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + +
    +
    GPSData Member List
    +
    +
    + +

    This is the complete list of members for GPSData, including all inherited members.

    + + + + + + + + +
    altitude (defined in GPSData)GPSData
    date (defined in GPSData)GPSData
    fix (defined in GPSData)GPSData
    latitude (defined in GPSData)GPSData
    longitude (defined in GPSData)GPSData
    satellites (defined in GPSData)GPSData
    time (defined in GPSData)GPSData
    +
    + + + + diff --git a/docs/struct_g_p_s_data.html b/docs/struct_g_p_s_data.html new file mode 100644 index 0000000..386dfd7 --- /dev/null +++ b/docs/struct_g_p_s_data.html @@ -0,0 +1,144 @@ + + + + + + + +BOLT Dash (C++): GPSData Struct Reference + + + + + + + + + + + + + + + + +
    +
    + + + + + + +
    +
    BOLT Dash (C++) +
    +
    +
    + + + + + + + + +
    +
    + +
    +
    +
    + +
    + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + +
    + +
    GPSData Struct Reference
    +
    +
    + + + + + + + + + + + + + + + + +

    +Public Attributes

    +double latitude = 0.0
     
    +double longitude = 0.0
     
    +std::string time = ""
     
    +std::string date = ""
     
    +double altitude = 0.0
     
    +int satellites = 0
     
    +std::string fix = "Invalid"
     
    +
    The documentation for this struct was generated from the following file: +
    +
    + + + + diff --git a/docs/structour__candata-members.html b/docs/structour__candata-members.html new file mode 100644 index 0000000..37d55c9 --- /dev/null +++ b/docs/structour__candata-members.html @@ -0,0 +1,136 @@ + + + + + + + +BOLT Dash (C++): Member List + + + + + + + + + + + + + + + + +
    +
    + + + + + + +
    +
    BOLT Dash (C++) +
    +
    +
    + + + + + + + + +
    +
    + +
    +
    +
    + + + + + + diff --git a/docs/structour__candata.html b/docs/structour__candata.html new file mode 100644 index 0000000..eea5e5f --- /dev/null +++ b/docs/structour__candata.html @@ -0,0 +1,214 @@ + + + + + + + +BOLT Dash (C++): our_candata Struct Reference + + + + + + + + + + + + + + + + +
    +
    + + + + + + +
    +
    BOLT Dash (C++) +
    +
    +
    + + + + + + + + +
    +
    + +
    +
    +
    + +
    + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + +
    + +
    our_candata Struct Reference
    +
    +
    + +

    This is a struct that contains all the data that we get from the CAN bus and is used in the dash project. + More...

    + +

    #include <can.h>

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    +Public Attributes

    +uint8_t aux_voltage {}
     The voltage of the aux pack.
     
    +uint8_t aux_percent {}
     The battery percentage of the aux pack.
     
    +uint8_t pack_state_of_charge {}
     The state of charge of the main pack as a percentage.
     
    +uint16_t pack_voltage {}
     The voltage of the main pack.
     
    +int16_t pack_current {}
     The current of the main pack.
     
    +uint16_t high_cell_temp {}
     The temperature of the hottest cell group in the main pack.
     
    +uint16_t low_cell_temp {}
     The temperature of the coldest cell group in the main pack.
     
    +int16_t motor_temperature {}
     The temperature of the motor.
     
    +uint16_t bms_temperature {}
     The temperature of the BMS.
     
    +uint16_t mc_temperature {}
     The temperature of the motor controller.
     
    +int16_t motor_speed {}
     The RPM of the motor.
     
    +int16_t bike_speed {}
     The speed of the bike in mph.
     
    +uint8_t bms_fault {}
     The fault status of the BMS.
     
    +uint8_t bms_error {}
     Whether the BMS has any errors.
     
    +uint8_t bms_warning {}
     Whether the BMS has any warnings.
     
    +uint32_t bms_error_codes {}
     The actual error codes of the BMS concatenated together.
     
    +uint8_t mc_fault {}
     Whether or no the MC has a fault.
     
    +uint8_t motor_on {}
     Whether or not the motor is active.
     
    +uint8_t bike_status {}
     The internal state of the bike, not used rn.
     
    +uint16_t highest_cell_voltage {}
     The highest cell voltage in the main pack.
     
    +uint16_t lowest_cell_voltage {}
     The lowest cell voltage in the main pack.
     
    +

    Detailed Description

    +

    This is a struct that contains all the data that we get from the CAN bus and is used in the dash project.

    +

    The documentation for this struct was generated from the following file: +
    +
    + + + + diff --git a/docs/structour__candata.js b/docs/structour__candata.js new file mode 100644 index 0000000..3055a68 --- /dev/null +++ b/docs/structour__candata.js @@ -0,0 +1,24 @@ +var structour__candata = +[ + [ "aux_percent", "structour__candata.html#a2f27833c993b361dae86811cf2dc8cc1", null ], + [ "aux_voltage", "structour__candata.html#ac6a49df6ef92171d255081f4193ecaba", null ], + [ "bike_speed", "structour__candata.html#a91da22817613daa581a1caefe1009d61", null ], + [ "bike_status", "structour__candata.html#aebfe1c507bccf95524c071e9a100917f", null ], + [ "bms_error", "structour__candata.html#a64ea5fe3164ab59c15c3c9c72700486c", null ], + [ "bms_error_codes", "structour__candata.html#ab7715b7e4d16aee41a2919163a396ecd", null ], + [ "bms_fault", "structour__candata.html#aaae561b9ae7cc78f5279288aa49c4d82", null ], + [ "bms_temperature", "structour__candata.html#ad6d7fd57efd9400b510993c40b2c7f34", null ], + [ "bms_warning", "structour__candata.html#a5e1f2c6c156021f7679cee5e2033e96c", null ], + [ "high_cell_temp", "structour__candata.html#af0bfcceda380408a9c3e54926389316e", null ], + [ "highest_cell_voltage", "structour__candata.html#abaf96e8325fdab008b6a6e4079c1a299", null ], + [ "low_cell_temp", "structour__candata.html#ab09abb61d44b018a5bf2df4272e3c6ee", null ], + [ "lowest_cell_voltage", "structour__candata.html#a37097ff238e8e2be3ac37666f987954c", null ], + [ "mc_fault", "structour__candata.html#a43502a87bb2da1ac2d475d625acf555d", null ], + [ "mc_temperature", "structour__candata.html#a1fc64bcb813314dce32b25a7df8664ce", null ], + [ "motor_on", "structour__candata.html#a72b801f88be3552f7bfa59c2c971c775", null ], + [ "motor_speed", "structour__candata.html#a1bcf43881237f8eea2d89486426c15bf", null ], + [ "motor_temperature", "structour__candata.html#ae42e90da9e66b88b650ebb77da6a8523", null ], + [ "pack_current", "structour__candata.html#ad88dd6a1e261f8008923d40ad22f3b7c", null ], + [ "pack_state_of_charge", "structour__candata.html#acd0602ac4d45088d4dfc5bda9391129d", null ], + [ "pack_voltage", "structour__candata.html#a6bf7ed9ae2fd95eee7dfad1ba677fd52", null ] +]; \ No newline at end of file diff --git a/docs/sync_off.png b/docs/sync_off.png new file mode 100644 index 0000000..3b443fc Binary files /dev/null and b/docs/sync_off.png differ diff --git a/docs/sync_on.png b/docs/sync_on.png new file mode 100644 index 0000000..e08320f Binary files /dev/null and b/docs/sync_on.png differ diff --git a/docs/tab_a.png b/docs/tab_a.png new file mode 100644 index 0000000..3b725c4 Binary files /dev/null and b/docs/tab_a.png differ diff --git a/docs/tab_ad.png b/docs/tab_ad.png new file mode 100644 index 0000000..e34850a Binary files /dev/null and b/docs/tab_ad.png differ diff --git a/docs/tab_b.png b/docs/tab_b.png new file mode 100644 index 0000000..e2b4a86 Binary files /dev/null and b/docs/tab_b.png differ diff --git a/docs/tab_bd.png b/docs/tab_bd.png new file mode 100644 index 0000000..91c2524 Binary files /dev/null and b/docs/tab_bd.png differ diff --git a/docs/tab_h.png b/docs/tab_h.png new file mode 100644 index 0000000..fd5cb70 Binary files /dev/null and b/docs/tab_h.png differ diff --git a/docs/tab_hd.png b/docs/tab_hd.png new file mode 100644 index 0000000..2489273 Binary files /dev/null and b/docs/tab_hd.png differ diff --git a/docs/tab_s.png b/docs/tab_s.png new file mode 100644 index 0000000..ab478c9 Binary files /dev/null and b/docs/tab_s.png differ diff --git a/docs/tab_sd.png b/docs/tab_sd.png new file mode 100644 index 0000000..757a565 Binary files /dev/null and b/docs/tab_sd.png differ diff --git a/docs/tabs.css b/docs/tabs.css new file mode 100644 index 0000000..edbb424 --- /dev/null +++ b/docs/tabs.css @@ -0,0 +1 @@ +.sm{position:relative;z-index:9999}.sm,.sm ul,.sm li{display:block;list-style:none;margin:0;padding:0;line-height:normal;direction:ltr;text-align:left;-webkit-tap-highlight-color:rgba(0,0,0,0)}.sm-rtl,.sm-rtl ul,.sm-rtl li{direction:rtl;text-align:right}.sm>li>h1,.sm>li>h2,.sm>li>h3,.sm>li>h4,.sm>li>h5,.sm>li>h6{margin:0;padding:0}.sm ul{display:none}.sm li,.sm a{position:relative}.sm a{display:block}.sm a.disabled{cursor:not-allowed}.sm:after{content:"\00a0";display:block;height:0;font:0/0 serif;clear:both;visibility:hidden;overflow:hidden}.sm,.sm *,.sm *:before,.sm *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.main-menu-btn{position:relative;display:inline-block;width:36px;height:36px;text-indent:36px;margin-left:8px;white-space:nowrap;overflow:hidden;cursor:pointer;-webkit-tap-highlight-color:rgba(0,0,0,0)}.main-menu-btn-icon,.main-menu-btn-icon:before,.main-menu-btn-icon:after{position:absolute;top:50%;left:2px;height:2px;width:24px;background:#364D7C;-webkit-transition:all .25s;transition:all .25s}.main-menu-btn-icon:before{content:'';top:-7px;left:0}.main-menu-btn-icon:after{content:'';top:7px;left:0}#main-menu-state:checked ~ .main-menu-btn .main-menu-btn-icon{height:0}#main-menu-state:checked ~ .main-menu-btn .main-menu-btn-icon:before{top:0;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}#main-menu-state:checked ~ .main-menu-btn .main-menu-btn-icon:after{top:0;-webkit-transform:rotate(45deg);transform:rotate(45deg)}#main-menu-state{position:absolute;width:1px;height:1px;margin:-1px;border:0;padding:0;overflow:hidden;clip:rect(1px,1px,1px,1px)}#main-menu-state:not(:checked) ~ #main-menu{display:none}#main-menu-state:checked ~ #main-menu{display:block}@media(min-width:768px){.main-menu-btn{position:absolute;top:-99999px}#main-menu-state:not(:checked) ~ #main-menu{display:block}}.sm-dox{background-image:url('tab_b.png')}.sm-dox a,.sm-dox a:focus,.sm-dox a:hover,.sm-dox a:active{padding:0 12px;padding-right:43px;font-family:'Lucida Grande',Geneva,Helvetica,Arial,sans-serif;font-size:13px;font-weight:bold;line-height:36px;text-decoration:none;text-shadow:0px 1px 1px rgba(255, 255, 255, 0.9);color:#283A5D;outline:0}.sm-dox a:hover{background-image:url('tab_a.png');background-repeat:repeat-x;color:white;text-shadow:0px 1px 1px rgba(0, 0, 0, 1.0)}.sm-dox a.current{color:#d23600}.sm-dox a.disabled{color:#bbb}.sm-dox a span.sub-arrow{position:absolute;top:50%;margin-top:-14px;left:auto;right:3px;width:28px;height:28px;overflow:hidden;font:bold 12px/28px monospace !important;text-align:center;text-shadow:none;background:rgba(255, 255, 255, 0.5);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.sm-dox a span.sub-arrow:before{display:block;content:'+'}.sm-dox a.highlighted span.sub-arrow:before{display:block;content:'-'}.sm-dox>li:first-child>a,.sm-dox>li:first-child>:not(ul) a{-moz-border-radius:5px 5px 0 0;-webkit-border-radius:5px;border-radius:5px 5px 0 0}.sm-dox>li:last-child>a,.sm-dox>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul{-moz-border-radius:0 0 5px 5px;-webkit-border-radius:0;border-radius:0 0 5px 5px}.sm-dox>li:last-child>a.highlighted,.sm-dox>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.sm-dox ul{background:white}.sm-dox ul a,.sm-dox ul a:focus,.sm-dox ul a:hover,.sm-dox ul a:active{font-size:12px;border-left:8px solid transparent;line-height:36px;text-shadow:none;background-color:white;background-image:none}.sm-dox ul a:hover{background-image:url('tab_a.png');background-repeat:repeat-x;color:white;text-shadow:0 1px 1px black}.sm-dox ul ul a,.sm-dox ul ul a:hover,.sm-dox ul ul a:focus,.sm-dox ul ul a:active{border-left:16px solid transparent}.sm-dox ul ul ul a,.sm-dox ul ul ul a:hover,.sm-dox ul ul ul a:focus,.sm-dox ul ul ul a:active{border-left:24px solid transparent}.sm-dox ul ul ul ul a,.sm-dox ul ul ul ul a:hover,.sm-dox ul ul ul ul a:focus,.sm-dox ul ul ul ul a:active{border-left:32px solid transparent}.sm-dox ul ul ul ul ul a,.sm-dox ul ul ul ul ul a:hover,.sm-dox ul ul ul ul ul a:focus,.sm-dox ul ul ul ul ul a:active{border-left:40px solid transparent}@media(min-width:768px){.sm-dox ul{position:absolute;width:12em}.sm-dox li{float:left}.sm-dox.sm-rtl li{float:right}.sm-dox ul li,.sm-dox.sm-rtl ul li,.sm-dox.sm-vertical li{float:none}.sm-dox a{white-space:nowrap}.sm-dox ul a,.sm-dox.sm-vertical a{white-space:normal}.sm-dox .sm-nowrap>li>a,.sm-dox .sm-nowrap>li>:not(ul) a{white-space:nowrap}.sm-dox{padding:0 10px;background-image:url('tab_b.png');line-height:36px}.sm-dox a span.sub-arrow{top:50%;margin-top:-2px;right:12px;width:0;height:0;border-width:4px;border-style:solid dashed dashed dashed;border-color:#283A5D transparent transparent transparent;background:transparent;-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted{padding:0 12px;background-image:url('tab_s.png');background-repeat:no-repeat;background-position:right;-moz-border-radius:0 !important;-webkit-border-radius:0;border-radius:0 !important}.sm-dox a:hover{background-image:url('tab_a.png');background-repeat:repeat-x;color:white;text-shadow:0px 1px 1px rgba(0, 0, 0, 1.0)}.sm-dox a:hover span.sub-arrow{border-color:white transparent transparent transparent}.sm-dox a.has-submenu{padding-right:24px}.sm-dox li{border-top:0}.sm-dox>li>ul:before,.sm-dox>li>ul:after{content:'';position:absolute;top:-18px;left:30px;width:0;height:0;overflow:hidden;border-width:9px;border-style:dashed dashed solid dashed;border-color:transparent transparent #bbb transparent}.sm-dox>li>ul:after{top:-16px;left:31px;border-width:8px;border-color:transparent transparent white transparent}.sm-dox ul{border:1px solid #bbb;padding:5px 0;background:white;-moz-border-radius:5px !important;-webkit-border-radius:5px;border-radius:5px !important;-moz-box-shadow:0 5px 9px rgba(0,0,0,0.2);-webkit-box-shadow:0 5px 9px rgba(0,0,0,0.2);box-shadow:0 5px 9px rgba(0,0,0,0.2)}.sm-dox ul a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-color:transparent transparent transparent #555555;border-style:dashed dashed dashed solid}.sm-dox ul a,.sm-dox ul a:hover,.sm-dox ul a:focus,.sm-dox ul a:active,.sm-dox ul a.highlighted{color:#555555;background-image:none;border:0 !important}.sm-dox ul a:hover{background-image:url('tab_a.png');background-repeat:repeat-x;color:white;text-shadow:0px 1px 1px rgba(0, 0, 0, 1.0)}.sm-dox ul a:hover span.sub-arrow{border-color:transparent transparent transparent white}.sm-dox span.scroll-up,.sm-dox span.scroll-down{position:absolute;display:none;visibility:hidden;overflow:hidden;background:white;height:36px}.sm-dox span.scroll-up:hover,.sm-dox span.scroll-down:hover{background:#eee}.sm-dox span.scroll-up:hover span.scroll-up-arrow,.sm-dox span.scroll-up:hover span.scroll-down-arrow{border-color:transparent transparent #d23600 transparent}.sm-dox span.scroll-down:hover span.scroll-down-arrow{border-color:#d23600 transparent transparent transparent}.sm-dox span.scroll-up-arrow,.sm-dox span.scroll-down-arrow{position:absolute;top:0;left:50%;margin-left:-6px;width:0;height:0;overflow:hidden;border-width:6px;border-style:dashed dashed solid dashed;border-color:transparent transparent #555555 transparent}.sm-dox span.scroll-down-arrow{top:8px;border-style:solid dashed dashed dashed;border-color:#555555 transparent transparent transparent}.sm-dox.sm-rtl a.has-submenu{padding-right:12px;padding-left:24px}.sm-dox.sm-rtl a span.sub-arrow{right:auto;left:12px}.sm-dox.sm-rtl.sm-vertical a.has-submenu{padding:10px 20px}.sm-dox.sm-rtl.sm-vertical a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-rtl>li>ul:before{left:auto;right:30px}.sm-dox.sm-rtl>li>ul:after{left:auto;right:31px}.sm-dox.sm-rtl ul a.has-submenu{padding:10px 20px !important}.sm-dox.sm-rtl ul a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-vertical{padding:10px 0;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.sm-dox.sm-vertical a{padding:10px 20px}.sm-dox.sm-vertical a:hover,.sm-dox.sm-vertical a:focus,.sm-dox.sm-vertical a:active,.sm-dox.sm-vertical a.highlighted{background:#fff}.sm-dox.sm-vertical a.disabled{background-image:url('tab_b.png')}.sm-dox.sm-vertical a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-style:dashed dashed dashed solid;border-color:transparent transparent transparent #555}.sm-dox.sm-vertical>li>ul:before,.sm-dox.sm-vertical>li>ul:after{display:none}.sm-dox.sm-vertical ul a{padding:10px 20px}.sm-dox.sm-vertical ul a:hover,.sm-dox.sm-vertical ul a:focus,.sm-dox.sm-vertical ul a:active,.sm-dox.sm-vertical ul a.highlighted{background:#eee}.sm-dox.sm-vertical ul a.disabled{background:white}} diff --git a/docs/web_8h_source.html b/docs/web_8h_source.html new file mode 100644 index 0000000..1accb4d --- /dev/null +++ b/docs/web_8h_source.html @@ -0,0 +1,123 @@ + + + + + + + +BOLT Dash (C++): Bolt_Dash/web.h Source File + + + + + + + + + + + + + + + + +
    +
    + + + + + + +
    +
    BOLT Dash (C++) +
    +
    +
    + + + + + + + + +
    +
    + +
    +
    +
    + +
    + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + +
    +
    web.h
    +
    +
    +
    1#ifndef WEB_H
    +
    2#define WEB_H
    +
    3
    +
    4#define RPM_TO_SPEED (19.0 / 45.0 * 27.63 * M_PI / 1056)
    +
    5
    +
    6namespace web {
    +
    7 void runApp();
    +
    8}
    +
    9
    +
    10#endif // !WEB)H
    +
    +
    + + + + diff --git a/doxy-config b/doxy-config new file mode 100644 index 0000000..727b049 --- /dev/null +++ b/doxy-config @@ -0,0 +1,2884 @@ +# Doxyfile 1.12.0 + +# This file describes the settings to be used by the documentation system +# Doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). +# +# Note: +# +# Use Doxygen to compare the used configuration file with the template +# configuration file: +# doxygen -x [configFile] +# Use Doxygen to compare the used configuration file with the template +# configuration file without replacing the environment variables or CMake type +# replacement variables: +# doxygen -x_noenv [configFile] + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "BOLT Dash (C++)" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# With the PROJECT_ICON tag one can specify an icon that is included in the tabs +# when the HTML document is shown. Doxygen will copy the logo to the output +# directory. + +PROJECT_ICON = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where Doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES then Doxygen will create up to 4096 +# sub-directories (in 2 levels) under the output directory of each output format +# and will distribute the generated files over these directories. Enabling this +# option can be useful when feeding Doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to +# control the number of sub-directories. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# Controls the number of sub-directories that will be created when +# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every +# level increment doubles the number of directories, resulting in 4096 +# directories at level 8 which is the default and also the maximum value. The +# sub-directories are organized in 2 levels, the first level always has a fixed +# number of 16 directories. +# Minimum value: 0, maximum value: 8, default value: 8. +# This tag requires that the tag CREATE_SUBDIRS is set to YES. + +CREATE_SUBDIRS_LEVEL = 8 + +# If the ALLOW_UNICODE_NAMES tag is set to YES, Doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by Doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian, +# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English +# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek, +# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with +# English messages), Korean, Korean-en (Korean with English messages), Latvian, +# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, +# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, +# Swedish, Turkish, Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, Doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, Doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, Doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, Doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which Doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where Doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, Doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the JAVADOC_BANNER tag is set to YES then Doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by Doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# By default Python docstrings are displayed as preformatted text and Doxygen's +# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the +# Doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as Doxygen documentation. +# The default value is: YES. + +PYTHON_DOCSTRING = YES + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then Doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:^^" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". Note that you cannot put \n's in the value part of an alias +# to insert newlines (in the resulting output). You can put ^^ in the value part +# of an alias to insert a newline as if a physical newline was in the original +# file. When you need a literal { or } or , in the value part of an alias you +# have to escape them by means of a backslash (\), this can lead to conflicts +# with the commands \{ and \} for these it is advised to use the version @{ and +# @} or use a double escape (\\{ and \\}) + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by Doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, +# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files). For instance to make Doxygen treat .inc files +# as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by Doxygen. When specifying no_extension you should add +# * to the FILE_PATTERNS. +# +# Note see also the list of default file extension mappings. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then Doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by Doxygen, so you can +# mix Doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 6. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 6 + +# The MARKDOWN_ID_STYLE tag can be used to specify the algorithm used to +# generate identifiers for the Markdown headings. Note: Every identifier is +# unique. +# Possible values are: DOXYGEN use a fixed 'autotoc_md' string followed by a +# sequence number starting at 0 and GITHUB use the lower case version of title +# with any whitespace replaced by '-' and punctuation characters removed. +# The default value is: DOXYGEN. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +MARKDOWN_ID_STYLE = DOXYGEN + +# When enabled Doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let Doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also makes the inheritance and +# collaboration diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software) sources only. Doxygen will parse +# them like normal C++ but will assume all classes use public instead of private +# inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# Doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then Doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, Doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# Doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run Doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +# The NUM_PROC_THREADS specifies the number of threads Doxygen is allowed to use +# during processing. When set to 0 Doxygen will based this on the number of +# cores available in the system. You can set it explicitly to a value larger +# than 0 to get more control over the balance between CPU load and processing +# speed. At this moment only the input processing can be done using multiple +# threads. Since this is still an experimental feature the default is set to 1, +# which effectively disables parallel processing. Please report any issues you +# encounter. Generating dot graphs in parallel is controlled by the +# DOT_NUM_THREADS setting. +# Minimum value: 0, maximum value: 32, default value: 1. + +NUM_PROC_THREADS = 1 + +# If the TIMESTAMP tag is set different from NO then each generated page will +# contain the date or date and time when the page was generated. Setting this to +# NO can help when comparing the output of multiple runs. +# Possible values are: YES, NO, DATETIME and DATE. +# The default value is: NO. + +TIMESTAMP = NO + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, Doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# will also hide undocumented C++ concepts if enabled. This option has no effect +# if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all friend +# declarations. If set to NO, these declarations will be included in the +# documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# With the correct setting of option CASE_SENSE_NAMES Doxygen will better be +# able to match the capabilities of the underlying filesystem. In case the +# filesystem is case sensitive (i.e. it supports files in the same directory +# whose names only differ in casing), the option must be set to YES to properly +# deal with such files in case they appear in the input. For filesystems that +# are not case sensitive the option should be set to NO to properly deal with +# output files written for symbols that only differ in casing, such as for two +# classes, one named CLASS and the other named Class, and to also support +# references to files without having to specify the exact matching casing. On +# Windows (including Cygwin) and macOS, users should typically set this option +# to NO, whereas on Linux or other Unix flavors it should typically be set to +# YES. +# Possible values are: SYSTEM, NO and YES. +# The default value is: SYSTEM. + +CASE_SENSE_NAMES = SYSTEM + +# If the HIDE_SCOPE_NAMES tag is set to NO then Doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then Doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class +# will show which file needs to be included to use the class. +# The default value is: YES. + +SHOW_HEADERFILE = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES then Doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then Doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then Doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then Doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then Doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and Doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING Doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# Doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by Doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by Doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents Doxygen's defaults, run Doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. See also section "Changing the +# layout of pages" for information. +# +# Note that if you run Doxygen from a directory containing a file called +# DoxygenLayout.xml, Doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +# The EXTERNAL_TOOL_PATH tag can be used to extend the search path (PATH +# environment variable) so that external tools such as latex and gs can be +# found. +# Note: Directories specified with EXTERNAL_TOOL_PATH are added in front of the +# path already specified by the PATH variable, and are added in the order +# specified. +# Note: This option is particularly useful for macOS version 14 (Sonoma) and +# higher, when running Doxygen from Doxywizard, because in this case any user- +# defined changes to the PATH are ignored. A typical example on macOS is to set +# EXTERNAL_TOOL_PATH = /Library/TeX/texbin /usr/local/bin +# together with the standard path, the full search path used by doxygen when +# launching external tools will then become +# PATH=/Library/TeX/texbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin + +EXTERNAL_TOOL_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by Doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by Doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then Doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, Doxygen will generate warnings for +# potential errors in the documentation, such as documenting some parameters in +# a documented function twice, or documenting parameters that don't exist or +# using markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# If WARN_IF_INCOMPLETE_DOC is set to YES, Doxygen will warn about incomplete +# function parameter documentation. If set to NO, Doxygen will accept that some +# parameters have no documentation without warning. +# The default value is: YES. + +WARN_IF_INCOMPLETE_DOC = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, Doxygen will only warn about wrong parameter +# documentation, but not about the absence of documentation. If EXTRACT_ALL is +# set to YES then this flag will automatically be disabled. See also +# WARN_IF_INCOMPLETE_DOC +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, Doxygen will warn about +# undocumented enumeration values. If set to NO, Doxygen will accept +# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: NO. + +WARN_IF_UNDOC_ENUM_VAL = NO + +# If the WARN_AS_ERROR tag is set to YES then Doxygen will immediately stop when +# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS +# then Doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the Doxygen process Doxygen will return with a non-zero status. +# If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS_PRINT then Doxygen behaves +# like FAIL_ON_WARNINGS but in case no WARN_LOGFILE is defined Doxygen will not +# write the warning messages in between other messages but write them at the end +# of a run, in case a WARN_LOGFILE is defined the warning messages will be +# besides being in the defined file also be shown at the end of a run, unless +# the WARN_LOGFILE is defined as - i.e. standard output (stdout) in that case +# the behavior will remain as with the setting FAIL_ON_WARNINGS. +# Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that Doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# See also: WARN_LINE_FORMAT +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# In the $text part of the WARN_FORMAT command it is possible that a reference +# to a more specific place is given. To make it easier to jump to this place +# (outside of Doxygen) the user can define a custom "cut" / "paste" string. +# Example: +# WARN_LINE_FORMAT = "'vi $file +$line'" +# See also: WARN_FORMAT +# The default value is: at line $line of file $file. + +WARN_LINE_FORMAT = "at line $line of file $file" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). In case the file specified cannot be opened for writing the +# warning and error messages are written to standard error. When as file - is +# specified the warning and error messages are written to standard output +# (stdout). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = Bolt_Dash/ + +# This tag can be used to specify the character encoding of the source files +# that Doxygen parses. Internally Doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: +# https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# See also: INPUT_FILE_ENCODING +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# This tag can be used to specify the character encoding of the source files +# that Doxygen parses The INPUT_FILE_ENCODING tag can be used to specify +# character encoding on a per file pattern basis. Doxygen will compare the file +# name with each pattern and apply the encoding instead of the default +# INPUT_ENCODING) if there is a match. The character encodings are a list of the +# form: pattern=encoding (like *.php=ISO-8859-1). +# See also: INPUT_ENCODING for further information on supported encodings. + +INPUT_FILE_ENCODING = + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by Doxygen. +# +# Note the list of default checked file patterns might differ from the list of +# default file extension mappings. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cxxm, +# *.cpp, *.cppm, *.ccm, *.c++, *.c++m, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, +# *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, *.h++, *.ixx, *.l, *.cs, *.d, +# *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to +# be provided as Doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cxxm \ + *.cpp \ + *.cppm \ + *.ccm \ + *.c++ \ + *.c++m \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.ixx \ + *.l \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.pyw \ + *.f90 \ + *.f95 \ + *.f03 \ + *.f08 \ + *.f18 \ + *.f \ + *.for \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf \ + *.ice + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which Doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# ANamespace::AClass, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that Doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that Doxygen will use the data processed and written to standard output +# for further processing, therefore nothing else, like debug statements or used +# commands (so in case of a Windows batch file always use @echo OFF), should be +# written to standard output. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by Doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by Doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the Doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +# The Fortran standard specifies that for fixed formatted Fortran code all +# characters from position 72 are to be considered as comment. A common +# extension is to allow longer lines before the automatic comment starts. The +# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can +# be processed before the automatic comment starts. +# Minimum value: 7, maximum value: 10000, default value: 72. + +FORTRAN_COMMENT_AFTER = 72 + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# multi-line macros, enums or list initialized variables directly into the +# documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct Doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of Doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by Doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then Doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes) +# that should be ignored while generating the index headers. The IGNORE_PREFIX +# tag works for classes, function and member names. The entity will be placed in +# the alphabetical list under the first letter of the entity name that remains +# after removing the prefix. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, Doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = docs + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank Doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that Doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that Doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of Doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank Doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that Doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank Doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that Doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by Doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). +# Note: Since the styling of scrollbars can currently not be overruled in +# Webkit/Chromium, the styling will be left out of the default doxygen.css if +# one or more extra stylesheets have been specified. So if scrollbar +# customization is desired it has to be added explicitly. For an example see the +# documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = doxygen-awesome-css/doxygen-awesome.css + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output +# should be rendered with a dark or light theme. +# Possible values are: LIGHT always generates light mode output, DARK always +# generates dark mode output, AUTO_LIGHT automatically sets the mode according +# to the user preference, uses light mode if no preference is set (the default), +# AUTO_DARK automatically sets the mode according to the user preference, uses +# dark mode if no preference is set and TOGGLE allows a user to switch between +# light and dark mode via a button. +# The default value is: AUTO_LIGHT. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE = LIGHT + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a color-wheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use gray-scales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via JavaScript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have JavaScript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# If the HTML_CODE_FOLDING tag is set to YES then classes and functions can be +# dynamically folded and expanded in the generated HTML source code. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_CODE_FOLDING = YES + +# If the HTML_COPY_CLIPBOARD tag is set to YES then Doxygen will show an icon in +# the top right corner of code and text fragments that allows the user to copy +# its content to the clipboard. Note this only works if supported by the browser +# and the web page is served via a secure context (see: +# https://www.w3.org/TR/secure-contexts/), i.e. using the https: or file: +# protocol. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COPY_CLIPBOARD = YES + +# Doxygen stores a couple of settings persistently in the browser (via e.g. +# cookies). By default these settings apply to all HTML pages generated by +# Doxygen across all projects. The HTML_PROJECT_COOKIE tag can be used to store +# the settings under a project specific key, such that the user preferences will +# be stored separately. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_PROJECT_COOKIE = + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: +# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To +# create a documentation set, Doxygen will generate a Makefile in the HTML +# output directory. Running make will produce the docset in that directory and +# running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag determines the URL of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDURL = + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then Doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# on Windows. In the beginning of 2021 Microsoft took the original page, with +# a.o. the download links, offline the HTML help workshop was already many years +# in maintenance mode). You can download the HTML help workshop from the web +# archives at Installation executable (see: +# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo +# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by Doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# Doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the main .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# The SITEMAP_URL tag is used to specify the full URL of the place where the +# generated documentation will be placed on the server by the user during the +# deployment of the documentation. The generated sitemap is called sitemap.xml +# and placed on the directory specified by HTML_OUTPUT. In case no SITEMAP_URL +# is specified no sitemap is generated. For information about the sitemap +# protocol see https://www.sitemaps.org +# This tag requires that the tag GENERATE_HTML is set to YES. + +SITEMAP_URL = + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location (absolute path +# including file name) of Qt's qhelpgenerator. If non-empty Doxygen will try to +# run qhelpgenerator on the generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine tune the look of the index (see "Fine-tuning the output"). As an +# example, the default style sheet generated by Doxygen has an example that +# shows how to put an image at the root of the tree instead of the PROJECT_NAME. +# Since the tree basically has the same information as the tab index, you could +# consider setting DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = YES + +# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the +# FULL_SIDEBAR option determines if the side bar is limited to only the treeview +# area (value NO) or if it should extend to the full height of the window (value +# YES). Setting this to YES gives a layout similar to +# https://docs.readthedocs.io with more room for contents, but less room for the +# project logo, title, and description. If either GENERATE_TREEVIEW or +# DISABLE_INDEX is set to NO, this option has no effect. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FULL_SIDEBAR = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# Doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# When the SHOW_ENUM_VALUES tag is set doxygen will show the specified +# enumeration values besides the enumeration mnemonics. +# The default value is: NO. + +SHOW_ENUM_VALUES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, Doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# If the OBFUSCATE_EMAILS tag is set to YES, Doxygen will obfuscate email +# addresses. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +OBFUSCATE_EMAILS = YES + +# If the HTML_FORMULA_FORMAT option is set to svg, Doxygen will use the pdf2svg +# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see +# https://inkscape.org) to generate formulas as SVG images instead of PNGs for +# the HTML output. These images will generally look nicer at scaled resolutions. +# Possible values are: png (the default) and svg (looks nicer but requires the +# pdf2svg or inkscape tool). +# The default value is: png. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FORMULA_FORMAT = png + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# Doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. + +FORMULA_MACROFILE = + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side JavaScript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# With MATHJAX_VERSION it is possible to specify the MathJax version to be used. +# Note that the different versions of MathJax have different requirements with +# regards to the different settings, so it is possible that also other MathJax +# settings have to be changed when switching between the different MathJax +# versions. +# Possible values are: MathJax_2 and MathJax_3. +# The default value is: MathJax_2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_VERSION = MathJax_2 + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. For more details about the output format see MathJax +# version 2 (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3 +# (see: +# http://docs.mathjax.org/en/latest/web/components/output.html). +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility. This is the name for Mathjax version 2, for MathJax version 3 +# this will be translated into chtml), NativeMML (i.e. MathML. Only supported +# for MathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This +# is the name for Mathjax version 3, for MathJax version 2 this will be +# translated into HTML-CSS) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. The default value is: +# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2 +# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3 +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# for MathJax version 2 (see +# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions): +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# For example for MathJax version 3 (see +# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): +# MATHJAX_EXTENSIONS = ams +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with JavaScript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled Doxygen will generate a search box for +# the HTML output. The underlying search engine uses JavaScript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the JavaScript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /