From 1c22c38a5d0ce8785e07968620c062c42794c21a Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Wed, 5 Nov 2014 20:02:08 +0100 Subject: [PATCH 01/16] Review some of my waveform switcheroo logic... --- frontend/ui/uimanager.lua | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index f1607ad0d..dc7bb2512 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -6,6 +6,9 @@ local util = require("ffi/util") local DEBUG = require("dbg") local _ = require("gettext") +local UPDATE_MODE_PARTIAL = 0x0 +local UPDATE_MODE_FULL = 0x1 + -- NOTE: Those have been confirmed on Kindle devices. Might be completely different on Kobo (except for AUTO)! local WAVEFORM_MODE_INIT = 0x0 -- Screen goes to white (clears) local WAVEFORM_MODE_DU = 0x1 -- Grey->white/grey->black @@ -25,7 +28,7 @@ local WAVEFORM_MODE_AUTO = 0x101 -- there is only one instance of this local UIManager = { - default_refresh_type = 0, -- 0 for partial refresh, 1 for full refresh + default_refresh_type = UPDATE_MODE_PARTIAL, default_waveform_mode = WAVEFORM_MODE_GC16, -- high fidelity waveform fast_waveform_mode = WAVEFORM_MODE_A2, full_refresh_waveform_mode = WAVEFORM_MODE_GC16, @@ -107,11 +110,14 @@ function UIManager:init() end -- Emulate the stock reader refresh behavior... --[[ - NOTE: For ref, on a Touch (debugPaint is my new best friend): - UI: gc16_fast + NOTE: For ref, on a Touch (debugPaint & a patched strace are your friend!): + UI: flash: gc16_fast, non-flash: auto (prefers gc16_fast) Reader: When flash: if to/from img: gc16, else gc16_fast; when non-flash: auto (seems to prefer gl16_fast); Waiting for marker only on flash On a PW2: - Same as Touch, except reader uses reagl on non-flash, non-flash lasts longer (12 pgs); Always waits for marker + UI: flash: fc16_fast, non-flash: auto (prefers gc16_fast) + Reader: When flash: if to/from img: gc16 (seems to have a larger bias towards this one), else gc16_fast; when non-flash: reagl (w/ UPDATE_MODE_FULL!); Always waits for marker + Note that the bottom status bar is refreshed separately, right after the screen, as a partial, auto (gc16_fast) update, and that's the marker that's waited after... + Non flash lasts longer (dual timeout: 14pgs / 7mins). --]] -- We don't really have an easy way to know if we're refreshing the UI, or a page, or if said page contains an image, so go with the highest fidelity option self.full_refresh_waveform_mode = WAVEFORM_MODE_GC16 @@ -385,12 +391,12 @@ function UIManager:run() local waveform_mode = self.default_waveform_mode if dirty then if force_partial_refresh or force_fast_refresh then - refresh_type = 0 + refresh_type = UPDATE_MODE_PARTIAL elseif force_full_refresh or self.refresh_count == self.FULL_REFRESH_COUNT - 1 then - refresh_type = 1 + refresh_type = UPDATE_MODE_FULL end -- Handle the waveform mode selection... - if refresh_type == 1 then + if refresh_type == UPDATE_MODE_FULL then waveform_mode = self.full_refresh_waveform_mode else waveform_mode = self.partial_refresh_waveform_mode @@ -398,6 +404,10 @@ function UIManager:run() if force_fast_refresh then waveform_mode = self.fast_waveform_mode end + -- And the PW2 REAGL trickery (they're always full refreshes, but there's no black flash) + if refresh_type == UPDATE_MODE_PARTIAL and waveform_mode == WAVEFORM_MODE_REAGL then + refresh_type = UPDATE_MODE_FULL + end if self.update_regions_func then local update_regions = self.update_regions_func() for _, update_region in ipairs(update_regions) do @@ -409,7 +419,8 @@ function UIManager:run() else Screen:refresh(refresh_type, waveform_mode) end - if self.refresh_type == 1 then + -- PW2 REAGL refreshes are always full (but without black flash), but we want to keep our black flash timeout working, so don't reset the count on full REAGL refreshes... + if refresh_type == UPDATE_MODE_FULL and waveform_mode ~= WAVEFORM_MODE_REAGL then self.refresh_count = 0 elseif not force_partial_refresh and not force_full_refresh then self.refresh_count = (self.refresh_count + 1)%self.FULL_REFRESH_COUNT From 13b02cbad9162870bef7eb42e92017ba8f70d193 Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Wed, 5 Nov 2014 21:43:48 +0100 Subject: [PATCH 02/16] Request regal waveform on phoenix & dahlia Depends on the corresponding changes in koreader-base ;) --- frontend/ui/uimanager.lua | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index dc7bb2512..dfb35ce83 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -6,6 +6,7 @@ local util = require("ffi/util") local DEBUG = require("dbg") local _ = require("gettext") +-- cf. koreader-base/ffi-cdecl/include/mxcfb-kindle.h (UPDATE_MODE_* applies to Kobo, too) local UPDATE_MODE_PARTIAL = 0x0 local UPDATE_MODE_FULL = 0x1 @@ -26,6 +27,10 @@ local WAVEFORM_MODE_REAGLD = 0x9 -- Ghost compensation waveform with dit local WAVEFORM_MODE_AUTO = 0x101 +-- Kobo's headers suck, so invent something to avoid magic numbers... +local WAVEFORM_MODE_KOBO_REGAL = 0x7 + + -- there is only one instance of this local UIManager = { default_refresh_type = UPDATE_MODE_PARTIAL, @@ -92,6 +97,15 @@ function UIManager:init() if KOBO_LIGHT_ON_START and tonumber(KOBO_LIGHT_ON_START) > -1 then Device:getPowerDevice():setIntensity( math.max( math.min(KOBO_LIGHT_ON_START,100) ,0) ) end + -- Emulate the stock reader refresh behavior... + self.full_refresh_waveform_mode = WAVEFORM_MODE_GC16 + -- Request regal waveform on devices that support it (Aura & H2O) + if Device.model == "Kobo_phoenix" or Device.model == "Kobo_dahlia" then + self.partial_refresh_waveform_mode = WAVEFORM_MODE_KOBO_REGAL + else + -- See the note in the Kindle code path later, the stock reader might be using WAVEFORM_MODE_AUTO + self.partial_refresh_waveform_mode = WAVEFORM_MODE_GC16 + end elseif Device:isKindle() then self.event_handlers["IntoSS"] = function() self:sendEvent(Event:new("FlushSettings")) @@ -116,7 +130,7 @@ function UIManager:init() On a PW2: UI: flash: fc16_fast, non-flash: auto (prefers gc16_fast) Reader: When flash: if to/from img: gc16 (seems to have a larger bias towards this one), else gc16_fast; when non-flash: reagl (w/ UPDATE_MODE_FULL!); Always waits for marker - Note that the bottom status bar is refreshed separately, right after the screen, as a partial, auto (gc16_fast) update, and that's the marker that's waited after... + Note that the bottom status bar is refreshed separately, right after the screen, as a partial, auto (gc16_fast) update, and it is its marker that's waited after... Non flash lasts longer (dual timeout: 14pgs / 7mins). --]] -- We don't really have an easy way to know if we're refreshing the UI, or a page, or if said page contains an image, so go with the highest fidelity option @@ -405,7 +419,7 @@ function UIManager:run() waveform_mode = self.fast_waveform_mode end -- And the PW2 REAGL trickery (they're always full refreshes, but there's no black flash) - if refresh_type == UPDATE_MODE_PARTIAL and waveform_mode == WAVEFORM_MODE_REAGL then + if refresh_type == UPDATE_MODE_PARTIAL and (waveform_mode == WAVEFORM_MODE_REAGL or waveform_mode == WAVEFORM_MODE_KOBO_REGAL) then refresh_type = UPDATE_MODE_FULL end if self.update_regions_func then @@ -420,7 +434,7 @@ function UIManager:run() Screen:refresh(refresh_type, waveform_mode) end -- PW2 REAGL refreshes are always full (but without black flash), but we want to keep our black flash timeout working, so don't reset the count on full REAGL refreshes... - if refresh_type == UPDATE_MODE_FULL and waveform_mode ~= WAVEFORM_MODE_REAGL then + if refresh_type == UPDATE_MODE_FULL and waveform_mode ~= WAVEFORM_MODE_REAGL and waveform_mode ~= WAVEFORM_MODE_KOBO_REGAL then self.refresh_count = 0 elseif not force_partial_refresh and not force_full_refresh then self.refresh_count = (self.refresh_count + 1)%self.FULL_REFRESH_COUNT From 374d9933550a1a1b65a4ff3819a2e37e44e2a898 Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Thu, 6 Nov 2014 08:44:43 +0100 Subject: [PATCH 03/16] One more thing to look into/fix... --- frontend/ui/uimanager.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index dfb35ce83..0206b64de 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -419,6 +419,7 @@ function UIManager:run() waveform_mode = self.fast_waveform_mode end -- And the PW2 REAGL trickery (they're always full refreshes, but there's no black flash) + -- FIXME: Possibly a bad idea if self.update_regions_func is set and we actually really want a partial update? if refresh_type == UPDATE_MODE_PARTIAL and (waveform_mode == WAVEFORM_MODE_REAGL or waveform_mode == WAVEFORM_MODE_KOBO_REGAL) then refresh_type = UPDATE_MODE_FULL end From 25adccbcd678b718640dbdc4fce0164e32b8075d Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Thu, 6 Nov 2014 09:51:20 +0100 Subject: [PATCH 04/16] More notes for tomorrow --- frontend/ui/uimanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index 0206b64de..12b78dc66 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -419,7 +419,7 @@ function UIManager:run() waveform_mode = self.fast_waveform_mode end -- And the PW2 REAGL trickery (they're always full refreshes, but there's no black flash) - -- FIXME: Possibly a bad idea if self.update_regions_func is set and we actually really want a partial update? + -- FIXME: Possibly a bad idea if self.update_regions_func is set and we actually really want a partial update? Fallback to default_waveform_mode (or GC16_FAST on Kindle) if refresh_type == UPDATE_MODE_PARTIAL and (waveform_mode == WAVEFORM_MODE_REAGL or waveform_mode == WAVEFORM_MODE_KOBO_REGAL) then refresh_type = UPDATE_MODE_FULL end From b3137736c83ea0822dc32fc004291df27ec28c92 Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Fri, 7 Nov 2014 00:17:00 +0100 Subject: [PATCH 05/16] Don't highjack regional updates on REAGL devices We wouldn't want those to become full updates ;). Also apply an optionally different waveform mode for such partial, regional updates (right now, only Kindle devices make use of this finer grained control). --- frontend/ui/uimanager.lua | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index 12b78dc66..aadef9561 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -35,7 +35,7 @@ local WAVEFORM_MODE_KOBO_REGAL = 0x7 local UIManager = { default_refresh_type = UPDATE_MODE_PARTIAL, default_waveform_mode = WAVEFORM_MODE_GC16, -- high fidelity waveform - fast_waveform_mode = WAVEFORM_MODE_A2, + fast_waveform_mode = WAVEFORM_MODE_A2, -- FIXME: Is this OK on Kobo? full_refresh_waveform_mode = WAVEFORM_MODE_GC16, partial_refresh_waveform_mode = WAVEFORM_MODE_GC16, -- force to repaint all the widget is stack, will be reset to false @@ -99,13 +99,15 @@ function UIManager:init() end -- Emulate the stock reader refresh behavior... self.full_refresh_waveform_mode = WAVEFORM_MODE_GC16 - -- Request regal waveform on devices that support it (Aura & H2O) + -- Request REGAL waveform on devices that support it (Aura & H2O) if Device.model == "Kobo_phoenix" or Device.model == "Kobo_dahlia" then self.partial_refresh_waveform_mode = WAVEFORM_MODE_KOBO_REGAL else - -- See the note in the Kindle code path later, the stock reader might be using WAVEFORM_MODE_AUTO + -- See the note in the Kindle code path later, the stock reader might be using AUTO self.partial_refresh_waveform_mode = WAVEFORM_MODE_GC16 end + -- NOTE: Mostly from lack of data, don't try anything fancier with our PARTIAL, regional updates... + --self.default_waveform_mode = WAVEFORM_MODE_AUTO elseif Device:isKindle() then self.event_handlers["IntoSS"] = function() self:sendEvent(Event:new("FlushSettings")) @@ -125,12 +127,12 @@ function UIManager:init() -- Emulate the stock reader refresh behavior... --[[ NOTE: For ref, on a Touch (debugPaint & a patched strace are your friend!): - UI: flash: gc16_fast, non-flash: auto (prefers gc16_fast) - Reader: When flash: if to/from img: gc16, else gc16_fast; when non-flash: auto (seems to prefer gl16_fast); Waiting for marker only on flash + UI: flash: GC16_FAST, non-flash: AUTO (prefers GC16_FAST) + Reader: When flash: if to/from img: GC16, else GC16_FAST; when non-flash: AUTO (seems to prefer GL16_FAST); Waiting for marker only on flash On a PW2: - UI: flash: fc16_fast, non-flash: auto (prefers gc16_fast) - Reader: When flash: if to/from img: gc16 (seems to have a larger bias towards this one), else gc16_fast; when non-flash: reagl (w/ UPDATE_MODE_FULL!); Always waits for marker - Note that the bottom status bar is refreshed separately, right after the screen, as a partial, auto (gc16_fast) update, and it is its marker that's waited after... + UI: flash: GC16_FAST, non-flash: AUTO (prefers GC16_FAST) + Reader: When flash: if to/from img: GC16, else GC16_FAST; when non-flash: REAGL (w/ UPDATE_MODE_FULL!); Always waits for marker + Note that the bottom status bar region is refreshed separately, right after the screen, as a PARTIAL, AUTO (GC16_FAST) update, and it's this marker that's waited after... Non flash lasts longer (dual timeout: 14pgs / 7mins). --]] -- We don't really have an easy way to know if we're refreshing the UI, or a page, or if said page contains an image, so go with the highest fidelity option @@ -140,9 +142,11 @@ function UIManager:init() self.partial_refresh_waveform_mode = WAVEFORM_MODE_REAGL else self.partial_refresh_waveform_mode = WAVEFORM_MODE_GL16_FAST - -- NOTE: Or we could go back to what KOReader did before fa55acc in koreader-base, which was also use WAVEFORM_MODE_AUTO ;). I have *no* idea how the driver makes its choice though... + -- NOTE: Or we could go back to what KOReader did before fa55acc in koreader-base, which was also to use AUTO ;). I have *no* idea how the driver makes its choice though... --self.partial_refresh_waveform_mode = WAVEFORM_MODE_AUTO end + -- Default to GC16_FAST (will be used for PARTIAL, regional updates) + self.default_waveform_mode = WAVEFORM_MODE_GC16_FAST end end @@ -418,11 +422,16 @@ function UIManager:run() if force_fast_refresh then waveform_mode = self.fast_waveform_mode end - -- And the PW2 REAGL trickery (they're always full refreshes, but there's no black flash) - -- FIXME: Possibly a bad idea if self.update_regions_func is set and we actually really want a partial update? Fallback to default_waveform_mode (or GC16_FAST on Kindle) - if refresh_type == UPDATE_MODE_PARTIAL and (waveform_mode == WAVEFORM_MODE_REAGL or waveform_mode == WAVEFORM_MODE_KOBO_REGAL) then + -- If the device is REAGL-aware, and we're doing a reader refresh (i.e., PARTIAL, but not regional), apply some trickery to match the stock reader's behavior (REAGL updates are always FULL, but there's no black flash) + if not self.update_regions_func and refresh_type == UPDATE_MODE_PARTIAL and (waveform_mode == WAVEFORM_MODE_REAGL or waveform_mode == WAVEFORM_MODE_KOBO_REGAL) then refresh_type = UPDATE_MODE_FULL end + -- If we truly asked for a PARTIAL, regional update, it's likely for an UI element, fall back to the default waveform mode, which is tailored per-device to hopefully be more appropriate than the one we use in the reader + if self.update_regions_func and refresh_type == UPDATE_MODE_PARTIAL and not force_fast_refresh then + -- NOTE: Using default_waveform_mode might seem counter-intuitive when we have partial_refresh_waveform_mode, but partial_refresh_waveform_mode is mostly there as a means to flag REGAL-aware devices ;). + -- Here, we're actually interested in handling regional updates (which happen to be PARTIAL by definition), and not 'PARTIAL' updates that actually refresh the whole screen. + waveform_mode = self.default_waveform_mode + end if self.update_regions_func then local update_regions = self.update_regions_func() for _, update_region in ipairs(update_regions) do @@ -434,7 +443,7 @@ function UIManager:run() else Screen:refresh(refresh_type, waveform_mode) end - -- PW2 REAGL refreshes are always full (but without black flash), but we want to keep our black flash timeout working, so don't reset the count on full REAGL refreshes... + -- REAGL refreshes are always FULL (but without a black flash), but we want to keep our black flash timeout working, so don't reset the count on FULL REAGL refreshes... if refresh_type == UPDATE_MODE_FULL and waveform_mode ~= WAVEFORM_MODE_REAGL and waveform_mode ~= WAVEFORM_MODE_KOBO_REGAL then self.refresh_count = 0 elseif not force_partial_refresh and not force_full_refresh then From 76c3a3aa4425b8ddee62701b42bd65e632054703 Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Fri, 7 Nov 2014 00:21:08 +0100 Subject: [PATCH 06/16] Minor comment tweaks --- frontend/ui/uimanager.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index aadef9561..5300389d7 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -426,9 +426,9 @@ function UIManager:run() if not self.update_regions_func and refresh_type == UPDATE_MODE_PARTIAL and (waveform_mode == WAVEFORM_MODE_REAGL or waveform_mode == WAVEFORM_MODE_KOBO_REGAL) then refresh_type = UPDATE_MODE_FULL end - -- If we truly asked for a PARTIAL, regional update, it's likely for an UI element, fall back to the default waveform mode, which is tailored per-device to hopefully be more appropriate than the one we use in the reader + -- If we truly asked for a PARTIAL, regional update, it's likely for an UI element, so fall back to the default waveform mode, which is tailored per-device to hopefully be more appropriate than the one we use in the reader if self.update_regions_func and refresh_type == UPDATE_MODE_PARTIAL and not force_fast_refresh then - -- NOTE: Using default_waveform_mode might seem counter-intuitive when we have partial_refresh_waveform_mode, but partial_refresh_waveform_mode is mostly there as a means to flag REGAL-aware devices ;). + -- NOTE: Using default_waveform_mode might seem counter-intuitive when we have partial_refresh_waveform_mode, but partial_refresh_waveform_mode is mostly there as a means to flag REAGL-aware devices ;). -- Here, we're actually interested in handling regional updates (which happen to be PARTIAL by definition), and not 'PARTIAL' updates that actually refresh the whole screen. waveform_mode = self.default_waveform_mode end @@ -443,7 +443,7 @@ function UIManager:run() else Screen:refresh(refresh_type, waveform_mode) end - -- REAGL refreshes are always FULL (but without a black flash), but we want to keep our black flash timeout working, so don't reset the count on FULL REAGL refreshes... + -- REAGL refreshes are always FULL (but without a black flash), but we want to keep our black flash timeout working, so don't reset the counter on FULL REAGL refreshes... if refresh_type == UPDATE_MODE_FULL and waveform_mode ~= WAVEFORM_MODE_REAGL and waveform_mode ~= WAVEFORM_MODE_KOBO_REGAL then self.refresh_count = 0 elseif not force_partial_refresh and not force_full_refresh then From df965eb534b0ff9f4bea5a8d9e7147f0e5a78dd4 Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Fri, 7 Nov 2014 00:47:47 +0100 Subject: [PATCH 07/16] Dry-coded skeleton detection of the KT2 & KV FIXME! Needs actual confirmation from people with the HW!! Once that's done, some device checks will probably need to be udated in the codebase to take those new devices into account ;). --- frontend/device/kindle/device.lua | 53 +++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/frontend/device/kindle/device.lua b/frontend/device/kindle/device.lua index 8de7d86b2..dd0201de4 100644 --- a/frontend/device/kindle/device.lua +++ b/frontend/device/kindle/device.lua @@ -53,6 +53,22 @@ local KindlePaperWhite2 = Kindle:new{ touch_dev = "/dev/input/event1", } +local KindleBasic = Kindle:new{ + model = "KindleBasic", + isTouchDevice = yes, + -- FIXME! + touch_dev = "/dev/input/event0", +} + +local KindleVoyage = Kindle:new{ + model = "KindleVoyage", + isTouchDevice = yes, + hasFrontlight = yes, + display_dpi = 230, + -- FIXME! + touch_dev = "/dev/input/event1", +} + function Kindle2:init() self.screen = require("device/screen"):new{device = self} self.input = require("device/input"):new{ @@ -149,6 +165,35 @@ function KindlePaperWhite2:init() self.input.open("/dev/input/event1") end +-- FIXME! +function KindleBasic:init() + self.screen = require("device/screen"):new{device = self} + self.powerd = require("device/kindle/powerd"):new{ + device = self, + batt_capacity_file = "/sys/devices/system/yoshi_battery/yoshi_battery0/battery_capacity", + is_charging_file = "/sys/devices/platform/aplite_charger.0/charging", + } + + Kindle.init(self) + + self.input.open("/dev/input/event0") +end + +-- FIXME! +function KindleVoyage:init() + self.screen = require("device/screen"):new{device = self} + self.powerd = require("device/kindle/powerd"):new{ + device = self, + fl_intensity_file = "/sys/class/backlight/max77696-bl/brightness", + batt_capacity_file = "/sys/devices/system/yoshi_battery/yoshi_battery0/battery_capacity", + is_charging_file = "/sys/devices/platform/aplite_charger.0/charging", + } + + Kindle.init(self) + + self.input.open("/dev/input/event1") +end + --[[ Test if a kindle device has Special Offers --]] @@ -188,6 +233,8 @@ function KindleTouch:exit() end KindlePaperWhite.exit = KindleTouch.exit KindlePaperWhite2.exit = KindleTouch.exit +KindleBasic.exit = KindleTouch.exit +KindleVoyage.exit = KindleTouch.exit function Kindle3:exit() -- send double menu key press events to trigger screen refresh @@ -223,6 +270,8 @@ local touch_set = Set { "0F", "11", "10", "12" } local pw_set = Set { "24", "1B", "1D", "1F", "1C", "20" } local pw2_set = Set { "D4", "5A", "D5", "D6", "D7", "D8", "F2", "17", "60", "F4", "F9", "62", "61", "5F" } +local kt2_set = Set { "C6" } +local kv_set = Set { "13", "54" } if k2_set[kindle_devcode] then return Kindle2 @@ -240,6 +289,10 @@ elseif pw_set[kindle_devcode] then return KindlePaperWhite elseif pw2_set[kindle_devcode] then return KindlePaperWhite2 +elseif kt2_set[kindle_devcode] then + return KindleBasic +elseif kv_set[kindle_devcode] then + return KindleVoyage end error("unknown Kindle model "..kindle_devcode) From a9d1c860fd6ec2b86a69629ebc76880e69cebea7 Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Fri, 7 Nov 2014 00:56:10 +0100 Subject: [PATCH 08/16] Sigh. --- frontend/device/kindle/device.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/device/kindle/device.lua b/frontend/device/kindle/device.lua index dd0201de4..73fb34de2 100644 --- a/frontend/device/kindle/device.lua +++ b/frontend/device/kindle/device.lua @@ -64,7 +64,7 @@ local KindleVoyage = Kindle:new{ model = "KindleVoyage", isTouchDevice = yes, hasFrontlight = yes, - display_dpi = 230, + display_dpi = 300, -- FIXME! touch_dev = "/dev/input/event1", } From ed6f027d6810f4dca48bcfafbd58791f930b3d7e Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Fri, 7 Nov 2014 16:53:56 +0100 Subject: [PATCH 09/16] Whee, the eink driver was updated for the KT2/KV! --- frontend/ui/uimanager.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index 5300389d7..6ef99e215 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -24,6 +24,10 @@ local WAVEFORM_MODE_DU4 = 0x7 -- Medium fidelity 4 level of gray dire -- Kindle PW2 local WAVEFORM_MODE_REAGL = 0x8 -- Ghost compensation waveform local WAVEFORM_MODE_REAGLD = 0x9 -- Ghost compensation waveform with dithering +-- Kindle Basic/Kindle Voyage +local WAVEFORM_MODE_GL4 = 0xA -- 2-bit from white transition +-- TODO: Use me in night mode on those devices! +local WAVEFORM_MODE_GL16_INV = 0xB -- High fidelity for black transition local WAVEFORM_MODE_AUTO = 0x101 From d488ca43fa1544fd03f082ec14ce06afd6b4db96 Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Fri, 7 Nov 2014 17:17:02 +0100 Subject: [PATCH 10/16] Some potentially fun stuff TODO :) --- frontend/device/kindle/device.lua | 1 + frontend/ui/uimanager.lua | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/device/kindle/device.lua b/frontend/device/kindle/device.lua index 73fb34de2..ed1234f13 100644 --- a/frontend/device/kindle/device.lua +++ b/frontend/device/kindle/device.lua @@ -192,6 +192,7 @@ function KindleVoyage:init() Kindle.init(self) self.input.open("/dev/input/event1") + -- TODO: Handle the page turn 'buttons'! end --[[ diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index 6ef99e215..73823d1ab 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -26,7 +26,7 @@ local WAVEFORM_MODE_REAGL = 0x8 -- Ghost compensation waveform local WAVEFORM_MODE_REAGLD = 0x9 -- Ghost compensation waveform with dithering -- Kindle Basic/Kindle Voyage local WAVEFORM_MODE_GL4 = 0xA -- 2-bit from white transition --- TODO: Use me in night mode on those devices! +-- TODO: Use me in night mode on those devices? local WAVEFORM_MODE_GL16_INV = 0xB -- High fidelity for black transition local WAVEFORM_MODE_AUTO = 0x101 From cd7e9c32571c20489f9d62eb5e313e4e629ca05b Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Fri, 7 Nov 2014 21:05:56 +0100 Subject: [PATCH 11/16] First stab at revamping the wait for marker stuff WIP, untested, can probably simplified some more. Good news is, it should be smarter, and thus provide a smoother user experience :). Relies on the relevant changes in base. --- frontend/device/screen.lua | 4 ++-- frontend/ui/uimanager.lua | 35 ++++++++++++++++++++++++++--------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/frontend/device/screen.lua b/frontend/device/screen.lua index d755bb3cc..1f6f40ec8 100644 --- a/frontend/device/screen.lua +++ b/frontend/device/screen.lua @@ -78,13 +78,13 @@ function Screen:setViewport(viewport) self.viewport.w, self.viewport.h) end -function Screen:refresh(refresh_type, waveform_mode, x, y, w, h) +function Screen:refresh(refresh_type, waveform_mode, wait_for_marker, x, y, w, h) if self.viewport and x and y then -- adapt to viewport x = x + self.viewport.x y = y + self.viewport.y end - self.fb:refresh(refresh_type, waveform_mode, x, y, w, h) + self.fb:refresh(refresh_type, waveform_mode, wait_for_marker, x, y, w, h) end function Screen:getSize() diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index 73823d1ab..c280659ac 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -42,6 +42,7 @@ local UIManager = { fast_waveform_mode = WAVEFORM_MODE_A2, -- FIXME: Is this OK on Kobo? full_refresh_waveform_mode = WAVEFORM_MODE_GC16, partial_refresh_waveform_mode = WAVEFORM_MODE_GC16, + wait_for_every_marker = false, -- force to repaint all the widget is stack, will be reset to false -- after each ui loop repaint_all = false, @@ -101,17 +102,19 @@ function UIManager:init() if KOBO_LIGHT_ON_START and tonumber(KOBO_LIGHT_ON_START) > -1 then Device:getPowerDevice():setIntensity( math.max( math.min(KOBO_LIGHT_ON_START,100) ,0) ) end - -- Emulate the stock reader refresh behavior... + -- Emulate the stock reader's refresh behavior... self.full_refresh_waveform_mode = WAVEFORM_MODE_GC16 - -- Request REGAL waveform on devices that support it (Aura & H2O) + -- Request REGAL waveform mode on devices that support it (Aura & H2O) if Device.model == "Kobo_phoenix" or Device.model == "Kobo_dahlia" then self.partial_refresh_waveform_mode = WAVEFORM_MODE_KOBO_REGAL + self.wait_for_every_marker = true else -- See the note in the Kindle code path later, the stock reader might be using AUTO self.partial_refresh_waveform_mode = WAVEFORM_MODE_GC16 + self.wait_for_every_marker = false end - -- NOTE: Mostly from lack of data, don't try anything fancier with our PARTIAL, regional updates... - --self.default_waveform_mode = WAVEFORM_MODE_AUTO + -- Let the driver decide what to do with PARTIAL, regional updates... + self.default_waveform_mode = WAVEFORM_MODE_AUTO elseif Device:isKindle() then self.event_handlers["IntoSS"] = function() self:sendEvent(Event:new("FlushSettings")) @@ -128,7 +131,7 @@ function UIManager:init() Device:usbPlugOut() self:sendEvent(Event:new("NotCharging")) end - -- Emulate the stock reader refresh behavior... + -- Emulate the stock reader's refresh behavior... --[[ NOTE: For ref, on a Touch (debugPaint & a patched strace are your friend!): UI: flash: GC16_FAST, non-flash: AUTO (prefers GC16_FAST) @@ -140,14 +143,19 @@ function UIManager:init() Non flash lasts longer (dual timeout: 14pgs / 7mins). --]] -- We don't really have an easy way to know if we're refreshing the UI, or a page, or if said page contains an image, so go with the highest fidelity option + -- We spend much more time in the reader than the UI, and our UI isn't very graphic anyway, so we'll follow the reader's behaviour above all self.full_refresh_waveform_mode = WAVEFORM_MODE_GC16 - -- We spend much more time in the reader than the UI, and our UI isn't very graphic anyway, so go with the reader behavior - if Device.model == "KindlePaperWhite2" then + -- Request REAGL waveform mode on devices that support it (PW2, KT2, KV) [FIXME: Is that actually true of the KT2?] + if Device.model == "KindlePaperWhite2" or Device.model == "KindleBasic" or Device.model == "KindleVoyage" then self.partial_refresh_waveform_mode = WAVEFORM_MODE_REAGL + -- We need to wait for every update marker when using REAGL waveform modes + self.wait_for_every_marker = true else self.partial_refresh_waveform_mode = WAVEFORM_MODE_GL16_FAST -- NOTE: Or we could go back to what KOReader did before fa55acc in koreader-base, which was also to use AUTO ;). I have *no* idea how the driver makes its choice though... --self.partial_refresh_waveform_mode = WAVEFORM_MODE_AUTO + -- Only wait for update markers on FULL updates + self.wait_for_every_marker = false end -- Default to GC16_FAST (will be used for PARTIAL, regional updates) self.default_waveform_mode = WAVEFORM_MODE_GC16_FAST @@ -411,6 +419,7 @@ function UIManager:run() local refresh_type = self.default_refresh_type local waveform_mode = self.default_waveform_mode + local wait_for_marker = self.wait_for_every_marker if dirty then if force_partial_refresh or force_fast_refresh then refresh_type = UPDATE_MODE_PARTIAL @@ -436,16 +445,24 @@ function UIManager:run() -- Here, we're actually interested in handling regional updates (which happen to be PARTIAL by definition), and not 'PARTIAL' updates that actually refresh the whole screen. waveform_mode = self.default_waveform_mode end + -- If the update is FULL or REAGL, wait for the previous update marker! + -- FIXME: Given the previous tests, could be folded into only check for UPDATE_FULL, in which case it can move to framebuffer_linux, and the whole wait_for_* can go away? + -- Except the fact that we probably need to wait for submission for partials on Kindle... + if refresh_type == UPDATE_MODE_FULL or (waveform_mode == WAVEFORM_MODE_REAGL or waveform_mode == WAVEFORM_MODE_KOBO_REGAL) then + wait_for_marker = true + else + wait_for_marker = false + end if self.update_regions_func then local update_regions = self.update_regions_func() for _, update_region in ipairs(update_regions) do -- in some rare cases update region has 1 pixel offset - Screen:refresh(refresh_type, waveform_mode, + Screen:refresh(refresh_type, waveform_mode, wait_for_marker, update_region.x-1, update_region.y-1, update_region.w+2, update_region.h+2) end else - Screen:refresh(refresh_type, waveform_mode) + Screen:refresh(refresh_type, waveform_mode, wait_for_marker) end -- REAGL refreshes are always FULL (but without a black flash), but we want to keep our black flash timeout working, so don't reset the counter on FULL REAGL refreshes... if refresh_type == UPDATE_MODE_FULL and waveform_mode ~= WAVEFORM_MODE_REAGL and waveform_mode ~= WAVEFORM_MODE_KOBO_REGAL then From d340159de8191245f029ab9dfe6514ecffa38784 Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Fri, 7 Nov 2014 22:18:22 +0100 Subject: [PATCH 12/16] Simplify the whole wait_for_marker commit. Companion commit to the same stuff in base ;). --- frontend/ui/uimanager.lua | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index c280659ac..1a3552fb4 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -107,6 +107,7 @@ function UIManager:init() -- Request REGAL waveform mode on devices that support it (Aura & H2O) if Device.model == "Kobo_phoenix" or Device.model == "Kobo_dahlia" then self.partial_refresh_waveform_mode = WAVEFORM_MODE_KOBO_REGAL + -- Since Kobo doesn't have MXCFB_WAIT_FOR_UPDATE_SUBMISSION, enabling this currently has no effect :). self.wait_for_every_marker = true else -- See the note in the Kindle code path later, the stock reader might be using AUTO @@ -148,7 +149,7 @@ function UIManager:init() -- Request REAGL waveform mode on devices that support it (PW2, KT2, KV) [FIXME: Is that actually true of the KT2?] if Device.model == "KindlePaperWhite2" or Device.model == "KindleBasic" or Device.model == "KindleVoyage" then self.partial_refresh_waveform_mode = WAVEFORM_MODE_REAGL - -- We need to wait for every update marker when using REAGL waveform modes + -- We need to wait for every update marker when using REAGL waveform modes. That mostly means we always use MXCFB_WAIT_FOR_UPDATE_SUBMISSION. self.wait_for_every_marker = true else self.partial_refresh_waveform_mode = WAVEFORM_MODE_GL16_FAST @@ -445,14 +446,6 @@ function UIManager:run() -- Here, we're actually interested in handling regional updates (which happen to be PARTIAL by definition), and not 'PARTIAL' updates that actually refresh the whole screen. waveform_mode = self.default_waveform_mode end - -- If the update is FULL or REAGL, wait for the previous update marker! - -- FIXME: Given the previous tests, could be folded into only check for UPDATE_FULL, in which case it can move to framebuffer_linux, and the whole wait_for_* can go away? - -- Except the fact that we probably need to wait for submission for partials on Kindle... - if refresh_type == UPDATE_MODE_FULL or (waveform_mode == WAVEFORM_MODE_REAGL or waveform_mode == WAVEFORM_MODE_KOBO_REGAL) then - wait_for_marker = true - else - wait_for_marker = false - end if self.update_regions_func then local update_regions = self.update_regions_func() for _, update_region in ipairs(update_regions) do From 3e9f2b06a3dc580dc0d1087e51c52b59a2203c7b Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Fri, 7 Nov 2014 23:31:34 +0100 Subject: [PATCH 13/16] Fix Wario battery/charger detection Not sure how we didn't catch that one sooner... ;p --- frontend/device/kindle/device.lua | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/frontend/device/kindle/device.lua b/frontend/device/kindle/device.lua index ed1234f13..801d1f190 100644 --- a/frontend/device/kindle/device.lua +++ b/frontend/device/kindle/device.lua @@ -156,8 +156,8 @@ function KindlePaperWhite2:init() self.powerd = require("device/kindle/powerd"):new{ device = self, fl_intensity_file = "/sys/class/backlight/max77696-bl/brightness", - batt_capacity_file = "/sys/devices/system/yoshi_battery/yoshi_battery0/battery_capacity", - is_charging_file = "/sys/devices/platform/aplite_charger.0/charging", + batt_capacity_file = "/sys/devices/system/wario_battery/wario_battery0/battery_capacity", + is_charging_file = "/sys/devices/system/wario_charger/wario_charger0/charging", } Kindle.init(self) @@ -165,34 +165,33 @@ function KindlePaperWhite2:init() self.input.open("/dev/input/event1") end --- FIXME! function KindleBasic:init() self.screen = require("device/screen"):new{device = self} self.powerd = require("device/kindle/powerd"):new{ device = self, - batt_capacity_file = "/sys/devices/system/yoshi_battery/yoshi_battery0/battery_capacity", - is_charging_file = "/sys/devices/platform/aplite_charger.0/charging", + batt_capacity_file = "/sys/devices/system/wario_battery/wario_battery0/battery_capacity", + is_charging_file = "/sys/devices/system/wario_charger/wario_charger0/charging", } Kindle.init(self) + -- FIXME! self.input.open("/dev/input/event0") end --- FIXME! function KindleVoyage:init() self.screen = require("device/screen"):new{device = self} self.powerd = require("device/kindle/powerd"):new{ device = self, fl_intensity_file = "/sys/class/backlight/max77696-bl/brightness", - batt_capacity_file = "/sys/devices/system/yoshi_battery/yoshi_battery0/battery_capacity", - is_charging_file = "/sys/devices/platform/aplite_charger.0/charging", + batt_capacity_file = "/sys/devices/system/wario_battery/wario_battery0/battery_capacity", + is_charging_file = "/sys/devices/system/wario_charger/wario_charger0/charging", } Kindle.init(self) self.input.open("/dev/input/event1") - -- TODO: Handle the page turn 'buttons'! + -- TODO: Handle the page turn 'buttons'! (/dev/input/event2) end --[[ From 52e21416e62640ed65dd01287ea3eddce8fa99e9 Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Sat, 8 Nov 2014 00:09:41 +0100 Subject: [PATCH 14/16] Detect more KV variants --- frontend/device/kindle/device.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/device/kindle/device.lua b/frontend/device/kindle/device.lua index 801d1f190..1f68026ac 100644 --- a/frontend/device/kindle/device.lua +++ b/frontend/device/kindle/device.lua @@ -271,7 +271,7 @@ local pw_set = Set { "24", "1B", "1D", "1F", "1C", "20" } local pw2_set = Set { "D4", "5A", "D5", "D6", "D7", "D8", "F2", "17", "60", "F4", "F9", "62", "61", "5F" } local kt2_set = Set { "C6" } -local kv_set = Set { "13", "54" } +local kv_set = Set { "13", "54", "2A", "4F", "52", "53" } if k2_set[kindle_devcode] then return Kindle2 From e9d5799ce49c37e0bb82e22020e3281a92b53bbc Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Sat, 8 Nov 2014 00:55:44 +0100 Subject: [PATCH 15/16] Add the KT2 & KV to relevant device checks --- frontend/apps/reader/modules/readeractivityindicator.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/apps/reader/modules/readeractivityindicator.lua b/frontend/apps/reader/modules/readeractivityindicator.lua index f8ccdd3a8..14db8aefc 100644 --- a/frontend/apps/reader/modules/readeractivityindicator.lua +++ b/frontend/apps/reader/modules/readeractivityindicator.lua @@ -7,7 +7,7 @@ local ReaderActivityIndicator = EventListener:new{} function ReaderActivityIndicator:init() local dev_mod = Device.model - if dev_mod == "KindlePaperWhite" or dev_mod == "KindlePaperWhite2" or dev_mod == "KindleTouch" then + if dev_mod == "KindlePaperWhite" or dev_mod == "KindlePaperWhite2" or dev_mod == "KindleVoyage" or dev_mod == "KindleBasic" or dev_mod == "KindleTouch" then require "liblipclua" self.lipc_handle = lipc.init("com.github.koreader.activityindicator") end From 5dd9e917b776e1d061dd6c3760bed13037b390b4 Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Sat, 8 Nov 2014 00:58:29 +0100 Subject: [PATCH 16/16] Kill a FIXME :) --- frontend/device/kindle/device.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/device/kindle/device.lua b/frontend/device/kindle/device.lua index 1f68026ac..af9bfdbd5 100644 --- a/frontend/device/kindle/device.lua +++ b/frontend/device/kindle/device.lua @@ -65,7 +65,6 @@ local KindleVoyage = Kindle:new{ isTouchDevice = yes, hasFrontlight = yes, display_dpi = 300, - -- FIXME! touch_dev = "/dev/input/event1", }