您尚未登录。

楼主 # 2021-12-18 13:31:42

资本家大善人
会员
注册时间: 2021-03-26
已发帖子: 120
积分: 212.5

分享一个V3X镜像

自制的,有问题麻烦说一下



适用于 https://whycan.com/t_7522.html  中的mipi-v3x



链接:
https://pan.baidu.com/s/1GhGtAKwBWQI940ZrbjnovA
提取码:pjs3


注意:
镜像连不上wifi会一直卡在那里
建议烧录完镜像后,在虚拟机里改下wifi名称和密码,顺便扩容
或者把手机热点wifi的名称密码改成楼下图里的

最近编辑记录 资本家大善人 (2021-12-18 15:54:56)

离线

楼主 #1 2021-12-18 13:33:46

资本家大善人
会员
注册时间: 2021-03-26
已发帖子: 120
积分: 212.5

Re: 分享一个V3X镜像

账号密码都是root
修改wifi密码

vim /etc/wpa_supplicant.conf

wifi.jpg

离线

楼主 #2 2021-12-18 13:50:27

资本家大善人
会员
注册时间: 2021-03-26
已发帖子: 120
积分: 212.5

Re: 分享一个V3X镜像

时钟

./clock

clock.jpg

天气钟

./weather

tq.jpg

NES游戏 键盘可用 wasd jk

./InfoNes hdl.nes /dev/input/event1

nes.jpg

播放视频

mplayer badapple.mp4

bad.jpg

usb摄像头

 ./cam /dev/video0

cam.jpg

语音识别 usb麦克风 键盘A按下录音 A松下识别

./baiduSpeech

最近编辑记录 资本家大善人 (2021-12-18 14:13:43)

离线

楼主 #3 2021-12-18 14:02:12

资本家大善人
会员
注册时间: 2021-03-26
已发帖子: 120
积分: 212.5

Re: 分享一个V3X镜像

usb摄像头源码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <asm/types.h>
#include <linux/videodev2.h>
#include <linux/fb.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <poll.h>
#include <math.h>
#include <wchar.h>
#include <time.h>
#include <stdbool.h>

#define CAM_WIDTH 320
#define CAM_HEIGHT 240

static char *dev_video;
static char *dev_fb0;

static char *yuv_buffer;
static char *rgb_buffer;
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
#define YUVToRGB(Y)                                                            \
	((u16)((((u8)(Y) >> 3) << 11) | (((u8)(Y) >> 2) << 5) | ((u8)(Y) >> 3)))
struct v4l2_buffer video_buffer;
/*全局变量*/
int lcd_fd;
int video_fd;
unsigned char *lcd_mem_p = NULL; //保存LCD屏映射到进程空间的首地址
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;

char *video_buff_buff[4]; /*保存摄像头缓冲区的地址*/
int video_height = 0;
int video_width = 0;
unsigned char *lcd_display_buff; //LCD显存空间
unsigned char *lcd_display_buff2; //LCD显存空间
static void errno_exit(const char *s)
{
	fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno));
	exit(EXIT_FAILURE);
}

static int xioctl(int fh, int request, void *arg)
{
	int r;

	do {
		r = ioctl(fh, request, arg);
	} while (-1 == r && EINTR == errno);

	return r;
}

static int video_init(void)
{
	struct v4l2_capability cap;
	ioctl(video_fd, VIDIOC_QUERYCAP, &cap);

	struct v4l2_fmtdesc dis_fmtdesc;
	dis_fmtdesc.index = 0;
	dis_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	// printf("-----------------------支持格式---------------------\n");
	// while (ioctl(video_fd, VIDIOC_ENUM_FMT, &dis_fmtdesc) != -1) {
	// 	printf("\t%d.%s\n", dis_fmtdesc.index + 1,
	// 	       dis_fmtdesc.description);
	// 	dis_fmtdesc.index++;
	// }
	struct v4l2_format video_format;
	video_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	video_format.fmt.pix.width = CAM_WIDTH;
	video_format.fmt.pix.height = CAM_HEIGHT;
	video_format.fmt.pix.pixelformat =
		V4L2_PIX_FMT_YUYV; //使用JPEG格式帧,用于静态图像采集

	ioctl(video_fd, VIDIOC_S_FMT, &video_format);

	printf("当前摄像头支持的分辨率:%dx%d\n", video_format.fmt.pix.width,
	       video_format.fmt.pix.height);
	if (video_format.fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV) {
		printf("当前摄像头不支持YUYV格式输出.\n");
		video_height = video_format.fmt.pix.height;
		video_width = video_format.fmt.pix.width;
		//return -3;
	} else {
		video_height = video_format.fmt.pix.height;
		video_width = video_format.fmt.pix.width;
		printf("当前摄像头支持YUYV格式输出.width %d height %d\n",
		       video_height, video_height);
	}
	/*3. 申请缓冲区*/
	struct v4l2_requestbuffers video_requestbuffers;
	memset(&video_requestbuffers, 0, sizeof(struct v4l2_requestbuffers));
	video_requestbuffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	video_requestbuffers.count = 4;
	video_requestbuffers.memory = V4L2_MEMORY_MMAP;
	if (ioctl(video_fd, VIDIOC_REQBUFS, &video_requestbuffers))
		return -4;
	printf("成功申请的缓冲区数量:%d\n", video_requestbuffers.count);
	/*4. 得到每个缓冲区的地址: 将申请的缓冲区映射到进程空间*/
	struct v4l2_buffer video_buffer;
	memset(&video_buffer, 0, sizeof(struct v4l2_buffer));
	int i;
	for (i = 0; i < video_requestbuffers.count; i++) {
		video_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		video_buffer.index = i;
		video_buffer.memory = V4L2_MEMORY_MMAP;
		if (ioctl(video_fd, VIDIOC_QUERYBUF, &video_buffer))
			return -5;
		/*映射缓冲区的地址到进程空间*/
		video_buff_buff[i] =
			mmap(NULL, video_buffer.length, PROT_READ | PROT_WRITE,
			     MAP_SHARED, video_fd, video_buffer.m.offset);
		printf("第%d个缓冲区地址:%#X\n", i, video_buff_buff[i]);
	}
	/*5. 将缓冲区放入到采集队列*/
	memset(&video_buffer, 0, sizeof(struct v4l2_buffer));
	for (i = 0; i < video_requestbuffers.count; i++) {
		video_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		video_buffer.index = i;
		video_buffer.memory = V4L2_MEMORY_MMAP;
		if (ioctl(video_fd, VIDIOC_QBUF, &video_buffer)) {
			printf("VIDIOC_QBUF error\n");
			return -6;
		}
	}
	printf("启动摄像头采集\n");
	/*6. 启动摄像头采集*/
	int opt_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	if (ioctl(video_fd, VIDIOC_STREAMON, &opt_type)) {
		printf("VIDIOC_STREAMON error\n");
		return -7;
	}

	return 0;
}
int lcd_init(void)
{
	/*2. 获取可变参数*/
	if (ioctl(lcd_fd, FBIOGET_VSCREENINFO, &vinfo))
		return -2;
	printf("屏幕X:%d   屏幕Y:%d  像素位数:%d\n", vinfo.xres, vinfo.yres,
	       vinfo.bits_per_pixel);
	//分配显存空间,完成图像显示
	lcd_display_buff =
		malloc(vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8);
	/*3. 获取固定参数*/
	if (ioctl(lcd_fd, FBIOGET_FSCREENINFO, &finfo))
		return -3;
	printf("smem_len=%d Byte,line_length=%d Byte\n", finfo.smem_len,
	       finfo.line_length);

	/*4. 映射LCD屏物理地址到进程空间*/
	lcd_mem_p = (unsigned char *)mmap(0, finfo.smem_len,
					  PROT_READ | PROT_WRITE, MAP_SHARED,
					  lcd_fd, 0); //从文件的那个地方开始映射
	memset(lcd_mem_p, 0xFFFFFFFF, finfo.smem_len);
	printf("映射LCD屏物理地址到进程空间\n");
	return 0;
}

static void close_device(void)
{
	if (-1 == close(video_fd))
		errno_exit("close");
	video_fd = -1;

	if (-1 == close(lcd_fd))
		errno_exit("close");
	lcd_fd = -1;
}

static void open_device(void)
{
	video_fd = open(dev_video, O_RDWR /* required */ | O_NONBLOCK, 0);
	if (-1 == video_fd) {
		fprintf(stderr, "Cannot open '%s': %d, %s\n", dev_video, errno,
			strerror(errno));
		exit(EXIT_FAILURE);
	}

	lcd_fd = open(dev_fb0, O_RDWR, 0);
	if (-1 == lcd_fd) {
		fprintf(stderr, "Cannot open '%s': %d, %s\n", dev_fb0, errno,
			strerror(errno));
		exit(EXIT_FAILURE);
	}
}
/*
将YUV格式数据转为RGB
*/
void yuv_to_rgb(unsigned char *yuv_buffer, unsigned char *rgb_buffer,
		int iWidth, int iHeight)
{
	int x;
	int z = 0;
	unsigned char *ptr = rgb_buffer;
	unsigned char *yuyv = yuv_buffer;
	for (x = 0; x < iWidth * iHeight; x++) {
		int r, g, b;
		int y, u, v;
		if (!z)
			y = yuyv[0] << 8;
		else
			y = yuyv[2] << 8;
		u = yuyv[1] - 128;
		v = yuyv[3] - 128;
		r = (y + (359 * v)) >> 8;
		g = (y - (88 * u) - (183 * v)) >> 8;
		b = (y + (454 * u)) >> 8;
		*(ptr++) = (b > 255) ? 255 : ((b < 0) ? 0 : b);
		*(ptr++) = (g > 255) ? 255 : ((g < 0) ? 0 : g);
		*(ptr++) = (r > 255) ? 255 : ((r < 0) ? 0 : r);
		if (z++) {
			z = 0;
			yuyv += 4;
		}
	}
}

void rgb24_to_rgb565(char *rgb24, char *rgb16)
{
	int i = 0, j = 0;
	for (i = 0; i < 320 * 240 * 3; i += 3) {
		rgb16[j] = rgb24[i] >> 3; // B
		rgb16[j] |= ((rgb24[i + 1] & 0x1C) << 3); // G
		rgb16[j + 1] = rgb24[i + 2] & 0xF8; // R
		rgb16[j + 1] |= (rgb24[i + 1] >> 5); // G

		j += 2;
	}
}
int main(int argc, char **argv)
{
	dev_video = argv[1];
	dev_fb0 = "/dev/fb0";
	open_device();
	video_init();
	lcd_init();
	/*3. 读取摄像头的数据*/
	struct pollfd video_fds;
	video_fds.events = POLLIN;
	video_fds.fd = video_fd;

	memset(&video_buffer, 0, sizeof(struct v4l2_buffer));
	rgb_buffer = malloc(CAM_WIDTH * CAM_HEIGHT * 3);
	yuv_buffer = malloc(CAM_WIDTH * CAM_HEIGHT * 3);
	unsigned char *rgb_p;
	int w, h, i, j;
	unsigned char r, g, b;
	unsigned int c;
	while (1) {
		/*等待摄像头采集数据*/
		poll(&video_fds, 1, -1);
		/*得到缓冲区的编号*/
		video_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		video_buffer.memory = V4L2_MEMORY_MMAP;
		ioctl(video_fd, VIDIOC_DQBUF, &video_buffer);
		//printf("当前采集OK的缓冲区编号:%d,地址:%#X num:%d\n",
		//       video_buffer.index, video_buff_buff[video_buffer.index],
		 //      strlen(video_buff_buff[video_buffer.index]));
		/*对缓冲区数据进行处理*/
		yuv_to_rgb(video_buff_buff[video_buffer.index], yuv_buffer,
		video_height, video_width);
		rgb24_to_rgb565(yuv_buffer, rgb_buffer);
		//printf("显示屏进行显示\n");
		//显示屏进行显示: 将显存空间的数据拷贝到LCD屏进行显示
		memcpy(lcd_mem_p, rgb_buffer,
		       vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8);
		/*将缓冲区放入采集队列*/
		ioctl(video_fd, VIDIOC_QBUF, &video_buffer);
		//printf("将缓冲区放入采集队列\n");
	}
	/*4. 关闭视频设备*/
	close(video_fd);

	return 0;
}

离线

楼主 #4 2021-12-18 14:12:35

资本家大善人
会员
注册时间: 2021-03-26
已发帖子: 120
积分: 212.5

Re: 分享一个V3X镜像

百度语音识别Qt源码
baiduSpeech.zip

离线

楼主 #5 2021-12-18 14:18:39

资本家大善人
会员
注册时间: 2021-03-26
已发帖子: 120
积分: 212.5

Re: 分享一个V3X镜像

时钟源码
clock.zip

#ifndef WIDGET_H
#define WIDGET_H
#include <QMainWindow>
#include<QPainter>
#include <QTimer>
#include <QTime>
#include <QWidget>
#include <QtMath>
namespace Ui {
class Widget;
}

class Widget : public QMainWindow
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();
    void paintEvent(QPaintEvent *);
    //定义文本区域
    QRectF textRectF(double r,int pointSize,double angle);
private slots:


private:
    Ui::Widget *ui;
};

#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(update()));//更新界面
    timer->start(1000);//每秒更新一次界面
}

Widget::~Widget()
{
    delete ui;
}

void Widget::paintEvent(QPaintEvent *event)
{

    Q_UNUSED(event);
    //获取系统时间
    QTime time = QTime::currentTime();
    // 时针、分针、秒针位置 - 多边形
    static const QPoint hourHand[3] = {
        QPoint(7, 8),
        QPoint(-7, 8),
        QPoint(0, -30)
    };
    static const QPoint minuteHand[3] = {
        QPoint(7, 8),
        QPoint(-7, 8),
        QPoint(0, -65)
    };
    static const QPoint secondHand[3] = {
        QPoint(7, 8),
        QPoint(-7, 8),
        QPoint(0, -80)
    };
    // 时针、分针、秒针颜色
    QColor hourColor(200, 100, 0, 200);
    QColor minuteColor(0, 127, 127, 150);
    QColor secondColor(0, 160, 230, 150);

    int side = qMin(width(), height());
    //获取窗口信息
    QPainter painter(this);
    //设置抗锯齿,精度越高,效率越低
    painter.setRenderHint(QPainter::Antialiasing);
    // 平移坐标系原点至中心点
    painter.translate(width() / 2, height() / 2);
    // 缩放
    painter.scale(side / 200.0, side / 200.0);

    // 绘制时针
    painter.setPen(Qt::NoPen);
    painter.setBrush(hourColor);
    painter.save();
    // 每圈360° = 12h 即:旋转角度 = 小时数 * 30°
    painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0)));
    painter.drawConvexPolygon(hourHand, 3);
    painter.restore();
    // 绘制小时线 (360度 / 12 = 30度)
    painter.setPen(hourColor);
    for (int i = 0; i < 12; ++i) {
        painter.drawLine(88, 0, 96, 0);
        painter.rotate(30.0);
    }

    int radius = 100;
    QFont font = painter.font();
    font.setBold(true);//字体加粗
    painter.setFont(font);
    int pointSize = font.pointSize();

    // 绘制小时文本
    int nHour = 0;
    for (int i = 0; i < 12; ++i) {
        nHour = i + 3;//原点变了,从3绘制(旋转0°)
        if (nHour > 12) nHour -= 12;//13 14 -> 1 2
        //在中心绘制
        painter.drawText(textRectF(radius*0.8, pointSize, i * 30), Qt::AlignCenter, QString::number(nHour));
    }

    painter.setPen(Qt::NoPen);
    // 绘制分针
    painter.setBrush(minuteColor);
        painter.save();
    // 每圈360° = 60m 即:旋转角度 = 分钟数 * 6°
    painter.rotate(6.0 * (time.minute() + time.second() / 60.0));
    painter.drawConvexPolygon(minuteHand, 3);
        painter.restore();
    // 绘制分钟线 (360度 / 60 = 6度)
    painter.setPen(minuteColor);
    for (int j = 0; j < 60; ++j) {
        if ((j % 5) != 0)
            painter.drawLine(92, 0, 96, 0);
        painter.rotate(6.0);
    }
    // 绘制秒针
    painter.setPen(Qt::NoPen);
    painter.setBrush(secondColor);
    painter.save();
    // 每圈360° = 60s 即:旋转角度 = 秒数 * 6°
    painter.rotate(6.0 * time.second());//旋转图像
    painter.drawConvexPolygon(secondHand, 3);
    painter.restore();

}

//绘制文本区域
//输入半径,区域大小,角度
QRectF Widget::textRectF(double r, int pointSize, double angle)
{
    QRectF rectF;
    rectF.setX(r*qCos(angle*M_PI/180.0) - pointSize*2);
    rectF.setY(r*qSin(angle*M_PI/180.0) - pointSize/2.0);
    rectF.setWidth(pointSize*4);
    rectF.setHeight(pointSize);
    return rectF;

}

离线

#6 2021-12-18 14:59:37

twzy
会员
注册时间: 2021-04-16
已发帖子: 162
积分: 318.5
个人网站

Re: 分享一个V3X镜像

请问这个nes有声音延时的问题吗?

离线

楼主 #7 2021-12-18 15:06:14

资本家大善人
会员
注册时间: 2021-03-26
已发帖子: 120
积分: 212.5

Re: 分享一个V3X镜像

twzy 说:

请问这个nes有声音延时的问题吗?

有延时(T_T)

离线

楼主 #9 2021-12-18 15:32:06

资本家大善人
会员
注册时间: 2021-03-26
已发帖子: 120
积分: 212.5

Re: 分享一个V3X镜像

uboot
https://gitee.com/byleefei/uboot-2021.07-v3x

make ARCH=arm  mipi-v3x_defconfig
make ARCH=arm menuconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j12

内核 跟v3s通用
https://gitee.com/byleefei/linux-5.10-v3x

最近编辑记录 资本家大善人 (2021-12-18 15:36:34)

离线

楼主 #10 2021-12-18 16:18:53

资本家大善人
会员
注册时间: 2021-03-26
已发帖子: 120
积分: 212.5

Re: 分享一个V3X镜像

扩容问题
软件GParted (apt-get 安装)
k1.jpg
k2.jpg
扩容,建立swap分区
k3.gif

离线

楼主 #11 2021-12-18 16:23:59

资本家大善人
会员
注册时间: 2021-03-26
已发帖子: 120
积分: 212.5

Re: 分享一个V3X镜像

更新软件包

apt-get update

k4.gif
安装需要的工具
k5.jpg

离线

楼主 #12 2021-12-18 16:29:34

资本家大善人
会员
注册时间: 2021-03-26
已发帖子: 120
积分: 212.5

Re: 分享一个V3X镜像

编译usb摄像头代码并运行
k6.jpg
k7.jpg

最近编辑记录 资本家大善人 (2021-12-18 16:30:00)

离线

楼主 #13 2021-12-20 00:55:42

资本家大善人
会员
注册时间: 2021-03-26
已发帖子: 120
积分: 212.5

Re: 分享一个V3X镜像

弄了桌面系统
浏览器访问坑网,加载只要几秒
50-75%CPU
65% 内存
v3s上直接爆内存怪不得打不开
78b4eb05451268af.jpg
远程桌面,还没弄好-7325f7e9167bae9b.png

离线

#14 2021-12-20 09:01:31

twzy
会员
注册时间: 2021-04-16
已发帖子: 162
积分: 318.5
个人网站

Re: 分享一个V3X镜像

资本家大善人 说:

弄了桌面系统
浏览器访问坑网,加载只要几秒
50-75%CPU
65% 内存
v3s上直接爆内存怪不得打不开
https://whycan.com/files/members/6250/78b4eb05451268af.jpg
远程桌面,还没弄好https://whycan.com/files/members/6250/-7325f7e9167bae9b.png

求方法,我自己安装的Ledx,感觉一直在重启

最近编辑记录 twzy (2021-12-20 09:23:47)

离线

楼主 #15 2021-12-20 11:37:07

资本家大善人
会员
注册时间: 2021-03-26
已发帖子: 120
积分: 212.5

Re: 分享一个V3X镜像

@twzy
https://releases.linaro.org/debian/images/alip-armhf/

这里是带桌面的文件系统,换掉原来的文件系统就行

记得启动交换分区,不然很卡

V3X和V3S就uboot有点差异,内核文件系统通用

最近编辑记录 资本家大善人 (2021-12-20 11:39:04)

离线

#16 2021-12-20 19:22:58

twzy
会员
注册时间: 2021-04-16
已发帖子: 162
积分: 318.5
个人网站

Re: 分享一个V3X镜像

资本家大善人 说:

@twzy
https://releases.linaro.org/debian/images/alip-armhf/

这里是带桌面的文件系统,换掉原来的文件系统就行

记得启动交换分区,不然很卡

V3X和V3S就uboot有点差异,内核文件系统通用

其他的已经跑起来了,今天画了个基于v3x的小电脑,已经打样了

另外v3x操作pc4~pc10引脚会报错,估计是使用v3s配置的原因,后续看看怎么修改吧

离线

#17 2021-12-27 15:03:26

树莓学LINUX
会员
注册时间: 2021-10-28
已发帖子: 74
积分: 54

Re: 分享一个V3X镜像

老哥成品出售吗,多少米

离线

#18 2021-12-28 12:26:51

jordonwu
会员
注册时间: 2021-07-05
已发帖子: 32
积分: 23

Re: 分享一个V3X镜像

该评论内容与本帖子无关,鼓励各位坑友积极发言讨论与帖子有关的内容!

离线

  • 不通过:其他

#19 2021-12-28 13:27:54

luciferseva
会员
注册时间: 2020-05-20
已发帖子: 43
积分: 11.5

Re: 分享一个V3X镜像

该评论内容与本帖子无关,鼓励各位坑友积极发言讨论与帖子有关的内容!

离线

  • 不通过:其他

楼主 #20 2022-01-02 00:45:41

资本家大善人
会员
注册时间: 2021-03-26
已发帖子: 120
积分: 212.5

Re: 分享一个V3X镜像

桌面镜像已上传,链接跟一楼一样,记得建立swap分区
链接:
https://pan.baidu.com/s/1GhGtAKwBWQI940ZrbjnovA
提取码:pjs3

最近编辑记录 资本家大善人 (2022-01-02 00:46:33)

离线

#21 2022-01-02 20:33:34

lsmcld
会员
所在地: 成都
注册时间: 2021-12-19
已发帖子: 21
积分: 16
个人网站

Re: 分享一个V3X镜像

该评论内容与本帖子无关,鼓励各位坑友积极发言讨论与帖子有关的内容!

离线

  • 不通过:其他

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn