五、RIFFA框架下的桌面采集和 PCIE 传输项目

桌面采集和 PCIE 传输项目框图

在这里插入图片描述
任务描述:PC端先发送图片的配置包信息,然后上位机启动截屏APP应用程序,将截屏数据下发给FPGA,FPGA收到一帧的图像数据后会返回给上位机一个ACK信号,标志着上衣帧数据接收完毕,可以接收下一帧数据。DDR3实现fpga数据的缓存,HDMI完成DDR3图像的读取与显示。
其中:DDR3读写操作和HDMI显示直接移植之前的项目:UART+DDR3+HDMI
上位机与FPGA之间的PCIE通道也已经打通:使用riffa框架打通PC和fpga之间的PCIE通道
本项目主要完成上位机软件和Riffa框架间的Pcie交互设计。

在这里插入图片描述

可知:这里包含两个channl,一个是命令通道,一个是数据通道。

1. 配置通道设计

1.1 配置通道要求与conf_channel模块时序设计:

1.点击pc机上软件的button按钮,会向FPGA发送配置包信息,FPGA收到配置包信息后可以将配置数据解析出来

2.包结构:配置包长度为 8 个 32 位的 DW。包头为第 0 个 DW 32’h01010101,配置数据宽度 第 1 个 DW :按照宽度进行下发。配置数据高度 第 2 个 DW:按照高度进行下发。第 3~7 个 DW:为保留填充 0;

3.riffa收发数据位宽为64bit

在这里插入图片描述
实际发送数据为:
在这里插入图片描述

时序设计:
在这里插入图片描述

1.2 上位机发送配置包代码:
void Cpcie_api_exDlg::conf2pcie()
{
fpga_t * fpga;
int sent;
int id = 0;
int chnl = 0;
//这是配置包包头32’h01010101 宽度 1920 高度 1080
unsigned int sendBuffer[8] = {0x01010101,0x780,0x438,0x00,0x00,0x00,0x00,0x00};//config width 1920 height 
1080
//打开pcie 设备
fpga = fpga_open(id);
if (fpga == NULL) {
MessageBox(TEXT("打开Riffa设备失败!"), TEXT("警告"), MB_YESNO);
}
//发送配置数据 FPGA是指fpga设备,chnl是chnl编号,sendBuffer就是数据源地址,
//8是DW数量,0是指的offset,1是last信号,25000指的是25000ms的超时时间,如果25s内数据没有发送成功会异常返回。
sent = fpga_send(fpga, chnl, sendBuffer,8, 0, 1, 25000);
fpga_close(fpga);
}
1.3 ila观测信号:

在这里插入图片描述

2数据通道要求:

  1. 此通道用来接收上位机下发的图像数据和接收到一帧图像数据后,fpga返回给上位机的ACK帧数据。

  2. 上位机发送图像数据时,每次发送一帧的图像数据,图像数据的长度就是图像DW的数量。(例如分辨率为:1920 x 1080的图像,一帧数据长度为:1920 x 1080DW)

  3. Frame_ack 要求在每接收完成一帧图像给上位机发送一次 frame_ack 帧数据,Frame_ack 帧数据是 8 个 DW 长度的 32’h55555555,用于通知上位机可以发送下一帧数据,保证有序的发送图像帧数据。

  4. 通道 2 接收的数据可以通过 DDR3 控制器写入到内存中,并通过读 DDR3 显示到显示器端。

2.1 ddr3+hdmi模块回顾:

在这里插入图片描述

由上面的DDR3+HDMI项目项目可以知道:
User_write_ctrl的位宽为128bit,且是64突发
而HDMI显示模块接收的像素数为16bit
而本次项目中,images_ctrl模块中FIFO读出的数据将直接与user_write_ctrl模块相连,因此需要满足两个条件:1pixel=16bit,1data=128bit

在这里插入图片描述

2.1 images_ctrl模块时序设计

在这里插入图片描述

2.2 ack_ctrl模块时序设计

在这里插入图片描述

2.3 捕获桌面并以 32bit FFBGR 格式发送给 FPGA 的 pcie 端程序

```cpp
```c
int Cpcie_api_exDlg::getAckFromPcie()
{
fpga_t * fpga;
int recv;
int id = 0;
int chnl = 1;
int ackok=0;
unsigned int recvBuffer[8];//recv ack
fpga = fpga_open(id);
if (fpga == NULL) {
MessageBox(TEXT("打开Riffa设备失败!"), TEXT("警告"), MB_YESNO);
}
while (ackok==0) {
recv = fpga_recv(fpga, chnl, recvBuffer, 8, 25000);
if (recv == 0x08 && recvBuffer[0]==0x55555555 && recvBuffer[7]==0x55555555) {
ackok = 1;
}
}
fpga_close(fpga);
return 0;
}

//捕获一帧数据发送给板卡用于测试
void Cpcie_api_exDlg::OnBnClickedBtncap1frame()
{
// TODO: 在此添加控件通知处理程序代码
getScreen2pcie();
getAckFromPcie();
}
void Cpcie_api_exDlg::getScreen2pcie()
{
CDC *pDC;//屏幕DC
HDC hdc = ::GetDC(NULL);
pDC = CDC::FromHandle(hdc);//获取当前整个屏幕DC
int BitPerPixel = pDC->GetDeviceCaps(BITSPIXEL);//获得颜色模式
int Width = pDC->GetDeviceCaps(HORZRES);
int Height = pDC->GetDeviceCaps(VERTRES);
CDC memDC;//内存DC
memDC.CreateCompatibleDC(pDC);
CBitmap memBitmap, *oldmemBitmap;//建立和屏幕兼容的bitmap
memBitmap.CreateCompatibleBitmap(pDC, Width, Height);
oldmemBitmap = memDC.SelectObject(&memBitmap);//将memBitmap选入内存DC
memDC.BitBlt(0, 0, Width, Height, pDC, 0, 0, SRCCOPY);//复制屏幕图像到内存DC

 //以下代码保存memDC中的位图到文件
BITMAP bmp;
memBitmap.GetBitmap(&bmp);//获得位图信息
BITMAPINFOHEADER bih = { 0 };//位图信息头
bih.biBitCount = bmp.bmBitsPixel;//每个像素字节大小
bih.biCompression = BI_RGB;
bih.biHeight = bmp.bmHeight;//高度
bih.biPlanes = 1;
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight;//图像数据大小
bih.biWidth = bmp.bmWidth;//宽度
BITMAPFILEHEADER bfh = { 0 };//位图文件头
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);//到位图数据的偏移量
bfh.bfSize = bfh.bfOffBits + bmp.bmWidthBytes * bmp.bmHeight;//文件总的大小
bfh.bfType = (WORD)0x4d42;
FILE *fp = fopen("images.bin", "w+b");
//fwrite(&bfh, 1, sizeof(BITMAPFILEHEADER), fp);//写入位图文件头
//fwrite(&bih, 1, sizeof(BITMAPINFOHEADER), fp);//写入位图信息头
byte * sendBuffer = new byte[bmp.bmWidthBytes * bmp.bmHeight];//申请内存保存位图数据
GetDIBits(memDC.m_hDC, (HBITMAP)memBitmap.m_hObject, 0, Height, sendBuffer,
(LPBITMAPINFO)&bih, DIB_RGB_COLORS);//获取位图数据
//fwrite(sendBuffer, 1, bmp.bmWidthBytes * bmp.bmHeight, fp);//写入位图数据
fpga_t * fpga;
int sent;
int id=0;
int chnl=1;
fpga = fpga_open(id);
if (fpga == NULL) {
MessageBox(TEXT("打开Riffa设备失败!"), TEXT("警告"), MB_YESNO);
}
//发送一整帧图像1920*1080*4byte //排列顺序是0xFFBBGGRR
sent = fpga_send(fpga, chnl, sendBuffer, bmp.bmWidthBytes * bmp.bmHeight/4, 0, 1, 25000);
fpga_close(fpga);
delete[] sendBuffer;
//fclose(fp);
memDC.SelectObject(oldmemBitmap);
}

3.模块连接示意图:

在这里插入图片描述

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值