Skip to content

Commit 94f981a

Browse files
committed
Merge pull request #22 from ddemidov/lcd
Implement FbMem and LCD classes
2 parents c075c4e + 83eebc1 commit 94f981a

File tree

1 file changed

+217
-0
lines changed

1 file changed

+217
-0
lines changed

ev3dev.py

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,16 @@
2727

2828
#~autogen
2929

30+
import os
3031
import os.path
3132
import fnmatch
3233
import numbers
3334
import platform
3435
import fcntl
3536
import array
37+
import mmap
38+
import ctypes
39+
from PIL import Image, ImageDraw
3640

3741
#------------------------------------------------------------------------------
3842
# Guess platform we are running on
@@ -1985,3 +1989,216 @@ def status(self):
19851989

19861990
#~autogen
19871991

1992+
class FbMem(object):
1993+
1994+
"""The framebuffer memory object.
1995+
1996+
Made of:
1997+
- the framebuffer file descriptor
1998+
- the fix screen info struct
1999+
- the var screen info struct
2000+
- the mapped memory
2001+
"""
2002+
2003+
#-------------------------------------------------------------------
2004+
# The code is adapted from
2005+
# https://github.com/LinkCareServices/cairotft/blob/master/cairotft/linuxfb.py
2006+
#
2007+
# The original code came with the following license:
2008+
#-------------------------------------------------------------------
2009+
# Copyright (c) 2012 Kurichan
2010+
#
2011+
# This program is free software. It comes without any warranty, to
2012+
# the extent permitted by applicable law. You can redistribute it
2013+
# and/or modify it under the terms of the Do What The Fuck You Want
2014+
# To Public License, Version 2, as published by Sam Hocevar. See
2015+
# http://sam.zoy.org/wtfpl/COPYING for more details.
2016+
#-------------------------------------------------------------------
2017+
2018+
2019+
__slots__ = ('fid', 'fix_info', 'var_info', 'mmap')
2020+
2021+
FBIOGET_VSCREENINFO = 0x4600
2022+
FBIOGET_FSCREENINFO = 0x4602
2023+
2024+
FB_VISUAL_MONO01 = 0
2025+
FB_VISUAL_MONO10 = 1
2026+
2027+
class FixScreenInfo(ctypes.Structure):
2028+
2029+
"""The fb_fix_screeninfo from fb.h."""
2030+
2031+
_fields_ = [
2032+
('id_name', ctypes.c_char * 16),
2033+
('smem_start', ctypes.c_ulong),
2034+
('smem_len', ctypes.c_uint32),
2035+
('type', ctypes.c_uint32),
2036+
('type_aux', ctypes.c_uint32),
2037+
('visual', ctypes.c_uint32),
2038+
('xpanstep', ctypes.c_uint16),
2039+
('ypanstep', ctypes.c_uint16),
2040+
('ywrapstep', ctypes.c_uint16),
2041+
('line_length', ctypes.c_uint32),
2042+
('mmio_start', ctypes.c_ulong),
2043+
('mmio_len', ctypes.c_uint32),
2044+
('accel', ctypes.c_uint32),
2045+
('reserved', ctypes.c_uint16 * 3),
2046+
]
2047+
2048+
2049+
class VarScreenInfo(ctypes.Structure):
2050+
2051+
class FbBitField(ctypes.Structure):
2052+
2053+
"""The fb_bitfield struct from fb.h."""
2054+
2055+
_fields_ = [
2056+
('offset', ctypes.c_uint32),
2057+
('length', ctypes.c_uint32),
2058+
('msb_right', ctypes.c_uint32),
2059+
]
2060+
2061+
2062+
"""The fb_var_screeninfo struct from fb.h."""
2063+
2064+
_fields_ = [
2065+
('xres', ctypes.c_uint32),
2066+
('yres', ctypes.c_uint32),
2067+
('xres_virtual', ctypes.c_uint32),
2068+
('yres_virtual', ctypes.c_uint32),
2069+
('xoffset', ctypes.c_uint32),
2070+
('yoffset', ctypes.c_uint32),
2071+
2072+
('bits_per_pixel', ctypes.c_uint32),
2073+
('grayscale', ctypes.c_uint32),
2074+
2075+
('red', FbBitField),
2076+
('green', FbBitField),
2077+
('blue', FbBitField),
2078+
('transp', FbBitField),
2079+
]
2080+
2081+
2082+
def __init__(self, fbdev=None):
2083+
"""Create the FbMem framebuffer memory object."""
2084+
fid = FbMem._open_fbdev(fbdev)
2085+
fix_info = FbMem._get_fix_info(fid)
2086+
fbmmap = FbMem._map_fb_memory(fid, fix_info)
2087+
self.fid = fid
2088+
self.fix_info = fix_info
2089+
self.var_info = FbMem._get_var_info(fid)
2090+
self.mmap = fbmmap
2091+
2092+
2093+
def __del__(self):
2094+
"""Close the FbMem framebuffer memory object."""
2095+
self.mmap.close()
2096+
FbMem._close_fbdev(self.fid)
2097+
2098+
2099+
@staticmethod
2100+
def _open_fbdev(fbdev=None):
2101+
"""Return the framebuffer file descriptor.
2102+
2103+
Try to use the FRAMEBUFFER
2104+
environment variable if fbdev is not given. Use '/dev/fb0' by
2105+
default.
2106+
"""
2107+
dev = fbdev or os.getenv('FRAMEBUFFER', '/dev/fb0')
2108+
fbfid = os.open(dev, os.O_RDWR)
2109+
return fbfid
2110+
2111+
2112+
@staticmethod
2113+
def _close_fbdev(fbfid):
2114+
"""Close the framebuffer file descriptor."""
2115+
os.close(fbfid)
2116+
2117+
2118+
@staticmethod
2119+
def _get_fix_info(fbfid):
2120+
"""Return the fix screen info from the framebuffer file descriptor."""
2121+
fix_info = FbMem.FixScreenInfo()
2122+
fcntl.ioctl(fbfid, FbMem.FBIOGET_FSCREENINFO, fix_info)
2123+
return fix_info
2124+
2125+
2126+
@staticmethod
2127+
def _get_var_info(fbfid):
2128+
"""Return the var screen info from the framebuffer file descriptor."""
2129+
var_info = FbMem.VarScreenInfo()
2130+
fcntl.ioctl(fbfid, FbMem.FBIOGET_VSCREENINFO, var_info)
2131+
return var_info
2132+
2133+
2134+
@staticmethod
2135+
def _map_fb_memory(fbfid, fix_info):
2136+
"""Map the framebuffer memory."""
2137+
return mmap.mmap(
2138+
fbfid,
2139+
fix_info.smem_len,
2140+
mmap.MAP_SHARED,
2141+
mmap.PROT_READ | mmap.PROT_WRITE,
2142+
offset=0
2143+
)
2144+
2145+
class Screen(FbMem):
2146+
"""
2147+
A convenience wrapper for the FbMem class.
2148+
Provides drawing functions from the python imaging library (PIL).
2149+
"""
2150+
2151+
def __init__(self):
2152+
FbMem.__init__(self)
2153+
2154+
self._img = Image.new(
2155+
"%s" % self.var_info.bits_per_pixel,
2156+
(self.fix_info.line_length * 8 / self.var_info.bits_per_pixel, self.yres),
2157+
"white")
2158+
2159+
self._draw = ImageDraw.Draw(self._img)
2160+
2161+
@property
2162+
def xres(self):
2163+
"""
2164+
Horizontal screen resolution
2165+
"""
2166+
return self.var_info.xres
2167+
2168+
@property
2169+
def yres(self):
2170+
"""
2171+
Vertical screen resolution
2172+
"""
2173+
return self.var_info.yres
2174+
2175+
@property
2176+
def shape(self):
2177+
"""
2178+
Dimensions of the screen.
2179+
"""
2180+
return (self.xres, self.yres)
2181+
2182+
@property
2183+
def draw(self):
2184+
"""
2185+
Returns a handle to PIL.ImageDraw.Draw class associated with the screen.
2186+
Example::
2187+
lcd.draw.rectangle((10,10,60,20), fill='black')
2188+
"""
2189+
return self._draw
2190+
2191+
def clear(self):
2192+
"""
2193+
Clears the screen
2194+
"""
2195+
self._draw.rectangle(((0,0), self.shape), fill="white")
2196+
2197+
def update(self):
2198+
"""
2199+
Applies pending changes to the screen.
2200+
Nothing will be drawn on the screen until this function is called.
2201+
"""
2202+
self.mmap[:] = self._img.tobytes("raw", "%s;I%s" % (self.var_info.bits_per_pixel,
2203+
self.fix_info.visual in [FbMem.FB_VISUAL_MONO01, FbMem.FB_VISUAL_MONO10] and "R" or ""))
2204+

0 commit comments

Comments
 (0)