Pwnagotchi_waveshare_V3适配(海南大学)(上)

简介: Pwnagotchi_waveshare_V3适配(海南大学)(上)

所需物料


  1. 树莓派(RPI-zero-w),记得得是w型号,不然无法扫描周围Wi-Fi
  2. waveshare_V3
  3. 移动电池(可选,用充电宝也行)
  4. 老式USB数据线
  5. 内存不少于16G的SD卡


image.jpeg


软件准备


微信图片_20220429232731.jpg



image.png



操作步骤


  1. 烧录镜像到SD卡中,注意烧录好不要插入树莓派中,只拔出即可
  2. 在电脑编辑器打开下载好的源代码,并按照以下修改添加


# pwnagotchi/ui/display.py
import os
import logging
import threading
import pwnagotchi.plugins as plugins
import pwnagotchi.ui.hw as hw
from pwnagotchi.ui.view import View
class Display(View):
    def __init__(self, config, state={}):
        super(Display, self).__init__(config, hw.display_for(config), state)
        config = config['ui']['display']
        self._enabled = config['enabled']
        self._rotation = config['rotation']
        self.init_display()
        self._canvas_next_event = threading.Event()
        self._canvas_next = None
        self._render_thread_instance = threading.Thread(
            target=self._render_thread,
            daemon=True
        )
        self._render_thread_instance.start()
    def is_inky(self):
        return self._implementation.name == 'inky'
    def is_papirus(self):
        return self._implementation.name == 'papirus'
    def is_waveshare_v1(self):
        return self._implementation.name == 'waveshare_1'
    def is_waveshare_v2(self):
        return self._implementation.name == 'waveshare_2'
    def is_waveshare_v3(self):
        return self._implementation.name == 'waveshare_3'
    def is_waveshare27inch(self):
        return self._implementation.name == 'waveshare27inch'
    def is_waveshare29inch(self):
        return self._implementation.name == 'waveshare29inch'
    def is_oledhat(self):
        return self._implementation.name == 'oledhat'
    def is_lcdhat(self):
        return self._implementation.name == 'lcdhat'
    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'
    def is_waveshare154inch(self):
        return self._implementation.name == 'waveshare154inch'
    def is_waveshare213d(self):
        return self._implementation.name == 'waveshare213d'
    def is_waveshare213bc(self):
        return self._implementation.name == 'waveshare213bc'
    def is_spotpear24inch(self):
        return self._implementation.name == 'spotpear24inch'
    def is_waveshare_any(self):
        return self.is_waveshare_v1() or self.is_waveshare_v2()
    def init_display(self):
        if self._enabled:
            self._implementation.initialize()
            plugins.on('display_setup', self._implementation)
        else:
            logging.warning("display module is disabled")
        self.on_render(self._on_view_rendered)
    def clear(self):
        self._implementation.clear()
    def image(self):
        img = None
        if self._canvas is not None:
            img = self._canvas if self._rotation == 0 else self._canvas.rotate(-self._rotation)
        return img
    def _render_thread(self):
        """Used for non-blocking screen updating."""
        while True:
            self._canvas_next_event.wait()
            self._canvas_next_event.clear()
            self._implementation.render(self._canvas_next)
    def _on_view_rendered(self, img):
        try:
            if self._config['ui']['web']['on_frame'] != '':
                os.system(self._config['ui']['web']['on_frame'])
        except Exception as e:
            logging.error("%s" % e)
        if self._enabled:
            self._canvas = (img if self._rotation == 0 else img.rotate(self._rotation))
            if self._implementation is not None:
                self._canvas_next = self._canvas
                self._canvas_next_event.set()


# pwnagotchi/ui/hw/__init__.py
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.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.waveshare3 import WaveshareV3
from pwnagotchi.ui.hw.waveshare27inch import Waveshare27inch
from pwnagotchi.ui.hw.waveshare29inch import Waveshare29inch
from pwnagotchi.ui.hw.waveshare144lcd import Waveshare144lcd
from pwnagotchi.ui.hw.waveshare154inch import Waveshare154inch
from pwnagotchi.ui.hw.waveshare213d import Waveshare213d
from pwnagotchi.ui.hw.waveshare213bc import Waveshare213bc
from pwnagotchi.ui.hw.spotpear24inch import Spotpear24inch
def display_for(config):
    # config has been normalized already in utils.load_config
    if config['ui']['display']['type'] == 'inky':
        return Inky(config)
    elif config['ui']['display']['type'] == 'papirus':
        return Papirus(config)
    if config['ui']['display']['type'] == 'oledhat':
        return OledHat(config)
    if config['ui']['display']['type'] == 'lcdhat':
        return LcdHat(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)
    elif config['ui']['display']['type'] == 'waveshare_2':
        return WaveshareV2(config)
    elif config['ui']['display']['type'] == 'waveshare_3':
        return WaveshareV3(config)
    elif config['ui']['display']['type'] == 'waveshare27inch':
        return Waveshare27inch(config)
    elif config['ui']['display']['type'] == 'waveshare29inch':
        return Waveshare29inch(config)
    elif config['ui']['display']['type'] == 'waveshare144lcd':
        return Waveshare144lcd(config)
    elif config['ui']['display']['type'] == 'waveshare154inch':
        return Waveshare154inch(config)
    elif config['ui']['display']['type'] == 'waveshare213d':
        return Waveshare213d(config)
    elif config['ui']['display']['type'] == 'waveshare213bc':
        return Waveshare213bc(config)
    elif config['ui']['display']['type'] == 'spotpear24inch':
        return Spotpear24inch(config)


# pwnagotchi/ui/hw/libs/waveshare/v3/epd2in13_V3.py
import logging
from . import epdconfig
import numpy as np
# Display resolution
EPD_WIDTH       = 122
EPD_HEIGHT      = 250
logger = logging.getLogger(__name__)
class EPD:
    def __init__(self):
        self.reset_pin = epdconfig.RST_PIN
        self.dc_pin = epdconfig.DC_PIN
        self.busy_pin = epdconfig.BUSY_PIN
        self.cs_pin = epdconfig.CS_PIN
        self.width = EPD_WIDTH
        self.height = EPD_HEIGHT
    lut_partial_update= [
        0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x80,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x40,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x14,0x0,0x0,0x0,0x0,0x0,0x0,  
        0x1,0x0,0x0,0x0,0x0,0x0,0x0,
        0x1,0x0,0x0,0x0,0x0,0x0,0x0,
        0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0,
        0x22,0x17,0x41,0x00,0x32,0x36,
    ]
    lut_full_update = [ 
        0x80,0x4A,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x40,0x4A,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x80,0x4A,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x40,0x4A,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0xF,0x0,0x0,0x0,0x0,0x0,0x0,
        0xF,0x0,0x0,0xF,0x0,0x0,0x2,
        0xF,0x0,0x0,0x0,0x0,0x0,0x0,
        0x1,0x0,0x0,0x0,0x0,0x0,0x0,
        0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x0,0x0,0x0,0x0,0x0,0x0,0x0,
        0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0,
        0x22,0x17,0x41,0x0,0x32,0x36,
    ]
    '''
    function :Hardware reset
    parameter:
    '''
    def reset(self):
        epdconfig.digital_write(self.reset_pin, 1)
        epdconfig.delay_ms(20) 
        epdconfig.digital_write(self.reset_pin, 0)
        epdconfig.delay_ms(2)
        epdconfig.digital_write(self.reset_pin, 1)
        epdconfig.delay_ms(20)   
    '''
    function :send command
    parameter:
     command : Command register
    '''
    def send_command(self, command):
        epdconfig.digital_write(self.dc_pin, 0)
        epdconfig.digital_write(self.cs_pin, 0)
        epdconfig.spi_writebyte([command])
        epdconfig.digital_write(self.cs_pin, 1)
    '''
    function :send data
    parameter:
     data : Write data
    '''
    def send_data(self, data):
        epdconfig.digital_write(self.dc_pin, 1)
        epdconfig.digital_write(self.cs_pin, 0)
        epdconfig.spi_writebyte([data])
        epdconfig.digital_write(self.cs_pin, 1)
    '''
    function :Wait until the busy_pin goes LOW
    parameter:
    '''
    def ReadBusy(self):
        logger.debug("e-Paper busy")
        while(epdconfig.digital_read(self.busy_pin) == 1):      # 0: idle, 1: busy
            epdconfig.delay_ms(10)  
        logger.debug("e-Paper busy release")
    '''
    function : Turn On Display
    parameter:
    '''
    def TurnOnDisplay(self):
        self.send_command(0x22) # Display Update Control
        self.send_data(0xC7)
        self.send_command(0x20) # Activate Display Update Sequence
        self.ReadBusy()
    '''
    function : Turn On Display Part
    parameter:
    '''
    def TurnOnDisplayPart(self):
        self.send_command(0x22) # Display Update Control
        self.send_data(0x0f)    # fast:0x0c, quality:0x0f, 0xcf
        self.send_command(0x20) # Activate Display Update Sequence
        self.ReadBusy()
    '''
    function : Set lut
    parameter:
        lut : lut data
    '''    
    def Lut(self, lut):
        self.send_command(0x32)
        for i in range(0, 153):
            self.send_data(lut[i])
        self.ReadBusy()
    '''
    function : Send lut data and configuration
    parameter:
        lut : lut data 
    '''
    def SetLut(self, lut):
        self.Lut(lut)
        self.send_command(0x3f)
        self.send_data(lut[153])
        self.send_command(0x03)     # gate voltage
        self.send_data(lut[154])
        self.send_command(0x04)     # source voltage
        self.send_data(lut[155])    # VSH
        self.send_data(lut[156])    # VSH2
        self.send_data(lut[157])    # VSL
        self.send_command(0x2c)     # VCOM
        self.send_data(lut[158])
    '''
    function : Setting the display window
    parameter:
        xstart : X-axis starting position
        ystart : Y-axis starting position
        xend : End position of X-axis
        yend : End position of Y-axis
    '''
    def SetWindow(self, x_start, y_start, x_end, y_end):
        self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION
        # x point must be the multiple of 8 or the last 3 bits will be ignored
        self.send_data((x_start>>3) & 0xFF)
        self.send_data((x_end>>3) & 0xFF)
        self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION
        self.send_data(y_start & 0xFF)
        self.send_data((y_start >> 8) & 0xFF)
        self.send_data(y_end & 0xFF)
        self.send_data((y_end >> 8) & 0xFF)
    '''
    function : Set Cursor
    parameter:
        x : X-axis starting position
        y : Y-axis starting position
    '''
    def SetCursor(self, x, y):
        self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER
        # x point must be the multiple of 8 or the last 3 bits will be ignored
        self.send_data(x & 0xFF)
        self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER
        self.send_data(y & 0xFF)
        self.send_data((y >> 8) & 0xFF)
    '''
    function : Initialize the e-Paper register
    parameter:
    '''
    def init(self):
        if (epdconfig.module_init() != 0):
            return -1
        # EPD hardware init start
        self.reset()
        self.ReadBusy()
        self.send_command(0x12)  #SWRESET
        self.ReadBusy() 
        self.send_command(0x01) #Driver output control      
        self.send_data(0xf9)
        self.send_data(0x00)
        self.send_data(0x00)
        self.send_command(0x11) #data entry mode       
        self.send_data(0x03)
        self.SetWindow(0, 0, self.width-1, self.height-1)
        self.SetCursor(0, 0)
        self.send_command(0x3c)
        self.send_data(0x05)
        self.send_command(0x21) #  Display update control
        self.send_data(0x00)
        self.send_data(0x80)
        self.send_command(0x18)
        self.send_data(0x80)
        self.ReadBusy()
        self.SetLut(self.lut_full_update)
        return 0
    '''
    function : Display images
    parameter:
        image : Image data
    '''
    def getbuffer(self, image):
        img = image
        imwidth, imheight = img.size
        if(imwidth == self.width and imheight == self.height):
            img = img.convert('1')
        elif(imwidth == self.height and imheight == self.width):
            # image has correct dimensions, but needs to be rotated
            img = img.rotate(90, expand=True).convert('1')
        else:
            logger.warning("Wrong image dimensions: must be " + str(self.width) + "x" + str(self.height))
            # return a blank buffer
            return [0x00] * (int(self.width/8) * self.height)
        buf = bytearray(img.tobytes('raw'))
        return buf
    '''
    function : Sends the image buffer in RAM to e-Paper and displays
    parameter:
        image : Image data
    '''
    def display(self, image):
        if self.width%8 == 0:
            linewidth = int(self.width/8)
        else:
            linewidth = int(self.width/8) + 1
        self.send_command(0x24)
        for j in range(0, self.height):
            for i in range(0, linewidth):
                self.send_data(image[i + j * linewidth])   
        self.TurnOnDisplay()
    '''
    function : Sends the image buffer in RAM to e-Paper and partial refresh
    parameter:
        image : Image data
    '''
    def displayPartial(self, image):
        if self.width%8 == 0:
            linewidth = int(self.width/8)
        else:
            linewidth = int(self.width/8) + 1
        epdconfig.digital_write(self.reset_pin, 0)
        epdconfig.delay_ms(1)
        epdconfig.digital_write(self.reset_pin, 1)  
        self.SetLut(self.lut_partial_update)
        self.send_command(0x37)
        self.send_data(0x00)
        self.send_data(0x00)
        self.send_data(0x00)
        self.send_data(0x00)
        self.send_data(0x00)
        self.send_data(0x40)
        self.send_data(0x00)
        self.send_data(0x00)
        self.send_data(0x00)  
        self.send_data(0x00)
        self.send_command(0x3C) #BorderWavefrom
        self.send_data(0x80)
        self.send_command(0x22) 
        self.send_data(0xC0)
        self.send_command(0x20)
        self.ReadBusy()
        self.SetWindow(0, 0, self.width - 1, self.height - 1)
        self.SetCursor(0, 0)
        self.send_command(0x24) # WRITE_RAM
        for j in range(0, self.height):
            for i in range(0, linewidth):
                self.send_data(image[i + j * linewidth])   
        self.TurnOnDisplayPart()
    '''
    function : Refresh a base image
    parameter:
        image : Image data
    '''
    def displayPartBaseImage(self, image):
        if self.width%8 == 0:
            linewidth = int(self.width/8)
        else:
            linewidth = int(self.width/8) + 1
        self.send_command(0x24)
        for j in range(0, self.height):
            for i in range(0, linewidth):
                self.send_data(image[i + j * linewidth])   
        self.send_command(0x26)
        for j in range(0, self.height):
            for i in range(0, linewidth):
                self.send_data(image[i + j * linewidth])  
        self.TurnOnDisplay()
    '''
    function : Clear screen
    parameter:
    '''
    def Clear(self, color):
        if self.width%8 == 0:
            linewidth = int(self.width/8)
        else:
            linewidth = int(self.width/8) + 1
        # logger.debug(linewidth)
        self.send_command(0x24)
        for j in range(0, self.height):
            for i in range(0, linewidth):
                self.send_data(color)
        self.TurnOnDisplay()
    '''
    function : Enter sleep mode
    parameter:
    '''
    def sleep(self):
        self.send_command(0x10) #enter deep sleep
        self.send_data(0x01)
        epdconfig.delay_ms(2000)
        epdconfig.module_exit()
### END OF FILE ###



相关文章
|
2月前
|
Android开发 iOS开发 API
鸿蒙开发:适配系统深浅色模式
无论是Android还是iOS,在系统设置中,都有着深色和浅色两种外观模式,同样,鸿蒙系统中也存在这样的外观切换,如何让自己的应用,跟随着系统的模式进行动态切换呢?目前系统给我们提供了两种方式可以实现,一种是资源形式,一种是动态的代码形式。
78 15
鸿蒙开发:适配系统深浅色模式
|
4月前
|
人工智能 数据可视化 Linux
插件发布新特性,让运动适配更简单。
为了提升开发者在AI运动场景中的应用体验,我们的AI运动识别插件已迭代至1.5.5版本,此次更新带来了“相对位置检测”与“骨骼图绘制器偏移”两大新特性,旨在简化运动适配流程,优化全屏模式下的使用体验,助力开发者更高效地开发健身、体育、体测、AR互动等应用。
|
9月前
|
编解码 前端开发
什么是适配?
什么是适配?
|
9月前
|
iOS开发
iPad适配
iPad适配
87 0
|
9月前
|
JSON iOS开发 数据格式
iPhont X适配
iPhont X适配
44 0
|
编解码 自然语言处理 前端开发
PC端高倍屏适配方案实践
随着PC端屏幕的发展,PC端也逐步出现了更高倍数的屏幕,相对于手机端的Retina屏,PC端也出现了多倍数适配的要求,本文主要是PC端高倍屏幕适配方案的一个实践总结,希望能给对PC端有适配高倍屏幕需求的同学有一些思路的启发和借鉴
219 0
|
前端开发 开发者 容器
总结适配方案|学习笔记
快速学习 总结适配方案
103 0
|
XML 编解码 Android开发
适配完结篇三 - 超稳定的values-wXXXdp适配方案(原创)
观点 • 适配还是使用百分比布局靠谱, 想一想 百分比 = match_parent其实值100%, 权重也是按比例 • 如何合理建立多套dimen值, 用数量取胜, 枚举市场上常见的最小宽度
798 0
适配完结篇三 - 超稳定的values-wXXXdp适配方案(原创)
|
网络安全 开发工具 数据安全/隐私保护
Pwnagotchi_waveshare_V5适配(海南大学)(下)
Pwnagotchi_waveshare_V5适配(海南大学)(下)
360 0
Pwnagotchi_waveshare_V5适配(海南大学)(下)
|
编解码 Linux 开发工具
RISC-V生态开发套件解析(十一):LicheeRV 86开发板MIPI/RGB显示输出方式切换
RISC-V生态开发套件解析(十一):LicheeRV 86开发板MIPI/RGB显示输出方式切换
714 0
RISC-V生态开发套件解析(十一):LicheeRV 86开发板MIPI/RGB显示输出方式切换