添加硬件(镜头和电机部分)
This commit is contained in:
parent
7c7e271a6c
commit
bb3ef5fc9a
|
@ -6,6 +6,8 @@
|
|||
#include <thread>
|
||||
#include "../uart/uartregsaccess.h"
|
||||
#include <iostream>
|
||||
#include "../uart/Gpio.h"
|
||||
#include <base/utils.h>
|
||||
|
||||
#define Reg(x) (fpgaParams.x)
|
||||
#define RegIndex(x) (std::distance((unsigned int*)&fpgaParams, (unsigned int*)&fpgaParams.x))
|
||||
|
@ -15,13 +17,55 @@
|
|||
|
||||
#define CO(x) std::cout << #x << " : "<< RegIndex(x) << std::endl
|
||||
|
||||
FpgaComm::controller::controller()
|
||||
{
|
||||
status_.reset(new Gpio(PORT_STATUS));
|
||||
reload_.reset(new GpioOut(PORT_RELOAD));
|
||||
cfg_.reset(new Gpio(PORT_CONFIG));
|
||||
reset_.reset(new GpioOut(PORT_RESET));
|
||||
}
|
||||
FpgaComm::controller::~controller()
|
||||
{}
|
||||
|
||||
void FpgaComm::controller::reset(void)
|
||||
{
|
||||
reset_->setValue(Gpio::Low);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
utils::to_log(LOG_LEVEL_DEBUG, "FPGA-reset set Low: %d\n", status_->getValue());
|
||||
|
||||
reset_->setValue(Gpio::High);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
utils::to_log(LOG_LEVEL_DEBUG, "FPGA-reset set High: %d\n", status_->getValue());
|
||||
}
|
||||
void FpgaComm::controller::reload(void)
|
||||
{
|
||||
// fpga 代码重载
|
||||
reload_->setValue(Gpio::Low);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(15));
|
||||
|
||||
cfg_->setValue(Gpio::Low);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(15));
|
||||
utils::to_log(LOG_LEVEL_DEBUG, "FPGA-reload set Low: %d\n", status_->getValue());
|
||||
|
||||
reload_->setValue(Gpio::High);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(15));
|
||||
cfg_->setValue(Gpio::High);
|
||||
utils::to_log(LOG_LEVEL_DEBUG, "FPGA-reload set High: %d\n", status_->getValue());
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::seconds(3));
|
||||
utils::to_log(LOG_LEVEL_DEBUG, "FPGA-reload set High after 3 seconds: %d\n", status_->getValue());
|
||||
}
|
||||
|
||||
FpgaComm::FpgaComm(int bauds) : bauds_(bauds)
|
||||
{
|
||||
controller_.reset(new controller());
|
||||
m_regsAccess.reset(new UartRegsAccess(FPGA_UART, bauds_, 0x03, 0x83));
|
||||
update();
|
||||
|
||||
Reg(AledR).sample = 256;
|
||||
WR_Reg(AledR);
|
||||
|
||||
controller_->reset();
|
||||
}
|
||||
|
||||
bool FpgaComm::read(unsigned int addr, unsigned int& val) {
|
||||
|
|
|
@ -130,19 +130,44 @@ enum
|
|||
DPI_300 = 0,
|
||||
DPI_200,
|
||||
};
|
||||
enum
|
||||
{
|
||||
CIS_SECTOR_COUNT = 6, // how many sectors of ONE CIS
|
||||
};
|
||||
|
||||
class GpioOut;
|
||||
class Gpio;
|
||||
|
||||
class FpgaComm : public IRegsAccess
|
||||
{
|
||||
int bauds_ = 921600;
|
||||
|
||||
class controller
|
||||
{
|
||||
enum ports
|
||||
{
|
||||
PORT_STATUS = 69,
|
||||
PORT_RELOAD = 70,
|
||||
PORT_CONFIG = 71,
|
||||
PORT_RESET = 232,
|
||||
};
|
||||
std::unique_ptr<Gpio> status_; // status reader - port 69
|
||||
std::unique_ptr<GpioOut> reload_; // codes reload - port 70
|
||||
std::unique_ptr<Gpio> cfg_; // configuration reload - port 71
|
||||
std::unique_ptr<GpioOut> reset_; // circuit reset - port Fpga_Reset
|
||||
|
||||
public:
|
||||
controller();
|
||||
~controller();
|
||||
|
||||
public:
|
||||
void reset(void);
|
||||
void reload(void);
|
||||
};
|
||||
std::unique_ptr<controller> controller_;
|
||||
|
||||
public:
|
||||
FpgaComm(int bauds = 921600);
|
||||
virtual ~FpgaComm(){}
|
||||
|
||||
enum { CIS_SECTOR_COUNT = 6 }; // how many sectors of ONE CIS
|
||||
|
||||
void reset();
|
||||
void regsAccess_reset(bool enable);
|
||||
void setRegs(int addr, int value);
|
||||
|
|
|
@ -0,0 +1,451 @@
|
|||
#include "gvideo.h"
|
||||
#include <iostream>
|
||||
#include <fcntl.h> /* low-level i/o */
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <dlfcn.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include "linux/v4l2-subdev.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <poll.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include <base/utils.h>
|
||||
|
||||
static const std::string loggername = "gVideo";
|
||||
|
||||
using namespace std;
|
||||
#define CLEAR(x) memset(&(x), 0, sizeof(x))
|
||||
#define LOG printf
|
||||
|
||||
int file_size(const char* filename)
|
||||
{
|
||||
struct stat statbuf;
|
||||
int ret = stat(filename, &statbuf);
|
||||
int size = -1;
|
||||
if (ret == 0)
|
||||
size = statbuf.st_size;
|
||||
return size;
|
||||
}
|
||||
|
||||
gVideo::gVideo()
|
||||
: fd(-1),
|
||||
buffers(0),
|
||||
bStart(false) ,
|
||||
dev_name("/dev/video3")
|
||||
{
|
||||
}
|
||||
|
||||
gVideo::~gVideo()
|
||||
{
|
||||
stop();
|
||||
close();
|
||||
}
|
||||
|
||||
bool gVideo::is_open()
|
||||
{
|
||||
return fd >= 0;
|
||||
}
|
||||
|
||||
void gVideo::close()
|
||||
{
|
||||
if (is_open()) {
|
||||
stop();
|
||||
uninit_device();
|
||||
close_device();
|
||||
}
|
||||
}
|
||||
|
||||
void gVideo::open(int width,int height) {
|
||||
if (is_open())
|
||||
return;
|
||||
|
||||
open_device();
|
||||
if (is_open()) {
|
||||
//init_device();
|
||||
set_size(width, height);
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
void gVideo::start()
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(m_lock);
|
||||
if (bStart)
|
||||
return;
|
||||
|
||||
start_capturing();
|
||||
bStart = true;
|
||||
}
|
||||
|
||||
void gVideo::stop() {
|
||||
std::lock_guard<std::mutex> lck(m_lock);
|
||||
if (bStart) {
|
||||
stop_capturing();
|
||||
bStart = false;
|
||||
}
|
||||
}
|
||||
|
||||
void gVideo::grab(int color, bool bcrrect, int timeout, int flatpara)
|
||||
{
|
||||
}
|
||||
|
||||
bool gVideo::hasframe() {
|
||||
return wait(0);
|
||||
}
|
||||
|
||||
bool gVideo::wait(int msTimeout) {
|
||||
pollfd pfd;
|
||||
pfd.fd = this->fd;
|
||||
pfd.events = POLLIN | POLLRDNORM;
|
||||
|
||||
if (poll(&pfd, 1, msTimeout) > 0) {
|
||||
return pfd.revents;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void* gVideo::read_frame(int timeout) {
|
||||
if (!wait(timeout)){
|
||||
utils::to_log(LOG_LEVEL_FATAL, "read frame time out");
|
||||
return 0;
|
||||
}
|
||||
v4l2_buffer buf;
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buf.memory = V4L2_MEMORY_USERPTR;
|
||||
if (-1 == ioctl(fd, VIDIOC_DQBUF, &buf)) {
|
||||
LOG_ERROR(utils::format_string("VIDIOC_DQBUF error!!! index :%d\n", buf.index));
|
||||
return 0;
|
||||
}
|
||||
if (-1 == ioctl(fd, VIDIOC_QBUF, &buf)) {
|
||||
LOG_ERROR(utils::format_string("VIDIOC_QBUF error!!! index :%d\n", buf.index));
|
||||
return 0;
|
||||
}
|
||||
return buffers[buf.index].start;
|
||||
}
|
||||
|
||||
void gVideo::set_size(int width,int height){
|
||||
if(!buffers.empty())
|
||||
uninit_device();
|
||||
|
||||
v4l_width=width;
|
||||
v4l_height=height;
|
||||
init_device();
|
||||
}
|
||||
|
||||
void gVideo::stop_capturing(void) {
|
||||
enum v4l2_buf_type type;
|
||||
|
||||
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
if (-1 == ioctl(fd, VIDIOC_STREAMOFF, &type))
|
||||
utils::to_log(LOG_LEVEL_FATAL, "streamo off");
|
||||
}
|
||||
|
||||
unsigned int querybuf_length;
|
||||
void gVideo::start_capturing(void)
|
||||
{
|
||||
enum v4l2_buf_type type;
|
||||
printf("start_capturing::querybuf_length = %d.\n",querybuf_length);
|
||||
for (int i = 0; i < n_buffers; ++i)
|
||||
{
|
||||
struct v4l2_buffer buf;
|
||||
struct v4l2_plane planes[VIDEO_MAX_PLANES];
|
||||
CLEAR(buf);
|
||||
CLEAR(planes);
|
||||
for(int j = 0; j < VIDEO_MAX_PLANES; j++)
|
||||
{
|
||||
//planes[j].length = buffers[i].length;
|
||||
planes[j].length = querybuf_length;
|
||||
planes[j].m.userptr =(unsigned long)buffers[i].start;
|
||||
}
|
||||
buf.index = i;
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
||||
buf.memory = V4L2_MEMORY_USERPTR;//V4L2_MEMORY_MMAP;
|
||||
buf.m.planes = planes;
|
||||
buf.length = 1;
|
||||
|
||||
if (-1 == ioctl(fd, VIDIOC_QBUF, &buf))
|
||||
LOG_ERROR(utils::format_string("VIDIOC_QBUF Error %d", i));
|
||||
else
|
||||
LOG_ERROR(utils::format_string("VIDIOC_QBUF %d\n", i));
|
||||
}
|
||||
|
||||
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
if (-1 == ioctl(fd, VIDIOC_STREAMON, &type))
|
||||
utils::to_log(LOG_LEVEL_FATAL, "VIDIOC_STREAMON");
|
||||
}
|
||||
|
||||
void gVideo::uninit_device(void)
|
||||
{
|
||||
if (!buffers.empty())
|
||||
{
|
||||
struct v4l2_requestbuffers req;
|
||||
CLEAR(req);
|
||||
req.count = 0;
|
||||
LOG_TRACE(utils::format_string("frame count: %d", req.count));
|
||||
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
req.memory = V4L2_MEMORY_USERPTR;
|
||||
|
||||
if (-1 == ioctl(fd, VIDIOC_REQBUFS, &req))
|
||||
{
|
||||
if (EINVAL == errno)
|
||||
utils::to_log(LOG_LEVEL_FATAL, "does not support user pointer i/o");
|
||||
else
|
||||
utils::to_log(LOG_LEVEL_FATAL, "VIDIOC_REQBUFS");
|
||||
}
|
||||
|
||||
for (int i = 0; i < n_buffers; ++i)
|
||||
free(buffers[i].start);
|
||||
|
||||
buffers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void gVideo::init_mmap(void)
|
||||
{
|
||||
|
||||
struct v4l2_requestbuffers req;
|
||||
int ret;
|
||||
unsigned int length;
|
||||
unsigned int offset;
|
||||
unsigned int page_size;
|
||||
int buffer_size = v4l_width * v4l_height * 3;
|
||||
printf("init_mmap::buduiqi:changdu: buffer_size= %d\n", buffer_size);
|
||||
page_size = getpagesize();
|
||||
buffer_size = (buffer_size + page_size - 1) & ~(page_size - 1);
|
||||
printf("init_mmap::shijichangdu:v4l_width = %d,v4l_height = %d\n", v4l_width,v4l_height);
|
||||
printf("init_mmap::duiqi:page_size = %d,buffer_size = %d\n", page_size,buffer_size);
|
||||
|
||||
CLEAR(req);
|
||||
|
||||
//6.VIDIOC_REQBUFS
|
||||
req.count = v4l_buffer_count;
|
||||
//req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
||||
//req.memory = V4L2_MEMORY_MMAP;
|
||||
req.memory = V4L2_MEMORY_USERPTR;
|
||||
printf("set v4l_buffer_count = %d\n", req.count);
|
||||
printf("set v4l_buffer_type = %d\n", req.type);
|
||||
printf("set v4l_buffer_memory = %d\n", req.memory);
|
||||
|
||||
ret = ioctl(fd, VIDIOC_REQBUFS, &req);
|
||||
if (ret < 0) {
|
||||
printf("Unable to request buffers: %s (%d).\n", strerror(errno),errno);
|
||||
}
|
||||
else {
|
||||
printf("%s VIDIOC_REQBUFS sucess\n",dev_name.c_str());
|
||||
}
|
||||
printf("%u buffers requested.\n", req.count);
|
||||
|
||||
buffers.resize(req.count);
|
||||
if (buffers.empty()) {
|
||||
printf("Out of memory\n");
|
||||
}
|
||||
|
||||
//7.VIDIOC_QUERYBUF
|
||||
for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
|
||||
const char *ts_type, *ts_source;
|
||||
struct v4l2_buffer buf;
|
||||
struct v4l2_plane planes[VIDEO_MAX_PLANES];
|
||||
CLEAR(buf);
|
||||
CLEAR(planes);
|
||||
buf.index = n_buffers;
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
||||
//buf.memory = V4L2_MEMORY_MMAP;
|
||||
buf.memory = V4L2_MEMORY_USERPTR;
|
||||
buf.length = VIDEO_MAX_PLANES;
|
||||
buf.m.planes = planes;
|
||||
|
||||
ret = ioctl(fd, VIDIOC_QUERYBUF, &buf);
|
||||
if (ret < 0) {
|
||||
printf("Unable to query buffer %u: %s (%d).\n", n_buffers,strerror(errno), errno);
|
||||
|
||||
}
|
||||
else {
|
||||
printf("index %d VIDIOC_QUERYBUF sucess.\n",n_buffers);
|
||||
|
||||
}
|
||||
//get_ts_flags(buf.flags, &ts_type, &ts_source);
|
||||
//printf("length: %u offset: %u timestamp type/source: %s/%s\n",
|
||||
// buf.length, buf.m.offset, ts_type, ts_source);
|
||||
|
||||
//mmap
|
||||
unsigned int length;
|
||||
unsigned int offset;
|
||||
length = buf.m.planes[0].length;
|
||||
offset = buf.m.planes[0].m.mem_offset;
|
||||
querybuf_length = buf.m.planes[0].length;
|
||||
printf("VIDIOC_QUERYBUF:Buffer %u length = %d.\n",n_buffers,length);
|
||||
printf("VIDIOC_QUERYBUF:Buffer %u offset = %d.\n",n_buffers,offset);
|
||||
printf("VIDIOC_QUERYBUF:Buffer %u querybuf_length = %d.\n",n_buffers,querybuf_length);
|
||||
}
|
||||
|
||||
for (n_buffers = 0; n_buffers < buffers.size(); ++n_buffers)
|
||||
{
|
||||
buffers[n_buffers].length = querybuf_length;
|
||||
buffers[n_buffers].start = memalign(/* boundary */ 1024, querybuf_length);
|
||||
printf("memalign:buffers[%d].length = %d\n", n_buffers,buffers[n_buffers].length);
|
||||
printf("memalign:buffers[%d].start = %p\n", n_buffers,buffers[n_buffers].start);
|
||||
|
||||
if (!buffers[n_buffers].start)
|
||||
{
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
// unsigned int page_size;
|
||||
// int buffer_size = v4l_width * v4l_height * 3;
|
||||
|
||||
// page_size = getpagesize();
|
||||
// buffer_size = (buffer_size + page_size - 1) & ~(page_size - 1);
|
||||
|
||||
// struct v4l2_requestbuffers req;
|
||||
// CLEAR(req);
|
||||
// req.count = v4l_buffer_count;
|
||||
// LOG_TRACE(utils::format_string("frame count: %d", req.count));
|
||||
// req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
// req.memory = V4L2_MEMORY_USERPTR;
|
||||
|
||||
// if (-1 == ioctl(fd, VIDIOC_REQBUFS, &req))
|
||||
// {
|
||||
// if (EINVAL == errno)
|
||||
// LOG_ERROR("%s does not support user pointer i/o");
|
||||
// else
|
||||
// LOG_ERROR("VIDIOC_REQBUFS");
|
||||
// }
|
||||
|
||||
// buffers.resize(req.count);
|
||||
|
||||
// for (n_buffers = 0; n_buffers < buffers.size(); ++n_buffers)
|
||||
// {
|
||||
// buffers[n_buffers].length = buffer_size;
|
||||
// buffers[n_buffers].start = memalign(/* boundary */ page_size, buffer_size);
|
||||
|
||||
// if (!buffers[n_buffers].start)
|
||||
// LOG_ERROR("Out of memory");
|
||||
// }
|
||||
|
||||
// struct v4l2_requestbuffers req;
|
||||
// CLEAR(req);
|
||||
|
||||
// req.count = v4l_buffer_count;
|
||||
|
||||
// LOG("frame count: %d \n",req.count);
|
||||
// req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
// req.memory = V4L2_MEMORY_MMAP;
|
||||
|
||||
// if (-1 == ioctl(fd, VIDIOC_REQBUFS, &req)) {
|
||||
// if (EINVAL == errno) {
|
||||
// LOG("%s does not support " "memory mapping\n", dev_name.c_str());
|
||||
// }
|
||||
// else {
|
||||
// LOG("VIDIOC_REQBUFS \n");
|
||||
// }
|
||||
// }
|
||||
|
||||
// LOG("frame count:%d \n" ,req.count);
|
||||
|
||||
// if (req.count < 2) {
|
||||
// LOG("Insufficient buffer memory on %s\n", dev_name.c_str());
|
||||
// }
|
||||
|
||||
// buffers.resize(req.count);
|
||||
// LOG("frame count: %d \n", req.count);
|
||||
|
||||
// if (buffers.empty()) {
|
||||
// LOG("Out of memory\n");
|
||||
// }
|
||||
|
||||
// for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
|
||||
// struct v4l2_buffer buf;
|
||||
// CLEAR(buf);
|
||||
// buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
// buf.memory = V4L2_MEMORY_MMAP;
|
||||
// buf.index = n_buffers;
|
||||
|
||||
// if (-1 == ioctl(fd, VIDIOC_QUERYBUF, &buf))
|
||||
// LOG("VIDIOC_QUERYBUF \n");
|
||||
// LOG("mmap buffer len:%d \n",buf.length);
|
||||
// buffers[n_buffers].length = buf.length;
|
||||
// buffers[n_buffers].start =
|
||||
// mmap(NULL /* start anywhere */,
|
||||
// buf.length,
|
||||
// PROT_READ | PROT_WRITE /* required */,
|
||||
// MAP_SHARED /* recommended */,
|
||||
// fd, buf.m.offset);
|
||||
|
||||
// if (MAP_FAILED == buffers[n_buffers].start){
|
||||
// LOG("MAP_FAILED!!! %d \n",buf.length);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
void printCamInfo(int fd)
|
||||
{ //获取摄像头所支持的分辨率
|
||||
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
struct v4l2_fmtdesc fmt_1;
|
||||
struct v4l2_frmsizeenum frmsize;
|
||||
struct v4l2_frmivalenum frmival;
|
||||
fmt_1.index = 0;
|
||||
fmt_1.type = type;
|
||||
while (ioctl(fd, VIDIOC_ENUM_FMT, &fmt_1) >= 0)
|
||||
{
|
||||
frmsize.pixel_format = fmt_1.pixelformat;
|
||||
frmsize.index = 0;
|
||||
while (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) >= 0)
|
||||
{
|
||||
if(frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE)
|
||||
LOG_TRACE(utils::format_string("line:%d %dx%d", __LINE__, frmsize.discrete.width, frmsize.discrete.height));
|
||||
else if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE)
|
||||
LOG_TRACE(utils::format_string("line:%d %dx%d", __LINE__, frmsize.discrete.width, frmsize.discrete.height));
|
||||
frmsize.index++;
|
||||
}
|
||||
fmt_1.index++;
|
||||
}
|
||||
}
|
||||
|
||||
void gVideo::init_device(void) {
|
||||
struct v4l2_capability cap;
|
||||
struct v4l2_format fmt;
|
||||
printCamInfo(fd);
|
||||
if (-1 == ioctl(fd, VIDIOC_QUERYCAP, &cap)) {
|
||||
if (EINVAL == errno)
|
||||
LOG_ERROR(utils::format_string("%s is no V4L2 device", dev_name.c_str()));
|
||||
else
|
||||
utils::to_log(LOG_LEVEL_DEBUG, "VIDIOC_QUERYCAP");
|
||||
}
|
||||
|
||||
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
|
||||
LOG_ERROR(utils::format_string("%s is no video capture device", dev_name.c_str()));
|
||||
|
||||
if (!(cap.capabilities & V4L2_CAP_STREAMING))
|
||||
LOG_ERROR(utils::format_string("%s does not support streaming i/o", dev_name.c_str()));
|
||||
|
||||
CLEAR(fmt);
|
||||
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
fmt.fmt.pix.width = v4l_width;
|
||||
fmt.fmt.pix.height = v4l_height;
|
||||
LOG_TRACE(utils::format_string("v4l2 init_device width:%d, height:%d\n", fmt.fmt.pix.width, fmt.fmt.pix.height));
|
||||
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
|
||||
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
|
||||
|
||||
if (-1 == ioctl(fd, VIDIOC_S_FMT, &fmt))
|
||||
utils::to_log(LOG_LEVEL_DEBUG, "VIDIOC_S_FMT error");
|
||||
init_mmap();
|
||||
}
|
||||
|
||||
void gVideo::close_device(void) {
|
||||
if (-1 == ::close(fd))
|
||||
utils::to_log(LOG_LEVEL_DEBUG, "close");
|
||||
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
void gVideo::open_device(void)
|
||||
{
|
||||
if((fd = ::open(dev_name.c_str(), O_RDWR /* required */ /*| O_NONBLOCK*/, 0)) == -1)
|
||||
LOG_ERROR(utils::format_string("Cannot open %s", dev_name.c_str()));
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
|
||||
#define LOG_TRACE(s) utils::to_log(LOG_LEVEL_DEBUG, s.c_str())
|
||||
#define LOG_ERROR LOG_TRACE
|
||||
|
||||
class gVideo
|
||||
{
|
||||
public:
|
||||
gVideo();
|
||||
virtual ~gVideo();
|
||||
|
||||
bool is_open();
|
||||
void close();
|
||||
void open(int width, int height);
|
||||
void start();
|
||||
void stop();
|
||||
void grab(int color, bool bcrrect = false, int timeout = 1000, int flatpara = 0);
|
||||
bool hasframe();
|
||||
virtual void *read_frame(int timeout);
|
||||
void set_size(int width, int height);
|
||||
|
||||
protected:
|
||||
bool wait(int msTimeout);
|
||||
|
||||
virtual void stop_capturing(void);
|
||||
virtual void start_capturing(void);
|
||||
void uninit_device(void);
|
||||
virtual void init_mmap(void);
|
||||
virtual void init_device(void);
|
||||
void close_device(void);
|
||||
void open_device(void);
|
||||
|
||||
|
||||
struct buffer
|
||||
{
|
||||
void *start;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
const int v4l_buffer_count = 5;
|
||||
int v4l_width = 3100;
|
||||
int v4l_height = 3100;
|
||||
std::string dev_name;
|
||||
int fd;
|
||||
std::vector<buffer> buffers;
|
||||
unsigned int n_buffers;
|
||||
std::mutex m_lock;
|
||||
volatile bool bStart;
|
||||
};
|
|
@ -0,0 +1,895 @@
|
|||
#include "gvideoisp1.h"
|
||||
#include <fcntl.h> /* low-level i/o */
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include "linux/videodev2.h"
|
||||
#include "linux/v4l2-subdev.h"
|
||||
#include <dlfcn.h>
|
||||
#include "string.h"
|
||||
#include <iostream>
|
||||
#include <malloc.h>
|
||||
|
||||
#include <base/utils.h>
|
||||
|
||||
|
||||
static const std::string loggername = "GVideoISP1";
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
|
||||
#define CLEAR(x) memset(&(x), 0, sizeof(x))
|
||||
|
||||
#define V4L2_BUF_TYPE_META_OUTPUT 14
|
||||
#define V4L2_CAP_META_OUTPUT 0x08000000 /* Is a metadata output device */
|
||||
|
||||
static struct {
|
||||
enum v4l2_buf_type type;
|
||||
bool supported;
|
||||
const char *name;
|
||||
const char *string;
|
||||
} buf_types[] = {
|
||||
{ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 1, "Video capture mplanes", "capture-mplane", },
|
||||
{ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, 1, "Video output", "output-mplane", },
|
||||
{ V4L2_BUF_TYPE_VIDEO_CAPTURE, 1, "Video capture", "capture", },
|
||||
{ V4L2_BUF_TYPE_VIDEO_OUTPUT, 1, "Video output mplanes", "output", },
|
||||
{ V4L2_BUF_TYPE_VIDEO_OVERLAY, 0, "Video overlay", "overlay" },
|
||||
//{ V4L2_BUF_TYPE_META_CAPTURE, 1, "Meta-data capture", "meta-capture", }//,
|
||||
};
|
||||
|
||||
static struct v4l2_format_info {
|
||||
const char *name;
|
||||
unsigned int fourcc;
|
||||
unsigned char n_planes;
|
||||
} pixel_formats[] = {
|
||||
{ "RGB332", V4L2_PIX_FMT_RGB332, 1 },
|
||||
{ "RGB444", V4L2_PIX_FMT_RGB444, 1 },
|
||||
{ "ARGB444", V4L2_PIX_FMT_ARGB444, 1 },
|
||||
{ "XRGB444", V4L2_PIX_FMT_XRGB444, 1 },
|
||||
{ "RGB555", V4L2_PIX_FMT_RGB555, 1 },
|
||||
{ "ARGB555", V4L2_PIX_FMT_ARGB555, 1 },
|
||||
{ "XRGB555", V4L2_PIX_FMT_XRGB555, 1 },
|
||||
{ "RGB565", V4L2_PIX_FMT_RGB565, 1 },
|
||||
{ "RGB555X", V4L2_PIX_FMT_RGB555X, 1 },
|
||||
{ "RGB565X", V4L2_PIX_FMT_RGB565X, 1 },
|
||||
{ "BGR666", V4L2_PIX_FMT_BGR666, 1 },
|
||||
{ "BGR24", V4L2_PIX_FMT_BGR24, 1 },
|
||||
{ "RGB24", V4L2_PIX_FMT_RGB24, 1 },
|
||||
{ "BGR32", V4L2_PIX_FMT_BGR32, 1 },
|
||||
{ "ABGR32", V4L2_PIX_FMT_ABGR32, 1 },
|
||||
{ "XBGR32", V4L2_PIX_FMT_XBGR32, 1 },
|
||||
{ "RGB32", V4L2_PIX_FMT_RGB32, 1 },
|
||||
{ "ARGB32", V4L2_PIX_FMT_ARGB32, 1 },
|
||||
{ "XRGB32", V4L2_PIX_FMT_XRGB32, 1 },
|
||||
//{ "HSV24", V4L2_PIX_FMT_HSV24, 1 },
|
||||
//{ "HSV32", V4L2_PIX_FMT_HSV32, 1 },
|
||||
{ "Y8", V4L2_PIX_FMT_GREY, 1 },
|
||||
{ "Y10", V4L2_PIX_FMT_Y10, 1 },
|
||||
{ "Y12", V4L2_PIX_FMT_Y12, 1 },
|
||||
{ "Y16", V4L2_PIX_FMT_Y16, 1 },
|
||||
{ "UYVY", V4L2_PIX_FMT_UYVY, 1 },
|
||||
{ "VYUY", V4L2_PIX_FMT_VYUY, 1 },
|
||||
{ "YUYV", V4L2_PIX_FMT_YUYV, 1 },
|
||||
{ "YVYU", V4L2_PIX_FMT_YVYU, 1 },
|
||||
{ "NV12", V4L2_PIX_FMT_NV12, 1 },
|
||||
{ "NV12M", V4L2_PIX_FMT_NV12M, 2 },
|
||||
{ "NV21", V4L2_PIX_FMT_NV21, 1 },
|
||||
{ "NV21M", V4L2_PIX_FMT_NV21M, 2 },
|
||||
{ "NV16", V4L2_PIX_FMT_NV16, 1 },
|
||||
{ "NV16M", V4L2_PIX_FMT_NV16M, 2 },
|
||||
{ "NV61", V4L2_PIX_FMT_NV61, 1 },
|
||||
{ "NV61M", V4L2_PIX_FMT_NV61M, 2 },
|
||||
{ "NV24", V4L2_PIX_FMT_NV24, 1 },
|
||||
{ "NV42", V4L2_PIX_FMT_NV42, 1 },
|
||||
{ "YUV420M", V4L2_PIX_FMT_YUV420M, 3 },
|
||||
{ "YUV422M", V4L2_PIX_FMT_YUV422M, 3 },
|
||||
{ "YUV444M", V4L2_PIX_FMT_YUV444M, 3 },
|
||||
{ "YVU420M", V4L2_PIX_FMT_YVU420M, 3 },
|
||||
{ "YVU422M", V4L2_PIX_FMT_YVU422M, 3 },
|
||||
{ "YVU444M", V4L2_PIX_FMT_YVU444M, 3 },
|
||||
{ "SBGGR8", V4L2_PIX_FMT_SBGGR8, 1 },
|
||||
{ "SGBRG8", V4L2_PIX_FMT_SGBRG8, 1 },
|
||||
{ "SGRBG8", V4L2_PIX_FMT_SGRBG8, 1 },
|
||||
{ "SRGGB8", V4L2_PIX_FMT_SRGGB8, 1 },
|
||||
{ "SBGGR10_DPCM8", V4L2_PIX_FMT_SBGGR10DPCM8, 1 },
|
||||
{ "SGBRG10_DPCM8", V4L2_PIX_FMT_SGBRG10DPCM8, 1 },
|
||||
{ "SGRBG10_DPCM8", V4L2_PIX_FMT_SGRBG10DPCM8, 1 },
|
||||
{ "SRGGB10_DPCM8", V4L2_PIX_FMT_SRGGB10DPCM8, 1 },
|
||||
{ "SBGGR10", V4L2_PIX_FMT_SBGGR10, 1 },
|
||||
{ "SGBRG10", V4L2_PIX_FMT_SGBRG10, 1 },
|
||||
{ "SGRBG10", V4L2_PIX_FMT_SGRBG10, 1 },
|
||||
{ "SRGGB10", V4L2_PIX_FMT_SRGGB10, 1 },
|
||||
{ "SBGGR10P", V4L2_PIX_FMT_SBGGR10P, 1 },
|
||||
{ "SGBRG10P", V4L2_PIX_FMT_SGBRG10P, 1 },
|
||||
{ "SGRBG10P", V4L2_PIX_FMT_SGRBG10P, 1 },
|
||||
{ "SRGGB10P", V4L2_PIX_FMT_SRGGB10P, 1 },
|
||||
{ "SBGGR12", V4L2_PIX_FMT_SBGGR12, 1 },
|
||||
{ "SGBRG12", V4L2_PIX_FMT_SGBRG12, 1 },
|
||||
{ "SGRBG12", V4L2_PIX_FMT_SGRBG12, 1 },
|
||||
{ "SRGGB12", V4L2_PIX_FMT_SRGGB12, 1 },
|
||||
{ "DV", V4L2_PIX_FMT_DV, 1 },
|
||||
{ "MJPEG", V4L2_PIX_FMT_MJPEG, 1 },
|
||||
{ "MPEG", V4L2_PIX_FMT_MPEG, 1 },
|
||||
};
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
enum v4l2_field field;
|
||||
} fields[] = {
|
||||
{ "any", V4L2_FIELD_ANY },
|
||||
{ "none", V4L2_FIELD_NONE },
|
||||
{ "top", V4L2_FIELD_TOP },
|
||||
{ "bottom", V4L2_FIELD_BOTTOM },
|
||||
{ "interlaced", V4L2_FIELD_INTERLACED },
|
||||
{ "seq-tb", V4L2_FIELD_SEQ_TB },
|
||||
{ "seq-bt", V4L2_FIELD_SEQ_BT },
|
||||
{ "alternate", V4L2_FIELD_ALTERNATE },
|
||||
{ "interlaced-tb", V4L2_FIELD_INTERLACED_TB },
|
||||
{ "interlaced-bt", V4L2_FIELD_INTERLACED_BT },
|
||||
};
|
||||
|
||||
GVideoISP1::GVideoISP1()
|
||||
{
|
||||
dev_name = "/dev/video0";
|
||||
}
|
||||
|
||||
GVideoISP1::~GVideoISP1()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void* GVideoISP1::read_frame(int timeout) {
|
||||
if (!wait(timeout)){
|
||||
utils::to_log(LOG_LEVEL_FATAL, "read frame time out!!!\n" );
|
||||
return 0;
|
||||
}
|
||||
struct v4l2_plane planes[VIDEO_MAX_PLANES];
|
||||
v4l2_buffer buf;
|
||||
int ret;
|
||||
memset(&buf, 0, sizeof buf);
|
||||
memset(planes, 0, sizeof planes);
|
||||
|
||||
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
||||
//buf.memory = V4L2_MEMORY_USERPTR;//V4L2_MEMORY_MMAP;
|
||||
buf.memory = V4L2_MEMORY_USERPTR;
|
||||
buf.length = VIDEO_MAX_PLANES;
|
||||
buf.m.planes = planes;
|
||||
|
||||
ret = ioctl(fd, VIDIOC_DQBUF, &buf);
|
||||
if (ret < 0) {
|
||||
LOG_TRACE(utils::format_string("Unable to dequeue buffer: %s (%d).",strerror(errno), errno));
|
||||
}
|
||||
else {
|
||||
LOG_TRACE(utils::format_string("VIDIOC_DQBUF sucess"));
|
||||
}
|
||||
|
||||
|
||||
ret = ioctl(fd, VIDIOC_QBUF, &buf);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR(utils::format_string("Unable to requeue buffer: %s (%d).\n",strerror(errno), errno));
|
||||
}
|
||||
else {
|
||||
LOG_TRACE(utils::format_string("VIDIOC_QBUF sucess"));
|
||||
}
|
||||
LOG_TRACE(utils::format_string("buf.index = %d,buf.addr = %p\n",buf.index,buffers[buf.index].start));
|
||||
return buffers[buf.index].start;
|
||||
}
|
||||
|
||||
unsigned int gsp1querybuf_length;
|
||||
void GVideoISP1::start_capturing(void) {
|
||||
unsigned int i;
|
||||
int ret;
|
||||
enum v4l2_buf_type type;
|
||||
|
||||
for (i = 0; i < n_buffers; ++i) {
|
||||
struct v4l2_buffer buf;
|
||||
struct v4l2_plane planes[VIDEO_MAX_PLANES];
|
||||
CLEAR(buf);
|
||||
CLEAR(planes);
|
||||
for(int j = 0; j < VIDEO_MAX_PLANES; j++)
|
||||
{
|
||||
//planes[j].length = buffers[i].length;
|
||||
planes[j].length = gsp1querybuf_length;
|
||||
planes[j].m.userptr =(unsigned long)buffers[i].start;
|
||||
}
|
||||
buf.index = i;
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
||||
buf.memory = V4L2_MEMORY_USERPTR;//V4L2_MEMORY_MMAP;
|
||||
buf.m.planes = planes;
|
||||
buf.length = 1;
|
||||
|
||||
ret = ioctl(fd, VIDIOC_QBUF, &buf);
|
||||
if (ret < 0)
|
||||
LOG_ERROR(utils::format_string("Unable to queue buffer: %s (%d).",strerror(errno), errno));
|
||||
else
|
||||
LOG_TRACE(utils::format_string("buf.index = %d VIDIOC_QBUF sucess.",i));
|
||||
}
|
||||
|
||||
type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
||||
ret = ioctl(fd, VIDIOC_STREAMON, &type);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR(utils::format_string("Unable to %s streaming: %s (%d).","start", strerror(errno), errno));
|
||||
}
|
||||
else {
|
||||
LOG_TRACE(utils::format_string("VIDIOC_STREAMON sucess."));
|
||||
}
|
||||
}
|
||||
|
||||
void GVideoISP1::stop_capturing(void) {
|
||||
enum v4l2_buf_type type;
|
||||
|
||||
type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
||||
if (-1 == ioctl(fd, VIDIOC_STREAMOFF, &type))
|
||||
LOG_ERROR(utils::format_string("streamo off"));
|
||||
|
||||
LOG_TRACE(utils::format_string("gVideo stop_capturing"));
|
||||
}
|
||||
|
||||
static void get_ts_flags(uint32_t flags, const char **ts_type, const char **ts_source)
|
||||
{
|
||||
switch (flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) {
|
||||
case V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN:
|
||||
*ts_type = "unk";
|
||||
break;
|
||||
case V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC:
|
||||
*ts_type = "mono";
|
||||
break;
|
||||
case V4L2_BUF_FLAG_TIMESTAMP_COPY:
|
||||
*ts_type = "copy";
|
||||
break;
|
||||
default:
|
||||
*ts_type = "inv";
|
||||
}
|
||||
switch (flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK) {
|
||||
case V4L2_BUF_FLAG_TSTAMP_SRC_EOF:
|
||||
*ts_source = "EoF";
|
||||
break;
|
||||
case V4L2_BUF_FLAG_TSTAMP_SRC_SOE:
|
||||
*ts_source = "SoE";
|
||||
break;
|
||||
default:
|
||||
*ts_source = "inv";
|
||||
}
|
||||
}
|
||||
|
||||
void GVideoISP1::init_mmap(void) {
|
||||
// struct v4l2_requestbuffers req;
|
||||
// int ret;
|
||||
// unsigned int length;
|
||||
// unsigned int offset;
|
||||
// unsigned int page_size;
|
||||
// int buffer_size = v4l_width * v4l_height * 3;
|
||||
// page_size = getpagesize();
|
||||
// buffer_size = (buffer_size + page_size - 1) & ~(page_size - 1);
|
||||
|
||||
// CLEAR(req);
|
||||
|
||||
// //6.VIDIOC_REQBUFS
|
||||
// req.count = v4l_buffer_count;
|
||||
// req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
||||
// req.memory = V4L2_MEMORY_USERPTR;//V4L2_MEMORY_MMAP;
|
||||
|
||||
// ret = ioctl(fd, VIDIOC_REQBUFS, &req);
|
||||
// if (ret < 0) {
|
||||
// LOG_ERROR(utils::format_string("Unable to request buffers: %s (%d).", strerror(errno),errno));
|
||||
// }
|
||||
// else {
|
||||
// LOG_TRACE(utils::format_string("%s VIDIOC_REQBUFS sucess",dev_name.c_str()));
|
||||
// }
|
||||
// LOG_TRACE(utils::format_string("%u buffers requested.", req.count));
|
||||
|
||||
// buffers.resize(req.count);
|
||||
|
||||
|
||||
// for (n_buffers = 0; n_buffers < buffers.size(); ++n_buffers)
|
||||
// {
|
||||
// buffers[n_buffers].length = buffer_size;
|
||||
// buffers[n_buffers].start = memalign(/* boundary */ page_size, buffer_size);
|
||||
|
||||
// if (!buffers[n_buffers].start)
|
||||
// LOG_ERROR("Out of memory");
|
||||
// }
|
||||
|
||||
struct v4l2_requestbuffers req;
|
||||
int ret;
|
||||
unsigned int length;
|
||||
unsigned int offset;
|
||||
unsigned int page_size;
|
||||
int buffer_size = v4l_width * v4l_height * 3;
|
||||
LOG_TRACE(utils::format_string("init_mmap::buduiqi:changdu: buffer_size= %d\n", buffer_size));
|
||||
page_size = getpagesize();
|
||||
buffer_size = (buffer_size + page_size - 1) & ~(page_size - 1);
|
||||
LOG_TRACE(utils::format_string("init_mmap::shijichangdu:v4l_width = %d,v4l_height = %d\n", v4l_width,v4l_height));
|
||||
LOG_TRACE(utils::format_string("init_mmap::duiqi:page_size = %d,buffer_size = %d\n", page_size,buffer_size));
|
||||
|
||||
CLEAR(req);
|
||||
|
||||
//6.VIDIOC_REQBUFS
|
||||
req.count = v4l_buffer_count;
|
||||
//req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
||||
//req.memory = V4L2_MEMORY_MMAP;
|
||||
req.memory = V4L2_MEMORY_USERPTR;
|
||||
LOG_TRACE(utils::format_string("set v4l_buffer_count = %d\n", req.count));
|
||||
LOG_TRACE(utils::format_string("set v4l_buffer_type = %d\n", req.type));
|
||||
LOG_TRACE(utils::format_string("set v4l_buffer_memory = %d\n", req.memory));
|
||||
|
||||
ret = ioctl(fd, VIDIOC_REQBUFS, &req);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR(utils::format_string("Unable to request buffers: %s (%d).\n", strerror(errno),errno));
|
||||
}
|
||||
else {
|
||||
LOG_TRACE(utils::format_string("%s VIDIOC_REQBUFS sucess\n",dev_name.c_str()));
|
||||
}
|
||||
LOG_TRACE(utils::format_string("%u buffers requested.\n", req.count));
|
||||
|
||||
buffers.resize(req.count);
|
||||
if (buffers.empty()) {
|
||||
utils::to_log(LOG_LEVEL_FATAL, "GVideoISP1::init_mmap: Out of memory\n");
|
||||
}
|
||||
|
||||
//7.VIDIOC_QUERYBUF
|
||||
for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
|
||||
const char *ts_type, *ts_source;
|
||||
struct v4l2_buffer buf;
|
||||
struct v4l2_plane planes[VIDEO_MAX_PLANES];
|
||||
CLEAR(buf);
|
||||
CLEAR(planes);
|
||||
buf.index = n_buffers;
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
||||
//buf.memory = V4L2_MEMORY_MMAP;
|
||||
buf.memory = V4L2_MEMORY_USERPTR;
|
||||
buf.length = VIDEO_MAX_PLANES;
|
||||
buf.m.planes = planes;
|
||||
|
||||
ret = ioctl(fd, VIDIOC_QUERYBUF, &buf);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR(utils::format_string("Unable to query buffer %u: %s (%d).\n", n_buffers,strerror(errno), errno));
|
||||
|
||||
}
|
||||
else {
|
||||
LOG_TRACE(utils::format_string("index %d VIDIOC_QUERYBUF sucess.\n",n_buffers));
|
||||
|
||||
}
|
||||
get_ts_flags(buf.flags, &ts_type, &ts_source);
|
||||
LOG_TRACE(utils::format_string("length: %u offset: %u timestamp type/source: %s/%s\n",
|
||||
buf.length, buf.m.offset, ts_type, ts_source));
|
||||
|
||||
//mmap
|
||||
unsigned int length;
|
||||
unsigned int offset;
|
||||
length = buf.m.planes[0].length;
|
||||
offset = buf.m.planes[0].m.mem_offset;
|
||||
gsp1querybuf_length = buf.m.planes[0].length;
|
||||
LOG_TRACE(utils::format_string("VIDIOC_QUERYBUF:Buffer %u length = %d.\n",n_buffers,length));
|
||||
LOG_TRACE(utils::format_string("VIDIOC_QUERYBUF:Buffer %u offset = %d.\n",n_buffers,offset));
|
||||
LOG_TRACE(utils::format_string("VIDIOC_QUERYBUF:Buffer %u querybuf_length = %d.\n",n_buffers,gsp1querybuf_length));
|
||||
}
|
||||
|
||||
for (n_buffers = 0; n_buffers < buffers.size(); ++n_buffers)
|
||||
{
|
||||
buffers[n_buffers].length = gsp1querybuf_length;
|
||||
buffers[n_buffers].start = memalign(/* boundary */ 1024, gsp1querybuf_length);
|
||||
LOG_TRACE(utils::format_string("memalign:buffers[%d].length = %d\n", n_buffers,buffers[n_buffers].length));
|
||||
LOG_TRACE(utils::format_string("memalign:buffers[%d].start = %p\n", n_buffers,buffers[n_buffers].start));
|
||||
|
||||
if (!buffers[n_buffers].start)
|
||||
{
|
||||
utils::to_log(LOG_LEVEL_FATAL, "GVideoISP1::init_mmap: Out of memory,exit application\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char *v4l2_buf_type_name(__u32 type)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(buf_types); ++i) {
|
||||
if (buf_types[i].type == type)
|
||||
return buf_types[i].name;
|
||||
}
|
||||
|
||||
if (type & V4L2_BUF_TYPE_PRIVATE)
|
||||
return "Private";
|
||||
else
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
static const struct v4l2_format_info *v4l2_format_by_fourcc(unsigned int fourcc)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(pixel_formats); ++i) {
|
||||
if (pixel_formats[i].fourcc == fourcc)
|
||||
return &pixel_formats[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static const char *v4l2_format_name(unsigned int fourcc)
|
||||
{
|
||||
const struct v4l2_format_info *info;
|
||||
static char name[5];
|
||||
unsigned int i;
|
||||
|
||||
info = v4l2_format_by_fourcc(fourcc);
|
||||
if (info)
|
||||
return info->name;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
name[i] = fourcc & 0xff;
|
||||
fourcc >>= 8;
|
||||
}
|
||||
|
||||
name[4] = '\0';
|
||||
return name;
|
||||
}
|
||||
|
||||
static void video_enum_frame_intervals(int fd, __u32 pixelformat,
|
||||
unsigned int width, unsigned int height)
|
||||
{
|
||||
struct v4l2_frmivalenum ival;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; ; ++i) {
|
||||
memset(&ival, 0, sizeof ival);
|
||||
ival.index = i;
|
||||
ival.pixel_format = pixelformat;
|
||||
ival.width = width;
|
||||
ival.height = height;
|
||||
ret = ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
if (i != ival.index)
|
||||
LOG_TRACE(utils::format_string("Warning: driver returned wrong ival index " "%u.\n", ival.index));
|
||||
if (pixelformat != ival.pixel_format)
|
||||
LOG_TRACE(utils::format_string("Warning: driver returned wrong ival pixel " "format %08x.\n", ival.pixel_format));
|
||||
if (width != ival.width)
|
||||
LOG_TRACE(utils::format_string("Warning: driver returned wrong ival width " "%u.\n", ival.width));
|
||||
if (height != ival.height)
|
||||
LOG_TRACE(utils::format_string("Warning: driver returned wrong ival height " "%u.\n", ival.height));
|
||||
|
||||
if (i != 0)
|
||||
utils::to_log(LOG_LEVEL_DEBUG, ", ");
|
||||
|
||||
switch (ival.type) {
|
||||
case V4L2_FRMIVAL_TYPE_DISCRETE:
|
||||
LOG_TRACE(utils::format_string("%u/%u", ival.discrete.numerator, ival.discrete.denominator));
|
||||
break;
|
||||
|
||||
case V4L2_FRMIVAL_TYPE_CONTINUOUS:
|
||||
LOG_TRACE(utils::format_string("%u/%u - %u/%u", ival.stepwise.min.numerator, ival.stepwise.min.denominator, ival.stepwise.max.numerator, ival.stepwise.max.denominator));
|
||||
return;
|
||||
|
||||
case V4L2_FRMIVAL_TYPE_STEPWISE:
|
||||
LOG_TRACE(utils::format_string("%u/%u - %u/%u (by %u/%u)", ival.stepwise.min.numerator, ival.stepwise.min.denominator, ival.stepwise.max.numerator, ival.stepwise.max.denominator, ival.stepwise.step.numerator, ival.stepwise.step.denominator));
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void video_enum_frame_sizes(int fd, __u32 pixelformat)
|
||||
{
|
||||
struct v4l2_frmsizeenum frame;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; ; ++i) {
|
||||
memset(&frame, 0, sizeof frame);
|
||||
frame.index = i;
|
||||
frame.pixel_format = pixelformat;
|
||||
ret = ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frame);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
if (i != frame.index)
|
||||
LOG_TRACE(utils::format_string("Warning: driver returned wrong frame index " "%u.\n", frame.index));
|
||||
if (pixelformat != frame.pixel_format)
|
||||
LOG_TRACE(utils::format_string("Warning: driver returned wrong frame pixel " "format %08x.\n", frame.pixel_format));
|
||||
|
||||
switch (frame.type) {
|
||||
case V4L2_FRMSIZE_TYPE_DISCRETE:
|
||||
LOG_TRACE(utils::format_string("\tFrame size: %ux%u (", frame.discrete.width, frame.discrete.height));
|
||||
video_enum_frame_intervals(fd, frame.pixel_format, frame.discrete.width, frame.discrete.height);
|
||||
break;
|
||||
|
||||
case V4L2_FRMSIZE_TYPE_CONTINUOUS:
|
||||
LOG_TRACE(utils::format_string("\tFrame size: %ux%u - %ux%u (", frame.stepwise.min_width, frame.stepwise.min_height, frame.stepwise.max_width, frame.stepwise.max_height));
|
||||
video_enum_frame_intervals(fd, frame.pixel_format, frame.stepwise.max_width, frame.stepwise.max_height);
|
||||
break;
|
||||
|
||||
case V4L2_FRMSIZE_TYPE_STEPWISE:
|
||||
LOG_TRACE(utils::format_string("\tFrame size: %ux%u - %ux%u (by %ux%u) (\n", frame.stepwise.min_width, frame.stepwise.min_height, frame.stepwise.max_width, frame.stepwise.max_height, frame.stepwise.step_width, frame.stepwise.step_height));
|
||||
video_enum_frame_intervals(fd, frame.pixel_format, frame.stepwise.max_width, frame.stepwise.max_height);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void video_enum_formats(int fd, enum v4l2_buf_type type)
|
||||
{
|
||||
struct v4l2_fmtdesc fmt;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; ; ++i) {
|
||||
memset(&fmt, 0, sizeof fmt);
|
||||
fmt.index = i;
|
||||
fmt.type = type;
|
||||
ret = ioctl(fd, VIDIOC_ENUM_FMT, &fmt);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
if (i != fmt.index)
|
||||
LOG_TRACE(utils::format_string("Warning: driver returned wrong format index " "%u.\n", fmt.index));
|
||||
if (type != fmt.type)
|
||||
LOG_TRACE(utils::format_string("Warning: driver returned wrong format type " "%u.\n", fmt.type));
|
||||
|
||||
LOG_TRACE(utils::format_string("\tFormat %u: %s (%08x)\n", i, v4l2_format_name(fmt.pixelformat), fmt.pixelformat));
|
||||
LOG_TRACE(utils::format_string("\tType: %s (%u)\n", v4l2_buf_type_name(fmt.type), fmt.type));
|
||||
LOG_TRACE(utils::format_string("\tName: %.32s\n", fmt.description));
|
||||
video_enum_frame_sizes(fd, fmt.pixelformat);
|
||||
}
|
||||
}
|
||||
|
||||
static void video_enum_inputs(int fd)
|
||||
{
|
||||
struct v4l2_input input;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; ; ++i) {
|
||||
memset(&input, 0, sizeof input);
|
||||
input.index = i;
|
||||
ret = ioctl(fd, VIDIOC_ENUMINPUT, &input);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
if (i != input.index)
|
||||
LOG_TRACE(utils::format_string("Warning: driver returned wrong input index " "%u.\n", input.index));
|
||||
|
||||
LOG_TRACE(utils::format_string("\tInput %u: %s.\n", i, input.name));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static const char *v4l2_field_name(__u32 field)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fields); ++i) {
|
||||
if (fields[i].field == field)
|
||||
return fields[i].name;
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
|
||||
static void rkisp_sd_set_crop(const char *ispsd, int fd, int pad, int *w, int *h)
|
||||
{
|
||||
struct v4l2_subdev_selection sel;
|
||||
int ret;
|
||||
|
||||
memset(&sel, 0, sizeof(sel));
|
||||
sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
|
||||
sel.pad = pad;
|
||||
sel.r.width = *w;
|
||||
sel.r.height = *h;
|
||||
sel.r.left = 0;
|
||||
sel.r.top = 0;
|
||||
sel.target = V4L2_SEL_TGT_CROP;
|
||||
sel.flags = V4L2_SEL_FLAG_LE;
|
||||
ret = ioctl(fd, VIDIOC_SUBDEV_S_SELECTION, &sel);
|
||||
if (ret) {
|
||||
LOG_ERROR(utils::format_string("subdev %s pad %d crop failed, ret = %d\n", ispsd, sel.pad, ret));
|
||||
}
|
||||
else {
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_S_SELECTION sucess.\n"));
|
||||
}
|
||||
|
||||
*w = sel.r.width;
|
||||
*h = sel.r.height;
|
||||
}
|
||||
|
||||
static void rkisp_video_set_crop(int fd, int x, int y, int w, int h)
|
||||
{
|
||||
struct v4l2_selection sel;
|
||||
int ret;
|
||||
memset(&sel, 0, sizeof(sel));
|
||||
sel.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
||||
sel.r.width = w;
|
||||
sel.r.height = h;
|
||||
sel.r.left = x;
|
||||
sel.r.top = y;
|
||||
sel.target = V4L2_SEL_TGT_CROP;
|
||||
sel.flags = 0;
|
||||
ret = ioctl(fd, VIDIOC_S_SELECTION, &sel);
|
||||
if (ret) {
|
||||
LOG_ERROR(utils::format_string("VIDIOC_S_SELECTION::set output crop(0,0/%dx%d) failed, %s\n", w, h, strerror(errno)));
|
||||
}
|
||||
else {
|
||||
LOG_TRACE(utils::format_string("sVIDIOC_S_SELECTION scuess\n"));
|
||||
}
|
||||
|
||||
}
|
||||
void GVideoISP1::init_device(void) {
|
||||
struct v4l2_capability cap;
|
||||
struct v4l2_format fmt;
|
||||
|
||||
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
struct v4l2_fmtdesc fmt_1;
|
||||
struct v4l2_frmsizeenum frmsize;
|
||||
struct v4l2_frmivalenum frmival;
|
||||
struct v4l2_subdev_format subdev_fmt;
|
||||
int subdev_fd;
|
||||
|
||||
unsigned int caps;
|
||||
bool has_video;
|
||||
bool has_meta;
|
||||
bool has_capture;
|
||||
bool has_output;
|
||||
bool has_mplane;
|
||||
|
||||
int ret;
|
||||
int i;
|
||||
//---------------------------set /dev/v4l2-subdev*-------------------------------------//
|
||||
//----------------------1.v4l2_subdev2 set format----------------------//
|
||||
subdev_fd = ::open(subdev2_name.c_str(),O_RDWR,0);
|
||||
if (-1 == subdev_fd) {
|
||||
LOG_ERROR(utils::format_string("Cannot open '%s'\n", subdev2_name.c_str()));
|
||||
}
|
||||
else {
|
||||
LOG_TRACE(utils::format_string("open %s success.fd = %d.\n",subdev2_name.c_str(),subdev_fd));
|
||||
}
|
||||
memset(&subdev_fmt, 0, sizeof subdev_fmt);
|
||||
subdev_fmt.pad = 0;
|
||||
subdev_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
|
||||
ret = ioctl(subdev_fd, VIDIOC_SUBDEV_G_FMT, &subdev_fmt);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR(utils::format_string("VIDIOC_SUBDEV_G_FMT failed.\n"));
|
||||
}
|
||||
else {
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_G_FMT SUCESS\n"));
|
||||
}
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_G_FMT:height = %d;width = %d;code = %d.\n", subdev_fmt.format.height,subdev_fmt.format.width,subdev_fmt.format.code));
|
||||
|
||||
subdev_fmt.format.width = v4l_width;
|
||||
subdev_fmt.format.height = v4l_height;
|
||||
LOG_TRACE(utils::format_string("set height = %d\n",subdev_fmt.format.height));
|
||||
LOG_TRACE(utils::format_string("set width = %d\n",subdev_fmt.format.width));
|
||||
ret = ioctl(subdev_fd, VIDIOC_SUBDEV_S_FMT, &subdev_fmt);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR(utils::format_string("VIDIOC_SUBDEV_S_FMT failed.\n"));
|
||||
}
|
||||
else {
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_S_FMT SUCESS\n"));
|
||||
}
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_S_FMT:height = %d;width = %d;code = %d.\n", subdev_fmt.format.height,subdev_fmt.format.width,subdev_fmt.format.code));
|
||||
::close(subdev_fd);
|
||||
//-------------------------------------------------------------//
|
||||
|
||||
//----------------------2.v4l2_subdev0 set format::pad0----------------------//
|
||||
subdev_fd = ::open(subdev0_name.c_str(),O_RDWR,0);
|
||||
if (-1 == subdev_fd) {
|
||||
LOG_ERROR(utils::format_string("Cannot open '%s'\n", subdev0_name.c_str()));
|
||||
}
|
||||
else {
|
||||
LOG_TRACE(utils::format_string("open %s success.fd = %d.\n",subdev0_name.c_str(),subdev_fd));
|
||||
}
|
||||
memset(&subdev_fmt, 0, sizeof subdev_fmt);
|
||||
subdev_fmt.pad = 0;
|
||||
subdev_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
|
||||
ret = ioctl(subdev_fd, VIDIOC_SUBDEV_G_FMT, &subdev_fmt);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR(utils::format_string("VIDIOC_SUBDEV_G_FMT failed.\n"));
|
||||
}
|
||||
else {
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_G_FMT SUCESS\n"));
|
||||
}
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_G_FMT:pad = %d;height = %d;width = %d;code = %d.\n", subdev_fmt.pad,subdev_fmt.format.height,subdev_fmt.format.width,subdev_fmt.format.code));
|
||||
subdev_fmt.format.width = v4l_width;
|
||||
subdev_fmt.format.height = v4l_height;
|
||||
LOG_TRACE(utils::format_string("set height = %d;width = %d\n",subdev_fmt.format.height,subdev_fmt.format.width));
|
||||
|
||||
ret = ioctl(subdev_fd, VIDIOC_SUBDEV_S_FMT, &subdev_fmt);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR(utils::format_string("VIDIOC_SUBDEV_S_FMT failed.\n"));
|
||||
}
|
||||
else {
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_S_FMT SUCESS\n"));
|
||||
}
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_S_FMT:pad = %d;height = %d;width = %d;code = %d.\n", subdev_fmt.pad,subdev_fmt.format.height,subdev_fmt.format.width,subdev_fmt.format.code));
|
||||
rkisp_sd_set_crop(subdev0_name.c_str(),subdev_fd, 0 , &v4l_width, &v4l_height);
|
||||
LOG_TRACE(utils::format_string("v4l_set height = %d;width = %d\n",v4l_width,v4l_height));
|
||||
//----------------------3.v4l2_subdev0 set format::pad2----------------------//
|
||||
rkisp_sd_set_crop(subdev0_name.c_str(),subdev_fd, 2 , &v4l_width, &v4l_height);
|
||||
LOG_TRACE(utils::format_string("v4l_set height = %d;width = %d\n",v4l_width,v4l_height));
|
||||
memset(&subdev_fmt, 0, sizeof subdev_fmt);
|
||||
subdev_fmt.pad = 2;
|
||||
subdev_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
|
||||
ret = ioctl(subdev_fd, VIDIOC_SUBDEV_G_FMT, &subdev_fmt);
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_G_FMT failed.\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_G_FMT SUCESS\n"));
|
||||
}
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_G_FMT:pad = %d\n",subdev_fmt.pad));
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_G_FMT:subdev_fmt.format.height = %d\n",subdev_fmt.format.height));
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_G_FMT:subdev_fmt.format.width = %d\n",subdev_fmt.format.width));
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_G_FMT:subdev_fmt.format.code = %d\n",subdev_fmt.format.code));
|
||||
subdev_fmt.format.width = v4l_width;
|
||||
subdev_fmt.format.height = v4l_height;
|
||||
LOG_TRACE(utils::format_string("set height = %d\n",subdev_fmt.format.height));
|
||||
LOG_TRACE(utils::format_string("set width = %d\n",subdev_fmt.format.width));
|
||||
|
||||
ret = ioctl(subdev_fd, VIDIOC_SUBDEV_S_FMT, &subdev_fmt);
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_S_FMT failed.\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_S_FMT SUCESS\n"));
|
||||
}
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_G_FMT:pad = %d\n",subdev_fmt.pad));
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_S_FMT:subdev_fmt.format.height = %d\n",subdev_fmt.format.height));
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_S_FMT:subdev_fmt.format.width = %d\n",subdev_fmt.format.width));
|
||||
LOG_TRACE(utils::format_string("VIDIOC_SUBDEV_S_FMT:subdev_fmt.format.code = %d\n",subdev_fmt.format.code));
|
||||
//-------------------------------------------------------------//
|
||||
|
||||
//-------4.set video selection(crop) because ispsd size changed------------------//
|
||||
rkisp_video_set_crop(fd, 0, 0, v4l_width, v4l_height);
|
||||
//----------------------1.VIDIOC_QUERYCAP----------------------//
|
||||
memset(&cap, 0, sizeof cap);
|
||||
if (-1 == ioctl(fd, VIDIOC_QUERYCAP, &cap))
|
||||
|
||||
ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_TRACE(utils::format_string("VIDIOC_QUERYCAP failed.\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_TRACE(utils::format_string("cap.capabilities = %x .\n",cap.capabilities));
|
||||
LOG_TRACE(utils::format_string("cap.device_caps = %x .\n",cap.device_caps));
|
||||
}
|
||||
caps = cap.capabilities & V4L2_CAP_DEVICE_CAPS
|
||||
? cap.device_caps : cap.capabilities;
|
||||
|
||||
has_video = caps & (V4L2_CAP_VIDEO_CAPTURE_MPLANE |
|
||||
V4L2_CAP_VIDEO_CAPTURE |
|
||||
V4L2_CAP_VIDEO_OUTPUT_MPLANE |
|
||||
V4L2_CAP_VIDEO_OUTPUT);
|
||||
// has_meta = caps & (V4L2_CAP_META_CAPTURE |
|
||||
// V4L2_CAP_META_OUTPUT);
|
||||
// has_capture = caps & (V4L2_CAP_VIDEO_CAPTURE_MPLANE |
|
||||
// V4L2_CAP_VIDEO_CAPTURE |
|
||||
// V4L2_CAP_META_CAPTURE);
|
||||
has_output = caps & (V4L2_CAP_VIDEO_OUTPUT_MPLANE |
|
||||
V4L2_CAP_VIDEO_OUTPUT |
|
||||
V4L2_CAP_META_OUTPUT);
|
||||
has_mplane = caps & (V4L2_CAP_VIDEO_CAPTURE_MPLANE |
|
||||
V4L2_CAP_VIDEO_OUTPUT_MPLANE);
|
||||
|
||||
LOG_TRACE(utils::format_string("Device `%s' on `%s' (driver '%s') supports%s%s%s%s %s mplanes.\n", cap.card, cap.bus_info, cap.driver, has_video ? " video," : "", has_meta ? " meta-data," : "", has_capture ? " capture," : "", has_output ? " output," : "", has_mplane ? "with" : "without"));
|
||||
|
||||
|
||||
if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
|
||||
LOG_ERROR(utils::format_string("%s does not support streaming i/o\n", dev_name.c_str()));
|
||||
}
|
||||
else {
|
||||
LOG_TRACE(utils::format_string("%s support streaming i/o\n", dev_name.c_str()));
|
||||
}
|
||||
//-------------------------------------------------------------//
|
||||
|
||||
//----------------------2.VIDIOC_ENUM_FMT----------------------//
|
||||
LOG_TRACE(utils::format_string("- Available formats:\n"));
|
||||
LOG_TRACE(utils::format_string("------------------------------------------------------\n"));
|
||||
LOG_TRACE(utils::format_string("fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE = %d\n", V4L2_BUF_TYPE_VIDEO_CAPTURE));
|
||||
video_enum_formats(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE);
|
||||
|
||||
LOG_TRACE(utils::format_string("------------------------------------------------------\n"));
|
||||
LOG_TRACE(utils::format_string("fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = %d\n", V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE));
|
||||
video_enum_formats(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
|
||||
|
||||
LOG_TRACE(utils::format_string("------------------------------------------------------\n"));
|
||||
LOG_TRACE(utils::format_string("fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT = %d\n", V4L2_BUF_TYPE_VIDEO_OUTPUT));
|
||||
video_enum_formats(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT);
|
||||
|
||||
LOG_TRACE(utils::format_string("------------------------------------------------------\n"));
|
||||
LOG_TRACE(utils::format_string("fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE = %d\n", V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE));
|
||||
video_enum_formats(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
|
||||
|
||||
LOG_TRACE(utils::format_string("------------------------------------------------------\n"));
|
||||
LOG_TRACE(utils::format_string("fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY = %d\n", V4L2_BUF_TYPE_VIDEO_OVERLAY));
|
||||
video_enum_formats(fd, V4L2_BUF_TYPE_VIDEO_OVERLAY);
|
||||
|
||||
LOG_TRACE(utils::format_string("------------------------------------------------------\n"));
|
||||
//LOG_TRACE(utils::format_string("fmt.type = V4L2_BUF_TYPE_META_CAPTURE = %d\n", V4L2_BUF_TYPE_META_CAPTURE));
|
||||
//video_enum_formats(fd, V4L2_BUF_TYPE_META_CAPTURE);
|
||||
|
||||
LOG_TRACE(utils::format_string("------------------------------------------------------\n"));
|
||||
LOG_TRACE(utils::format_string("fmt.type = V4L2_BUF_TYPE_META_OUTPUT = %d\n", V4L2_BUF_TYPE_META_OUTPUT));
|
||||
//video_enum_formats(fd, V4L2_BUF_TYPE_META_OUTPUT);
|
||||
LOG_TRACE(utils::format_string("------------------------------------------------------\n"));
|
||||
//--------------------------------------------------------------//
|
||||
|
||||
//----------------------3.VIDIOC_ENUMINPUT----------------------//
|
||||
LOG_TRACE(utils::format_string("- Available inputs:\n"));
|
||||
video_enum_inputs(fd);
|
||||
//-------------------------------------------------------------//
|
||||
|
||||
//----------------------4.VIDIOC_S_FMT-------------------------//
|
||||
LOG_TRACE(utils::format_string("..........................................................................\n"));
|
||||
CLEAR(fmt);
|
||||
//fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
||||
fmt.fmt.pix.width = v4l_width;
|
||||
fmt.fmt.pix.height = v4l_height;
|
||||
//fmt.fmt.pix.width = 2112;
|
||||
//fmt.fmt.pix.height = 1568;
|
||||
LOG_TRACE(utils::format_string("v4l2 VIDIOC_S_FMT width:%d, height:%d\n", fmt.fmt.pix.width, fmt.fmt.pix.height));
|
||||
//fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
|
||||
//fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
|
||||
//fmt.fmt.pix_mp.width = 1728;
|
||||
//fmt.fmt.pix_mp.height = 1568;
|
||||
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_RGB24;
|
||||
fmt.fmt.pix_mp.field = 0;
|
||||
fmt.fmt.pix_mp.num_planes = 1;
|
||||
fmt.fmt.pix_mp.flags = 0;
|
||||
fmt.fmt.pix_mp.plane_fmt[0].bytesperline = 0;
|
||||
fmt.fmt.pix_mp.plane_fmt[0].sizeimage = 0;
|
||||
|
||||
ret = ioctl(fd, VIDIOC_S_FMT, &fmt);
|
||||
if (ret < 0) {
|
||||
LOG_TRACE(utils::format_string("Unable to set format: %s (%d).\n", strerror(errno),errno));
|
||||
|
||||
}
|
||||
else {
|
||||
LOG_TRACE(utils::format_string("VIDIOC_S_FMT sucess.\n"));
|
||||
}
|
||||
|
||||
LOG_TRACE(utils::format_string("Video format set: %s (%08x) %ux%u field %s, %u planes: \n", v4l2_format_name(fmt.fmt.pix_mp.pixelformat), fmt.fmt.pix_mp.pixelformat, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, v4l2_field_name(fmt.fmt.pix_mp.field), fmt.fmt.pix_mp.num_planes));
|
||||
|
||||
for (i = 0; i < fmt.fmt.pix_mp.num_planes; i++) {
|
||||
LOG_TRACE(utils::format_string(" * bytesperline %u, buffer size %u\n", fmt.fmt.pix_mp.plane_fmt[i].bytesperline, fmt.fmt.pix_mp.plane_fmt[i].sizeimage));
|
||||
}
|
||||
//-------------------------------------------------------------//
|
||||
|
||||
//----------------------5.VIDIOC_G_FMT-------------------------//
|
||||
memset(&fmt, 0, sizeof fmt);
|
||||
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
||||
ret = ioctl(fd, VIDIOC_G_FMT, &fmt);
|
||||
if (ret < 0) {
|
||||
LOG_TRACE(utils::format_string("Unable to get format: %s (%d).\n", strerror(errno),errno));
|
||||
}
|
||||
else {
|
||||
utils::to_log(LOG_LEVEL_DEBUG, "VIDIOC_G_FMT sucess.");
|
||||
}
|
||||
LOG_TRACE(utils::format_string("Video format: %s (%08x) %ux%u field %s, %u planes: \n", v4l2_format_name(fmt.fmt.pix_mp.pixelformat), fmt.fmt.pix_mp.pixelformat, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, v4l2_field_name(fmt.fmt.pix_mp.field), fmt.fmt.pix_mp.num_planes));
|
||||
for (i = 0; i < fmt.fmt.pix_mp.num_planes; i++)
|
||||
LOG_TRACE(utils::format_string(" * bytesperline %u, buffer size %u\n", fmt.fmt.pix_mp.plane_fmt[i].bytesperline, fmt.fmt.pix_mp.plane_fmt[i].sizeimage));
|
||||
|
||||
::close(subdev_fd);
|
||||
//-------------------------------------------------------------//
|
||||
|
||||
//6.VIDIOC_REQBUFS //7.VIDIOC_QUERYBUF mmmap
|
||||
init_mmap();
|
||||
//-------------------------------------------------------------//
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
#include "gvideo.h"
|
||||
|
||||
|
||||
class GVideoISP1 : public gVideo
|
||||
{
|
||||
public:
|
||||
GVideoISP1();
|
||||
virtual ~GVideoISP1();
|
||||
|
||||
virtual void *read_frame(int timeout);
|
||||
|
||||
protected:
|
||||
virtual void start_capturing(void);
|
||||
virtual void stop_capturing(void);
|
||||
virtual void init_mmap(void);
|
||||
virtual void init_device(void);
|
||||
|
||||
private:
|
||||
const std::string subdev0_name = "/dev/v4l-subdev0";
|
||||
const std::string subdev1_name = "/dev/v4l-subdev1";
|
||||
const std::string subdev2_name = "/dev/v4l-subdev2";
|
||||
const std::string subdev3_name = "/dev/v4l-subdev3";
|
||||
};
|
File diff suppressed because one or more lines are too long
|
@ -21,6 +21,8 @@
|
|||
#define IMAGE_HANDLER_PROTO void(dyn_mem_ptr, bool, LPPACKIMAGE)
|
||||
|
||||
class FpgaComm;
|
||||
class GVideoISP1;
|
||||
class MotorBoard;
|
||||
|
||||
class scanner_hw : public sane_opt_provider
|
||||
{
|
||||
|
@ -29,6 +31,8 @@ class scanner_hw : public sane_opt_provider
|
|||
bool auto_scan_ = false;
|
||||
int time_to_exit_auto_scan_ = 60; // seconds
|
||||
std::unique_ptr<FpgaComm> img_controller_;
|
||||
std::unique_ptr<GVideoISP1> camera_;
|
||||
std::unique_ptr<MotorBoard> motor_;
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -104,34 +108,34 @@ public:
|
|||
// "default": 300,
|
||||
// "range": [200, 300]
|
||||
// },
|
||||
// "is-wait-scan": {
|
||||
// "cat": "base",
|
||||
// "group": "feeder",
|
||||
// "title": "待纸扫描",
|
||||
// "desc": "启用后,文稿放入扫描仪时将自动启动扫描",
|
||||
// "type": "bool",
|
||||
// "fix-id": 34873,
|
||||
// "ui-pos": 12,
|
||||
// "auth": 0,
|
||||
// "size": 4,
|
||||
// "cur": false,
|
||||
// "default": false
|
||||
// },
|
||||
// "wait-scan-exit": {
|
||||
// "cat": "base",
|
||||
// "group": "feeder",
|
||||
// "title": "待纸扫描退出时间",
|
||||
// "desc": "设置结束待纸扫描的时间",
|
||||
// "type": "string",
|
||||
// "fix-id": 34920,
|
||||
// "ui-pos": 13,
|
||||
// "auth": 0,
|
||||
// "size": 16,
|
||||
// "cur": "60s",
|
||||
// "default": "60s",
|
||||
// "range": ["15s", "30s", "60s", "2min", "4min", "8min"],
|
||||
// "depend": "is-wait-scan==true"
|
||||
// },
|
||||
// "is-wait-scan": {
|
||||
// "cat": "base",
|
||||
// "group": "feeder",
|
||||
// "title": "待纸扫描",
|
||||
// "desc": "启用后,文稿放入扫描仪时将自动启动扫描",
|
||||
// "type": "bool",
|
||||
// "fix-id": 34873,
|
||||
// "ui-pos": 12,
|
||||
// "auth": 0,
|
||||
// "size": 4,
|
||||
// "cur": false,
|
||||
// "default": false
|
||||
// },
|
||||
// "wait-scan-exit": {
|
||||
// "cat": "base",
|
||||
// "group": "feeder",
|
||||
// "title": "待纸扫描退出时间",
|
||||
// "desc": "设置结束待纸扫描的时间",
|
||||
// "type": "string",
|
||||
// "fix-id": 34920,
|
||||
// "ui-pos": 13,
|
||||
// "auth": 0,
|
||||
// "size": 16,
|
||||
// "cur": "60s",
|
||||
// "default": "60s",
|
||||
// "range": ["15s", "30s", "60s", "2min", "4min", "8min"],
|
||||
// "depend": "is-wait-scan==true"
|
||||
// },
|
||||
// "baud": {
|
||||
// "cat": "none",
|
||||
// "group": "CIS",
|
||||
|
@ -188,7 +192,7 @@ public:
|
|||
// "title": "曝光度(正面蓝色通道)",
|
||||
// "desc": "正面蓝色通道的曝光强度",
|
||||
// "type": "int",
|
||||
// "ui-pos": 30,
|
||||
// "ui-pos": 32,
|
||||
// "auth": 0,
|
||||
// "size": 4,
|
||||
// "cur": 0,
|
||||
|
@ -222,7 +226,7 @@ public:
|
|||
// "title": "曝光度(正面红色通道)",
|
||||
// "desc": "正面红色通道的曝光强度",
|
||||
// "type": "int",
|
||||
// "ui-pos": 32,
|
||||
// "ui-pos": 30,
|
||||
// "auth": 0,
|
||||
// "size": 4,
|
||||
// "cur": 0,
|
||||
|
@ -239,7 +243,7 @@ public:
|
|||
// "title": "曝光度(背面蓝色通道)",
|
||||
// "desc": "背面蓝色通道的曝光强度",
|
||||
// "type": "int",
|
||||
// "ui-pos": 33,
|
||||
// "ui-pos": 35,
|
||||
// "auth": 0,
|
||||
// "size": 4,
|
||||
// "cur": 0,
|
||||
|
@ -273,7 +277,7 @@ public:
|
|||
// "title": "曝光度(背面红色通道)",
|
||||
// "desc": "背面红色通道的曝光强度",
|
||||
// "type": "int",
|
||||
// "ui-pos": 35,
|
||||
// "ui-pos": 33,
|
||||
// "auth": 0,
|
||||
// "size": 4,
|
||||
// "cur": 0,
|
||||
|
@ -321,8 +325,8 @@ public:
|
|||
// "off-f": {
|
||||
// "cat": "none",
|
||||
// "group": "CIS",
|
||||
// "title": "偏移(正面)",
|
||||
// "desc": "正面的偏移量",
|
||||
// "title": "增益补偿(正面)",
|
||||
// "desc": "正面的增益补偿量",
|
||||
// "type": "int",
|
||||
// "ui-pos": 45,
|
||||
// "auth": 0,
|
||||
|
@ -330,7 +334,7 @@ public:
|
|||
// "cur": 0,
|
||||
// "default": 0,
|
||||
// "range": {
|
||||
// "min": 0,
|
||||
// "min": -100,
|
||||
// "max": 100,
|
||||
// "step": 1
|
||||
// }
|
||||
|
@ -338,8 +342,8 @@ public:
|
|||
// "off-b": {
|
||||
// "cat": "none",
|
||||
// "group": "CIS",
|
||||
// "title": "偏移(背面)",
|
||||
// "desc": "背面的偏移量",
|
||||
// "title": "增益补偿(背面)",
|
||||
// "desc": "背面的增益补偿量",
|
||||
// "type": "int",
|
||||
// "ui-pos": 46,
|
||||
// "auth": 0,
|
||||
|
@ -347,7 +351,7 @@ public:
|
|||
// "cur": 0,
|
||||
// "default": 0,
|
||||
// "range": {
|
||||
// "min": 0,
|
||||
// "min": -100,
|
||||
// "max": 100,
|
||||
// "step": 1
|
||||
// }
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
#pragma once
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
class AutoSemaphore
|
||||
{
|
||||
public:
|
||||
AutoSemaphore()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~AutoSemaphore()
|
||||
{
|
||||
notify_all();
|
||||
}
|
||||
|
||||
virtual void notify_all()
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(mutx);
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
virtual bool wait(int timeout_ms)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(mutx);
|
||||
return cv.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::no_timeout;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::mutex mutx;
|
||||
std::condition_variable cv;
|
||||
};
|
||||
|
||||
class AutoEvent : public AutoSemaphore
|
||||
{
|
||||
public:
|
||||
AutoEvent()
|
||||
: bNotify(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~AutoEvent()
|
||||
{
|
||||
notify_all();
|
||||
}
|
||||
|
||||
virtual void notify_all()
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(mutx);
|
||||
bNotify = true;
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
virtual bool wait(int timeout_ms)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(mutx);
|
||||
if (bNotify)
|
||||
{
|
||||
bNotify = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ret = cv.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::no_timeout;
|
||||
bNotify = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
volatile bool bNotify;
|
||||
};
|
|
@ -0,0 +1,427 @@
|
|||
#include "motorboard.h"
|
||||
|
||||
#include <iostream>
|
||||
#include "../uart/PinMonitor.h"
|
||||
#include "../uart/uartregsaccess.h"
|
||||
#include <iomanip>
|
||||
|
||||
#include <base/utils.h>
|
||||
|
||||
|
||||
#define MOTOR_UART "/dev/ttyS4"
|
||||
|
||||
static const std::string loggername = "MotorBoard";
|
||||
|
||||
|
||||
MotorBoard::MotorBoard()
|
||||
: devPort(MOTOR_UART),
|
||||
m_glue({nullptr, nullptr, nullptr,nullptr,nullptr,nullptr})
|
||||
{
|
||||
m_uartEnable.reset(new GpioOut(152));
|
||||
m_uartEnable->setDirection(Gpio::out);
|
||||
// m_uartEnable->setEdge(Gpio::rising);
|
||||
//m_uartEnable->setValue(Gpio::Low);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
m_regsAccess.reset(new UartRegsAccess(devPort, bauds, 0x07, 0x87));
|
||||
m_intPinMonitor.reset(new PinMonitor(intport, std::bind(&MotorBoard::pin_call, this, std::placeholders::_1)));
|
||||
//m_scansensorMonitor.reset(new PinMonitor(149, std::bind(&MotorBoard::scansensor_call, this, std::placeholders::_1)));
|
||||
//m_uartEnable->setValue(Gpio::High);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
m_os_mode = os_mode();
|
||||
}
|
||||
static int paperinnum = 0;
|
||||
void MotorBoard::start()
|
||||
{
|
||||
keep_last_paper=false;
|
||||
unsigned int val;
|
||||
SMBCONFIG *smbc = (SMBCONFIG *)(&val);
|
||||
read(0, val);
|
||||
smbc->enable = 0;
|
||||
write(0, val);
|
||||
smbc->enable = 1;
|
||||
write(0, val);
|
||||
paperinnum =0 ;
|
||||
}
|
||||
|
||||
void MotorBoard::stop()
|
||||
{
|
||||
unsigned int val;
|
||||
SMBCONFIG *smbc = (SMBCONFIG *)(&val);
|
||||
read(0, val);
|
||||
smbc->enable = 0;
|
||||
write(0, val);
|
||||
}
|
||||
|
||||
|
||||
void MotorBoard::pick_paper(void)
|
||||
{
|
||||
unsigned int val;
|
||||
SMBCONFIG *smbc = (SMBCONFIG *)(&val);
|
||||
read(0x00, val);
|
||||
smbc->pick_paper = 0;
|
||||
write(0x00, val);
|
||||
smbc->pick_paper = 1;
|
||||
write(0x00, val);
|
||||
// smbc->pick_paper = 0;
|
||||
// write(0x00, val);
|
||||
}
|
||||
|
||||
void MotorBoard::clear_error()
|
||||
{
|
||||
unsigned int val;
|
||||
SMBCONFIG *smbc = (SMBCONFIG *)(&val);
|
||||
read(0, val);
|
||||
smbc->error_clean = 1;
|
||||
write(0, val);
|
||||
smbc->error_clean = 0;
|
||||
write(0, val);
|
||||
}
|
||||
|
||||
bool MotorBoard::wait_paper_in(int timeout_ms)
|
||||
{
|
||||
return cv_paper_in.wait(timeout_ms);
|
||||
}
|
||||
|
||||
bool MotorBoard::wait_paper_out(int timeout_ms)
|
||||
{
|
||||
return cv_paper_out.wait(timeout_ms);
|
||||
}
|
||||
|
||||
bool MotorBoard::wait_error(int timeout_ms)
|
||||
{
|
||||
return cv_error.wait(timeout_ms);
|
||||
}
|
||||
|
||||
bool MotorBoard::wait_done(int timeout_ms)
|
||||
{
|
||||
return cv_scan_done.wait(timeout_ms);
|
||||
}
|
||||
|
||||
int MotorBoard::os_mode()
|
||||
{
|
||||
unsigned int val;
|
||||
read(0x02, val);
|
||||
SMB_MODE *smb_mode = (SMB_MODE *)&val;
|
||||
return smb_mode->scan_mode;
|
||||
}
|
||||
|
||||
bool MotorBoard::paper_ready()
|
||||
{
|
||||
unsigned int val;
|
||||
read(0x02, val);
|
||||
SMB_MODE *smb_mode = (SMB_MODE *)&val;
|
||||
return smb_mode->feeding_paper_ready;
|
||||
}
|
||||
|
||||
bool MotorBoard::is_scanning()
|
||||
{
|
||||
unsigned int val;
|
||||
read(0x02, val);
|
||||
SMB_MODE *smb_mode = (SMB_MODE *)&val;
|
||||
return smb_mode->work_status;
|
||||
}
|
||||
|
||||
int MotorBoard::paper_counter()
|
||||
{
|
||||
unsigned int val;
|
||||
read(0x02, val);
|
||||
SMBMODE *smb_mode = (SMBMODE *)&val;
|
||||
return smb_mode->scan_num;
|
||||
}
|
||||
|
||||
bool MotorBoard::set_paper_inspect_param(unsigned int value /* = 1000 */)
|
||||
{
|
||||
unsigned int val;
|
||||
if (!read(0x04, val))
|
||||
return false;
|
||||
SMBCONFIGEXT *smb_config_ext = (SMBCONFIGEXT *)&val;
|
||||
smb_config_ext->error_range_set = value;
|
||||
return write(0x04, val);
|
||||
}
|
||||
|
||||
bool MotorBoard::get_keeplastpaper(){
|
||||
return keep_last_paper;
|
||||
}
|
||||
|
||||
bool MotorBoard::set_paper_inpect_info(unsigned int value)
|
||||
{
|
||||
unsigned int val;
|
||||
if (!read(0x04, val))
|
||||
return false;
|
||||
SMBCONFIGEXT *smb_config_ext = (SMBCONFIGEXT *)&val;
|
||||
smb_config_ext->paper_infor = value;
|
||||
return write(0x04, val);
|
||||
}
|
||||
|
||||
bool MotorBoard::set_paper_inspect(bool enable /* = true */)
|
||||
{
|
||||
unsigned int val;
|
||||
if (!read(0x04, val))
|
||||
return false;
|
||||
SMBCONFIGEXT *smb_config_ext = (SMBCONFIGEXT *)&val;
|
||||
smb_config_ext->paper_size_check_en = enable;
|
||||
return write(0x04, val);
|
||||
}
|
||||
|
||||
bool MotorBoard::set_double_inpect(bool enable)
|
||||
{
|
||||
unsigned int val;
|
||||
if (!read(0x00, val))
|
||||
return false;
|
||||
SMBCONFIG *smb_config = (SMBCONFIG *)&val;
|
||||
smb_config->double_paper = enable;
|
||||
return write(0x00, val);
|
||||
}
|
||||
bool MotorBoard::get_doublle_inpect()
|
||||
{
|
||||
}
|
||||
|
||||
bool MotorBoard::set_auto_paper(bool enable){
|
||||
unsigned int val;
|
||||
if (!read(0x00, val))
|
||||
return false;
|
||||
SMBCONFIG *smb_config = (SMBCONFIG *)&val;
|
||||
smb_config->paper_auto_module = enable;
|
||||
return write(0x00, val);
|
||||
}
|
||||
|
||||
bool MotorBoard::set_staple_inpect(bool enable)
|
||||
{
|
||||
unsigned int val;
|
||||
if (!read(0x00, val))
|
||||
return false;
|
||||
SMBCONFIG *smb_config = (SMBCONFIG *)&val;
|
||||
smb_config->staple_enable = enable;
|
||||
return write(0x00, val);
|
||||
}
|
||||
|
||||
bool MotorBoard::get_staple_inpect()
|
||||
{
|
||||
}
|
||||
bool MotorBoard::set_color_mode(int mode)
|
||||
{
|
||||
unsigned int val;
|
||||
if (!read(0x00, val))
|
||||
return false;
|
||||
SMBCONFIG *smb_config = (SMBCONFIG *)&val;
|
||||
smb_config->color_mode = mode;
|
||||
return write(0x00, val);
|
||||
}
|
||||
int MotorBoard::get_color_mode()
|
||||
{
|
||||
}
|
||||
|
||||
bool MotorBoard::set_speed_mode(int mode)
|
||||
{
|
||||
unsigned int val;
|
||||
if (!read(0x00, val))
|
||||
return false;
|
||||
|
||||
SMBCONFIG *smb_config = (SMBCONFIG *)&val;
|
||||
smb_config->speed_set_enable = 1;
|
||||
smb_config->v_setting = mode;
|
||||
write(0x00, val);
|
||||
smb_config->speed_set_enable = 0;
|
||||
return write(0x00, val);
|
||||
}
|
||||
|
||||
int MotorBoard::get_speed_mode()
|
||||
{
|
||||
unsigned int val;
|
||||
if (!read(0x00, val))
|
||||
return -1;
|
||||
SMBCONFIG *smb_config = (SMBCONFIG *)&val;
|
||||
return smb_config->v_setting;
|
||||
}
|
||||
|
||||
bool MotorBoard::set_cuospeed(unsigned int speed)
|
||||
{
|
||||
unsigned int val;
|
||||
if (!read(0x04, val))
|
||||
return -1;
|
||||
SMB_CONFIG_EXT *smb_config = (SMB_CONFIG_EXT *)&val;
|
||||
smb_config->cuo_speed = speed;
|
||||
return write(0x04,val);
|
||||
|
||||
}
|
||||
|
||||
std::shared_ptr<IRegsAccess> MotorBoard::regs()
|
||||
{
|
||||
return m_regsAccess;
|
||||
}
|
||||
|
||||
static int pinindex=0;
|
||||
void MotorBoard::pin_call(unsigned int pinNum)
|
||||
{
|
||||
static int index = 0;
|
||||
utils::to_log(LOG_LEVEL_DEBUG, utils::format_string("pin %d", index++).c_str());
|
||||
int os_m = os_mode();
|
||||
if (m_os_mode != os_m)
|
||||
{
|
||||
m_os_mode = os_m;
|
||||
cv_os_mode.notify_all();
|
||||
if (m_glue.m_os_mode_call)
|
||||
m_glue.m_os_mode_call(m_os_mode);
|
||||
}
|
||||
|
||||
if (m_os_mode)
|
||||
{
|
||||
utils::to_log(LOG_LEVEL_DEBUG, "not scan mode");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int val;
|
||||
SMBSTATUS *smb_status = (SMBSTATUS *)&val;
|
||||
if (!read(0x01, val))
|
||||
utils::to_log(LOG_LEVEL_DEBUG, "read error");
|
||||
utils::to_log(LOG_LEVEL_DEBUG, utils::format_string("status %08x", val).c_str());
|
||||
//printf("\n reg 1 val =%d",val);
|
||||
if(val & 0x800){
|
||||
//printf("\n keep_last_paper ");
|
||||
keep_last_paper=true;
|
||||
}
|
||||
if(val & 0x1000)
|
||||
{
|
||||
if(m_glue.m_set_sleepmode_call)
|
||||
m_glue.m_set_sleepmode_call(val & 0xf000);
|
||||
}
|
||||
if(val & 0x80000)
|
||||
{
|
||||
if(m_glue.m_mltop_call)
|
||||
m_glue.m_mltop_call(val);
|
||||
}
|
||||
if(smb_status->paper_auto)
|
||||
{
|
||||
if(m_glue.m_auto_paper)
|
||||
m_glue.m_auto_paper(1);
|
||||
}
|
||||
if (val & 0xAFE)
|
||||
{
|
||||
cv_error.notify_all();
|
||||
if (m_glue.m_error_call)
|
||||
m_glue.m_error_call(val & 0x30efe); //0xefe index of 16:aquireimage error index of bit 17 :size check error
|
||||
|
||||
utils::to_log(LOG_LEVEL_DEBUG, "error");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!smb_status->scan_pulse)
|
||||
{
|
||||
cv_paper_in.notify_all();
|
||||
utils::to_log(LOG_LEVEL_DEBUG, "paper in");
|
||||
printf("\n paper pulse num = %d ", paperinnum++);
|
||||
}
|
||||
|
||||
if(smb_status->paper_left)
|
||||
{
|
||||
cv_paper_out.notify_all();
|
||||
utils::to_log(LOG_LEVEL_DEBUG, "paper left");
|
||||
}
|
||||
}
|
||||
|
||||
if (val & 0x400)
|
||||
{
|
||||
utils::to_log(LOG_LEVEL_DEBUG, "done");
|
||||
cv_scan_done.notify_all();
|
||||
if (m_glue.m_scan_done_call)
|
||||
m_glue.m_scan_done_call();
|
||||
}
|
||||
}
|
||||
|
||||
void MotorBoard::scansensor_call(unsigned int pinNum)
|
||||
{
|
||||
// static int indexscansensor=0;
|
||||
// m_uartEnable->setValue(Gpio::High);
|
||||
// utils::to_log(LOG_LEVEL_DEBUG, string_format(" gpio149 call times -%d ", indexscansensor++));
|
||||
// cv_paper_in.notify_all();
|
||||
// m_uartEnable->setValue(Gpio::Low);
|
||||
}
|
||||
bool MotorBoard::write(unsigned int addr, unsigned int val)
|
||||
{
|
||||
return m_regsAccess->write(addr, val);
|
||||
}
|
||||
|
||||
bool MotorBoard::read(unsigned int addr, unsigned int &val)
|
||||
{
|
||||
return m_regsAccess->read(addr, val);
|
||||
}
|
||||
|
||||
void MotorBoard::set_callbacks(MotorBoardGlue glue)
|
||||
{
|
||||
m_glue = glue;
|
||||
}
|
||||
|
||||
bool MotorBoard::set_screw_inpect(bool enable)
|
||||
{
|
||||
unsigned int val;
|
||||
if (!read(0x00, val))
|
||||
return false;
|
||||
SMBCONFIG *smb_config = (SMBCONFIG *)&val;
|
||||
smb_config->skew_enable = enable;
|
||||
return write(0x00, val);
|
||||
}
|
||||
bool MotorBoard::get_screw_inpect()
|
||||
{
|
||||
unsigned int val;
|
||||
read(0x00, val);
|
||||
SMBCONFIG *smb_mode = (SMBCONFIG *)&val;
|
||||
return smb_mode->skew_enable;
|
||||
}
|
||||
|
||||
bool MotorBoard::set_screw_level(int level)
|
||||
{
|
||||
unsigned int val;
|
||||
if (!read(0x00, val))
|
||||
return false;
|
||||
SMBCONFIG *smb_config = (SMBCONFIG *)&val;
|
||||
smb_config->skew_parameter = level;
|
||||
return write(0x00, val);
|
||||
}
|
||||
|
||||
bool MotorBoard::set_long_paper(bool enable)
|
||||
{
|
||||
unsigned int val;
|
||||
if (!read(0x00, val))
|
||||
return false;
|
||||
SMBCONFIG *smb_config = (SMBCONFIG *)&val;
|
||||
smb_config->paper = enable;
|
||||
return write(0x00, val);
|
||||
}
|
||||
|
||||
int MotorBoard::get_screw_level()
|
||||
{
|
||||
unsigned int val;
|
||||
auto ret= read(0x00, val);
|
||||
if(!ret)
|
||||
return -1;
|
||||
SMBCONFIG *smb_mode = (SMBCONFIG *)&val;
|
||||
return smb_mode->skew_parameter;
|
||||
}
|
||||
|
||||
bool MotorBoard::en_testbit(bool en)
|
||||
{
|
||||
unsigned int val;
|
||||
auto ret= read(0x00, val);
|
||||
if(!ret)
|
||||
return -1;
|
||||
SMBCONFIG *smb_mode = (SMBCONFIG *)&val;
|
||||
smb_mode->testbit = en?1:0;
|
||||
return write(0x00,val);
|
||||
}
|
||||
|
||||
void MotorBoard::release_statecontrol()
|
||||
{
|
||||
set_auto_paper(false);
|
||||
m_regsAccess.reset();
|
||||
m_intPinMonitor.reset();
|
||||
|
||||
}
|
||||
|
||||
void MotorBoard::init_statecontrol()
|
||||
{
|
||||
m_regsAccess.reset(new UartRegsAccess(devPort, bauds, 0x07, 0x87));
|
||||
m_intPinMonitor.reset(new PinMonitor(intport, std::bind(&MotorBoard::pin_call, this, std::placeholders::_1)));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
m_os_mode = os_mode();
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include "autoevent.hpp"
|
||||
|
||||
class IRegsAccess;
|
||||
class PinMonitor;
|
||||
class Gpio;
|
||||
class ICapturer;
|
||||
|
||||
typedef struct SMB_CONFIG
|
||||
{
|
||||
unsigned int enable : 1;
|
||||
unsigned int color_mode : 1;
|
||||
unsigned int paper : 1;
|
||||
unsigned int double_paper : 1;
|
||||
unsigned int staple_enable : 1; // 5
|
||||
unsigned int error_clean : 1;
|
||||
unsigned int status_init : 1;
|
||||
unsigned int pick_paper : 1;
|
||||
unsigned int skew_enable : 1;
|
||||
unsigned int skew_parameter : 3; // 7
|
||||
unsigned int key_staple_enable : 1;
|
||||
unsigned int iic_config_addr : 7;
|
||||
unsigned int iic_config : 1;
|
||||
unsigned int v_setting : 2; // 11
|
||||
unsigned int speed_set_enable : 1;
|
||||
unsigned int scan_busy_motor_stop : 1;
|
||||
unsigned int sleep_state : 1;
|
||||
unsigned int sleep_parameter : 3; // 6
|
||||
unsigned int _600dpi : 1;
|
||||
unsigned int paper_auto_module : 1; // 2
|
||||
unsigned int testbit : 1;
|
||||
} SMBCONFIG;
|
||||
|
||||
typedef struct SMB_STATUS
|
||||
{
|
||||
unsigned int scan_pulse : 1;
|
||||
unsigned int m1_paper_sin : 1;
|
||||
unsigned int open_machine : 1;
|
||||
unsigned int pick_failed : 1;
|
||||
unsigned int stop_jam : 1; // 5
|
||||
unsigned int double_paper : 1;
|
||||
unsigned int staple : 1;
|
||||
unsigned int papertilted : 1;
|
||||
unsigned int count_pulse : 1;
|
||||
unsigned int scan_mode_change : 1; // 5
|
||||
unsigned int motor_status : 1;
|
||||
unsigned int keep_last_paper : 1;
|
||||
unsigned int sleep_set : 1;
|
||||
unsigned int sleep_conf : 3;
|
||||
unsigned int dsp_get_paper_error : 1;
|
||||
unsigned int paper_check_result : 1;
|
||||
unsigned int top_wuzhi : 1;
|
||||
unsigned int ml_top_sin : 1; // 10
|
||||
unsigned int paper_auto : 1;
|
||||
unsigned int paper_left : 1;
|
||||
} SMBSTATUS;
|
||||
|
||||
typedef struct SMB_MODE
|
||||
{
|
||||
unsigned int scan_num : 14;
|
||||
unsigned int scan_mode : 2;
|
||||
unsigned int feeding_paper_ready : 1;
|
||||
unsigned int work_status : 1;
|
||||
} SMBMODE;
|
||||
|
||||
typedef struct SMB_CONFIG_EXT
|
||||
{
|
||||
unsigned int paper_infor : 5;
|
||||
unsigned int paper_size_check_en : 1;
|
||||
unsigned int error_range_set : 15;
|
||||
unsigned int cuo_speed : 7;
|
||||
} SMBCONFIGEXT;
|
||||
|
||||
struct MotorBoardGlue
|
||||
{
|
||||
MotorBoardGlue(const std::function<void(unsigned int)> error_call,
|
||||
const std::function<void()> scan_done_call,
|
||||
const std::function<void(unsigned int)> os_mode_call,
|
||||
const std::function<void(unsigned int)> set_sleepmode_call,
|
||||
const std::function<void(unsigned int)> mltop_call,
|
||||
std::function<void(unsigned int)> auto_paper)
|
||||
: m_error_call(error_call),
|
||||
m_scan_done_call(scan_done_call),
|
||||
m_os_mode_call(os_mode_call),
|
||||
m_set_sleepmode_call(set_sleepmode_call),
|
||||
m_mltop_call(mltop_call),
|
||||
m_auto_paper(auto_paper)
|
||||
{
|
||||
}
|
||||
|
||||
std::function<void(unsigned int)> m_error_call;
|
||||
std::function<void()> m_scan_done_call;
|
||||
std::function<void(unsigned int)> m_os_mode_call;
|
||||
std::function<void(unsigned int)> m_set_sleepmode_call;
|
||||
std::function<void(unsigned int)> m_mltop_call;
|
||||
std::function<void(unsigned int)> m_auto_paper;
|
||||
};
|
||||
|
||||
class MotorBoard
|
||||
{
|
||||
public:
|
||||
MotorBoard();
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
void clear_error();
|
||||
void pick_paper();
|
||||
int os_mode();
|
||||
bool paper_ready();
|
||||
bool is_scanning();
|
||||
int paper_counter();
|
||||
bool set_long_paper(bool enable);
|
||||
bool set_double_inpect(bool enable);
|
||||
bool get_doublle_inpect();
|
||||
bool set_staple_inpect(bool enable);
|
||||
bool set_auto_paper(bool enable);
|
||||
bool get_staple_inpect();
|
||||
bool set_color_mode(int mode);
|
||||
int get_color_mode();
|
||||
int get_speed_mode();
|
||||
bool set_speed_mode(int mode);
|
||||
bool set_screw_inpect(bool enable);
|
||||
bool get_screw_inpect();
|
||||
bool set_screw_level(int level);
|
||||
int get_screw_level();
|
||||
bool wait_paper_out(int timeout_ms);
|
||||
bool wait_paper_in(int timeout_ms);
|
||||
bool wait_error(int timeout_ms);
|
||||
bool wait_done(int timeout_ms);
|
||||
bool read(unsigned int addr, unsigned int &val);
|
||||
bool write(unsigned int addr, unsigned int val);
|
||||
bool set_paper_inspect_param(unsigned int value = 1000);
|
||||
bool set_paper_inpect_info(unsigned int value);
|
||||
bool set_paper_inspect(bool enable = true);
|
||||
bool set_cuospeed(unsigned int speed);
|
||||
void set_callbacks(MotorBoardGlue glue);
|
||||
bool get_keeplastpaper();
|
||||
bool en_testbit(bool en);
|
||||
std::shared_ptr<IRegsAccess> regs();
|
||||
void release_statecontrol();
|
||||
void init_statecontrol();
|
||||
private:
|
||||
void pin_call(unsigned int pinNum);
|
||||
void scansensor_call(unsigned int pinNum);
|
||||
const std::string devPort;
|
||||
const unsigned int bauds = 921600;
|
||||
const int readflag = 0x07;
|
||||
const int writeflag = 0x87;
|
||||
const unsigned int intport = 151;
|
||||
std::shared_ptr<IRegsAccess> m_regsAccess;
|
||||
std::shared_ptr<PinMonitor> m_intPinMonitor;
|
||||
std::shared_ptr<Gpio> m_uartEnable;
|
||||
AutoSemaphore cv_paper_out;
|
||||
AutoSemaphore cv_paper_in;
|
||||
AutoSemaphore cv_error;
|
||||
AutoSemaphore cv_scan_done;
|
||||
AutoSemaphore cv_os_mode;
|
||||
unsigned int m_os_mode;
|
||||
volatile bool keep_last_paper;
|
||||
MotorBoardGlue m_glue;
|
||||
bool b_paperin;
|
||||
};
|
|
@ -0,0 +1,129 @@
|
|||
#include "PinMonitor.h"
|
||||
|
||||
#include "DevUtil.h"
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <thread>
|
||||
#include <iostream>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <base/utils.h>
|
||||
|
||||
static const std::string loggername = "PinMonitor";
|
||||
PinMonitor::PinMonitor(unsigned int pinNum, std::function<void(int)> call_back)
|
||||
: pin(pinNum)
|
||||
{
|
||||
pin.setDirection(Gpio::in);
|
||||
pin.setEdge(Gpio::falling);
|
||||
this->call_back = call_back;
|
||||
thread_monitor = std::thread(&PinMonitor::monitor, this);
|
||||
//printf("PinMonitor threadid = %d \n",thread_monitor.get_id());
|
||||
// int priority=sched_get_priority_max(SCHED_FIFO);
|
||||
// if(priority==-1)
|
||||
// {
|
||||
// printf("sched_get_priority_max error \n");
|
||||
// }
|
||||
// thparm.sched_priority = priority;
|
||||
// if(pthread_setschedparam(thread_monitor.native_handle(),SCHED_FIFO,&thparm))
|
||||
// {
|
||||
// printf("failed to error set pthread_setschedparam \n");
|
||||
// }
|
||||
}
|
||||
|
||||
PinMonitor::~PinMonitor()
|
||||
{
|
||||
bMonitor = false;
|
||||
if (thread_monitor.joinable())
|
||||
thread_monitor.join();
|
||||
}
|
||||
|
||||
void PinMonitor::monitor()
|
||||
{
|
||||
pollfd pfd;
|
||||
int ret = 0;
|
||||
pfd.fd = -1;
|
||||
char buf[8];
|
||||
int num;
|
||||
chronograph sw;
|
||||
|
||||
pfd.fd = open(pin.getValuePath().c_str(), O_RDONLY);
|
||||
if (pfd.fd < 0)
|
||||
ret = -1;
|
||||
|
||||
pfd.events = POLLPRI;
|
||||
num = read(pfd.fd, buf, 8); // This is to clear the avaible read
|
||||
|
||||
while (bMonitor)
|
||||
{
|
||||
ret = poll(&pfd, 1, 1000);
|
||||
if (ret > 0)
|
||||
{
|
||||
if (pfd.revents & POLLPRI)
|
||||
{
|
||||
lseek(pfd.fd, 0, SEEK_SET);
|
||||
num = read(pfd.fd, buf, 8);
|
||||
|
||||
buf[num - 1] = '\0';
|
||||
ret = atoi(buf);
|
||||
//LOG_TRACE("poll call");
|
||||
if (call_back)
|
||||
{
|
||||
sw.reset();
|
||||
call_back(pin.getPort());
|
||||
utils::to_log(LOG_LEVEL_DEBUG, utils::format_string("poll call times = %.2f \n",sw.elapse_ms()).c_str());
|
||||
}
|
||||
|
||||
|
||||
sw.reset();
|
||||
while(sw.elapse_ms() < 10)
|
||||
{
|
||||
ret = poll(&pfd, 1, 1);
|
||||
if (ret > 0)
|
||||
{
|
||||
num = read(pfd.fd, buf, 8);
|
||||
buf[num - 1] = '\0';
|
||||
ret = atoi(buf);
|
||||
//printf("pMonitor nread = %d ret val = %d \n",num,ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close(pfd.fd);
|
||||
|
||||
// int n;
|
||||
// int epfd = epoll_create(1);
|
||||
// int fd = open(pin.getValuePath().c_str(), O_RDONLY);
|
||||
// char buf[8];
|
||||
// //printf("open returned %d: %s\n", fd, strerror(errno));
|
||||
// if (fd > 0)
|
||||
// {
|
||||
// struct epoll_event ev;
|
||||
// struct epoll_event events;
|
||||
// ev.events = EPOLLPRI;
|
||||
// ev.data.fd = fd;
|
||||
|
||||
// n = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev);
|
||||
|
||||
// while (bMonitor)
|
||||
// {
|
||||
// n = epoll_wait(epfd, &events, 1, 1000);
|
||||
|
||||
// if (n > 0)
|
||||
// {
|
||||
// n = lseek(fd, 0, SEEK_SET);
|
||||
// n = read(fd, buf, 8);
|
||||
|
||||
// buf[n - 1] = '\0';
|
||||
// auto ret = atoi(buf);
|
||||
// if (call_back)
|
||||
// call_back(pin.getPort());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// close(fd);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
#include "Gpio.h"
|
||||
#include <thread>
|
||||
#include <functional>
|
||||
|
||||
class PinMonitor
|
||||
{
|
||||
public:
|
||||
PinMonitor(unsigned int pinNum, std::function<void(int)> call_back);
|
||||
~PinMonitor();
|
||||
|
||||
private:
|
||||
void monitor();
|
||||
//sched_param thparm;
|
||||
Gpio pin;
|
||||
std::function<void(unsigned int)> call_back;
|
||||
std::thread thread_monitor;
|
||||
volatile bool bMonitor = true;
|
||||
};
|
|
@ -4,7 +4,7 @@ target("hardware")
|
|||
set_kind("static")
|
||||
add_syslinks("pthread", "dl")
|
||||
add_includedirs("../sdk")
|
||||
add_files("*.cpp", "./cis/*.cpp", "./uart/*.cpp", "../sdk/base/*.c*", "../sdk/json/*.c*", "../sdk/sane_opt_json/*.c*")
|
||||
add_files("*.cpp", "./cis/*.cpp", "./uart/*.cpp", "./motor/*.cpp", "../sdk/base/*.c*", "../sdk/json/*.c*", "../sdk/sane_opt_json/*.c*")
|
||||
--add_deps("gusb", "applog")
|
||||
--add_rules("utils.bin2c",{linewidth = 32,extension = {".bin"}})
|
||||
--add_files("table.bin")
|
||||
|
|
|
@ -221,7 +221,8 @@ dyn_mem_ptr async_usb_gadget::handle_ctrl_message(dyn_mem_ptr data)
|
|||
reply = handle_ctrl_setup(data);
|
||||
break;
|
||||
case FUNCTIONFS_BIND:
|
||||
utils::to_log(LOG_LEVEL_ALL, "EP0 FFS BIND\n");
|
||||
// utils::to_log(LOG_LEVEL_ALL, "EP0 FFS BIND\n");
|
||||
utils::log_mem_info("EP0 FFS BIND:", pev, sizeof(*pev), LOG_LEVEL_DEBUG);
|
||||
break;
|
||||
case FUNCTIONFS_UNBIND:
|
||||
utils::to_log(LOG_LEVEL_ALL, "EP0 FFS UNBIND\n");
|
||||
|
|
Loading…
Reference in New Issue