板级调试小助手(3)基于PYNQ的OLED视频显示

一、前言

在之前的文章中介绍了《板级调试小助手》的系统结构和DDS自定义外设的搭建。这篇文章主要介绍一下如何在PYNQ中驱动平时长剑的OLED12864显示屏,并显示BadApple(毕竟有屏幕的地方就要有BadApple)。效果如下:

BadApple

本项目完全开源,开源地址请查看《板级调试小助手(1)系统结构和原理》文章最后

二、OLED驱动设计

OLED显示屏使用了IIC协议,为了能方便PS端控制,我们需要将其设计成自动读取BRAM中的数据,并显示,OLED驱动的顶层如下所示。

cpp 复制代码
module oled_top #
(
    parameter   SLAVE_ADDR =  7'b0111100,       //从机地址
    parameter   CLK_FREQ   = 26'd100_000_000,   //系统时钟(Hz)
    parameter   I2C_FREQ   = 19'd350_000,       //IIC频率
    parameter   BIT_CTRL   =  1'b0              //字地址位控制(16b/8b)
)
(
    input sysClk,           //系统时钟
    input sysRst,           //全局复位

    //RAM数据接口
    output [9:0]rd_addr,        //读RAM地址
    input  [7:0]ram_rd_data,    //读RAM数据

    //IIC接口
    output      oled_scl,
    inout       oled_sda
);

wire            i2c_dir_clk     ;
wire            i2c_exec        ;
wire    [15:0]  i2c_data        ;
wire            i2c_done        ;


i2c_dri #(
    .SLAVE_ADDR (SLAVE_ADDR    ) ,
    .CLK_FREQ   (CLK_FREQ      ) ,   
    .I2C_FREQ   (I2C_FREQ      )     
)
i2c_dri_u (
    //global clock
    .clk        (sysClk          ), 
    .rst_n      (~sysRst         ), 
    .i2c_exec   (i2c_exec      ), 
    .bit_ctrl   (BIT_CTRL        ), 
    .i2c_rh_wl  (1'b0            ), 
    .i2c_addr   (i2c_data[15:8]), 
    .i2c_data_w (i2c_data[7:0] ), 
    .i2c_data_r (                ), 
    .i2c_done   (i2c_done      ), 
    .scl        (oled_scl      ), 
    .sda        (oled_sda     ), 
    .dri_clk    (i2c_dir_clk   )  
    );

oled_ctrl oled_ctrl_u(
    .I_sys_clk    (i2c_dir_clk),
    .I_reset_n    (~sysRst      ),
    .I_i2c_done   (i2c_done   ),
    .O_i2c_data   (i2c_data   ),
    .O_i2c_exec   (i2c_exec   ),
    .O_rd_addr    (rd_addr    ),
    .I_ram_rd_data(ram_rd_data)
);

endmodule

可以看到顶层代码中,除了IIC接口,也具有一个RAM数据读接口。 i2c_dri 模块是OLED驱动模块,oled_ctrl模块用于读取BRAM数据写入OLED的控制模块,具体代码这里就不展示了,需要请移步第一章最后的开源地址。

三、PS端的python代码处理

PL端设计好之后PS端就很好设计的,主要分为一下几个步骤:

1、调用OpenCV库读取.mp4文件,逐帧解析;

2、将解析后的视频帧转换成OLED可以显示的数据;

3、将数据通过AXI总线写入BRAM

PS端代码如下:

python 复制代码
#显示开机动画
video_path = '123.mp4';
cap = cv2.VideoCapture(video_path);  #创建VideoCapture对象
while True:
    ret, frame = cap.read()     #读一帧数据
    # 如果正确读取帧,ret为True
    if not ret:
        print("Error: No more frames to read.")
        break
    gray_image = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    _, binary_image = cv2.threshold(gray_image, 170, 255, cv2.THRESH_BINARY)
    #变成numpy可以处理的数组
    numpy_image = np.array(binary_image)
    #获取转换后的数据
    re_Addr,re_Data = oled.oled_show(numpy_image)
    #写入oled显示缓存
    for i in range(0, 256):
        bram_ip.write(re_Addr[i],re_Data[i])
相关推荐
鸥梨菌Honevid1 小时前
UVM 中 raise_objection 与 drop_objection 的作用与重要性详解
fpga开发
EasyGBS3 小时前
通信基站/铁塔机房无人值守,国标GB28181公网平台EasyGBS视频能力怎么去管
深度学习·安全·音视频
鲲穹AI种草4 小时前
音频剪辑降噪格式转换,鲲穹音频处理大师实测分享
音视频·音频剪辑
江节胜-胜行全栈AI5 小时前
实现海康/宇视NVR硬盘录像机/IPC摄像机监控历史回放录像rstp流视频的倍数下载
音视频
林墨聊AIGC6 小时前
AI分镜模板:一键生成高效短剧视觉流程
人工智能·ai作画·aigc·音视频·ai写作
程序员JerrySUN6 小时前
Jetson Edge AI 实战05:Secure Boot 到底在保护什么?PKC、SBK、Fuse 与可信启动链一次讲清【视频讲解】
arm开发·人工智能·安全·计算机视觉·目标跟踪·音视频
voipmaker6 小时前
选煤厂智能化:UWB 人员定位系统 WebAPI 对接融合通信平台实战
物联网·实时互动·json·音视频·实时音视频·web·视频
木头左8 小时前
音频转文字与说话人识别部署与使用指南
音视频
DogDaoDao8 小时前
当视频理解撞上大语言模型:一篇 37 页综述的全景拆解
人工智能·语言模型·音视频·知识图谱·视频
阿明副业观察8 小时前
AI短剧分镜秘籍:从零到电影级视觉冲击
大数据·人工智能·aigc·音视频·ai写作