{"action":"created","comment":{"url":"https://api.github.com/repos/betaflight/betaflight/pulls/comments/85964752","pull_request_review_id":6647806,"id":85964752,"diff_hunk":"@@ -0,0 +1,1342 @@\n+/*\n+ * This file is part of Cleanflight.\n+ *\n+ * Cleanflight is free software: you can redistribute it and/or modify\n+ * it under the terms of the GNU General Public License as published by\n+ * the Free Software Foundation, either version 3 of the License, or\n+ * (at your option) any later version.\n+ *\n+ * Cleanflight is distributed in the hope that it will be useful,\n+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+ * GNU General Public License for more details.\n+ *\n+ * You should have received a copy of the GNU General Public License\n+ * along with Cleanflight.  If not, see <http://www.gnu.org/licenses/>.\n+ */\n+\n+/*\n+ Created by Marcin Baliniak\n+ OSD-CMS separation by jflyper\n+ */\n+\n+#include <stdbool.h>\n+#include <stdint.h>\n+#include <string.h>\n+#include <ctype.h>\n+\n+#include \"platform.h\"\n+\n+#include \"build/version.h\"\n+\n+#ifdef CMS\n+\n+#include \"drivers/system.h\"\n+\n+#include \"common/typeconversion.h\"\n+\n+#include \"io/cms.h\"\n+#include \"io/cms_types.h\"\n+#ifdef CANVAS\n+#include \"io/canvas.h\"\n+#endif\n+\n+#include \"io/flashfs.h\"\n+#include \"io/osd.h\"\n+#include \"io/display.h\"\n+\n+#include \"fc/config.h\"\n+#include \"fc/rc_controls.h\"\n+#include \"fc/runtime_config.h\"\n+\n+#include \"flight/pid.h\"\n+\n+#include \"config/config_profile.h\"\n+#include \"config/config_master.h\"\n+#include \"config/feature.h\"\n+\n+#include \"io/cms.h\"\n+\n+#include \"build/debug.h\"\n+\n+// Device management\n+\n+#define CMS_MAX_DEVICE 4\n+\n+cmsDeviceInitFuncPtr cmsDeviceInitFunc[CMS_MAX_DEVICE];\n+int cmsDeviceCount;\n+int cmsCurrentDevice = -1;\n+int cmsLastDevice = -1;\n+\n+bool cmsDeviceRegister(cmsDeviceInitFuncPtr func)\n+{\n+    if (cmsDeviceCount == CMS_MAX_DEVICE)\n+        return false;\n+\n+    cmsDeviceInitFunc[cmsDeviceCount++] = func;\n+\n+    return true;\n+}\n+\n+cmsDeviceInitFuncPtr cmsDeviceSelectCurrent(void)\n+{\n+    if (cmsDeviceCount == 0)\n+        return NULL;\n+\n+    if (cmsCurrentDevice < 0)\n+        cmsCurrentDevice = 0;\n+\n+    return cmsDeviceInitFunc[cmsCurrentDevice];\n+}\n+\n+cmsDeviceInitFuncPtr cmsDeviceSelectNext(void)\n+{\n+    if (cmsDeviceCount == 0)\n+        return NULL;\n+\n+    cmsCurrentDevice = (cmsCurrentDevice + 1) % cmsDeviceCount; // -1 Okay\n+\n+    return cmsDeviceInitFunc[cmsCurrentDevice];\n+}\n+\n+#define CMS_UPDATE_INTERVAL 50 // msec\n+\n+// XXX Why is this here? Something wrong?\n+// XXX Something like Drawing Context that holds all state variables would be the way...\n+int8_t lastCursorPos;\n+\n+void cmsScreenClear(displayPort_t *instance)\n+{\n+    instance->vTable->clear();\n+    instance->cleared = true;\n+    lastCursorPos = -1; // XXX Here\n+}\n+\n+void cmsScreenBegin(displayPort_t *instance)\n+{\n+    instance->vTable->begin();\n+    instance->vTable->clear();\n+}\n+\n+void cmsScreenEnd(displayPort_t *instance)\n+{\n+    instance->vTable->end();\n+}\n+\n+int cmsScreenWrite(displayPort_t *instance, uint8_t x, uint8_t y, char *s)\n+{\n+    return instance->vTable->write(x, y, s);\n+}\n+\n+void cmsScreenHeartBeat(displayPort_t *instance)\n+{\n+    if (instance->vTable->heartbeat)\n+        instance->vTable->heartbeat();","path":"src/main/io/cms.c","position":134,"original_position":134,"commit_id":"042096fbb77fec37f191f93496d0964e00c96dc9","original_commit_id":"042096fbb77fec37f191f93496d0964e00c96dc9","user":{"login":"martinbudden","id":194586,"avatar_url":"https://avatars.githubusercontent.com/u/194586?v=3","gravatar_id":"","url":"https://api.github.com/users/martinbudden","html_url":"https://github.com/martinbudden","followers_url":"https://api.github.com/users/martinbudden/followers","following_url":"https://api.github.com/users/martinbudden/following{/other_user}","gists_url":"https://api.github.com/users/martinbudden/gists{/gist_id}","starred_url":"https://api.github.com/users/martinbudden/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/martinbudden/subscriptions","organizations_url":"https://api.github.com/users/martinbudden/orgs","repos_url":"https://api.github.com/users/martinbudden/repos","events_url":"https://api.github.com/users/martinbudden/events{/privacy}","received_events_url":"https://api.github.com/users/martinbudden/received_events","type":"User","site_admin":false},"body":"Rather than have `if (instance->vTable->heartbeat)` just call `instance->vTable->heartbeat();` and ensure vTable is set up with an empty `heartbeat` function - the overhead is about the same and the code is much neater. Likewise with `resync` and `txroom`","created_at":"2016-11-01T16:25:25Z","updated_at":"2016-11-01T16:25:25Z","html_url":"https://github.com/betaflight/betaflight/pull/1422#discussion_r85964752","pull_request_url":"https://api.github.com/repos/betaflight/betaflight/pulls/1422","_links":{"self":{"href":"https://api.github.com/repos/betaflight/betaflight/pulls/comments/85964752"},"html":{"href":"https://github.com/betaflight/betaflight/pull/1422#discussion_r85964752"},"pull_request":{"href":"https://api.github.com/repos/betaflight/betaflight/pulls/1422"}}},"pull_request":{"url":"https://api.github.com/repos/betaflight/betaflight/pulls/1422","id":91418991,"html_url":"https://github.com/betaflight/betaflight/pull/1422","diff_url":"https://github.com/betaflight/betaflight/pull/1422.diff","patch_url":"https://github.com/betaflight/betaflight/pull/1422.patch","issue_url":"https://api.github.com/repos/betaflight/betaflight/issues/1422","number":1422,"state":"open","locked":false,"title":"Configuration Menu System (CMS)","user":{"login":"jflyper","id":14850998,"avatar_url":"https://avatars.githubusercontent.com/u/14850998?v=3","gravatar_id":"","url":"https://api.github.com/users/jflyper","html_url":"https://github.com/jflyper","followers_url":"https://api.github.com/users/jflyper/followers","following_url":"https://api.github.com/users/jflyper/following{/other_user}","gists_url":"https://api.github.com/users/jflyper/gists{/gist_id}","starred_url":"https://api.github.com/users/jflyper/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jflyper/subscriptions","organizations_url":"https://api.github.com/users/jflyper/orgs","repos_url":"https://api.github.com/users/jflyper/repos","events_url":"https://api.github.com/users/jflyper/events{/privacy}","received_events_url":"https://api.github.com/users/jflyper/received_events","type":"User","site_admin":false},"body":"This is a continuation of #1352.\n\nWith enormous help from the community, the CMS is now:\n- Partially separated from OSD; more separation needs CMS data structures to be moved to osd.c.\n- Capable of running on multiple display devices: OSD, UART connected external OSD (MWOSD with CANVAS extension) and I2C OLED; if multiple displays are available simultaneously, they can be switched from one to another.\n\nIntegrated OSD & External MWOSD\n![img_6516](https://cloud.githubusercontent.com/assets/14850998/19816856/f9a6ae16-9d83-11e6-9790-7045c6462df7.JPG)\n\nI2C OLED\n![ca15631e-d757-45da-ab86-4ce4607c54de](https://cloud.githubusercontent.com/assets/14850998/19816865/01bc8c10-9d84-11e6-958f-fe3fb6a5efde.png)\n\nCode branch:\n[https://github.com/jflyper/cleanflight/tree/bfdev-osd-cms-separation-poc](https://github.com/jflyper/cleanflight/tree/bfdev-osd-cms-separation-poc)\n\nMWOSD: (already merged in the current master)\n[https://github.com/ShikOfTheRa/scarab-osd/tree/master](https://github.com/ShikOfTheRa/scarab-osd/tree/master)\n","created_at":"2016-10-28T17:21:01Z","updated_at":"2016-11-01T16:25:25Z","closed_at":null,"merged_at":null,"merge_commit_sha":"55332b3d6f8ab0fdefe1266940e8b7e20f90ad97","assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/betaflight/betaflight/milestones/3","html_url":"https://github.com/betaflight/betaflight/milestones/Betaflight%20v3.1","labels_url":"https://api.github.com/repos/betaflight/betaflight/milestones/3/labels","id":1844374,"number":3,"title":"Betaflight v3.1","description":"v3.1 release\r\n\r\nIncluding:\r\n- config parameters from Cleanflight\r\n- pwm mapping tidy up","creator":{"login":"blckmn","id":6168871,"avatar_url":"https://avatars.githubusercontent.com/u/6168871?v=3","gravatar_id":"","url":"https://api.github.com/users/blckmn","html_url":"https://github.com/blckmn","followers_url":"https://api.github.com/users/blckmn/followers","following_url":"https://api.github.com/users/blckmn/following{/other_user}","gists_url":"https://api.github.com/users/blckmn/gists{/gist_id}","starred_url":"https://api.github.com/users/blckmn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/blckmn/subscriptions","organizations_url":"https://api.github.com/users/blckmn/orgs","repos_url":"https://api.github.com/users/blckmn/repos","events_url":"https://api.github.com/users/blckmn/events{/privacy}","received_events_url":"https://api.github.com/users/blckmn/received_events","type":"User","site_admin":false},"open_issues":13,"closed_issues":90,"state":"open","created_at":"2016-06-23T00:05:58Z","updated_at":"2016-11-01T16:16:40Z","due_on":"2016-11-30T00:00:00Z","closed_at":null},"commits_url":"https://api.github.com/repos/betaflight/betaflight/pulls/1422/commits","review_comments_url":"https://api.github.com/repos/betaflight/betaflight/pulls/1422/comments","review_comment_url":"https://api.github.com/repos/betaflight/betaflight/pulls/comments{/number}","comments_url":"https://api.github.com/repos/betaflight/betaflight/issues/1422/comments","statuses_url":"https://api.github.com/repos/betaflight/betaflight/statuses/042096fbb77fec37f191f93496d0964e00c96dc9","head":{"label":"jflyper:bfdev-osd-cms-separation-poc","ref":"bfdev-osd-cms-separation-poc","sha":"042096fbb77fec37f191f93496d0964e00c96dc9","user":{"login":"jflyper","id":14850998,"avatar_url":"https://avatars.githubusercontent.com/u/14850998?v=3","gravatar_id":"","url":"https://api.github.com/users/jflyper","html_url":"https://github.com/jflyper","followers_url":"https://api.github.com/users/jflyper/followers","following_url":"https://api.github.com/users/jflyper/following{/other_user}","gists_url":"https://api.github.com/users/jflyper/gists{/gist_id}","starred_url":"https://api.github.com/users/jflyper/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jflyper/subscriptions","organizations_url":"https://api.github.com/users/jflyper/orgs","repos_url":"https://api.github.com/users/jflyper/repos","events_url":"https://api.github.com/users/jflyper/events{/privacy}","received_events_url":"https://api.github.com/users/jflyper/received_events","type":"User","site_admin":false},"repo":{"id":52951844,"name":"cleanflight","full_name":"jflyper/cleanflight","owner":{"login":"jflyper","id":14850998,"avatar_url":"https://avatars.githubusercontent.com/u/14850998?v=3","gravatar_id":"","url":"https://api.github.com/users/jflyper","html_url":"https://github.com/jflyper","followers_url":"https://api.github.com/users/jflyper/followers","following_url":"https://api.github.com/users/jflyper/following{/other_user}","gists_url":"https://api.github.com/users/jflyper/gists{/gist_id}","starred_url":"https://api.github.com/users/jflyper/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jflyper/subscriptions","organizations_url":"https://api.github.com/users/jflyper/orgs","repos_url":"https://api.github.com/users/jflyper/repos","events_url":"https://api.github.com/users/jflyper/events{/privacy}","received_events_url":"https://api.github.com/users/jflyper/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jflyper/cleanflight","description":"Clean-code version of the baseflight flight controller firmware","fork":true,"url":"https://api.github.com/repos/jflyper/cleanflight","forks_url":"https://api.github.com/repos/jflyper/cleanflight/forks","keys_url":"https://api.github.com/repos/jflyper/cleanflight/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jflyper/cleanflight/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jflyper/cleanflight/teams","hooks_url":"https://api.github.com/repos/jflyper/cleanflight/hooks","issue_events_url":"https://api.github.com/repos/jflyper/cleanflight/issues/events{/number}","events_url":"https://api.github.com/repos/jflyper/cleanflight/events","assignees_url":"https://api.github.com/repos/jflyper/cleanflight/assignees{/user}","branches_url":"https://api.github.com/repos/jflyper/cleanflight/branches{/branch}","tags_url":"https://api.github.com/repos/jflyper/cleanflight/tags","blobs_url":"https://api.github.com/repos/jflyper/cleanflight/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jflyper/cleanflight/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jflyper/cleanflight/git/refs{/sha}","trees_url":"https://api.github.com/repos/jflyper/cleanflight/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jflyper/cleanflight/statuses/{sha}","languages_url":"https://api.github.com/repos/jflyper/cleanflight/languages","stargazers_url":"https://api.github.com/repos/jflyper/cleanflight/stargazers","contributors_url":"https://api.github.com/repos/jflyper/cleanflight/contributors","subscribers_url":"https://api.github.com/repos/jflyper/cleanflight/subscribers","subscription_url":"https://api.github.com/repos/jflyper/cleanflight/subscription","commits_url":"https://api.github.com/repos/jflyper/cleanflight/commits{/sha}","git_commits_url":"https://api.github.com/repos/jflyper/cleanflight/git/commits{/sha}","comments_url":"https://api.github.com/repos/jflyper/cleanflight/comments{/number}","issue_comment_url":"https://api.github.com/repos/jflyper/cleanflight/issues/comments{/number}","contents_url":"https://api.github.com/repos/jflyper/cleanflight/contents/{+path}","compare_url":"https://api.github.com/repos/jflyper/cleanflight/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jflyper/cleanflight/merges","archive_url":"https://api.github.com/repos/jflyper/cleanflight/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jflyper/cleanflight/downloads","issues_url":"https://api.github.com/repos/jflyper/cleanflight/issues{/number}","pulls_url":"https://api.github.com/repos/jflyper/cleanflight/pulls{/number}","milestones_url":"https://api.github.com/repos/jflyper/cleanflight/milestones{/number}","notifications_url":"https://api.github.com/repos/jflyper/cleanflight/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jflyper/cleanflight/labels{/name}","releases_url":"https://api.github.com/repos/jflyper/cleanflight/releases{/id}","deployments_url":"https://api.github.com/repos/jflyper/cleanflight/deployments","created_at":"2016-03-02T09:47:22Z","updated_at":"2016-04-10T02:03:59Z","pushed_at":"2016-11-01T15:31:18Z","git_url":"git://github.com/jflyper/cleanflight.git","ssh_url":"git@github.com:jflyper/cleanflight.git","clone_url":"https://github.com/jflyper/cleanflight.git","svn_url":"https://github.com/jflyper/cleanflight","homepage":"http://cleanflight.com","size":125355,"stargazers_count":0,"watchers_count":0,"language":"C","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"betaflight:master","ref":"master","sha":"af2a575460c8bb7c699c56a3ddd1886d453e96b6","user":{"login":"betaflight","id":19597933,"avatar_url":"https://avatars.githubusercontent.com/u/19597933?v=3","gravatar_id":"","url":"https://api.github.com/users/betaflight","html_url":"https://github.com/betaflight","followers_url":"https://api.github.com/users/betaflight/followers","following_url":"https://api.github.com/users/betaflight/following{/other_user}","gists_url":"https://api.github.com/users/betaflight/gists{/gist_id}","starred_url":"https://api.github.com/users/betaflight/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/betaflight/subscriptions","organizations_url":"https://api.github.com/users/betaflight/orgs","repos_url":"https://api.github.com/users/betaflight/repos","events_url":"https://api.github.com/users/betaflight/events{/privacy}","received_events_url":"https://api.github.com/users/betaflight/received_events","type":"Organization","site_admin":false},"repo":{"id":37060852,"name":"betaflight","full_name":"betaflight/betaflight","owner":{"login":"betaflight","id":19597933,"avatar_url":"https://avatars.githubusercontent.com/u/19597933?v=3","gravatar_id":"","url":"https://api.github.com/users/betaflight","html_url":"https://github.com/betaflight","followers_url":"https://api.github.com/users/betaflight/followers","following_url":"https://api.github.com/users/betaflight/following{/other_user}","gists_url":"https://api.github.com/users/betaflight/gists{/gist_id}","starred_url":"https://api.github.com/users/betaflight/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/betaflight/subscriptions","organizations_url":"https://api.github.com/users/betaflight/orgs","repos_url":"https://api.github.com/users/betaflight/repos","events_url":"https://api.github.com/users/betaflight/events{/privacy}","received_events_url":"https://api.github.com/users/betaflight/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/betaflight/betaflight","description":"Betaflight Flight Controller Firmware","fork":true,"url":"https://api.github.com/repos/betaflight/betaflight","forks_url":"https://api.github.com/repos/betaflight/betaflight/forks","keys_url":"https://api.github.com/repos/betaflight/betaflight/keys{/key_id}","collaborators_url":"https://api.github.com/repos/betaflight/betaflight/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/betaflight/betaflight/teams","hooks_url":"https://api.github.com/repos/betaflight/betaflight/hooks","issue_events_url":"https://api.github.com/repos/betaflight/betaflight/issues/events{/number}","events_url":"https://api.github.com/repos/betaflight/betaflight/events","assignees_url":"https://api.github.com/repos/betaflight/betaflight/assignees{/user}","branches_url":"https://api.github.com/repos/betaflight/betaflight/branches{/branch}","tags_url":"https://api.github.com/repos/betaflight/betaflight/tags","blobs_url":"https://api.github.com/repos/betaflight/betaflight/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/betaflight/betaflight/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/betaflight/betaflight/git/refs{/sha}","trees_url":"https://api.github.com/repos/betaflight/betaflight/git/trees{/sha}","statuses_url":"https://api.github.com/repos/betaflight/betaflight/statuses/{sha}","languages_url":"https://api.github.com/repos/betaflight/betaflight/languages","stargazers_url":"https://api.github.com/repos/betaflight/betaflight/stargazers","contributors_url":"https://api.github.com/repos/betaflight/betaflight/contributors","subscribers_url":"https://api.github.com/repos/betaflight/betaflight/subscribers","subscription_url":"https://api.github.com/repos/betaflight/betaflight/subscription","commits_url":"https://api.github.com/repos/betaflight/betaflight/commits{/sha}","git_commits_url":"https://api.github.com/repos/betaflight/betaflight/git/commits{/sha}","comments_url":"https://api.github.com/repos/betaflight/betaflight/comments{/number}","issue_comment_url":"https://api.github.com/repos/betaflight/betaflight/issues/comments{/number}","contents_url":"https://api.github.com/repos/betaflight/betaflight/contents/{+path}","compare_url":"https://api.github.com/repos/betaflight/betaflight/compare/{base}...{head}","merges_url":"https://api.github.com/repos/betaflight/betaflight/merges","archive_url":"https://api.github.com/repos/betaflight/betaflight/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/betaflight/betaflight/downloads","issues_url":"https://api.github.com/repos/betaflight/betaflight/issues{/number}","pulls_url":"https://api.github.com/repos/betaflight/betaflight/pulls{/number}","milestones_url":"https://api.github.com/repos/betaflight/betaflight/milestones{/number}","notifications_url":"https://api.github.com/repos/betaflight/betaflight/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/betaflight/betaflight/labels{/name}","releases_url":"https://api.github.com/repos/betaflight/betaflight/releases{/id}","deployments_url":"https://api.github.com/repos/betaflight/betaflight/deployments","created_at":"2015-06-08T10:37:44Z","updated_at":"2016-11-01T13:46:16Z","pushed_at":"2016-11-01T15:31:19Z","git_url":"git://github.com/betaflight/betaflight.git","ssh_url":"git@github.com:betaflight/betaflight.git","clone_url":"https://github.com/betaflight/betaflight.git","svn_url":"https://github.com/betaflight/betaflight","homepage":"","size":153437,"stargazers_count":658,"watchers_count":658,"language":"C","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":272,"mirror_url":null,"open_issues_count":113,"forks":272,"open_issues":113,"watchers":658,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/betaflight/betaflight/pulls/1422"},"html":{"href":"https://github.com/betaflight/betaflight/pull/1422"},"issue":{"href":"https://api.github.com/repos/betaflight/betaflight/issues/1422"},"comments":{"href":"https://api.github.com/repos/betaflight/betaflight/issues/1422/comments"},"review_comments":{"href":"https://api.github.com/repos/betaflight/betaflight/pulls/1422/comments"},"review_comment":{"href":"https://api.github.com/repos/betaflight/betaflight/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/betaflight/betaflight/pulls/1422/commits"},"statuses":{"href":"https://api.github.com/repos/betaflight/betaflight/statuses/042096fbb77fec37f191f93496d0964e00c96dc9"}}}}
{"actor":{"display_login":"martinbudden"}}