自制的,有问题麻烦说一下
适用于 https://whycan.com/t_7522.html 中的mipi-v3x
链接:
https://pan.baidu.com/s/1GhGtAKwBWQI940ZrbjnovA
提取码:pjs3
注意:
镜像连不上wifi会一直卡在那里
建议烧录完镜像后,在虚拟机里改下wifi名称和密码,顺便扩容
或者把手机热点wifi的名称密码改成楼下图里的
最近编辑记录 资本家大善人 (2021-12-18 15:54:56)
离线
账号密码都是root
修改wifi密码
vim /etc/wpa_supplicant.conf
离线
时钟
./clock
天气钟
./weather
NES游戏 键盘可用 wasd jk
./InfoNes hdl.nes /dev/input/event1
播放视频
mplayer badapple.mp4
usb摄像头
./cam /dev/video0
语音识别 usb麦克风 键盘A按下录音 A松下识别
./baiduSpeech
最近编辑记录 资本家大善人 (2021-12-18 14:13:43)
离线
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;
}
离线
百度语音识别Qt源码
baiduSpeech.zip
离线
时钟源码
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;
}
离线
请问这个nes有声音延时的问题吗?
有延时(T_T)
离线
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)
离线
扩容问题
软件GParted (apt-get 安装)
扩容,建立swap分区
离线
更新软件包
apt-get update
安装需要的工具
离线
编译usb摄像头代码并运行
最近编辑记录 资本家大善人 (2021-12-18 16:30:00)
离线
弄了桌面系统
浏览器访问坑网,加载只要几秒
50-75%CPU
65% 内存
v3s上直接爆内存怪不得打不开
远程桌面,还没弄好
离线
弄了桌面系统
浏览器访问坑网,加载只要几秒
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)
离线
@twzy
https://releases.linaro.org/debian/images/alip-armhf/
这里是带桌面的文件系统,换掉原来的文件系统就行
记得启动交换分区,不然很卡
V3X和V3S就uboot有点差异,内核文件系统通用
最近编辑记录 资本家大善人 (2021-12-20 11:39:04)
离线
@twzy
https://releases.linaro.org/debian/images/alip-armhf/这里是带桌面的文件系统,换掉原来的文件系统就行
记得启动交换分区,不然很卡
V3X和V3S就uboot有点差异,内核文件系统通用
其他的已经跑起来了,今天画了个基于v3x的小电脑,已经打样了
另外v3x操作pc4~pc10引脚会报错,估计是使用v3s配置的原因,后续看看怎么修改吧
离线
离线
离线
桌面镜像已上传,链接跟一楼一样,记得建立swap分区
链接:
https://pan.baidu.com/s/1GhGtAKwBWQI940ZrbjnovA
提取码:pjs3
最近编辑记录 资本家大善人 (2022-01-02 00:46:33)
离线
GBA游戏模拟器
apt-get install visualboy*
离线
@资本家大善人
收藏一下 谢谢!!!!
离线
你这个是支持FLASH启动的吗
离线