This repository has been archived by the owner on Sep 22, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 98
/
screen.lua
259 lines (229 loc) · 8.33 KB
/
screen.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
--[[
Copyright (C) 2011 Hans-Werner Hilse <[email protected]>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
]]--
--[[
Codes for rotation modes:
1 for no rotation,
2 for landscape with bottom on the right side of screen, etc.
2
+--------------+
| +----------+ |
| | | |
| | Freedom! | |
| | | |
| | | |
3 | | | | 1
| | | |
| | | |
| +----------+ |
| |
| |
+--------------+
0
--]]
local WAVEFORM_MODE_INIT = 0x0 -- Screen goes to white (clears)
local WAVEFORM_MODE_DU = 0x1 -- Grey->white/grey->black
local WAVEFORM_MODE_GC16 = 0x2 -- High fidelity (flashing)
local WAVEFORM_MODE_GC4 = WAVEFORM_MODE_GC16 -- For compatibility
local WAVEFORM_MODE_GC16_FAST = 0x3 -- Medium fidelity
local WAVEFORM_MODE_A2 = 0x4 -- Faster but even lower fidelity
local WAVEFORM_MODE_GL16 = 0x5 -- High fidelity from white transition
local WAVEFORM_MODE_GL16_FAST = 0x6 -- Medium fidelity from white transition
local WAVEFORM_MODE_AUTO = 0x101
Screen = {
cur_rotation_mode = 0,
-- these two variabls are used to help switching from framework to reader
native_rotation_mode = nil,
kpv_rotation_mode = nil,
saved_bb = nil,
}
function Screen:refresh(refesh_type, waveform_mode, x, y, w, h)
if x then x = x < 0 and 0 or math.floor(x) end
if y then y = y < 0 and 0 or math.floor(y) end
if w then w = w > G_width and G_width or math.ceil(w) end
if h then h = h > G_height and G_height or math.ceil(h) end
if not waveform_mode then
waveform_mode = WAVEFORM_MODE_GC16
end
fb:refresh(refesh_type, waveform_mode, x, y, w, h)
end
function Screen:setRotationMode(mode)
if mode < 0 or mode > 3 then
Debug("Illegal mode parameter to Screen:setRotatonMode()!")
return
end
self.cur_rotation_mode = mode
-- you have to reopen framebuffer after rotate
fb:setOrientation(self.cur_rotation_mode)
fb:close()
fb = einkfb.open("/dev/fb0")
G_width, G_height = fb:getSize()
end
-- @orien: 1 for clockwise rotate, -1 for anti-clockwise
-- Remember to reread screen resolution after this function call
function Screen:screenRotate(orien)
if orien == "clockwise" then
orien = -1
elseif orien == "anticlockwise" then
orien = 1
else
return
end
self.cur_rotation_mode = (self.cur_rotation_mode + orien) % 4
-- you have to reopen framebuffer after rotate
fb:setOrientation(self.cur_rotation_mode)
fb:close()
fb = einkfb.open("/dev/fb0")
end
function Screen:updateRotationMode()
if util.isEmulated() == 1 then -- in EMU mode always set to 0
self.cur_rotation_mode = 0
else
orie_fd = assert(io.open("/sys/module/eink_fb_hal_broads/parameters/bs_orientation", "r"))
updown_fd = assert(io.open("/sys/module/eink_fb_hal_broads/parameters/bs_upside_down", "r"))
self.cur_rotation_mode = orie_fd:read() + (updown_fd:read() * 2)
end
end
function Screen:saveCurrentBB()
local width, height = G_width, G_height
if not self.saved_bb then
self.saved_bb = Blitbuffer.new(width, height)
end
if self.saved_bb:getWidth() ~= width then
self.saved_bb:free()
self.saved_bb = Blitbuffer.new(width, height)
end
self.saved_bb:blitFullFrom(fb.bb)
end
function Screen:restoreFromSavedBB()
self:restoreFromBB(self.saved_bb)
end
function Screen:getCurrentScreenBB()
local bb = Blitbuffer.new(G_width, G_height)
bb:blitFullFrom(fb.bb)
return bb
end
function Screen:restoreFromBB(bb)
if bb then
fb.bb:blitFullFrom(bb)
else
Debug("Got nil bb in restoreFromSavedBB!")
end
end
function Screen:screenshot()
if util.isEmulated() == 1 then
return
end
local secs, usecs = util.gettime()
self:fb2bmp("/dev/fb0", lfs.currentdir().."/screenshots/"..os.date("%Y%m%d%H%M%S")..".bmp", true, nil)
local nsecs, nusecs = util.gettime()
local diff = nsecs - secs + (nusecs - usecs)/1000000
--self:fb2bmp("/dev/fb0", lfs.currentdir().."/screenshots/"..os.date("%Y%m%d%H%M%S")..".bmp", true, "bzip2 ")
--self:fb2pgm("/dev/fb0", lfs.currentdir().."/screenshots/"..os.date("%Y%m%d%H%M%S")..".pgm", "bzip2 ", 4)
local msg = "Screenshot is ready in "
InfoMessage:inform(msg..string.format("%.2fs ", diff), DINFO_DELAY, 1, MSG_WARN, msg..math.ceil(diff*1000).." milliseconds")
end
-- NuPogodi (02.07.2012): added the functions to save the fb-content in common graphic files - bmp & pgm.
-- ToDo: png, gif ?
function Screen:LE(x) -- converts positive upto 32bit-number to a little-endian for bmp-header
local s, n = "", 4
if x<0x10000 then
s = string.char(0,0)
n = 2
end
x = math.floor(x)
for i = 1,n do
s = s..string.char(x%256)
x = math.floor(x/256)
end
return s
end
--[[ This function saves the 4bpp framebuffer as 4bpp BMP and, if necessary, packes the output by command os.execute(pack..fn).
Since framebuffer enumerates the lines from top to bottom and the bmp-file does it in the inversed order, the process includes
a vertical flip that makes it a bit slower, namely,
~0.16(s) @ Kindle3 & Kindle2 (600x800) ~0.02s @ without v-flip
~0.36(s) @ Kindle DX (824x1200)
NB: needs free memory of G_width*G_height/2 bytes to manupulate the fb-content! ]]
function Screen:fb2bmp(fin, fout, vflip, pack) -- atm, for 4bpp framebuffers only
local inputf = io.open(fin,"rb")
if inputf then
local outputf, size = io.open(fout,"wb")
if outputf then
-- writing bmp-header
outputf:write(string.char(0x42,0x4D,0xF6,0xA9,3,0,0,0,0,0,0x76,0,0,0,40,0),
self:LE(G_width), self:LE(G_height), -- width & height: 4 chars each
string.char(0,0,1,0,4,0,0,0,0,0),
self:LE(G_height*G_width/2), -- raw bytes in image
string.char(0x87,0x19,0,0,0x87,0x19,0,0), -- 6536 pixel/m = 166 dpi for both x&y resolutions
string.char(16,0,0,0,0,0,0,0)) -- 16 colors
local line, i = G_width/2, 15
-- add palette to bmp-header
while i>=0 do
outputf:write(string.char(i*16+i):rep(3), string.char(0))
i=i-1
end
if vflip then -- flip image vertically to make it bmp-compliant
-- read the fb-content line-by-line & fill the content-table in the inversed order
local content = {}
for i=1, G_height do
table.insert(content, 1, inputf:read(line))
end
-- write the v-flipped bmp-data
for i=1, G_height do
outputf:write(content[i])
end
else -- without v-flip, it takes only 0.02s @ 600x800, 4bpp
outputf:write(inputf:read("*all"))
end
outputf:close()
-- here one may use either standard archivers (bzip2, gzip)
-- or standalone converters (bmp2png, bmp2gif)
if pack then os.execute(pack..fout) end
end -- if output f
inputf:close()
end -- if inputf
end
--[[ This function saves the fb-content (both 4bpp and 8bpp) as 8bpp PGM and pack it.
It's relatively slow for 4bpp devices such as
~2.5s @ K2 and K3 > 600x800, 4bpp
~5.0s @ KDX > 824x1200,
but should be very fast (<<0.1s) when no color conversion (4bpp>8bpp) is needed. ]]
--[[
function Screen:fb2pgm(fin, fout, pack, bpp)
local inputf = assert(io.open(fin,"rb"))
if inputf then
local outputf = assert(io.open(fout,"wb"))
outputf:write("P5\n# Created by kindlepdfviewer\n"..G_width.." "..G_height.."\n255\n")
if bpp == 8 then -- then needs free memory of G_width*G_height bytes, but extremely fast!
outputf:write(inputf:read("*all"))
else -- convert 4bpp to 8bpp; needs free memory just to store a block = G_width/2 bytes
local bpp8, block, i, j, line = {}, G_width/2
-- to accelerate a process, let us first create the convertion table: char (0..255) > 2 chars
for j=0, 255 do
i = j%16
bpp8[#bpp8+1] = string.char(255-j+i, 255-i*16)
end
-- now read, convert & write the fb-content by blocks
for i=1, G_height do
line = inputf:read(block)
for j=1, block do
outputf:write(bpp8[1+string.byte(line,j)])
end
end
end
inputf:close()
outputf:close()
if pack then os.execute(pack..fout) end
end
end
]]