NOTE: You need to be a member of the video
group to use the LCD
The EV3 has a 178 x 128 pixels monochrome LCD. The ev3dev video driver
provides standard Linux framebuffer interface
and it’s possible to write pixel data into /dev/fb0
directly using write
or mmap
.
You can get information about the framebuffer by running fbset -i
.
robot@ev3dev:~$ fbset -i
mode "178x128"
geometry 178 128 178 128 1
timings 0 0 0 0 0 0 0
rgba 1/0,1/0,1/0,0/0
endmode
Frame buffer device information:
Name : ST7586
Address : 0xc39be000
Size : 3072
Type : PACKED PIXELS
Visual : MONO01
XPanStep : 0
YPanStep : 0
YWrapStep : 0
LineLength : 24
Accelerator : No
The 1
at the end of geometry
means that there is 1 bit per pixel. So, each
byte in the buffer represents 8 pixels. The leftmost pixel is in the least
significant bit.
Visual : MONO01
tells us that the value 0 is white and the value 1 is black.
LineLength : 24
means that each horizontal line is 24 bytes. If you do the
math, 178 pixels / 8 bits per byte * 1 bit per pixel = 22.25 bytes. This means
not all of the bits in a line are actually displayed.
Suppose below is the pixel buffer:
(76543210)(FEDCBA98)
row0 10000100 00000000 00000000 ... (total 24 bytes)
row1 10000100 00000000 00000000 ... (total 24 bytes)
row2 10000100 00000000 00000000 ... (total 24 bytes)
... (total 128 rows)
It draws two vertical lines at column 2 (0 based index) and column 7 (also 0 based index).
Use python to draw something interesting.
#!/usr/bin/env python
# Hard coding these values is not a good idea because the values could
# change. But, since this is an example, we want to keep it short.
SCREEN_WIDTH = 178 # pixels
SCREEN_HEIGHT = 128 # pixels
LINE_LENGTH = 24 # bytes
SIZE = 3072 # bytes
import os
import array
def main():
buf = [0] * SIZE
# draw a vertical line in column 100 (0 based index)
for row in range(0, SCREEN_HEIGHT):
buf[row * LINE_LENGTH + int(100 / 8)] = 1 << (100 % 8)
# draw a horizontal line in row 64 (0 based index)
for col in range(0, LINE_LENGTH):
buf[64 * LINE_LENGTH + col] = 0xff
import math
# draw a circle, center at (40,40), radius is 20
for x in range(0, 20):
y = math.sqrt(20 * 20 - x * x)
buf[(40 + int(y)) * LINE_LENGTH + int((40 + x) / 8)] = 1 << ((40 + x) % 8)
buf[(40 - int(y)) * LINE_LENGTH + int((40 + x) / 8)] = 1 << ((40 + x) % 8)
buf[(40 + int(y)) * LINE_LENGTH + int((40 - x) / 8)] = 1 << ((40 - x) % 8)
buf[(40 - int(y)) * LINE_LENGTH + int((40 - x) / 8)] = 1 << ((40 - x) % 8)
f = os.open('/dev/fb0', os.O_RDWR)
s = array.array('B', buf).tostring()
os.write(f, s)
os.close(f)
if __name__ == '__main__':
main()