diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..18f134d --- /dev/null +++ b/.clang-format @@ -0,0 +1,141 @@ +--- +Language: Cpp +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: true +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: false +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortLambdasOnASingleLine: None +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: true + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 140 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 2 +ContinuationIndentWidth: 2 +Cpp11BracedListStyle: true +DeriveLineEnding: false +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: true +FixNamespaceComments: false +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + - Regex: '.*' + Priority: 1 + SortPriority: 0 +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseLabels: true +IndentGotoLabels: true +IndentPPDirectives: BeforeHash +IndentWidth: 2 +IndentWrappedFunctionNames: false +# Requires Clang >= 15, could also cause incorrect code formatting: +# InsertBraces: true +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: All +PackConstructorInitializers: NextLine +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +ReferenceAlignment: Pointer +ReflowComments: true +SeparateDefinitionBlocks: Always +SortIncludes: false +SortUsingDeclarations: true +SpaceAfterCStyleCast: true +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatementsExceptForEachMacros +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +SpaceAroundPointerQualifiers: Default +Standard: Latest +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseCRLF: false +UseTab: Never +... diff --git a/.clang-format-ignore b/.clang-format-ignore new file mode 100644 index 0000000..4fad63f --- /dev/null +++ b/.clang-format-ignore @@ -0,0 +1,13 @@ +sim/timers.h +sim/task.cpp +sim/task.h +sim/projdefs.h +sim/portmacro_cmsis.h +sim/FreeRTOS.h +sim/nrfx/** +sim/libraries/** +sim/host/** +gif-h/** +external/** +InfiniTime/** +lv_drivers/** diff --git a/littlefs-do-main.cpp b/littlefs-do-main.cpp index 0a5dfbd..883786d 100644 --- a/littlefs-do-main.cpp +++ b/littlefs-do-main.cpp @@ -77,26 +77,40 @@ Pinetime::Controllers::FS fs {spiNorFlash}; Pinetime::Controllers::Settings settingsController {fs}; const char* lfs_error_to_string(int err) { - if (err == LFS_ERR_OK) return "LFS_ERR_OK"; // No error - if (err == LFS_ERR_IO) return "LFS_ERR_IO"; // Error during device operation - if (err == LFS_ERR_CORRUPT) return "LFS_ERR_CORRUPT"; // Corrupted - if (err == LFS_ERR_NOENT) return "LFS_ERR_NOENT"; // No directory entry - if (err == LFS_ERR_EXIST) return "LFS_ERR_EXIST"; // Entry already exists - if (err == LFS_ERR_NOTDIR) return "LFS_ERR_NOTDIR"; // Entry is not a dir - if (err == LFS_ERR_ISDIR) return "LFS_ERR_ISDIR"; // Entry is a dir - if (err == LFS_ERR_NOTEMPTY) return "LFS_ERR_NOTEMPTY"; // Dir is not empty - if (err == LFS_ERR_BADF) return "LFS_ERR_BADF"; // Bad file number - if (err == LFS_ERR_FBIG) return "LFS_ERR_FBIG"; // File too large - if (err == LFS_ERR_INVAL) return "LFS_ERR_INVAL"; // Invalid parameter - if (err == LFS_ERR_NOSPC) return "LFS_ERR_NOSPC"; // No space left on device - if (err == LFS_ERR_NOMEM) return "LFS_ERR_NOMEM"; // No more memory available - if (err == LFS_ERR_NOATTR) return "LFS_ERR_NOATTR"; // No data/attr available - if (err == LFS_ERR_NAMETOOLONG) return "LFS_ERR_NAMETOOLONG"; // File name too long + if (err == LFS_ERR_OK) + return "LFS_ERR_OK"; // No error + if (err == LFS_ERR_IO) + return "LFS_ERR_IO"; // Error during device operation + if (err == LFS_ERR_CORRUPT) + return "LFS_ERR_CORRUPT"; // Corrupted + if (err == LFS_ERR_NOENT) + return "LFS_ERR_NOENT"; // No directory entry + if (err == LFS_ERR_EXIST) + return "LFS_ERR_EXIST"; // Entry already exists + if (err == LFS_ERR_NOTDIR) + return "LFS_ERR_NOTDIR"; // Entry is not a dir + if (err == LFS_ERR_ISDIR) + return "LFS_ERR_ISDIR"; // Entry is a dir + if (err == LFS_ERR_NOTEMPTY) + return "LFS_ERR_NOTEMPTY"; // Dir is not empty + if (err == LFS_ERR_BADF) + return "LFS_ERR_BADF"; // Bad file number + if (err == LFS_ERR_FBIG) + return "LFS_ERR_FBIG"; // File too large + if (err == LFS_ERR_INVAL) + return "LFS_ERR_INVAL"; // Invalid parameter + if (err == LFS_ERR_NOSPC) + return "LFS_ERR_NOSPC"; // No space left on device + if (err == LFS_ERR_NOMEM) + return "LFS_ERR_NOMEM"; // No more memory available + if (err == LFS_ERR_NOATTR) + return "LFS_ERR_NOATTR"; // No data/attr available + if (err == LFS_ERR_NAMETOOLONG) + return "LFS_ERR_NAMETOOLONG"; // File name too long return "unknown"; } -void print_help_generic(const std::string &program_name) -{ +void print_help_generic(const std::string& program_name) { std::cout << "Usage: " << program_name << " [options]" << std::endl; std::cout << "Commands:" << std::endl; std::cout << " -h, --help show this help message for the selected command and exit" << std::endl; @@ -110,43 +124,43 @@ void print_help_generic(const std::string &program_name) std::cout << " settings list settings from 'settings.h'" << std::endl; std::cout << " res resource.zip handling" << std::endl; } -void print_help_stat(const std::string &program_name) -{ + +void print_help_stat(const std::string& program_name) { std::cout << "Usage: " << program_name << " stat [options] [path]" << std::endl; std::cout << "Options:" << std::endl; std::cout << " -h, --help show this help message for the selected command and exit" << std::endl; std::cout << " path path to directory or file to work on, defaults to '/'" << std::endl; } -void print_help_ls(const std::string &program_name) -{ + +void print_help_ls(const std::string& program_name) { std::cout << "Usage: " << program_name << " ls [options] [path]" << std::endl; std::cout << "Options:" << std::endl; std::cout << " -h, --help show this help message for the selected command and exit" << std::endl; std::cout << " path path to directory or file to work on, defaults to '/'" << std::endl; } -void print_help_mkdir(const std::string &program_name) -{ + +void print_help_mkdir(const std::string& program_name) { std::cout << "Usage: " << program_name << " mkdir [options] path" << std::endl; std::cout << "Options:" << std::endl; std::cout << " -h, --help show this help message for the selected command and exit" << std::endl; std::cout << " path path to directory to create" << std::endl; } -void print_help_rmdir(const std::string &program_name) -{ + +void print_help_rmdir(const std::string& program_name) { std::cout << "Usage: " << program_name << " rmdir [options] path" << std::endl; std::cout << "Options:" << std::endl; std::cout << " -h, --help show this help message for the selected command and exit" << std::endl; std::cout << " path path to directory to remove" << std::endl; } -void print_help_rm(const std::string &program_name) -{ + +void print_help_rm(const std::string& program_name) { std::cout << "Usage: " << program_name << " rm [options] path" << std::endl; std::cout << "Options:" << std::endl; std::cout << " -h, --help show this help message for the selected command and exit" << std::endl; std::cout << " path path to file or directory directory to remove" << std::endl; } -void print_help_cp(const std::string &program_name) -{ + +void print_help_cp(const std::string& program_name) { std::cout << "Usage: " << program_name << " cp [options] source [source2 ...] destination" << std::endl; std::cout << "Options:" << std::endl; std::cout << " -h, --help show this help message for the selected command and exit" << std::endl; @@ -155,14 +169,14 @@ void print_help_cp(const std::string &program_name) std::cout << "the host system into the raw image, otherwise the files are copied" << std::endl; std::cout << "from the raw image to the host system provided directory." << std::endl; } -void print_help_settings(const std::string &program_name) -{ + +void print_help_settings(const std::string& program_name) { std::cout << "Usage: " << program_name << " settings [options]" << std::endl; std::cout << "Options:" << std::endl; std::cout << " -h, --help show this help message for the selected command and exit" << std::endl; } -void print_help_res(const std::string &program_name) -{ + +void print_help_res(const std::string& program_name) { std::cout << "Usage: " << program_name << " res [options]" << std::endl; std::cout << "actions:" << std::endl; std::cout << " load res.zip load zip file into SPI memory" << std::endl; @@ -170,17 +184,14 @@ void print_help_res(const std::string &program_name) std::cout << " -h, --help show this help message for the selected command and exit" << std::endl; } -int command_stat(const std::string &program_name, const std::vector &args, bool verbose) -{ +int command_stat(const std::string& program_name, const std::vector& args, bool verbose) { if (verbose) std::cout << "running command 'stat'" << std::endl; // argv: littlefs-do stat [args] std::string path = "/"; // check for help flag first - for (const std::string &arg : args) - { - if (arg == "-h" || arg == "--help") - { + for (const std::string& arg : args) { + if (arg == "-h" || arg == "--help") { print_help_stat(program_name); return 0; } @@ -189,14 +200,15 @@ int command_stat(const std::string &program_name, const std::vector if (verbose) { std::cout << "no path given, showing '/'" << std::endl; } - } if (args.size() == 1) { + } + if (args.size() == 1) { path = args.at(0); } lfs_info info; int ret = fs.Stat(path.c_str(), &info); if (ret) { - std::cout << "fs.Stat returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; + std::cout << "fs.Stat returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; return ret; } if (info.type == LFS_TYPE_REG) { @@ -206,25 +218,21 @@ int command_stat(const std::string &program_name, const std::vector } else if (info.type == LFS_TYPE_DIR) { std::cout << "type: DIR" << std::endl; std::cout << "name: " << std::string(info.name) << std::endl; - } - else { + } else { std::cout << "unknown type: " << info.type << std::endl; return 1; } return 0; } -int command_ls(const std::string &program_name, const std::vector &args, bool verbose) -{ +int command_ls(const std::string& program_name, const std::vector& args, bool verbose) { if (verbose) std::cout << "running command 'ls'" << std::endl; // argv: littlefs-do ls [args] std::string path = "/"; // check for help flag first - for (const std::string &arg : args) - { - if (arg == "-h" || arg == "--help") - { + for (const std::string& arg : args) { + if (arg == "-h" || arg == "--help") { print_help_ls(program_name); return 0; } @@ -233,14 +241,15 @@ int command_ls(const std::string &program_name, const std::vector & if (verbose) { std::cout << "no path given, showing '/'" << std::endl; } - } if (args.size() == 1) { + } + if (args.size() == 1) { path = args.at(0); } lfs_info info; int ret = fs.Stat(path.c_str(), &info); if (ret) { - std::cout << "fs.Stat returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; + std::cout << "fs.Stat returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; return ret; } if (info.type == LFS_TYPE_REG) { @@ -253,13 +262,13 @@ int command_ls(const std::string &program_name, const std::vector & lfs_dir_t lfs_dir; ret = fs.DirOpen(path.c_str(), &lfs_dir); if (ret) { - std::cout << "fs.DirOpen returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; + std::cout << "fs.DirOpen returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; return ret; } ret = fs.DirRead(&lfs_dir, &info); while (ret > 0) { if (ret < 0) { - std::cout << "fs.DirRead returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; + std::cout << "fs.DirRead returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; return ret; } if (info.type == LFS_TYPE_REG) { @@ -277,7 +286,7 @@ int command_ls(const std::string &program_name, const std::vector & ret = fs.DirRead(&lfs_dir, &info); } // end of while loop if (ret < 0) { - std::cout << "fs.DirRead returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; + std::cout << "fs.DirRead returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; return ret; } } else { // endif provided path @@ -286,17 +295,15 @@ int command_ls(const std::string &program_name, const std::vector & } return 0; } -int command_mkdir(const std::string &program_name, const std::vector &args, bool verbose) -{ + +int command_mkdir(const std::string& program_name, const std::vector& args, bool verbose) { if (verbose) { std::cout << "running command 'mkdir'" << std::endl; } // argv: littlefs-do mkdir path // check for help flag first - for (const std::string &arg : args) - { - if (arg == "-h" || arg == "--help") - { + for (const std::string& arg : args) { + if (arg == "-h" || arg == "--help") { print_help_mkdir(program_name); return 0; } @@ -306,31 +313,27 @@ int command_mkdir(const std::string &program_name, const std::vector &args, bool verbose) -{ +int command_rmdir(const std::string& program_name, const std::vector& args, bool verbose) { if (verbose) { std::cout << "running command 'rmdir'" << std::endl; } // argv: littlefs-do rmdir path // check for help flag first - for (const std::string &arg : args) - { - if (arg == "-h" || arg == "--help") - { + for (const std::string& arg : args) { + if (arg == "-h" || arg == "--help") { print_help_rmdir(program_name); return 0; } @@ -340,15 +343,14 @@ int command_rmdir(const std::string &program_name, const std::vector &args, bool verbose) -{ +int command_rm(const std::string& program_name, const std::vector& args, bool verbose) { if (verbose) { std::cout << "running command 'rm'" << std::endl; } // argv: littlefs-do rm path // check for help flag first - for (const std::string &arg : args) - { - if (arg == "-h" || arg == "--help") - { + for (const std::string& arg : args) { + if (arg == "-h" || arg == "--help") { print_help_rm(program_name); return 0; } @@ -385,30 +384,26 @@ int command_rm(const std::string &program_name, const std::vector & print_help_rm(program_name); return 1; } - for (const std::string &path : args) - { + for (const std::string& path : args) { if (verbose) { std::cout << "rm: " << path << std::endl; } // assume non-files are directories int ret = fs.FileDelete(path.c_str()); if (ret < 0) { - std::cout << "fs.FileDelete returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; + std::cout << "fs.FileDelete returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; return ret; } } return 0; } -int command_cp(const std::string &program_name, const std::vector &args, bool verbose) -{ +int command_cp(const std::string& program_name, const std::vector& args, bool verbose) { if (verbose) { std::cout << "running 'cp'" << std::endl; } - for (const std::string &arg : args) - { - if (arg == "-h" || arg == "--help") - { + for (const std::string& arg : args) { + if (arg == "-h" || arg == "--help") { print_help_cp(program_name); return 0; } @@ -418,7 +413,7 @@ int command_cp(const std::string &program_name, const std::vector & print_help_cp(program_name); return 1; } - const std::string &destination = args.back(); + const std::string& destination = args.back(); static constexpr size_t memorySize {0x400000}; std::array buffer; if (destination[0] == '/') { @@ -429,7 +424,7 @@ int command_cp(const std::string &program_name, const std::vector & lfs_info info; int ret = fs.Stat(destination.c_str(), &info); if (ret) { - std::cout << "fs.Stat for destination path returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; + std::cout << "fs.Stat for destination path returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; return ret; } if (info.type == LFS_TYPE_REG) { @@ -437,57 +432,52 @@ int command_cp(const std::string &program_name, const std::vector & return 1; } } - for (size_t i=0; i & lfs_file_t file_p; ret = fs.FileOpen(&file_p, source.c_str(), LFS_O_RDONLY); if (ret) { - std::cout << "fs.FileOpen returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; + std::cout << "fs.FileOpen returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; return ret; } ret = fs.FileRead(&file_p, buffer.data(), info.size); if (ret < 0) { - std::cout << "fs.FileRead returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; + std::cout << "fs.FileRead returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; fs.FileClose(&file_p); return ret; } fs.FileClose(&file_p); std::ofstream ofs(dest_path, std::ios::binary); - ofs.write((char*)(buffer.data()), info.size); + ofs.write((char*) (buffer.data()), info.size); } } // end cp from raw image to host - + return 0; } -int command_settings(const std::string &program_name, const std::vector &args, bool verbose) -{ +int command_settings(const std::string& program_name, const std::vector& args, bool verbose) { if (verbose) { std::cout << "running 'settings'" << std::endl; } - for (const std::string &arg : args) - { - if (arg == "-h" || arg == "--help") - { + for (const std::string& arg : args) { + if (arg == "-h" || arg == "--help") { print_help_settings(program_name); return 0; } @@ -537,10 +524,14 @@ int command_settings(const std::string &program_name, const std::vector(clockface) << " " << clockface_str << std::endl; @@ -548,30 +539,49 @@ int command_settings(const std::string &program_name, const std::vector(chimes) << " " << chimes_str << std::endl; } auto color_str = [](auto c) { - if (c == Settings::Colors::White) return "White"; - if (c == Settings::Colors::Silver) return "Silver"; - if (c == Settings::Colors::Gray) return "Gray"; - if (c == Settings::Colors::Black) return "Black"; - if (c == Settings::Colors::Red) return "Red"; - if (c == Settings::Colors::Maroon) return "Maroon"; - if (c == Settings::Colors::Yellow) return "Yellow"; - if (c == Settings::Colors::Olive) return "Olive"; - if (c == Settings::Colors::Lime) return "Lime"; - if (c == Settings::Colors::Green) return "Cyan"; - if (c == Settings::Colors::Teal) return "Teal"; - if (c == Settings::Colors::Blue) return "Blue"; - if (c == Settings::Colors::Navy) return "Navy"; - if (c == Settings::Colors::Magenta) return "Magenta"; - if (c == Settings::Colors::Purple) return "Purple"; - if (c == Settings::Colors::Orange) return "Orange"; + if (c == Settings::Colors::White) + return "White"; + if (c == Settings::Colors::Silver) + return "Silver"; + if (c == Settings::Colors::Gray) + return "Gray"; + if (c == Settings::Colors::Black) + return "Black"; + if (c == Settings::Colors::Red) + return "Red"; + if (c == Settings::Colors::Maroon) + return "Maroon"; + if (c == Settings::Colors::Yellow) + return "Yellow"; + if (c == Settings::Colors::Olive) + return "Olive"; + if (c == Settings::Colors::Lime) + return "Lime"; + if (c == Settings::Colors::Green) + return "Cyan"; + if (c == Settings::Colors::Teal) + return "Teal"; + if (c == Settings::Colors::Blue) + return "Blue"; + if (c == Settings::Colors::Navy) + return "Navy"; + if (c == Settings::Colors::Magenta) + return "Magenta"; + if (c == Settings::Colors::Purple) + return "Purple"; + if (c == Settings::Colors::Orange) + return "Orange"; return "unknown"; }; std::cout << "PTSColorTime: " << color_str(settingsController.GetPTSColorTime()) << std::endl; @@ -583,9 +593,12 @@ int command_settings(const std::string &program_name, const std::vector(notif) << " " << notif_str << std::endl; @@ -602,10 +615,14 @@ int command_settings(const std::string &program_name, const std::vector(brightness) << " " << brightness_str << std::endl; @@ -615,10 +632,10 @@ int command_settings(const std::string &program_name, const std::vector &args, bool verbose) -{ + +int command_res(const std::string& program_name, const std::vector& args, bool verbose) { if (verbose) { std::cout << "running 'res'" << std::endl; } - for (const std::string &arg : args) - { - if (arg == "-h" || arg == "--help") - { + for (const std::string& arg : args) { + if (arg == "-h" || arg == "--help") { print_help_res(program_name); return 0; } @@ -668,17 +683,17 @@ int command_res(const std::string &program_name, const std::vector print_help_res(program_name); return 1; } - for (size_t i=1; i buffer_compressed(f_size); std::ifstream ifs(path, std::ios::binary); - ifs.read((char*)(buffer_compressed.data()), f_size); + ifs.read((char*) (buffer_compressed.data()), f_size); mz_zip_archive zip_archive {}; int mz_status = mz_zip_reader_init_file(&zip_archive, zip_filename.c_str(), 0); @@ -693,16 +708,15 @@ int command_res(const std::string &program_name, const std::vector } size_t uncomp_size = 0; - void *p = nullptr; + void* p = nullptr; // extract resources.json file to heap, create a string and parse it p = mz_zip_reader_extract_file_to_heap(&zip_archive, "resources.json", &uncomp_size, 0); - if (!p) - { + if (!p) { std::cout << "mz_zip_reader_extract_file_to_heap() failed to extract resources.json file" << std::endl; mz_zip_reader_end(&zip_archive); return 1; } - std::string_view json_data(static_cast(p), uncomp_size); + std::string_view json_data(static_cast(p), uncomp_size); nlohmann::json doc = nlohmann::json::parse(json_data); mz_free(p); // free json data, already converted into json document if (!doc.contains("resources")) { @@ -711,18 +725,18 @@ int command_res(const std::string &program_name, const std::vector return 1; } // copy all listed resources to SPI raw file - for (const auto &res : doc["resources"]) { + for (const auto& res : doc["resources"]) { const auto filename = res["filename"].get(); const auto dest_path = res["path"].get(); if (verbose) { - std::cout << "copy file " << std::left << std::setw(25) << filename - << " from zip to SPI path '" << dest_path << "'" << std::endl; + std::cout << "copy file " << std::left << std::setw(25) << filename << " from zip to SPI path '" << dest_path << "'" + << std::endl; } // make sure destination directory exists before copy - const std::filesystem::path dest_dir = std::filesystem::path{dest_path}.parent_path(); + const std::filesystem::path dest_dir = std::filesystem::path {dest_path}.parent_path(); mkdir_path(dest_dir); // extract from zip to heap to then copy to SPI raw file - void *p = mz_zip_reader_extract_file_to_heap(&zip_archive, filename.c_str(), &uncomp_size, 0); + void* p = mz_zip_reader_extract_file_to_heap(&zip_archive, filename.c_str(), &uncomp_size, 0); if (!p) { std::cout << "mz_zip_reader_extract_file_to_heap() failed to extract file: " << filename << std::endl; mz_zip_reader_end(&zip_archive); @@ -731,12 +745,12 @@ int command_res(const std::string &program_name, const std::vector lfs_file_t file_p; int ret = fs.FileOpen(&file_p, dest_path.c_str(), LFS_O_WRONLY | LFS_O_CREAT); if (ret) { - std::cout << "fs.FileOpen returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; + std::cout << "fs.FileOpen returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; return ret; } - ret = fs.FileWrite(&file_p, static_cast(p), uncomp_size); + ret = fs.FileWrite(&file_p, static_cast(p), uncomp_size); if (ret < 0) { - std::cout << "fs.FileWrite returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; + std::cout << "fs.FileWrite returned error code: " << ret << " " << lfs_error_to_string(ret) << std::endl; fs.FileClose(&file_p); return ret; } @@ -764,9 +778,7 @@ int command_res(const std::string &program_name, const std::vector return 0; } - -int main(int argc, char **argv) -{ +int main(int argc, char** argv) { // parse arguments if (argc <= 1) { print_help_generic(argv[0]); @@ -774,8 +786,7 @@ int main(int argc, char **argv) } bool verbose = false; std::vector args; - for (int i=1; i /*Dummy include by default*/ -#define LV_DRV_DELAY_US(us) /*delay_us(us)*/ /*Delay the given number of microseconds*/ -#define LV_DRV_DELAY_MS(ms) /*delay_ms(ms)*/ /*Delay the given number of milliseconds*/ - -/********************* - * DISPLAY INTERFACE - *********************/ - -/*------------ - * Common - *------------*/ -#define LV_DRV_DISP_INCLUDE /*Dummy include by default*/ -#define LV_DRV_DISP_CMD_DATA(val) /*pin_x_set(val)*/ /*Set the command/data pin to 'val'*/ -#define LV_DRV_DISP_RST(val) /*pin_x_set(val)*/ /*Set the reset pin to 'val'*/ - -/*--------- - * SPI - *---------*/ -#define LV_DRV_DISP_SPI_CS(val) /*spi_cs_set(val)*/ /*Set the SPI's Chip select to 'val'*/ -#define LV_DRV_DISP_SPI_WR_BYTE(data) /*spi_wr(data)*/ /*Write a byte the SPI bus*/ -#define LV_DRV_DISP_SPI_WR_ARRAY(adr, n) /*spi_wr_mem(adr, n)*/ /*Write 'n' bytes to SPI bus from 'adr'*/ - -/*------------------ - * Parallel port - *-----------------*/ -#define LV_DRV_DISP_PAR_CS(val) /*par_cs_set(val)*/ /*Set the Parallel port's Chip select to 'val'*/ -#define LV_DRV_DISP_PAR_SLOW /*par_slow()*/ /*Set low speed on the parallel port*/ -#define LV_DRV_DISP_PAR_FAST /*par_fast()*/ /*Set high speed on the parallel port*/ -#define LV_DRV_DISP_PAR_WR_WORD(data) /*par_wr(data)*/ /*Write a word to the parallel port*/ -#define LV_DRV_DISP_PAR_WR_ARRAY(adr, n) /*par_wr_mem(adr,n)*/ /*Write 'n' bytes to Parallel ports from 'adr'*/ - -/*************************** - * INPUT DEVICE INTERFACE - ***************************/ - -/*---------- - * Common - *----------*/ -#define LV_DRV_INDEV_INCLUDE /*Dummy include by default*/ -#define LV_DRV_INDEV_RST(val) /*pin_x_set(val)*/ /*Set the reset pin to 'val'*/ -#define LV_DRV_INDEV_IRQ_READ 0 /*pn_x_read()*/ /*Read the IRQ pin*/ - -/*--------- - * SPI - *---------*/ -#define LV_DRV_INDEV_SPI_CS(val) /*spi_cs_set(val)*/ /*Set the SPI's Chip select to 'val'*/ -#define LV_DRV_INDEV_SPI_XCHG_BYTE(data) 0 /*spi_xchg(val)*/ /*Write 'val' to SPI and give the read value*/ - -/*--------- - * I2C - *---------*/ -#define LV_DRV_INDEV_I2C_START /*i2c_start()*/ /*Make an I2C start*/ -#define LV_DRV_INDEV_I2C_STOP /*i2c_stop()*/ /*Make an I2C stop*/ -#define LV_DRV_INDEV_I2C_RESTART /*i2c_restart()*/ /*Make an I2C restart*/ -#define LV_DRV_INDEV_I2C_WR(data) /*i2c_wr(data)*/ /*Write a byte to the I1C bus*/ -#define LV_DRV_INDEV_I2C_READ(last_read) 0 /*i2c_rd()*/ /*Read a byte from the I2C bud*/ - - -/********************* - * DISPLAY DRIVERS - *********************/ -#ifndef USE_WAYLAND -# define USE_WAYLAND 0 -#endif - -#if USE_WAYLAND -# define WAYLAND_HOR_RES 480 -# define WAYLAND_VER_RES 320 -# define WAYLAND_SURF_TITLE "LVGL" -#endif -/*------------------- - * Monitor of PC - *-------------------*/ -#ifndef USE_MONITOR -# define USE_MONITOR 1 -#endif - -#if USE_MONITOR -# define MONITOR_HOR_RES 240 -# define MONITOR_VER_RES 240 - -/* Scale window by this factor (useful when simulating small screens) */ -#ifndef MONITOR_ZOOM -# define MONITOR_ZOOM 1 -#endif - -/* Used to test true double buffering with only address changing. - * Set LV_draw_buf_SIZE = (LV_HOR_RES * LV_VER_RES) and LV_draw_buf_DOUBLE = 1 and LV_COLOR_DEPTH = 32" */ -# define MONITOR_DOUBLE_BUFFERED 0 - -/*Eclipse: Visual Studio: */ -# define MONITOR_SDL_INCLUDE_PATH - -/*Different rendering might be used if running in a Virtual machine*/ -# define MONITOR_VIRTUAL_MACHINE 0 - -/*Open two windows to test multi display support*/ -# define MONITOR_DUAL 0 -#endif - -/*----------------------------------- - * Native Windows (including mouse) - *----------------------------------*/ -#ifndef USE_WINDOWS -# define USE_WINDOWS 0 -#endif - -#define USE_WINDOWS 0 -#if USE_WINDOWS -# define WINDOW_HOR_RES 480 -# define WINDOW_VER_RES 320 -#endif - -/*---------------------------------------- - * GTK drivers (monitor, mouse, keyboard - *---------------------------------------*/ -#ifndef USE_GTK -# define USE_GTK 0 -#endif - -/*---------------- - * SSD1963 - *--------------*/ -#ifndef USE_SSD1963 -# define USE_SSD1963 0 -#endif - -#if USE_SSD1963 -# define SSD1963_HOR_RES LV_HOR_RES -# define SSD1963_VER_RES LV_VER_RES -# define SSD1963_HT 531 -# define SSD1963_HPS 43 -# define SSD1963_LPS 8 -# define SSD1963_HPW 10 -# define SSD1963_VT 288 -# define SSD1963_VPS 12 -# define SSD1963_FPS 4 -# define SSD1963_VPW 10 -# define SSD1963_HS_NEG 0 /*Negative hsync*/ -# define SSD1963_VS_NEG 0 /*Negative vsync*/ -# define SSD1963_ORI 0 /*0, 90, 180, 270*/ -# define SSD1963_COLOR_DEPTH 16 -#endif - -/*---------------- - * R61581 - *--------------*/ -#ifndef USE_R61581 -# define USE_R61581 0 -#endif - -#if USE_R61581 -# define R61581_HOR_RES LV_HOR_RES -# define R61581_VER_RES LV_VER_RES -# define R61581_HSPL 0 /*HSYNC signal polarity*/ -# define R61581_HSL 10 /*HSYNC length (Not Implemented)*/ -# define R61581_HFP 10 /*Horitontal Front poarch (Not Implemented)*/ -# define R61581_HBP 10 /*Horitontal Back poarch (Not Implemented */ -# define R61581_VSPL 0 /*VSYNC signal polarity*/ -# define R61581_VSL 10 /*VSYNC length (Not Implemented)*/ -# define R61581_VFP 8 /*Vertical Front poarch*/ -# define R61581_VBP 8 /*Vertical Back poarch */ -# define R61581_DPL 0 /*DCLK signal polarity*/ -# define R61581_EPL 1 /*ENABLE signal polarity*/ -# define R61581_ORI 0 /*0, 180*/ -# define R61581_LV_COLOR_DEPTH 16 /*Fix 16 bit*/ -#endif - -/*------------------------------ - * ST7565 (Monochrome, low res.) - *-----------------------------*/ -#ifndef USE_ST7565 -# define USE_ST7565 0 -#endif - -#if USE_ST7565 -/*No settings*/ -#endif /*USE_ST7565*/ - -/*------------------------------ - * GC9A01 (color, low res.) - *-----------------------------*/ -#ifndef USE_GC9A01 -# define USE_GC9A01 0 -#endif - -#if USE_GC9A01 -/*No settings*/ -#endif /*USE_GC9A01*/ - -/*------------------------------------------ - * UC1610 (4 gray 160*[104|128]) - * (EA DOGXL160 160x104 tested) - *-----------------------------------------*/ -#ifndef USE_UC1610 -# define USE_UC1610 0 -#endif - -#if USE_UC1610 -# define UC1610_HOR_RES LV_HOR_RES -# define UC1610_VER_RES LV_VER_RES -# define UC1610_INIT_CONTRAST 33 /* init contrast, values in [%] */ -# define UC1610_INIT_HARD_RST 0 /* 1 : hardware reset at init, 0 : software reset */ -# define UC1610_TOP_VIEW 0 /* 0 : Bottom View, 1 : Top View */ -#endif /*USE_UC1610*/ - -/*------------------------------------------------- - * SHARP memory in pixel monochrome display series - * LS012B7DD01 (184x38 pixels.) - * LS013B7DH03 (128x128 pixels.) - * LS013B7DH05 (144x168 pixels.) - * LS027B7DH01 (400x240 pixels.) (tested) - * LS032B7DD02 (336x536 pixels.) - * LS044Q7DH01 (320x240 pixels.) - *------------------------------------------------*/ -#ifndef USE_SHARP_MIP -# define USE_SHARP_MIP 0 -#endif - -#if USE_SHARP_MIP -# define SHARP_MIP_HOR_RES LV_HOR_RES -# define SHARP_MIP_VER_RES LV_VER_RES -# define SHARP_MIP_SOFT_COM_INVERSION 0 -# define SHARP_MIP_REV_BYTE(b) /*((uint8_t) __REV(__RBIT(b)))*/ /*Architecture / compiler dependent byte bits order reverse*/ -#endif /*USE_SHARP_MIP*/ - -/*------------------------------------------------- - * ILI9341 240X320 TFT LCD - *------------------------------------------------*/ -#ifndef USE_ILI9341 -# define USE_ILI9341 0 -#endif - -#if USE_ILI9341 -# define ILI9341_HOR_RES LV_HOR_RES -# define ILI9341_VER_RES LV_VER_RES -# define ILI9341_GAMMA 1 -# define ILI9341_TEARING 0 -#endif /*USE_ILI9341*/ - -/*----------------------------------------- - * Linux frame buffer device (/dev/fbx) - *-----------------------------------------*/ -#define USE_FBDEV 0 -#ifndef USE_FBDEV -# define USE_FBDEV 1 -#endif - -#if USE_FBDEV -# define FBDEV_PATH "/dev/fb0" -#endif - -/*----------------------------------------- - * FreeBSD frame buffer device (/dev/fbx) - *.........................................*/ -#ifndef USE_BSD_FBDEV -# define USE_BSD_FBDEV 0 -#endif - -#if USE_BSD_FBDEV -# define FBDEV_PATH "/dev/fb0" -#endif - -/*----------------------------------------- - * DRM/KMS device (/dev/dri/cardX) - *-----------------------------------------*/ -#ifndef USE_DRM -# define USE_DRM 0 -#endif - -#if USE_DRM -# define DRM_CARD "/dev/dri/card0" -# define DRM_CONNECTOR_ID -1 /* -1 for the first connected one */ -#endif - -/********************* - * INPUT DEVICES - *********************/ - -/*-------------- - * XPT2046 - *--------------*/ -#ifndef USE_XPT2046 -# define USE_XPT2046 0 -#endif - -#if USE_XPT2046 -# define XPT2046_HOR_RES 480 -# define XPT2046_VER_RES 320 -# define XPT2046_X_MIN 200 -# define XPT2046_Y_MIN 200 -# define XPT2046_X_MAX 3800 -# define XPT2046_Y_MAX 3800 -# define XPT2046_AVG 4 -# define XPT2046_X_INV 0 -# define XPT2046_Y_INV 0 -# define XPT2046_XY_SWAP 0 -#endif - -/*----------------- - * FT5406EE8 - *-----------------*/ -#ifndef USE_FT5406EE8 -# define USE_FT5406EE8 0 -#endif - -#if USE_FT5406EE8 -# define FT5406EE8_I2C_ADR 0x38 /*7 bit address*/ -#endif - -/*--------------- - * AD TOUCH - *--------------*/ -#ifndef USE_AD_TOUCH -# define USE_AD_TOUCH 0 -#endif - -#if USE_AD_TOUCH -/*No settings*/ -#endif - - -/*--------------------------------------- - * Mouse or touchpad on PC (using SDL) - *-------------------------------------*/ -#ifndef USE_MOUSE -# define USE_MOUSE 1 -#endif - -#if USE_MOUSE -/*No settings*/ -#endif - -/*------------------------------------------- - * Mousewheel as encoder on PC (using SDL) - *------------------------------------------*/ -#ifndef USE_MOUSEWHEEL -# define USE_MOUSEWHEEL 1 -#endif - -#if USE_MOUSEWHEEL -/*No settings*/ -#endif - -/*------------------------------------------------- - * Touchscreen as libinput interface (for Linux based systems) - *------------------------------------------------*/ -#ifndef USE_LIBINPUT -# define USE_LIBINPUT 0 -#endif - -#if USE_LIBINPUT -# define LIBINPUT_NAME "/dev/input/event0" /*You can use the "evtest" Linux tool to get the list of devices and test them*/ -#endif /*USE_LIBINPUT*/ - -/*------------------------------------------------- - * Mouse or touchpad as evdev interface (for Linux based systems) - *------------------------------------------------*/ -#ifndef USE_EVDEV -# define USE_EVDEV 0 -#endif - -#ifndef USE_BSD_EVDEV -# define USE_BSD_EVDEV 0 -#endif - -#if USE_EVDEV || USE_BSD_EVDEV -# define EVDEV_NAME "/dev/input/event0" /*You can use the "evtest" Linux tool to get the list of devices and test them*/ -# define EVDEV_SWAP_AXES 0 /*Swap the x and y axes of the touchscreen*/ - -# define EVDEV_CALIBRATE 0 /*Scale and offset the touchscreen coordinates by using maximum and minimum values for each axis*/ - -# if EVDEV_CALIBRATE -# define EVDEV_HOR_MIN 0 /*to invert axis swap EVDEV_XXX_MIN by EVDEV_XXX_MAX*/ -# define EVDEV_HOR_MAX 4096 /*"evtest" Linux tool can help to get the correct calibraion values>*/ -# define EVDEV_VER_MIN 0 -# define EVDEV_VER_MAX 4096 -# endif /*EVDEV_CALIBRATE*/ -#endif /*USE_EVDEV*/ - -/*------------------------------- - * Keyboard of a PC (using SDL) - *------------------------------*/ -#ifndef USE_KEYBOARD -# define USE_KEYBOARD 1 -#endif - -#if USE_KEYBOARD -/*No settings*/ -#endif - -#endif /*LV_DRV_CONF_H*/ + #ifndef LV_DRV_CONF_H + #define LV_DRV_CONF_H + + #include "lv_conf.h" + + /********************* + * DELAY INTERFACE + *********************/ + #define LV_DRV_DELAY_INCLUDE /*Dummy include by default*/ + #define LV_DRV_DELAY_US(us) /*delay_us(us)*/ /*Delay the given number of microseconds*/ + #define LV_DRV_DELAY_MS(ms) /*delay_ms(ms)*/ /*Delay the given number of milliseconds*/ + + /********************* + * DISPLAY INTERFACE + *********************/ + + /*------------ + * Common + *------------*/ + #define LV_DRV_DISP_INCLUDE /*Dummy include by default*/ + #define LV_DRV_DISP_CMD_DATA(val) /*pin_x_set(val)*/ /*Set the command/data pin to 'val'*/ + #define LV_DRV_DISP_RST(val) /*pin_x_set(val)*/ /*Set the reset pin to 'val'*/ + + /*--------- + * SPI + *---------*/ + #define LV_DRV_DISP_SPI_CS(val) /*spi_cs_set(val)*/ /*Set the SPI's Chip select to 'val'*/ + #define LV_DRV_DISP_SPI_WR_BYTE(data) /*spi_wr(data)*/ /*Write a byte the SPI bus*/ + #define LV_DRV_DISP_SPI_WR_ARRAY(adr, n) /*spi_wr_mem(adr, n)*/ /*Write 'n' bytes to SPI bus from 'adr'*/ + + /*------------------ + * Parallel port + *-----------------*/ + #define LV_DRV_DISP_PAR_CS(val) /*par_cs_set(val)*/ /*Set the Parallel port's Chip select to 'val'*/ + #define LV_DRV_DISP_PAR_SLOW /*par_slow()*/ /*Set low speed on the parallel port*/ + #define LV_DRV_DISP_PAR_FAST /*par_fast()*/ /*Set high speed on the parallel port*/ + #define LV_DRV_DISP_PAR_WR_WORD(data) /*par_wr(data)*/ /*Write a word to the parallel port*/ + #define LV_DRV_DISP_PAR_WR_ARRAY(adr, n) /*par_wr_mem(adr,n)*/ /*Write 'n' bytes to Parallel ports from 'adr'*/ + + /*************************** + * INPUT DEVICE INTERFACE + ***************************/ + + /*---------- + * Common + *----------*/ + #define LV_DRV_INDEV_INCLUDE /*Dummy include by default*/ + #define LV_DRV_INDEV_RST(val) /*pin_x_set(val)*/ /*Set the reset pin to 'val'*/ + #define LV_DRV_INDEV_IRQ_READ 0 /*pn_x_read()*/ /*Read the IRQ pin*/ + + /*--------- + * SPI + *---------*/ + #define LV_DRV_INDEV_SPI_CS(val) /*spi_cs_set(val)*/ /*Set the SPI's Chip select to 'val'*/ + #define LV_DRV_INDEV_SPI_XCHG_BYTE(data) 0 /*spi_xchg(val)*/ /*Write 'val' to SPI and give the read value*/ + + /*--------- + * I2C + *---------*/ + #define LV_DRV_INDEV_I2C_START /*i2c_start()*/ /*Make an I2C start*/ + #define LV_DRV_INDEV_I2C_STOP /*i2c_stop()*/ /*Make an I2C stop*/ + #define LV_DRV_INDEV_I2C_RESTART /*i2c_restart()*/ /*Make an I2C restart*/ + #define LV_DRV_INDEV_I2C_WR(data) /*i2c_wr(data)*/ /*Write a byte to the I1C bus*/ + #define LV_DRV_INDEV_I2C_READ(last_read) 0 /*i2c_rd()*/ /*Read a byte from the I2C bud*/ + + /********************* + * DISPLAY DRIVERS + *********************/ + #ifndef USE_WAYLAND + #define USE_WAYLAND 0 + #endif + + #if USE_WAYLAND + #define WAYLAND_HOR_RES 480 + #define WAYLAND_VER_RES 320 + #define WAYLAND_SURF_TITLE "LVGL" + #endif + /*------------------- + * Monitor of PC + *-------------------*/ + #ifndef USE_MONITOR + #define USE_MONITOR 1 + #endif + + #if USE_MONITOR + #define MONITOR_HOR_RES 240 + #define MONITOR_VER_RES 240 + + /* Scale window by this factor (useful when simulating small screens) */ + #ifndef MONITOR_ZOOM + #define MONITOR_ZOOM 1 + #endif + + /* Used to test true double buffering with only address changing. + * Set LV_draw_buf_SIZE = (LV_HOR_RES * LV_VER_RES) and LV_draw_buf_DOUBLE = 1 and LV_COLOR_DEPTH = 32" */ + #define MONITOR_DOUBLE_BUFFERED 0 + + /*Eclipse: Visual Studio: */ + #define MONITOR_SDL_INCLUDE_PATH + + /*Different rendering might be used if running in a Virtual machine*/ + #define MONITOR_VIRTUAL_MACHINE 0 + + /*Open two windows to test multi display support*/ + #define MONITOR_DUAL 0 + #endif + + /*----------------------------------- + * Native Windows (including mouse) + *----------------------------------*/ + #ifndef USE_WINDOWS + #define USE_WINDOWS 0 + #endif + + #define USE_WINDOWS 0 + #if USE_WINDOWS + #define WINDOW_HOR_RES 480 + #define WINDOW_VER_RES 320 + #endif + + /*---------------------------------------- + * GTK drivers (monitor, mouse, keyboard + *---------------------------------------*/ + #ifndef USE_GTK + #define USE_GTK 0 + #endif + + /*---------------- + * SSD1963 + *--------------*/ + #ifndef USE_SSD1963 + #define USE_SSD1963 0 + #endif + + #if USE_SSD1963 + #define SSD1963_HOR_RES LV_HOR_RES + #define SSD1963_VER_RES LV_VER_RES + #define SSD1963_HT 531 + #define SSD1963_HPS 43 + #define SSD1963_LPS 8 + #define SSD1963_HPW 10 + #define SSD1963_VT 288 + #define SSD1963_VPS 12 + #define SSD1963_FPS 4 + #define SSD1963_VPW 10 + #define SSD1963_HS_NEG 0 /*Negative hsync*/ + #define SSD1963_VS_NEG 0 /*Negative vsync*/ + #define SSD1963_ORI 0 /*0, 90, 180, 270*/ + #define SSD1963_COLOR_DEPTH 16 + #endif + + /*---------------- + * R61581 + *--------------*/ + #ifndef USE_R61581 + #define USE_R61581 0 + #endif + + #if USE_R61581 + #define R61581_HOR_RES LV_HOR_RES + #define R61581_VER_RES LV_VER_RES + #define R61581_HSPL 0 /*HSYNC signal polarity*/ + #define R61581_HSL 10 /*HSYNC length (Not Implemented)*/ + #define R61581_HFP 10 /*Horitontal Front poarch (Not Implemented)*/ + #define R61581_HBP 10 /*Horitontal Back poarch (Not Implemented */ + #define R61581_VSPL 0 /*VSYNC signal polarity*/ + #define R61581_VSL 10 /*VSYNC length (Not Implemented)*/ + #define R61581_VFP 8 /*Vertical Front poarch*/ + #define R61581_VBP 8 /*Vertical Back poarch */ + #define R61581_DPL 0 /*DCLK signal polarity*/ + #define R61581_EPL 1 /*ENABLE signal polarity*/ + #define R61581_ORI 0 /*0, 180*/ + #define R61581_LV_COLOR_DEPTH 16 /*Fix 16 bit*/ + #endif + + /*------------------------------ + * ST7565 (Monochrome, low res.) + *-----------------------------*/ + #ifndef USE_ST7565 + #define USE_ST7565 0 + #endif + + #if USE_ST7565 + /*No settings*/ + #endif /*USE_ST7565*/ + + /*------------------------------ + * GC9A01 (color, low res.) + *-----------------------------*/ + #ifndef USE_GC9A01 + #define USE_GC9A01 0 + #endif + + #if USE_GC9A01 + /*No settings*/ + #endif /*USE_GC9A01*/ + + /*------------------------------------------ + * UC1610 (4 gray 160*[104|128]) + * (EA DOGXL160 160x104 tested) + *-----------------------------------------*/ + #ifndef USE_UC1610 + #define USE_UC1610 0 + #endif + + #if USE_UC1610 + #define UC1610_HOR_RES LV_HOR_RES + #define UC1610_VER_RES LV_VER_RES + #define UC1610_INIT_CONTRAST 33 /* init contrast, values in [%] */ + #define UC1610_INIT_HARD_RST 0 /* 1 : hardware reset at init, 0 : software reset */ + #define UC1610_TOP_VIEW 0 /* 0 : Bottom View, 1 : Top View */ + #endif /*USE_UC1610*/ + + /*------------------------------------------------- + * SHARP memory in pixel monochrome display series + * LS012B7DD01 (184x38 pixels.) + * LS013B7DH03 (128x128 pixels.) + * LS013B7DH05 (144x168 pixels.) + * LS027B7DH01 (400x240 pixels.) (tested) + * LS032B7DD02 (336x536 pixels.) + * LS044Q7DH01 (320x240 pixels.) + *------------------------------------------------*/ + #ifndef USE_SHARP_MIP + #define USE_SHARP_MIP 0 + #endif + + #if USE_SHARP_MIP + #define SHARP_MIP_HOR_RES LV_HOR_RES + #define SHARP_MIP_VER_RES LV_VER_RES + #define SHARP_MIP_SOFT_COM_INVERSION 0 + #define SHARP_MIP_REV_BYTE(b) /*((uint8_t) __REV(__RBIT(b)))*/ /*Architecture / compiler dependent byte bits order reverse*/ + #endif /*USE_SHARP_MIP*/ + + /*------------------------------------------------- + * ILI9341 240X320 TFT LCD + *------------------------------------------------*/ + #ifndef USE_ILI9341 + #define USE_ILI9341 0 + #endif + + #if USE_ILI9341 + #define ILI9341_HOR_RES LV_HOR_RES + #define ILI9341_VER_RES LV_VER_RES + #define ILI9341_GAMMA 1 + #define ILI9341_TEARING 0 + #endif /*USE_ILI9341*/ + + /*----------------------------------------- + * Linux frame buffer device (/dev/fbx) + *-----------------------------------------*/ + #define USE_FBDEV 0 + #ifndef USE_FBDEV + #define USE_FBDEV 1 + #endif + + #if USE_FBDEV + #define FBDEV_PATH "/dev/fb0" + #endif + + /*----------------------------------------- + * FreeBSD frame buffer device (/dev/fbx) + *.........................................*/ + #ifndef USE_BSD_FBDEV + #define USE_BSD_FBDEV 0 + #endif + + #if USE_BSD_FBDEV + #define FBDEV_PATH "/dev/fb0" + #endif + + /*----------------------------------------- + * DRM/KMS device (/dev/dri/cardX) + *-----------------------------------------*/ + #ifndef USE_DRM + #define USE_DRM 0 + #endif + + #if USE_DRM + #define DRM_CARD "/dev/dri/card0" + #define DRM_CONNECTOR_ID -1 /* -1 for the first connected one */ + #endif + + /********************* + * INPUT DEVICES + *********************/ + + /*-------------- + * XPT2046 + *--------------*/ + #ifndef USE_XPT2046 + #define USE_XPT2046 0 + #endif + + #if USE_XPT2046 + #define XPT2046_HOR_RES 480 + #define XPT2046_VER_RES 320 + #define XPT2046_X_MIN 200 + #define XPT2046_Y_MIN 200 + #define XPT2046_X_MAX 3800 + #define XPT2046_Y_MAX 3800 + #define XPT2046_AVG 4 + #define XPT2046_X_INV 0 + #define XPT2046_Y_INV 0 + #define XPT2046_XY_SWAP 0 + #endif + + /*----------------- + * FT5406EE8 + *-----------------*/ + #ifndef USE_FT5406EE8 + #define USE_FT5406EE8 0 + #endif + + #if USE_FT5406EE8 + #define FT5406EE8_I2C_ADR 0x38 /*7 bit address*/ + #endif + + /*--------------- + * AD TOUCH + *--------------*/ + #ifndef USE_AD_TOUCH + #define USE_AD_TOUCH 0 + #endif + + #if USE_AD_TOUCH + /*No settings*/ + #endif + + /*--------------------------------------- + * Mouse or touchpad on PC (using SDL) + *-------------------------------------*/ + #ifndef USE_MOUSE + #define USE_MOUSE 1 + #endif + + #if USE_MOUSE + /*No settings*/ + #endif + + /*------------------------------------------- + * Mousewheel as encoder on PC (using SDL) + *------------------------------------------*/ + #ifndef USE_MOUSEWHEEL + #define USE_MOUSEWHEEL 1 + #endif + + #if USE_MOUSEWHEEL + /*No settings*/ + #endif + + /*------------------------------------------------- + * Touchscreen as libinput interface (for Linux based systems) + *------------------------------------------------*/ + #ifndef USE_LIBINPUT + #define USE_LIBINPUT 0 + #endif + + #if USE_LIBINPUT + #define LIBINPUT_NAME "/dev/input/event0" /*You can use the "evtest" Linux tool to get the list of devices and test them*/ + #endif /*USE_LIBINPUT*/ + + /*------------------------------------------------- + * Mouse or touchpad as evdev interface (for Linux based systems) + *------------------------------------------------*/ + #ifndef USE_EVDEV + #define USE_EVDEV 0 + #endif + + #ifndef USE_BSD_EVDEV + #define USE_BSD_EVDEV 0 + #endif + + #if USE_EVDEV || USE_BSD_EVDEV + #define EVDEV_NAME "/dev/input/event0" /*You can use the "evtest" Linux tool to get the list of devices and test them*/ + #define EVDEV_SWAP_AXES 0 /*Swap the x and y axes of the touchscreen*/ + + #define EVDEV_CALIBRATE 0 /*Scale and offset the touchscreen coordinates by using maximum and minimum values for each axis*/ + + #if EVDEV_CALIBRATE + #define EVDEV_HOR_MIN 0 /*to invert axis swap EVDEV_XXX_MIN by EVDEV_XXX_MAX*/ + #define EVDEV_HOR_MAX 4096 /*"evtest" Linux tool can help to get the correct calibraion values>*/ + #define EVDEV_VER_MIN 0 + #define EVDEV_VER_MAX 4096 + #endif /*EVDEV_CALIBRATE*/ + #endif /*USE_EVDEV*/ + + /*------------------------------- + * Keyboard of a PC (using SDL) + *------------------------------*/ + #ifndef USE_KEYBOARD + #define USE_KEYBOARD 1 + #endif + + #if USE_KEYBOARD + /*No settings*/ + #endif + + #endif /*LV_DRV_CONF_H*/ #endif /*End of "Content enable"*/ diff --git a/main.cpp b/main.cpp index cfd3d2f..67a05ec 100644 --- a/main.cpp +++ b/main.cpp @@ -13,15 +13,14 @@ #define SDL_MAIN_HANDLED /*To fix SDL's "undefined reference to WinMain" issue*/ #include #include "lvgl/lvgl.h" -//#include "lvgl/examples/lv_examples.h" -//#include "lv_demos/lv_demo.h" +// #include "lvgl/examples/lv_examples.h" +// #include "lv_demos/lv_demo.h" #include "lv_drivers/display/monitor.h" #include "lv_drivers/indev/mouse.h" #include "lv_drivers/indev/keyboard.h" #include "lv_drivers/indev/mousewheel.h" - -# // be sure to get the sim headers for SimpleWeatherService.h +#// be sure to get the sim headers for SimpleWeatherService.h #include "host/ble_gatt.h" #include "host/ble_uuid.h" @@ -71,9 +70,9 @@ #include // put_time #include #include -#include // localtime +#include // localtime #if defined(WITH_PNG) -#include + #include #endif #include @@ -87,24 +86,23 @@ * TYPEDEFS **********************/ // copied from lv_drivers/display/monitor.c to get the SDL_Window for the InfiniTime screen -extern "C" -{ +extern "C" { typedef struct { - SDL_Window * window; - SDL_Renderer * renderer; - SDL_Texture * texture; + SDL_Window* window; + SDL_Renderer* renderer; + SDL_Texture* texture; volatile bool sdl_refr_qry; #if MONITOR_DOUBLE_BUFFERED - uint32_t * tft_fb_act; + uint32_t* tft_fb_act; #else uint32_t tft_fb[LV_HOR_RES_MAX * LV_VER_RES_MAX]; #endif -}monitor_t; +} monitor_t; + extern monitor_t monitor; } -void saveScreenshot() -{ +void saveScreenshot() { auto now = std::chrono::system_clock::now(); auto in_time_t = std::chrono::system_clock::to_time_t(now); // timestamped png filename @@ -112,57 +110,62 @@ void saveScreenshot() ss << "InfiniSim_" << std::put_time(std::localtime(&in_time_t), "%F_%H%M%S"); std::string screenshot_filename_base = ss.str(); // TODO: use std::format once we have C++20 and new enough GCC 13 - //std::string screenshot_filename_base = std::format("InfiniSim_%F_%H%M%S", std::chrono::floor(now)); - //std::string screenshot_filename_base = "InfiniSim"; + // std::string screenshot_filename_base = std::format("InfiniSim_%F_%H%M%S", std::chrono::floor(now)); + // std::string screenshot_filename_base = "InfiniSim"; const int width = 240; const int height = 240; auto renderer = monitor.renderer; - #if defined(WITH_PNG) std::string screenshot_filename = screenshot_filename_base + ".png"; - FILE * fp2 = fopen(screenshot_filename.c_str(), "wb"); + FILE* fp2 = fopen(screenshot_filename.c_str(), "wb"); if (!fp2) { // dealing with error return; } // 1. Create png struct pointer png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr){ - // dealing with error + if (!png_ptr) { + // dealing with error } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { - png_destroy_write_struct(&png_ptr, (png_infopp)NULL); - // dealing with error + png_destroy_write_struct(&png_ptr, (png_infopp) NULL); + // dealing with error } int bit_depth = 8; png_init_io(png_ptr, fp2); - png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, \ - PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, \ - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + png_set_IHDR(png_ptr, + info_ptr, + width, + height, + bit_depth, + PNG_COLOR_TYPE_RGBA, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); // 3. Convert 1d array to 2d array to be suitable for png struct // I assumed the original array is 1d std::array row_pointers; - //png_bytepp row_pointers = (png_bytepp)png_malloc(png_ptr, sizeof(png_bytep) * height); + // png_bytepp row_pointers = (png_bytepp)png_malloc(png_ptr, sizeof(png_bytep) * height); for (int i = 0; i < height; i++) { - row_pointers[i] = (png_bytep)png_malloc(png_ptr, width*4); + row_pointers[i] = (png_bytep) png_malloc(png_ptr, width * 4); } constexpr size_t zoom = MONITOR_ZOOM; const Uint32 format = SDL_PIXELFORMAT_RGBA8888; - SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, width*zoom, height*zoom, 32, format); + SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormat(0, width * zoom, height * zoom, 32, format); SDL_RenderReadPixels(renderer, NULL, format, surface->pixels, surface->pitch); - png_bytep pixels = (png_bytep)surface->pixels; + png_bytep pixels = (png_bytep) surface->pixels; for (int hi = 0; hi < height; hi++) { for (int wi = 0; wi < width; wi++) { int c = wi * 4; - row_pointers.at(hi)[wi*4+0] = pixels[hi*surface->pitch*zoom + wi*4*zoom + 3]; // red - row_pointers.at(hi)[wi*4+1] = pixels[hi*surface->pitch*zoom + wi*4*zoom + 2]; // greeen - row_pointers.at(hi)[wi*4+2] = pixels[hi*surface->pitch*zoom + wi*4*zoom + 1]; // blue - row_pointers.at(hi)[wi*4+3] = 255; // alpha + row_pointers.at(hi)[wi * 4 + 0] = pixels[hi * surface->pitch * zoom + wi * 4 * zoom + 3]; // red + row_pointers.at(hi)[wi * 4 + 1] = pixels[hi * surface->pitch * zoom + wi * 4 * zoom + 2]; // greeen + row_pointers.at(hi)[wi * 4 + 2] = pixels[hi * surface->pitch * zoom + wi * 4 * zoom + 1]; // blue + row_pointers.at(hi)[wi * 4 + 3] = 255; // alpha } } @@ -177,7 +180,7 @@ void saveScreenshot() #else std::string screenshot_filename = screenshot_filename_base + ".bmp"; const Uint32 format = SDL_PIXELFORMAT_RGB888; - SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 24, format); + SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 24, format); SDL_RenderReadPixels(renderer, NULL, format, surface->pixels, surface->pitch); SDL_SaveBMP(surface, screenshot_filename.c_str()); SDL_FreeSurface(surface); @@ -185,32 +188,30 @@ void saveScreenshot() std::cout << "InfiniSim: Screenshot created: " << screenshot_filename << std::endl; } -class GifManager -{ +class GifManager { private: GifWriter writer = {}; std::chrono::system_clock::time_point last_frame; bool in_progress = false; - static constexpr uint32_t delay_ds = 100/20; // in 1/100 s, so 1 ds = 10 ms + static constexpr uint32_t delay_ds = 100 / 20; // in 1/100 s, so 1 ds = 10 ms static constexpr int sdl_width = 240; static constexpr int sdl_height = 240; public: - GifManager() - {} - ~GifManager() - { + GifManager() { + } + + ~GifManager() { if (in_progress) { close(); } } - bool is_in_progress() const - { + bool is_in_progress() const { return in_progress; } - void create_new() - { + + void create_new() { assert(!in_progress); auto now = std::chrono::system_clock::now(); auto in_time_t = std::chrono::system_clock::to_time_t(now); @@ -219,44 +220,43 @@ class GifManager ss << "InfiniSim_" << std::put_time(std::localtime(&in_time_t), "%F_%H%M%S"); std::string screenshot_filename_base = ss.str(); // TODO: use std::format once we have C++20 and new enough GCC 13 - //std::string screenshot_filename_base = std::format("InfiniSim_%F_%H%M%S", std::chrono::floor(now)); + // std::string screenshot_filename_base = std::format("InfiniSim_%F_%H%M%S", std::chrono::floor(now)); std::string screenshot_filename = screenshot_filename_base + ".gif"; std::cout << "InfiniSim: Screen-capture started: " << screenshot_filename << std::endl; - GifBegin( &writer, screenshot_filename.c_str(), sdl_width, sdl_height, delay_ds, 8, true ); + GifBegin(&writer, screenshot_filename.c_str(), sdl_width, sdl_height, delay_ds, 8, true); in_progress = true; write_frame(true); } - void write_frame(bool force = false) - { + + void write_frame(bool force = false) { assert(in_progress); auto now = std::chrono::system_clock::now(); - if (force || ((now - last_frame) > std::chrono::milliseconds(delay_ds*10)) ) - { + if (force || ((now - last_frame) > std::chrono::milliseconds(delay_ds * 10))) { last_frame = std::chrono::system_clock::now(); auto renderer = monitor.renderer; constexpr size_t zoom = MONITOR_ZOOM; const Uint32 format = SDL_PIXELFORMAT_RGBA8888; - SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, sdl_width*zoom, sdl_height*zoom, 32, format); + SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormat(0, sdl_width * zoom, sdl_height * zoom, 32, format); SDL_RenderReadPixels(renderer, NULL, format, surface->pixels, surface->pitch); - uint8_t *pixels = (uint8_t*) surface->pixels; + uint8_t* pixels = (uint8_t*) surface->pixels; - std::array image; + std::array image; for (int hi = 0; hi < sdl_height; hi++) { for (int wi = 0; wi < sdl_width; wi++) { - auto red = pixels[hi*surface->pitch*zoom + wi*4*zoom + 3]; // red - auto green = pixels[hi*surface->pitch*zoom + wi*4*zoom + 2]; // green - auto blue = pixels[hi*surface->pitch*zoom + wi*4*zoom + 1]; // blue - image[(hi * sdl_width + wi)*4 + 0] = red; - image[(hi * sdl_width + wi)*4 + 1] = green; - image[(hi * sdl_width + wi)*4 + 2] = blue; - image[(hi * sdl_width + wi)*4 + 3] = 255; // no alpha + auto red = pixels[hi * surface->pitch * zoom + wi * 4 * zoom + 3]; // red + auto green = pixels[hi * surface->pitch * zoom + wi * 4 * zoom + 2]; // green + auto blue = pixels[hi * surface->pitch * zoom + wi * 4 * zoom + 1]; // blue + image[(hi * sdl_width + wi) * 4 + 0] = red; + image[(hi * sdl_width + wi) * 4 + 1] = green; + image[(hi * sdl_width + wi) * 4 + 2] = blue; + image[(hi * sdl_width + wi) * 4 + 3] = 255; // no alpha } } GifWriteFrame(&writer, image.data(), sdl_width, sdl_height, delay_ds, 8, false); } } - void close() - { + + void close() { assert(in_progress); in_progress = false; GifEnd(&writer); @@ -268,13 +268,13 @@ class GifManager * STATIC PROTOTYPES **********************/ static void hal_init(void); -static int tick_thread(void *data); +static int tick_thread(void* data); /********************** * STATIC VARIABLES **********************/ -lv_indev_t *kb_indev; -lv_indev_t *mouse_indev = nullptr; +lv_indev_t* kb_indev; +lv_indev_t* mouse_indev = nullptr; /********************** * MACROS @@ -284,7 +284,8 @@ lv_indev_t *mouse_indev = nullptr; * GLOBAL FUNCTIONS **********************/ -void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {} +void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { +} /********************* * DEFINES @@ -305,8 +306,7 @@ void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action /********************** * GLOBAL FUNCTIONS **********************/ -constexpr NRF_TWIM_Type *NRF_TWIM1 = nullptr; - +constexpr NRF_TWIM_Type* NRF_TWIM1 = nullptr; static constexpr uint8_t touchPanelTwiAddress = 0x15; static constexpr uint8_t motionSensorTwiAddress = 0x18; @@ -332,13 +332,13 @@ Pinetime::Drivers::SpiNorFlash spiNorFlash {"spiNorFlash.raw"}; static constexpr uint32_t MaxTwiFrequencyWithoutHardwareBug {0x06200000}; Pinetime::Drivers::TwiMaster twiMaster {NRF_TWIM1, MaxTwiFrequencyWithoutHardwareBug, Pinetime::PinMap::TwiSda, Pinetime::PinMap::TwiScl}; Pinetime::Drivers::Cst816S touchPanel; // {twiMaster, touchPanelTwiAddress}; -//#ifdef PINETIME_IS_RECOVERY -// #include "displayapp/DummyLittleVgl.h" -// #include "displayapp/DisplayAppRecovery.h" -//#else -// #include "displayapp/LittleVgl.h" -// #include "displayapp/DisplayApp.h" -//#endif +// #ifdef PINETIME_IS_RECOVERY +// #include "displayapp/DummyLittleVgl.h" +// #include "displayapp/DisplayAppRecovery.h" +// #else +// #include "displayapp/LittleVgl.h" +// #include "displayapp/DisplayApp.h" +// #endif Pinetime::Drivers::Bma421 motionSensor {twiMaster, motionSensorTwiAddress}; Pinetime::Drivers::Hrs3300 heartRateSensor {twiMaster, heartRateSensorTwiAddress}; @@ -383,9 +383,9 @@ Pinetime::Applications::DisplayApp displayApp(lcd, settingsController, motorController, motionController, - #if defined(INFINITIME_TIMERCONTROLLER) +#if defined(INFINITIME_TIMERCONTROLLER) timerController, - #endif +#endif stopWatchController, alarmController, brightnessController, @@ -400,9 +400,9 @@ Pinetime::System::SystemTask systemTask(spi, batteryController, bleController, dateTimeController, - #if defined(INFINITIME_TIMERCONTROLLER) +#if defined(INFINITIME_TIMERCONTROLLER) timerController, - #endif +#endif stopWatchController, alarmController, watchdog, @@ -423,707 +423,682 @@ std::chrono::time_point NoI class Framework { public: - // Contructor which initialize the parameters. - Framework(bool visible_, int height_, int width_) : - visible(visible_), height(height_), width(width_) - { - if (visible) { - //SDL_Init(SDL_INIT_VIDEO); // Initializing SDL as Video - SDL_CreateWindowAndRenderer(width, height, 0, &window, &renderer); - SDL_SetWindowTitle(window, "LV Simulator Status"); - { // move window a bit to the right, to not be over the PineTime Screen - int x,y; - SDL_GetWindowPosition(window, &x, &y); - SDL_SetWindowPosition(window, x+LV_HOR_RES_MAX, y); - } - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); // setting draw color - SDL_RenderClear(renderer); // Clear the newly created window - SDL_RenderPresent(renderer); // Reflects the changes done in the - // window. - } - init_NRF_WDT(); - init_NRF_POWER(); - - // Attempt to load background BMP from memory for the status display window - const size_t SIM_BACKGROUND_size = sizeof(SIM_BACKGROUND); - SDL_RWops *rw = SDL_RWFromMem((void*)SIM_BACKGROUND, SIM_BACKGROUND_size); - SDL_Surface* simDisplayBgRaw = SDL_LoadBMP_RW(rw, 1); - if (simDisplayBgRaw == NULL) { - printf("Failed to load sim background image: %s\n", SDL_GetError()); - } else { - // convert the loaded image into a texture - simDisplayTexture = SDL_CreateTextureFromSurface(renderer, simDisplayBgRaw); - SDL_FreeSurface(simDisplayBgRaw); - simDisplayBgRaw = NULL; - } - motorController.Init(); - settingsController.Init(); + // Contructor which initialize the parameters. + Framework(bool visible_, int height_, int width_) : visible(visible_), height(height_), width(width_) { + if (visible) { + // SDL_Init(SDL_INIT_VIDEO); // Initializing SDL as Video + SDL_CreateWindowAndRenderer(width, height, 0, &window, &renderer); + SDL_SetWindowTitle(window, "LV Simulator Status"); + { // move window a bit to the right, to not be over the PineTime Screen + int x, y; + SDL_GetWindowPosition(window, &x, &y); + SDL_SetWindowPosition(window, x + LV_HOR_RES_MAX, y); + } + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); // setting draw color + SDL_RenderClear(renderer); // Clear the newly created window + SDL_RenderPresent(renderer); // Reflects the changes done in the + // window. + } + init_NRF_WDT(); + init_NRF_POWER(); + + // Attempt to load background BMP from memory for the status display window + const size_t SIM_BACKGROUND_size = sizeof(SIM_BACKGROUND); + SDL_RWops* rw = SDL_RWFromMem((void*) SIM_BACKGROUND, SIM_BACKGROUND_size); + SDL_Surface* simDisplayBgRaw = SDL_LoadBMP_RW(rw, 1); + if (simDisplayBgRaw == NULL) { + printf("Failed to load sim background image: %s\n", SDL_GetError()); + } else { + // convert the loaded image into a texture + simDisplayTexture = SDL_CreateTextureFromSurface(renderer, simDisplayBgRaw); + SDL_FreeSurface(simDisplayBgRaw); + simDisplayBgRaw = NULL; + } + motorController.Init(); + settingsController.Init(); - printf("initial free_size = %u\n", xPortGetFreeHeapSize()); + printf("initial free_size = %u\n", xPortGetFreeHeapSize()); - // update time to current system time once on startup - dateTimeController.SetCurrentTime(std::chrono::system_clock::now()); + // update time to current system time once on startup + dateTimeController.SetCurrentTime(std::chrono::system_clock::now()); - systemTask.Start(); + systemTask.Start(); - // initialize the first LVGL screen - //const auto clockface = settingsController.GetClockFace(); - //switch_to_screen(1+clockface); - } + // initialize the first LVGL screen + // const auto clockface = settingsController.GetClockFace(); + // switch_to_screen(1+clockface); + } - // Destructor - ~Framework(){ - if (simDisplayTexture != NULL) { - SDL_DestroyTexture(simDisplayTexture); - } - SDL_DestroyRenderer(renderer); - SDL_DestroyWindow(window); - SDL_Quit(); + // Destructor + ~Framework() { + if (simDisplayTexture != NULL) { + SDL_DestroyTexture(simDisplayTexture); } + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); + } - void draw_circle_red(int center_x, int center_y, int radius_){ - SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); - draw_circle_(center_x, center_y, radius_); - } - void draw_circle_green(int center_x, int center_y, int radius_){ - SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); - draw_circle_(center_x, center_y, radius_); - } - void draw_circle_blue(int center_x, int center_y, int radius_){ - SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); - draw_circle_(center_x, center_y, radius_); - } - void draw_circle_yellow(int center_x, int center_y, int radius_){ - SDL_SetRenderDrawColor(renderer, 255, 255, 0, 255); - draw_circle_(center_x, center_y, radius_); - } - void draw_circle_grey(int center_x, int center_y, int radius_){ - SDL_SetRenderDrawColor(renderer, 128, 128, 128, 255); - draw_circle_(center_x, center_y, radius_); - } - void draw_circle_white(int center_x, int center_y, int radius_){ - SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); - draw_circle_(center_x, center_y, radius_); - } - void draw_circle_(int center_x, int center_y, int radius_){ - // Drawing circle - for(int x=center_x-radius_; x<=center_x+radius_; x++){ - for(int y=center_y-radius_; y<=center_y+radius_; y++){ - if((std::pow(center_y-y,2)+std::pow(center_x-x,2)) <= - std::pow(radius_,2)){ - SDL_RenderDrawPoint(renderer, x, y); - } - } - } - } + void draw_circle_red(int center_x, int center_y, int radius_) { + SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); + draw_circle_(center_x, center_y, radius_); + } - void refresh() { - // left edge for all "bubbles" (circles) - constexpr const int bubbleLeftEdge = 65; - // always refresh the LVGL screen - this->refresh_screen(); + void draw_circle_green(int center_x, int center_y, int radius_) { + SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); + draw_circle_(center_x, center_y, radius_); + } - if (!visible) { - return; - } - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); - SDL_RenderClear(renderer); - // Render the background if it was able to be loaded - if (simDisplayTexture != NULL) { - SDL_RenderCopy(renderer, simDisplayTexture, NULL, NULL); - } - { // motorController.motor_is_running - constexpr const int center_x = bubbleLeftEdge; - constexpr const int center_y = 216; - bool motor_is_running = nrf_gpio_pin_read(Pinetime::PinMap::Motor); - if (motor_is_running) { - draw_circle_red(center_x, center_y, 15); - } else { - draw_circle_grey(center_x, center_y, 15); - } - } - { // ble.motor_is_running - constexpr const int center_x = bubbleLeftEdge; - constexpr const int center_y = 24; - if (bleController.IsConnected()) { - draw_circle_blue(center_x, center_y, 15); - } else { - draw_circle_grey(center_x, center_y, 15); - } - } - // batteryController.percentRemaining - { - const int center_x = bubbleLeftEdge; - const int center_y = 164; - const int max_bar_length = 150; - const int filled_bar_length = max_bar_length * (batteryController.percentRemaining/100.0); - const int rect_height = 14; - SDL_Rect rect { - .x = center_x - rect_height/2, - .y = center_y, - .w = max_bar_length, - .h = rect_height - }; - SDL_SetRenderDrawColor(renderer, 128, 128, 128, 255); - SDL_RenderDrawRect(renderer, &rect); - - rect.w = filled_bar_length; - rect.h++; - rect.h-=2; - SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); - SDL_RenderFillRect(renderer, &rect); - //set color and new x pos, draw again - } - { // batteryController.isCharging - constexpr const int center_x = bubbleLeftEdge; - constexpr const int center_y = 120; - if (batteryController.isCharging) { - draw_circle_yellow(center_x, center_y, 15); - } else - { - draw_circle_grey(center_x, center_y, 15); - } - } - { // brightnessController.Level - constexpr const int center_y = 72; - const Pinetime::Controllers::BrightnessController::Levels level = brightnessController.Level(); - uint8_t level_idx = 0; - if (level == Pinetime::Controllers::BrightnessController::Levels::Low) - { - level_idx = 1; - } else if (level == Pinetime::Controllers::BrightnessController::Levels::Medium) - { - level_idx = 2; - } else if (level == Pinetime::Controllers::BrightnessController::Levels::High) - { - level_idx = 3; - } - for (uint8_t i=0; i<4; i++) { - const int bubble_size = (i*2) + 5; - const int center_x = bubbleLeftEdge + ((bubble_size+10) * i) - 5; - if (i <= level_idx) { - draw_circle_white(center_x, center_y, bubble_size); - } else { - draw_circle_grey(center_x, center_y, bubble_size); - } - } - } - // Show the change on the screen - SDL_RenderPresent(renderer); - } + void draw_circle_blue(int center_x, int center_y, int radius_) { + SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); + draw_circle_(center_x, center_y, radius_); + } - // prepared notficitions, one per message category - const std::vector notification_messages { - "0category:\nUnknown", - "Lorem ipsum\ndolor sit amet,\nconsectetur adipiscing elit,\n", - "1SimpleAlert", - "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", - "2Email:", - "Vitae aliquet nec ullamcorper sit amet.", - "3News:", - "Id\naliquet\nrisus\nfeugiat\nin\nante\nmetus\ndictum\nat.", - "4IncomingCall:", - "Ut porttitor leo a diam sollicitudin.", - "5MissedCall:", - "Ultrices tincidunt arcu non sodales neque sodales ut etiam sit.", - "6Sms:", - "Pellentesque dignissim enim sit amet.", - "7VoiceMail:", - "Urna nec tincidunt praesent semper feugiat nibh sed pulvinar proin.", - "8Schedule:", - "Tellus id interdum velit laoreet id donec ultrices tincidunt.", - "9HighProriotyAlert:", - "Viverra maecenas accumsan lacus vel facilisis volutpat est velit egestas.", - "10InstantMessage:", - "Volutpat consequat mauris nunc congue.", - }; - size_t notification_idx = 0; // which message to send next - void send_notification() { - Pinetime::Controllers::NotificationManager::Notification notif; - const std::string &title = notification_messages.at(notification_idx*2); - const std::string &message = notification_messages.at(notification_idx*2+1); - std::copy(title.begin(), title.end(), notif.message.data()); - notif.message[title.size()] = '\0'; // title and message is \0 separated - std::copy(message.begin(), message.end(), notif.message.data()+title.size()+1); - notif.message[title.size() + 1 + message.size()] = '\0'; // zero terminate the message - notif.size = title.size() + 1 + message.size(); - notif.category = static_cast(notification_idx % 11); - notificationManager.Push(std::move(notif)); - // send next message the next time - notification_idx++; - if (notification_idx >= notification_messages.size()/2) { - notification_idx = 0; - } - if (settingsController.GetNotificationStatus() == Pinetime::Controllers::Settings::Notification::On) - { - if (screen_off_created) { - // wake up! (deletes screen_off label) - systemTask.PushMessage(Pinetime::System::Messages::GoToRunning); + void draw_circle_yellow(int center_x, int center_y, int radius_) { + SDL_SetRenderDrawColor(renderer, 255, 255, 0, 255); + draw_circle_(center_x, center_y, radius_); + } + + void draw_circle_grey(int center_x, int center_y, int radius_) { + SDL_SetRenderDrawColor(renderer, 128, 128, 128, 255); + draw_circle_(center_x, center_y, radius_); + } + + void draw_circle_white(int center_x, int center_y, int radius_) { + SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); + draw_circle_(center_x, center_y, radius_); + } + + void draw_circle_(int center_x, int center_y, int radius_) { + // Drawing circle + for (int x = center_x - radius_; x <= center_x + radius_; x++) { + for (int y = center_y - radius_; y <= center_y + radius_; y++) { + if ((std::pow(center_y - y, 2) + std::pow(center_x - x, 2)) <= std::pow(radius_, 2)) { + SDL_RenderDrawPoint(renderer, x, y); } - displayApp.PushMessage(Pinetime::Applications::Display::Messages::NewNotification); } } + } - // can't use SDL_PollEvent, as those are fed to lvgl - // implement a non-descructive key-pressed handler (as not consuming SDL_Events) - void handle_keys() { - const Uint8 *state = SDL_GetKeyboardState(NULL); - const bool key_shift = state[SDL_SCANCODE_LSHIFT] || state[SDL_SCANCODE_RSHIFT]; - auto debounce = [&] (const char key_low, const char key_capital, const bool scancode, bool &key_handled) { - if (scancode && !key_handled) { - if (key_shift) { - this->handle_key(key_capital); - } else { - this->handle_key(key_low); - } - key_handled = true; - } else if (scancode && key_handled) { - // ignore, already handled - } else { - key_handled = false; - } - }; - debounce('r', 'R', state[SDL_SCANCODE_R], key_handled_r); - debounce('n', 'N', state[SDL_SCANCODE_N], key_handled_n); - debounce('m', 'M', state[SDL_SCANCODE_M], key_handled_m); - debounce('b', 'B', state[SDL_SCANCODE_B], key_handled_b); - debounce('v', 'V', state[SDL_SCANCODE_V], key_handled_v); - debounce('c', 'C', state[SDL_SCANCODE_C], key_handled_c); - debounce('l', 'L', state[SDL_SCANCODE_L], key_handled_l); - debounce('p', 'P', state[SDL_SCANCODE_P], key_handled_p); - debounce('s', 'S', state[SDL_SCANCODE_S], key_handled_s); - debounce('h', 'H', state[SDL_SCANCODE_H], key_handled_h); - debounce('i', 'I', state[SDL_SCANCODE_I], key_handled_i); - debounce('w', 'W', state[SDL_SCANCODE_W], key_handled_w); - // screen switcher buttons - debounce('1', '!'+1, state[SDL_SCANCODE_1], key_handled_1); - debounce('2', '!'+2, state[SDL_SCANCODE_2], key_handled_2); - debounce('3', '!'+3, state[SDL_SCANCODE_3], key_handled_3); - debounce('4', '!'+4, state[SDL_SCANCODE_4], key_handled_4); - debounce('5', '!'+5, state[SDL_SCANCODE_5], key_handled_5); - debounce('6', '!'+6, state[SDL_SCANCODE_6], key_handled_6); - debounce('7', '!'+7, state[SDL_SCANCODE_7], key_handled_7); - debounce('8', '!'+8, state[SDL_SCANCODE_8], key_handled_8); - debounce('9', '!'+9, state[SDL_SCANCODE_9], key_handled_9); - debounce('0', '!'+0, state[SDL_SCANCODE_0], key_handled_0); - // direction keys - debounce(':', ':', state[SDL_SCANCODE_UP], key_handled_up); - debounce(';', ';', state[SDL_SCANCODE_DOWN], key_handled_down); - debounce('<', '<', state[SDL_SCANCODE_LEFT], key_handled_left); - debounce('>', '>', state[SDL_SCANCODE_RIGHT], key_handled_right); + void refresh() { + // left edge for all "bubbles" (circles) + constexpr const int bubbleLeftEdge = 65; + // always refresh the LVGL screen + this->refresh_screen(); + + if (!visible) { + return; } - // inject a swipe gesture to the touch handler and notify displayapp to notice it - void send_gesture(Pinetime::Drivers::Cst816S::Gestures gesture) - { - Pinetime::Drivers::Cst816S::TouchInfos info; - info.isValid = true; - info.touching = true; - info.gesture = gesture; - touchHandler.ProcessTouchInfo(info); - displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent); - info.touching = false; - info.gesture = Pinetime::Drivers::Cst816S::Gestures::None; - touchHandler.ProcessTouchInfo(info); + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); + SDL_RenderClear(renderer); + // Render the background if it was able to be loaded + if (simDisplayTexture != NULL) { + SDL_RenderCopy(renderer, simDisplayTexture, NULL, NULL); } - // modify the simulated controller depending on the pressed key - void handle_key(SDL_Keycode key) { - if (key == 'r') { - motorController.StartRinging(); - } else if (key == 'R') { - motorController.StopRinging(); - } else if (key == 'm') { - motorController.RunForDuration(100); - } else if (key == 'M') { - motorController.RunForDuration(255); - } else if (key == 'n') { - send_notification(); - } else if (key == 'N') { - notificationManager.ClearNewNotificationFlag(); - } else if (key == 'b') { - bleController.Connect(); - } else if (key == 'B') { - bleController.Disconnect(); - } else if (key == 'v') { - if (batteryController.percentRemaining >= 90) { - batteryController.percentRemaining = 100; - } else { - batteryController.percentRemaining += 10; - } - } else if (key == 'V') { - if (batteryController.percentRemaining <= 10) { - batteryController.percentRemaining = 0; - } else { - batteryController.percentRemaining -= 10; - } - } else if (key == 'c') { - batteryController.isCharging = true; - batteryController.isPowerPresent = true; - } else if (key == 'C') { - batteryController.isCharging = false; - batteryController.isPowerPresent = false; - } else if (key == 'l' && !screen_off_created) { - brightnessController.Higher(); - } else if (key == 'L' && !screen_off_created) { - brightnessController.Lower(); - } else if (key == 'p') { - this->print_memory_usage = true; - } else if (key == 'P') { - this->print_memory_usage = false; - } else if (key == 's') { - motionSensor.steps += 500; - } else if (key == 'S') { - if (motionSensor.steps > 500) { - motionSensor.steps -= 500; - } else { - motionSensor.steps = 0; - } - } else if (key == 'h') { - if (heartRateController.State() == Pinetime::Controllers::HeartRateController::States::Stopped) { - heartRateController.Enable(); - } else if (heartRateController.State() == Pinetime::Controllers::HeartRateController::States::NotEnoughData) { - heartRateController.Update(Pinetime::Controllers::HeartRateController::States::Running, 10); - } else { - uint8_t heartrate = heartRateController.HeartRate(); - heartRateController.Update(Pinetime::Controllers::HeartRateController::States::Running, heartrate + 10); - } - } else if (key == 'H') { - heartRateController.Disable(); - } else if (key == 'i') { - saveScreenshot(); - } else if (key == 'I') { - if (!gif_manager.is_in_progress()) - { - gif_manager.create_new(); - } else { - gif_manager.close(); - } - } else if (key == 'w') { - generate_weather_data(false); - } else if (key == 'W') { - generate_weather_data(true); - } else if (key >= '0' && key <= '9') { - this->switch_to_screen(key-'0'); - } else if (key >= '!'+0 && key <= '!'+9) { - this->switch_to_screen(key-'!'+10); - } else if (key == ':') { // up - send_gesture(Pinetime::Drivers::Cst816S::Gestures::SlideUp); - } else if (key == ';') { // down - send_gesture(Pinetime::Drivers::Cst816S::Gestures::SlideDown); - } else if (key == '<') { // left - send_gesture(Pinetime::Drivers::Cst816S::Gestures::SlideLeft); - } else if (key == '>') { // up - send_gesture(Pinetime::Drivers::Cst816S::Gestures::SlideRight); + { // motorController.motor_is_running + constexpr const int center_x = bubbleLeftEdge; + constexpr const int center_y = 216; + bool motor_is_running = nrf_gpio_pin_read(Pinetime::PinMap::Motor); + if (motor_is_running) { + draw_circle_red(center_x, center_y, 15); + } else { + draw_circle_grey(center_x, center_y, 15); } - batteryController.voltage = batteryController.percentRemaining * 50; } - - void write_uint64(std::span data, uint64_t val) - { - assert(data.size() >= 8); - for (int i=0; i<8; i++) - { - data[i] = (val >> (i*8)) & 0xff; + { // ble.motor_is_running + constexpr const int center_x = bubbleLeftEdge; + constexpr const int center_y = 24; + if (bleController.IsConnected()) { + draw_circle_blue(center_x, center_y, 15); + } else { + draw_circle_grey(center_x, center_y, 15); } } - void write_int16(std::span data, int16_t val) + // batteryController.percentRemaining { - assert(data.size() >= 2); - data[0] = val & 0xff; - data[1] = (val >> 8) & 0xff; + const int center_x = bubbleLeftEdge; + const int center_y = 164; + const int max_bar_length = 150; + const int filled_bar_length = max_bar_length * (batteryController.percentRemaining / 100.0); + const int rect_height = 14; + SDL_Rect rect {.x = center_x - rect_height / 2, .y = center_y, .w = max_bar_length, .h = rect_height}; + SDL_SetRenderDrawColor(renderer, 128, 128, 128, 255); + SDL_RenderDrawRect(renderer, &rect); + + rect.w = filled_bar_length; + rect.h++; + rect.h -= 2; + SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); + SDL_RenderFillRect(renderer, &rect); + // set color and new x pos, draw again } - void set_current_weather(uint64_t timestamp, int16_t temperature, int iconId) - { - std::array dataBuffer {}; - std::span data(dataBuffer); - os_mbuf buffer; - ble_gatt_access_ctxt ctxt; - ctxt.om = &buffer; - buffer.om_data = dataBuffer.data(); - - // fill buffer with specified format - int16_t minTemperature = temperature; - int16_t maxTemperature = temperature; - dataBuffer.at(0) = 0; // MessageType::CurrentWeather - dataBuffer.at(1) = 0; // Vesion 0 - write_uint64(data.subspan(2), timestamp); - write_int16(data.subspan(10), temperature); - write_int16(data.subspan(12), minTemperature); - write_int16(data.subspan(14), maxTemperature); - dataBuffer.at(48) = static_cast(iconId); - - // send weather to SimpleWeatherService - systemTask.nimble().weather().OnCommand(&ctxt); + { // batteryController.isCharging + constexpr const int center_x = bubbleLeftEdge; + constexpr const int center_y = 120; + if (batteryController.isCharging) { + draw_circle_yellow(center_x, center_y, 15); + } else { + draw_circle_grey(center_x, center_y, 15); + } } - void set_forecast( - uint64_t timestamp, - std::array< - std::optional, - Pinetime::Controllers::SimpleWeatherService::MaxNbForecastDays> days) - { - std::array dataBuffer {}; - std::span data(dataBuffer); - os_mbuf buffer; - ble_gatt_access_ctxt ctxt; - ctxt.om = &buffer; - buffer.om_data = dataBuffer.data(); - - // fill buffer with specified format - dataBuffer.at(0) = 1; // MessageType::Forecast - dataBuffer.at(1) = 0; // Vesion 0 - write_uint64(data.subspan(2), timestamp); - dataBuffer.at(10) = static_cast(days.size()); - for (int i = 0; i < days.size(); i++) - { - const std::optional &day = days.at(i); - if (!day.has_value()) { - continue; + { // brightnessController.Level + constexpr const int center_y = 72; + const Pinetime::Controllers::BrightnessController::Levels level = brightnessController.Level(); + uint8_t level_idx = 0; + if (level == Pinetime::Controllers::BrightnessController::Levels::Low) { + level_idx = 1; + } else if (level == Pinetime::Controllers::BrightnessController::Levels::Medium) { + level_idx = 2; + } else if (level == Pinetime::Controllers::BrightnessController::Levels::High) { + level_idx = 3; + } + for (uint8_t i = 0; i < 4; i++) { + const int bubble_size = (i * 2) + 5; + const int center_x = bubbleLeftEdge + ((bubble_size + 10) * i) - 5; + if (i <= level_idx) { + draw_circle_white(center_x, center_y, bubble_size); + } else { + draw_circle_grey(center_x, center_y, bubble_size); } - write_int16(data.subspan(11+(i*5)), day->minTemperature.PreciseCelsius()); - write_int16(data.subspan(13+(i*5)), day->maxTemperature.PreciseCelsius()); - dataBuffer.at(15+(i*5)) = static_cast(day->iconId); } - // send Forecast to SimpleWeatherService - systemTask.nimble().weather().OnCommand(&ctxt); } + // Show the change on the screen + SDL_RenderPresent(renderer); + } - void generate_weather_data(bool clear) { - if (clear) { - set_current_weather(0, 0, 0); - std::array, Pinetime::Controllers::SimpleWeatherService::MaxNbForecastDays> days; - set_forecast(0, days); - return; - } - auto timestamp = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); - srand((int)timestamp); - - // Generate current weather data - int16_t temperature = (rand() % 81 - 40) * 100; - set_current_weather((uint64_t)timestamp, temperature, rand() % 9); - - // Generate forecast data - std::array, Pinetime::Controllers::SimpleWeatherService::MaxNbForecastDays> days; - for (int i = 0; i < Pinetime::Controllers::SimpleWeatherService::MaxNbForecastDays; i++) { - days[i] = Pinetime::Controllers::SimpleWeatherService::Forecast::Day { - Pinetime::Controllers::SimpleWeatherService::Temperature(temperature - rand() % 10 * 100), - Pinetime::Controllers::SimpleWeatherService::Temperature(temperature + rand() % 10 * 100), - Pinetime::Controllers::SimpleWeatherService::Icons(rand() % 9), - }; + // prepared notficitions, one per message category + const std::vector notification_messages { + "0category:\nUnknown", + "Lorem ipsum\ndolor sit amet,\nconsectetur adipiscing elit,\n", + "1SimpleAlert", + "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + "2Email:", + "Vitae aliquet nec ullamcorper sit amet.", + "3News:", + "Id\naliquet\nrisus\nfeugiat\nin\nante\nmetus\ndictum\nat.", + "4IncomingCall:", + "Ut porttitor leo a diam sollicitudin.", + "5MissedCall:", + "Ultrices tincidunt arcu non sodales neque sodales ut etiam sit.", + "6Sms:", + "Pellentesque dignissim enim sit amet.", + "7VoiceMail:", + "Urna nec tincidunt praesent semper feugiat nibh sed pulvinar proin.", + "8Schedule:", + "Tellus id interdum velit laoreet id donec ultrices tincidunt.", + "9HighProriotyAlert:", + "Viverra maecenas accumsan lacus vel facilisis volutpat est velit egestas.", + "10InstantMessage:", + "Volutpat consequat mauris nunc congue.", + }; + size_t notification_idx = 0; // which message to send next + + void send_notification() { + Pinetime::Controllers::NotificationManager::Notification notif; + const std::string& title = notification_messages.at(notification_idx * 2); + const std::string& message = notification_messages.at(notification_idx * 2 + 1); + std::copy(title.begin(), title.end(), notif.message.data()); + notif.message[title.size()] = '\0'; // title and message is \0 separated + std::copy(message.begin(), message.end(), notif.message.data() + title.size() + 1); + notif.message[title.size() + 1 + message.size()] = '\0'; // zero terminate the message + notif.size = title.size() + 1 + message.size(); + notif.category = static_cast(notification_idx % 11); + notificationManager.Push(std::move(notif)); + // send next message the next time + notification_idx++; + if (notification_idx >= notification_messages.size() / 2) { + notification_idx = 0; + } + if (settingsController.GetNotificationStatus() == Pinetime::Controllers::Settings::Notification::On) { + if (screen_off_created) { + // wake up! (deletes screen_off label) + systemTask.PushMessage(Pinetime::System::Messages::GoToRunning); } - set_forecast((uint64_t)timestamp, days); + displayApp.PushMessage(Pinetime::Applications::Display::Messages::NewNotification); } + } - void handle_touch_and_button() { - int x, y; - uint32_t buttons = SDL_GetMouseState(&x, &y); - const bool left_click = (buttons & SDL_BUTTON_LMASK) != 0; - const bool right_click = (buttons & SDL_BUTTON_RMASK) != 0; - if (left_click) { - left_release_sent = false; - systemTask.PushMessage(Pinetime::System::Messages::OnTouchEvent); - return; - } else { - if (!left_release_sent) { - left_release_sent = true; - systemTask.PushMessage(Pinetime::System::Messages::OnTouchEvent); - return; + // can't use SDL_PollEvent, as those are fed to lvgl + // implement a non-descructive key-pressed handler (as not consuming SDL_Events) + void handle_keys() { + const Uint8* state = SDL_GetKeyboardState(NULL); + const bool key_shift = state[SDL_SCANCODE_LSHIFT] || state[SDL_SCANCODE_RSHIFT]; + auto debounce = [&](const char key_low, const char key_capital, const bool scancode, bool& key_handled) { + if (scancode && !key_handled) { + if (key_shift) { + this->handle_key(key_capital); + } else { + this->handle_key(key_low); } + key_handled = true; + } else if (scancode && key_handled) { + // ignore, already handled + } else { + key_handled = false; } - if (right_click != right_last_state) { - right_last_state =right_click; - systemTask.PushMessage(Pinetime::System::Messages::HandleButtonEvent); - return; - } - } + }; + debounce('r', 'R', state[SDL_SCANCODE_R], key_handled_r); + debounce('n', 'N', state[SDL_SCANCODE_N], key_handled_n); + debounce('m', 'M', state[SDL_SCANCODE_M], key_handled_m); + debounce('b', 'B', state[SDL_SCANCODE_B], key_handled_b); + debounce('v', 'V', state[SDL_SCANCODE_V], key_handled_v); + debounce('c', 'C', state[SDL_SCANCODE_C], key_handled_c); + debounce('l', 'L', state[SDL_SCANCODE_L], key_handled_l); + debounce('p', 'P', state[SDL_SCANCODE_P], key_handled_p); + debounce('s', 'S', state[SDL_SCANCODE_S], key_handled_s); + debounce('h', 'H', state[SDL_SCANCODE_H], key_handled_h); + debounce('i', 'I', state[SDL_SCANCODE_I], key_handled_i); + debounce('w', 'W', state[SDL_SCANCODE_W], key_handled_w); + // screen switcher buttons + debounce('1', '!' + 1, state[SDL_SCANCODE_1], key_handled_1); + debounce('2', '!' + 2, state[SDL_SCANCODE_2], key_handled_2); + debounce('3', '!' + 3, state[SDL_SCANCODE_3], key_handled_3); + debounce('4', '!' + 4, state[SDL_SCANCODE_4], key_handled_4); + debounce('5', '!' + 5, state[SDL_SCANCODE_5], key_handled_5); + debounce('6', '!' + 6, state[SDL_SCANCODE_6], key_handled_6); + debounce('7', '!' + 7, state[SDL_SCANCODE_7], key_handled_7); + debounce('8', '!' + 8, state[SDL_SCANCODE_8], key_handled_8); + debounce('9', '!' + 9, state[SDL_SCANCODE_9], key_handled_9); + debounce('0', '!' + 0, state[SDL_SCANCODE_0], key_handled_0); + // direction keys + debounce(':', ':', state[SDL_SCANCODE_UP], key_handled_up); + debounce(';', ';', state[SDL_SCANCODE_DOWN], key_handled_down); + debounce('<', '<', state[SDL_SCANCODE_LEFT], key_handled_left); + debounce('>', '>', state[SDL_SCANCODE_RIGHT], key_handled_right); + } - // helper function to switch between screens - void switch_to_screen(uint8_t screen_idx) - { - if (screen_idx == 1) { - settingsController.SetWatchFace(Pinetime::Applications::WatchFace::Digital); - displayApp.StartApp(Pinetime::Applications::Apps::Clock, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); - } - else if (screen_idx == 2) { - settingsController.SetWatchFace(Pinetime::Applications::WatchFace::Analog); - displayApp.StartApp(Pinetime::Applications::Apps::Clock, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); - } - else if (screen_idx == 3) { - settingsController.SetWatchFace(Pinetime::Applications::WatchFace::PineTimeStyle); - displayApp.StartApp(Pinetime::Applications::Apps::Clock, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); - } - else if (screen_idx == 4) { - displayApp.StartApp(Pinetime::Applications::Apps::Paddle, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); - } - else if (screen_idx == 5) { - displayApp.StartApp(Pinetime::Applications::Apps::Twos, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); - } - else if (screen_idx == 6) { - displayApp.StartApp(Pinetime::Applications::Apps::Metronome, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); - } - else if (screen_idx == 7) { - displayApp.StartApp(Pinetime::Applications::Apps::FirmwareUpdate, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); - } - else if (screen_idx == 8) { - displayApp.StartApp(Pinetime::Applications::Apps::BatteryInfo, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); - } - else if (screen_idx == 9) { - displayApp.StartApp(Pinetime::Applications::Apps::FlashLight, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); - } - else if (screen_idx == 0) { - displayApp.StartApp(Pinetime::Applications::Apps::QuickSettings, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); - } - else if (screen_idx == 11) { - displayApp.StartApp(Pinetime::Applications::Apps::Music, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); - } - else if (screen_idx == 12) { - displayApp.StartApp(Pinetime::Applications::Apps::Paint, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + // inject a swipe gesture to the touch handler and notify displayapp to notice it + void send_gesture(Pinetime::Drivers::Cst816S::Gestures gesture) { + Pinetime::Drivers::Cst816S::TouchInfos info; + info.isValid = true; + info.touching = true; + info.gesture = gesture; + touchHandler.ProcessTouchInfo(info); + displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent); + info.touching = false; + info.gesture = Pinetime::Drivers::Cst816S::Gestures::None; + touchHandler.ProcessTouchInfo(info); + } + + // modify the simulated controller depending on the pressed key + void handle_key(SDL_Keycode key) { + if (key == 'r') { + motorController.StartRinging(); + } else if (key == 'R') { + motorController.StopRinging(); + } else if (key == 'm') { + motorController.RunForDuration(100); + } else if (key == 'M') { + motorController.RunForDuration(255); + } else if (key == 'n') { + send_notification(); + } else if (key == 'N') { + notificationManager.ClearNewNotificationFlag(); + } else if (key == 'b') { + bleController.Connect(); + } else if (key == 'B') { + bleController.Disconnect(); + } else if (key == 'v') { + if (batteryController.percentRemaining >= 90) { + batteryController.percentRemaining = 100; + } else { + batteryController.percentRemaining += 10; } - else if (screen_idx == 13) { - displayApp.StartApp(Pinetime::Applications::Apps::SysInfo, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + } else if (key == 'V') { + if (batteryController.percentRemaining <= 10) { + batteryController.percentRemaining = 0; + } else { + batteryController.percentRemaining -= 10; } - else if (screen_idx == 14) { - displayApp.StartApp(Pinetime::Applications::Apps::Steps, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + } else if (key == 'c') { + batteryController.isCharging = true; + batteryController.isPowerPresent = true; + } else if (key == 'C') { + batteryController.isCharging = false; + batteryController.isPowerPresent = false; + } else if (key == 'l' && !screen_off_created) { + brightnessController.Higher(); + } else if (key == 'L' && !screen_off_created) { + brightnessController.Lower(); + } else if (key == 'p') { + this->print_memory_usage = true; + } else if (key == 'P') { + this->print_memory_usage = false; + } else if (key == 's') { + motionSensor.steps += 500; + } else if (key == 'S') { + if (motionSensor.steps > 500) { + motionSensor.steps -= 500; + } else { + motionSensor.steps = 0; } - else if (screen_idx == 15) { - displayApp.StartApp(Pinetime::Applications::Apps::Error, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + } else if (key == 'h') { + if (heartRateController.State() == Pinetime::Controllers::HeartRateController::States::Stopped) { + heartRateController.Enable(); + } else if (heartRateController.State() == Pinetime::Controllers::HeartRateController::States::NotEnoughData) { + heartRateController.Update(Pinetime::Controllers::HeartRateController::States::Running, 10); + } else { + uint8_t heartrate = heartRateController.HeartRate(); + heartRateController.Update(Pinetime::Controllers::HeartRateController::States::Running, heartrate + 10); } - else if (screen_idx == 17) { - displayApp.StartApp(Pinetime::Applications::Apps::PassKey, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + } else if (key == 'H') { + heartRateController.Disable(); + } else if (key == 'i') { + saveScreenshot(); + } else if (key == 'I') { + if (!gif_manager.is_in_progress()) { + gif_manager.create_new(); + } else { + gif_manager.close(); } - else { - std::cout << "unhandled screen_idx: " << int(screen_idx) << std::endl; + } else if (key == 'w') { + generate_weather_data(false); + } else if (key == 'W') { + generate_weather_data(true); + } else if (key >= '0' && key <= '9') { + this->switch_to_screen(key - '0'); + } else if (key >= '!' + 0 && key <= '!' + 9) { + this->switch_to_screen(key - '!' + 10); + } else if (key == ':') { // up + send_gesture(Pinetime::Drivers::Cst816S::Gestures::SlideUp); + } else if (key == ';') { // down + send_gesture(Pinetime::Drivers::Cst816S::Gestures::SlideDown); + } else if (key == '<') { // left + send_gesture(Pinetime::Drivers::Cst816S::Gestures::SlideLeft); + } else if (key == '>') { // up + send_gesture(Pinetime::Drivers::Cst816S::Gestures::SlideRight); + } + batteryController.voltage = batteryController.percentRemaining * 50; + } + + void write_uint64(std::span data, uint64_t val) { + assert(data.size() >= 8); + for (int i = 0; i < 8; i++) { + data[i] = (val >> (i * 8)) & 0xff; + } + } + + void write_int16(std::span data, int16_t val) { + assert(data.size() >= 2); + data[0] = val & 0xff; + data[1] = (val >> 8) & 0xff; + } + + void set_current_weather(uint64_t timestamp, int16_t temperature, int iconId) { + std::array dataBuffer {}; + std::span data(dataBuffer); + os_mbuf buffer; + ble_gatt_access_ctxt ctxt; + ctxt.om = &buffer; + buffer.om_data = dataBuffer.data(); + + // fill buffer with specified format + int16_t minTemperature = temperature; + int16_t maxTemperature = temperature; + dataBuffer.at(0) = 0; // MessageType::CurrentWeather + dataBuffer.at(1) = 0; // Vesion 0 + write_uint64(data.subspan(2), timestamp); + write_int16(data.subspan(10), temperature); + write_int16(data.subspan(12), minTemperature); + write_int16(data.subspan(14), maxTemperature); + dataBuffer.at(48) = static_cast(iconId); + + // send weather to SimpleWeatherService + systemTask.nimble().weather().OnCommand(&ctxt); + } + + void set_forecast(uint64_t timestamp, + std::array, + Pinetime::Controllers::SimpleWeatherService::MaxNbForecastDays> days) { + std::array dataBuffer {}; + std::span data(dataBuffer); + os_mbuf buffer; + ble_gatt_access_ctxt ctxt; + ctxt.om = &buffer; + buffer.om_data = dataBuffer.data(); + + // fill buffer with specified format + dataBuffer.at(0) = 1; // MessageType::Forecast + dataBuffer.at(1) = 0; // Vesion 0 + write_uint64(data.subspan(2), timestamp); + dataBuffer.at(10) = static_cast(days.size()); + for (int i = 0; i < days.size(); i++) { + const std::optional& day = days.at(i); + if (!day.has_value()) { + continue; } + write_int16(data.subspan(11 + (i * 5)), day->minTemperature.PreciseCelsius()); + write_int16(data.subspan(13 + (i * 5)), day->maxTemperature.PreciseCelsius()); + dataBuffer.at(15 + (i * 5)) = static_cast(day->iconId); } - static void screen_off_delete_cb(lv_obj_t *obj, lv_event_t event) - { - if (event == LV_EVENT_DELETE) { - auto* fw = static_cast(obj->user_data); - if (obj == fw->screen_off_bg) - { - // on delete make sure to not double free the screen_off objects - fw->screen_off_created = false; - } + // send Forecast to SimpleWeatherService + systemTask.nimble().weather().OnCommand(&ctxt); + } + + void generate_weather_data(bool clear) { + if (clear) { + set_current_weather(0, 0, 0); + std::array, + Pinetime::Controllers::SimpleWeatherService::MaxNbForecastDays> + days; + set_forecast(0, days); + return; + } + auto timestamp = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); + srand((int) timestamp); + + // Generate current weather data + int16_t temperature = (rand() % 81 - 40) * 100; + set_current_weather((uint64_t) timestamp, temperature, rand() % 9); + + // Generate forecast data + std::array, + Pinetime::Controllers::SimpleWeatherService::MaxNbForecastDays> + days; + for (int i = 0; i < Pinetime::Controllers::SimpleWeatherService::MaxNbForecastDays; i++) { + days[i] = Pinetime::Controllers::SimpleWeatherService::Forecast::Day { + Pinetime::Controllers::SimpleWeatherService::Temperature(temperature - rand() % 10 * 100), + Pinetime::Controllers::SimpleWeatherService::Temperature(temperature + rand() % 10 * 100), + Pinetime::Controllers::SimpleWeatherService::Icons(rand() % 9), + }; + } + set_forecast((uint64_t) timestamp, days); + } + + void handle_touch_and_button() { + int x, y; + uint32_t buttons = SDL_GetMouseState(&x, &y); + const bool left_click = (buttons & SDL_BUTTON_LMASK) != 0; + const bool right_click = (buttons & SDL_BUTTON_RMASK) != 0; + if (left_click) { + left_release_sent = false; + systemTask.PushMessage(Pinetime::System::Messages::OnTouchEvent); + return; + } else { + if (!left_release_sent) { + left_release_sent = true; + systemTask.PushMessage(Pinetime::System::Messages::OnTouchEvent); + return; } } - // render the current status of the simulated controller - void refresh_screen() { - const Pinetime::Controllers::BrightnessController::Levels level = brightnessController.Level(); - if (level == Pinetime::Controllers::BrightnessController::Levels::Off) { - if (!screen_off_created) { - screen_off_created = true; - screen_off_bg = lv_obj_create(lv_scr_act(), nullptr); - lv_obj_set_size(screen_off_bg, 240, 240); - lv_obj_set_pos(screen_off_bg, 0, 0); - lv_obj_set_style_local_bg_color(screen_off_bg, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); - screen_off_bg->user_data = this; // add callback to prevent double free through Alarm Screen - lv_obj_set_event_cb(screen_off_bg, screen_off_delete_cb); - screen_off_label = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_static(screen_off_label, "Screen is OFF"); - lv_obj_align(screen_off_label, nullptr, LV_ALIGN_CENTER, 0, -20); - } - /* Periodically call the lv_task handler. - * It could be done in a timer interrupt or an OS task too.*/ - // only call the task handler if the screen is off, - // when the screen is enabled the call is done in the SystemTask class - lv_task_handler(); - } else { - if (screen_off_created) { - screen_off_created = false; - lv_obj_del(screen_off_bg); - lv_obj_del(screen_off_label); - } + if (right_click != right_last_state) { + right_last_state = right_click; + systemTask.PushMessage(Pinetime::System::Messages::HandleButtonEvent); + return; + } + } + + // helper function to switch between screens + void switch_to_screen(uint8_t screen_idx) { + if (screen_idx == 1) { + settingsController.SetWatchFace(Pinetime::Applications::WatchFace::Digital); + displayApp.StartApp(Pinetime::Applications::Apps::Clock, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + } else if (screen_idx == 2) { + settingsController.SetWatchFace(Pinetime::Applications::WatchFace::Analog); + displayApp.StartApp(Pinetime::Applications::Apps::Clock, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + } else if (screen_idx == 3) { + settingsController.SetWatchFace(Pinetime::Applications::WatchFace::PineTimeStyle); + displayApp.StartApp(Pinetime::Applications::Apps::Clock, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + } else if (screen_idx == 4) { + displayApp.StartApp(Pinetime::Applications::Apps::Paddle, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + } else if (screen_idx == 5) { + displayApp.StartApp(Pinetime::Applications::Apps::Twos, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + } else if (screen_idx == 6) { + displayApp.StartApp(Pinetime::Applications::Apps::Metronome, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + } else if (screen_idx == 7) { + displayApp.StartApp(Pinetime::Applications::Apps::FirmwareUpdate, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + } else if (screen_idx == 8) { + displayApp.StartApp(Pinetime::Applications::Apps::BatteryInfo, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + } else if (screen_idx == 9) { + displayApp.StartApp(Pinetime::Applications::Apps::FlashLight, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + } else if (screen_idx == 0) { + displayApp.StartApp(Pinetime::Applications::Apps::QuickSettings, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + } else if (screen_idx == 11) { + displayApp.StartApp(Pinetime::Applications::Apps::Music, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + } else if (screen_idx == 12) { + displayApp.StartApp(Pinetime::Applications::Apps::Paint, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + } else if (screen_idx == 13) { + displayApp.StartApp(Pinetime::Applications::Apps::SysInfo, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + } else if (screen_idx == 14) { + displayApp.StartApp(Pinetime::Applications::Apps::Steps, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + } else if (screen_idx == 15) { + displayApp.StartApp(Pinetime::Applications::Apps::Error, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + } else if (screen_idx == 17) { + displayApp.StartApp(Pinetime::Applications::Apps::PassKey, Pinetime::Applications::DisplayApp::FullRefreshDirections::None); + } else { + std::cout << "unhandled screen_idx: " << int(screen_idx) << std::endl; + } + } + + static void screen_off_delete_cb(lv_obj_t* obj, lv_event_t event) { + if (event == LV_EVENT_DELETE) { + auto* fw = static_cast(obj->user_data); + if (obj == fw->screen_off_bg) { + // on delete make sure to not double free the screen_off objects + fw->screen_off_created = false; } + } + } - if (print_memory_usage) { - auto currentFreeHeap = xPortGetFreeHeapSize(); - if (currentFreeHeap != lastFreeHeapSize) { - auto minimumEverFreeHeap = xPortGetMinimumEverFreeHeapSize(); - // 14KiB is the LVGL memory size used in InfiniTime - constexpr uint32_t pinetime_heap_memory = configTOTAL_HEAP_SIZE; - uint32_t mem_used = pinetime_heap_memory - currentFreeHeap; - // The "budget" value shows how much free lvgl memory the PineTime - // would have free and will go negative when more memory is used - // in the simulator than is available on the real hardware. - int32_t budget = configTOTAL_HEAP_SIZE - mem_used; - printf("Mem: %5u used (change: %+5d, peak: %5u) %d budget left\n", mem_used, lastFreeHeapSize - currentFreeHeap, minimumEverFreeHeap, budget); - lastFreeHeapSize = currentFreeHeap; - } + // render the current status of the simulated controller + void refresh_screen() { + const Pinetime::Controllers::BrightnessController::Levels level = brightnessController.Level(); + if (level == Pinetime::Controllers::BrightnessController::Levels::Off) { + if (!screen_off_created) { + screen_off_created = true; + screen_off_bg = lv_obj_create(lv_scr_act(), nullptr); + lv_obj_set_size(screen_off_bg, 240, 240); + lv_obj_set_pos(screen_off_bg, 0, 0); + lv_obj_set_style_local_bg_color(screen_off_bg, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + screen_off_bg->user_data = this; // add callback to prevent double free through Alarm Screen + lv_obj_set_event_cb(screen_off_bg, screen_off_delete_cb); + screen_off_label = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(screen_off_label, "Screen is OFF"); + lv_obj_align(screen_off_label, nullptr, LV_ALIGN_CENTER, 0, -20); + } + /* Periodically call the lv_task handler. + * It could be done in a timer interrupt or an OS task too.*/ + // only call the task handler if the screen is off, + // when the screen is enabled the call is done in the SystemTask class + lv_task_handler(); + } else { + if (screen_off_created) { + screen_off_created = false; + lv_obj_del(screen_off_bg); + lv_obj_del(screen_off_label); } + } - if (gif_manager.is_in_progress()) - { - gif_manager.write_frame(); + if (print_memory_usage) { + auto currentFreeHeap = xPortGetFreeHeapSize(); + if (currentFreeHeap != lastFreeHeapSize) { + auto minimumEverFreeHeap = xPortGetMinimumEverFreeHeapSize(); + // 14KiB is the LVGL memory size used in InfiniTime + constexpr uint32_t pinetime_heap_memory = configTOTAL_HEAP_SIZE; + uint32_t mem_used = pinetime_heap_memory - currentFreeHeap; + // The "budget" value shows how much free lvgl memory the PineTime + // would have free and will go negative when more memory is used + // in the simulator than is available on the real hardware. + int32_t budget = configTOTAL_HEAP_SIZE - mem_used; + printf("Mem: %5u used (change: %+5d, peak: %5u) %d budget left\n", + mem_used, + lastFreeHeapSize - currentFreeHeap, + minimumEverFreeHeap, + budget); + lastFreeHeapSize = currentFreeHeap; } } - bool print_memory_usage = false; + if (gif_manager.is_in_progress()) { + gif_manager.write_frame(); + } + } + + bool print_memory_usage = false; - // variables to create and destroy an lvgl overlay to indicate a turned off screen - bool screen_off_created = false; - lv_obj_t *screen_off_bg; - lv_obj_t *screen_off_label; + // variables to create and destroy an lvgl overlay to indicate a turned off screen + bool screen_off_created = false; + lv_obj_t* screen_off_bg; + lv_obj_t* screen_off_label; private: - bool key_handled_r = false; // r ... enable ringing, R ... disable ringing - bool key_handled_m = false; // m ... let motor run, M ... stop motor - bool key_handled_n = false; // n ... send notification, N ... clear new notification flag - bool key_handled_b = false; // b ... connect Bluetooth, B ... disconnect Bluetooth - bool key_handled_v = false; // battery Voltage and percentage, v ... increase, V ... decrease - bool key_handled_c = false; // c ... charging, C ... not charging - bool key_handled_l = false; // l ... increase brightness level, L ... lower brightness level - bool key_handled_p = false; // p ... enable print memory usage, P ... disable print memory usage - bool key_handled_s = false; // s ... increase step count, S ... decrease step count - bool key_handled_h = false; // h ... set heartrate running, H ... stop heartrate - bool key_handled_i = false; // i ... take screenshot, I ... start/stop Gif screen capture - bool key_handled_w = false; // w ... generate weather data, W ... clear weather data - // numbers from 0 to 9 to switch between screens - bool key_handled_1 = false; - bool key_handled_2 = false; - bool key_handled_3 = false; - bool key_handled_4 = false; - bool key_handled_5 = false; - bool key_handled_6 = false; - bool key_handled_7 = false; - bool key_handled_8 = false; - bool key_handled_9 = false; - bool key_handled_0 = false; - // direction arrows - bool key_handled_up = false; // inject swipe up - bool key_handled_down = false; // inject swipe down - bool key_handled_left = false; // inject swipe left - bool key_handled_right = false; // inject swipe right - bool visible; // show Simulator window - int height; // Height of the window - int width; // Width of the window - SDL_Renderer *renderer = NULL; // Pointer for the renderer - SDL_Window *window = NULL; // Pointer for the window - SDL_Texture* simDisplayTexture = NULL; // Background for the sim status window - - bool left_release_sent = true; // make sure to send one mouse button release event - bool right_last_state = false; // varable used to send message only on changing state - - size_t lastFreeHeapSize = configTOTAL_HEAP_SIZE; - - GifManager gif_manager; + bool key_handled_r = false; // r ... enable ringing, R ... disable ringing + bool key_handled_m = false; // m ... let motor run, M ... stop motor + bool key_handled_n = false; // n ... send notification, N ... clear new notification flag + bool key_handled_b = false; // b ... connect Bluetooth, B ... disconnect Bluetooth + bool key_handled_v = false; // battery Voltage and percentage, v ... increase, V ... decrease + bool key_handled_c = false; // c ... charging, C ... not charging + bool key_handled_l = false; // l ... increase brightness level, L ... lower brightness level + bool key_handled_p = false; // p ... enable print memory usage, P ... disable print memory usage + bool key_handled_s = false; // s ... increase step count, S ... decrease step count + bool key_handled_h = false; // h ... set heartrate running, H ... stop heartrate + bool key_handled_i = false; // i ... take screenshot, I ... start/stop Gif screen capture + bool key_handled_w = false; // w ... generate weather data, W ... clear weather data + // numbers from 0 to 9 to switch between screens + bool key_handled_1 = false; + bool key_handled_2 = false; + bool key_handled_3 = false; + bool key_handled_4 = false; + bool key_handled_5 = false; + bool key_handled_6 = false; + bool key_handled_7 = false; + bool key_handled_8 = false; + bool key_handled_9 = false; + bool key_handled_0 = false; + // direction arrows + bool key_handled_up = false; // inject swipe up + bool key_handled_down = false; // inject swipe down + bool key_handled_left = false; // inject swipe left + bool key_handled_right = false; // inject swipe right + bool visible; // show Simulator window + int height; // Height of the window + int width; // Width of the window + SDL_Renderer* renderer = NULL; // Pointer for the renderer + SDL_Window* window = NULL; // Pointer for the window + SDL_Texture* simDisplayTexture = NULL; // Background for the sim status window + + bool left_release_sent = true; // make sure to send one mouse button release event + bool right_last_state = false; // varable used to send message only on changing state + + size_t lastFreeHeapSize = configTOTAL_HEAP_SIZE; + + GifManager gif_manager; }; int mallocFailedCount = 0; int stackOverflowCount = 0; -int main(int argc, char **argv) -{ + +int main(int argc, char** argv) { // parse arguments bool fw_status_window_visible = true; bool arg_help = false; - for (int i=1; i #include -void NVIC_SystemReset(void) {} +void NVIC_SystemReset(void) { +} void APP_ERROR_HANDLER(int err) { fprintf(stderr, "APP_ERROR_HANDLER: %d", err); } namespace { -std::unordered_map allocatedMemory; -size_t currentFreeHeap = configTOTAL_HEAP_SIZE; -size_t minimumEverFreeHeap = configTOTAL_HEAP_SIZE; + std::unordered_map allocatedMemory; + size_t currentFreeHeap = configTOTAL_HEAP_SIZE; + size_t minimumEverFreeHeap = configTOTAL_HEAP_SIZE; } -void *pvPortMalloc( size_t xWantedSize ) { +void* pvPortMalloc(size_t xWantedSize) { void* ptr = malloc(xWantedSize); allocatedMemory[ptr] = xWantedSize; - const size_t currentSize = std::accumulate( - allocatedMemory.begin(), allocatedMemory.end(), 0, - [](const size_t lhs, const std::pair& item){ + const size_t currentSize = + std::accumulate(allocatedMemory.begin(), allocatedMemory.end(), 0, [](const size_t lhs, const std::pair& item) { return lhs + item.second; - }); + }); currentFreeHeap = configTOTAL_HEAP_SIZE - currentSize; minimumEverFreeHeap = std::min(currentFreeHeap, minimumEverFreeHeap); return ptr; } -void vPortFree( void *pv ) { + +void vPortFree(void* pv) { allocatedMemory.erase(pv); return free(pv); } diff --git a/sim/components/battery/BatteryController.cpp b/sim/components/battery/BatteryController.cpp index effd0a2..f5f582b 100644 --- a/sim/components/battery/BatteryController.cpp +++ b/sim/components/battery/BatteryController.cpp @@ -1,7 +1,7 @@ #include "components/battery/BatteryController.h" -//#include "drivers/PinMap.h" -//#include -//#include +// #include "drivers/PinMap.h" +// #include +// #include #include using namespace Pinetime::Controllers; @@ -10,7 +10,7 @@ Battery* Battery::instance = nullptr; Battery::Battery() { instance = this; - //nrf_gpio_cfg_input(PinMap::Charging, static_cast GPIO_PIN_CNF_PULL_Disabled); + // nrf_gpio_cfg_input(PinMap::Charging, static_cast GPIO_PIN_CNF_PULL_Disabled); } void Battery::ReadPowerState() { @@ -29,66 +29,66 @@ void Battery::MeasureVoltage() { } // Non blocking read isReading = true; - //SaadcInit(); + // SaadcInit(); - //nrfx_saadc_sample(); + // nrfx_saadc_sample(); } -//void Battery::AdcCallbackStatic(nrfx_saadc_evt_t const* event) { -// instance->SaadcEventHandler(event); -//} +// void Battery::AdcCallbackStatic(nrfx_saadc_evt_t const* event) { +// instance->SaadcEventHandler(event); +// } -//void Battery::SaadcInit() { -// nrfx_saadc_config_t adcConfig = NRFX_SAADC_DEFAULT_CONFIG; -// APP_ERROR_CHECK(nrfx_saadc_init(&adcConfig, AdcCallbackStatic)); +// void Battery::SaadcInit() { +// nrfx_saadc_config_t adcConfig = NRFX_SAADC_DEFAULT_CONFIG; +// APP_ERROR_CHECK(nrfx_saadc_init(&adcConfig, AdcCallbackStatic)); // -// nrf_saadc_channel_config_t adcChannelConfig = {.resistor_p = NRF_SAADC_RESISTOR_DISABLED, -// .resistor_n = NRF_SAADC_RESISTOR_DISABLED, -// .gain = NRF_SAADC_GAIN1_4, -// .reference = NRF_SAADC_REFERENCE_INTERNAL, -// .acq_time = NRF_SAADC_ACQTIME_40US, -// .mode = NRF_SAADC_MODE_SINGLE_ENDED, -// .burst = NRF_SAADC_BURST_ENABLED, -// .pin_p = batteryVoltageAdcInput, -// .pin_n = NRF_SAADC_INPUT_DISABLED}; -// APP_ERROR_CHECK(nrfx_saadc_channel_init(0, &adcChannelConfig)); -// APP_ERROR_CHECK(nrfx_saadc_buffer_convert(&saadc_value, 1)); -//} +// nrf_saadc_channel_config_t adcChannelConfig = {.resistor_p = NRF_SAADC_RESISTOR_DISABLED, +// .resistor_n = NRF_SAADC_RESISTOR_DISABLED, +// .gain = NRF_SAADC_GAIN1_4, +// .reference = NRF_SAADC_REFERENCE_INTERNAL, +// .acq_time = NRF_SAADC_ACQTIME_40US, +// .mode = NRF_SAADC_MODE_SINGLE_ENDED, +// .burst = NRF_SAADC_BURST_ENABLED, +// .pin_p = batteryVoltageAdcInput, +// .pin_n = NRF_SAADC_INPUT_DISABLED}; +// APP_ERROR_CHECK(nrfx_saadc_channel_init(0, &adcChannelConfig)); +// APP_ERROR_CHECK(nrfx_saadc_buffer_convert(&saadc_value, 1)); +// } // -//void Battery::SaadcEventHandler(nrfx_saadc_evt_t const* p_event) { -// const uint16_t battery_max = 4180; // maximum voltage of battery ( max charging voltage is 4.21 ) -// const uint16_t battery_min = 3200; // minimum voltage of battery before shutdown ( depends on the battery ) +// void Battery::SaadcEventHandler(nrfx_saadc_evt_t const* p_event) { +// const uint16_t battery_max = 4180; // maximum voltage of battery ( max charging voltage is 4.21 ) +// const uint16_t battery_min = 3200; // minimum voltage of battery before shutdown ( depends on the battery ) // -// if (p_event->type == NRFX_SAADC_EVT_DONE) { +// if (p_event->type == NRFX_SAADC_EVT_DONE) { // -// APP_ERROR_CHECK(nrfx_saadc_buffer_convert(&saadc_value, 1)); +// APP_ERROR_CHECK(nrfx_saadc_buffer_convert(&saadc_value, 1)); // -// // A hardware voltage divider divides the battery voltage by 2 -// // ADC gain is 1/4 -// // thus adc_voltage = battery_voltage / 2 * gain = battery_voltage / 8 -// // reference_voltage is 600mV -// // p_event->data.done.p_buffer[0] = (adc_voltage / reference_voltage) * 1024 -// voltage = p_event->data.done.p_buffer[0] * (8 * 600) / 1024; +// // A hardware voltage divider divides the battery voltage by 2 +// // ADC gain is 1/4 +// // thus adc_voltage = battery_voltage / 2 * gain = battery_voltage / 8 +// // reference_voltage is 600mV +// // p_event->data.done.p_buffer[0] = (adc_voltage / reference_voltage) * 1024 +// voltage = p_event->data.done.p_buffer[0] * (8 * 600) / 1024; // -// uint8_t newPercent; -// if (isFull) { -// newPercent = 100; -// } else if (voltage < battery_min) { -// newPercent = 0; -// } else { -// newPercent = std::min((voltage - battery_min) * 100 / (battery_max - battery_min), isCharging ? 99 : 100); -// } +// uint8_t newPercent; +// if (isFull) { +// newPercent = 100; +// } else if (voltage < battery_min) { +// newPercent = 0; +// } else { +// newPercent = std::min((voltage - battery_min) * 100 / (battery_max - battery_min), isCharging ? 99 : 100); +// } // -// if ((isPowerPresent && newPercent > percentRemaining) || (!isPowerPresent && newPercent < percentRemaining) || firstMeasurement) { -// firstMeasurement = false; -// percentRemaining = newPercent; -// systemTask->PushMessage(System::Messages::BatteryPercentageUpdated); -// } +// if ((isPowerPresent && newPercent > percentRemaining) || (!isPowerPresent && newPercent < percentRemaining) || firstMeasurement) { +// firstMeasurement = false; +// percentRemaining = newPercent; +// systemTask->PushMessage(System::Messages::BatteryPercentageUpdated); +// } // -// nrfx_saadc_uninit(); -// isReading = false; -// } -//} +// nrfx_saadc_uninit(); +// isReading = false; +// } +// } void Battery::Register(Pinetime::System::SystemTask* systemTask) { this->systemTask = systemTask; diff --git a/sim/components/battery/BatteryController.h b/sim/components/battery/BatteryController.h index 61d10f3..a02101a 100644 --- a/sim/components/battery/BatteryController.h +++ b/sim/components/battery/BatteryController.h @@ -38,7 +38,7 @@ namespace Pinetime { private: static Battery* instance; - //static constexpr nrf_saadc_input_t batteryVoltageAdcInput = NRF_SAADC_INPUT_AIN7; + // static constexpr nrf_saadc_input_t batteryVoltageAdcInput = NRF_SAADC_INPUT_AIN7; public: uint16_t voltage = 0; uint8_t percentRemaining = 0; @@ -48,10 +48,10 @@ namespace Pinetime { bool isPowerPresent = false; bool firstMeasurement = true; - //void SaadcInit(); + // void SaadcInit(); - //void SaadcEventHandler(nrfx_saadc_evt_t const* p_event); - //static void AdcCallbackStatic(nrfx_saadc_evt_t const* event); + // void SaadcEventHandler(nrfx_saadc_evt_t const* p_event); + // static void AdcCallbackStatic(nrfx_saadc_evt_t const* event); static constexpr uint8_t lowBatteryThreshold {20}; diff --git a/sim/components/ble/NimbleController.cpp b/sim/components/ble/NimbleController.cpp index 9c29f86..57977f8 100644 --- a/sim/components/ble/NimbleController.cpp +++ b/sim/components/ble/NimbleController.cpp @@ -1,19 +1,19 @@ #include "components/ble/NimbleController.h" #include -//#include -//#define min // workaround: nimble's min/max macros conflict with libstdc++ -//#define max -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#undef max -//#undef min +// #include +// #define min // workaround: nimble's min/max macros conflict with libstdc++ +// #define max +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #undef max +// #undef min #include "components/ble/BleController.h" #include "components/ble/NotificationManager.h" #include "components/datetime/DateTimeController.h" @@ -37,332 +37,332 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask, notificationManager {notificationManager}, spiNorFlash {spiNorFlash}, fs {fs}, -// dfuService {systemTask, bleController, spiNorFlash}, + // dfuService {systemTask, bleController, spiNorFlash}, -// currentTimeClient {dateTimeController}, + // currentTimeClient {dateTimeController}, anService {systemTask, notificationManager}, -// alertNotificationClient {systemTask, notificationManager}, -// currentTimeService {dateTimeController}, + // alertNotificationClient {systemTask, notificationManager}, + // currentTimeService {dateTimeController}, musicService {*this}, weatherService {dateTimeController}, -// batteryInformationService {batteryController}, -// immediateAlertService {systemTask, notificationManager}, -// heartRateService {systemTask, heartRateController}, + // batteryInformationService {batteryController}, + // immediateAlertService {systemTask, notificationManager}, + // heartRateService {systemTask, heartRateController}, motionService {*this, motionController} { -// fsService {systemTask, fs}, -// serviceDiscovery({¤tTimeClient, &alertNotificationClient}) { + // fsService {systemTask, fs}, + // serviceDiscovery({¤tTimeClient, &alertNotificationClient}) { } -//void nimble_on_reset(int reason) { -// NRF_LOG_INFO("Nimble lost sync, resetting state; reason=%d", reason); -//} +// void nimble_on_reset(int reason) { +// NRF_LOG_INFO("Nimble lost sync, resetting state; reason=%d", reason); +// } // -//void nimble_on_sync(void) { -// int rc; +// void nimble_on_sync(void) { +// int rc; // -// NRF_LOG_INFO("Nimble is synced"); +// NRF_LOG_INFO("Nimble is synced"); // -// rc = ble_hs_util_ensure_addr(0); -// ASSERT(rc == 0); +// rc = ble_hs_util_ensure_addr(0); +// ASSERT(rc == 0); // -// nptr->StartAdvertising(); -//} +// nptr->StartAdvertising(); +// } // -//int GAPEventCallback(struct ble_gap_event* event, void* arg) { -// auto nimbleController = static_cast(arg); -// return nimbleController->OnGAPEvent(event); -//} +// int GAPEventCallback(struct ble_gap_event* event, void* arg) { +// auto nimbleController = static_cast(arg); +// return nimbleController->OnGAPEvent(event); +// } void NimbleController::Init() { -// while (!ble_hs_synced()) { -// } -// -// nptr = this; -// ble_hs_cfg.reset_cb = nimble_on_reset; -// ble_hs_cfg.sync_cb = nimble_on_sync; -// ble_hs_cfg.store_status_cb = ble_store_util_status_rr; -// -// ble_svc_gap_init(); -// ble_svc_gatt_init(); -// -// deviceInformationService.Init(); -// currentTimeClient.Init(); -// currentTimeService.Init(); + // while (!ble_hs_synced()) { + // } + // + // nptr = this; + // ble_hs_cfg.reset_cb = nimble_on_reset; + // ble_hs_cfg.sync_cb = nimble_on_sync; + // ble_hs_cfg.store_status_cb = ble_store_util_status_rr; + // + // ble_svc_gap_init(); + // ble_svc_gatt_init(); + // + // deviceInformationService.Init(); + // currentTimeClient.Init(); + // currentTimeService.Init(); musicService.Init(); weatherService.Init(); navService.Init(); -// anService.Init(); -// dfuService.Init(); -// batteryInformationService.Init(); -// immediateAlertService.Init(); -// heartRateService.Init(); -// motionService.Init(); -// fsService.Init(); -// -// int rc; -// rc = ble_hs_util_ensure_addr(0); -// ASSERT(rc == 0); -// rc = ble_hs_id_infer_auto(0, &addrType); -// ASSERT(rc == 0); -// rc = ble_svc_gap_device_name_set(deviceName); -// ASSERT(rc == 0); -// rc = ble_svc_gap_device_appearance_set(0xC2); -// ASSERT(rc == 0); -// Pinetime::Controllers::Ble::BleAddress address; -// rc = ble_hs_id_copy_addr(addrType, address.data(), nullptr); -// ASSERT(rc == 0); -// -// bleController.Address(std::move(address)); -// switch (addrType) { -// case BLE_OWN_ADDR_PUBLIC: -// bleController.AddressType(Ble::AddressTypes::Public); -// break; -// case BLE_OWN_ADDR_RANDOM: -// bleController.AddressType(Ble::AddressTypes::Random); -// break; -// case BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT: -// bleController.AddressType(Ble::AddressTypes::RPA_Public); -// break; -// case BLE_OWN_ADDR_RPA_RANDOM_DEFAULT: -// bleController.AddressType(Ble::AddressTypes::RPA_Random); -// break; -// } -// -// rc = ble_gatts_start(); -// ASSERT(rc == 0); -// -// RestoreBond(); -// -// StartAdvertising(); + // anService.Init(); + // dfuService.Init(); + // batteryInformationService.Init(); + // immediateAlertService.Init(); + // heartRateService.Init(); + // motionService.Init(); + // fsService.Init(); + // + // int rc; + // rc = ble_hs_util_ensure_addr(0); + // ASSERT(rc == 0); + // rc = ble_hs_id_infer_auto(0, &addrType); + // ASSERT(rc == 0); + // rc = ble_svc_gap_device_name_set(deviceName); + // ASSERT(rc == 0); + // rc = ble_svc_gap_device_appearance_set(0xC2); + // ASSERT(rc == 0); + // Pinetime::Controllers::Ble::BleAddress address; + // rc = ble_hs_id_copy_addr(addrType, address.data(), nullptr); + // ASSERT(rc == 0); + // + // bleController.Address(std::move(address)); + // switch (addrType) { + // case BLE_OWN_ADDR_PUBLIC: + // bleController.AddressType(Ble::AddressTypes::Public); + // break; + // case BLE_OWN_ADDR_RANDOM: + // bleController.AddressType(Ble::AddressTypes::Random); + // break; + // case BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT: + // bleController.AddressType(Ble::AddressTypes::RPA_Public); + // break; + // case BLE_OWN_ADDR_RPA_RANDOM_DEFAULT: + // bleController.AddressType(Ble::AddressTypes::RPA_Random); + // break; + // } + // + // rc = ble_gatts_start(); + // ASSERT(rc == 0); + // + // RestoreBond(); + // + // StartAdvertising(); } -//void NimbleController::StartAdvertising() { -// struct ble_gap_adv_params adv_params; -// struct ble_hs_adv_fields fields; -// struct ble_hs_adv_fields rsp_fields; -// -// memset(&adv_params, 0, sizeof(adv_params)); -// memset(&fields, 0, sizeof(fields)); -// memset(&rsp_fields, 0, sizeof(rsp_fields)); -// -// adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; -// adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; -// /* fast advertise for 30 sec */ -// if (fastAdvCount < 15) { -// adv_params.itvl_min = 32; -// adv_params.itvl_max = 47; -// fastAdvCount++; -// } else { -// adv_params.itvl_min = 1636; -// adv_params.itvl_max = 1651; -// } -// -// fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP; -// fields.uuids128 = &dfuServiceUuid; -// fields.num_uuids128 = 1; -// fields.uuids128_is_complete = 1; -// fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; -// -// rsp_fields.name = reinterpret_cast(deviceName); -// rsp_fields.name_len = strlen(deviceName); -// rsp_fields.name_is_complete = 1; -// -// int rc; -// rc = ble_gap_adv_set_fields(&fields); -// ASSERT(rc == 0); -// -// rc = ble_gap_adv_rsp_set_fields(&rsp_fields); -// ASSERT(rc == 0); -// -// rc = ble_gap_adv_start(addrType, NULL, 2000, &adv_params, GAPEventCallback, this); -// ASSERT(rc == 0); -//} -// -//int NimbleController::OnGAPEvent(ble_gap_event* event) { -// switch (event->type) { -// case BLE_GAP_EVENT_ADV_COMPLETE: -// NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_ADV_COMPLETE"); -// NRF_LOG_INFO("reason=%d; status=%0X", event->adv_complete.reason, event->connect.status); -// StartAdvertising(); -// break; -// -// case BLE_GAP_EVENT_CONNECT: -// /* A new connection was established or a connection attempt failed. */ -// NRF_LOG_INFO("Connect event : BLE_GAP_EVENT_CONNECT"); -// NRF_LOG_INFO("connection %s; status=%0X ", event->connect.status == 0 ? "established" : "failed", event->connect.status); -// -// if (event->connect.status != 0) { -// /* Connection failed; resume advertising. */ -// currentTimeClient.Reset(); -// alertNotificationClient.Reset(); -// connectionHandle = BLE_HS_CONN_HANDLE_NONE; -// bleController.Disconnect(); -// fastAdvCount = 0; -// StartAdvertising(); -// } else { -// connectionHandle = event->connect.conn_handle; -// bleController.Connect(); -// systemTask.PushMessage(Pinetime::System::Messages::BleConnected); -// // Service discovery is deferred via systemtask -// } -// break; -// -// case BLE_GAP_EVENT_DISCONNECT: -// /* Connection terminated; resume advertising. */ -// NRF_LOG_INFO("Disconnect event : BLE_GAP_EVENT_DISCONNECT"); -// NRF_LOG_INFO("disconnect reason=%d", event->disconnect.reason); -// -// if (event->disconnect.conn.sec_state.bonded) { -// PersistBond(event->disconnect.conn); -// } -// -// currentTimeClient.Reset(); -// alertNotificationClient.Reset(); -// connectionHandle = BLE_HS_CONN_HANDLE_NONE; -// bleController.Disconnect(); -// fastAdvCount = 0; -// StartAdvertising(); -// break; -// -// case BLE_GAP_EVENT_CONN_UPDATE: -// /* The central has updated the connection parameters. */ -// NRF_LOG_INFO("Update event : BLE_GAP_EVENT_CONN_UPDATE"); -// NRF_LOG_INFO("update status=%0X ", event->conn_update.status); -// break; -// -// case BLE_GAP_EVENT_CONN_UPDATE_REQ: -// /* The central has requested updated connection parameters */ -// NRF_LOG_INFO("Update event : BLE_GAP_EVENT_CONN_UPDATE_REQ"); -// NRF_LOG_INFO("update request : itvl_min=%d itvl_max=%d latency=%d supervision=%d", -// event->conn_update_req.peer_params->itvl_min, -// event->conn_update_req.peer_params->itvl_max, -// event->conn_update_req.peer_params->latency, -// event->conn_update_req.peer_params->supervision_timeout); -// break; -// -// case BLE_GAP_EVENT_ENC_CHANGE: -// /* Encryption has been enabled or disabled for this connection. */ -// NRF_LOG_INFO("Security event : BLE_GAP_EVENT_ENC_CHANGE"); -// NRF_LOG_INFO("encryption change event; status=%0X ", event->enc_change.status); -// -// if (event->enc_change.status == 0) { -// struct ble_gap_conn_desc desc; -// ble_gap_conn_find(event->enc_change.conn_handle, &desc); -// if (desc.sec_state.bonded) { -// PersistBond(desc); -// } -// -// NRF_LOG_INFO("new state: encrypted=%d authenticated=%d bonded=%d key_size=%d", -// desc.sec_state.encrypted, -// desc.sec_state.authenticated, -// desc.sec_state.bonded, -// desc.sec_state.key_size); -// } -// break; -// -// case BLE_GAP_EVENT_PASSKEY_ACTION: -// /* Authentication has been requested for this connection. -// * -// * BLE authentication is determined by the combination of I/O capabilities -// * on the central and peripheral. When the peripheral is display only and -// * the central has a keyboard and display then passkey auth is selected. -// * When both the central and peripheral have displays and support yes/no -// * buttons then numeric comparison is selected. We currently advertise -// * display capability only so we only handle the "display" action here. -// * -// * Standards insist that the rand() PRNG be deterministic. -// * Use the tinycrypt prng here since rand() is predictable. -// */ -// NRF_LOG_INFO("Security event : BLE_GAP_EVENT_PASSKEY_ACTION"); -// if (event->passkey.params.action == BLE_SM_IOACT_DISP) { -// struct ble_sm_io pkey = {0}; -// pkey.action = event->passkey.params.action; -// pkey.passkey = ble_ll_rand() % 1000000; -// bleController.SetPairingKey(pkey.passkey); -// systemTask.PushMessage(Pinetime::System::Messages::OnPairing); -// ble_sm_inject_io(event->passkey.conn_handle, &pkey); -// } -// break; -// -// case BLE_GAP_EVENT_SUBSCRIBE: -// NRF_LOG_INFO("Subscribe event; conn_handle=%d attr_handle=%d " -// "reason=%d prevn=%d curn=%d previ=%d curi=???\n", -// event->subscribe.conn_handle, -// event->subscribe.attr_handle, -// event->subscribe.reason, -// event->subscribe.prev_notify, -// event->subscribe.cur_notify, -// event->subscribe.prev_indicate); -// -// if (event->subscribe.reason == BLE_GAP_SUBSCRIBE_REASON_TERM) { -// heartRateService.UnsubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); -// motionService.UnsubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); -// } else if (event->subscribe.prev_notify == 0 && event->subscribe.cur_notify == 1) { -// heartRateService.SubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); -// motionService.SubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); -// } else if (event->subscribe.prev_notify == 1 && event->subscribe.cur_notify == 0) { -// heartRateService.UnsubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); -// motionService.UnsubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); -// } -// break; -// -// case BLE_GAP_EVENT_MTU: -// NRF_LOG_INFO("MTU Update event; conn_handle=%d cid=%d mtu=%d", event->mtu.conn_handle, event->mtu.channel_id, event->mtu.value); -// break; -// -// case BLE_GAP_EVENT_REPEAT_PAIRING: { -// NRF_LOG_INFO("Pairing event : BLE_GAP_EVENT_REPEAT_PAIRING"); -// /* We already have a bond with the peer, but it is attempting to -// * establish a new secure link. This app sacrifices security for -// * convenience: just throw away the old bond and accept the new link. -// */ -// -// /* Delete the old bond. */ -// struct ble_gap_conn_desc desc; -// ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc); -// ble_store_util_delete_peer(&desc.peer_id_addr); -// -// /* Return BLE_GAP_REPEAT_PAIRING_RETRY to indicate that the host should -// * continue with the pairing operation. -// */ -// } -// return BLE_GAP_REPEAT_PAIRING_RETRY; -// -// case BLE_GAP_EVENT_NOTIFY_RX: { -// /* Peer sent us a notification or indication. */ -// /* Attribute data is contained in event->notify_rx.attr_data. */ -// NRF_LOG_INFO("Notify event : BLE_GAP_EVENT_NOTIFY_RX"); -// size_t notifSize = OS_MBUF_PKTLEN(event->notify_rx.om); -// -// NRF_LOG_INFO("received %s; conn_handle=%d attr_handle=%d " -// "attr_len=%d", -// event->notify_rx.indication ? "indication" : "notification", -// event->notify_rx.conn_handle, -// event->notify_rx.attr_handle, -// notifSize); -// -// alertNotificationClient.OnNotification(event); -// } break; -// -// case BLE_GAP_EVENT_NOTIFY_TX: -// NRF_LOG_INFO("Notify event : BLE_GAP_EVENT_NOTIFY_TX"); -// break; -// -// case BLE_GAP_EVENT_IDENTITY_RESOLVED: -// NRF_LOG_INFO("Identity event : BLE_GAP_EVENT_IDENTITY_RESOLVED"); -// break; -// -// default: -// NRF_LOG_INFO("UNHANDLED GAP event : %d", event->type); -// break; -// } -// return 0; -//} +// void NimbleController::StartAdvertising() { +// struct ble_gap_adv_params adv_params; +// struct ble_hs_adv_fields fields; +// struct ble_hs_adv_fields rsp_fields; +// +// memset(&adv_params, 0, sizeof(adv_params)); +// memset(&fields, 0, sizeof(fields)); +// memset(&rsp_fields, 0, sizeof(rsp_fields)); +// +// adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; +// adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; +// /* fast advertise for 30 sec */ +// if (fastAdvCount < 15) { +// adv_params.itvl_min = 32; +// adv_params.itvl_max = 47; +// fastAdvCount++; +// } else { +// adv_params.itvl_min = 1636; +// adv_params.itvl_max = 1651; +// } +// +// fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP; +// fields.uuids128 = &dfuServiceUuid; +// fields.num_uuids128 = 1; +// fields.uuids128_is_complete = 1; +// fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; +// +// rsp_fields.name = reinterpret_cast(deviceName); +// rsp_fields.name_len = strlen(deviceName); +// rsp_fields.name_is_complete = 1; +// +// int rc; +// rc = ble_gap_adv_set_fields(&fields); +// ASSERT(rc == 0); +// +// rc = ble_gap_adv_rsp_set_fields(&rsp_fields); +// ASSERT(rc == 0); +// +// rc = ble_gap_adv_start(addrType, NULL, 2000, &adv_params, GAPEventCallback, this); +// ASSERT(rc == 0); +// } +// +// int NimbleController::OnGAPEvent(ble_gap_event* event) { +// switch (event->type) { +// case BLE_GAP_EVENT_ADV_COMPLETE: +// NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_ADV_COMPLETE"); +// NRF_LOG_INFO("reason=%d; status=%0X", event->adv_complete.reason, event->connect.status); +// StartAdvertising(); +// break; +// +// case BLE_GAP_EVENT_CONNECT: +// /* A new connection was established or a connection attempt failed. */ +// NRF_LOG_INFO("Connect event : BLE_GAP_EVENT_CONNECT"); +// NRF_LOG_INFO("connection %s; status=%0X ", event->connect.status == 0 ? "established" : "failed", event->connect.status); +// +// if (event->connect.status != 0) { +// /* Connection failed; resume advertising. */ +// currentTimeClient.Reset(); +// alertNotificationClient.Reset(); +// connectionHandle = BLE_HS_CONN_HANDLE_NONE; +// bleController.Disconnect(); +// fastAdvCount = 0; +// StartAdvertising(); +// } else { +// connectionHandle = event->connect.conn_handle; +// bleController.Connect(); +// systemTask.PushMessage(Pinetime::System::Messages::BleConnected); +// // Service discovery is deferred via systemtask +// } +// break; +// +// case BLE_GAP_EVENT_DISCONNECT: +// /* Connection terminated; resume advertising. */ +// NRF_LOG_INFO("Disconnect event : BLE_GAP_EVENT_DISCONNECT"); +// NRF_LOG_INFO("disconnect reason=%d", event->disconnect.reason); +// +// if (event->disconnect.conn.sec_state.bonded) { +// PersistBond(event->disconnect.conn); +// } +// +// currentTimeClient.Reset(); +// alertNotificationClient.Reset(); +// connectionHandle = BLE_HS_CONN_HANDLE_NONE; +// bleController.Disconnect(); +// fastAdvCount = 0; +// StartAdvertising(); +// break; +// +// case BLE_GAP_EVENT_CONN_UPDATE: +// /* The central has updated the connection parameters. */ +// NRF_LOG_INFO("Update event : BLE_GAP_EVENT_CONN_UPDATE"); +// NRF_LOG_INFO("update status=%0X ", event->conn_update.status); +// break; +// +// case BLE_GAP_EVENT_CONN_UPDATE_REQ: +// /* The central has requested updated connection parameters */ +// NRF_LOG_INFO("Update event : BLE_GAP_EVENT_CONN_UPDATE_REQ"); +// NRF_LOG_INFO("update request : itvl_min=%d itvl_max=%d latency=%d supervision=%d", +// event->conn_update_req.peer_params->itvl_min, +// event->conn_update_req.peer_params->itvl_max, +// event->conn_update_req.peer_params->latency, +// event->conn_update_req.peer_params->supervision_timeout); +// break; +// +// case BLE_GAP_EVENT_ENC_CHANGE: +// /* Encryption has been enabled or disabled for this connection. */ +// NRF_LOG_INFO("Security event : BLE_GAP_EVENT_ENC_CHANGE"); +// NRF_LOG_INFO("encryption change event; status=%0X ", event->enc_change.status); +// +// if (event->enc_change.status == 0) { +// struct ble_gap_conn_desc desc; +// ble_gap_conn_find(event->enc_change.conn_handle, &desc); +// if (desc.sec_state.bonded) { +// PersistBond(desc); +// } +// +// NRF_LOG_INFO("new state: encrypted=%d authenticated=%d bonded=%d key_size=%d", +// desc.sec_state.encrypted, +// desc.sec_state.authenticated, +// desc.sec_state.bonded, +// desc.sec_state.key_size); +// } +// break; +// +// case BLE_GAP_EVENT_PASSKEY_ACTION: +// /* Authentication has been requested for this connection. +// * +// * BLE authentication is determined by the combination of I/O capabilities +// * on the central and peripheral. When the peripheral is display only and +// * the central has a keyboard and display then passkey auth is selected. +// * When both the central and peripheral have displays and support yes/no +// * buttons then numeric comparison is selected. We currently advertise +// * display capability only so we only handle the "display" action here. +// * +// * Standards insist that the rand() PRNG be deterministic. +// * Use the tinycrypt prng here since rand() is predictable. +// */ +// NRF_LOG_INFO("Security event : BLE_GAP_EVENT_PASSKEY_ACTION"); +// if (event->passkey.params.action == BLE_SM_IOACT_DISP) { +// struct ble_sm_io pkey = {0}; +// pkey.action = event->passkey.params.action; +// pkey.passkey = ble_ll_rand() % 1000000; +// bleController.SetPairingKey(pkey.passkey); +// systemTask.PushMessage(Pinetime::System::Messages::OnPairing); +// ble_sm_inject_io(event->passkey.conn_handle, &pkey); +// } +// break; +// +// case BLE_GAP_EVENT_SUBSCRIBE: +// NRF_LOG_INFO("Subscribe event; conn_handle=%d attr_handle=%d " +// "reason=%d prevn=%d curn=%d previ=%d curi=???\n", +// event->subscribe.conn_handle, +// event->subscribe.attr_handle, +// event->subscribe.reason, +// event->subscribe.prev_notify, +// event->subscribe.cur_notify, +// event->subscribe.prev_indicate); +// +// if (event->subscribe.reason == BLE_GAP_SUBSCRIBE_REASON_TERM) { +// heartRateService.UnsubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); +// motionService.UnsubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); +// } else if (event->subscribe.prev_notify == 0 && event->subscribe.cur_notify == 1) { +// heartRateService.SubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); +// motionService.SubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); +// } else if (event->subscribe.prev_notify == 1 && event->subscribe.cur_notify == 0) { +// heartRateService.UnsubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); +// motionService.UnsubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); +// } +// break; +// +// case BLE_GAP_EVENT_MTU: +// NRF_LOG_INFO("MTU Update event; conn_handle=%d cid=%d mtu=%d", event->mtu.conn_handle, event->mtu.channel_id, event->mtu.value); +// break; +// +// case BLE_GAP_EVENT_REPEAT_PAIRING: { +// NRF_LOG_INFO("Pairing event : BLE_GAP_EVENT_REPEAT_PAIRING"); +// /* We already have a bond with the peer, but it is attempting to +// * establish a new secure link. This app sacrifices security for +// * convenience: just throw away the old bond and accept the new link. +// */ +// +// /* Delete the old bond. */ +// struct ble_gap_conn_desc desc; +// ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc); +// ble_store_util_delete_peer(&desc.peer_id_addr); +// +// /* Return BLE_GAP_REPEAT_PAIRING_RETRY to indicate that the host should +// * continue with the pairing operation. +// */ +// } +// return BLE_GAP_REPEAT_PAIRING_RETRY; +// +// case BLE_GAP_EVENT_NOTIFY_RX: { +// /* Peer sent us a notification or indication. */ +// /* Attribute data is contained in event->notify_rx.attr_data. */ +// NRF_LOG_INFO("Notify event : BLE_GAP_EVENT_NOTIFY_RX"); +// size_t notifSize = OS_MBUF_PKTLEN(event->notify_rx.om); +// +// NRF_LOG_INFO("received %s; conn_handle=%d attr_handle=%d " +// "attr_len=%d", +// event->notify_rx.indication ? "indication" : "notification", +// event->notify_rx.conn_handle, +// event->notify_rx.attr_handle, +// notifSize); +// +// alertNotificationClient.OnNotification(event); +// } break; +// +// case BLE_GAP_EVENT_NOTIFY_TX: +// NRF_LOG_INFO("Notify event : BLE_GAP_EVENT_NOTIFY_TX"); +// break; +// +// case BLE_GAP_EVENT_IDENTITY_RESOLVED: +// NRF_LOG_INFO("Identity event : BLE_GAP_EVENT_IDENTITY_RESOLVED"); +// break; +// +// default: +// NRF_LOG_INFO("UNHANDLED GAP event : %d", event->type); +// break; +// } +// return 0; +// } void NimbleController::StartDiscovery() { -// if (connectionHandle != BLE_HS_CONN_HANDLE_NONE) { -// serviceDiscovery.StartDiscovery(connectionHandle); -// } + // if (connectionHandle != BLE_HS_CONN_HANDLE_NONE) { + // serviceDiscovery.StartDiscovery(connectionHandle); + // } } uint16_t NimbleController::connHandle() { @@ -370,103 +370,103 @@ uint16_t NimbleController::connHandle() { } void NimbleController::NotifyBatteryLevel(uint8_t level) { -// if (connectionHandle != BLE_HS_CONN_HANDLE_NONE) { -// batteryInformationService.NotifyBatteryLevel(connectionHandle, level); -// } + // if (connectionHandle != BLE_HS_CONN_HANDLE_NONE) { + // batteryInformationService.NotifyBatteryLevel(connectionHandle, level); + // } } void NimbleController::EnableRadio() { -// bleController.EnableRadio(); -// bleController.Disconnect(); -// fastAdvCount = 0; -// StartAdvertising(); + // bleController.EnableRadio(); + // bleController.Disconnect(); + // fastAdvCount = 0; + // StartAdvertising(); } void NimbleController::DisableRadio() { -// bleController.DisableRadio(); -// if (bleController.IsConnected()) { -// ble_gap_terminate(connectionHandle, BLE_ERR_REM_USER_CONN_TERM); -// bleController.Disconnect(); -// } else { -// ble_gap_adv_stop(); -// } + // bleController.DisableRadio(); + // if (bleController.IsConnected()) { + // ble_gap_terminate(connectionHandle, BLE_ERR_REM_USER_CONN_TERM); + // bleController.Disconnect(); + // } else { + // ble_gap_adv_stop(); + // } } -//void NimbleController::PersistBond(struct ble_gap_conn_desc& desc) { -// union ble_store_key key; -// union ble_store_value our_sec, peer_sec, peer_cccd_set[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)] = {0}; -// int rc; -// -// memset(&key, 0, sizeof key); -// memset(&our_sec, 0, sizeof our_sec); -// key.sec.peer_addr = desc.peer_id_addr; -// rc = ble_store_read_our_sec(&key.sec, &our_sec.sec); -// -// if (memcmp(&our_sec.sec, &bondId, sizeof bondId) == 0) { -// return; -// } -// -// memcpy(&bondId, &our_sec.sec, sizeof bondId); -// -// memset(&key, 0, sizeof key); -// memset(&peer_sec, 0, sizeof peer_sec); -// key.sec.peer_addr = desc.peer_id_addr; -// rc += ble_store_read_peer_sec(&key.sec, &peer_sec.sec); -// -// if (rc == 0) { -// memset(&key, 0, sizeof key); -// key.cccd.peer_addr = desc.peer_id_addr; -// int peer_count = 0; -// ble_store_util_count(BLE_STORE_OBJ_TYPE_CCCD, &peer_count); -// for (int i = 0; i < peer_count; i++) { -// key.cccd.idx = peer_count; -// ble_store_read_cccd(&key.cccd, &peer_cccd_set[i].cccd); -// } -// -// /* Wakeup Spi and SpiNorFlash before accessing the file system -// * This should be fixed in the FS driver -// */ -// systemTask.PushMessage(Pinetime::System::Messages::GoToRunning); -// systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping); -// vTaskDelay(10); -// -// lfs_file_t file_p; -// -// rc = fs.FileOpen(&file_p, "/bond.dat", LFS_O_WRONLY | LFS_O_CREAT); -// if (rc == 0) { -// fs.FileWrite(&file_p, reinterpret_cast(&our_sec.sec), sizeof our_sec); -// fs.FileWrite(&file_p, reinterpret_cast(&peer_sec.sec), sizeof peer_sec); -// fs.FileWrite(&file_p, reinterpret_cast(&peer_count), 1); -// for (int i = 0; i < peer_count; i++) { -// fs.FileWrite(&file_p, reinterpret_cast(&peer_cccd_set[i].cccd), sizeof(struct ble_store_value_cccd)); -// } -// fs.FileClose(&file_p); -// } -// systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping); -// } -//} +// void NimbleController::PersistBond(struct ble_gap_conn_desc& desc) { +// union ble_store_key key; +// union ble_store_value our_sec, peer_sec, peer_cccd_set[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)] = {0}; +// int rc; +// +// memset(&key, 0, sizeof key); +// memset(&our_sec, 0, sizeof our_sec); +// key.sec.peer_addr = desc.peer_id_addr; +// rc = ble_store_read_our_sec(&key.sec, &our_sec.sec); +// +// if (memcmp(&our_sec.sec, &bondId, sizeof bondId) == 0) { +// return; +// } +// +// memcpy(&bondId, &our_sec.sec, sizeof bondId); +// +// memset(&key, 0, sizeof key); +// memset(&peer_sec, 0, sizeof peer_sec); +// key.sec.peer_addr = desc.peer_id_addr; +// rc += ble_store_read_peer_sec(&key.sec, &peer_sec.sec); +// +// if (rc == 0) { +// memset(&key, 0, sizeof key); +// key.cccd.peer_addr = desc.peer_id_addr; +// int peer_count = 0; +// ble_store_util_count(BLE_STORE_OBJ_TYPE_CCCD, &peer_count); +// for (int i = 0; i < peer_count; i++) { +// key.cccd.idx = peer_count; +// ble_store_read_cccd(&key.cccd, &peer_cccd_set[i].cccd); +// } +// +// /* Wakeup Spi and SpiNorFlash before accessing the file system +// * This should be fixed in the FS driver +// */ +// systemTask.PushMessage(Pinetime::System::Messages::GoToRunning); +// systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping); +// vTaskDelay(10); +// +// lfs_file_t file_p; +// +// rc = fs.FileOpen(&file_p, "/bond.dat", LFS_O_WRONLY | LFS_O_CREAT); +// if (rc == 0) { +// fs.FileWrite(&file_p, reinterpret_cast(&our_sec.sec), sizeof our_sec); +// fs.FileWrite(&file_p, reinterpret_cast(&peer_sec.sec), sizeof peer_sec); +// fs.FileWrite(&file_p, reinterpret_cast(&peer_count), 1); +// for (int i = 0; i < peer_count; i++) { +// fs.FileWrite(&file_p, reinterpret_cast(&peer_cccd_set[i].cccd), sizeof(struct ble_store_value_cccd)); +// } +// fs.FileClose(&file_p); +// } +// systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping); +// } +// } -//void NimbleController::RestoreBond() { -// lfs_file_t file_p; -// union ble_store_value sec, cccd; -// uint8_t peer_count = 0; -// -// if (fs.FileOpen(&file_p, "/bond.dat", LFS_O_RDONLY) == 0) { -// memset(&sec, 0, sizeof sec); -// fs.FileRead(&file_p, reinterpret_cast(&sec.sec), sizeof sec); -// ble_store_write_our_sec(&sec.sec); -// -// memset(&sec, 0, sizeof sec); -// fs.FileRead(&file_p, reinterpret_cast(&sec.sec), sizeof sec); -// ble_store_write_peer_sec(&sec.sec); -// -// fs.FileRead(&file_p, &peer_count, 1); -// for (int i = 0; i < peer_count; i++) { -// fs.FileRead(&file_p, reinterpret_cast(&cccd.cccd), sizeof(struct ble_store_value_cccd)); -// ble_store_write_cccd(&cccd.cccd); -// } -// -// fs.FileClose(&file_p); -// fs.FileDelete("/bond.dat"); -// } -//} +// void NimbleController::RestoreBond() { +// lfs_file_t file_p; +// union ble_store_value sec, cccd; +// uint8_t peer_count = 0; +// +// if (fs.FileOpen(&file_p, "/bond.dat", LFS_O_RDONLY) == 0) { +// memset(&sec, 0, sizeof sec); +// fs.FileRead(&file_p, reinterpret_cast(&sec.sec), sizeof sec); +// ble_store_write_our_sec(&sec.sec); +// +// memset(&sec, 0, sizeof sec); +// fs.FileRead(&file_p, reinterpret_cast(&sec.sec), sizeof sec); +// ble_store_write_peer_sec(&sec.sec); +// +// fs.FileRead(&file_p, &peer_count, 1); +// for (int i = 0; i < peer_count; i++) { +// fs.FileRead(&file_p, reinterpret_cast(&cccd.cccd), sizeof(struct ble_store_value_cccd)); +// ble_store_write_cccd(&cccd.cccd); +// } +// +// fs.FileClose(&file_p); +// fs.FileDelete("/bond.dat"); +// } +// } diff --git a/sim/components/ble/NimbleController.h b/sim/components/ble/NimbleController.h index 8566d1b..222055a 100644 --- a/sim/components/ble/NimbleController.h +++ b/sim/components/ble/NimbleController.h @@ -7,22 +7,23 @@ #include #undef max #undef min -//#include "components/ble/AlertNotificationClient.h" +// #include "components/ble/AlertNotificationClient.h" #include "components/ble/AlertNotificationService.h" -//#include "components/ble/BatteryInformationService.h" -//#include "components/ble/CurrentTimeClient.h" -//#include "components/ble/CurrentTimeService.h" -//#include "components/ble/DeviceInformationService.h" -//#include "components/ble/DfuService.h" -//#include "components/ble/HeartRateService.h" -//#include "components/ble/ImmediateAlertService.h" +// #include "components/ble/BatteryInformationService.h" +// #include "components/ble/CurrentTimeClient.h" +// #include "components/ble/CurrentTimeService.h" +// #include "components/ble/DeviceInformationService.h" +// #include "components/ble/DfuService.h" +// #include "components/ble/HeartRateService.h" +// #include "components/ble/ImmediateAlertService.h" #include "components/ble/MusicService.h" #include "components/ble/NavigationService.h" -//#include "components/ble/ServiceDiscovery.h" +// #include "components/ble/ServiceDiscovery.h" #include "components/ble/MotionService.h" #include "components/ble/SimpleWeatherService.h" #include "components/fs/FS.h" -//#include "components/ble/FSService.h" + +// #include "components/ble/FSService.h" namespace Pinetime { namespace Drivers { @@ -56,28 +57,31 @@ namespace Pinetime { Pinetime::Controllers::FS& fs); void Init(); void StartAdvertising(); -// int OnGAPEvent(ble_gap_event* event); + // int OnGAPEvent(ble_gap_event* event); -// int OnDiscoveryEvent(uint16_t i, const ble_gatt_error* pError, const ble_gatt_svc* pSvc); -// int OnCTSCharacteristicDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_chr* characteristic); -// int OnANSCharacteristicDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_chr* characteristic); -// int OnCurrentTimeReadResult(uint16_t connectionHandle, const ble_gatt_error* error, ble_gatt_attr* attribute); -// int OnANSDescriptorDiscoveryEventCallback(uint16_t connectionHandle, -// const ble_gatt_error* error, -// uint16_t characteristicValueHandle, -// const ble_gatt_dsc* descriptor); + // int OnDiscoveryEvent(uint16_t i, const ble_gatt_error* pError, const ble_gatt_svc* pSvc); + // int OnCTSCharacteristicDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_chr* + // characteristic); int OnANSCharacteristicDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const + // ble_gatt_chr* characteristic); int OnCurrentTimeReadResult(uint16_t connectionHandle, const ble_gatt_error* error, + // ble_gatt_attr* attribute); int OnANSDescriptorDiscoveryEventCallback(uint16_t connectionHandle, + // const ble_gatt_error* error, + // uint16_t characteristicValueHandle, + // const ble_gatt_dsc* descriptor); void StartDiscovery(); Pinetime::Controllers::MusicService& music() { return musicService; }; + Pinetime::Controllers::NavigationService& navigation() { return navService; }; + Pinetime::Controllers::AlertNotificationService& alertService() { return anService; }; + Pinetime::Controllers::SimpleWeatherService& weather() { return weatherService; }; @@ -93,8 +97,8 @@ namespace Pinetime { void DisableRadio(); private: -// void PersistBond(struct ble_gap_conn_desc& desc); -// void RestoreBond(); + // void PersistBond(struct ble_gap_conn_desc& desc); + // void RestoreBond(); static constexpr const char* deviceName = "InfiniTime"; Pinetime::System::SystemTask& systemTask; @@ -103,33 +107,33 @@ namespace Pinetime { Pinetime::Controllers::NotificationManager& notificationManager; Pinetime::Drivers::SpiNorFlash& spiNorFlash; Pinetime::Controllers::FS& fs; -// Pinetime::Controllers::DfuService dfuService; + // Pinetime::Controllers::DfuService dfuService; -// DeviceInformationService deviceInformationService; -// CurrentTimeClient currentTimeClient; + // DeviceInformationService deviceInformationService; + // CurrentTimeClient currentTimeClient; AlertNotificationService anService; -// AlertNotificationClient alertNotificationClient; -// CurrentTimeService currentTimeService; + // AlertNotificationClient alertNotificationClient; + // CurrentTimeService currentTimeService; MusicService musicService; SimpleWeatherService weatherService; NavigationService navService; -// BatteryInformationService batteryInformationService; -// ImmediateAlertService immediateAlertService; -// HeartRateService heartRateService; + // BatteryInformationService batteryInformationService; + // ImmediateAlertService immediateAlertService; + // HeartRateService heartRateService; MotionService motionService; -// FSService fsService; -// ServiceDiscovery serviceDiscovery; + // FSService fsService; + // ServiceDiscovery serviceDiscovery; uint8_t addrType; uint16_t connectionHandle = BLE_HS_CONN_HANDLE_NONE; uint8_t fastAdvCount = 0; uint8_t bondId[16] = {0}; -// ble_uuid128_t dfuServiceUuid { -// .u {.type = BLE_UUID_TYPE_128}, -// .value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x30, 0x15, 0x00, 0x00}}; + // ble_uuid128_t dfuServiceUuid { + // .u {.type = BLE_UUID_TYPE_128}, + // .value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x30, 0x15, 0x00, 0x00}}; }; -// static NimbleController* nptr; + // static NimbleController* nptr; } } diff --git a/sim/components/brightness/BrightnessController.cpp b/sim/components/brightness/BrightnessController.cpp index 7e198c4..5935b8c 100644 --- a/sim/components/brightness/BrightnessController.cpp +++ b/sim/components/brightness/BrightnessController.cpp @@ -1,41 +1,41 @@ #include "BrightnessController.h" -//#include +// #include #include "displayapp/screens/Symbols.h" #include "drivers/PinMap.h" using namespace Pinetime::Controllers; void BrightnessController::Init() { - //nrf_gpio_cfg_output(PinMap::LcdBacklightLow); - //nrf_gpio_cfg_output(PinMap::LcdBacklightMedium); - //nrf_gpio_cfg_output(PinMap::LcdBacklightHigh); + // nrf_gpio_cfg_output(PinMap::LcdBacklightLow); + // nrf_gpio_cfg_output(PinMap::LcdBacklightMedium); + // nrf_gpio_cfg_output(PinMap::LcdBacklightHigh); Set(level); } void BrightnessController::Set(BrightnessController::Levels level) { this->level = level; - //switch (level) { - // default: - // case Levels::High: - // nrf_gpio_pin_clear(PinMap::LcdBacklightLow); - // nrf_gpio_pin_clear(PinMap::LcdBacklightMedium); - // nrf_gpio_pin_clear(PinMap::LcdBacklightHigh); - // break; - // case Levels::Medium: - // nrf_gpio_pin_clear(PinMap::LcdBacklightLow); - // nrf_gpio_pin_clear(PinMap::LcdBacklightMedium); - // nrf_gpio_pin_set(PinMap::LcdBacklightHigh); - // break; - // case Levels::Low: - // nrf_gpio_pin_clear(PinMap::LcdBacklightLow); - // nrf_gpio_pin_set(PinMap::LcdBacklightMedium); - // nrf_gpio_pin_set(PinMap::LcdBacklightHigh); - // break; - // case Levels::Off: - // nrf_gpio_pin_set(PinMap::LcdBacklightLow); - // nrf_gpio_pin_set(PinMap::LcdBacklightMedium); - // nrf_gpio_pin_set(PinMap::LcdBacklightHigh); - // break; - //} + // switch (level) { + // default: + // case Levels::High: + // nrf_gpio_pin_clear(PinMap::LcdBacklightLow); + // nrf_gpio_pin_clear(PinMap::LcdBacklightMedium); + // nrf_gpio_pin_clear(PinMap::LcdBacklightHigh); + // break; + // case Levels::Medium: + // nrf_gpio_pin_clear(PinMap::LcdBacklightLow); + // nrf_gpio_pin_clear(PinMap::LcdBacklightMedium); + // nrf_gpio_pin_set(PinMap::LcdBacklightHigh); + // break; + // case Levels::Low: + // nrf_gpio_pin_clear(PinMap::LcdBacklightLow); + // nrf_gpio_pin_set(PinMap::LcdBacklightMedium); + // nrf_gpio_pin_set(PinMap::LcdBacklightHigh); + // break; + // case Levels::Off: + // nrf_gpio_pin_set(PinMap::LcdBacklightLow); + // nrf_gpio_pin_set(PinMap::LcdBacklightMedium); + // nrf_gpio_pin_set(PinMap::LcdBacklightHigh); + // break; + // } } void BrightnessController::Lower() { diff --git a/sim/components/firmwarevalidator/FirmwareValidator.cpp b/sim/components/firmwarevalidator/FirmwareValidator.cpp index 63454dc..93dc3e8 100644 --- a/sim/components/firmwarevalidator/FirmwareValidator.cpp +++ b/sim/components/firmwarevalidator/FirmwareValidator.cpp @@ -1,21 +1,21 @@ #include "components/firmwarevalidator/FirmwareValidator.h" -//#include -//#include "drivers/InternalFlash.h" +// #include +// #include "drivers/InternalFlash.h" using namespace Pinetime::Controllers; bool FirmwareValidator::IsValidated() const { return true; // lv_sim -// auto* imageOkPtr = reinterpret_cast(validBitAdress); -// return (*imageOkPtr) == validBitValue; + // auto* imageOkPtr = reinterpret_cast(validBitAdress); + // return (*imageOkPtr) == validBitValue; } void FirmwareValidator::Validate() { -// if (!IsValidated()) -// Pinetime::Drivers::InternalFlash::WriteWord(validBitAdress, validBitValue); + // if (!IsValidated()) + // Pinetime::Drivers::InternalFlash::WriteWord(validBitAdress, validBitValue); } void FirmwareValidator::Reset() { -// NVIC_SystemReset(); + // NVIC_SystemReset(); } diff --git a/sim/components/heartrate/HeartRateController.cpp b/sim/components/heartrate/HeartRateController.cpp index 4d407a8..aeb0d72 100644 --- a/sim/components/heartrate/HeartRateController.cpp +++ b/sim/components/heartrate/HeartRateController.cpp @@ -8,7 +8,7 @@ void HeartRateController::Update(HeartRateController::States newState, uint8_t h this->state = newState; if (this->heartRate != heartRate) { this->heartRate = heartRate; - //service->OnNewHeartRateValue(heartRate); + // service->OnNewHeartRateValue(heartRate); } } @@ -30,6 +30,6 @@ void HeartRateController::SetHeartRateTask(Pinetime::Applications::HeartRateTask this->task = task; } -//void HeartRateController::SetService(Pinetime::Controllers::HeartRateService* service) { -// this->service = service; -//} +// void HeartRateController::SetService(Pinetime::Controllers::HeartRateService* service) { +// this->service = service; +// } diff --git a/sim/components/heartrate/HeartRateController.h b/sim/components/heartrate/HeartRateController.h index f1dcd8b..73049d7 100644 --- a/sim/components/heartrate/HeartRateController.h +++ b/sim/components/heartrate/HeartRateController.h @@ -1,15 +1,18 @@ #pragma once #include -//#include + +// #include namespace Pinetime { namespace Applications { class HeartRateTask; } + namespace System { class SystemTask; } + namespace Controllers { class HeartRateController { public: @@ -21,20 +24,22 @@ namespace Pinetime { void Update(States newState, uint8_t heartRate); void SetHeartRateTask(Applications::HeartRateTask* task); + States State() const { return state; } + uint8_t HeartRate() const { return heartRate; } -// void SetService(Pinetime::Controllers::HeartRateService* service); + // void SetService(Pinetime::Controllers::HeartRateService* service); private: Applications::HeartRateTask* task = nullptr; States state = States::Stopped; uint8_t heartRate = 0; - //Pinetime::Controllers::HeartRateService* service = nullptr; + // Pinetime::Controllers::HeartRateService* service = nullptr; }; } } diff --git a/sim/displayapp/LittleVgl.cpp b/sim/displayapp/LittleVgl.cpp index cf77240..c2cca71 100644 --- a/sim/displayapp/LittleVgl.cpp +++ b/sim/displayapp/LittleVgl.cpp @@ -84,7 +84,7 @@ LittleVgl::LittleVgl(Pinetime::Drivers::St7789& lcd, Pinetime::Controllers::FS& } void LittleVgl::Init() { -// lv_init(); + // lv_init(); InitTheme(); InitDisplay(); InitTouchpad(); @@ -161,36 +161,36 @@ bool LittleVgl::IsScrolling() { } // glue the lvgl code to the lv-sim monitor driver -void DrawBuffer(lv_disp_drv_t *disp_drv, uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t* data, size_t size) { +void DrawBuffer(lv_disp_drv_t* disp_drv, uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t* data, size_t size) { lv_area_t area; area.x1 = x; - area.x2 = x+width-1; + area.x2 = x + width - 1; area.y1 = y; - area.y2 = y+height-1; + area.y2 = y + height - 1; lv_color_t* color_p = reinterpret_cast(data); monitor_flush(disp_drv, &area, color_p); } // copied from lv_drivers/display/monitor.c to get the SDL_Window for the InfiniTime screen -extern "C" -{ +extern "C" { typedef struct { - SDL_Window * window; - SDL_Renderer * renderer; - SDL_Texture * texture; + SDL_Window* window; + SDL_Renderer* renderer; + SDL_Texture* texture; volatile bool sdl_refr_qry; #if MONITOR_DOUBLE_BUFFERED - uint32_t * tft_fb_act; + uint32_t* tft_fb_act; #else uint32_t tft_fb[LV_HOR_RES_MAX * LV_VER_RES_MAX]; #endif -}monitor_t; +} monitor_t; + extern monitor_t monitor; } // positive height moves screen down (draw y=0 to y=height) // negative height moves screen up (draw y=height to y=0) -void MoveScreen(lv_disp_drv_t *disp_drv, int16_t height) { +void MoveScreen(lv_disp_drv_t* disp_drv, int16_t height) { if (height == 0) return; // nothing to do @@ -200,35 +200,35 @@ void MoveScreen(lv_disp_drv_t *disp_drv, int16_t height) { constexpr size_t zoom = MONITOR_ZOOM; const Uint32 format = SDL_PIXELFORMAT_RGBA8888; - SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, sdl_width*zoom, sdl_height*zoom, 32, format); + SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormat(0, sdl_width * zoom, sdl_height * zoom, 32, format); SDL_RenderReadPixels(renderer, NULL, format, surface->pixels, surface->pitch); - uint8_t *pixels = (uint8_t*) surface->pixels; + uint8_t* pixels = (uint8_t*) surface->pixels; - std::array color_p; + std::array color_p; for (int hi = 0; hi < sdl_height; hi++) { for (int wi = 0; wi < sdl_width; wi++) { - auto red = pixels[hi*surface->pitch*zoom + wi*4*zoom + 3]; // red - auto green = pixels[hi*surface->pitch*zoom + wi*4*zoom + 2]; // greeen - auto blue = pixels[hi*surface->pitch*zoom + wi*4*zoom + 1]; // blue + auto red = pixels[hi * surface->pitch * zoom + wi * 4 * zoom + 3]; // red + auto green = pixels[hi * surface->pitch * zoom + wi * 4 * zoom + 2]; // greeen + auto blue = pixels[hi * surface->pitch * zoom + wi * 4 * zoom + 1]; // blue color_p.at(hi * sdl_width + wi) = LV_COLOR_MAKE(red, green, blue); } } int16_t buffer_height = sdl_height - abs(height); if (height >= 0) { - DrawBuffer(disp_drv, 0, height, sdl_width, sdl_height, (uint8_t*)color_p.data(), sdl_width*buffer_height *2); + DrawBuffer(disp_drv, 0, height, sdl_width, sdl_height, (uint8_t*) color_p.data(), sdl_width * buffer_height * 2); } else { - DrawBuffer(disp_drv, 0, 0, sdl_width, sdl_height, (uint8_t*)(&color_p.at(sdl_width*abs(height))), sdl_width*buffer_height *2); + DrawBuffer(disp_drv, 0, 0, sdl_width, sdl_height, (uint8_t*) (&color_p.at(sdl_width * abs(height))), sdl_width * buffer_height * 2); } } void LittleVgl::FlushDisplay(const lv_area_t* area, lv_color_t* color_p) { uint16_t y1, y2, width, height = 0; - //if ((scrollDirection == LittleVgl::FullRefreshDirections::Down) && (area->y2 == visibleNbLines - 1)) { - // writeOffset = ((writeOffset + totalNbLines) - visibleNbLines) % totalNbLines; - //} else if ((scrollDirection == FullRefreshDirections::Up) && (area->y1 == 0)) { - // writeOffset = (writeOffset + visibleNbLines) % totalNbLines; - //} + // if ((scrollDirection == LittleVgl::FullRefreshDirections::Down) && (area->y2 == visibleNbLines - 1)) { + // writeOffset = ((writeOffset + totalNbLines) - visibleNbLines) % totalNbLines; + // } else if ((scrollDirection == FullRefreshDirections::Up) && (area->y1 == 0)) { + // writeOffset = (writeOffset + visibleNbLines) % totalNbLines; + // } y1 = (area->y1 + writeOffset) % totalNbLines; y2 = (area->y2 + writeOffset) % totalNbLines; @@ -294,29 +294,29 @@ void LittleVgl::FlushDisplay(const lv_area_t* area, lv_color_t* color_p) { height = totalNbLines - y1; if (height > 0) { - //lcd.DrawBuffer(area->x1, y1, width, height, reinterpret_cast(color_p), width * height * 2); + // lcd.DrawBuffer(area->x1, y1, width, height, reinterpret_cast(color_p), width * height * 2); DrawBuffer(&disp_drv, area->x1, y1, width, height, reinterpret_cast(color_p), width * height * 2); } uint16_t pixOffset = width * height; height = y2 + 1; - //lcd.DrawBuffer(area->x1, 0, width, height, reinterpret_cast(color_p + pixOffset), width * height * 2); + // lcd.DrawBuffer(area->x1, 0, width, height, reinterpret_cast(color_p + pixOffset), width * height * 2); DrawBuffer(&disp_drv, area->x1, 0, width, height, reinterpret_cast(color_p + pixOffset), width * height * 2); } else { - //lcd.DrawBuffer(area->x1, y1, width, height, reinterpret_cast(color_p), width * height * 2); + // lcd.DrawBuffer(area->x1, y1, width, height, reinterpret_cast(color_p), width * height * 2); DrawBuffer(&disp_drv, area->x1, y1, width, height, reinterpret_cast(color_p), width * height * 2); } // IMPORTANT!!! // Inform the graphics library that you are ready with the flushing - //lv_disp_flush_ready(&disp_drv); + // lv_disp_flush_ready(&disp_drv); // call flush with flushing_last set // workaround because lv_disp_flush_ready() doesn't seem to trigger monitor_flush - lv_disp_t *disp = lv_disp_get_default(); + lv_disp_t* disp = lv_disp_get_default(); lv_disp_get_buf(disp)->flushing_last = true; - lv_area_t area_zero {0,0,0,0}; + lv_area_t area_zero {0, 0, 0, 0}; monitor_flush(&disp_drv, &area_zero, color_p); // delay drawing to mimic PineTime display rendering speed vTaskDelay(pdMS_TO_TICKS(3)); diff --git a/sim/drivers/Bma421.cpp b/sim/drivers/Bma421.cpp index f2d3cdd..b17f0da 100644 --- a/sim/drivers/Bma421.cpp +++ b/sim/drivers/Bma421.cpp @@ -7,76 +7,82 @@ using namespace Pinetime::Drivers; namespace { -// int8_t user_i2c_read(uint8_t reg_addr, uint8_t* reg_data, uint32_t length, void* intf_ptr) { -// auto bma421 = static_cast(intf_ptr); -// bma421->Read(reg_addr, reg_data, length); -// return 0; -// } -// -// int8_t user_i2c_write(uint8_t reg_addr, const uint8_t* reg_data, uint32_t length, void* intf_ptr) { -// auto bma421 = static_cast(intf_ptr); -// bma421->Write(reg_addr, reg_data, length); -// return 0; -// } -// -// void user_delay(uint32_t period_us, void* intf_ptr) { -// nrf_delay_us(period_us); -// } + // int8_t user_i2c_read(uint8_t reg_addr, uint8_t* reg_data, uint32_t length, void* intf_ptr) { + // auto bma421 = static_cast(intf_ptr); + // bma421->Read(reg_addr, reg_data, length); + // return 0; + // } + // + // int8_t user_i2c_write(uint8_t reg_addr, const uint8_t* reg_data, uint32_t length, void* intf_ptr) { + // auto bma421 = static_cast(intf_ptr); + // bma421->Write(reg_addr, reg_data, length); + // return 0; + // } + // + // void user_delay(uint32_t period_us, void* intf_ptr) { + // nrf_delay_us(period_us); + // } } Bma421::Bma421(TwiMaster& twiMaster, uint8_t twiAddress) : twiMaster {twiMaster}, deviceAddress {twiAddress} { -// bma.intf = BMA4_I2C_INTF; -// bma.bus_read = user_i2c_read; -// bma.bus_write = user_i2c_write; -// bma.variant = BMA42X_VARIANT; -// bma.intf_ptr = this; -// bma.delay_us = user_delay; -// bma.read_write_len = 16; + // bma.intf = BMA4_I2C_INTF; + // bma.bus_read = user_i2c_read; + // bma.bus_write = user_i2c_write; + // bma.variant = BMA42X_VARIANT; + // bma.intf_ptr = this; + // bma.delay_us = user_delay; + // bma.read_write_len = 16; } void Bma421::Init() { if (not isResetOk) return; // Call SoftReset (and reset TWI device) first! -// auto ret = bma423_init(&bma); -// if (ret != BMA4_OK) -// return; + // auto ret = bma423_init(&bma); + // if (ret != BMA4_OK) + // return; - switch(bma.chip_id) { - case BMA423_CHIP_ID: deviceType = DeviceTypes::BMA421; break; - case BMA425_CHIP_ID: deviceType = DeviceTypes::BMA425; break; - default: deviceType = DeviceTypes::Unknown; break; + switch (bma.chip_id) { + case BMA423_CHIP_ID: + deviceType = DeviceTypes::BMA421; + break; + case BMA425_CHIP_ID: + deviceType = DeviceTypes::BMA425; + break; + default: + deviceType = DeviceTypes::Unknown; + break; } -// ret = bma423_write_config_file(&bma); -// if (ret != BMA4_OK) -// return; -// -// ret = bma4_set_interrupt_mode(BMA4_LATCH_MODE, &bma); -// if (ret != BMA4_OK) -// return; -// -// ret = bma423_feature_enable(BMA423_STEP_CNTR, 1, &bma); -// if (ret != BMA4_OK) -// return; -// -// ret = bma423_step_detector_enable(0, &bma); -// if (ret != BMA4_OK) -// return; -// -// ret = bma4_set_accel_enable(1, &bma); -// if (ret != BMA4_OK) -// return; -// -// struct bma4_accel_config accel_conf; -// accel_conf.odr = BMA4_OUTPUT_DATA_RATE_100HZ; -// accel_conf.range = BMA4_ACCEL_RANGE_2G; -// accel_conf.bandwidth = BMA4_ACCEL_NORMAL_AVG4; -// accel_conf.perf_mode = BMA4_CIC_AVG_MODE; -// ret = bma4_set_accel_config(&accel_conf, &bma); -// if (ret != BMA4_OK) -// return; -// + // ret = bma423_write_config_file(&bma); + // if (ret != BMA4_OK) + // return; + // + // ret = bma4_set_interrupt_mode(BMA4_LATCH_MODE, &bma); + // if (ret != BMA4_OK) + // return; + // + // ret = bma423_feature_enable(BMA423_STEP_CNTR, 1, &bma); + // if (ret != BMA4_OK) + // return; + // + // ret = bma423_step_detector_enable(0, &bma); + // if (ret != BMA4_OK) + // return; + // + // ret = bma4_set_accel_enable(1, &bma); + // if (ret != BMA4_OK) + // return; + // + // struct bma4_accel_config accel_conf; + // accel_conf.odr = BMA4_OUTPUT_DATA_RATE_100HZ; + // accel_conf.range = BMA4_ACCEL_RANGE_2G; + // accel_conf.bandwidth = BMA4_ACCEL_NORMAL_AVG4; + // accel_conf.perf_mode = BMA4_CIC_AVG_MODE; + // ret = bma4_set_accel_config(&accel_conf, &bma); + // if (ret != BMA4_OK) + // return; + // isOk = true; } @@ -96,39 +102,41 @@ void Bma421::Write(uint8_t registerAddress, const uint8_t* data, size_t size) { Bma421::Values Bma421::Process() { if (not isOk) return {}; -// struct bma4_accel data; -// bma4_read_accel_xyz(&data, &bma); -// -// uint32_t steps = 0; -// bma423_step_counter_output(&steps, &bma); -// -// int32_t temperature = 0; -// bma4_get_temperature(&temperature, BMA4_DEG, &bma); -// temperature = temperature / 1000; -// -// uint8_t activity = 0; -// bma423_activity_output(&activity, &bma); -// -// // X and Y axis are swapped because of the way the sensor is mounted in the PineTime -// return {steps, data.y, data.x, data.z}; + // struct bma4_accel data; + // bma4_read_accel_xyz(&data, &bma); + // + // uint32_t steps = 0; + // bma423_step_counter_output(&steps, &bma); + // + // int32_t temperature = 0; + // bma4_get_temperature(&temperature, BMA4_DEG, &bma); + // temperature = temperature / 1000; + // + // uint8_t activity = 0; + // bma423_activity_output(&activity, &bma); + // + // // X and Y axis are swapped because of the way the sensor is mounted in the PineTime + // return {steps, data.y, data.x, data.z}; return {steps, 0, 0, 0}; } + bool Bma421::IsOk() const { return isOk; } void Bma421::ResetStepCounter() { -// bma423_reset_step_counter(&bma); + // bma423_reset_step_counter(&bma); steps = 0; } void Bma421::SoftReset() { -// auto ret = bma4_soft_reset(&bma); -// if (ret == BMA4_OK) { -// isResetOk = true; -// nrf_delay_ms(1); -// } + // auto ret = bma4_soft_reset(&bma); + // if (ret == BMA4_OK) { + // isResetOk = true; + // nrf_delay_ms(1); + // } } + Bma421::DeviceTypes Bma421::DeviceType() const { return deviceType; } diff --git a/sim/drivers/Bma421.h b/sim/drivers/Bma421.h index b532749..04bc340 100644 --- a/sim/drivers/Bma421.h +++ b/sim/drivers/Bma421.h @@ -7,19 +7,18 @@ namespace Pinetime { namespace Drivers { class TwiMaster; + class Bma421 { public: - enum class DeviceTypes : uint8_t { - Unknown, - BMA421, - BMA425 - }; + enum class DeviceTypes : uint8_t { Unknown, BMA421, BMA425 }; + struct Values { uint32_t steps; int16_t x; int16_t y; int16_t z; }; + Bma421(TwiMaster& twiMaster, uint8_t twiAddress); Bma421(const Bma421&) = delete; Bma421& operator=(const Bma421&) = delete; diff --git a/sim/drivers/Cst816s.cpp b/sim/drivers/Cst816s.cpp index 659511f..dfb4cdd 100644 --- a/sim/drivers/Cst816s.cpp +++ b/sim/drivers/Cst816s.cpp @@ -14,8 +14,8 @@ using namespace Pinetime::Drivers; * TODO : we need a complete datasheet and protocol reference! * */ -//Cst816S::Cst816S(TwiMaster& twiMaster, uint8_t twiAddress) : twiMaster {twiMaster}, twiAddress {twiAddress} { -//} +// Cst816S::Cst816S(TwiMaster& twiMaster, uint8_t twiAddress) : twiMaster {twiMaster}, twiAddress {twiAddress} { +// } Cst816S::Cst816S() { } @@ -35,10 +35,10 @@ Cst816S::TouchInfos Cst816S::GetTouchInfo() { info.x = x; info.y = y; info.touching = (buttons & SDL_BUTTON_LMASK) != 0; - //info.gesture = gesture; + // info.gesture = gesture; info.isValid = x > 0 && x <= maxX && y > 0 && y <= maxY; - if(info.isValid) { - if(!is_pressed && info.touching) { + if (info.isValid) { + if (!is_pressed && info.touching) { // start klick pressed_since = std::chrono::steady_clock::now(); is_pressed = true; @@ -47,23 +47,23 @@ Cst816S::TouchInfos Cst816S::GetTouchInfo() { is_stationary = true; x_start = info.x; y_start = info.y; - } else if(is_pressed && info.touching) { + } else if (is_pressed && info.touching) { // is it long press? if (is_stationary) { // check if while touching we moved away from the start coordinates double x_diff = static_cast(info.x) - x_start; double y_diff = static_cast(info.y) - y_start; double norm = hypot(x_diff, y_diff); - if(norm > 20) { // we moved out of start area + if (norm > 20) { // we moved out of start area is_stationary = false; } } if (!is_long_press && !is_swipe) { // check for long-press only if it's not yet a long-press and didn't move std::chrono::duration press_duration = std::chrono::steady_clock::now() - pressed_since; - if(is_stationary && press_duration.count() > 1.0) { + if (is_stationary && press_duration.count() > 1.0) { // longer than 1 second pressed, then it is long-press is_long_press = true; info.gesture = Gestures::LongPress; - } else if(!is_stationary) { + } else if (!is_stationary) { // moved mouse fast enough to not be a long-press is_swipe = true; double x_diff = static_cast(info.x) - x_start; @@ -85,15 +85,15 @@ Cst816S::TouchInfos Cst816S::GetTouchInfo() { } } } - } else if(is_pressed && !info.touching) { + } else if (is_pressed && !info.touching) { // end klick is_pressed = false; double x_diff = static_cast(info.x) - x_start; double y_diff = static_cast(info.y) - y_start; double norm = hypot(x_diff, y_diff); - if(norm < 20) { - if(is_stationary && !is_long_press && !is_swipe) { + if (norm < 20) { + if (is_stationary && !is_long_press && !is_swipe) { // no swipe with less than 5 pixel mouse movement info.gesture = Gestures::SingleTap; } diff --git a/sim/drivers/Cst816s.h b/sim/drivers/Cst816s.h index 3a989da..e6b9a03 100644 --- a/sim/drivers/Cst816s.h +++ b/sim/drivers/Cst816s.h @@ -1,6 +1,6 @@ #pragma once -//#include "drivers/TwiMaster.h" +// #include "drivers/TwiMaster.h" #include #include @@ -18,6 +18,7 @@ namespace Pinetime { DoubleTap = 0x0B, LongPress = 0x0C }; + struct TouchInfos { uint16_t x = 0; uint16_t y = 0; @@ -27,7 +28,7 @@ namespace Pinetime { }; Cst816S(); -// Cst816S(TwiMaster& twiMaster, uint8_t twiAddress); + // Cst816S(TwiMaster& twiMaster, uint8_t twiAddress); Cst816S(const Cst816S&) = delete; Cst816S& operator=(const Cst816S&) = delete; Cst816S(Cst816S&&) = delete; @@ -41,39 +42,41 @@ namespace Pinetime { uint8_t GetChipId() const { return chipId; } + uint8_t GetVendorId() const { return vendorId; } + uint8_t GetFwVersion() const { return fwVersion; } + private: bool CheckDeviceIds(); // Unused/Unavailable commented out static constexpr uint8_t gestureIndex = 1; static constexpr uint8_t touchPointNumIndex = 2; - //static constexpr uint8_t touchEventIndex = 3; + // static constexpr uint8_t touchEventIndex = 3; static constexpr uint8_t touchXHighIndex = 3; static constexpr uint8_t touchXLowIndex = 4; - //static constexpr uint8_t touchIdIndex = 5; + // static constexpr uint8_t touchIdIndex = 5; static constexpr uint8_t touchYHighIndex = 5; static constexpr uint8_t touchYLowIndex = 6; - //static constexpr uint8_t touchStep = 6; - //static constexpr uint8_t touchXYIndex = 7; - //static constexpr uint8_t touchMiscIndex = 8; + // static constexpr uint8_t touchStep = 6; + // static constexpr uint8_t touchXYIndex = 7; + // static constexpr uint8_t touchMiscIndex = 8; static constexpr uint8_t maxX = 240; static constexpr uint8_t maxY = 240; -// TwiMaster& twiMaster; -// uint8_t twiAddress; + // TwiMaster& twiMaster; + // uint8_t twiAddress; const uint8_t chipId = 0xb4; const uint8_t vendorId = 0; const uint8_t fwVersion = 1; - // simulation members for swipe detection from mouse std::chrono::time_point pressed_since; bool is_pressed = false; diff --git a/sim/drivers/SpiMaster.cpp b/sim/drivers/SpiMaster.cpp index e9d9473..21c7622 100644 --- a/sim/drivers/SpiMaster.cpp +++ b/sim/drivers/SpiMaster.cpp @@ -1,6 +1,6 @@ #include "drivers/SpiMaster.h" -//#include -//#include +// #include +// #include #include #include @@ -10,249 +10,250 @@ SpiMaster::SpiMaster(const SpiMaster::SpiModule spi, const SpiMaster::Parameters } bool SpiMaster::Init() { -// if(mutex == nullptr) { -// mutex = xSemaphoreCreateBinary(); -// ASSERT(mutex != nullptr); -// } -// -// /* Configure GPIO pins used for pselsck, pselmosi, pselmiso and pselss for SPI0 */ -// nrf_gpio_pin_set(params.pinSCK); -// nrf_gpio_cfg_output(params.pinSCK); -// nrf_gpio_pin_clear(params.pinMOSI); -// nrf_gpio_cfg_output(params.pinMOSI); -// nrf_gpio_cfg_input(params.pinMISO, NRF_GPIO_PIN_NOPULL); -// // nrf_gpio_cfg_output(params.pinCSN); -// // pinCsn = params.pinCSN; -// -// switch (spi) { -// case SpiModule::SPI0: -// spiBaseAddress = NRF_SPIM0; -// break; -// case SpiModule::SPI1: -// spiBaseAddress = NRF_SPIM1; -// break; -// default: -// return false; -// } -// -// /* Configure pins, frequency and mode */ -// spiBaseAddress->PSELSCK = params.pinSCK; -// spiBaseAddress->PSELMOSI = params.pinMOSI; -// spiBaseAddress->PSELMISO = params.pinMISO; -// -// uint32_t frequency; -// switch (params.Frequency) { -// case Frequencies::Freq8Mhz: -// frequency = 0x80000000; -// break; -// default: -// return false; -// } -// spiBaseAddress->FREQUENCY = frequency; -// -// uint32_t regConfig = 0; -// switch (params.bitOrder) { -// case BitOrder::Msb_Lsb: -// break; -// case BitOrder::Lsb_Msb: -// regConfig = 1; -// break; -// default: -// return false; -// } -// switch (params.mode) { -// case Modes::Mode0: -// break; -// case Modes::Mode1: -// regConfig |= (0x01 << 1); -// break; -// case Modes::Mode2: -// regConfig |= (0x02 << 1); -// break; -// case Modes::Mode3: -// regConfig |= (0x03 << 1); -// break; -// default: -// return false; -// } -// -// spiBaseAddress->CONFIG = regConfig; -// spiBaseAddress->EVENTS_ENDRX = 0; -// spiBaseAddress->EVENTS_ENDTX = 0; -// spiBaseAddress->EVENTS_END = 0; -// -// spiBaseAddress->INTENSET = ((unsigned) 1 << (unsigned) 6); -// spiBaseAddress->INTENSET = ((unsigned) 1 << (unsigned) 1); -// spiBaseAddress->INTENSET = ((unsigned) 1 << (unsigned) 19); -// -// spiBaseAddress->ENABLE = (SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos); -// -// NRFX_IRQ_PRIORITY_SET(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn, 2); -// NRFX_IRQ_ENABLE(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn); -// -// xSemaphoreGive(mutex); + // if(mutex == nullptr) { + // mutex = xSemaphoreCreateBinary(); + // ASSERT(mutex != nullptr); + // } + // + // /* Configure GPIO pins used for pselsck, pselmosi, pselmiso and pselss for SPI0 */ + // nrf_gpio_pin_set(params.pinSCK); + // nrf_gpio_cfg_output(params.pinSCK); + // nrf_gpio_pin_clear(params.pinMOSI); + // nrf_gpio_cfg_output(params.pinMOSI); + // nrf_gpio_cfg_input(params.pinMISO, NRF_GPIO_PIN_NOPULL); + // // nrf_gpio_cfg_output(params.pinCSN); + // // pinCsn = params.pinCSN; + // + // switch (spi) { + // case SpiModule::SPI0: + // spiBaseAddress = NRF_SPIM0; + // break; + // case SpiModule::SPI1: + // spiBaseAddress = NRF_SPIM1; + // break; + // default: + // return false; + // } + // + // /* Configure pins, frequency and mode */ + // spiBaseAddress->PSELSCK = params.pinSCK; + // spiBaseAddress->PSELMOSI = params.pinMOSI; + // spiBaseAddress->PSELMISO = params.pinMISO; + // + // uint32_t frequency; + // switch (params.Frequency) { + // case Frequencies::Freq8Mhz: + // frequency = 0x80000000; + // break; + // default: + // return false; + // } + // spiBaseAddress->FREQUENCY = frequency; + // + // uint32_t regConfig = 0; + // switch (params.bitOrder) { + // case BitOrder::Msb_Lsb: + // break; + // case BitOrder::Lsb_Msb: + // regConfig = 1; + // break; + // default: + // return false; + // } + // switch (params.mode) { + // case Modes::Mode0: + // break; + // case Modes::Mode1: + // regConfig |= (0x01 << 1); + // break; + // case Modes::Mode2: + // regConfig |= (0x02 << 1); + // break; + // case Modes::Mode3: + // regConfig |= (0x03 << 1); + // break; + // default: + // return false; + // } + // + // spiBaseAddress->CONFIG = regConfig; + // spiBaseAddress->EVENTS_ENDRX = 0; + // spiBaseAddress->EVENTS_ENDTX = 0; + // spiBaseAddress->EVENTS_END = 0; + // + // spiBaseAddress->INTENSET = ((unsigned) 1 << (unsigned) 6); + // spiBaseAddress->INTENSET = ((unsigned) 1 << (unsigned) 1); + // spiBaseAddress->INTENSET = ((unsigned) 1 << (unsigned) 19); + // + // spiBaseAddress->ENABLE = (SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos); + // + // NRFX_IRQ_PRIORITY_SET(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn, 2); + // NRFX_IRQ_ENABLE(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn); + // + // xSemaphoreGive(mutex); return true; } -//void SpiMaster::SetupWorkaroundForFtpan58(NRF_SPIM_Type* spim, uint32_t ppi_channel, uint32_t gpiote_channel) { -// // Create an event when SCK toggles. -// NRF_GPIOTE->CONFIG[gpiote_channel] = (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) | (spim->PSEL.SCK << GPIOTE_CONFIG_PSEL_Pos) | -// (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos); -// -// // Stop the spim instance when SCK toggles. -// NRF_PPI->CH[ppi_channel].EEP = (uint32_t) &NRF_GPIOTE->EVENTS_IN[gpiote_channel]; -// NRF_PPI->CH[ppi_channel].TEP = (uint32_t) &spim->TASKS_STOP; -// NRF_PPI->CHENSET = 1U << ppi_channel; -// spiBaseAddress->EVENTS_END = 0; -// -// // Disable IRQ -// spim->INTENCLR = (1 << 6); -// spim->INTENCLR = (1 << 1); -// spim->INTENCLR = (1 << 19); -//} +// void SpiMaster::SetupWorkaroundForFtpan58(NRF_SPIM_Type* spim, uint32_t ppi_channel, uint32_t gpiote_channel) { +// // Create an event when SCK toggles. +// NRF_GPIOTE->CONFIG[gpiote_channel] = (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) | (spim->PSEL.SCK << GPIOTE_CONFIG_PSEL_Pos) +// | +// (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos); +// +// // Stop the spim instance when SCK toggles. +// NRF_PPI->CH[ppi_channel].EEP = (uint32_t) &NRF_GPIOTE->EVENTS_IN[gpiote_channel]; +// NRF_PPI->CH[ppi_channel].TEP = (uint32_t) &spim->TASKS_STOP; +// NRF_PPI->CHENSET = 1U << ppi_channel; +// spiBaseAddress->EVENTS_END = 0; +// +// // Disable IRQ +// spim->INTENCLR = (1 << 6); +// spim->INTENCLR = (1 << 1); +// spim->INTENCLR = (1 << 19); +// } -//void SpiMaster::DisableWorkaroundForFtpan58(NRF_SPIM_Type* spim, uint32_t ppi_channel, uint32_t gpiote_channel) { -// NRF_GPIOTE->CONFIG[gpiote_channel] = 0; -// NRF_PPI->CH[ppi_channel].EEP = 0; -// NRF_PPI->CH[ppi_channel].TEP = 0; -// NRF_PPI->CHENSET = ppi_channel; -// spiBaseAddress->EVENTS_END = 0; -// spim->INTENSET = (1 << 6); -// spim->INTENSET = (1 << 1); -// spim->INTENSET = (1 << 19); -//} +// void SpiMaster::DisableWorkaroundForFtpan58(NRF_SPIM_Type* spim, uint32_t ppi_channel, uint32_t gpiote_channel) { +// NRF_GPIOTE->CONFIG[gpiote_channel] = 0; +// NRF_PPI->CH[ppi_channel].EEP = 0; +// NRF_PPI->CH[ppi_channel].TEP = 0; +// NRF_PPI->CHENSET = ppi_channel; +// spiBaseAddress->EVENTS_END = 0; +// spim->INTENSET = (1 << 6); +// spim->INTENSET = (1 << 1); +// spim->INTENSET = (1 << 19); +// } void SpiMaster::OnEndEvent() { if (currentBufferAddr == 0) { return; } -// auto s = currentBufferSize; -// if (s > 0) { -// auto currentSize = std::min((size_t) 255, s); -// PrepareTx(currentBufferAddr, currentSize); -// currentBufferAddr += currentSize; -// currentBufferSize -= currentSize; -// -// spiBaseAddress->TASKS_START = 1; -// } else { -// BaseType_t xHigherPriorityTaskWoken = pdFALSE; -// if (taskToNotify != nullptr) { -// vTaskNotifyGiveFromISR(taskToNotify, &xHigherPriorityTaskWoken); -// portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -// } -// -// nrf_gpio_pin_set(this->pinCsn); -// currentBufferAddr = 0; -// BaseType_t xHigherPriorityTaskWoken2 = pdFALSE; -// xSemaphoreGiveFromISR(mutex, &xHigherPriorityTaskWoken2); -// portYIELD_FROM_ISR(xHigherPriorityTaskWoken | xHigherPriorityTaskWoken2); -// } + // auto s = currentBufferSize; + // if (s > 0) { + // auto currentSize = std::min((size_t) 255, s); + // PrepareTx(currentBufferAddr, currentSize); + // currentBufferAddr += currentSize; + // currentBufferSize -= currentSize; + // + // spiBaseAddress->TASKS_START = 1; + // } else { + // BaseType_t xHigherPriorityTaskWoken = pdFALSE; + // if (taskToNotify != nullptr) { + // vTaskNotifyGiveFromISR(taskToNotify, &xHigherPriorityTaskWoken); + // portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + // } + // + // nrf_gpio_pin_set(this->pinCsn); + // currentBufferAddr = 0; + // BaseType_t xHigherPriorityTaskWoken2 = pdFALSE; + // xSemaphoreGiveFromISR(mutex, &xHigherPriorityTaskWoken2); + // portYIELD_FROM_ISR(xHigherPriorityTaskWoken | xHigherPriorityTaskWoken2); + // } } void SpiMaster::OnStartedEvent() { } -//void SpiMaster::PrepareTx(const volatile uint32_t bufferAddress, const volatile size_t size) { -// spiBaseAddress->TXD.PTR = bufferAddress; -// spiBaseAddress->TXD.MAXCNT = size; -// spiBaseAddress->TXD.LIST = 0; -// spiBaseAddress->RXD.PTR = 0; -// spiBaseAddress->RXD.MAXCNT = 0; -// spiBaseAddress->RXD.LIST = 0; -// spiBaseAddress->EVENTS_END = 0; -//} +// void SpiMaster::PrepareTx(const volatile uint32_t bufferAddress, const volatile size_t size) { +// spiBaseAddress->TXD.PTR = bufferAddress; +// spiBaseAddress->TXD.MAXCNT = size; +// spiBaseAddress->TXD.LIST = 0; +// spiBaseAddress->RXD.PTR = 0; +// spiBaseAddress->RXD.MAXCNT = 0; +// spiBaseAddress->RXD.LIST = 0; +// spiBaseAddress->EVENTS_END = 0; +// } -//void SpiMaster::PrepareRx(const volatile uint32_t cmdAddress, -// const volatile size_t cmdSize, -// const volatile uint32_t bufferAddress, -// const volatile size_t size) { -// spiBaseAddress->TXD.PTR = 0; -// spiBaseAddress->TXD.MAXCNT = 0; -// spiBaseAddress->TXD.LIST = 0; -// spiBaseAddress->RXD.PTR = bufferAddress; -// spiBaseAddress->RXD.MAXCNT = size; -// spiBaseAddress->RXD.LIST = 0; -// spiBaseAddress->EVENTS_END = 0; -//} +// void SpiMaster::PrepareRx(const volatile uint32_t cmdAddress, +// const volatile size_t cmdSize, +// const volatile uint32_t bufferAddress, +// const volatile size_t size) { +// spiBaseAddress->TXD.PTR = 0; +// spiBaseAddress->TXD.MAXCNT = 0; +// spiBaseAddress->TXD.LIST = 0; +// spiBaseAddress->RXD.PTR = bufferAddress; +// spiBaseAddress->RXD.MAXCNT = size; +// spiBaseAddress->RXD.LIST = 0; +// spiBaseAddress->EVENTS_END = 0; +// } bool SpiMaster::Write(uint8_t pinCsn, const uint8_t* data, size_t size, const std::function& preTransactionHook) { -// if (data == nullptr) -// return false; -// auto ok = xSemaphoreTake(mutex, portMAX_DELAY); -// ASSERT(ok == true); -// taskToNotify = xTaskGetCurrentTaskHandle(); -// -// this->pinCsn = pinCsn; -// -// if (size == 1) { -// SetupWorkaroundForFtpan58(spiBaseAddress, 0, 0); -// } else { -// DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0); -// } -// -// nrf_gpio_pin_clear(this->pinCsn); -// -// currentBufferAddr = (uint32_t) data; -// currentBufferSize = size; -// -// auto currentSize = std::min((size_t) 255, (size_t) currentBufferSize); -// PrepareTx(currentBufferAddr, currentSize); -// currentBufferSize -= currentSize; -// currentBufferAddr += currentSize; -// spiBaseAddress->TASKS_START = 1; -// -// if (size == 1) { -// while (spiBaseAddress->EVENTS_END == 0) -// ; -// nrf_gpio_pin_set(this->pinCsn); -// currentBufferAddr = 0; -// xSemaphoreGive(mutex); -// } + // if (data == nullptr) + // return false; + // auto ok = xSemaphoreTake(mutex, portMAX_DELAY); + // ASSERT(ok == true); + // taskToNotify = xTaskGetCurrentTaskHandle(); + // + // this->pinCsn = pinCsn; + // + // if (size == 1) { + // SetupWorkaroundForFtpan58(spiBaseAddress, 0, 0); + // } else { + // DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0); + // } + // + // nrf_gpio_pin_clear(this->pinCsn); + // + // currentBufferAddr = (uint32_t) data; + // currentBufferSize = size; + // + // auto currentSize = std::min((size_t) 255, (size_t) currentBufferSize); + // PrepareTx(currentBufferAddr, currentSize); + // currentBufferSize -= currentSize; + // currentBufferAddr += currentSize; + // spiBaseAddress->TASKS_START = 1; + // + // if (size == 1) { + // while (spiBaseAddress->EVENTS_END == 0) + // ; + // nrf_gpio_pin_set(this->pinCsn); + // currentBufferAddr = 0; + // xSemaphoreGive(mutex); + // } return true; } bool SpiMaster::Read(uint8_t pinCsn, uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize) { -// xSemaphoreTake(mutex, portMAX_DELAY); -// -// taskToNotify = nullptr; -// -// this->pinCsn = pinCsn; -// DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0); -// spiBaseAddress->INTENCLR = (1 << 6); -// spiBaseAddress->INTENCLR = (1 << 1); -// spiBaseAddress->INTENCLR = (1 << 19); -// -// nrf_gpio_pin_clear(this->pinCsn); -// -// currentBufferAddr = 0; -// currentBufferSize = 0; -// -// PrepareTx((uint32_t) cmd, cmdSize); -// spiBaseAddress->TASKS_START = 1; -// while (spiBaseAddress->EVENTS_END == 0) -// ; -// -// PrepareRx((uint32_t) cmd, cmdSize, (uint32_t) data, dataSize); -// spiBaseAddress->TASKS_START = 1; -// -// while (spiBaseAddress->EVENTS_END == 0) -// ; -// nrf_gpio_pin_set(this->pinCsn); -// -// xSemaphoreGive(mutex); + // xSemaphoreTake(mutex, portMAX_DELAY); + // + // taskToNotify = nullptr; + // + // this->pinCsn = pinCsn; + // DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0); + // spiBaseAddress->INTENCLR = (1 << 6); + // spiBaseAddress->INTENCLR = (1 << 1); + // spiBaseAddress->INTENCLR = (1 << 19); + // + // nrf_gpio_pin_clear(this->pinCsn); + // + // currentBufferAddr = 0; + // currentBufferSize = 0; + // + // PrepareTx((uint32_t) cmd, cmdSize); + // spiBaseAddress->TASKS_START = 1; + // while (spiBaseAddress->EVENTS_END == 0) + // ; + // + // PrepareRx((uint32_t) cmd, cmdSize, (uint32_t) data, dataSize); + // spiBaseAddress->TASKS_START = 1; + // + // while (spiBaseAddress->EVENTS_END == 0) + // ; + // nrf_gpio_pin_set(this->pinCsn); + // + // xSemaphoreGive(mutex); return true; } void SpiMaster::Sleep() { -// while (spiBaseAddress->ENABLE != 0) { -// spiBaseAddress->ENABLE = (SPIM_ENABLE_ENABLE_Disabled << SPIM_ENABLE_ENABLE_Pos); -// } -// nrf_gpio_cfg_default(params.pinSCK); -// nrf_gpio_cfg_default(params.pinMOSI); -// nrf_gpio_cfg_default(params.pinMISO); + // while (spiBaseAddress->ENABLE != 0) { + // spiBaseAddress->ENABLE = (SPIM_ENABLE_ENABLE_Disabled << SPIM_ENABLE_ENABLE_Pos); + // } + // nrf_gpio_cfg_default(params.pinSCK); + // nrf_gpio_cfg_default(params.pinMOSI); + // nrf_gpio_cfg_default(params.pinMISO); NRF_LOG_INFO("[SPIMASTER] sleep"); } @@ -263,34 +264,34 @@ void SpiMaster::Wakeup() { } bool SpiMaster::WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize) { -// xSemaphoreTake(mutex, portMAX_DELAY); -// -// taskToNotify = nullptr; -// -// this->pinCsn = pinCsn; -// DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0); -// spiBaseAddress->INTENCLR = (1 << 6); -// spiBaseAddress->INTENCLR = (1 << 1); -// spiBaseAddress->INTENCLR = (1 << 19); -// -// nrf_gpio_pin_clear(this->pinCsn); -// -// currentBufferAddr = 0; -// currentBufferSize = 0; -// -// PrepareTx((uint32_t) cmd, cmdSize); -// spiBaseAddress->TASKS_START = 1; -// while (spiBaseAddress->EVENTS_END == 0) -// ; -// -// PrepareTx((uint32_t) data, dataSize); -// spiBaseAddress->TASKS_START = 1; -// -// while (spiBaseAddress->EVENTS_END == 0) -// ; -// nrf_gpio_pin_set(this->pinCsn); -// -// xSemaphoreGive(mutex); + // xSemaphoreTake(mutex, portMAX_DELAY); + // + // taskToNotify = nullptr; + // + // this->pinCsn = pinCsn; + // DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0); + // spiBaseAddress->INTENCLR = (1 << 6); + // spiBaseAddress->INTENCLR = (1 << 1); + // spiBaseAddress->INTENCLR = (1 << 19); + // + // nrf_gpio_pin_clear(this->pinCsn); + // + // currentBufferAddr = 0; + // currentBufferSize = 0; + // + // PrepareTx((uint32_t) cmd, cmdSize); + // spiBaseAddress->TASKS_START = 1; + // while (spiBaseAddress->EVENTS_END == 0) + // ; + // + // PrepareTx((uint32_t) data, dataSize); + // spiBaseAddress->TASKS_START = 1; + // + // while (spiBaseAddress->EVENTS_END == 0) + // ; + // nrf_gpio_pin_set(this->pinCsn); + // + // xSemaphoreGive(mutex); return true; } diff --git a/sim/drivers/SpiMaster.h b/sim/drivers/SpiMaster.h index 4e53492..52aa12e 100644 --- a/sim/drivers/SpiMaster.h +++ b/sim/drivers/SpiMaster.h @@ -4,8 +4,9 @@ #include #include -//#include -//#include + +// #include +// #include namespace Pinetime { namespace Drivers { @@ -15,6 +16,7 @@ namespace Pinetime { enum class BitOrder : uint8_t { Msb_Lsb, Lsb_Msb }; enum class Modes : uint8_t { Mode0, Mode1, Mode2, Mode3 }; enum class Frequencies : uint8_t { Freq8Mhz }; + struct Parameters { BitOrder bitOrder; Modes mode; @@ -43,15 +45,15 @@ namespace Pinetime { void Wakeup(); private: -// void SetupWorkaroundForFtpan58(NRF_SPIM_Type* spim, uint32_t ppi_channel, uint32_t gpiote_channel); -// void DisableWorkaroundForFtpan58(NRF_SPIM_Type* spim, uint32_t ppi_channel, uint32_t gpiote_channel); -// void PrepareTx(const volatile uint32_t bufferAddress, const volatile size_t size); -// void PrepareRx(const volatile uint32_t cmdAddress, -// const volatile size_t cmdSize, -// const volatile uint32_t bufferAddress, -// const volatile size_t size); + // void SetupWorkaroundForFtpan58(NRF_SPIM_Type* spim, uint32_t ppi_channel, uint32_t gpiote_channel); + // void DisableWorkaroundForFtpan58(NRF_SPIM_Type* spim, uint32_t ppi_channel, uint32_t gpiote_channel); + // void PrepareTx(const volatile uint32_t bufferAddress, const volatile size_t size); + // void PrepareRx(const volatile uint32_t cmdAddress, + // const volatile size_t cmdSize, + // const volatile uint32_t bufferAddress, + // const volatile size_t size); -// NRF_SPIM_Type* spiBaseAddress; + // NRF_SPIM_Type* spiBaseAddress; uint8_t pinCsn; SpiMaster::SpiModule spi; @@ -59,8 +61,8 @@ namespace Pinetime { volatile uint32_t currentBufferAddr = 0; volatile size_t currentBufferSize = 0; -// volatile TaskHandle_t taskToNotify; -// SemaphoreHandle_t mutex = nullptr; + // volatile TaskHandle_t taskToNotify; + // SemaphoreHandle_t mutex = nullptr; }; } } diff --git a/sim/drivers/SpiNorFlash.cpp b/sim/drivers/SpiNorFlash.cpp index ad4830b..c1b4b2a 100644 --- a/sim/drivers/SpiNorFlash.cpp +++ b/sim/drivers/SpiNorFlash.cpp @@ -8,9 +8,9 @@ using namespace Pinetime::Drivers; -SpiNorFlash::SpiNorFlash(const std::string& memoryFilePath) : memoryFilePath{memoryFilePath} { +SpiNorFlash::SpiNorFlash(const std::string& memoryFilePath) : memoryFilePath {memoryFilePath} { namespace fs = std::filesystem; - fs::path f{ memoryFilePath }; + fs::path f {memoryFilePath}; if (fs::exists(f)) { memoryFile = std::fstream(memoryFilePath, std::ios::binary | std::fstream::in | std::fstream::out); } else { @@ -19,6 +19,7 @@ SpiNorFlash::SpiNorFlash(const std::string& memoryFilePath) : memoryFilePath{mem memoryFile.write("", 1); } } + SpiNorFlash::~SpiNorFlash() { if (memoryFile.is_open()) { memoryFile.close(); @@ -27,8 +28,10 @@ SpiNorFlash::~SpiNorFlash() { void SpiNorFlash::Init() { device_id = ReadIdentification(); - NRF_LOG_INFO( - "[SpiNorFlash] Manufacturer : %d, Memory type : %d, memory density : %d", device_id.manufacturer, device_id.type, device_id.density); + NRF_LOG_INFO("[SpiNorFlash] Manufacturer : %d, Memory type : %d, memory density : %d", + device_id.manufacturer, + device_id.type, + device_id.density); } void SpiNorFlash::Uninit() { @@ -38,9 +41,7 @@ void SpiNorFlash::Sleep() { NRF_LOG_INFO("[SpiNorFlash] Sleep") } -void SpiNorFlash::Wakeup() { - NRF_LOG_INFO("[SpiNorFlash] Wakeup") -} +void SpiNorFlash::Wakeup() {NRF_LOG_INFO("[SpiNorFlash] Wakeup")} SpiNorFlash::Identification SpiNorFlash::ReadIdentification() { return {}; @@ -68,15 +69,13 @@ void SpiNorFlash::Read(uint32_t address, uint8_t* buffer, size_t size) { throw std::runtime_error("SpiNorFlash::Read out of bounds"); } memoryFile.seekp(address); - memoryFile.read(reinterpret_cast(buffer), size); + memoryFile.read(reinterpret_cast(buffer), size); } void SpiNorFlash::WriteEnable() { - } void SpiNorFlash::SectorErase(uint32_t sectorAddress) { - } uint8_t SpiNorFlash::ReadSecurityRegister() { @@ -100,6 +99,6 @@ void SpiNorFlash::Write(uint32_t address, const uint8_t* buffer, size_t size) { throw std::runtime_error("SpiNorFlash::Write out of bounds"); } memoryFile.seekp(address); - memoryFile.write(reinterpret_cast(buffer), size); + memoryFile.write(reinterpret_cast(buffer), size); memoryFile.flush(); } diff --git a/sim/drivers/SpiNorFlash.h b/sim/drivers/SpiNorFlash.h index f5b8e77..ab75ec1 100644 --- a/sim/drivers/SpiNorFlash.h +++ b/sim/drivers/SpiNorFlash.h @@ -6,6 +6,7 @@ namespace Pinetime { namespace Drivers { class Spi; + class SpiNorFlash { public: explicit SpiNorFlash(const std::string& memoryFilePath); @@ -61,7 +62,6 @@ namespace Pinetime { static constexpr size_t memorySize {0x400000}; const std::string& memoryFilePath; - Identification device_id; std::fstream memoryFile; }; diff --git a/sim/drivers/TwiMaster.cpp b/sim/drivers/TwiMaster.cpp index cd89d7d..2d48381 100644 --- a/sim/drivers/TwiMaster.cpp +++ b/sim/drivers/TwiMaster.cpp @@ -12,163 +12,163 @@ TwiMaster::TwiMaster(NRF_TWIM_Type* module, uint32_t frequency, uint8_t pinSda, : module {module}, frequency {frequency}, pinSda {pinSda}, pinScl {pinScl} { } -//void TwiMaster::ConfigurePins() const { -// NRF_GPIO->PIN_CNF[pinScl] = -// (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) | -// (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | -// (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | -// (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) | -// (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos); -// -// NRF_GPIO->PIN_CNF[pinSda] = -// (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) | -// (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | -// (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | -// (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) | -// (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos); -//} +// void TwiMaster::ConfigurePins() const { +// NRF_GPIO->PIN_CNF[pinScl] = +// (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) | +// (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | +// (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | +// (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) | +// (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos); +// +// NRF_GPIO->PIN_CNF[pinSda] = +// (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) | +// (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | +// (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | +// (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) | +// (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos); +// } void TwiMaster::Init() { -// if (mutex == nullptr) { -// mutex = xSemaphoreCreateBinary(); -// } -// -// ConfigurePins(); -// -// twiBaseAddress = module; -// -// twiBaseAddress->FREQUENCY = frequency; -// -// twiBaseAddress->PSEL.SCL = pinScl; -// twiBaseAddress->PSEL.SDA = pinSda; -// twiBaseAddress->EVENTS_LASTRX = 0; -// twiBaseAddress->EVENTS_STOPPED = 0; -// twiBaseAddress->EVENTS_LASTTX = 0; -// twiBaseAddress->EVENTS_ERROR = 0; -// twiBaseAddress->EVENTS_RXSTARTED = 0; -// twiBaseAddress->EVENTS_SUSPENDED = 0; -// twiBaseAddress->EVENTS_TXSTARTED = 0; -// -// twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Enabled << TWIM_ENABLE_ENABLE_Pos); -// -// xSemaphoreGive(mutex); + // if (mutex == nullptr) { + // mutex = xSemaphoreCreateBinary(); + // } + // + // ConfigurePins(); + // + // twiBaseAddress = module; + // + // twiBaseAddress->FREQUENCY = frequency; + // + // twiBaseAddress->PSEL.SCL = pinScl; + // twiBaseAddress->PSEL.SDA = pinSda; + // twiBaseAddress->EVENTS_LASTRX = 0; + // twiBaseAddress->EVENTS_STOPPED = 0; + // twiBaseAddress->EVENTS_LASTTX = 0; + // twiBaseAddress->EVENTS_ERROR = 0; + // twiBaseAddress->EVENTS_RXSTARTED = 0; + // twiBaseAddress->EVENTS_SUSPENDED = 0; + // twiBaseAddress->EVENTS_TXSTARTED = 0; + // + // twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Enabled << TWIM_ENABLE_ENABLE_Pos); + // + // xSemaphoreGive(mutex); } TwiMaster::ErrorCodes TwiMaster::Read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* data, size_t size) { -// xSemaphoreTake(mutex, portMAX_DELAY); -// Wakeup(); -// auto ret = Write(deviceAddress, ®isterAddress, 1, false); -// ret = Read(deviceAddress, data, size, true); -// Sleep(); -// xSemaphoreGive(mutex); -// return ret; + // xSemaphoreTake(mutex, portMAX_DELAY); + // Wakeup(); + // auto ret = Write(deviceAddress, ®isterAddress, 1, false); + // ret = Read(deviceAddress, data, size, true); + // Sleep(); + // xSemaphoreGive(mutex); + // return ret; return TwiMaster::ErrorCodes::NoError; } TwiMaster::ErrorCodes TwiMaster::Write(uint8_t deviceAddress, uint8_t registerAddress, const uint8_t* data, size_t size) { -// ASSERT(size <= maxDataSize); -// xSemaphoreTake(mutex, portMAX_DELAY); -// Wakeup(); -// internalBuffer[0] = registerAddress; -// std::memcpy(internalBuffer + 1, data, size); -// auto ret = Write(deviceAddress, internalBuffer, size + 1, true); -// Sleep(); -// xSemaphoreGive(mutex); -// return ret; + // ASSERT(size <= maxDataSize); + // xSemaphoreTake(mutex, portMAX_DELAY); + // Wakeup(); + // internalBuffer[0] = registerAddress; + // std::memcpy(internalBuffer + 1, data, size); + // auto ret = Write(deviceAddress, internalBuffer, size + 1, true); + // Sleep(); + // xSemaphoreGive(mutex); + // return ret; return TwiMaster::ErrorCodes::NoError; } -//TwiMaster::ErrorCodes TwiMaster::Read(uint8_t deviceAddress, uint8_t* buffer, size_t size, bool stop) { -// twiBaseAddress->ADDRESS = deviceAddress; -// twiBaseAddress->TASKS_RESUME = 0x1UL; -// twiBaseAddress->RXD.PTR = (uint32_t) buffer; -// twiBaseAddress->RXD.MAXCNT = size; -// -// twiBaseAddress->TASKS_STARTRX = 1; -// -// while (!twiBaseAddress->EVENTS_RXSTARTED && !twiBaseAddress->EVENTS_ERROR) -// ; -// twiBaseAddress->EVENTS_RXSTARTED = 0x0UL; -// -// txStartedCycleCount = DWT->CYCCNT; -// uint32_t currentCycleCount; -// while (!twiBaseAddress->EVENTS_LASTRX && !twiBaseAddress->EVENTS_ERROR) { -// currentCycleCount = DWT->CYCCNT; -// if ((currentCycleCount - txStartedCycleCount) > HwFreezedDelay) { -// FixHwFreezed(); -// return ErrorCodes::TransactionFailed; -// } -// } -// twiBaseAddress->EVENTS_LASTRX = 0x0UL; -// -// if (stop || twiBaseAddress->EVENTS_ERROR) { -// twiBaseAddress->TASKS_STOP = 0x1UL; -// while (!twiBaseAddress->EVENTS_STOPPED) -// ; -// twiBaseAddress->EVENTS_STOPPED = 0x0UL; -// } else { -// twiBaseAddress->TASKS_SUSPEND = 0x1UL; -// while (!twiBaseAddress->EVENTS_SUSPENDED) -// ; -// twiBaseAddress->EVENTS_SUSPENDED = 0x0UL; -// } -// -// if (twiBaseAddress->EVENTS_ERROR) { -// twiBaseAddress->EVENTS_ERROR = 0x0UL; -// } -// return ErrorCodes::NoError; -//} +// TwiMaster::ErrorCodes TwiMaster::Read(uint8_t deviceAddress, uint8_t* buffer, size_t size, bool stop) { +// twiBaseAddress->ADDRESS = deviceAddress; +// twiBaseAddress->TASKS_RESUME = 0x1UL; +// twiBaseAddress->RXD.PTR = (uint32_t) buffer; +// twiBaseAddress->RXD.MAXCNT = size; +// +// twiBaseAddress->TASKS_STARTRX = 1; +// +// while (!twiBaseAddress->EVENTS_RXSTARTED && !twiBaseAddress->EVENTS_ERROR) +// ; +// twiBaseAddress->EVENTS_RXSTARTED = 0x0UL; +// +// txStartedCycleCount = DWT->CYCCNT; +// uint32_t currentCycleCount; +// while (!twiBaseAddress->EVENTS_LASTRX && !twiBaseAddress->EVENTS_ERROR) { +// currentCycleCount = DWT->CYCCNT; +// if ((currentCycleCount - txStartedCycleCount) > HwFreezedDelay) { +// FixHwFreezed(); +// return ErrorCodes::TransactionFailed; +// } +// } +// twiBaseAddress->EVENTS_LASTRX = 0x0UL; +// +// if (stop || twiBaseAddress->EVENTS_ERROR) { +// twiBaseAddress->TASKS_STOP = 0x1UL; +// while (!twiBaseAddress->EVENTS_STOPPED) +// ; +// twiBaseAddress->EVENTS_STOPPED = 0x0UL; +// } else { +// twiBaseAddress->TASKS_SUSPEND = 0x1UL; +// while (!twiBaseAddress->EVENTS_SUSPENDED) +// ; +// twiBaseAddress->EVENTS_SUSPENDED = 0x0UL; +// } +// +// if (twiBaseAddress->EVENTS_ERROR) { +// twiBaseAddress->EVENTS_ERROR = 0x0UL; +// } +// return ErrorCodes::NoError; +// } -//TwiMaster::ErrorCodes TwiMaster::Write(uint8_t deviceAddress, const uint8_t* data, size_t size, bool stop) { -// twiBaseAddress->ADDRESS = deviceAddress; -// twiBaseAddress->TASKS_RESUME = 0x1UL; -// twiBaseAddress->TXD.PTR = (uint32_t) data; -// twiBaseAddress->TXD.MAXCNT = size; -// -// twiBaseAddress->TASKS_STARTTX = 1; -// -// while (!twiBaseAddress->EVENTS_TXSTARTED && !twiBaseAddress->EVENTS_ERROR) -// ; -// twiBaseAddress->EVENTS_TXSTARTED = 0x0UL; -// -// txStartedCycleCount = DWT->CYCCNT; -// uint32_t currentCycleCount; -// while (!twiBaseAddress->EVENTS_LASTTX && !twiBaseAddress->EVENTS_ERROR) { -// currentCycleCount = DWT->CYCCNT; -// if ((currentCycleCount - txStartedCycleCount) > HwFreezedDelay) { -// FixHwFreezed(); -// return ErrorCodes::TransactionFailed; -// } -// } -// twiBaseAddress->EVENTS_LASTTX = 0x0UL; -// -// if (stop || twiBaseAddress->EVENTS_ERROR) { -// twiBaseAddress->TASKS_STOP = 0x1UL; -// while (!twiBaseAddress->EVENTS_STOPPED) -// ; -// twiBaseAddress->EVENTS_STOPPED = 0x0UL; -// } else { -// twiBaseAddress->TASKS_SUSPEND = 0x1UL; -// while (!twiBaseAddress->EVENTS_SUSPENDED) -// ; -// twiBaseAddress->EVENTS_SUSPENDED = 0x0UL; -// } -// -// if (twiBaseAddress->EVENTS_ERROR) { -// twiBaseAddress->EVENTS_ERROR = 0x0UL; -// uint32_t error = twiBaseAddress->ERRORSRC; -// twiBaseAddress->ERRORSRC = error; -// } -// -// return ErrorCodes::NoError; -//} +// TwiMaster::ErrorCodes TwiMaster::Write(uint8_t deviceAddress, const uint8_t* data, size_t size, bool stop) { +// twiBaseAddress->ADDRESS = deviceAddress; +// twiBaseAddress->TASKS_RESUME = 0x1UL; +// twiBaseAddress->TXD.PTR = (uint32_t) data; +// twiBaseAddress->TXD.MAXCNT = size; +// +// twiBaseAddress->TASKS_STARTTX = 1; +// +// while (!twiBaseAddress->EVENTS_TXSTARTED && !twiBaseAddress->EVENTS_ERROR) +// ; +// twiBaseAddress->EVENTS_TXSTARTED = 0x0UL; +// +// txStartedCycleCount = DWT->CYCCNT; +// uint32_t currentCycleCount; +// while (!twiBaseAddress->EVENTS_LASTTX && !twiBaseAddress->EVENTS_ERROR) { +// currentCycleCount = DWT->CYCCNT; +// if ((currentCycleCount - txStartedCycleCount) > HwFreezedDelay) { +// FixHwFreezed(); +// return ErrorCodes::TransactionFailed; +// } +// } +// twiBaseAddress->EVENTS_LASTTX = 0x0UL; +// +// if (stop || twiBaseAddress->EVENTS_ERROR) { +// twiBaseAddress->TASKS_STOP = 0x1UL; +// while (!twiBaseAddress->EVENTS_STOPPED) +// ; +// twiBaseAddress->EVENTS_STOPPED = 0x0UL; +// } else { +// twiBaseAddress->TASKS_SUSPEND = 0x1UL; +// while (!twiBaseAddress->EVENTS_SUSPENDED) +// ; +// twiBaseAddress->EVENTS_SUSPENDED = 0x0UL; +// } +// +// if (twiBaseAddress->EVENTS_ERROR) { +// twiBaseAddress->EVENTS_ERROR = 0x0UL; +// uint32_t error = twiBaseAddress->ERRORSRC; +// twiBaseAddress->ERRORSRC = error; +// } +// +// return ErrorCodes::NoError; +// } void TwiMaster::Sleep() { -// twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Disabled << TWIM_ENABLE_ENABLE_Pos); + // twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Disabled << TWIM_ENABLE_ENABLE_Pos); } void TwiMaster::Wakeup() { -// twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Enabled << TWIM_ENABLE_ENABLE_Pos); + // twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Enabled << TWIM_ENABLE_ENABLE_Pos); } /* Sometimes, the TWIM device just freeze and never set the event EVENTS_LASTTX. @@ -176,12 +176,12 @@ void TwiMaster::Wakeup() { * This is just a workaround, and it would be better if we could find a way to prevent * this issue from happening. * */ -//void TwiMaster::FixHwFreezed() { -// NRF_LOG_INFO("I2C device frozen, reinitializing it!"); +// void TwiMaster::FixHwFreezed() { +// NRF_LOG_INFO("I2C device frozen, reinitializing it!"); // -// uint32_t twi_state = NRF_TWI1->ENABLE; +// uint32_t twi_state = NRF_TWI1->ENABLE; // -// Sleep(); +// Sleep(); // -// twiBaseAddress->ENABLE = twi_state; -//} +// twiBaseAddress->ENABLE = twi_state; +// } diff --git a/sim/drivers/TwiMaster.h b/sim/drivers/TwiMaster.h index bc2bd8d..77bb350 100644 --- a/sim/drivers/TwiMaster.h +++ b/sim/drivers/TwiMaster.h @@ -1,6 +1,6 @@ #pragma once #include -//#include +// #include #include // NRF_TWIM_Type #include @@ -20,13 +20,13 @@ namespace Pinetime { void Wakeup(); private: -// ErrorCodes Read(uint8_t deviceAddress, uint8_t* buffer, size_t size, bool stop); -// ErrorCodes Write(uint8_t deviceAddress, const uint8_t* data, size_t size, bool stop); -// void FixHwFreezed(); -// void ConfigurePins() const; + // ErrorCodes Read(uint8_t deviceAddress, uint8_t* buffer, size_t size, bool stop); + // ErrorCodes Write(uint8_t deviceAddress, const uint8_t* data, size_t size, bool stop); + // void FixHwFreezed(); + // void ConfigurePins() const; NRF_TWIM_Type* twiBaseAddress; -// SemaphoreHandle_t mutex = nullptr; + // SemaphoreHandle_t mutex = nullptr; NRF_TWIM_Type* module; uint32_t frequency; uint8_t pinSda; diff --git a/sim/heartratetask/HeartRateTask.cpp b/sim/heartratetask/HeartRateTask.cpp index 21526a1..fcc3f13 100644 --- a/sim/heartratetask/HeartRateTask.cpp +++ b/sim/heartratetask/HeartRateTask.cpp @@ -13,70 +13,70 @@ void HeartRateTask::Start() { messageQueue = xQueueCreate(10, 1); controller.SetHeartRateTask(this); -// if (pdPASS != xTaskCreate(HeartRateTask::Process, "Heartrate", 500, this, 0, &taskHandle)) -// APP_ERROR_HANDLER(NRF_ERROR_NO_MEM); + // if (pdPASS != xTaskCreate(HeartRateTask::Process, "Heartrate", 500, this, 0, &taskHandle)) + // APP_ERROR_HANDLER(NRF_ERROR_NO_MEM); } -//void HeartRateTask::Process(void* instance) { -// auto* app = static_cast(instance); -// app->Work(); -//} +// void HeartRateTask::Process(void* instance) { +// auto* app = static_cast(instance); +// app->Work(); +// } void HeartRateTask::Work() { -// int lastBpm = 0; -// while (true) { -// Messages msg; -// uint32_t delay; -// if (state == States::Running) { -// if (measurementStarted) -// delay = 40; -// else -// delay = 100; -// } else -// delay = portMAX_DELAY; -// -// if (xQueueReceive(messageQueue, &msg, delay)) { -// switch (msg) { -// case Messages::GoToSleep: -// StopMeasurement(); -// state = States::Idle; -// break; -// case Messages::WakeUp: -// state = States::Running; -// if (measurementStarted) { -// lastBpm = 0; -// StartMeasurement(); -// } -// break; -// case Messages::StartMeasurement: -// if (measurementStarted) -// break; -// lastBpm = 0; -// StartMeasurement(); -// measurementStarted = true; -// break; -// case Messages::StopMeasurement: -// if (!measurementStarted) -// break; -// StopMeasurement(); -// measurementStarted = false; -// break; -// } -// } -// -// if (measurementStarted) { -// auto hrs = heartRateSensor.ReadHrs(); -// ppg.Preprocess(hrs); -// auto bpm = ppg.HeartRate(); -// -// if (lastBpm == 0 && bpm == 0) -// controller.Update(Controllers::HeartRateController::States::NotEnoughData, 0); -// if (bpm != 0) { -// lastBpm = bpm; -// controller.Update(Controllers::HeartRateController::States::Running, lastBpm); -// } -// } -// } + // int lastBpm = 0; + // while (true) { + // Messages msg; + // uint32_t delay; + // if (state == States::Running) { + // if (measurementStarted) + // delay = 40; + // else + // delay = 100; + // } else + // delay = portMAX_DELAY; + // + // if (xQueueReceive(messageQueue, &msg, delay)) { + // switch (msg) { + // case Messages::GoToSleep: + // StopMeasurement(); + // state = States::Idle; + // break; + // case Messages::WakeUp: + // state = States::Running; + // if (measurementStarted) { + // lastBpm = 0; + // StartMeasurement(); + // } + // break; + // case Messages::StartMeasurement: + // if (measurementStarted) + // break; + // lastBpm = 0; + // StartMeasurement(); + // measurementStarted = true; + // break; + // case Messages::StopMeasurement: + // if (!measurementStarted) + // break; + // StopMeasurement(); + // measurementStarted = false; + // break; + // } + // } + // + // if (measurementStarted) { + // auto hrs = heartRateSensor.ReadHrs(); + // ppg.Preprocess(hrs); + // auto bpm = ppg.HeartRate(); + // + // if (lastBpm == 0 && bpm == 0) + // controller.Update(Controllers::HeartRateController::States::NotEnoughData, 0); + // if (bpm != 0) { + // lastBpm = bpm; + // controller.Update(Controllers::HeartRateController::States::Running, lastBpm); + // } + // } + // } } void HeartRateTask::PushMessage(HeartRateTask::Messages msg) { @@ -89,13 +89,13 @@ void HeartRateTask::PushMessage(HeartRateTask::Messages msg) { } } -//void HeartRateTask::StartMeasurement() { -// heartRateSensor.Enable(); -// vTaskDelay(100); -// ppg.SetOffset(static_cast(heartRateSensor.ReadHrs())); -//} +// void HeartRateTask::StartMeasurement() { +// heartRateSensor.Enable(); +// vTaskDelay(100); +// ppg.SetOffset(static_cast(heartRateSensor.ReadHrs())); +// } // -//void HeartRateTask::StopMeasurement() { -// heartRateSensor.Disable(); -// vTaskDelay(100); -//} +// void HeartRateTask::StopMeasurement() { +// heartRateSensor.Disable(); +// vTaskDelay(100); +// } diff --git a/sim/heartratetask/HeartRateTask.h b/sim/heartratetask/HeartRateTask.h index 8cd449a..9e4f74c 100644 --- a/sim/heartratetask/HeartRateTask.h +++ b/sim/heartratetask/HeartRateTask.h @@ -1,16 +1,19 @@ #pragma once #include -//#include +// #include #include -//#include + +// #include namespace Pinetime { namespace Drivers { class Hrs3300; } + namespace Controllers { class HeartRateController; } + namespace Applications { class HeartRateTask { public: @@ -23,16 +26,16 @@ namespace Pinetime { private: enum class States : uint8_t { Disabled, Waiting, BackgroundMeasuring, ForegroundMeasuring }; - //static void Process(void* instance); - //void StartMeasurement(); - //void StopMeasurement(); + // static void Process(void* instance); + // void StartMeasurement(); + // void StopMeasurement(); -// TaskHandle_t taskHandle; + // TaskHandle_t taskHandle; QueueHandle_t messageQueue; States state = States::Disabled; Drivers::Hrs3300& heartRateSensor; Controllers::HeartRateController& controller; -// Controllers::Ppg ppg; + // Controllers::Ppg ppg; bool measurementStarted = false; }; diff --git a/sim/nrf_assert.h b/sim/nrf_assert.h index 1391df1..9e0bb5d 100644 --- a/sim/nrf_assert.h +++ b/sim/nrf_assert.h @@ -2,5 +2,5 @@ #include #ifndef ASSERT -#define ASSERT(expr) assert(expr) + #define ASSERT(expr) assert(expr) #endif diff --git a/sim/portmacro_cmsis.cpp b/sim/portmacro_cmsis.cpp index badb24d..eff3305 100644 --- a/sim/portmacro_cmsis.cpp +++ b/sim/portmacro_cmsis.cpp @@ -1,3 +1,4 @@ #include "portmacro_cmsis.h" -void portYIELD_FROM_ISR(BaseType_t) {} +void portYIELD_FROM_ISR(BaseType_t) { +} diff --git a/sim/queue.cpp b/sim/queue.cpp index eafa31b..66f3e8f 100644 --- a/sim/queue.cpp +++ b/sim/queue.cpp @@ -3,9 +3,8 @@ #include #include -QueueHandle_t xQueueCreate(const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize) -{ - Queue_t *xQueue = new Queue_t; +QueueHandle_t xQueueCreate(const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize) { + Queue_t* xQueue = new Queue_t; if (uxItemSize != 1) { throw std::runtime_error("uxItemSize must be 1"); } @@ -13,24 +12,21 @@ QueueHandle_t xQueueCreate(const UBaseType_t uxQueueLength, const UBaseType_t ux return xQueue; } -BaseType_t xQueueSend(QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait) -{ - Queue_t* pxQueue = ( Queue_t * ) xQueue; +BaseType_t xQueueSend(QueueHandle_t xQueue, const void* const pvItemToQueue, TickType_t xTicksToWait) { + Queue_t* pxQueue = (Queue_t*) xQueue; std::lock_guard guard(pxQueue->mutex); - pxQueue->queue.push_back(*reinterpret_cast(pvItemToQueue)); + pxQueue->queue.push_back(*reinterpret_cast(pvItemToQueue)); return true; } -BaseType_t xQueueSendFromISR(QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t *xHigherPriorityTaskWoken) -{ +BaseType_t xQueueSendFromISR(QueueHandle_t xQueue, const void* const pvItemToQueue, BaseType_t* xHigherPriorityTaskWoken) { TickType_t xTicksToWait = 0; *xHigherPriorityTaskWoken = pdFALSE; return xQueueSend(xQueue, pvItemToQueue, 0.0); } -BaseType_t xQueueReceive(QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait) -{ - Queue_t* pxQueue = ( Queue_t * ) xQueue; +BaseType_t xQueueReceive(QueueHandle_t xQueue, void* const pvBuffer, TickType_t xTicksToWait) { + Queue_t* pxQueue = (Queue_t*) xQueue; while (pxQueue->queue.empty()) { if (xTicksToWait <= 25) { return false; @@ -42,17 +38,16 @@ BaseType_t xQueueReceive(QueueHandle_t xQueue, void * const pvBuffer, TickType_t return false; } std::lock_guard guard(pxQueue->mutex); - uint8_t *buf = reinterpret_cast(pvBuffer); + uint8_t* buf = reinterpret_cast(pvBuffer); *buf = pxQueue->queue.at(0); pxQueue->queue.erase(pxQueue->queue.begin()); return true; } -UBaseType_t uxQueueMessagesWaiting(const QueueHandle_t xQueue) -{ +UBaseType_t uxQueueMessagesWaiting(const QueueHandle_t xQueue) { UBaseType_t uxReturn; SDL_assert(xQueue); - Queue_t* pxQueue = ( Queue_t * ) xQueue; + Queue_t* pxQueue = (Queue_t*) xQueue; // taskENTER_CRITICAL(); { std::lock_guard guard(pxQueue->mutex); diff --git a/sim/queue.h b/sim/queue.h index 81a57eb..a0b895c 100644 --- a/sim/queue.h +++ b/sim/queue.h @@ -8,23 +8,29 @@ * returns an QueueHandle_t variable that can then be used as a parameter to * xQueueSend(), xQueueReceive(), etc. */ -typedef void * QueueHandle_t; +typedef void* QueueHandle_t; + struct Queue_t { std::mutex mutex; std::vector queue; - Queue_t() {} - Queue_t(const Queue_t &o) { - queue=o.queue; + + Queue_t() { + } + + Queue_t(const Queue_t& o) { + queue = o.queue; } - Queue_t &operator=(const Queue_t &o) { - queue=o.queue; + + Queue_t& operator=(const Queue_t& o) { + queue = o.queue; return *this; - } + } }; -//using QueueHandle_t = std::vector; + +// using QueueHandle_t = std::vector; QueueHandle_t xQueueCreate(const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize); -BaseType_t xQueueSend(QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait); -BaseType_t xQueueSendFromISR(QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t *xHigherPriorityTaskWoken); -BaseType_t xQueueReceive(QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ); +BaseType_t xQueueSend(QueueHandle_t xQueue, const void* const pvItemToQueue, TickType_t xTicksToWait); +BaseType_t xQueueSendFromISR(QueueHandle_t xQueue, const void* const pvItemToQueue, BaseType_t* xHigherPriorityTaskWoken); +BaseType_t xQueueReceive(QueueHandle_t xQueue, void* const pvBuffer, TickType_t xTicksToWait); UBaseType_t uxQueueMessagesWaiting(const QueueHandle_t xQueue); diff --git a/sim/semphr.cpp b/sim/semphr.cpp index 4dbab2c..e045187 100644 --- a/sim/semphr.cpp +++ b/sim/semphr.cpp @@ -4,15 +4,14 @@ QueueHandle_t xSemaphoreCreateMutex() { SemaphoreHandle_t xSemaphore = xQueueCreate(1, 1); - Queue_t *pxQueue = (Queue_t *)xSemaphore; + Queue_t* pxQueue = (Queue_t*) xSemaphore; // Queue full represents taken semaphore/locked mutex pxQueue->queue.push_back(0); return xSemaphore; } -BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, - TickType_t xTicksToWait) { - Queue_t *pxQueue = (Queue_t *)xSemaphore; +BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait) { + Queue_t* pxQueue = (Queue_t*) xSemaphore; constexpr TickType_t DELAY_BETWEEN_ATTEMPTS = 25; do { if (pxQueue->mutex.try_lock()) { @@ -33,7 +32,7 @@ BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, } BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore) { - Queue_t *pxQueue = (Queue_t *)xSemaphore; + Queue_t* pxQueue = (Queue_t*) xSemaphore; std::lock_guard guard(pxQueue->mutex); if (pxQueue->queue.size() != 1) { throw std::runtime_error("Mutex released without being held"); diff --git a/sim/semphr.h b/sim/semphr.h index 74975d7..cbcaf7f 100644 --- a/sim/semphr.h +++ b/sim/semphr.h @@ -7,5 +7,5 @@ typedef QueueHandle_t SemaphoreHandle_t; QueueHandle_t xSemaphoreCreateMutex(); -BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait); -BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore); +BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait); +BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore); diff --git a/sim/timers.cpp b/sim/timers.cpp index ded5f21..99c5b4d 100644 --- a/sim/timers.cpp +++ b/sim/timers.cpp @@ -1,8 +1,8 @@ #include "timers.h" #include -uint32_t timer_callback_wrapper(uint32_t interval, void *param) { - TimerHandle_t *xTimer = static_cast(param); +uint32_t timer_callback_wrapper(uint32_t interval, void* param) { + TimerHandle_t* xTimer = static_cast(param); if (!xTimer->running) { return 0; } @@ -14,19 +14,20 @@ uint32_t timer_callback_wrapper(uint32_t interval, void *param) { return 0; // cancel timer } -void *pvTimerGetTimerID(const TimerHandle_t &xTimer) { // return pvTimerID from xTimerCreate +void* pvTimerGetTimerID(const TimerHandle_t& xTimer) { // return pvTimerID from xTimerCreate return xTimer.pvTimerID; } -void vTimerSetTimerID(TimerHandle_t &xTimer, void *pvNewID) { + +void vTimerSetTimerID(TimerHandle_t& xTimer, void* pvNewID) { xTimer.pvTimerID = pvNewID; } -TimerHandle_t xTimerCreate(const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - const TickType_t xTimerPeriodInTicks, - const UBaseType_t uxAutoReload, // false=one-shot, true=recurring - void * const pvTimerID, // pointer passed to callback - TimerCallbackFunction_t pxCallbackFunction) -{ +TimerHandle_t +xTimerCreate(const char* const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const TickType_t xTimerPeriodInTicks, + const UBaseType_t uxAutoReload, // false=one-shot, true=recurring + void* const pvTimerID, // pointer passed to callback + TimerCallbackFunction_t pxCallbackFunction) { TimerHandle_t xTimer; xTimer.timer_period_in_ms = pdTICKS_TO_MS(xTimerPeriodInTicks); xTimer.auto_reload = uxAutoReload == pdTRUE; @@ -36,7 +37,7 @@ TimerHandle_t xTimerCreate(const char * const pcTimerName, /*lint !e971 Unqualif return xTimer; } -bool xTimerStart(TimerHandle_t &xTimer, TickType_t xTicksToWait) { +bool xTimerStart(TimerHandle_t& xTimer, TickType_t xTicksToWait) { xTimer.running = true; xTimer.expiry_time = xTaskGetTickCount() + pdMS_TO_TICKS(xTimer.timer_period_in_ms); xTimer.timer_id = SDL_AddTimer(xTimer.timer_period_in_ms, timer_callback_wrapper, &xTimer); @@ -46,7 +47,7 @@ bool xTimerStart(TimerHandle_t &xTimer, TickType_t xTicksToWait) { return xTimer.timer_id != 0; } -bool xTimerChangePeriod(TimerHandle_t &xTimer, TickType_t xNewPeriod, TickType_t xTicksToWait) { +bool xTimerChangePeriod(TimerHandle_t& xTimer, TickType_t xNewPeriod, TickType_t xTicksToWait) { if (xTimer.running) { xTimerStop(xTimer, xTicksToWait); xTimer.timer_period_in_ms = pdTICKS_TO_MS(xNewPeriod); @@ -57,23 +58,22 @@ bool xTimerChangePeriod(TimerHandle_t &xTimer, TickType_t xNewPeriod, TickType_t return true; } -bool xTimerReset(TimerHandle_t &xTimer, TickType_t xTicksToWait) { +bool xTimerReset(TimerHandle_t& xTimer, TickType_t xTicksToWait) { if (xTimer.running) { xTimerStop(xTimer, xTicksToWait); } return xTimerStart(xTimer, xTicksToWait); } -bool xTimerStop(TimerHandle_t &xTimer, TickType_t xTicksToWait) { +bool xTimerStop(TimerHandle_t& xTimer, TickType_t xTicksToWait) { xTimer.running = false; return SDL_RemoveTimer(xTimer.timer_id); } -TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) -{ +TickType_t xTimerGetExpiryTime(TimerHandle_t xTimer) { return xTimer.expiry_time; } -BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) { +BaseType_t xTimerIsTimerActive(TimerHandle_t xTimer) { return xTimer.running; }