From bb3ef5fc9a1cc202d5bd28e5f0afc4c0d66fc01f Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Wed, 20 Dec 2023 15:23:24 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=A1=AC=E4=BB=B6=EF=BC=88?= =?UTF-8?q?=E9=95=9C=E5=A4=B4=E5=92=8C=E7=94=B5=E6=9C=BA=E9=83=A8=E5=88=86?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hardware/cis/FpgaComm.cpp | 44 ++ hardware/cis/FpgaComm.h | 33 +- hardware/cis/gvideo.cpp | 451 +++++++++++++++++ hardware/cis/gvideo.h | 52 ++ hardware/cis/gvideoisp1.cpp | 895 ++++++++++++++++++++++++++++++++++ hardware/cis/gvideoisp1.h | 24 + hardware/hardware.cpp | 20 +- hardware/hardware.h | 80 +-- hardware/motor/autoevent.hpp | 70 +++ hardware/motor/motorboard.cpp | 427 ++++++++++++++++ hardware/motor/motorboard.h | 166 +++++++ hardware/uart/PinMonitor.cpp | 129 +++++ hardware/uart/PinMonitor.h | 19 + hardware/xmake.lua | 2 +- usb/usb_io.cpp | 3 +- 15 files changed, 2366 insertions(+), 49 deletions(-) create mode 100644 hardware/cis/gvideo.cpp create mode 100644 hardware/cis/gvideo.h create mode 100644 hardware/cis/gvideoisp1.cpp create mode 100644 hardware/cis/gvideoisp1.h create mode 100644 hardware/motor/autoevent.hpp create mode 100644 hardware/motor/motorboard.cpp create mode 100644 hardware/motor/motorboard.h create mode 100644 hardware/uart/PinMonitor.cpp create mode 100644 hardware/uart/PinMonitor.h diff --git a/hardware/cis/FpgaComm.cpp b/hardware/cis/FpgaComm.cpp index b61dde2..6548e02 100644 --- a/hardware/cis/FpgaComm.cpp +++ b/hardware/cis/FpgaComm.cpp @@ -6,6 +6,8 @@ #include #include "../uart/uartregsaccess.h" #include +#include "../uart/Gpio.h" +#include #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) { diff --git a/hardware/cis/FpgaComm.h b/hardware/cis/FpgaComm.h index 90fed95..9012a2f 100644 --- a/hardware/cis/FpgaComm.h +++ b/hardware/cis/FpgaComm.h @@ -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 status_; // status reader - port 69 + std::unique_ptr reload_; // codes reload - port 70 + std::unique_ptr cfg_; // configuration reload - port 71 + std::unique_ptr reset_; // circuit reset - port Fpga_Reset + + public: + controller(); + ~controller(); + + public: + void reset(void); + void reload(void); + }; + std::unique_ptr 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); diff --git a/hardware/cis/gvideo.cpp b/hardware/cis/gvideo.cpp new file mode 100644 index 0000000..2e67da1 --- /dev/null +++ b/hardware/cis/gvideo.cpp @@ -0,0 +1,451 @@ +#include "gvideo.h" +#include +#include /* low-level i/o */ +#include +#include +#include +#include +#include +#include +#include "linux/v4l2-subdev.h" + +#include +#include +#include + +#include + +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 lck(m_lock); + if (bStart) + return; + + start_capturing(); + bStart = true; +} + +void gVideo::stop() { + std::lock_guard 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())); +} \ No newline at end of file diff --git a/hardware/cis/gvideo.h b/hardware/cis/gvideo.h new file mode 100644 index 0000000..7b633f2 --- /dev/null +++ b/hardware/cis/gvideo.h @@ -0,0 +1,52 @@ +#pragma once +#include +#include +#include + +#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 buffers; + unsigned int n_buffers; + std::mutex m_lock; + volatile bool bStart; +}; diff --git a/hardware/cis/gvideoisp1.cpp b/hardware/cis/gvideoisp1.cpp new file mode 100644 index 0000000..bdf18f8 --- /dev/null +++ b/hardware/cis/gvideoisp1.cpp @@ -0,0 +1,895 @@ +#include "gvideoisp1.h" +#include /* low-level i/o */ +#include +#include +#include +#include +#include "linux/videodev2.h" +#include "linux/v4l2-subdev.h" +#include +#include "string.h" +#include +#include + +#include + + +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(); + //-------------------------------------------------------------// +} \ No newline at end of file diff --git a/hardware/cis/gvideoisp1.h b/hardware/cis/gvideoisp1.h new file mode 100644 index 0000000..133df41 --- /dev/null +++ b/hardware/cis/gvideoisp1.h @@ -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"; +}; \ No newline at end of file diff --git a/hardware/hardware.cpp b/hardware/hardware.cpp index 6e4f16d..5732f75 100644 --- a/hardware/hardware.cpp +++ b/hardware/hardware.cpp @@ -1,13 +1,15 @@ #include "hardware.h" #include "./cis/FpgaComm.h" +#include "./cis/gvideoisp1.h" +#include "./motor/motorboard.h" #include #include ///////////////////////////////////////////////////////////////////////////////////////////////////////// // scanner_hw static std::string device_opt_json[] = { - "{\"mode\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u989c\\u8272\\u6a21\\u5f0f\",\"desc\":\"\\u9009\\u62e9\\u8272\\u5f69\\u6a21\\u5f0f\",\"type\":\"string\",\"fix-id\":34819,\"ui-pos\":10,\"auth\":0,\"size\":12,\"cur\":\"\\u5f69\\u8272\",\"default\":\"\\u5f69\\u8272\",\"range\":[\"\\u5f69\\u8272\",\"\\u7070\\u5ea6\"]},\"resolution\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u5206\\u8fa8\\u7387\",\"desc\":\"\\u8bbe\\u7f6e\\u626b\\u63cf\\u56fe\\u50cf\\u7684\\u5206\\u8fa8\\u7387\",\"type\":\"int\",\"fix-id\":34840,\"ui-pos\":11,\"auth\":0,\"size\":4,\"cur\":300,\"default\":300,\"range\":[200,300]},\"is-wait-scan\":{\"cat\":\"base\",\"group\":\"feeder\",\"title\":\"\\u5f85\\u7eb8\\u626b\\u63cf\",\"desc\":\"\\u542f\\u7528\\u540e\\uff0c\\u6587\\u7a3f\\u653e\\u5165\\u626b\\u63cf\\u4eea\\u65f6\\u5c06\\u81ea\\u52a8\\u542f\\u52a8\\u626b\\u63cf\",\"type\":\"bool\",\"fix-id\":34873,\"ui-pos\":12,\"auth\":0,\"size\":4,\"cur\":false,\"default\":false},\"wait-scan-exit\":{\"cat\":\"base\",\"group\":\"feeder\",\"title\":\"\\u5f85\\u7eb8\\u626b\\u63cf\\u9000\\u51fa\\u65f6\\u95f4\",\"desc\":\"\\u8bbe\\u7f6e\\u7ed3\\u675f\\u5f85\\u7eb8\\u626b\\u63cf\\u7684\\u65f6\\u95f4\",\"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\",\"title\":\"\\u6ce2\\u7279\\u7387\",\"desc\":\"CIS\\u63a7\\u5236\\u901a\\u4fe1\\u901f\\u7387\",\"type\":\"int\",\"ui-pos\":20,\"auth\":0,\"size\":4,\"cur\":921600,\"default\":921600,\"range\":[110,300,600,1200,2400,4800,9600,19200,38400,57600,115200,500000,921600,1500000]},\"act-after\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u5ef6\\u8fdf\\u54cd\\u5e94\",\"desc\":\"\\u91c7\\u96c6\\u5934\\u63a5\\u53d7\\u547d\\u4ee4\\u540e\\u7684\\u52a8\\u4f5c\\u5ef6\\u8fdf\\u65f6\\u95f4\",\"type\":\"int\",\"ui-pos\":21,\"auth\":0,\"unit\":\"microsec\",\"size\":4,\"cur\":1000,\"default\":1000},\"fram-h\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u5e27\\u9ad8\\u5ea6\",\"desc\":\"\\u91c7\\u96c6\\u5934\\u6bcf\\u4e00\\u5e27\\u7684\\u91c7\\u96c6\\u9ad8\\u5ea6\",\"type\":\"int\",\"ui-pos\":22,\"auth\":0,\"size\":4,\"cur\":12,\"default\":12},\"sample\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u91c7\\u6837\\u9891\\u7387\",\"desc\":\"\\u91c7\\u6837\\u9891\\u7387\",\"type\":\"int\",\"ui-pos\":23,\"auth\":0,\"size\":4,\"cur\":256,\"default\":256},\"expo-fb\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u66dd\\u5149\\u5ea6\\uff08\\u6b63\\u9762\\u84dd\\u8272\\u901a\\u9053\\uff09\",\"desc\":\"\\u6b63\\u9762\\u84dd\\u8272\\u901a\\u9053\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"ui-pos\":30,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"expo-fg\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u66dd\\u5149\\u5ea6\\uff08\\u6b63\\u9762\\u7eff\\u8272\\u901a\\u9053\\uff09\",\"desc\":\"\\u6b63\\u9762\\u7eff\\u8272\\u901a\\u9053\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"ui-pos\":31,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"expo-fr\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u66dd\\u5149\\u5ea6\\uff08\\u6b63\\u9762\\u7ea2\\u8272\\u901a\\u9053\\uff09\",\"desc\":\"\\u6b63\\u9762\\u7ea2\\u8272\\u901a\\u9053\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"ui-pos\":32,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"expo-bb\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u66dd\\u5149\\u5ea6\\uff08\\u80cc\\u9762\\u84dd\\u8272\\u901a\\u9053\\uff09\",\"desc\":\"\\u80cc\\u9762\\u84dd\\u8272\\u901a\\u9053\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"ui-pos\":33,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"expo-bg\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u66dd\\u5149\\u5ea6\\uff08\\u80cc\\u9762\\u7eff\\u8272\\u901a\\u9053\\uff09\",\"desc\":\"\\u80cc\\u9762\\u7eff\\u8272\\u901a\\u9053\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"ui-pos\":34,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"expo-br\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u66dd\\u5149\\u5ea6\\uff08\\u80cc\\u9762\\u7ea2\\u8272\\u901a\\u9053\\uff09\",\"desc\":\"\\u80cc\\u9762\\u7ea2\\u8272\\u901a\\u9053\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"ui-pos\":35,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"gain-f\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u589e\\u76ca\\uff08\\u6b63\\u9762\\uff09\",\"desc\":\"\\u6b63\\u9762\\u7684\\u589e\\u76ca\\u91cf\",\"type\":\"int\",\"ui-pos\":40,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"gain-b\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u589e\\u76ca\\uff08\\u80cc\\u9762\\uff09\",\"desc\":\"\\u80cc\\u9762\\u7684\\u589e\\u76ca\\u91cf\",\"type\":\"int\",\"ui-pos\":41,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"off-f\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u504f\\u79fb\\uff08\\u6b63\\u9762\\uff09\",\"desc\":\"\\u6b63\\u9762\\u7684\\u504f\\u79fb\\u91cf\",\"type\":\"int\",\"ui-pos\":45,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":0,\"max\":100,\"step\":1}},\"off-b\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u504f\\u79fb\\uff08\\u80cc\\u9762\\uff09\",\"desc\":\"\\u80cc\\u9762\\u7684\\u504f\\u79fb\\u91cf\",\"type\":\"int\",\"ui-pos\":46,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":0,\"max\":100,\"step\":1}}}" + "{\"mode\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u989c\\u8272\\u6a21\\u5f0f\",\"desc\":\"\\u9009\\u62e9\\u8272\\u5f69\\u6a21\\u5f0f\",\"type\":\"string\",\"fix-id\":34819,\"ui-pos\":10,\"auth\":0,\"size\":12,\"cur\":\"\\u5f69\\u8272\",\"default\":\"\\u5f69\\u8272\",\"range\":[\"\\u5f69\\u8272\",\"\\u7070\\u5ea6\"]},\"resolution\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u5206\\u8fa8\\u7387\",\"desc\":\"\\u8bbe\\u7f6e\\u626b\\u63cf\\u56fe\\u50cf\\u7684\\u5206\\u8fa8\\u7387\",\"type\":\"int\",\"fix-id\":34840,\"ui-pos\":11,\"auth\":0,\"size\":4,\"cur\":300,\"default\":300,\"range\":[200,300]},\"is-wait-scan\":{\"cat\":\"base\",\"group\":\"feeder\",\"title\":\"\\u5f85\\u7eb8\\u626b\\u63cf\",\"desc\":\"\\u542f\\u7528\\u540e\\uff0c\\u6587\\u7a3f\\u653e\\u5165\\u626b\\u63cf\\u4eea\\u65f6\\u5c06\\u81ea\\u52a8\\u542f\\u52a8\\u626b\\u63cf\",\"type\":\"bool\",\"fix-id\":34873,\"ui-pos\":12,\"auth\":0,\"size\":4,\"cur\":false,\"default\":false},\"wait-scan-exit\":{\"cat\":\"base\",\"group\":\"feeder\",\"title\":\"\\u5f85\\u7eb8\\u626b\\u63cf\\u9000\\u51fa\\u65f6\\u95f4\",\"desc\":\"\\u8bbe\\u7f6e\\u7ed3\\u675f\\u5f85\\u7eb8\\u626b\\u63cf\\u7684\\u65f6\\u95f4\",\"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\",\"title\":\"\\u6ce2\\u7279\\u7387\",\"desc\":\"CIS\\u63a7\\u5236\\u901a\\u4fe1\\u901f\\u7387\",\"type\":\"int\",\"ui-pos\":20,\"auth\":0,\"size\":4,\"cur\":921600,\"default\":921600,\"range\":[110,300,600,1200,2400,4800,9600,19200,38400,57600,115200,500000,921600,1500000]},\"act-after\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u5ef6\\u8fdf\\u54cd\\u5e94\",\"desc\":\"\\u91c7\\u96c6\\u5934\\u63a5\\u53d7\\u547d\\u4ee4\\u540e\\u7684\\u52a8\\u4f5c\\u5ef6\\u8fdf\\u65f6\\u95f4\",\"type\":\"int\",\"ui-pos\":21,\"auth\":0,\"unit\":\"microsec\",\"size\":4,\"cur\":1000,\"default\":1000},\"fram-h\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u5e27\\u9ad8\\u5ea6\",\"desc\":\"\\u91c7\\u96c6\\u5934\\u6bcf\\u4e00\\u5e27\\u7684\\u91c7\\u96c6\\u9ad8\\u5ea6\",\"type\":\"int\",\"ui-pos\":22,\"auth\":0,\"size\":4,\"cur\":12,\"default\":12},\"sample\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u91c7\\u6837\\u9891\\u7387\",\"desc\":\"\\u91c7\\u6837\\u9891\\u7387\",\"type\":\"int\",\"ui-pos\":23,\"auth\":0,\"size\":4,\"cur\":256,\"default\":256},\"expo-fb\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u66dd\\u5149\\u5ea6\\uff08\\u6b63\\u9762\\u84dd\\u8272\\u901a\\u9053\\uff09\",\"desc\":\"\\u6b63\\u9762\\u84dd\\u8272\\u901a\\u9053\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"ui-pos\":32,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"expo-fg\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u66dd\\u5149\\u5ea6\\uff08\\u6b63\\u9762\\u7eff\\u8272\\u901a\\u9053\\uff09\",\"desc\":\"\\u6b63\\u9762\\u7eff\\u8272\\u901a\\u9053\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"ui-pos\":31,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"expo-fr\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u66dd\\u5149\\u5ea6\\uff08\\u6b63\\u9762\\u7ea2\\u8272\\u901a\\u9053\\uff09\",\"desc\":\"\\u6b63\\u9762\\u7ea2\\u8272\\u901a\\u9053\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"ui-pos\":30,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"expo-bb\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u66dd\\u5149\\u5ea6\\uff08\\u80cc\\u9762\\u84dd\\u8272\\u901a\\u9053\\uff09\",\"desc\":\"\\u80cc\\u9762\\u84dd\\u8272\\u901a\\u9053\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"ui-pos\":35,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"expo-bg\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u66dd\\u5149\\u5ea6\\uff08\\u80cc\\u9762\\u7eff\\u8272\\u901a\\u9053\\uff09\",\"desc\":\"\\u80cc\\u9762\\u7eff\\u8272\\u901a\\u9053\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"ui-pos\":34,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"expo-br\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u66dd\\u5149\\u5ea6\\uff08\\u80cc\\u9762\\u7ea2\\u8272\\u901a\\u9053\\uff09\",\"desc\":\"\\u80cc\\u9762\\u7ea2\\u8272\\u901a\\u9053\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"ui-pos\":33,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"gain-f\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u589e\\u76ca\\uff08\\u6b63\\u9762\\uff09\",\"desc\":\"\\u6b63\\u9762\\u7684\\u589e\\u76ca\\u91cf\",\"type\":\"int\",\"ui-pos\":40,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"gain-b\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u589e\\u76ca\\uff08\\u80cc\\u9762\\uff09\",\"desc\":\"\\u80cc\\u9762\\u7684\\u589e\\u76ca\\u91cf\",\"type\":\"int\",\"ui-pos\":41,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"off-f\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u589e\\u76ca\\u8865\\u507f\\uff08\\u6b63\\u9762\\uff09\",\"desc\":\"\\u6b63\\u9762\\u7684\\u589e\\u76ca\\u8865\\u507f\\u91cf\",\"type\":\"int\",\"ui-pos\":45,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-100,\"max\":100,\"step\":1}},\"off-b\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u589e\\u76ca\\u8865\\u507f\\uff08\\u80cc\\u9762\\uff09\",\"desc\":\"\\u80cc\\u9762\\u7684\\u589e\\u76ca\\u8865\\u507f\\u91cf\",\"type\":\"int\",\"ui-pos\":46,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-100,\"max\":100,\"step\":1}}}" }; @@ -194,24 +196,32 @@ int scanner_hw::open(std::function image_handler) (img_controller_.get()->*exposure[i * SIDE_COUNT + j])(exposure_[i][j]); } - for(int i = 0; i < CIS_SECTOR_COUNT; ++i) + for(int i = 0; i < FpgaComm::CIS_SECTOR_COUNT; ++i) img_controller_->setAGain(i, gain_[SIDE_FRONT]); - for(int i = 0; i < CIS_SECTOR_COUNT; ++i) + for(int i = 0; i < FpgaComm::CIS_SECTOR_COUNT; ++i) img_controller_->setBGain(i, gain_[SIDE_BACK]); - for(int i = 0; i < CIS_SECTOR_COUNT; ++i) + for(int i = 0; i < FpgaComm::CIS_SECTOR_COUNT; ++i) img_controller_->setAOffset(i, off_[SIDE_FRONT]); - for(int i = 0; i < CIS_SECTOR_COUNT; ++i) + for(int i = 0; i < FpgaComm::CIS_SECTOR_COUNT; ++i) img_controller_->setBOffset(i, off_[SIDE_BACK]); + camera_.reset(new GVideoISP1()); + + motor_.reset(new MotorBoard()); + return 0; } int scanner_hw::start_scan(void) { + camera_->start(); + return 0; } int scanner_hw::stop_scan(void) { + camera_->stop(); + return 0; } int scanner_hw::close(void) diff --git a/hardware/hardware.h b/hardware/hardware.h index a579ab0..4a3ba7c 100644 --- a/hardware/hardware.h +++ b/hardware/hardware.h @@ -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 img_controller_; + std::unique_ptr camera_; + std::unique_ptr 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 // } diff --git a/hardware/motor/autoevent.hpp b/hardware/motor/autoevent.hpp new file mode 100644 index 0000000..0b5e932 --- /dev/null +++ b/hardware/motor/autoevent.hpp @@ -0,0 +1,70 @@ +#pragma once +#include +#include + +class AutoSemaphore +{ +public: + AutoSemaphore() + { + } + + virtual ~AutoSemaphore() + { + notify_all(); + } + + virtual void notify_all() + { + std::lock_guard lck(mutx); + cv.notify_all(); + } + + virtual bool wait(int timeout_ms) + { + std::unique_lock 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 lck(mutx); + bNotify = true; + cv.notify_all(); + } + + virtual bool wait(int timeout_ms) + { + std::unique_lock 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; +}; \ No newline at end of file diff --git a/hardware/motor/motorboard.cpp b/hardware/motor/motorboard.cpp new file mode 100644 index 0000000..3fc74bf --- /dev/null +++ b/hardware/motor/motorboard.cpp @@ -0,0 +1,427 @@ +#include "motorboard.h" + +#include +#include "../uart/PinMonitor.h" +#include "../uart/uartregsaccess.h" +#include + +#include + + +#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 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(); +} \ No newline at end of file diff --git a/hardware/motor/motorboard.h b/hardware/motor/motorboard.h new file mode 100644 index 0000000..fe47edf --- /dev/null +++ b/hardware/motor/motorboard.h @@ -0,0 +1,166 @@ +#pragma once +#include +#include +#include +#include +#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 error_call, + const std::function scan_done_call, + const std::function os_mode_call, + const std::function set_sleepmode_call, + const std::function mltop_call, + std::function 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 m_error_call; + std::function m_scan_done_call; + std::function m_os_mode_call; + std::function m_set_sleepmode_call; + std::function m_mltop_call; + std::function 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 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 m_regsAccess; + std::shared_ptr m_intPinMonitor; + std::shared_ptr 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; +}; \ No newline at end of file diff --git a/hardware/uart/PinMonitor.cpp b/hardware/uart/PinMonitor.cpp new file mode 100644 index 0000000..f20dcf8 --- /dev/null +++ b/hardware/uart/PinMonitor.cpp @@ -0,0 +1,129 @@ +#include "PinMonitor.h" + +#include "DevUtil.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static const std::string loggername = "PinMonitor"; +PinMonitor::PinMonitor(unsigned int pinNum, std::function 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); +} \ No newline at end of file diff --git a/hardware/uart/PinMonitor.h b/hardware/uart/PinMonitor.h new file mode 100644 index 0000000..5032c71 --- /dev/null +++ b/hardware/uart/PinMonitor.h @@ -0,0 +1,19 @@ +#pragma once +#include "Gpio.h" +#include +#include + +class PinMonitor +{ +public: + PinMonitor(unsigned int pinNum, std::function call_back); + ~PinMonitor(); + +private: + void monitor(); + //sched_param thparm; + Gpio pin; + std::function call_back; + std::thread thread_monitor; + volatile bool bMonitor = true; +}; \ No newline at end of file diff --git a/hardware/xmake.lua b/hardware/xmake.lua index 56256f5..cd011cc 100644 --- a/hardware/xmake.lua +++ b/hardware/xmake.lua @@ -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") diff --git a/usb/usb_io.cpp b/usb/usb_io.cpp index 637f177..9689068 100644 --- a/usb/usb_io.cpp +++ b/usb/usb_io.cpp @@ -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");