DFRobot V2 screen

This commit is contained in:
Ferny G 2020-04-17 09:27:58 -05:00 committed by dadav
parent 2b17e5322b
commit 8c2b4e2075
36 changed files with 1537 additions and 11 deletions

View File

@ -49,8 +49,11 @@ class Display(View):
def is_lcdhat(self):
return self._implementation.name == 'lcdhat'
def is_dfrobot(self):
return self._implementation.name == 'dfrobot'
def is_dfrobot_v1(self):
return self._implementation.name == 'dfrobot_v1'
def is_dfrobot_v2(self):
return self._implementation.name == 'dfrobot_v2'
def is_waveshare144lcd(self):
return self._implementation.name == 'waveshare144lcd'

View File

@ -2,7 +2,8 @@ from pwnagotchi.ui.hw.inky import Inky
from pwnagotchi.ui.hw.papirus import Papirus
from pwnagotchi.ui.hw.oledhat import OledHat
from pwnagotchi.ui.hw.lcdhat import LcdHat
from pwnagotchi.ui.hw.dfrobot import DFRobot
from pwnagotchi.ui.hw.dfrobot1 import DFRobotV1
from pwnagotchi.ui.hw.dfrobot2 import DFRobotV2
from pwnagotchi.ui.hw.waveshare1 import WaveshareV1
from pwnagotchi.ui.hw.waveshare2 import WaveshareV2
from pwnagotchi.ui.hw.waveshare27inch import Waveshare27inch
@ -27,8 +28,11 @@ def display_for(config):
if config['ui']['display']['type'] == 'lcdhat':
return LcdHat(config)
if config['ui']['display']['type'] == 'dfrobot':
return DFRobot(config)
if config['ui']['display']['type'] == 'dfrobot_1':
return DFRobotV1(config)
if config['ui']['display']['type'] == 'dfrobot_2':
return DFRobotV2(config)
elif config['ui']['display']['type'] == 'waveshare_1':
return WaveshareV1(config)

View File

@ -3,9 +3,9 @@ import logging
import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.hw.base import DisplayImpl
class DFRobot(DisplayImpl):
class DFRobotV1(DisplayImpl):
def __init__(self, config):
super(DFRobot, self).__init__(config, 'dfrobot')
super(DFRobotV1, self).__init__(config, 'dfrobot_1')
self._display = None
def layout(self):
@ -31,8 +31,8 @@ class DFRobot(DisplayImpl):
return self._layout
def initialize(self):
logging.info("initializing dfrobot display")
from pwnagotchi.ui.hw.libs.dfrobot.dfrobot import DFRobot
logging.info("initializing dfrobot1 display")
from pwnagotchi.ui.hw.libs.dfrobot.v1.dfrobot import DFRobot
self._display = DFRobot()
def render(self, canvas):

View File

@ -0,0 +1,43 @@
import logging
import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.hw.base import DisplayImpl
class DFRobotV2(DisplayImpl):
def __init__(self, config):
super(DFRobotV2, self).__init__(config, 'dfrobot_2')
self._display = None
def layout(self):
fonts.setup(10, 9, 10, 35, 25, 9)
self._layout['width'] = 250
self._layout['height'] = 122
self._layout['face'] = (0, 40)
self._layout['name'] = (5, 20)
self._layout['channel'] = (0, 0)
self._layout['aps'] = (28, 0)
self._layout['uptime'] = (185, 0)
self._layout['line1'] = [0, 14, 250, 14]
self._layout['line2'] = [0, 108, 250, 108]
self._layout['friend_face'] = (0, 92)
self._layout['friend_name'] = (40, 94)
self._layout['shakes'] = (0, 109)
self._layout['mode'] = (225, 109)
self._layout['status'] = {
'pos': (125, 20),
'font': fonts.status_font(fonts.Medium),
'max': 20
}
return self._layout
def initialize(self):
logging.info("initializing dfrobot2 display")
from pwnagotchi.ui.hw.libs.dfrobot.v2.dfrobot import DFRobot
self._display = DFRobot()
def render(self, canvas):
buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self):
self._display.Clear(0xFF)

View File

@ -0,0 +1,66 @@
# DFRobot display support
import logging
from . import dfrobot_epaper
#Resolution of display
WIDTH = 250
HEIGHT = 122
RASPBERRY_SPI_BUS = 0
RASPBERRY_SPI_DEV = 0
RASPBERRY_PIN_CS = 27
RASPBERRY_PIN_CD = 17
RASPBERRY_PIN_BUSY = 4
class DFRobot:
def __init__(self):
self._display = dfrobot_epaper.DFRobot_Epaper_SPI(RASPBERRY_SPI_BUS, RASPBERRY_SPI_DEV, RASPBERRY_PIN_CS, RASPBERRY_PIN_CD, RASPBERRY_PIN_BUSY)
self._display.begin()
self.clear(0xFF)
self.FULL = self._display.FULL
self.PART = self._display.PART
def getbuffer(self, image):
if HEIGHT % 8 == 0:
linewidth = HEIGHT // 8
else:
linewidth = HEIGHT // 8 + 1
buf = [0xFF] * (linewidth * WIDTH)
image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
if (imwidth == HEIGHT and imheight == WIDTH):
for y in range(imheight):
for x in range(imwidth):
if pixels[x,y] == 0:
x = imwidth - x
buf[x // 8 + y * linewidth] &= ~(0x80 >> (x % 8))
elif (imwidth == WIDTH and imheight == HEIGHT):
for y in range(imheight):
for x in range(imwidth):
newx = y
newy = WIDTH - x - 1
if pixels[x,y] == 0:
newy = imwidth - newy - 1
buf[newx // 8 + newy * linewidth] &= ~(0x80 >> (y % 8))
return buf
def flush(self, type):
self._display.flush(type)
def display(self, buf):
self._display.setBuffer(buf)
self.flush(self._display.PART)
def clear(self, color):
if HEIGHT % 8 == 0:
linewidth = HEIGHT // 8
else:
linewidth = HEIGHT // 8 + 1
buf = [color] * (linewidth * WIDTH)
self._display.setBuffer(buf)
self.flush(self._display.FULL)

View File

@ -0,0 +1,673 @@
# -*- coding:utf-8 -*-
import sys
from .dfrobot_printString import PrintString
from .dfrobot_fonts import Fonts
def color24to16(color):
return (((color >> 8) & 0xf800) | ((color >> 5) & 0x7e0) | ((color >> 3) & 0x1f))
def color16to24(color):
return (((color & 0xf800) << 8) | ((color & 0x7e0) << 5) | ((color & 0x1f) << 3))
def swap(o1, o2):
return (o2, o1)
class DFRobot_Display(PrintString):
WHITE24 = 0xffffff
SILVER24 = 0xc0c0c0
GRAY24 = 0x808080
BLACK24 = 0x000000
RED24 = 0xff0000
MAROON24 = 0x800000
YELLOW24 = 0xffff00
OLIVE24 = 0x808000
GREEN24 = 0x00ff00
DARKGREEN24 = 0x008000
CYAN24 = 0x00ffff
BLUE24 = 0x0000ff
NAVY24 = 0x000080
FUCHSIA24 = 0xff00ff
PURPLE24 = 0x800080
TEAL24 = 0x008080
WHITE16 = color24to16(WHITE24)
SILVER16 = color24to16(SILVER24)
GRAY16 = color24to16(GRAY24)
BLACK16 = color24to16(BLACK24)
RED16 = color24to16(RED24)
MAROON16 = color24to16(MAROON24)
YELLOW16 = color24to16(YELLOW24)
OLIVE16 = color24to16(OLIVE24)
GREEN16 = color24to16(GREEN24)
DARKGREEN16 = color24to16(DARKGREEN24)
CYAN16 = color24to16(CYAN24)
BLUE16 = color24to16(BLUE24)
NAVY16 = color24to16(NAVY24)
FUCHSIA16 = color24to16(FUCHSIA24)
PURPLE16 = color24to16(PURPLE24)
TEAL16 = color24to16(TEAL24)
WHITE = WHITE16
SILVER = SILVER16
GRAY = GRAY16
BLACK = BLACK16
RED = RED16
MAROON = MAROON16
YELLOW = YELLOW16
OLIVE = OLIVE16
GREEN = GREEN16
DARKGREEN = DARKGREEN16
CYAN = CYAN16
BLUE = BLUE16
NAVY = NAVY16
FUCHSIA = FUCHSIA16
PURPLE = PURPLE16
TEAL = TEAL16
POSITIVE = 1
REVERSE = -1
BITMAP_TBMLLR = "TBMLLR"
BITMAP_TBMRLL = "TBMRLL"
BITMAP_BTMLLR = "BTMLLR"
BITMAP_BTMRLL = "BTMRLL"
BITMAP_LRMTLB = "LRMTLB"
BITMAP_LRMBLT = "LRMBLT"
BITMAP_RLMTLB = "RLMTLB"
BIMTAP_RLMBLT = "RLMBLT"
BITMAP_UNKNOW = "UNKNOW"
def __init__(self, w, h):
PrintString.__init__(self)
print("DFRobot_Display init " + str(w) + " " + str(h))
self._width = w
self._height = h
self._lineWidth = 1
self._bitmapSize = 1
self._bitmapFmt = ""
self._bmpFmt = self.BITMAP_TBMLLR
self._fonts = Fonts()
self._textSize = 1
self._textColor = self.BLACK
self._textBackground = self.WHITE
self._textCursorX = 0
self._textCursorY = 0
self._textIntervalRow = 0
self._textIntervalCol = 0
def _ternaryExpression(self, condition, o1, o2):
if condition:
return o1
return o2
def _getDirection(self, value):
if value >= 0:
return 1
return -1
def color16to24(self, color):
return color16to24(color)
def color24to16(self, color):
return color24to16(color)
def setColorTo16(self):
self.WHITE = self.WHITE16
self.SILVER = self.SILVER16
self.GRAY = self.GRAY16
self.BLACK = self.BLACK16
self.RED = self.RED16
self.MAROON = self.MAROON16
self.YELLOW = self.YELLOW16
self.OLIVE = self.OLIVE16
self.GREEN = self.GREEN16
self.DARKGREEN = self.DARKGREEN16
self.CYAN = self.CYAN16
self.BLUE = self.BLUE16
self.NAVY = self.NAVY16
self.FUCHSIA = self.FUCHSIA16
self.PURPLE = self.PURPLE16
self.TEAL = self.TEAL16
def setColorTo24(self):
self.WHITE = self.WHITE24
self.SILVER = self.SILVER24
self.GRAY = self.GRAY24
self.BLACK = self.BLACK24
self.RED = self.RED24
self.MAROON = self.MAROON24
self.YELLOW = self.YELLOW24
self.OLIVE = self.OLIVE24
self.GREEN = self.GREEN24
self.DARKGREEN = self.DARKGREEN24
self.CYAN = self.CYAN24
self.BLUE = self.BLUE24
self.NAVY = self.NAVY24
self.FUCHSIA = self.FUCHSIA24
self.PURPLE = self.PURPLE24
self.TEAL = self.TEAL24
def setLineWidth(self, w):
if w < 0:
return
self._lineWidth = w
def setTextFormat(self, size, color, background, intervalRow = 2, intervalCol = 0):
self._textColor = color
self._textIntervalRow = intervalRow
self._textIntervalCol = intervalCol
self._textBackground = background
if size < 0:
return
self._textSize = size
def setTextCursor(self, x, y):
self._textCursorX = int(x)
self._textCursorY = int(y)
def setBitmapSize(self, size):
if size < 0:
return
self._bitmapSize = size
def setBitmapFmt(self, fmt):
self._bmpFmt = fmt
def setExFonts(self, obj):
self._fonts.setExFonts(obj)
def setExFontsFmt(self, width, height):
self._fonts.setExFontsFmt(width, height)
def setEnableDefaultFonts(self, opt):
self._fonts.setEnableDefaultFonts(opt)
def pixel(self, x, y, color):
pass
def clear(self, color):
self.fillRect(0, 0, self._width, self._height, color)
self._textCursorX = 0
self._textCursorY = 0
def VLine(self, x, y, h, color):
x = int(x)
y = int(y)
h = int(h)
direction = self._getDirection(h)
x -= self._lineWidth // 2
h = self._ternaryExpression(h > 0, h, -h)
for i in range(self._ternaryExpression(h > 0, h, - h)):
xx = x
for j in range(self._lineWidth):
self.pixel(xx, y, color)
xx += 1
y += direction
def HLine(self, x, y, w, color):
x = int(x)
y = int(y)
w = int(w)
direction = self._getDirection(w)
y -= self._lineWidth // 2
for i in range(self._ternaryExpression(w > 0, w, - w)):
yy = y
for j in range(self._lineWidth):
self.pixel(x, yy, color)
yy += 1
x += direction
def line(self, x, y, x1, y1, color):
x = int(x)
y = int(y)
x1 = int(x1)
y1 = int(y1)
if x == x1:
self.VLine(x, y, y1 - y, color)
return
if y == y1:
self.HLine(x, y, x1 - x, color)
return
dx = abs(x1 - x)
dy = abs(y1 - y)
dirX = self._ternaryExpression(x < x1, 1, -1)
dirY = self._ternaryExpression(y < y1, 1, -1)
if dx > dy:
err = dx / 2
for i in range(dx):
self.HLine(x, y, 1, color)
x += dirX
err -= dy
if err < 0:
err += dx
y += dirY
self.HLine(x1, y1, 1, color)
else:
err = dy / 2
for i in range(dy):
self.VLine(x, y, 1, color)
y += dirY
err -= dx
if err < 0:
err += dy
x += dirX
self.VLine(x1, y1, 1, color)
def triangle(self, x, y, x1, y1, x2, y2, color):
self.line(x, y, x1, y1, color)
self.line(x1, y1, x2, y2, color)
self.line(x2, y2, x, y, color)
def fillTriangle(self, x, y, x1, y1, x2, y2, color):
self.line(x, y, x1, y1, color)
self.line(x1, y1, x2, y2, color)
self.line(x2, y2, x, y, color)
x = int(x)
y = int(y)
x1 = int(x1)
y1 = int(y1)
x2 = int(x2)
y2 = int(y2)
temp = self._lineWidth
self._lineWidth = 1
if x == x1 and x == x2:
ymax = max([y, y1, y2])
ymin = min([y, y1, y2])
self.HLine(x, ymin, ymax - ymin, color)
self._lineWidth = temp
return
if y == y1 and y == y2:
xmax = max([x, x1, x2])
xmin = max([x, x1, x2])
self.VLine(xmin, y, xmax - xmin, color)
self._lineWidth = temp
return
direction = self.POSITIVE
if y == y1 or y1 == y2 or y == y2:
if y == y1:
(x, x2) = swap(x, x2)
(y, y2) = swap(y, y2)
elif y == y2:
(x, x1) = swap(x, x1)
(y, y1) = swap(y, y1)
if y > y1:
direction = self.REVERSE
if x1 > x2:
(x1, x2) = swap(x1, x2)
(y1, y2) = swap(y1, y2)
else:
if y > y1:
(x, x1) = swap(x, x1)
(y, y1) = swap(y, y1)
if y > y2:
(x, x2) = swap(x, x2)
(y, y2) = swap(y, y2)
if y1 > y2:
(x1, x2) = swap(x1, x2)
(y1, y2) = swap(y1, y2)
dx1 = x1 - x
dx2 = x2 - x
dx3 = x2 - x1
dy1 = y1 - y
dy2 = y2 - y
dy3 = y2 - y1
if direction == self.POSITIVE:
for i in range(dy1):
self.HLine(x + dx1 * i / dy1, y + i, (x + dx2 * i / dy2) - (x + dx1 * i / dy1) + 1, color)
for i in range(dy3):
self.HLine(x1 + dx3 * i / dy3, y1 + i, (x + dx2 * (i + dy1) / dy2) - (x1 + dx3 * i / dy3) + 1, color)
else:
y = y1 + dy1
dy1 = - dy1
for i in range(dy1):
self.HLine(x + dx1 * i / dy1, y1 + dy1 - i, (x + dx2 * i / dy1) - (x + dx1 * i / dy1) + 1, color)
self._lineWidth = temp
def rect(self, x, y, w, h, color):
if w < 0:
x += w
w = -w
if h < 0:
y += h
h = -h
self.HLine(x - self._lineWidth // 2, y, w + self._lineWidth, color)
self.HLine(x - self._lineWidth // 2, y + h, w + self._lineWidth, color)
self.VLine(x, y - self._lineWidth // 2, h + self._lineWidth, color)
self.VLine(x + w, y - self._lineWidth // 2, h + self._lineWidth, color)
def fillRect(self, x, y, w, h, color):
temp = self._lineWidth
self._lineWidth = 1
if w < 0:
x += w
w = abs(w)
for i in range(w):
self.VLine(x + i, y, h, color)
self._lineWidth = temp
QUADRANT_1 = 1
QUADRANT_2 = 2
QUADRANT_3 = 4
QUADRANT_4 = 8
QUADRANT_ALL = 15
def circleHelper(self, x, y, r, quadrant, color):
x = int(x)
y = int(y)
r = abs(int(r))
vx = 0
vy = r
dx = 1
dy = -2 * r
p = 1 - r
if quadrant & self.QUADRANT_1:
self.VLine(x + r, y, 1, color)
if quadrant & self.QUADRANT_2:
self.VLine(x, y - r, 1, color)
if quadrant & self.QUADRANT_3:
self.VLine(x - r, y, 1, color)
if quadrant & self.QUADRANT_4:
self.VLine(x, y + r, 1, color)
halfLineWidth = self._lineWidth // 2
while vx < vy:
if p >= 0:
vy -= 1
dy += 2
p += dy
vx += 1
dx += 2
p += dx
if quadrant & self.QUADRANT_1:
self.fillRect(x + vx - halfLineWidth, y - vy - halfLineWidth, self._lineWidth, self._lineWidth, color) # quadrant 1
self.fillRect(x + vy - halfLineWidth, y - vx - halfLineWidth, self._lineWidth, self._lineWidth, color) # quadrant 1
if quadrant & self.QUADRANT_2:
self.fillRect(x - vx - halfLineWidth, y - vy - halfLineWidth, self._lineWidth, self._lineWidth, color) # quadrant 2
self.fillRect(x - vy - halfLineWidth, y - vx - halfLineWidth, self._lineWidth, self._lineWidth, color) # quadrant 2
if quadrant & self.QUADRANT_3:
self.fillRect(x - vx - halfLineWidth, y + vy - halfLineWidth, self._lineWidth, self._lineWidth, color) # quadrant 3
self.fillRect(x - vy - halfLineWidth, y + vx - halfLineWidth, self._lineWidth, self._lineWidth, color) # quadrant 3
if quadrant & self.QUADRANT_4:
self.fillRect(x + vx - halfLineWidth, y + vy - halfLineWidth, self._lineWidth, self._lineWidth, color) # quadrant 4
self.fillRect(x + vy - halfLineWidth, y + vx - halfLineWidth, self._lineWidth, self._lineWidth, color) # quadrant 4
def circle(self, x, y, r, color):
self.circleHelper(x, y, r, self.QUADRANT_ALL, color)
def fillCircleHelper(self, x, y, r, quadrant, color):
x = int(x)
y = int(y)
r = abs(int(r))
temp = self._lineWidth
self._lineWidth = 1
vx = 0
vy = r
dx = 1
dy = -2 * r
p = 1 - r
if quadrant & self.QUADRANT_1:
self.HLine(x, y, r + 1, color)
if quadrant & self.QUADRANT_2:
self.VLine(x, y, - r - 1, color)
if quadrant & self.QUADRANT_3:
self.HLine(x, y, - r - 1, color)
if quadrant & self.QUADRANT_4:
self.VLine(x, y, r + 1, color)
while vx < vy:
if p >= 0:
vy -= 1
dy += 2
p += dy
vx += 1
dx += 2
p += dx
if quadrant & self.QUADRANT_1:
self.VLine(x + vx, y - vy, vy, color) # quadrant 1
self.VLine(x + vy, y - vx, vx, color) # quadrant 1
if quadrant & self.QUADRANT_2:
self.VLine(x - vx, y - vy, vy, color) # quadrant 2
self.VLine(x - vy, y - vx, vx, color) # quadrant 2
if quadrant & self.QUADRANT_3:
self.VLine(x - vx, y + vy, - vy, color) # quadrant 3
self.VLine(x - vy, y + vx, - vx, color) # quadrant 3
if quadrant & self.QUADRANT_4:
self.VLine(x + vx, y + vy, - vy, color) # quadrant 4
self.VLine(x + vy, y + vx, - vx, color) # quadrant 4
self._lineWidth = temp
def fillCircle(self, x, y, r, color):
self.fillCircleHelper(x, y, r, self.QUADRANT_ALL, color)
def roundRect(self, x, y, w, h, r, color):
x = int(x)
y = int(y)
w = int(w)
h = int(h)
r = abs(int(r))
if w < 0:
x += w
w = abs(w)
if h < 0:
y += h
h = abs(h)
self.HLine(x + r, y, w - 2 * r + 1, color)
self.HLine(x + r, y + h, w - 2 * r + 1, color)
self.VLine(x, y + r, h - 2 * r + 1, color)
self.VLine(x + w, y + r, h - 2 * r + 1, color)
self.circleHelper(x + r, y + r, r, self.QUADRANT_2, color)
self.circleHelper(x + w - r, y + r, r, self.QUADRANT_1, color)
self.circleHelper(x + r, y + h - r, r, self.QUADRANT_3, color)
self.circleHelper(x + w - r, y + h - r, r, self.QUADRANT_4, color)
def fillRoundRect(self, x, y, w, h, r, color):
x = int(x)
y = int(y)
w = int(w)
h = int(h)
r = abs(int(r))
if w < 0:
x += w
w = abs(w)
if h < 0:
y += h
h = abs(h)
self.fillRect(x + r, y, w - 2 * r, h, color)
self.fillRect(x, y + r, r, h - 2 * r, color)
self.fillRect(x + w - r, y + r, r, h - 2 * r, color)
self.fillCircleHelper(x + r, y + r, r, self.QUADRANT_2, color)
self.fillCircleHelper(x + w - r - 1, y + r, r, self.QUADRANT_1, color)
self.fillCircleHelper(x + r, y + h - r - 1, r, self.QUADRANT_3, color)
self.fillCircleHelper(x + w - r - 1, y + h - r - 1, r, self.QUADRANT_4, color)
def _bitmapHelper(self, increaseAxis, staticAxis, data, dataBit, exchange, color, background):
for i in data:
for j in range(8):
if i & dataBit:
if exchange:
self.fillRect(staticAxis, increaseAxis, self._bitmapSize, self._bitmapSize, color)
else:
self.fillRect(increaseAxis, staticAxis, self._bitmapSize, self._bitmapSize, color)
else:
if exchange:
self.fillRect(staticAxis, increaseAxis, self._bitmapSize, self._bitmapSize, background)
else:
self.fillRect(increaseAxis, staticAxis, self._bitmapSize, self._bitmapSize, background)
increaseAxis += self._bitmapSize
if dataBit & 0x80:
i <<= 1
else:
i >>= 1
def bitmap(self, x, y, bitmap, w, h, color, background):
if w < 0 or h < 0:
return
x = abs(int(x))
y = abs(int(y))
if self._bmpFmt == self.BITMAP_TBMLLR:
oneLineDataLen = (w - 1) // 8 + 1
for i in range(h):
yMask = y + i * self._bitmapSize
self._bitmapHelper(x, yMask, bitmap[i * oneLineDataLen : oneLineDataLen * (i + 1)], 0x80, False, color, background)
elif self._bmpFmt == self.BITMAP_TBMRLL:
oneLineDataLen = (w - 1) // 8 + 1
for i in range(h):
yMask = y + i * self._bitmapSize
self._bitmapHelper(x, yMask, bitmap[i * oneLineDataLen : oneLineDataLen * (i + 1)], 0x01, False, color, background)
elif self._bmpFmt == self.BITMAP_BTMLLR:
oneLineDataLen = (w - 1) // 8 + 1
for i in range(h):
yMask = y + h * self._bitmapSize - i * self._bitmapSize
self._bitmapHelper(x, yMask, bitmap[i * oneLineDataLen : oneLineDataLen * (i + 1)], 0x80, False, color, background)
elif self._bmpFmt == self.BITMAP_BTMRLL:
oneLineDataLen = (w - 1) // 8 + 1
for i in range(h):
yMask = y + h * self._bitmapSize - i * self._bitmapSize
self._bitmapHelper(x, yMask, bitmap[i * oneLineDataLen : oneLineDataLen * (i + 1)], 0x01, False, color, background)
elif self._bmpFmt == self.BITMAP_LRMTLB:
oneLineDataLen = (h - 1) // 8 + 1
for i in range(w):
xMask = x + i * self._bitmapSize
self._bitmapHelper(y, xMask, bitmap[i * oneLineDataLen : oneLineDataLen * (i + 1)], 0x80, True, color, background)
elif self._bmpFmt == self.BITMAP_LRMBLT:
oneLineDataLen = (h - 1) // 8 + 1
for i in range(w):
xMask = x + i * self._bitmapSize
self._bitmapHelper(y, xMask, bitmap[i * oneLineDataLen : oneLineDataLen * (i + 1)], 0x01, True, color, background)
elif self._bmpFmt == self.BITMAP_RLMTLB:
oneLineDataLen = (h - 1) // 8 + 1
for i in range(w):
xMask = x + w * self._bitmapSize - i * self._bitmapSize
self._bitmapHelper(y, xMask, bitmap[i * oneLineDataLen : oneLineDataLen * (i + 1)], 0x80, True, color, background)
elif self._bmpFmt == self.BIMTAP_RLMBLT:
oneLineDataLen = (h - 1) // 8 + 1
for i in range(w):
xMask = x + w * self._bitmapSize - i * self._bitmapSize
self._bitmapHelper(y, xMask, bitmap[i * oneLineDataLen : oneLineDataLen * (i + 1)], 0x01, True, color, background)
def _bytesToNumber(self, data):
r = 0
i = len(data)
while i > 0:
i -= 1
r = r << 8 | data[i]
return r
def _getQuads(self, data, count):
r = []
for i in range(count):
r.append(data[i * 4 + 54 : i * 4 + 58])
return r
BITMAP_COMPRESSION_NO = 0
BITMAP_COMPRESSION_RLE8 = 1
BITMAP_COMPRESSION_RLE4 = 2
BITMAP_COMPRESSION_FIELDS = 3
def startDrawBitmapFile(self, x, y):
pass
def bitmapFileHelper(self, buf):
pass
def endDrawBitmapFile(self):
pass
def bitmapFile(self, x, y, path):
try:
f = open(path, "rb")
except:
print("open file error")
return
c = bytearray(f.read())
f.close()
if c[0] != 0x42 and c[1] != 0x4d:
print("file error")
print(c[0])
print(c[1])
return
DIBOffset = self._bytesToNumber(c[10:14])
width = self._bytesToNumber(c[18:22])
height = self._bytesToNumber(c[22:26])
colorBits = self._bytesToNumber(c[28:30])
compression = self._bytesToNumber(c[30:32])
# print("w: %d, h: %d, colorBits: %d" %(width, height, colorBits))
if colorBits == 24:
width3 = width * 3
for i in range(height):
self.startDrawBitmapFile(x, y + height - i)
buf = []
left = DIBOffset + i * width3
i = 0
while i < width3:
buf.append(c[left + i + 2])
buf.append(c[left + i + 1])
buf.append(c[left + i + 0])
i += 3
self.bitmapFileHelper(buf)
self.endDrawBitmapFile()
elif colorBits == 1:
quads = self._getQuads(c, 2)
addr = DIBOffset
if compression == self.BITMAP_COMPRESSION_NO:
addrCountComplement = (width // 8 + 1) % 4
if addrCountComplement != 0:
addrCountComplement = 4 - addrCountComplement
for i in range(height):
w = width
addrCount = 0
self.startDrawBitmapFile(x, y + height - i - 1)
buf = []
while w > 0:
d = c[addr + addrCount]
addrCount = addrCount + 1
j = 8
while w > 0 and j > 0:
j -= 1
quad = d & (0x01 << j)
if quad > 0:
quad = 1
buf.append(quads[quad][2])
buf.append(quads[quad][1])
buf.append(quads[quad][0])
w -= 1
self.bitmapFileHelper(buf)
addrCount += addrCountComplement
addr += addrCount
self.endDrawBitmapFile()
else:
print("dont support this bitmap file format yet")
def writeOneChar(self, c):
if len(c) > 1:
c = c[0]
(l, width, height, fmt) = self._fonts.getOneCharacter(c)
temp = self._bmpFmt
self._bmpFmt = fmt
ts = self._textSize
if ord(c) == ord("\n"):
self._textCursorX = 0
self._textCursorY += height * ts + self._textIntervalCol
elif len(l):
temp1 = self._bitmapSize
self._bitmapSize = ts
self._textCursorX += self._textIntervalRow
if self._textCursorX + ts * width > self._width:
self.fillRect(self._textCursorX, self._textCursorY, self._width - self._textCursorX, self._fonts._extensionFontsHeight * ts + self._textIntervalCol, self._textBackground)
self._textCursorX = self._textIntervalRow
self._textCursorY += ts * self._fonts._extensionFontsHeight + self._textIntervalCol
self.fillRect(self._textCursorX, self._textCursorY, self._fonts._extensionFontsWidth * ts + self._textIntervalRow, self._fonts._extensionFontsHeight * ts + self._textIntervalCol, self._textBackground)
self.bitmap(self._textCursorX, self._textCursorY, l, width, height, self._textColor, self._textBackground)
self._textCursorX += ts * width
self._bitmapSize = temp1
self._bmpFmt = temp

View File

@ -0,0 +1,69 @@
# -*- coding:utf-8 -*-
import json
class Fonts:
def __init__(self):
self._haveFontsABC = False
self._fontsABC = {}
self._fontsABCWidth = 0
self._fontsABCHeight = 0
self._fontsABCFmt = ""
self._haveExtensionFonts = False
self._extensionFontsWidth = 0
self._extensionFontsHeight = 0
self._enableDefaultFonts = True
def setFontsABC(self, fonts):
self._haveFontsABC = True
self._fontsABC = fonts.fonts
self._fontsABCWidth = fonts.width
self._fontsABCHeight = fonts.height
self._fontsABCFmt = fonts.fmt
self._extensionFontsWidth = fonts.width * 2
self._extensionFontsHeight = fonts.height * 2
def setExFonts(self, obj):
self._haveExtensionFonts = True
self._extensionFonts = obj
self._enableDefaultFonts = False
def setEnableDefaultFonts(self, opt):
if opt:
self._enableDefaultFonts = True
else:
self._enableDefaultFonts = False
def setExFontsFmt(self, width, height):
if self._haveExtensionFonts:
self._extensionFonts.setFmt(width, height)
self._extensionFontsWidth = width
self._extensionFontsHeight = height
def getOneCharacter(self, c):
w = 0
h = 0
fmt = "UNKNOW"
rslt = []
done = False
if self._haveFontsABC and self._enableDefaultFonts:
try:
rslt = self._fontsABC[c]
w = self._fontsABCWidth
h = self._fontsABCHeight
fmt = self._fontsABCFmt
done = True
except:
# print("try get fonts ABC faild")
pass
if self._haveExtensionFonts and done == False:
try:
(rslt, w, h, fmt) = self._extensionFonts.getOne(c)
done = True
except:
print("try get unicode fonts faild: %s" %(c))
return (rslt, w, h, fmt)

View File

@ -0,0 +1,25 @@
# -*- coding:utf-8 -*-
import sys
class PrintString:
def __init__(self):
pass
def writeOneChar(self, ch):
pass
def printStr(self, c):
try:
c = str(c)
except:
return
if sys.version_info.major == 2:
c = c.decode("utf-8")
for i in c:
self.writeOneChar(i)
def printStrLn(self, c):
self.printStr(c)
self.writeOneChar("\n")

View File

@ -0,0 +1,250 @@
# -*- coding:utf-8 -*-
import time
import sys
sys.path.append("..")
import RPi.GPIO as RPIGPIO
from .dfrobot_display.dfrobot_display import DFRobot_Display
from .display_extension import fonts_8_16 as fonts_ABC
try:
from .spi import SPI
from .gpio import GPIO
except:
print("unknow platform")
exit()
CONFIG_IL0376F = {
}
CONFIG_IL3895 = {
}
class DFRobot_Epaper(DFRobot_Display):
XDOT = 128
YDOT = 250
FULL = True
PART = False
def __init__(self, width = 250, height = 122):
DFRobot_Display.__init__(self, width, height)
# length = width * height // 8
length = 4000
self._displayBuffer = bytearray(length)
i = 0
while i < length:
self._displayBuffer[i] = 0xff
i = i + 1
self._isBusy = False
self._busyExitEdge = GPIO.RISING
self._fonts.setFontsABC(fonts_ABC)
self.setExFontsFmt(16, 16)
def _busyCB(self, channel):
self._isBusy = False
def setBusyExitEdge(self, edge):
if edge != GPIO.HIGH and edge != GPIO.LOW:
return
self._busyEdge = edge
def begin(self):
pass
#self._init()
#self._powerOn()
#self.setBusyCB(self._busyCB)
#self._powerOn()
def setBuffer(self, buffer):
self._displayBuffer = buffer
def pixel(self, x, y, color):
if x < 0 or x >= self._width:
return
if y < 0 or y >= self._height:
return
x = int(x)
y = int(y)
m = int(x * 16 + (y + 1) / 8)
sy = int((y + 1) % 8)
if color == self.WHITE:
if sy != 0:
self._displayBuffer[m] = self._displayBuffer[m] | int(pow(2, 8 - sy))
else:
self._displayBuffer[m - 1] = self._displayBuffer[m - 1] | 1
elif color == self.BLACK:
if sy != 0:
self._displayBuffer[m] = self._displayBuffer[m] & (0xff - int(pow(2, 8 - sy)))
else:
self._displayBuffer[m - 1] = self._displayBuffer[m - 1] & 0xfe
def _initLut(self, mode):
if mode == self.FULL:
self.writeCmdAndData(0x32, [ 0xA0, 0x90, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x50, 0x90, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xA0, 0x90, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x50, 0x90, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0F, 0x0F, 0x00, 0x00, 0x00,
0x0F, 0x0F, 0x00, 0x00, 0x03,
0x0F, 0x0F, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
])
elif mode == self.PART:
self.writeCmdAndData(0x32, [0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x50, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,
0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0f, 0x00, 0x00, 0x00, 0x00,
0x0, 0x00, 0x00, 0x00, 0x00,
0x0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
])
def _setRamData(self, xStart, xEnd, yStart, yStart1, yEnd, yEnd1):
self.writeCmdAndData(0x44, [xStart, xEnd])
self.writeCmdAndData(0x45, [yStart, yStart1, yEnd, yEnd1])
def _setRamPointer(self, x, y, y1):
self.writeCmdAndData(0x4e, [x])
self.writeCmdAndData(0x4f, [y, y1])
def _init(self,mode):
self.writeCmdAndData(0x12, [])
self.writeCmdAndData(0x01, [0xf9, 0x00, 0x00])
self.writeCmdAndData(0x74, [0x54])
self.writeCmdAndData(0x7e, [0x3b])
self.writeCmdAndData(0x11, [0x01])
self._setRamData(0x00, 0x0f, 0xf9,0x00, 0x00, 0x00)
self.writeCmdAndData(0x3c, [0x03])
self._setRamPointer(0x00, 0xf9, 0x00)
self.writeCmdAndData(0x21, [0x08])
self.writeCmdAndData(0x2c, [0x50])
self.writeCmdAndData(0x03, [0x15])
self.writeCmdAndData(0x04, [0x41,0xa8,0x32])
self.writeCmdAndData(0x3a, [0x2c])
self.writeCmdAndData(0x3b, [0x0b])
self.writeCmdAndData(0x0c, [0x8b,0x9c,0x96,0x0f])
def _writeDisRam(self, sizeX, sizeY):
if sizeX % 8 != 0:
sizeX = sizeX + (8 - sizeX % 8)
sizeX = sizeX // 8
self.writeCmdAndData(0x24, self._displayBuffer[0: sizeX * sizeY])
def _updateDis(self, mode):
if mode == self.FULL:
self.writeCmdAndData(0x22, [0xc7])
elif mode == self.PART:
self.writeCmdAndData(0x22, [0xc7])
else:
return
self.writeCmdAndData(0x20, [])
def _waitBusyExit(self):
temp = 0
while self.readBusy() != False:
time.sleep(0.01)
temp = temp + 1
if (temp % 200) == 0:
print("waitBusyExit")
def _powerOn(self):
self.writeCmdAndData(0x22, [0xC0])
self.writeCmdAndData(0x20, [])
def _powerOff(self):
self.writeCmdAndData(0x10, [0x01])
time.sleep(0.1)
def _disPart(self, xStart, xEnd, yStart, yEnd):
self._setRamData(xStart // 8, xEnd // 8, yEnd % 256, yEnd // 256, yStart % 256, yStart // 256)
self._setRamPointer(xStart // 8, yEnd % 256, yEnd // 256)
self._writeDisRam(xEnd - xStart, yEnd - yStart + 1)
self._updateDis(self.PART)
def flush(self, mode):
if mode != self.FULL and mode != self.PART:
return
self._init(mode)
self._initLut(mode)
self._powerOn()
if mode == self.PART:
self._disPart(0, self.XDOT - 1, 0, self.YDOT - 1)
else:
self._setRamPointer(0x00, (self.YDOT - 1) % 256, (self.YDOT - 1) // 256)
self._writeDisRam(self.XDOT, self.YDOT)
self._updateDis(self.FULL)
def startDrawBitmapFile(self, x, y):
self._bitmapFileStartX = x
self._bitmapFileStartY = y
def bitmapFileHelper(self, buf):
for i in range(len(buf) // 3):
addr = i * 3
if buf[addr] == 0x00 and buf[addr + 1] == 0x00 and buf[addr + 2] == 0x00:
self.pixel(self._bitmapFileStartX, self._bitmapFileStartY, self.BLACK)
else:
self.pixel(self._bitmapFileStartX, self._bitmapFileStartY, self.WHITE)
self._bitmapFileStartX += 1
def endDrawBitmapFile(self):
self.flush(self.PART)
class DFRobot_Epaper_SPI(DFRobot_Epaper):
def __init__(self, bus, dev, cs, cd, busy):
DFRobot_Epaper.__init__(self)
self._spi = SPI(bus, dev)
self._cs = GPIO(cs, GPIO.OUT)
self._cd = GPIO(cd, GPIO.OUT)
self._busy = GPIO(busy, GPIO.IN)
def writeCmdAndData(self, cmd, data = []):
self._waitBusyExit()
self._cs.setOut(GPIO.LOW)
self._cd.setOut(GPIO.LOW)
self._spi.transfer([cmd])
self._cd.setOut(GPIO.HIGH)
self._spi.transfer(data)
self._cs.setOut(GPIO.HIGH)
def readBusy(self):
return self._busy.read()
def setBusyCB(self, cb):
self._busy.setInterrupt(self._busyExitEdge, cb)
def __del__(self):
RPIGPIO.cleanup()

View File

@ -0,0 +1,101 @@
fonts = { # left to right, msb to bottom, lsb to top
" ": [0x00,0x00,0x00,0x00,0x00,0x00],
"!": [0x00,0x00,0x5F,0x00,0x00,0x00],
"\"": [0x00,0x07,0x00,0x07,0x00,0x00],
"#": [0x14,0x7F,0x14,0x7F,0x14,0x00],
"$": [0x24,0x2A,0x7F,0x2A,0x12,0x00],
"%": [0x23,0x13,0x08,0x64,0x62,0x00],
"&": [0x36,0x49,0x56,0x20,0x50,0x00],
"'": [0x00,0x08,0x07,0x03,0x00,0x00],
"(": [0x00,0x1C,0x22,0x41,0x00,0x00],
")": [0x00,0x41,0x22,0x1C,0x00,0x00],
"*": [0x24,0x18,0x7E,0x18,0x24,0x00],
"+": [0x08,0x08,0x3E,0x08,0x08,0x00],
",": [0x00,0x80,0x70,0x30,0x00,0x00],
"-": [0x08,0x08,0x08,0x08,0x08,0x00],
".": [0x00,0x00,0x60,0x60,0x00,0x00],
"/": [0x20,0x10,0x08,0x04,0x02,0x00],
"0": [0x3E,0x41,0x49,0x41,0x3E,0x00],
"1": [0x00,0x42,0x7F,0x40,0x00,0x00],
"2": [0x72,0x49,0x49,0x49,0x46,0x00],
"3": [0x21,0x41,0x49,0x4D,0x32,0x00],
"4": [0x18,0x14,0x12,0x7F,0x10,0x00],
"5": [0x27,0x45,0x45,0x45,0x38,0x00],
"6": [0x3C,0x4A,0x49,0x49,0x31,0x00],
"7": [0x41,0x21,0x11,0x09,0x07,0x00],
"8": [0x36,0x49,0x49,0x49,0x36,0x00],
"9": [0x46,0x49,0x49,0x29,0x16,0x00],
":": [0x00,0x00,0x14,0x00,0x00,0x00],
";": [0x00,0x40,0x34,0x00,0x00,0x00],
"<": [0x00,0x08,0x14,0x22,0x41,0x00],
"=": [0x14,0x14,0x14,0x14,0x14,0x00],
">": [0x00,0x41,0x22,0x14,0x08,0x00],
"?": [0x02,0x01,0x59,0x09,0x06,0x00],
"@": [0x3E,0x41,0x5D,0x59,0x4E,0x00],
"A": [0x7C,0x12,0x11,0x12,0x7C,0x00],
"B": [0x7F,0x49,0x49,0x49,0x36,0x00],
"C": [0x3E,0x41,0x41,0x41,0x22,0x00],
"D": [0x7F,0x41,0x41,0x41,0x3E,0x00],
"E": [0x7F,0x49,0x49,0x49,0x41,0x00],
"F": [0x7F,0x09,0x09,0x09,0x01,0x00],
"G": [0x3E,0x41,0x41,0x51,0x73,0x00],
"H": [0x7F,0x08,0x08,0x08,0x7F,0x00],
"I": [0x00,0x41,0x7F,0x41,0x00,0x00],
"J": [0x20,0x40,0x41,0x3F,0x01,0x00],
"K": [0x7F,0x08,0x14,0x22,0x41,0x00],
"L": [0x7F,0x40,0x40,0x40,0x40,0x00],
"M": [0x7F,0x02,0x1C,0x02,0x7F,0x00],
"N": [0x7F,0x04,0x08,0x10,0x7F,0x00],
"O": [0x3E,0x41,0x41,0x41,0x3E,0x00],
"P": [0x7F,0x09,0x09,0x09,0x06,0x00],
"Q": [0x3E,0x41,0x51,0x21,0x5E,0x00],
"R": [0x7F,0x09,0x19,0x29,0x46,0x00],
"S": [0x26,0x49,0x49,0x49,0x32,0x00],
"T": [0x03,0x01,0x7F,0x01,0x03,0x00],
"U": [0x3F,0x40,0x40,0x40,0x3F,0x00],
"V": [0x1F,0x20,0x40,0x20,0x1F,0x00],
"W": [0x3F,0x40,0x38,0x40,0x3F,0x00],
"X": [0x63,0x14,0x08,0x14,0x63,0x00],
"Y": [0x03,0x04,0x78,0x04,0x03,0x00],
"Z": [0x61,0x59,0x49,0x4D,0x43,0x00],
"[": [0x00,0x7F,0x41,0x41,0x41,0x00],
"\\": [0x02,0x04,0x08,0x10,0x20,0x00],
"]": [0x00,0x41,0x41,0x41,0x7f,0x00],
"^": [0x04,0x02,0x01,0x02,0x04,0x00],
"_": [0x40,0x40,0x40,0x40,0x46,0x00],
"'": [0x00,0x03,0x07,0x08,0x00,0x00],
"a": [0x20,0x54,0x54,0x78,0x40,0x00],
"b": [0x7F,0x28,0x44,0x44,0x38,0x00],
"c": [0x38,0x44,0x44,0x44,0x28,0x00],
"d": [0x38,0x44,0x44,0x28,0x7F,0x00],
"e": [0x38,0x54,0x54,0x54,0x18,0x00],
"f": [0x00,0x08,0x7E,0x09,0x02,0x00],
"g": [0x38,0xA4,0xA4,0x9C,0x78,0x00],
"h": [0x7F,0x08,0x04,0x04,0x78,0x00],
"i": [0x00,0x44,0x7D,0x40,0x00,0x00],
"j": [0x20,0x40,0x40,0x3D,0x00,0x00],
"k": [0x7F,0x10,0x28,0x44,0x00,0x00],
"l": [0x00,0x41,0x7F,0x40,0x00,0x00],
"m": [0x7C,0x04,0x78,0x04,0x78,0x00],
"n": [0x7C,0x08,0x04,0x04,0x78,0x00],
"o": [0x38,0x44,0x44,0x44,0x38,0x00],
"p": [0xFC,0x18,0x24,0x24,0x18,0x00],
"q": [0x18,0x24,0x24,0x18,0xFC,0x00],
"r": [0x7C,0x08,0x04,0x04,0x08,0x00],
"s": [0x48,0x54,0x54,0x54,0x24,0x00],
"t": [0x04,0x04,0x3F,0x44,0x24,0x00],
"u": [0x3C,0x40,0x40,0x20,0x7C,0x00],
"v": [0x1C,0x20,0x40,0x20,0x1C,0x00],
"w": [0x3C,0x40,0x20,0x40,0x3C,0x00],
"x": [0x44,0x28,0x10,0x28,0x44,0x00],
"y": [0x4C,0x90,0x90,0x90,0x7C,0x00],
"z": [0x44,0x64,0x54,0x4C,0x44,0x00],
"{": [0x00,0x08,0x36,0x41,0x00,0x00],
"|": [0x00,0x00,0x77,0x00,0x00,0x00],
"}": [0x00,0x41,0x36,0x08,0x00,0x00],
"~": [0x02,0x01,0x02,0x04,0x02,0x00]
}
width = 6
height = 8
fmt = "LRMBLT"

View File

@ -0,0 +1,101 @@
fonts = { # top to bottom, msb left, lsb right
" ": [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
"!": [0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00],
"\"": [0x00,0x63,0x63,0x63,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
"#": [0x00,0x00,0x00,0x36,0x36,0x7F,0x36,0x36,0x36,0x7F,0x36,0x36,0x00,0x00,0x00,0x00],
"$": [0x0C,0x0C,0x3E,0x63,0x61,0x60,0x3E,0x03,0x03,0x43,0x63,0x3E,0x0C,0x0C,0x00,0x00],
"%": [0x00,0x00,0x00,0x00,0x00,0x61,0x63,0x06,0x0C,0x18,0x33,0x63,0x00,0x00,0x00,0x00],
"&": [0x00,0x00,0x00,0x1C,0x36,0x36,0x1C,0x3B,0x6E,0x66,0x66,0x3B,0x00,0x00,0x00,0x00],
"'": [0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
"(": [0x00,0x00,0x0C,0x18,0x18,0x30,0x30,0x30,0x30,0x18,0x18,0x0C,0x00,0x00,0x00,0x00],
")": [0x00,0x00,0x18,0x0C,0x0C,0x06,0x06,0x06,0x06,0x0C,0x0C,0x18,0x00,0x00,0x00,0x00],
"*": [0x00,0x00,0x00,0x00,0x42,0x66,0x3C,0xFF,0x3C,0x66,0x42,0x00,0x00,0x00,0x00,0x00],
"+": [0x00,0x00,0x00,0x00,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00],
",": [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00],
"-": [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
".": [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00],
"/": [0x00,0x00,0x01,0x03,0x07,0x0E,0x1C,0x38,0x70,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00],
"0": [0x00,0x00,0x3E,0x63,0x63,0x63,0x6B,0x6B,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00],
"1": [0x00,0x00,0x0C,0x1C,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3F,0x00,0x00,0x00,0x00],
"2": [0x00,0x00,0x3E,0x63,0x03,0x06,0x0C,0x18,0x30,0x61,0x63,0x7F,0x00,0x00,0x00,0x00],
"3": [0x00,0x00,0x3E,0x63,0x03,0x03,0x1E,0x03,0x03,0x03,0x63,0x3E,0x00,0x00,0x00,0x00],
"4": [0x00,0x00,0x06,0x0E,0x1E,0x36,0x66,0x66,0x7F,0x06,0x06,0x0F,0x00,0x00,0x00,0x00],
"5": [0x00,0x00,0x7F,0x60,0x60,0x60,0x7E,0x03,0x03,0x63,0x73,0x3E,0x00,0x00,0x00,0x00],
"6": [0x00,0x00,0x1C,0x30,0x60,0x60,0x7E,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00],
"7": [0x00,0x00,0x7F,0x63,0x03,0x06,0x06,0x0C,0x0C,0x18,0x18,0x18,0x00,0x00,0x00,0x00],
"8": [0x00,0x00,0x3E,0x63,0x63,0x63,0x3E,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00],
"9": [0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x3F,0x03,0x03,0x06,0x3C,0x00,0x00,0x00,0x00],
":": [0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00],
";": [0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00],
"<": [0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00],
"=": [0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00],
">": [0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00],
"?": [0x00,0x00,0x3E,0x63,0x63,0x06,0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x00,0x00,0x00,0x00],
"@": [0x00,0x00,0x3E,0x63,0x63,0x6F,0x6B,0x6B,0x6E,0x60,0x60,0x3E,0x00,0x00,0x00,0x00],
"A": [0x00,0x00,0x08,0x1C,0x36,0x63,0x63,0x63,0x7F,0x63,0x63,0x63,0x00,0x00,0x00,0x00],
"B": [0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x33,0x33,0x33,0x33,0x7E,0x00,0x00,0x00,0x00],
"C": [0x00,0x00,0x1E,0x33,0x61,0x60,0x60,0x60,0x60,0x61,0x33,0x1E,0x00,0x00,0x00,0x00],
"D": [0x00,0x00,0x7C,0x36,0x33,0x33,0x33,0x33,0x33,0x33,0x36,0x7C,0x00,0x00,0x00,0x00],
"E": [0x00,0x00,0x7F,0x33,0x31,0x34,0x3C,0x34,0x30,0x31,0x33,0x7F,0x00,0x00,0x00,0x00],
"F": [0x00,0x00,0x7F,0x33,0x31,0x34,0x3C,0x34,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00],
"G": [0x00,0x00,0x1E,0x33,0x61,0x60,0x60,0x6F,0x63,0x63,0x37,0x1D,0x00,0x00,0x00,0x00],
"H": [0x00,0x00,0x63,0x63,0x63,0x63,0x7F,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00],
"I": [0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00],
"J": [0x00,0x00,0x0F,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,0x00,0x00,0x00],
"K": [0x00,0x00,0x73,0x33,0x36,0x36,0x3C,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00],
"L": [0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x33,0x7F,0x00,0x00,0x00,0x00],
"M": [0x00,0x00,0x63,0x77,0x7F,0x6B,0x63,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00],
"N": [0x00,0x00,0x63,0x63,0x73,0x7B,0x7F,0x6F,0x67,0x63,0x63,0x63,0x00,0x00,0x00,0x00],
"O": [0x00,0x00,0x1C,0x36,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1C,0x00,0x00,0x00,0x00],
"P": [0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00],
"Q": [0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x63,0x63,0x6B,0x6F,0x3E,0x06,0x07,0x00,0x00],
"R": [0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00],
"S": [0x00,0x00,0x3E,0x63,0x63,0x30,0x1C,0x06,0x03,0x63,0x63,0x3E,0x00,0x00,0x00,0x00],
"T": [0x00,0x00,0xFF,0xDB,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00],
"U": [0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00],
"V": [0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1C,0x08,0x00,0x00,0x00,0x00],
"W": [0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x36,0x36,0x00,0x00,0x00,0x00],
"X": [0x00,0x00,0xC3,0xC3,0x66,0x3C,0x18,0x18,0x3C,0x66,0xC3,0xC3,0x00,0x00,0x00,0x00],
"Y": [0x00,0x00,0xC3,0xC3,0xC3,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00],
"Z": [0x00,0x00,0x7F,0x63,0x43,0x06,0x0C,0x18,0x30,0x61,0x63,0x7F,0x00,0x00,0x00,0x00],
"[": [0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00],
"\\": [0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x07,0x03,0x01,0x00,0x00,0x00,0x00],
"]": [0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00],
"^": [0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
"_": [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00],
"'": [0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
"a": [0x00,0x00,0x00,0x00,0x00,0x3C,0x46,0x06,0x3E,0x66,0x66,0x3B,0x00,0x00,0x00,0x00],
"b": [0x00,0x00,0x70,0x30,0x30,0x3C,0x36,0x33,0x33,0x33,0x33,0x6E,0x00,0x00,0x00,0x00],
"c": [0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x60,0x60,0x60,0x63,0x3E,0x00,0x00,0x00,0x00],
"d": [0x00,0x00,0x0E,0x06,0x06,0x1E,0x36,0x66,0x66,0x66,0x66,0x3B,0x00,0x00,0x00,0x00],
"e": [0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x63,0x7E,0x60,0x63,0x3E,0x00,0x00,0x00,0x00],
"f": [0x00,0x00,0x1C,0x36,0x32,0x30,0x7C,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00],
"g": [0x00,0x00,0x00,0x00,0x00,0x3B,0x66,0x66,0x66,0x66,0x3E,0x06,0x66,0x3C,0x00,0x00],
"h": [0x00,0x00,0x70,0x30,0x30,0x36,0x3B,0x33,0x33,0x33,0x33,0x73,0x00,0x00,0x00,0x00],
"i": [0x00,0x00,0x0C,0x0C,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00],
"j": [0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,0x00],
"k": [0x00,0x00,0x70,0x30,0x30,0x33,0x33,0x36,0x3C,0x36,0x33,0x73,0x00,0x00,0x00,0x00],
"l": [0x00,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00],
"m": [0x00,0x00,0x00,0x00,0x00,0x6E,0x7F,0x6B,0x6B,0x6B,0x6B,0x6B,0x00,0x00,0x00,0x00],
"n": [0x00,0x00,0x00,0x00,0x00,0x6E,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x00],
"o": [0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00],
"p": [0x00,0x00,0x00,0x00,0x00,0x6E,0x33,0x33,0x33,0x33,0x3E,0x30,0x30,0x78,0x00,0x00],
"q": [0x00,0x00,0x00,0x00,0x00,0x3B,0x66,0x66,0x66,0x66,0x3E,0x06,0x06,0x0F,0x00,0x00],
"r": [0x00,0x00,0x00,0x00,0x00,0x6E,0x3B,0x33,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00],
"s": [0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x38,0x0E,0x03,0x63,0x3E,0x00,0x00,0x00,0x00],
"t": [0x00,0x00,0x08,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x1B,0x0E,0x00,0x00,0x00,0x00],
"u": [0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x3B,0x00,0x00,0x00,0x00],
"v": [0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x36,0x36,0x1C,0x1C,0x08,0x00,0x00,0x00,0x00],
"w": [0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x36,0x00,0x00,0x00,0x00],
"x": [0x00,0x00,0x00,0x00,0x00,0x63,0x36,0x1C,0x1C,0x1C,0x36,0x63,0x00,0x00,0x00,0x00],
"y": [0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x3F,0x03,0x06,0x3C,0x00,0x00],
"z": [0x00,0x00,0x00,0x00,0x00,0x7F,0x66,0x0C,0x18,0x30,0x63,0x7F,0x00,0x00,0x00,0x00],
"{": [0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00],
"|": [0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00],
"}": [0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00],
"~": [0x00,0x00,0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
}
width = 8
height = 16
fmt = "TBMLLR"

View File

@ -0,0 +1,80 @@
# -*- coding:utf-8 -*-
'''
depends: freetype-py
'''
import freetype
import math
#import sys
#reload(sys)
#sys.setdefaultencoding("utf-8")
import importlib,sys
#importlib.reload(sys)
class Freetype_Helper:
def __init__(self, filePath):
self._face = freetype.Face(filePath)
self._width = 0
self._height = 0
self._fade = 96
def setFmt(self, width, height):
self._width = int(width)
self._height = int(height)
self._face.set_pixel_sizes(width, height)
def setDisLowerLimite(self, limite):
self._fade = limite
def getOne(self, ch):
self._face.load_char(ch)
bitmap = self._face.glyph.bitmap
originY = self._face.glyph.bitmap_top
width = bitmap.width
height = bitmap.rows
buffer = bitmap.buffer
rslt = []
# width = 4
# height = 4
# buffer = [0xff] * width * height
if height > self._height:
buffer = buffer[0: width * self._height]
height = self._height
if width > self._width:
for i in range(height):
rslt += buffer[i * width: i * width + self._width]
width = self._width
buffer = rslt
rslt = []
if (ord(ch) >= ord(" ") and ord(ch) <= ord("~")) or width <= (self._width // 2):
rslt = [0] * (((self._width - 1) // 16 + 1) * self._height + 1)
left = (self._width // 2 - width) // 2
lineDataLen = (self._width - 1) // 16 + 1
else:
rslt = [0] * (((self._width - 1) // 8 + 1) * self._height + 1)
left = (self._width - width) // 2
lineDataLen = (self._width - 1) // 8 + 1
if left < 0:
left = 0
# top = (self._height - height) * lineDataLen // 2
top = ((self._height * 8 + 5) // 10 - originY) * lineDataLen
if top < 0:
top = 0
for i in range(height):
for j in range(width):
if buffer[i * width + j] > self._fade:
try:
rslt[i * lineDataLen + (j + left) // 8 + top] |= 0x80 >> ((j + left) % 8)
except:
print("freetype_helper getOne err: width: %d, height: %d, top: %d, left: %d, rslt_len: %d, originY: %d" %(width, height, top, left, len(rslt), originY))
raise("err")
# rslt[i * lineDataLen + (j + left) // 8 + top] |= 0x80 >> ((j + left) % 8)
if (ord(ch) >= ord(" ") and ord(ch) <= ord("~")) or width < (self._width // 2):
return (rslt, self._width // 2, self._height, "TBMLLR")
else:
return (rslt, self._width, self._height, "TBMLLR")

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@ -0,0 +1,2 @@
wqydkzh.ttf = 文泉驿等宽正黑.ttf GPL2 license </br>
zkklt.ttf = 站酷快乐体.ttf Chinese open source fonts file, use with freetype_helper.py

View File

@ -0,0 +1,64 @@
# -*- coding:utf-8 -*-
import time
import RPi.GPIO as RPIGPIO
RPIGPIO.setmode(RPIGPIO.BCM)
RPIGPIO.setwarnings(False)
class GPIO:
HIGH = RPIGPIO.HIGH
LOW = RPIGPIO.LOW
OUT = RPIGPIO.OUT
IN = RPIGPIO.IN
RISING = RPIGPIO.RISING
FALLING = RPIGPIO.FALLING
BOTH = RPIGPIO.BOTH
def __init__(self, pin, mode, defaultOut = HIGH):
self._pin = pin
self._fInt = None
self._intDone = True
self._intMode = None
if mode == self.OUT:
RPIGPIO.setup(pin, mode)
if defaultOut == self.HIGH:
RPIGPIO.output(pin, defaultOut)
else:
RPIGPIO.output(pin, self.LOW)
else:
RPIGPIO.setup(pin, self.IN, pull_up_down = RPIGPIO.PUD_UP)
def setOut(self, level):
if level:
RPIGPIO.output(self._pin, self.HIGH)
else:
RPIGPIO.output(self._pin, self.LOW)
def _intCB(self, status):
if self._intDone:
self._intDone = False
time.sleep(0.02)
if self._intMode == self.BOTH:
self._fInt()
elif self._intMode == self.RISING and self.read() == self.HIGH:
self._fInt()
elif self._intMode == self.FALLING and self.read() == self.LOW:
self._fInt()
self._intDone = True
def setInterrupt(self, mode, cb):
if mode != self.RISING and mode != self.FALLING and mode != self.BOTH:
return
self._intMode = mode
RPIGPIO.add_event_detect(self._pin, mode, self._intCB)
self._fInt = cb
def read(self):
return RPIGPIO.input(self._pin)
def cleanup(self):
RPIGPIO.cleanup()

View File

@ -0,0 +1,21 @@
# -*- coding:utf-8 -*-
'''
change i2c frequency on raspberry:
1. edit /etc/modprobe.d
2. add line:
options i2c_bcm2708 baudrate=400000
'''
import smbus
class I2C:
def __init__(self, port):
self._bus = smbus.SMBus(port)
def writeBytes(self, addr, reg, buf):
self._bus.write_block_data(addr, reg, buf)
def readBytes(self, addr, reg, length):
return self._bus.read_block_data(addr, reg, length)

View File

@ -0,0 +1,21 @@
# -*- coding:utf-8 -*-
import spidev
class SPI:
MODE_1 = 1
MODE_2 = 2
MODE_3 = 3
MODE_4 = 4
def __init__(self, bus, dev, speed = 3900000, mode = MODE_4):
self._bus = spidev.SpiDev()
self._bus.open(0, 0)
self._bus.no_cs = True
self._bus.max_speed_hz = speed
def transfer(self, buf):
if len(buf):
return self._bus.xfer(buf)
return []

View File

@ -257,8 +257,11 @@ def load_config(args):
elif config['ui']['display']['type'] in ('lcdhat',):
config['ui']['display']['type'] = 'lcdhat'
elif config['ui']['display']['type'] in ('dfrobot', 'df'):
config['ui']['display']['type'] = 'dfrobot'
elif config['ui']['display']['type'] in ('dfrobot_1', 'df1'):
config['ui']['display']['type'] = 'dfrobot_1'
elif config['ui']['display']['type'] in ('dfrobot_2', 'df2'):
config['ui']['display']['type'] = 'dfrobot_2'
elif config['ui']['display']['type'] in ('ws_154inch', 'ws154inch', 'waveshare_154inch', 'waveshare154inch'):
config['ui']['display']['type'] = 'waveshare154inch'