2023-07-17 first

This commit is contained in:
modehua 2023-07-16 20:29:37 -07:00
parent c563054e16
commit cd5d017147
127 changed files with 44840 additions and 0 deletions

105
BlockingQueue.h Normal file
View File

@ -0,0 +1,105 @@
#pragma once
#include <mutex>
#include <condition_variable>
#include <deque>
#include <iostream>
#include <exception>
template <typename T>
class BlockingQueue
{
private:
BlockingQueue(const BlockingQueue &rhs);
BlockingQueue &operator=(const BlockingQueue &rhs);
mutable std::mutex _mutex;
std::condition_variable _condvar;
std::deque<T> _queue;
bool isShutDown = false;
T tRet;
public:
BlockingQueue()
: _mutex(), _condvar(), _queue()
{
}
~BlockingQueue()
{
ShutDown();
}
void ShutDown()
{
isShutDown = true;
_condvar.notify_all();
_queue.clear();
}
bool IsShutDown()
{
return isShutDown;
}
//β²å
void Put(const T task)
{
std::lock_guard<std::mutex> lock(_mutex);
if (!isShutDown)
{
{
_queue.push_back(task);
}
_condvar.notify_all();
}
}
//Í·È¡
T Take()
{
std::unique_lock<std::mutex> lock(_mutex);
if (_queue.size() <= 0)
_condvar.wait(lock);
if (isShutDown || _queue.empty())
{
return tRet;
}
T front(_queue.front());
_queue.pop_front();
return front;
}
T Front()
{
std::unique_lock<std::mutex> lock(_mutex);
if (_queue.size() <= 0)
_condvar.wait(lock);
if (isShutDown || _queue.empty())
{
return tRet;
}
T front(_queue.front());
return front;
}
size_t Size() const
{
std::lock_guard<std::mutex> lock(_mutex);
return _queue.size();
}
void Clear()
{
std::unique_lock<std::mutex> lock(_mutex);
if (_queue.size() <= 0)
return;
if (_queue.size()>0)
{
_queue.clear();
}
}
};

140
CImageMerge.cpp Normal file
View File

@ -0,0 +1,140 @@
// #include "CImageMerge.h"
// #include <sstream>
// CImageMerge::CImageMerge()
// {
// }
// CImageMerge::~CImageMerge()
// {
// }
// cv::Mat CImageMerge::MergeImage(cv::Mat &srcMat, int dstwidth, int dstheight,int mode)
// {
// cv::Mat dst(srcMat.rows, srcMat.cols / (mode == 0 ? 1:3), CV_8UC(mode == 0 ? 1 : 3));
// auto graymerge = [](cv::Mat& src,cv::Mat dst)->cv::Mat{
// int width_block = src.cols / 12;
// int heigh_block = src.rows;
// // 20 vsp 拼接算法
// // src(cv::Rect(width_block,0,width_block*2,heigh_block)).copyTo(dst(cv::Rect(0,0,width_block*2,heigh_block)));
// // src(cv::Rect(0,0,width_block,heigh_block)).copyTo(dst(cv::Rect(width_block*2,0,width_block,heigh_block)));
// // src(cv::Rect(width_block*3,0,width_block*2,heigh_block)).copyTo(dst(cv::Rect(width_block*4,0,width_block*2,heigh_block)));
// // src(cv::Rect(width_block*5,0,width_block,heigh_block)).copyTo(dst(cv::Rect(width_block*3,0,width_block,heigh_block)));
// // src(cv::Rect(width_block*7,0,width_block*2,heigh_block)).copyTo(dst(cv::Rect(width_block*6,0,width_block*2,heigh_block)));
// // src(cv::Rect(width_block*6,0,width_block,heigh_block)).copyTo(dst(cv::Rect(width_block*8,0,width_block,heigh_block)));
// // src(cv::Rect(width_block*9,0,width_block*2,heigh_block)).copyTo(dst(cv::Rect(width_block*10,0,width_block*2,heigh_block)));
// // src(cv::Rect(width_block*11,0,width_block,heigh_block)).copyTo(dst(cv::Rect(width_block*9,0,width_block,heigh_block)));
// //return dst;
// // 45 vsp 拼接算法
// src(cv::Rect(0,0,width_block*2,heigh_block)).copyTo(dst(cv::Rect(width_block,0,width_block*2,heigh_block)));
// src(cv::Rect(width_block*2,0,width_block,heigh_block)).copyTo(dst(cv::Rect(0,0,width_block,heigh_block)));
// src(cv::Rect(width_block*3,0,width_block,heigh_block)).copyTo(dst(cv::Rect(width_block*5,0,width_block,heigh_block)));
// src(cv::Rect(width_block*4,0,width_block*2,heigh_block)).copyTo(dst(cv::Rect(width_block*3,0,width_block*2,heigh_block)));
// src(cv::Rect(width_block*6,0,width_block*2,heigh_block)).copyTo(dst(cv::Rect(width_block*7,0,width_block*2,heigh_block)));
// src(cv::Rect(width_block*8,0,width_block,heigh_block)).copyTo(dst(cv::Rect(width_block*6,0,width_block,heigh_block)));
// src(cv::Rect(width_block*9,0,width_block,heigh_block)).copyTo(dst(cv::Rect(width_block*11,0,width_block,heigh_block)));
// src(cv::Rect(width_block*10,0,width_block*2,heigh_block)).copyTo(dst(cv::Rect(width_block*9,0,width_block*2,heigh_block)));
// return dst;
// };
// //cv::imwrite("org.jpg",srcMat);
// if (!srcMat.empty())
// {
// if(mode == 0)//灰度模式
// return graymerge(srcMat,dst);
// std::vector<cv::Mat> ch_mats;
// int blockcnt = 12;
// int spitWidth = srcMat.cols / blockcnt;
// cv::Mat retMat(srcMat.rows, srcMat.cols / 3, CV_8UC3);
// for (int i = 0; i < 4; i++)
// {
// if (i < 2)
// {
// ch_mats.push_back(srcMat(cv::Rect(spitWidth * (i * 3 + 1), 0, spitWidth, srcMat.rows)));
// ch_mats.push_back(srcMat(cv::Rect(spitWidth * (i * 3 + 2), 0, spitWidth, srcMat.rows)));
// ch_mats.push_back(srcMat(cv::Rect(spitWidth * (i * 3 + 0), 0, spitWidth, srcMat.rows)));
// }
// else
// {
// ch_mats.push_back(srcMat(cv::Rect(spitWidth * (i * 3 + 1), 0, spitWidth, srcMat.rows)));
// ch_mats.push_back(srcMat(cv::Rect(spitWidth * (i * 3 + 0), 0, spitWidth, srcMat.rows)));
// ch_mats.push_back(srcMat(cv::Rect(spitWidth * (i * 3 + 2), 0, spitWidth, srcMat.rows)));
// }
// cv::merge(ch_mats, retMat(cv::Rect(spitWidth * i, 0, spitWidth, srcMat.rows)));
// ch_mats.clear();
// }
// return graymerge(retMat,dst);
// }
// return srcMat;
// }
// cv::Mat CImageMerge::MergeImage(bool iscolor, cv::Mat &srcMat, int dstwidth, int dstheight)
// {
// int blockcnt = 12;
// int spitWidth = srcMat.cols / blockcnt;
// int abortwidth; // = spitWidth == 3888 ? 432 : (spitWidth == 2592 ? 216 : 144);
// if (!iscolor) // 灰度
// {
// abortwidth = spitWidth == 1296 ? 432 : (spitWidth == 648 ? 216 : 144);
// }
// else
// {
// abortwidth = spitWidth == 3888 ? 432 : (spitWidth == 1944 ? 216 : 144);
// }
// cv::Mat dst(dstheight, dstwidth - abortwidth * 2, CV_8UC(iscolor ? 3 : 1));
// if (!iscolor)
// {
// for (int i = 0; i < 2; i++)
// {
// srcMat(cv::Rect((dstwidth / 2 + abortwidth) * i, 0, dstwidth / 2 - abortwidth, dstheight)).copyTo(dst(cv::Rect(dst.cols / 2 * i, 0, dst.cols / 2, dstheight)));
// }
// srcMat.release();
// return dst;
// }
// else
// {
// std::vector<cv::Mat> m_splits;
// std::vector<int> m_index = {1, 4, 7, 10, 2, 5, 6, 9, 0, 3, 8, 11};
// for (int i = 0; i < 3; i++)
// {
// int startindex = i == 0 ? 0 : (i == 1 ? 4 : 8);
// cv::Mat t_mat(dstheight, dstwidth - abortwidth * 2, CV_8UC1);
// srcMat(cv::Rect(spitWidth * m_index[startindex + 0], 0, spitWidth, dstheight)).copyTo(t_mat(cv::Rect(0, 0, spitWidth, dstheight)));
// srcMat(cv::Rect(spitWidth * m_index[startindex + 1], 0, spitWidth - abortwidth, dstheight)).copyTo(t_mat(cv::Rect(spitWidth, 0, spitWidth - abortwidth, dstheight)));
// srcMat(cv::Rect(spitWidth * m_index[startindex + 2] + abortwidth, 0, spitWidth - abortwidth, dstheight)).copyTo(t_mat(cv::Rect(spitWidth * 2 - abortwidth, 0, spitWidth - abortwidth, dstheight)));
// srcMat(cv::Rect(spitWidth * m_index[startindex + 3], 0, spitWidth, dstheight)).copyTo(t_mat(cv::Rect(spitWidth * 3 - abortwidth * 2, 0, spitWidth, dstheight)));
// m_splits.push_back(t_mat);
// }
// cv::merge(m_splits, dst);
// m_splits.clear();
// }
// srcMat.release();
// return dst;
// }
// cv::Mat CImageMerge::MergeFrames(std::vector<cv::Mat> frames, int type, int dpi)
// {
// if (frames.empty())
// return cv::Mat();
// int size = frames.size();
// auto it = frames.begin();
// int dstH = it->rows * size;
// int abortwidth = dpi == 0x02 || dpi == 0x01 ? 432 : 864; // 216*2 432*2
// int dstwidth = dpi == 0x02 || dpi == 0x01 ? 7344 : 14688;
// cv::Mat matdst(dstH, dstwidth, CV_8UC(type == 1 ? 3 : 1));
// for (int i = 0; i < size; i++)
// {
// auto itemimg = frames[i];
// itemimg = MergeImage(type, itemimg, dstwidth + abortwidth, itemimg.rows);
// itemimg.copyTo(matdst(cv::Rect(0, itemimg.rows * i, itemimg.cols, itemimg.rows)));
// itemimg.release();
// }
// return matdst;
// }

15
CImageMerge.h Normal file
View File

@ -0,0 +1,15 @@
// #pragma once
// #include <opencv2/opencv.hpp>
// class CImageMerge
// {
// private:
// /* data */
// public:
// CImageMerge(/* args */);
// ~CImageMerge();
// public:
// cv::Mat MergeImage(cv::Mat& srcMat,int dstwidth,int dstheight,int mode);
// cv::Mat MergeImage(bool iscolor,cv::Mat& srcMat,int dstwidth,int dstheight);
// cv::Mat MergeFrames(std::vector<cv::Mat> frames, int type, int dpi);
// };

79
CMakeLists.txt Normal file
View File

@ -0,0 +1,79 @@
cmake_minimum_required(VERSION 3.0.0)
project(scanservice)
add_compile_options(-std=c++14)
#set (CMAKE_GENERATOR "/home/holdtecs/zzm-linux/rk3288-linux/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++")
#
# set(CMAKE_SYSTEM_NAME Linux)
# set(CMAKE_SYSTEM_PROCESSOR arm)
#roofs
#set(linux_sdk_path /home/holdtecs/zzm-linux/rk3288-linux)
#set(linux_sdk_path /mnt/disk2/linux-rhx/rk3288-linux)
#set(CMAKE_SYSROOT ${linux_sdk_path}/buildroot/output/rockchip_rk3288/host/arm-buildroot-linux-gnueabihf/sysroot)
# set(CMAKE_STAGING_PREFIX ${PROJECT_SOURCE_DIR}/install)
#
#set(tools ${linux_sdk_path}/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf)
# set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
# set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
# set(CMAKE_LIBRARY_ARCHITECTURE arm)
set(-mfloat-abi=hard)
# set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
# set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
# set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(OpenCV_DIR /home/modehua/sdk/sysroots/cortexa9t2hf-neon-xilinx-linux-gnueabi/usr/include/opencv4/)
#set(OpenCV_DIR /home/holdtecs/zzm-linux/fs/usr/lib)
#find_package( OpenCV 3 REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
FILE(GLOB SRC "*.cpp" "*.h" "*.c")
FILE(GLOB IMAGEPRO "imageprocess/*.h" "imageprocess/*.cpp" )
FILE(GLOB FPGA "fpga/*.h" "fpga/*.cpp" )
# message(STATUS "SRC:" ${SRC})
# message(STATUS "IMAGEPRO:" ${IMAGEPRO})
#message(STATUS "FPGA:" ${FPGA})
set(CMAKE_BUILD_TYPE "Release")
include_directories(
fpga
imageprocess
imageprocess/include
#/home/modehua/sdk/sysroots/cortexa9t2hf-neon-xilinx-linux-gnueabi/usr/include/opencv4/
)
add_executable(${PROJECT_NAME} ${SRC})
#
SET(-CMAKE_BUILD_TYPE "Release")
install(TARGETS ${PROJECT_NAME} DESTINATION bin)
add_custom_command(TARGET ${PROJECT_NAME}
POST_BUILD
COMMAND $ENV{STRIP} -s ${PROJECT_NAME})
set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS_RELEASE "-s")
#target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS} pthread)
message(/home/modehua/sdk/scanservices/scanservices/fpga/bin/libfpgaupdate.a)
target_link_libraries(${PROJECT_NAME} /home/modehua/sdk/scanservices/scanservices/fpga/bin/libfpgaupdate.a)
#target_link_libraries(${PROJECT_NAME} opencv_core opencv_highgui opencv_imgproc opencv_imgcodecs turbojpeg pthread )
target_link_libraries(${PROJECT_NAME} pthread )
target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR}
${PROJECT_SOURCE_DIR}/fpga
${PROJECT_SOURCE_DIR}/imageprocess
${PROJECT_SOURCE_DIR}/imageprocess/include
${PROJECT_SOURCE_DIR}/home/modehua/sdk/sysroots/cortexa9t2hf-neon-xilinx-linux-gnueabi/usr/include/opencv4/
)

292
CSizedetect.cpp Normal file
View File

@ -0,0 +1,292 @@
// #include "CSizedetect.h"
// #include <opencv2/opencv.hpp>
// #include "ImageProcess_Public.h"
// #include "opencv2/imgproc/types_c.h"
// #include "opencv2/imgproc/imgproc_c.h"
// void threshold_Mat(const cv::Mat& src, cv::Mat& dst, double thre)
// {
// if (src.channels() == 3)
// {
// #ifdef USE_ONENCL
// if (cl_res.context)
// transforColor_threshold_opencl(src, dst, static_cast<uchar>(thre));
// else
// #endif
// {
// cv::Mat gray = hg::transforColor(src);
// cv::threshold(gray, dst, thre, 255, cv::THRESH_BINARY);
// gray.release();
// }
// }
// else
// cv::threshold(src, dst, thre, 255, cv::THRESH_BINARY);
// }
// void findContours(const cv::Mat& src, std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& hierarchy, int retr, int method, cv::Point offset)
// {
// #if CV_VERSION_REVISION == 6
// CvMat c_image = src;
// #else
// CvMat c_image;
// c_image = cvMat(src.rows, src.cols, src.type(), src.data);
// c_image.step = src.step[0];
// c_image.type = (c_image.type & ~cv::Mat::CONTINUOUS_FLAG) | (src.flags & cv::Mat::CONTINUOUS_FLAG);
// #endif
// cv::MemStorage storage(cvCreateMemStorage());
// CvSeq* _ccontours = nullptr;
// #if CV_VERSION_REVISION == 6
// cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, CvPoint(offset));
// #else
// cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, CvPoint{ offset.x, offset.y });
// #endif
// if (!_ccontours)
// {
// contours.clear();
// return;
// }
// cv::Seq<CvSeq*> all_contours(cvTreeToNodeSeq(_ccontours, sizeof(CvSeq), storage));
// size_t total = all_contours.size();
// contours.resize(total);
// cv::SeqIterator<CvSeq*> it = all_contours.begin();
// for (size_t i = 0; i < total; i++, ++it)
// {
// CvSeq* c = *it;
// reinterpret_cast<CvContour*>(c)->color = static_cast<int>(i);
// int count = c->total;
// int* data = new int[static_cast<size_t>(count * 2)];
// cvCvtSeqToArray(c, data);
// for (int j = 0; j < count; j++)
// {
// contours[i].push_back(cv::Point(data[j * 2], data[j * 2 + 1]));
// }
// delete[] data;
// }
// hierarchy.resize(total);
// it = all_contours.begin();
// for (size_t i = 0; i < total; i++, ++it)
// {
// CvSeq* c = *it;
// int h_next = c->h_next ? reinterpret_cast<CvContour*>(c->h_next)->color : -1;
// int h_prev = c->h_prev ? reinterpret_cast<CvContour*>(c->h_prev)->color : -1;
// int v_next = c->v_next ? reinterpret_cast<CvContour*>(c->v_next)->color : -1;
// int v_prev = c->v_prev ? reinterpret_cast<CvContour*>(c->v_prev)->color : -1;
// hierarchy[i] = cv::Vec4i(h_next, h_prev, v_next, v_prev);
// }
// storage.release();
// }
// std::vector<cv::Point> getMaxContour(const std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i>& hierarchy)
// {
// std::vector<cv::Point> maxContour;
// if (contours.size() < 1) return {};
// for (size_t i = 0, length = hierarchy.size(); i < length; i++)
// if (hierarchy[i][3] == -1)
// for (const auto& item : contours[i])
// maxContour.push_back(item);
// return maxContour;
// }
// cv::RotatedRect getBoundingRect(const std::vector<cv::Point>& contour)
// {
// if (contour.empty()) return {};
// cv::RotatedRect rect = minAreaRect(contour);
// if (rect.angle < -45)
// {
// rect.angle += 90;
// float temp = rect.size.width;
// rect.size.width = rect.size.height;
// rect.size.height = temp;
// }
// if (rect.angle > 45)
// {
// rect.angle -= 90;
// float temp = rect.size.width;
// rect.size.width = rect.size.height;
// rect.size.height = temp;
// }
// return rect;
// }
// CSizedetect::CSizedetect(int papaertype,int dpi) : m_papertype(papaertype),
// m_horThre(70),
// m_verThre(100),
// m_dpi(dpi)
// {
// }
// CSizedetect::~CSizedetect(void) {}
// void CSizedetect::SetPapertype(int papertype) {
// m_papertype=papertype;
// }
// static int x=0;
// int CSizedetect::preprocess(cv::Mat &mat, void *unused)
// {
// if(!mat.empty())
// {
// float width, height;
// cv::Mat thre;
// hg::threshold_Mat(mat, thre, 40);
// cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(8, 1));
// cv::morphologyEx(thre, thre, cv::MORPH_OPEN, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar::all(0));
// std::vector<std::vector<cv::Point>> contours;
// std::vector<cv::Vec4i> hierarchy;
// hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL);
// std::vector<cv::Point> maxContour = hg::getMaxContour(contours, hierarchy);
// cv::RotatedRect rect = hg::getBoundingRect(maxContour);
// width = rect.size.width;
// height = rect.size.height;
// //fastMeasureSize(mat.data,mat.cols,mat.rows,mat.channels(),width,height,40,20,5);
// HGSize dstSize;
// if(m_supportPaper.count((PaperSize)m_papertype)>0)//包含设置的幅面
// {
// dstSize=m_supportPaper[(PaperSize)m_papertype];
// if(m_dpi==0x02||m_dpi==0x03)
// {
// float ratio = m_dpi==0x02? 1.5f : 3.0f;
// dstSize.width*=ratio;
// dstSize.height*=ratio;
// }
// LOG("mat_width =%.2f ,mat_height = %.2f std_width = %df std_height=%df m_dpi = %d \n",width,height,dstSize.width,dstSize.height,m_dpi);
// if((width>(dstSize.width+m_horThre))||(width<(dstSize.width-m_horThre))||(height > (dstSize.height+m_verThre))||(height < (dstSize.height-m_verThre)))
// {
// return 1;
// }
// }
// }
// return 0;
// }
// void CSizedetect::rotate(float &x, float &y, float angle)
// {
// float a = x * cos(angle) - y * sin(angle);
// float b = x * sin(angle) + y * cos(angle);
// x = a;
// y = b;
// }
// void CSizedetect::minAeaRect(const float *x, const float *y, int size, float &width, float &height)
// {
// float area = width * height;
// // rotate 0~90 degree
// for (int i = 0; i < 91; ++i)
// {
// float tmpx = x[0], tmpy = y[0];
// rotate(tmpx, tmpy, i);
// float xl = tmpx, xr = tmpx, yt = tmpy, yb = tmpy;
// // traverse all points
// for (int j = 1; j < size; ++j)
// {
// tmpx = x[j];
// tmpy = y[j];
// rotate(tmpx, tmpy, i);
// if (tmpx < xl)
// xl = tmpx;
// if (tmpx > xr)
// xr = tmpx;
// if (tmpy < yb)
// yb = tmpy;
// if (tmpy > yt)
// yt = tmpy;
// }
// float xx = xr - xl, yy = yt - yb;
// if (area > xx * yy)
// {
// area = xx * yy;
// height = xx;
// width = yy;
// }
// }
// //
// if (height < width)
// {
// float tmp = height;
// height = width;
// width = tmp;
// }
// }
// void CSizedetect::fastMeasureSize(const unsigned char *data, int src_width, int src_height, int channels, float &dst_width, float &dst_height, int threshold, int indent, int step)
// {
// int bytesPerLine = src_width * channels;
// int indent_x = indent * channels;
// int indent_y = indent;
// int step_x = step * channels;
// int step_y = step;
// int total_count = (bytesPerLine + src_height) * 2 / indent;
// if (total_count < 1)
// return;
// float *points_x = new float[total_count];
// float *points_y = new float[total_count];
// int points_count = 0;
// //top
// int rows = src_height / 2;
// for (int x = 0; x < bytesPerLine; x += indent_x)
// for (int y = 0; y < rows; y += step_y)
// if (data[y * bytesPerLine + x] > threshold)
// {
// points_x[points_count] = x / channels;
// points_y[points_count] = y;
// points_count++;
// break;
// }
// //bottom
// for (int x = 0; x < bytesPerLine; x += indent_x)
// for (int y = src_height - 1; y >= rows; y -= step_y)
// if (data[y * bytesPerLine + x] > threshold)
// {
// points_x[points_count] = x / channels;
// points_y[points_count] = y;
// points_count++;
// break;
// }
// //left
// int cols = bytesPerLine / 2;
// for (int y = 0; y < src_height; y += indent)
// for (int x = 0; x < cols; x += step_x)
// if (data[y * bytesPerLine + x] > threshold)
// {
// points_x[points_count] = x / channels;
// points_y[points_count] = y;
// points_count++;
// break;
// }
// //right
// for (int y = 0; y < src_height; y += indent)
// for (int x = bytesPerLine - 1; x >= cols; x -= step_x)
// if (data[y * bytesPerLine + x] > threshold)
// {
// points_x[points_count] = x / channels;
// points_y[points_count] = y;
// points_count++;
// break;
// }
// if (points_count > 3)
// {
// dst_width = src_width;
// dst_height = src_height;
// minAeaRect(points_x, points_y, points_count, dst_width, dst_height);
// }
// delete[] points_x;
// delete[] points_y;
// }

42
CSizedetect.h Normal file
View File

@ -0,0 +1,42 @@
// #pragma once
// #include "IPreproc.h"
// #include <map>
// #include "scanservices_utils.h"
// class CSizedetect : public IPreproc
// {
// public:
// explicit CSizedetect(int papaertype,int dpi);
// virtual ~CSizedetect(void);
// virtual int preprocess(cv::Mat& mat,void* unused);
// void SetPapertype(int papertype);
// private:
// void rotate(float& x, float& y, float angle);
// void minAeaRect(const float* x, const float* y, int size, float& width, float& height);
// void fastMeasureSize(const unsigned char* data, int src_width, int src_height, int channels, float& dst_width, float& dst_height, int threshold = 40, int indent = 20, int step = 5);
// private:
// int m_papertype;
// int m_horThre;
// int m_verThre;
// int m_dpi;
// std::map<PaperSize,HGSize> m_supportPaper={
// {PaperSize::G400_A3,HGSize{2338,3307}},
// {PaperSize::G400_A4,HGSize{1653,2338}},
// {PaperSize::G400_A4R,HGSize{2338,1653}},
// {PaperSize::G400_A5,HGSize{1165,1653}},
// {PaperSize::G400_A5R,HGSize{1653,1165}},
// {PaperSize::G400_A6,HGSize{826,1165}},
// {PaperSize::G400_A6R,HGSize{1165,826}},
// {PaperSize::G400_B4,HGSize{1969,2780}},
// {PaperSize::G400_B5,HGSize{1385,1968}},
// {PaperSize::G400_B5R,HGSize{1968,1385}},
// {PaperSize::G400_B6R,HGSize{1433,1007}},
// {PaperSize::G400_B6,HGSize{1007,1433}},
// {PaperSize::G400_DOUBLELETTER,HGSize{2200,3401}},
// {PaperSize::G400_LEGAL,HGSize{1700,2800}},
// {PaperSize::G400_LETTER,HGSize{1700,2198}},
// {PaperSize::G400_LETTERR,HGSize{2198,1700}},
// {PaperSize::G400_LONGLETTER,HGSize{2040,2640}},
// {PaperSize::G400_MAXSIZE,HGSize{2338,6614}}
// };
// };

41
CameraParam.h Normal file
View File

@ -0,0 +1,41 @@
#pragma once
#include <sstream>
//#define LIGHT_DIFF(maxthre, x) ((maxthre)-x)
#define LIGHT_DIFF(x) (200 - x)
#define BLACK_DIFF(x) (8.0 - x)
#define FMT_STEP(x) \
do \
{ \
if (x < 1 && x > 0) \
{ \
x = 1; \
} \
if (step < 0 && step > -1) \
{ \
x = -1; \
} \
} while (0)
struct FPGAConfigParam
{
unsigned int ExposureF[3]; //RGB
unsigned int GainF[6]; //123456
unsigned int OffsetF[6]; //123456
unsigned int ExposureB[3]; //RGB
unsigned int GainB[6]; //123456
unsigned int OffsetB[6]; //123456
unsigned int DpiMode;
unsigned int ColorMode;
unsigned int MaxBright;
unsigned int MaxExp;
unsigned int Sp;
unsigned int HRatio;
unsigned int VRatio;
std::string LutPath;
std::string TextLutPath;
std::string Flat_BwPath;
std::string Flat_WhitePath;
};

2
CapComdef.h Normal file
View File

@ -0,0 +1,2 @@
#pragma once
#include <memory>

403
CorrectParam.cpp Normal file
View File

@ -0,0 +1,403 @@
#include "CorrectParam.h"
#include <iostream>
#include <fstream>
#include <sys/stat.h>
#include <sstream>
#include <iomanip>
using namespace std;
#define JSONPATH "/usr/local/huago/cameraparam.json"
#define TEXTLUT200COLORPATH "/usr/local/huago/Textlut200clr.bmp"
#define LUT200COLORPATH "/usr/local/huago/lut200clr.bmp"
#define LUT200_COLOR_BLACKPATH "/usr/local/huago/lut200clrbw.bmp"
#define LUT200_COLOR_WHITEPATH "/usr/local/huago/lut200clrwhite.bmp"
#define TEXTLUT200GRAYPATH "/usr/local/huago/Textlut200gray.bmp"
#define LUT200GRAYPATH "/usr/local/huago/lut200gray.bmp"
#define LUT200_GRAY_BLACKPATH "/usr/local/huago/lut200graybw.bmp"
#define LUT200_GRAY_WHITEPATH "/usr/local/huago/lut200graywhite.bmp"
#define TEXTLUT300COLORPATH "/usr/local/huago/Textlut300clr.bmp"
#define LUT300COLORPATH "/usr/local/huago/lut300clr.bmp"
#define LUT300_COLOR_BLACKPATH "/usr/local/huago/lut300clrbw.bmp"
#define LUT300_COLOR_WHITEPATH "/usr/local/huago/lut300clrwhite.bmp"
#define TEXTLUT300GRAYPATH "/usr/local/huago/Textlut300gray.bmp"
#define LUT300GRAYPATH "/usr/local/huago/lut300gray.bmp"
#define LUT300_GRAY_BLACKPATH "/usr/local/huago/lut300graybw.bmp"
#define LUT300_GRAY_WHITEPATH "/usr/local/huago/lut300graywhite.bmp"
#define LUT600COLORPATH "/usr/local/huago/lut600clr.bmp"
#define TEXTLUT600COLORPATH "/usr/local/huago/Textlut600clr.bmp"
#define LUT600_COLOR_BLACKPATH "/usr/local/huago/lut600clrbw.bmp"
#define LUT600_COLOR_WHITEPATH "/usr/local/huago/lut600clrwhite.bmp"
#define LUT600GRAYPATH "/usr/local/huago/lut600gray.bmp"
#define TEXTLUT600GRAYPATH "/usr/local/huago/Textlut600gray.bmp"
#define LUT600_GRAY_BLACKPATH "/usr/local/huago/lut600graybw.bmp"
#define LUT600_GRAY_WHITEPATH "/usr/local/huago/lut600graywhite.bmp"
CorrectParam::CorrectParam()
{
initdefaultpapram();
}
CorrectParam::~CorrectParam()
{
}
std::vector<FPGAConfigParam> CorrectParam::GetCorrectParams()
{
struct stat buff;
if (stat(JSONPATH, &buff) != 0)//不存在
{
initdefaultpapram();
}
std::lock_guard<std::mutex> lc(m_lc);
std::ifstream i(JSONPATH);
json j;
i >> j;
std::vector<FPGAConfigParam> vct_param;
for (json::iterator it = j.begin(); it != j.end(); ++it)
{
auto tmv = it.value();
FPGAConfigParam param;
from_json(tmv, param);
vct_param.push_back(param);
}
return vct_param;
}
FPGAConfigParam CorrectParam::GetFpgaparam(int dpi,int mode)
{
FPGAConfigParam param;
auto filejson = GetCorrectParams();
for (size_t i = 0; i < filejson.size(); i++)
{
if ((filejson[i].ColorMode == mode) &&
(filejson[i].DpiMode == dpi))
{
param = filejson[i];
break;
}
}
return param;
}
void CorrectParam::SaveCorrectParam(FPGAConfigParam& parms)
{
auto filejson = GetCorrectParams();
for (size_t i = 0; i < filejson.size(); i++)
{
if ((filejson[i].ColorMode == parms.ColorMode) &&
(filejson[i].DpiMode == parms.DpiMode))
{
memcpy(filejson[i].ExposureB, parms.ExposureB, sizeof(parms.ExposureB));
memcpy(filejson[i].ExposureF, parms.ExposureF, sizeof(parms.ExposureF));
memcpy(filejson[i].GainB, parms.GainB, sizeof(parms.GainB));
memcpy(filejson[i].GainF, parms.GainF, sizeof(parms.GainF));
memcpy(filejson[i].OffsetB, parms.OffsetB, sizeof(parms.OffsetB));
memcpy(filejson[i].OffsetF, parms.OffsetF, sizeof(parms.OffsetF));
filejson[i].LutPath = parms.LutPath;
filejson[i].TextLutPath = parms.TextLutPath;
filejson[i].Flat_BwPath = parms.Flat_BwPath;
filejson[i].Flat_WhitePath = parms.Flat_WhitePath;
filejson[i].Sp = parms.Sp;
filejson[i].HRatio = parms.HRatio;
filejson[i].VRatio = parms.VRatio;
break;
}
}
json j = json::array();
for (size_t i = 0; i < filejson.size(); i++)
{
json t_j;
to_json(t_j, filejson[i]);
j.push_back(t_j);
}
std::lock_guard<std::mutex> lc(m_lc);
ofstream ofs(JSONPATH);
ofs << std::setw(4) << j << std::endl;
}
void CorrectParam::initdefaultpapram()
{
struct stat buff;
if (stat(JSONPATH, &buff) != 0)//不存在
{
json js = json::array();
{
FPGAConfigParam param;
json t_j;
//彩色 300 dpi
param.ColorMode = 1;//彩色
param.DpiMode = 2;//300 dpi
param.MaxBright = 200;
param.MaxExp = 1470;
param.Sp = 1490;
param.HRatio = 1065353216;
param.VRatio = 1065353216;
param.LutPath = LUT300COLORPATH;
param.TextLutPath = TEXTLUT300COLORPATH;
param.Flat_BwPath = LUT300_COLOR_BLACKPATH;
param.Flat_WhitePath = LUT300_COLOR_WHITEPATH;
for (size_t i = 0; i < 6; i++)
{
if(i<3)
param.ExposureB[i] = param.ExposureF[i] = 650;//1500
param.GainF[i] = param.GainB[i] = 170;
param.OffsetF[i] = param.OffsetB[i] = 125;
}
to_json(t_j, param);
js.push_back(t_j);
//灰度 300 dpi
param.ColorMode = 0;//灰度
param.MaxBright = 200;
param.MaxExp = 1780;
param.Sp = 4470;
param.LutPath = LUT300GRAYPATH;
param.TextLutPath = TEXTLUT300GRAYPATH;
param.Flat_BwPath = LUT300_GRAY_BLACKPATH;
param.Flat_WhitePath = LUT300_GRAY_WHITEPATH;
to_json(t_j, param);
js.push_back(t_j);
//彩色 200 dpi
param.ColorMode = 1;//彩色
param.DpiMode = 1;//200 dpi
param.LutPath = LUT200COLORPATH;
param.TextLutPath = TEXTLUT200COLORPATH;
param.Flat_BwPath = LUT200_COLOR_BLACKPATH;
param.Flat_WhitePath = LUT200_COLOR_WHITEPATH;
for (size_t i = 0; i < 6; i++)
{
if(i<3)
param.ExposureB[i] = param.ExposureF[i] =600;//1500
param.GainF[i] = param.GainB[i] = 170;
param.OffsetF[i] = param.OffsetB[i] = 125;
}
to_json(t_j, param);
js.push_back(t_j);
//灰度 200dpi
param.ColorMode = 0;//灰度
param.LutPath = LUT200GRAYPATH;
param.TextLutPath = TEXTLUT200GRAYPATH;
param.Flat_BwPath = LUT200_GRAY_BLACKPATH;
param.Flat_WhitePath = LUT200_GRAY_WHITEPATH;
to_json(t_j, param);
js.push_back(t_j);
//彩色 600 dpi
param.ColorMode = 1;//彩色
param.DpiMode = 0x03;//200 dpi
param.MaxBright = 180;
param.MaxExp = 2680;
param.Sp = 2700;
param.LutPath = LUT600COLORPATH;
param.TextLutPath = TEXTLUT600COLORPATH;
param.Flat_BwPath = LUT600_COLOR_BLACKPATH;
param.Flat_WhitePath = LUT600_COLOR_WHITEPATH;
for (size_t i = 0; i < 6; i++)
{
if(i<3)
param.ExposureB[i] = param.ExposureF[i] = 0x800;//1500
param.GainF[i] = param.GainB[i] = 170;
param.OffsetF[i] = param.OffsetB[i] = 125;
}
to_json(t_j, param);
js.push_back(t_j);
//灰度 600dpi
param.ColorMode = 0;//灰度
param.DpiMode = 0x03;//600 dpi
param.MaxBright = 180;
param.MaxExp = 2680;
param.Sp = 8135;
param.LutPath = LUT600GRAYPATH;
param.TextLutPath = TEXTLUT600GRAYPATH;
param.Flat_BwPath = LUT600_GRAY_BLACKPATH;
param.Flat_WhitePath = LUT600_GRAY_WHITEPATH;
to_json(t_j, param);
js.push_back(t_j);
std::ofstream ofs(JSONPATH);
ofs << std::setw(4) << js << std::endl;
}
}
}
void CorrectParam::to_json(json& j, FPGAConfigParam& param)
{
j = json{ {"ExposureF",param.ExposureF},
{"GainF",param.GainF},
{"OffsetF",param.OffsetF},
{"ExposureB",param.ExposureB},
{"GainB",param.GainB},
{"OffsetB",param.OffsetB},
{"DpiMode",param.DpiMode},
{"ColorMode",param.ColorMode},
{"MaxBright",param.MaxBright},
{"MaxExp",param.MaxExp},
{"Sp",param.Sp},
{"HRatio",param.HRatio},
{"VRatio",param.VRatio},
{"LutPath",param.LutPath},
{"TextLutPath",param.TextLutPath},
{"FlatBlackPath",param.Flat_BwPath},
{"FlatWhitePath",param.Flat_WhitePath}
};
}
void CorrectParam::from_json(json& j, FPGAConfigParam& param)
{
if(j.contains("ExposureF"))
j.at("ExposureF").get_to(param.ExposureF);
else
param.ExposureF[0]=param.ExposureF[1]=param.ExposureF[2]=0x258;
if(j.contains("GainF"))
j.at("GainF").get_to(param.GainF);
else
{
for(int i = 0;i< sizeof(param.GainF)/sizeof(param.GainF[0]);i++)
{
param.GainF[i] = 170;
}
}
if(j.contains("OffsetF"))
j.at("OffsetF").get_to(param.OffsetF);
else
{
for(int i = 0;i< sizeof(param.OffsetF)/sizeof(param.OffsetF[0]);i++)
{
param.OffsetF[i] = 125;
}
}
if(j.contains("ExposureB"))
j.at("ExposureB").get_to(param.ExposureB);
else
param.ExposureB[0]=param.ExposureB[1]=param.ExposureB[2]=0x258;
if(j.contains("GainB"))
j.at("GainB").get_to(param.GainB);
else
{
for(int i = 0;i< sizeof(param.GainB)/sizeof(param.GainB[0]);i++)
{
param.GainB[i] = 170;
}
}
if(j.contains("OffsetB"))
j.at("OffsetB").get_to(param.OffsetB);
else
{
for(int i = 0;i< sizeof(param.OffsetB)/sizeof(param.OffsetB[0]);i++)
{
param.OffsetB[i] = 125;
}
}
if(j.contains("DpiMode"))
j.at("DpiMode").get_to(param.DpiMode);
else
param.DpiMode = 1;
if(j.contains("ColorMode"))
j.at("ColorMode").get_to(param.ColorMode);
else
param.ColorMode = 1;
if(j.contains("MaxBright"))
j.at("MaxBright").get_to(param.MaxBright);
else
param.MaxBright = 200;
if(j.contains("MaxExp"))
j.at("MaxExp").get_to(param.MaxExp);
else
param.MaxExp = 0x258;
if(j.contains("Sp"))
j.at("Sp").get_to(param.Sp);
else
param.Sp = 0x640;
if(j.contains("HRatio"))
j.at("HRatio").get_to(param.HRatio);
else
param.HRatio = 1065353216;
if(j.contains("VRatio"))
j.at("VRatio").get_to(param.VRatio);
else
param.VRatio = 1065353216;
if(j.contains("LutPath"))
j.at("LutPath").get_to(param.LutPath);
else
{
if(param.DpiMode==1)
param.LutPath = param.ColorMode == 1 ? LUT200COLORPATH:LUT200GRAYPATH;
else if(param.DpiMode==2 )
param.LutPath = param.ColorMode == 1 ? LUT300COLORPATH:LUT300GRAYPATH;
else if(param.DpiMode==3)
param.LutPath = param.ColorMode == 1 ? LUT600COLORPATH:LUT600GRAYPATH;
else
param.LutPath = "";//未知dpi
}
if(j.contains("TextLutPath"))
j.at("TextLutPath").get_to(param.TextLutPath);
else
{
if(param.DpiMode==1)
param.TextLutPath = param.ColorMode == 1 ? TEXTLUT200COLORPATH:TEXTLUT200GRAYPATH;
else if(param.DpiMode==2 )
param.TextLutPath = param.ColorMode == 1 ? TEXTLUT300COLORPATH:TEXTLUT300GRAYPATH;
else if(param.DpiMode==3)
param.TextLutPath = param.ColorMode == 1 ? TEXTLUT600COLORPATH:TEXTLUT600GRAYPATH;
else
param.TextLutPath = "";//未知dpi
}
if(j.contains("FlatBlackPath"))
j.at("FlatBlackPath").get_to(param.Flat_BwPath);
else
{
if(param.DpiMode==1)
param.Flat_BwPath = param.ColorMode == 1 ? LUT200_COLOR_BLACKPATH:LUT200_GRAY_BLACKPATH;
else if(param.DpiMode==2 )
param.Flat_BwPath = param.ColorMode == 1 ? LUT300_COLOR_BLACKPATH:LUT300_GRAY_BLACKPATH;
else if(param.DpiMode==3)
param.Flat_BwPath = param.ColorMode == 1 ? LUT600_COLOR_BLACKPATH:LUT600_GRAY_BLACKPATH;
else
param.Flat_BwPath = "";//未知dpi
}
if(j.contains("FlatWhitePath"))
j.at("FlatWhitePath").get_to(param.Flat_WhitePath);
else
{
if(param.DpiMode==1)
param.Flat_WhitePath = param.ColorMode == 1 ? LUT200_COLOR_WHITEPATH:LUT200_GRAY_WHITEPATH;
else if(param.DpiMode==2 )
param.Flat_WhitePath = param.ColorMode == 1 ? LUT300_COLOR_WHITEPATH:LUT300_GRAY_WHITEPATH;
else if(param.DpiMode==3)
param.Flat_WhitePath = param.ColorMode == 1 ? LUT600_COLOR_WHITEPATH:LUT600_GRAY_WHITEPATH;
else
param.Flat_WhitePath = "";//未知dpi
}
}

24
CorrectParam.h Normal file
View File

@ -0,0 +1,24 @@
#pragma once
#include "json.hpp"
#include <vector>
#include <memory>
#include "CameraParam.h"
#include "CorrectParam.h"
#include <mutex>
using json = nlohmann::json;
class CorrectParam
{
public:
CorrectParam(/* args */);
~CorrectParam();
FPGAConfigParam GetFpgaparam(int dpi,int mode);
void SaveCorrectParam(FPGAConfigParam& parms);
private:
void initdefaultpapram();
std::mutex m_lc;
std::vector<FPGAConfigParam> GetCorrectParams();
void to_json(json& j, FPGAConfigParam& param);
void from_json(json& j, FPGAConfigParam& param);
};

140
CuoZhiMotor.cpp Normal file
View File

@ -0,0 +1,140 @@
#include "CuoZhiMotor.h"
#include <random>
CuoZhiMotor::CuoZhiMotor()
: Motor(motorPorts_Cuozhi)
{
auto t_smbtype = smbtype == SMBType::MB_DRV_TMC216 ? MotorConfig::MTBDType::MT_TMC : MotorConfig::MTBDType::MT_DRV;
m_cuoparamex = m_mtconfig->GetMotorSpeedParam(false, t_smbtype, 4, 1, 1);
speedConfig();
mspCuozhiFeeding = {.finalPeriod = 1427500, .Fmin = 2027500, .stepnum = 30, .a = 100, .offset = 4, .finalDelay = 3000};
if (smbtype == SMBType::MB_DRV_TMC216)
{
mspCuozhiFeeding.finalPeriod /= 4;
mspCuozhiFeeding.Fmin /= 4;
}
delays_feeding = speedup_cfg(mspCuozhiFeeding.finalPeriod, mspCuozhiFeeding.Fmin, mspCuozhiFeeding.stepnum, mspCuozhiFeeding.a,
mspCuozhiFeeding.offset, mspCuozhiFeeding.finalDelay);
}
CuoZhiMotor::~CuoZhiMotor()
{
}
void CuoZhiMotor::pauseWaitForThread()
{
if (thStart.joinable())
{
thStart.join();
}
pause();
}
void CuoZhiMotor::startAsyn()
{
if (thStart.joinable())
{
thStart.join();
}
thStart = std::thread(&CuoZhiMotor::forward, this);
}
void CuoZhiMotor::start()
{
forward();
}
void CuoZhiMotor::reset()
{
if (thStart.joinable())
{
thStart.join();
}
setDirection(1);
delays_forward.clear();
delays_forward = speedup_cfg(mspCuozhiBackward.finalPeriod,
mspCuozhiBackward.Fmin,
mspCuozhiBackward.stepnum,
mspCuozhiBackward.a,
mspCuozhiBackward.offset,
mspCuozhiBackward.finalDelay);
LOG("finalPeriod=%d Fmin=%d \n", mspCuozhiBackward.finalPeriod, mspCuozhiBackward.Fmin);
Motor::start(delays_forward, mspCuozhiBackward);
std::random_device rd; // obtain a random number from hardware
std::mt19937 gen(rd()); // seed the generator
std::uniform_int_distribution<> distr(100, 400); // define the range
std::this_thread::sleep_for(std::chrono::milliseconds(distr(gen)));
stop();
delays_backward.clear();
delays_backward = speedup_cfg(mspCuozhiBackward.finalPeriod, mspCuozhiBackward.Fmin, mspCuozhiBackward.stepnum, mspCuozhiBackward.a,
mspCuozhiBackward.offset, mspCuozhiBackward.finalDelay);
setDirection(0);
Motor::start(delays_backward, mspCuozhiBackward);
if(smbtype==SMBType::MB_DRV_8825)
std::this_thread::sleep_for(std::chrono::milliseconds(30));
else
std::this_thread::sleep_for(std::chrono::milliseconds(150));
stop();
speedRecover();
}
void CuoZhiMotor::forward()
{
setDirection(1);
Motor::start(delays_forward, m_cuoparamex.mt_param);
}
void CuoZhiMotor::backward()
{
setDirection(0);
Motor::start(delays_backward, mspCuozhiBackward);
}
void CuoZhiMotor::feeding()
{
setDirection(1);
Motor::start(delays_feeding, mspCuozhiFeeding);
}
void CuoZhiMotor::speedChange(int speed, int dpi, int colormode) // speed should be in range [0,5] (by ply,at 2019.5.23)
{
auto t_smbtype = smbtype == SMBType::MB_DRV_8825 ? MotorConfig::MTBDType::MT_DRV : MotorConfig::MTBDType::MT_TMC;
m_cuoparamex = m_mtconfig->GetMotorSpeedParam(false, t_smbtype, speed, colormode, dpi);
speedConfig();
}
void CuoZhiMotor::speedRecover()
{
speedConfig();
}
void CuoZhiMotor::speedConfig()
{
LOG("CuoZhiMotor speed=%d \n dpi=%d \n colormode=%d \n finalPeriod=%d \n Fmin=%d \n a=%.2f \n offset=%.2f \n stepnum=%.2f \n finalDelay=%.2f \n ",
m_cuoparamex.speed,
m_cuoparamex.dpi,
m_cuoparamex.colormode,
m_cuoparamex.mt_param.finalPeriod,
m_cuoparamex.mt_param.Fmin,
m_cuoparamex.mt_param.a,
m_cuoparamex.mt_param.offset,
m_cuoparamex.mt_param.stepnum,
m_cuoparamex.mt_param.finalDelay);
delays_forward.clear();
delays_forward = speedup_cfg(m_cuoparamex.mt_param.finalPeriod, m_cuoparamex.mt_param.Fmin, m_cuoparamex.mt_param.stepnum, m_cuoparamex.mt_param.a,
m_cuoparamex.mt_param.offset, m_cuoparamex.mt_param.finalDelay);
std::vector<int> vct_speedupdon(delays_forward);
int size= vct_speedupdon.size();
int half_len = vct_speedupdon.size()/3;
for (int i = size-1; i > 0; i--)
{
delays_forward.push_back(vct_speedupdon[i]);
}
delays_backward.clear();
delays_backward = speedup_cfg(mspCuozhiBackward.finalPeriod, mspCuozhiBackward.Fmin, mspCuozhiBackward.stepnum, mspCuozhiBackward.a,
mspCuozhiBackward.offset, mspCuozhiBackward.finalDelay);
}

40
CuoZhiMotor.h Normal file
View File

@ -0,0 +1,40 @@
#pragma once
#include "Motor.h"
#include <thread>
#include <iostream>
class CuoZhiMotor : public Motor
{
public:
const MotorSpeedParam mspCuozhiBackward= {.finalPeriod = 627500,.Fmin = 1407750,.stepnum = 25,.a=150,.offset=8,.finalDelay=3000,.acceleration_time=0};
public:
CuoZhiMotor();
~CuoZhiMotor();
void reset();
virtual void start();
void startAsyn();
void pauseWaitForThread();
void backward();
void feeding();
void speedChange(int speed, int dpi = 1,int colormode = 1);
void speedRecover();
private:
MotorSpeedParam mspCuozhiFeeding;
std::vector<int> delays_forward;
MotorSpeedParamEx m_cuoparamex;
std::vector<int> delays_backward;
std::vector<int> delays_feeding;
std::thread thStart;
void forward();
void speedConfig();
};

29
DevUtil.cpp Normal file
View File

@ -0,0 +1,29 @@
#include "DevUtil.h"
#include <fstream>
#define IOEXPORTPATH "/sys/class/gpio/export"
#define PWMEXPORTPATH "/sys/class/pwm/pwmchip%d/export"
int read_dev_i(std::string path) {
int val = -1;
std::ifstream ifin(path.c_str());
ifin >> val;
return val;
}
std::string read_dev_s(std::string path) {
std::string val;
std::ifstream ifin(path.c_str());
ifin >> val;
return val;
}
DeviceExport::DeviceExport()
{
int num = sizeof(ports) / sizeof(ports[0]);
for (int i = 0; i < num; i++)
write_dev(IOEXPORTPATH, ports[i]);
num = sizeof(pwms) / sizeof(pwms[0]);
for (int i = 0; i < num; i++)
write_dev(string_format(PWMEXPORTPATH, pwms[i]), 0);
}

158
DevUtil.h Normal file
View File

@ -0,0 +1,158 @@
#pragma once
#include <string>
#include <fstream>
#include <memory>
#include "scanservices_utils.h"
template<typename ... Args>
std::string string_format(const std::string& format, Args ... args) {
size_t size = snprintf(nullptr, 0, format.c_str(), args ...) + 1;
std::unique_ptr<char[]> buf(new char[size]);
snprintf(buf.get(), size, format.c_str(), args ...);
return std::string(buf.get(), buf.get() + size - 1);
}
template<typename T>
void write_dev(std::string path, T value) {
std::ofstream ofout(path);
ofout << value;
}
extern int read_dev_i(std::string path);
extern std::string read_dev_s(std::string path);
enum PIN_PORT_7010
{
//通道0-------------START
SCAN_SENSOR = 0 + 1019, //扫描传感器
HAVE_OR_NO_PAPER = 3 + 1019, //有无纸(0无纸1有纸)
OPEN_COVER_SENSOR = 4 + 1019, //是否开盖0未开盖1开盖
ULTRASONIC_SENSORS_OUT0 = 18 + 1019,
ULTRASONIC_SENSORS_OUT1 = 17 + 1019,
ULTRASONIC_SENSORS_ON = 20 + 1019,
ULTRASONIC_SENSORS_ADJ = 19 + 1019,
//通道0-------------END
SENSOR_POWER = 66 + 1019,
//通道1-------------START
BUTTON_1_POWER = 21+1019, //按键1 电源
BUTTON_2 = 22+1019, //按键2
BUTTON_3 = 23+1019, //按键3
LED_0_GREEN = 24+1019,
LED_1_WHITE = 25+1019,
LED_2_RED = 26+1019,
//PWM0 电机1-START
CUOZHI_PIN_DIR = 54+901, //方向0
CUOZHI_PIN_ENABEL = 55+901, //使能有效0
CUOZHI_PIN_RESET = 56+901, //重启 1电机转动一般默认为1
CUOZHI_PIN_SLEEP = 57+901, //睡眠 1电机转动一般默认为1
//PWM0 电机1-END
//PWM1 电机2-START
ZOUZHI_PIN_DIR = 59+901, //方向0
ZOUZHI_PIN_ENABEL = 60+901, //使能有效0
ZOUZHI_PIN_RESET = 61+901, //重启 1电机转动一般默认为1
ZOUZHI_PIN_SLEEP = 62+901, //睡眠 1电机转动一般默认为1
//PWM1 电机2-END
//通道1-------------END
MOTOR_POWER_1 = 64 + 901, //电机1 电源开关
MOTOR_POWER_2 = 65 + 901, //电机2 电源开关
};
enum PORTS
{
//Start = 171,
//Stop = 49,
//Power = 5,
Fpga_InitN = 7,//GPIO0_A7
Fpga_Load = 8,//GPIO0_B7
#ifndef G300
Power_12v_Off = 12,
#endif
//MotorPower = 48,
//CuoZhiMotor_Reset = 56,
//CuoZhiMotor_Sleep = 57,
//CuoZhiMotor_Enable = 58,
//CuoZhiMotor_Direction = 62,
//CuoZhiMotor_Decay = 63,
//CuoZhiMotor_Home = 184,
//CuoZhiMotor_Fault = 185,
//CuoZhiMotor_Mode0 = 59,
//CuoZhiMotor_Mode1 = 60,
//CuoZhiMotor_Mode2 = 61,
//Cover = 189,// 'GPIO6A5' opened:0 ; closed:1
//Paper = 225,// 'GPIO7B1' has paper:0 ; no paper:1
//Scan = 226,// 'GPIO7B2' no paper:0 ; has paper:1
//PaperJam = 102,
//Double_Paper = 219,// 'GPIO7A3' not doubled:0 ; doubled:1
SW_NOR_FLASH = 221,
//Double_Enable = 250,// 'GPIO8A2' off: 0 ; on: 1
//ZouZhiMotor_Reset = 64,
//ZouZhiMotor_Sleep = 65,
//ZouZhiMotor_Enable = 66,
//ZouZhiMotor_Direction = 70,
//ZouZhiMotor_Decay = 71,
//ZouZhiMotor_Home = 187,
//ZouZhiMotor_Fault = 188,
//ZouZhiMotor_Mode0 = 67,
//ZouZhiMotor_Mode1 = 68,
//ZouZhiMotor_Mode2 = 69,
CIS_3v3_Off = 96,
CIS_5v_En = 98,
Fpga_InitDone = 99,
Image_In_Transfer = 101,
Fpga_Reset = 232,
CIS_T_S0=190,
CIS_T_S1=191,
CIS_T_S2=234,
CIS_T_S3=233
};
// class DeviceExport {
// public:
// DeviceExport();
// private:
// #ifndef G300
// const int ports[42] = { Start , Stop, Power, Fpga_Load, Power_12v_Off, MotorPower, CuoZhiMotor_Reset, CuoZhiMotor_Sleep, CuoZhiMotor_Enable,
// CuoZhiMotor_Direction, CuoZhiMotor_Decay, CuoZhiMotor_Home, CuoZhiMotor_Fault , CuoZhiMotor_Mode0 ,
// CuoZhiMotor_Mode1, CuoZhiMotor_Mode2, Cover, Paper, Scan, PaperJam,Double_Paper, Double_Enable,
// ZouZhiMotor_Reset, ZouZhiMotor_Sleep, ZouZhiMotor_Enable, ZouZhiMotor_Direction, ZouZhiMotor_Decay,
// ZouZhiMotor_Home, ZouZhiMotor_Fault, ZouZhiMotor_Mode0, ZouZhiMotor_Mode1, ZouZhiMotor_Mode2,
// CIS_3v3_Off, CIS_5v_En, Fpga_InitDone, Image_In_Transfer, Fpga_Reset, SW_NOR_FLASH,CIS_T_S0,CIS_T_S1,CIS_T_S2,CIS_T_S3};
// #else
// const int ports[37] = { Start , Stop, Power, Fpga_Load, MotorPower, CuoZhiMotor_Reset, CuoZhiMotor_Sleep, CuoZhiMotor_Enable,
// CuoZhiMotor_Direction, CuoZhiMotor_Decay, CuoZhiMotor_Home, CuoZhiMotor_Fault , CuoZhiMotor_Mode0 ,
// CuoZhiMotor_Mode1, CuoZhiMotor_Mode2, Cover, Paper, Scan, PaperJam, Double_Paper, Double_Enable,
// ZouZhiMotor_Reset, ZouZhiMotor_Sleep, ZouZhiMotor_Enable, ZouZhiMotor_Direction, ZouZhiMotor_Decay,
// ZouZhiMotor_Home, ZouZhiMotor_Fault, ZouZhiMotor_Mode0, ZouZhiMotor_Mode1, ZouZhiMotor_Mode2,
// CIS_3v3_Off, CIS_5v_En, Fpga_InitDone, Image_In_Transfer, Fpga_Reset,Fpga_InitN };
// #endif
// const int pwms[2] = { 2, 3 };
// };
class DeviceExport
{
public:
DeviceExport();
private:
const int ports[14] = { MOTOR_POWER_1, CUOZHI_PIN_RESET, CUOZHI_PIN_SLEEP,CUOZHI_PIN_ENABEL, CUOZHI_PIN_DIR,
MOTOR_POWER_2, ZOUZHI_PIN_RESET, ZOUZHI_PIN_SLEEP,ZOUZHI_PIN_ENABEL, ZOUZHI_PIN_DIR,
SCAN_SENSOR,HAVE_OR_NO_PAPER, OPEN_COVER_SENSOR,};
const int pwms[4] = { 0, 1 ,2};
};

633
FpgaComm.cpp Normal file
View File

@ -0,0 +1,633 @@
//
// Created by Nick on 2019/4/7.
//
#include <iostream>
#include "FpgaComm.h"
#include <thread>
#define LOG_TAG "FpgaComm"
#define LOGD(...) ((void)printf(__VA_ARGS__))
int FpgaComm::read(int addr)
{
unsigned char *pdata = bufRecv;
pdata[0] = 0x03;
pdata[1] = (unsigned char)addr;
m_serial.Write(bufRecv, 2);
if (m_serial.Read(bufRecv, 5, 300))
{
int ret = 0;
unsigned char *pdata = (unsigned char *)(&ret);
for (int i = 0; i < 4; i++)
{
pdata[i] = bufRecv[4 - i];
}
return ret;
}
return -1;
}
void FpgaComm::write(int addr, int data)
{
unsigned char *pdata = bufSend;
pdata[0] = 0x83;
pdata[1] = (unsigned char)addr;
unsigned char *idata = (unsigned char *)&data;
for (int i = 0; i < 4; i++)
{
pdata[6 - i] = idata[i];
}
m_serial.Write(bufSend, sizeof(bufSend));
}
void FpgaComm::updateRegs(int addr)
{
write(addr, fpgaParams.regs[addr]);
}
void FpgaComm::setFrameHeight(int height)
{
fpgaParams.params.frame.height = height;
write(0x00, fpgaParams.regs[0x00]);
}
int FpgaComm::getFrameHeight()
{
// fpgaParams.params.frame.height = height;
int reg0v = read(0x00);
FrameFpga *frameinfo = (FrameFpga *)&reg0v;
return frameinfo->height;
}
int FpgaComm::getAutoFrameHeight()
{
unsigned int val;
unsigned int reg8 = 0;
reg8 = read(0x08);
val = read(14);
int regv = val;
val &= 0x0000ffff;
write(0x8, reg8 & 0xfffffff7);
std::this_thread::sleep_for(std::chrono::milliseconds(5));
// val = read(14);
// regv = val;
// val &= 0x0000ffff;
// reg8 = read(0x8);
// LOG("TWO height = %d reg[14] = %d \n", val, regv);
std::this_thread::sleep_for(std::chrono::milliseconds(5));
write(0x8, reg8 | 0x8);
return val;
}
void FpgaComm::setFrameNum(int num)
{
fpgaParams.params.frame.num = num;
write(0x00, fpgaParams.regs[0x00]);
}
void FpgaComm::enableLed(bool bEnable)
{
fpgaParams.params.AledR.user_define.led_sample.ledEnable = bEnable;
write(0x05, fpgaParams.regs[0x05]);
#ifdef HAS_UV
fpgaParams.params.BledR.user_define.led_sample.ledEnable = bEnable;
write(0x08, fpgaParams.regs[0x08]);
#else
fpgaParams.params.BledR.user_define.led_sample.ledEnable = 0;
write(0x08, fpgaParams.regs[0x08]);
#endif
}
void FpgaComm::enableUV(bool enable)
{
#ifdef HAS_UV
isUVEnable = enable;
fpgaParams.params.BledR.user_define.led_sample.ledEnable = isUVEnable;
write(0x08, fpgaParams.regs[0x08]);
#endif
}
void FpgaComm::capture()
{ // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʲô<CAB2>أ<EFBFBD>
fpgaParams.params.cmd.cmd = 0;
write(0x02, fpgaParams.regs[0x02]);
fpgaParams.params.cmd.cmd = 1;
write(0x02, fpgaParams.regs[0x02]);
}
int FpgaComm::getRegs(int addr)
{
return fpgaParams.regs[addr];
}
void FpgaComm::setRegs(int addr, int value)
{
fpgaParams.regs[addr] = value;
write(addr, value);
}
FpgaComm::FpgaComm() : fanGpio(FAN_PORT) // <20><>ʼ<EFBFBD><CABC>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ȡ<EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
{
m_serial.Open(com.c_str(), bauds);
// for(int i = 0; i < MAX_REGS; i++){
// fpgaParams.regs[i] = read(i);
// LOG("reg[%d] = 0x%08x \n", i, fpgaParams.regs[i]);
// }
fpgaParams.params.AledR.user_define.led_sample.sample = 256;
updateRegs(0x05);
enableLed(true);
}
void FpgaComm::updateRegs()
{
for (int i = 0x05; i < MAX_REGS; i++)
{
updateRegs(i);
}
fpgaParams.params.AledR.user_define.led_sample.sample = 256;
updateRegs(0x05);
}
void FpgaComm::setAGain(int indexGain, int value)
{
AdGain adGain;
adGain.value = value;
indexGain++;
fpgaParams.params.Aad.bits.ad0_addr = indexGain * 2;
fpgaParams.params.Aad.bits.ad1_addr = fpgaParams.params.Aad.bits.ad0_addr + 1;
fpgaParams.params.Aad.bits.ad0_value = adGain.gain_value.gain_low8;
fpgaParams.params.Aad.bits.ad1_value = adGain.gain_value.gain_hight;
fpgaParams.params.Aad.bits.ad0_rw = 0;
fpgaParams.params.Aad.bits.ad1_rw = 0;
updateRegs(0x04);
fpgaParams.params.mode.adcA = 1;
updateRegs(0x01);
fpgaParams.params.mode.adcA = 0;
updateRegs(0x01);
}
void FpgaComm::getAGain(int indexGain, int &Avalue, int &Bvalue)
{
AdGain adGain;
CisAdGain adgain;
// adGain.value = value;
indexGain++;
fpgaParams.params.Aad.bits.ad0_addr = indexGain * 2;
fpgaParams.params.Aad.bits.ad1_addr = fpgaParams.params.Aad.bits.ad0_addr + 1;
fpgaParams.params.Aad.bits.ad0_value = 0;
fpgaParams.params.Aad.bits.ad1_value = 0;
fpgaParams.params.Aad.bits.ad0_rw = 0;
fpgaParams.params.Aad.bits.ad1_rw = 0;
updateRegs(0x04);
fpgaParams.params.mode.adcA = 1;
updateRegs(0x01);
fpgaParams.params.mode.adcA = 0;
updateRegs(0x01);
auto ret = read(0x03);
adgain.value = ret;
Avalue = adgain.bits.ad0_value;
Bvalue = adgain.bits.ad1_value;
}
void FpgaComm::setBGain(int indexGain, int value)
{
AdGain adGain;
adGain.value = value;
indexGain++;
fpgaParams.params.Bad.bits.ad0_addr = indexGain * 2;
fpgaParams.params.Bad.bits.ad1_addr = indexGain * 2 + 1;
fpgaParams.params.Bad.bits.ad0_value = adGain.gain_value.gain_low8;
fpgaParams.params.Bad.bits.ad1_value = adGain.gain_value.gain_hight;
fpgaParams.params.Bad.bits.ad0_rw = 0;
fpgaParams.params.Bad.bits.ad1_rw = 0;
updateRegs(0x07);
fpgaParams.params.mode.adcB = 1;
updateRegs(0x01);
fpgaParams.params.mode.adcB = 0;
updateRegs(0x01);
}
void FpgaComm::getBGain(int indexGain, int &Avalue, int &Bvalue)
{
AdGain adGain;
CisAdGain adgain;
// adGain.value = value;
indexGain++;
fpgaParams.params.Bad.bits.ad0_addr = indexGain * 2;
fpgaParams.params.Bad.bits.ad1_addr = indexGain * 2 + 1;
fpgaParams.params.Bad.bits.ad0_value = adGain.gain_value.gain_low8;
fpgaParams.params.Bad.bits.ad1_value = adGain.gain_value.gain_hight;
fpgaParams.params.Bad.bits.ad0_rw = 1;
fpgaParams.params.Bad.bits.ad1_rw = 1;
updateRegs(0x07);
fpgaParams.params.mode.adcB = 1;
updateRegs(0x01);
fpgaParams.params.mode.adcB = 0;
updateRegs(0x01);
auto ret = read(0x03);
adgain.value = ret;
Avalue = adgain.bits.ad0_value;
Bvalue = adgain.bits.ad1_value;
}
void FpgaComm::setAOffset(int indexOffset, int value)
{
fpgaParams.params.Aad.bits.ad0_rw = 0;
fpgaParams.params.Aad.bits.ad1_rw = 0;
fpgaParams.params.Aad.bits.ad0_addr = indexOffset + 0x0e;
fpgaParams.params.Aad.bits.ad1_addr = 0x14;
fpgaParams.params.Aad.bits.ad1_value = 0x50;
fpgaParams.params.Aad.bits.ad0_value = value;
updateRegs(0x04);
fpgaParams.params.mode.adcA = 1;
updateRegs(0x01);
fpgaParams.params.mode.adcA = 0;
updateRegs(0x01);
}
void FpgaComm::getAOffset(int indexGain, int &Avalue, int &Bvalue)
{
fpgaParams.params.Aad.bits.ad0_rw = 1;
fpgaParams.params.Aad.bits.ad1_rw = 1;
fpgaParams.params.Aad.bits.ad0_addr = indexGain + 0x0e;
fpgaParams.params.Aad.bits.ad1_addr = 0x14;
fpgaParams.params.Aad.bits.ad1_value = 0x50;
fpgaParams.params.Aad.bits.ad0_value = 0;
updateRegs(0x04);
fpgaParams.params.mode.adcA = 1;
updateRegs(0x01);
fpgaParams.params.mode.adcA = 0;
updateRegs(0x01);
CisAdGain adgain;
auto ret = read(0x03);
adgain.value = ret;
Avalue = adgain.bits.ad0_value;
Bvalue = adgain.bits.ad1_value;
}
void FpgaComm::setBOffset(int indexOffset, int value)
{
fpgaParams.params.Bad.bits.ad0_rw = 0;
fpgaParams.params.Bad.bits.ad1_rw = 0;
fpgaParams.params.Bad.bits.ad0_addr = indexOffset + 0x0e;
fpgaParams.params.Bad.bits.ad1_addr = 0x14;
fpgaParams.params.Aad.bits.ad1_value = 0x50;
fpgaParams.params.Bad.bits.ad0_value = value;
updateRegs(0x07);
fpgaParams.params.mode.adcB = 1;
updateRegs(0x01);
fpgaParams.params.mode.adcB = 0;
updateRegs(0x01);
}
void FpgaComm::getBOffset(int indexGain, int &Avalue, int &Bvalue)
{
fpgaParams.params.Bad.bits.ad0_rw = 1;
fpgaParams.params.Bad.bits.ad1_rw = 1;
fpgaParams.params.Bad.bits.ad0_addr = indexGain + 0x0e;
fpgaParams.params.Bad.bits.ad1_addr = 0x14;
fpgaParams.params.Aad.bits.ad1_value = 0x50;
fpgaParams.params.Bad.bits.ad0_value = 0;
updateRegs(0x07);
fpgaParams.params.mode.adcB = 1;
updateRegs(0x01);
fpgaParams.params.mode.adcB = 0;
updateRegs(0x01);
CisAdGain adgain;
auto ret = read(0x03);
adgain.value = ret;
Avalue = adgain.bits.ad0_value;
Bvalue = adgain.bits.ad1_value;
}
void FpgaComm::setAExposureR(int value)
{
fpgaParams.params.AledR.ledR = value;
updateRegs(0x05);
fpgaParams.regs[0x05] = read(0x05);
}
void FpgaComm::setAExposureG(int value)
{
fpgaParams.params.AledGB.bits.ledG = value;
updateRegs(0x06);
fpgaParams.regs[0x06] = read(0x06);
}
void FpgaComm::setAExposureB(int value)
{
fpgaParams.params.AledGB.bits.ledB = value;
updateRegs(0x06);
fpgaParams.regs[0x06] = read(0x06);
}
void FpgaComm::setAExposureUV(int value)
{
#ifdef HAS_UV
fpgaParams.params.UVLed.bits.ledASide = value;
updateRegs(0x0d);
fpgaParams.regs[0x0d] = read(0x0d);
#endif
}
void FpgaComm::setBExposureR(int value)
{
fpgaParams.params.BledR.ledR = value;
updateRegs(0x08);
fpgaParams.regs[0x08] = read(0x08);
}
void FpgaComm::setBExposureG(int value)
{
fpgaParams.params.BledGB.bits.ledG = value;
updateRegs(0x09);
fpgaParams.regs[0x09] = read(0x09);
}
void FpgaComm::setBExposureB(int value)
{
fpgaParams.params.BledGB.bits.ledB = value;
updateRegs(0x09);
fpgaParams.regs[0x09] = read(0x09);
}
void FpgaComm::setBExpousreUV(int value)
{
#ifdef HAS_UV
fpgaParams.params.UVLed.bits.ledBSide = value;
updateRegs(0x0d);
fpgaParams.regs[0x0d] = read(0x0d);
#endif
}
void FpgaComm::setEnTestCol(bool en)
{
fpgaParams.params.AledR.user_define.led_sample.en_test_color = en ? 1 : 0;
updateRegs(0x05);
fpgaParams.regs[0x05] = read(0x05);
}
void FpgaComm::setEnTestBit(bool en)
{
fpgaParams.params.AledR.user_define.led_sample.en_test = en ? 1 : 0;
updateRegs(0x05);
fpgaParams.regs[0x05] = read(0x05);
}
void FpgaComm::setFanMode(int mode)
{
fanGpio.setValue(mode == 3 ? Gpio::Low : Gpio::High);
}
void FpgaComm::setSp(int value)
{
setRegs(0x01, value);
}
int FpgaComm::getSp()
{
return fpgaParams.params.mode.sp;
}
void FpgaComm::setColorMode(int mode)
{
fpgaParams.params.mode.colorMode = mode;
updateRegs(0x01);
}
int FpgaComm::getColorMode()
{
return fpgaParams.params.mode.colorMode;
}
void FpgaComm::setSample(int sample)
{
fpgaParams.params.mode.sample = sample;
updateRegs(0x01);
fpgaParams.params.AledR.user_define.led_sample.sample = sample;
updateRegs(0x05);
}
void FpgaComm::EnableTest(bool bTest)
{
fpgaParams.params.mode.selftest = bTest;
updateRegs(0x01);
}
int FpgaComm::IsTest()
{
return fpgaParams.params.mode.selftest;
}
int FpgaComm::getSample()
{
return fpgaParams.params.mode.sample;
}
void FpgaComm::setDpi(int dpi)
{
fpgaParams.params.mode.dpi = dpi;
updateRegs(0x01);
}
int FpgaComm::getDpi()
{
return fpgaParams.params.mode.dpi;
}
void FpgaComm::setSample(int sampleFront, int sampleBack)
{
fpgaParams.params.mode.sample = sampleFront;
updateRegs(0x01);
fpgaParams.params.AledR.user_define.led_sample.sample = sampleBack;
updateRegs(0x05);
}
// 20190626 YHP autoTrig function
void FpgaComm::setTrigMode(bool isArmMode)
{
int tmp = read(0x0b);
if (!isArmMode)
{ // default value+ ARM MODE,bit27 =0;
fpgaParams.params.TrigMode = tmp & 0XFBFFFFFF;
}
else
{
fpgaParams.params.TrigMode = tmp | (1 << 26);
}
updateRegs(0x0b);
}
// void FpgaComm::setDelayTime(int value) {
// // fpgaParams.params.DelayTime = value;
// // updateRegs(0x0C);
// }
void FpgaComm::setFrame_interval_min(int min)
{
fpgaParams.params.FrameInterval.Frame_Interval_min = min;
fpgaParams.params.FrameInterval.reversed = 0;
updateRegs(0xc);
}
int FpgaComm::getFrame_interval_min()
{
fpgaParams.params.FrameInterval.reversed = 0;
auto value = read(0x0c);
fpgaParams.params.FrameInterval = *(CisFrameInterval *)&value;
return fpgaParams.params.FrameInterval.Frame_Interval_min;
}
void FpgaComm::setFrame_interval_max(int max)
{
fpgaParams.params.FrameInterval.Frame_Interval_max = max;
fpgaParams.params.FrameInterval.reversed = 0;
updateRegs(0xc);
}
int FpgaComm::getFrame_interval_max()
{
fpgaParams.params.FrameInterval.reversed = 0;
auto value = read(0x0c);
fpgaParams.params.FrameInterval = *(CisFrameInterval *)&value;
return fpgaParams.params.FrameInterval.Frame_Interval_max;
}
// <20><><EFBFBD>¼Ĵ<C2BC><C4B4><EFBFBD><EFBFBD><EFBFBD>Ϣ
void FpgaComm::update()
{
for (int i = 0; i < MAX_REGS; i++)
{
fpgaParams.regs[i] = read(i);
LOG("reg[%d] = 0x%08x \n", i, fpgaParams.regs[i]);
}
}
void FpgaComm::enableJamCheck(bool b)
{
// fpgaParams.params.BledR.user_define.led_sample.jamEnable = b;
// updateRegs(0x08);
}
void FpgaComm::resetADC()
{
fpgaParams.params.Aad.bits.ad0_rw = 0;
fpgaParams.params.Aad.bits.ad0_addr = 0;
fpgaParams.params.Aad.bits.ad0_value = 0;
fpgaParams.params.Aad.bits.ad1_rw = 0;
fpgaParams.params.Aad.bits.ad1_addr = 0;
fpgaParams.params.Aad.bits.ad1_value = 0;
updateRegs(0x04);
fpgaParams.params.mode.adcA = 1;
updateRegs(0x01);
fpgaParams.params.mode.adcA = 0;
updateRegs(0x01);
fpgaParams.params.Bad.bits.ad0_rw = 0;
fpgaParams.params.Bad.bits.ad0_addr = 0;
fpgaParams.params.Bad.bits.ad0_value = 0;
fpgaParams.params.Bad.bits.ad1_rw = 0;
fpgaParams.params.Bad.bits.ad1_addr = 0;
fpgaParams.params.Bad.bits.ad1_value = 0;
updateRegs(0x07);
fpgaParams.params.mode.adcB = 1;
updateRegs(0x01);
fpgaParams.params.mode.adcB = 0;
updateRegs(0x01);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
fpgaParams.params.Aad.bits.ad0_rw = 0;
fpgaParams.params.Aad.bits.ad0_addr = 0;
fpgaParams.params.Aad.bits.ad0_value = 7;
fpgaParams.params.Aad.bits.ad1_rw = 0;
fpgaParams.params.Aad.bits.ad1_addr = 0;
fpgaParams.params.Aad.bits.ad1_value = 7;
updateRegs(0x04);
fpgaParams.params.mode.adcA = 1;
updateRegs(0x01);
fpgaParams.params.mode.adcA = 0;
updateRegs(0x01);
fpgaParams.params.Bad.bits.ad0_rw = 0;
fpgaParams.params.Bad.bits.ad0_addr = 0;
fpgaParams.params.Bad.bits.ad0_value = 7;
fpgaParams.params.Bad.bits.ad1_rw = 0;
fpgaParams.params.Bad.bits.ad1_addr = 0;
fpgaParams.params.Bad.bits.ad1_value = 7;
updateRegs(0x07);
fpgaParams.params.mode.adcB = 1;
updateRegs(0x01);
fpgaParams.params.mode.adcB = 0;
updateRegs(0x01);
fpgaParams.params.Aad.bits.ad0_rw = 0;
fpgaParams.params.Aad.bits.ad0_addr = 1;
fpgaParams.params.Aad.bits.ad0_value = 0x50;
fpgaParams.params.Aad.bits.ad1_rw = 0;
fpgaParams.params.Aad.bits.ad1_addr = 1;
fpgaParams.params.Aad.bits.ad1_value = 0x50;
updateRegs(0x04);
fpgaParams.params.mode.adcA = 1;
updateRegs(0x01);
fpgaParams.params.mode.adcA = 0;
updateRegs(0x01);
fpgaParams.params.Bad.bits.ad0_rw = 0;
fpgaParams.params.Bad.bits.ad0_addr = 1;
fpgaParams.params.Bad.bits.ad0_value = 0x50;
fpgaParams.params.Bad.bits.ad1_rw = 0;
fpgaParams.params.Bad.bits.ad1_addr = 1;
fpgaParams.params.Bad.bits.ad1_value = 0x50;
updateRegs(0x07);
fpgaParams.params.mode.adcB = 1;
updateRegs(0x01);
fpgaParams.params.mode.adcB = 0;
updateRegs(0x01);
}
void FpgaComm::setVsp(unsigned int Aside, unsigned int BSide)
{
// auto ret = read(13);
CISVSP vsp; // = *(CISVSP*)&ret;
vsp.bits.ASide_VSP = Aside;
vsp.bits.BSide_VSP = BSide;
vsp.bits.reserved = 0;
printf("setVsp A side =%d B side=%d vspint=%08x \n", vsp.bits.ASide_VSP, vsp.bits.BSide_VSP, vsp.value);
write(13, vsp.value);
}
unsigned int FpgaComm::getFrame_counter_val()
{
int crt_frame_count=0;
unsigned int reg8 = 0;
reg8 = read(8);
//write(8,reg8 & 0x8);
std::this_thread::sleep_for(std::chrono::milliseconds(10));
write(8, reg8 & 0xfffffff7);//off stop snap
reg8 = read(8);
std::this_thread::sleep_for(std::chrono::milliseconds(10));
crt_frame_count = read(0x10);
if(crt_frame_count <= 0)//读取失败或帧数为0的情况下多读几次
{
for(int i = 0;i<3;i++)
{
crt_frame_count = read(0x10);
printf("try %d times read frame count,frame_count = %d \n",i,crt_frame_count);
if(crt_frame_count > 0)
break;
}
}
write(8, reg8 | 0x8);// on reset counter
std::this_thread::sleep_for(std::chrono::milliseconds(2));
//printf("TWO height reg[14] = %d reg[16] = %d \n", read(14) & 0xffff,read(16));
return crt_frame_count;
}
int FpgaComm::getFrameNum(){
return fpgaParams.params.frame.num;
}
void FpgaComm::set_cis_type(bool isA3_CIS)
{
fpgaParams.params.AledR.user_define.led_sample.cis_type = isA3_CIS?1:0;
}

284
FpgaComm.h Normal file
View File

@ -0,0 +1,284 @@
//
// Created by Nick on 2019/4/7.
//
#ifndef HGSCANSERVICE_FPGACOMM_H
#define HGSCANSERVICE_FPGACOMM_H
#include "serialib.h"
#include <string>
#include <memory>
#include <cstring>
#include "Gpio.h"
#include "scanservices_utils.h"
//#define HAS_UV
#ifdef HAS_UV
#define MAX_REGS 0x0e
#else
#define MAX_REGS 0x0d
#endif
typedef struct Frame_FPGA
{
unsigned int height:16;
unsigned int num : 16;
} FrameFpga;
typedef struct Mode_FPGA
{
unsigned short int colorMode : 1;
unsigned short int dpi : 2;
unsigned short int led : 1;
unsigned short sample : 9;
unsigned short int adcA : 1;
unsigned short int adcB : 1;
unsigned short int selftest : 1;
unsigned short int sp;
} ModeFpga;
typedef struct CMD_FPGA
{
unsigned int cmd : 1; //start : 1 , stop : 0
unsigned int reserved : 31;
} CmdFpga;
typedef struct STATUS_FPGA
{
unsigned int status : 1; //start : 1 , stop : 0
unsigned int reserved : 31;
} StatusFpga;
typedef union Ad_Gain
{
struct
{
unsigned short int gain_low8 : 8;
unsigned short int gain_hight : 1;
} gain_value;
unsigned short int value;
} AdGain;
typedef union CIS_AD_Gain
{
struct
{
unsigned short int ad0_value : 8; //!< 数据位
unsigned short int ad0_reserved : 2; //!< 保留位
unsigned short int ad0_addr : 5; //!< 寄存器地址
unsigned short int ad0_rw : 1; //!< 读写位 1:读, 0:写
unsigned short int ad1_value : 8; //!< 数据位
unsigned short int ad1_reserved : 2; //!< 保留位
unsigned short int ad1_addr : 5; //!< 寄存器地址
unsigned short int ad1_rw : 1; //!< 读写位 1:读, 0:写;
} bits;
int value;
} CisAdGain;
typedef struct CIS_LED_RF {
union
{
struct
{
unsigned short int ledEnable : 1;
unsigned short int fanMode : 2;
unsigned short int jamEnable : 1;
unsigned short int sample : 9;
} led_sample;
unsigned short int reserved;
} user_define;
unsigned short int ledR;
}CisLedRF;
typedef struct CIS_LED_R
{
union
{
struct
{
unsigned short int ledEnable : 1;
unsigned short int sample : 9;
unsigned short int en_test_color :1;
unsigned short int en_test : 1;
unsigned short int cis_type : 1 ;
} led_sample;
unsigned short int reserved;
} user_define;
unsigned short int ledR;
} CisLedR;
typedef union CIS_LED_GB
{
struct
{
unsigned short int ledG;
unsigned short int ledB;
} bits;
int value;
} CisLedGB;
typedef union CIS_LED_UV
{
struct
{
unsigned short int ledASide;
unsigned short int ledBSide;
} bits;
int value;
} CisLedUv;
typedef union CIS_VSP
{
struct
{
unsigned int ASide_VSP:9;
unsigned int BSide_VSP:9;
unsigned int reserved : 14;
} bits;
int value;
} CISVSP;
typedef struct CIS_FRAME_INTERVAL
{
unsigned short Frame_Interval_min;
unsigned short Frame_Interval_max:13;
unsigned short reversed:3;
}CisFrameInterval;
typedef union Fpga_Params
{
struct
{
FrameFpga frame; //0x00
ModeFpga mode; //0x01
CmdFpga cmd; //0x02
StatusFpga status; //0x03
CisAdGain Aad; //0x04
CisLedR AledR; //0x05
CisLedGB AledGB; //0x06
CisAdGain Bad; //0x07
#ifndef G300
CisLedRF BledR; //0x08
#else
CisLedR BledR; //0x08
#endif
CisLedGB BledGB; //0x09
unsigned int ExpIncr; //0x0a
unsigned int TrigMode; //0x0b
CisFrameInterval FrameInterval; //0x0c
CisLedUv UVLed; //0x0d
unsigned int reversed;//0x0e
unsigned int fpgaversion;//0x0f
unsigned int ConFrameCount;//多帧计数
} params;
int regs[17];
} FpgaParams;
#define FAN_PORT 59
class FpgaComm
{
public:
FpgaComm();
void reset();
void setRegs(int addr, int value);
int getRegs(int addr);
void setFrameHeight(int height);
int getFrameHeight();
int getAutoFrameHeight();
void setFrameNum(int num);
void enableLed(bool bEnable);
void enableUV(bool enable);
void capture();
void updateRegs();
void setAGain(int indexGain, int value);
void getAGain(int indexGain, int &Avalue, int &Bvalue);
void setBGain(int indexGain, int value);
void getBGain(int indexGain, int &Avalue, int &Bvalue);
void setAOffset(int indexOffset, int value);
void getAOffset(int indexGain, int &Avalue, int &Bvalue);
void setBOffset(int indexOffset, int value);
void getBOffset(int indexGain, int &Avalue, int &Bvalue);
void setAExposureR(int value);
void setAExposureG(int value);
void setAExposureB(int value);
void setAExposureUV(int value);
void setBExposureR(int value);
void setBExposureG(int value);
void setBExposureB(int value);
void setBExpousreUV(int value);
void setEnTestCol(bool en);
void setEnTestBit(bool en);
void setFanMode(int mode);
void setSp(int value);
int getSp();
void setSample(int sampleFront,int sampleBack);
void EnableTest(bool bTest);
int IsTest();
void setColorMode(int mode);
int getColorMode();
void setDpi(int dpi);
int getDpi();
void setSample(int sample);
int getSample();
int read(int addr);
//20190626 YHP autoTrig function
void setFrame_interval_min(int min);
int getFrame_interval_min();
void setFrame_interval_max(int max);
int getFrame_interval_max();
//void setDelayTime(int value);
void setTrigMode(bool isArmMode);
void update();
void enableJamCheck(bool b);
void resetADC();
void setVsp(unsigned int Aside,unsigned int BSide);
unsigned int getFrame_counter_val();
int getFrameNum();
void set_cis_type(bool isA3_CIS);
private:
const std::string com = "/dev/ttyS3";
const unsigned int bauds = 921600;
unsigned char bufSend[7];
unsigned char bufRecv[5];
serialib m_serial;
FpgaParams fpgaParams;
bool isUVEnable = false;
Gpio fanGpio;
void updateRegs(int addr);
void write(int addr, int data);
};
#endif //HGSCANSERVICE_FPGACOMM_H

339
FsmState.cpp Normal file
View File

@ -0,0 +1,339 @@
#include "FsmState.h"
#include "Scanner.h"
Scanner *FsmState::scanner = NULL;
FsmState::FsmState()
{
}
FsmState::~FsmState()
{
}
std::map<std::string, std::shared_ptr<FsmState>> FsmStateManager::fsmStates;
void StandbyState::initial()
{
LOG("StandbyState \n");
typeName = "StandbyState";
scanner->getPanelLeds().setStatus(LedStatus::Ready);
doReset();
}
FsmState *StandbyState::on_event(ScanEvent event)
{
LOG("StandbyState on_event %d \n", event);
if (event == S_EVT_COVER_OPENED)
{
return FsmStateManagerEx<CoverOpenState>::GetState();
}
else if (event == S_EVT_JAM_OUT)
{
return FsmStateManagerEx<ErrorJamState>::GetState();
}
else if (event == S_EVT_PAPER_STANDBY)
{
if (scanner->getSensor().isPaperStandby())
{
LOG("StandbyState on_event : %s \n", "true");
return FsmStateManagerEx<PaperReadyState>::GetState();
}
}
else if (event == S_EVT_START_SCAN)
{
scanner->getPanelLeds().setStatus(LedStatus::NoPaper);
std::this_thread::sleep_for(std::chrono::milliseconds(1200));
scanner->getPanelLeds().setStatus(LedStatus::Ready);
}
return this;
}
void StandbyState::doReset()
{
if (!scanner->isRested)
scanner->reset();
}
void CoverOpenState::initial()
{
LOG("CoverOpenState \n");
typeName = "CoverOpenState";
scanner->getPanelLeds().setStatus(LedStatus::CoverOpen);
}
FsmState *CoverOpenState::on_event(ScanEvent event)
{
LOG("CoverOpenState on_event %d \n", event);
if (event == S_EVT_COVER_CLOSED)
{
if (!scanner->getSensor().isPaperAtScan())
{
std::this_thread::sleep_for(std::chrono::seconds(1));
scanner->reset();
return FsmStateManagerEx<InitState>::GetState();
}
else
{
return FsmStateManagerEx<ErrorJamState>::GetState();
}
}
else if (event == S_EVT_CLEAR_ERR)
{
return FsmStateManagerEx<InitState>::GetState();
}
return this;
}
InitState::InitState()
{
}
FsmState *InitState::on_event(ScanEvent event)
{
LOG("InitState on_event %d \n", event);
if (!(scanner->getSensor().isCoverClosed()))
{
return FsmStateManagerEx<CoverOpenState>::GetState();
}
else if (scanner->getSensor().isPaperStandby())
{
LOG("------------------有纸\r\n");
return FsmStateManagerEx<PaperReadyState>::GetState();
}
else if ((scanner->getSensor().isPaperAtScan()))
{
LOG("------------------卡纸\r\n");
return FsmStateManagerEx<ErrorJamState>::GetState();
}
else
LOG("---------扫描仪已经准备完成------\r\n");
return FsmStateManagerEx<StandbyState>::GetState();
}
void InitState::initial()
{
LOG("InitState 999 \n");
typeName = "InitState"; //啥用?
scanner->put(S_EVT_NORES);
}
void ErrorJamState::initial()
{
LOG("ErrorJamState \n");
typeName = "ErrorJamState";
scanner->getPanelLeds().setStatus(LedStatus::Abnormal);
}
void ErrorJamState::doPaper_pullout()
{
scanner->paper_pullout();
}
FsmState *ErrorJamState::on_event(ScanEvent event)
{
//LOG("ErrorJamState on_event %d \n", event);
if (scanner->getSensor().isCoverClosed() && !scanner->getSensor().isPaperStandby() && !scanner->getSensor().isPaperIn())
{
return FsmStateManagerEx<StandbyState>::GetState();
}
else if (event == S_EVT_COVER_OPENED)
{
return FsmStateManagerEx<CoverOpenState>::GetState();
}
else if (event == S_EVT_PAPER_PULLOUT) // && scanner->GetIsDoublePaper()
{
scanner->paper_pullout();
return this;
}
else if (event == S_EVT_CLEAR_ERR)
{
if (!scanner->getSensor().isCoverClosed())
{
return FsmStateManagerEx<CoverOpenState>::GetState();
}
else //if (scanner->getSensor().isPaperStandby() && !scanner->getSensor().isPaperIn())
{
//LOG("ErrorJamState GetIsDoublePaper %s \n", scanner->GetIsDoublePaper() ? "TRUE" : "FALSE");
//LOG("ErrorJamState GetIsJamPaper %s \n", scanner->GetIsJamPaper() ? "TRUE" : "FALSE");
if (!scanner->GetIsDoublePaper() && !scanner->GetIsJamPaper() && !scanner->getSensor().isPaperAtScan())
{
if (scanner->getSensor().isPaperStandby())
return FsmStateManagerEx<PaperReadyState>::GetState();
else
return FsmStateManagerEx<StandbyState>::GetState();
}
}
}
return this;
}
void PaperReadyState::initial()
{
LOG("PaperReadyState setStatus(PanelLeds::Ready) \n");
typeName = "PaperReadyState";
scanner->getPanelLeds().setStatus(LedStatus::Ready);
}
FsmState *PaperReadyState::on_event(ScanEvent event)
{
LOG("FsmState PaperReadyState on_event %d \n",event);
if (event == S_EVT_COVER_OPENED)
{
return FsmStateManagerEx<CoverOpenState>::GetState();
}
else if (event == S_EVT_PAPER_NOT_STANDBY)
{
if (!scanner->getSensor().isPaperStandby())
{
return FsmStateManagerEx<StandbyState>::GetState();
}
}
else if (event == S_EVT_PAPER_AT_SCAN)
{
return FsmStateManagerEx<ErrorState>::GetState();
}
else if (event == S_EVT_START_SCAN)
{
return FsmStateManagerEx<ScanningState>::GetState();
}
return this;
}
void ErrorState::initial()
{
LOG("ErrorState \n");
typeName = "ErrorState";
scanner->getPanelLeds().setStatus(LedStatus::Abnormal);
}
FsmState *ErrorState::on_event(ScanEvent event)
{
LOG("ErrorState on_event %d \n", event);
if (event == S_EVT_COVER_OPENED)
{
return FsmStateManagerEx<CoverOpenState>::GetState();
}
if (scanner->getSensor().isCoverClosed() && !scanner->getSensor().isPaperStandby() && scanner->getSensor().isPaperIn())
{
return FsmStateManagerEx<StandbyState>::GetState();
}
else if (event == S_EVT_PAPER_STANDBY)
{
LOG("ErrorState on_event S_EVT_PAPER_STANDBY\n");
if (scanner->getSensor().isPaperStandby()) //有纸 且没卡纸
{
return FsmStateManagerEx<PaperReadyState>::GetState();
}
else
{
scanner->ResetJamIn();
return FsmStateManagerEx<StandbyState>::GetState();
}
}
else if (event == S_EVT_CLEAR_ERR)
{
if (!scanner->getSensor().isCoverClosed()) //没关盖
{
return FsmStateManagerEx<CoverOpenState>::GetState();
}
else if (!scanner->GetIsJamIn())
{
if (scanner->getSensor().isPaperStandby()) //有纸 且没卡纸
{
if (!scanner->getSensor().isPaperIn())
return FsmStateManagerEx<PaperReadyState>::GetState();
}
else
{
return FsmStateManagerEx<StandbyState>::GetState();
}
}
}
return this;
}
void ScanningState::initial()
{
LOG("ScanningState \n");
typeName = "ScanningState";
scanner->getPanelLeds().setStatus(LedStatus::Scanning);
scanner->startScan();
}
FsmState *ScanningState::on_event(ScanEvent event)
{
LOG("ScanningState on_event \n");
if (event == S_EVT_COVER_IN_OPEN)
{
return FsmStateManagerEx<CoverOpenState>::GetState();
}
else if (event == S_EVT_STOP_SCAN)
{
LOG("ScanningState call for %d \n", event);
scanner->getPanelLeds().setStatus(LedStatus::StopScan);
scanner->stop_scan();
auto ret = scanner->getSensor().isPaperStandby() ? FsmStateManagerEx<PaperReadyState>::GetState() : FsmStateManagerEx<StandbyState>::GetState();
return ret;
// if (scanner->getSensor().isPaperStandby())
// {
// return FsmStateManagerEx<PaperReadyState>::GetState();
// }
// else
// {
// return FsmStateManagerEx<StandbyState>::GetState();
// }
}
else if (event == S_EVT_COVER_OPENED)
{
//scanner->stop_scan();
scanner->emergency_stop(S_EVT_COVER_OPENED);
return FsmStateManagerEx<CoverOpenState>::GetState();
}
else if (event == S_EVT_DOUBLEPAPER)
{
scanner->SetIsDoublePaper(true);
scanner->emergency_stop(1);
LOG("\nScanningState S_EVT_DOUBLEPAPER %s \n",GetCurrentTimeStamp(2).c_str());
writesyslog(LOG_INFO,"double paper error\n");
return FsmStateManagerEx<ErrorJamState>::GetState();
}
else if (event == S_EVT_JAM_IN)
{
scanner->emergency_stop(0);
LOG("ScanningState S_EVT_JAM_IN \n");
return FsmStateManagerEx<ErrorState>::GetState();
}
else if (event == S_EVT_JAM_OUT)
{
scanner->emergency_stop(0);
LOG("ScanningState S_EVT_JAM_OUT \n");
return FsmStateManagerEx<ErrorJamState>::GetState();
}
else if (event == S_EVT_PAPER_AT_SCAN)
{
//ToDo:add notifyAll operation
}
else if (event == S_EVT_PAPER_NOT_AT_SCAN)
{
//ToDo:add notifyAll operation
}
else if (event == S_EVT_SAMPLE_ERR)
{
scanner->stop_scan();
return FsmStateManagerEx<ErrorState>::GetState();
}
else if (event == S_EVT_PAPER_NOT_STANDBY)
{
std::this_thread::sleep_for(chrono::milliseconds(100));
if(!scanner->getSensor().isPaperStandby())
{
scanner->stop_scan();
return FsmStateManagerEx<StandbyState>::GetState();
}
}
return this;
}

148
FsmState.h Normal file
View File

@ -0,0 +1,148 @@
#pragma once
#include <memory>
#include <map>
#include <typeinfo>
#include <string>
#include "scanservices_utils.h"
#include "utilsfunc.h"
class Scanner;
enum ScanEvent {
S_EVT_NORES = 0x0,
S_EVT_SCAN_FINISHED = 0x2,
S_EVT_CLEAR_ERR = 0x03,
S_EVT_PAPER_PULLOUT = 0x05,
S_EVT_COVER_OPENED = 0x01,
S_EVT_COVER_CLOSED = 0x102,
S_EVT_PAPER_AT_SCAN = 0x08,
S_EVT_PAPER_NOT_AT_SCAN = 0x106,
S_EVT_DOUBLEPAPER = 0x110,
S_EVT_NOT_DOUBLEPAPER = 0x111,
S_EVT_START_SCAN = 0x45,
S_EVT_STOP_SCAN = 0x46,
S_EVT_SCAN_STARTED = 0x112,
S_EVT_SCAN_STOPPED = 0x113,
S_EVT_JAM_IN = 0x114,
S_EVT_JAM_OUT = 0x115,
S_EVT_SAMPLE_ERR = 0x116,
S_EVT_COVER_IN_OPEN = 0x117,
S_EVT_ERROR_PICKING = 0x4,
S_EVT_ERROR_JAM = 0x8,
S_EVT_ERROR_DOUBLEPAPER = 0x10,
S_EVT_ERROR_STAPLE = 0x20,
S_EVT_ERROR_FPGA = 0x44,
S_EVT_HAVING_IMAGE = 0x47,
S_EVT_ONE_PAPER_END = 0x59,
S_EVT_PAPER_NOT_STANDBY = 0,//?
S_EVT_PAPER_STANDBY = 0 //?
};
class FsmState
{
public:
FsmState();
virtual ~FsmState();
virtual FsmState* on_event(ScanEvent event) = 0;
virtual void initial() {}
static void setScanner(Scanner* scan) {
scanner = scan;
}
std::string typeName = "FsmState";
protected:
static Scanner* scanner;
};
class FsmStateManager
{
protected:
static std::map<std::string, std::shared_ptr<FsmState>> fsmStates;
};
template<typename T>
class FsmStateManagerEx : public FsmStateManager
{
public:
static FsmState* GetState()
{
std::string type_name = typeid(T).name();
std::map<std::string, std::shared_ptr<FsmState>>::iterator iter = fsmStates.find(type_name);
if (iter == fsmStates.end()) {
fsmStates.insert(std::pair<std::string, std::shared_ptr<FsmState>>(type_name, std::shared_ptr<FsmState>(new T)));
}
fsmStates[type_name]->initial();
return fsmStates[type_name].get();
}
};
//????
class StandbyState :public FsmState {
public:
virtual void initial();
virtual FsmState* on_event(ScanEvent event);
protected:
virtual void doReset();
};
//?????
class CoverOpenState : public FsmState {
public:
virtual void initial();
virtual FsmState* on_event(ScanEvent event);
};
class InitState :public FsmState {
public:
InitState();
virtual FsmState* on_event(ScanEvent event);
virtual void initial();
};
class ErrorJamState : public FsmState {
public:
ErrorJamState() {}
virtual void initial();
virtual FsmState* on_event(ScanEvent event);
void doPaper_pullout();
};
class PaperReadyState : public FsmState {
public:
PaperReadyState() {}
virtual void initial();
FsmState* on_event(ScanEvent event);
};
class ErrorState : public FsmState {
public:
ErrorState() {}
virtual void initial();
virtual FsmState* on_event(ScanEvent event);
};
class ScanningState : public FsmState {
public:
ScanningState() {}
virtual void initial();
virtual FsmState* on_event(ScanEvent event);
};

74
Gpio.cpp Normal file
View File

@ -0,0 +1,74 @@
//
// Created by yingluo907 on 2019/4/11.
//
#include "Gpio.h"
#include "DevUtil.h"
#define IOPATH "%s/gpio%d/%s"
const std::string Gpio::falling = "falling";
const std::string Gpio::rising = "rising";
const std::string Gpio::both = "both";
const std::string Gpio::none = "none";
const std::string Gpio::in = "in";
const std::string Gpio::out = "out";
Gpio::Gpio(int port)
{
this->port = port;
path_value = string_format(IOPATH, path_gpiobase.c_str(), port, path_value.c_str());
path_edge = string_format(IOPATH, path_gpiobase.c_str(), port, path_edge.c_str());
path_direction = string_format(IOPATH, path_gpiobase.c_str(), port, path_direction.c_str());
path_active_low = string_format(IOPATH, path_gpiobase.c_str(), port, path_active_low.c_str());
}
int Gpio::getPort()
{
return port;
}
void Gpio::setValue(GpioLevel level)
{
write_dev(path_value, level);
}
Gpio::GpioLevel Gpio::getValue() {
return (Gpio::GpioLevel)read_dev_i(path_value);
}
std::string Gpio::getDirection()
{
return read_dev_s(path_direction);
}
void Gpio::setDirection(std::string direction)
{
write_dev(path_direction, direction);
}
void Gpio::setActive(GpioLevel level)
{
write_dev(path_active_low, level);
}
Gpio::GpioLevel Gpio::getActive()
{
return (GpioLevel)read_dev_i(path_active_low);
}
void Gpio::setEdge(std::string edge)
{
write_dev(path_edge, edge);
}
std::string Gpio::getEdge()
{
return read_dev_s(path_edge);
}
GpioOut::GpioOut(int port) :
Gpio(port)
{
setDirection(out);
}

56
Gpio.h Normal file
View File

@ -0,0 +1,56 @@
//
// Created by yingluo907 on 2019/4/11.
//
#ifndef HGSCANSERVICE_GPIO_H
#define HGSCANSERVICE_GPIO_H
#include <string>
class Gpio {
public:
enum GpioLevel {
Low,
High
};
public:
static const std::string falling;
static const std::string rising;
static const std::string both;
static const std::string none;
static const std::string in;
static const std::string out;
public:
Gpio(int port);
int getPort();
void setValue(GpioLevel level);
GpioLevel getValue();
std::string getDirection();
void setDirection(std::string direction);
void setActive(GpioLevel level);
GpioLevel getActive();
void setEdge(std::string edge);
std::string getEdge();
std::string getValuePath() {
return path_value;
}
private:
const std::string path_gpiobase = "/sys/class/gpio";
int port;
std::string path_value = "value";
std::string path_edge = "edge";
std::string path_direction = "direction";
std::string path_active_low = "active_low";
};
class GpioOut : public Gpio
{
public:
GpioOut(int port);
};
#endif //HGSCANSERVICE_GPIO_H

1142
HCamDevice.cpp Normal file

File diff suppressed because it is too large Load Diff

165
HCamDevice.h Normal file
View File

@ -0,0 +1,165 @@
/*
* @Author: your name
* @Date: 2022-01-11 09:41:39
* @LastEditTime: 2022-11-18 14:09:29
* @LastEditors: Zhaozhonmin 1656963645@qq.com
* @Description: koroFileHeader查看配置 : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: \zynq_MSS\capimage\HCamDevice.h
*/
#pragma once
#include <string>
#include <linux/videodev2.h>
// #include "../cameraConfig.h"
//#include "../CameraParams.h"
#include <functional>
#include <memory>
#include <thread>
union CamZ_Reg_4
{
int value;
struct
{
unsigned int unuse_0 : 2;
unsigned int color_mode : 1;
unsigned int unuse_1 : 2;
unsigned int encode_divide : 3;
unsigned int encode_divide_mode : 1;
unsigned int unuse_2 : 5;
unsigned int en_adc_cfg : 1;
unsigned int clr_exp : 1;
unsigned int soft_reset : 1;
unsigned int en_pattern : 1;
unsigned int line_enable : 1; //不使用
unsigned int byte_sync : 1;
unsigned int adc_config_all : 1 ;
unsigned int adc_select : 5 ;
unsigned int test_pattern : 1;
unsigned int gpio1 : 1 ;
unsigned int gpio2 : 1 ;
unsigned int reserved : 3;
}params;
};
#define adcRegSize 20
#define REG_NUM 14
typedef std::function<void(uint32_t)> GetImgProcSize;
typedef std::function<void(uint32_t)> GetImgFormat;
typedef std::function<void(uint32_t)> GetCameraEvents;
typedef std::function<void(int)> ReLoadCorrecEvent;
//class Camconfig;
class HCamDevice
{
public:
HCamDevice();
~HCamDevice();
int open_video();
int close_video();
void HtCamStartVideoCapturing();
void HtCamStopVideoCapturing();
int HtCamWaitVideoCapture(int msTimeout);
int HtCamReadCaptureFrame(void **pbuf, int timeout);
int width() { return v4lWidth; }
int height() { return v4lHeight; }
uint32_t HtCamReadFpgaRegs(uint8_t reg_addr);
void HtCamWriteFpgaRegs(uint8_t reg_addr, uint32_t reg_value);
void HtCamChangeTriggerInAndEXt(int in_out);
void HtCamSetTriggerMode(int val);
int HtCamGetTriggerMode();
int HtCamGetColorMode();
uint32_t HtCamReadPsRegs(uint8_t reg_addr);
void HtCamWritePsRegs(uint8_t reg_addr, uint32_t reg_value);
void savePsReg();
void HtCamWriteAllADC();
void HtCamInitADCReg();
void HtCamWriteADCReg(uint8_t addr,uint8_t data);
void HtCamReadADCReg(uint8_t addr, uint8_t *data);
void set_get_imgSize_event(GetImgProcSize _getImgProcSize);
void set_get_imgFormat_event(GetImgFormat _getImgFormat);
void set_reload_correct_event(ReLoadCorrecEvent _reLoadCorrectEvent);
void set_get_CameraEvents_event(GetCameraEvents _getCameraEvents);
void HtCamOverClockClear(); // 清除切换超频标志位
uint8_t getADCReg(int addr);
void setADCReg(int addr , uint8_t value);
void saveADCReg();
// void setConfig(Camconfig* _config){config = _config;}
void HtCamChangeMonoStartSample(int start_sample);
private:
int init_fd();
int init_sample();
int init_capture();
int init_video_buffer();
int init_dev();
void init_ps_regs();
void HtCamSwitchSampleModes(unsigned char mode);
void HtCamChangeExposureValue(unsigned int value);
void HtCamExitVideoCapturing();
void HtCamResizeBuffer(int width, int height, int number);
void HtCamChangeAdjustSpTime(uint32_t sp_time_gap, uint32_t sp_time_rw);
void HtCamChangeAdjustPhase(uint16_t times, uint8_t dir);
int HtCamStartSampling();
int HtCamStopSampling();
void HtCamChangeDpi(int dpi);
bool HtCamPsDpiChange(int dpi);
void HtCamImageProcessChange();
int HtCamEventWorkThread(void);
struct captureBuffer
{
void *start;
int dmabuf_fd;
uint32_t length;
};
const unsigned int phyBaseAddr = 0x40010000;
const unsigned int AddrMapSize = 0x100;
unsigned int *virBaseAddr;
int memfd;
std::string subDeviceName;
int subDevicefd;
std::string videoDevName = "/dev/video0";
int videofd;
unsigned int v4lWidth;
unsigned int v4lHeight;
unsigned int v4lBufferCount;
int nplanes;
int drivertype;
enum v4l2_buf_type v4l2buftype;
enum v4l2_memory v4l2memtype;
struct captureBuffer *captureBufers;
int lastSucceedBufferIndex;
uint32_t pPsReg[ REG_NUM + 1] = {0};
uint8_t pADCReg[adcRegSize];
GetImgProcSize getImgProcSize;
GetImgFormat getImgFormat;
GetCameraEvents getCameraEvents = nullptr;
ReLoadCorrecEvent reLoadCorrectEvent = nullptr;
std::shared_ptr<std::thread> event_thread = nullptr;
//Camconfig* config = nullptr;
};

113
HGUsb.cpp Normal file
View File

@ -0,0 +1,113 @@
#include "HGUsb.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
HGUsb::HGUsb()
{
m_usbBulkIn.reset(new UsbEndPoint(UsbEndPoint::EndpointType::EP_Bulk_In));
m_usbBulkOut.reset(new UsbEndPoint(UsbEndPoint::EndpointType::EP_Bulk_Out));
}
HGUsb::~HGUsb()
{
if (m_usbBulkIn.get())
m_usbBulkIn.reset();
if (m_usbBulkOut.get())
m_usbBulkOut.reset();
if (m_usbCtl.get())
m_usbInt.reset();
if (m_usbInt.get())
m_usbInt.reset();
}
int HGUsb::open()
{
int ret = (int)HGUSB_ErrorCode::HG_USBSuccess;
if (is_connect())
{
LOG("PC has connected USB\n");
ret = m_usbBulkIn->open();
ret = m_usbBulkOut->open();
}
else
{
ret = (int)HGUSB_ErrorCode::HG_USBPCUnConnected;
LOG("PC havn't connected USB\n");
}
return ret;
}
void HGUsb::close()
{
m_usbBulkIn->close();
m_usbBulkOut->close();
}
int HGUsb::read_bulk(void *pdata, int length)
{
int ret = 0;
if (!pdata)
return (int)HGUSB_ErrorCode::HG_USBInvalidePtr;
if (m_usbBulkOut.get())
{
ret = m_usbBulkOut->read(pdata, length);
}
return ret;
}
int HGUsb::write_bulk(void *pdata, int length)
{
int ret = 0;
if (!pdata)
return (int)HGUSB_ErrorCode::HG_USBInvalidePtr;
if (m_usbBulkIn.get())
{
ret = m_usbBulkIn->write(pdata, length);
return ret;
}
}
int HGUsb::write_int(void *pdata, int length)
{
int ret = 0;
if (!pdata)
return (int)HGUSB_ErrorCode::HG_USBInvalidePtr;
if (m_usbInt.get())
m_usbInt->write(pdata, length);
return ret;
}
int HGUsb::write_control(int rtype, int req, int value, int index, int len, void *data)
{
int ret = 0;
if (!data)
return (int)HGUSB_ErrorCode::HG_USBInvalidePtr;
if (m_usbCtl.get())
{
//need to transfer protocol,did not realized
}
return ret;
}
bool HGUsb::is_connect()
{
//DEBUG("check if PC and Scanner connected ");
int fd, n;
char buf[20] = "\0";
fd = ::open(STATE_PATH, O_RDONLY);
read(fd, buf, 20);
::close(fd);
return strstr(buf, "CONFIGURED");
}
//
bool HGUsb::is_open()
{
return m_usbBulkIn->is_open() && m_usbBulkOut->is_open();
}

24
HGUsb.h Normal file
View File

@ -0,0 +1,24 @@
#include <memory>
#include "UsbEndpoint.h"
using namespace std;
class HGUsb
{
public:
HGUsb();
~HGUsb();
int open();
void close();
int read_bulk(void *pdata, int length);
int write_bulk(void *pdata, int length);
int write_int(void *pdata, int length);
int write_control(int rtype, int req, int value, int index, int len, void *data);
bool is_connect();
bool is_open();
private:
std::unique_ptr<UsbEndPoint> m_usbBulkIn;
std::unique_ptr<UsbEndPoint> m_usbBulkOut;
std::unique_ptr<UsbEndPoint> m_usbInt;
std::unique_ptr<UsbEndPoint> m_usbCtl;
};

62
ICapturer.h Normal file
View File

@ -0,0 +1,62 @@
#pragma once
#include <atomic>
#include <memory>
#include "BlockingQueue.h"
#include "scanservices_utils.h"
#include "gvideo.h"
#include "HCamDevice.h"
class FpgaComm;
class ICapturer
{
public:
ICapturer() {}
virtual ~ICapturer() {}
virtual void SetParent(void *scanner) = 0;
virtual void open() = 0;
virtual void snap() = 0;
virtual void stopsnap(bool autosize) = 0;
virtual void close() = 0;
virtual int read(int addr) = 0;
virtual void *readFrameTest(int timeout) = 0;
virtual void UpdateScanParam(HG_ScanConfiguration config) = 0;
virtual void createCorrect(int correctmode) = 0;
virtual void setFPGATriggerMode(bool autotrigger, int delay) = 0;
virtual void setFanMode(int mode) = 0;
virtual void fpgaReload() = 0;
virtual bool capturerImage() = 0;
virtual void waitsnapdone(int state) = 0;
virtual bool IsImageQueueEmpty() = 0;
virtual void resetimageremain() = 0;
virtual std::atomic_int &getimageremain() = 0;
virtual void clearimages() = 0;
virtual void setScanFlag(bool brun) = 0;
protected:
std::shared_ptr<FpgaComm> m_capFpageregs;
BlockingQueue<V4L2_DATAINFO> m_v4l2data;
std::shared_ptr<HCamDevice> video;//Capturer 类内部自己初始化
HG_ScanConfiguration m_config;
};

5
IPreproc.cpp Normal file
View File

@ -0,0 +1,5 @@
#include "IPreproc.h"
IPreproc::IPreproc(void){}
IPreproc::~IPreproc(void){}

13
IPreproc.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
#include <vector>
//#include <opencv2/opencv.hpp>
class IPreproc
{
public:
IPreproc(void);
virtual ~IPreproc(void);
//virtual int preprocess(cv::Mat& mat,void* unused=nullptr) = 0;
};

44
IScanner.h Normal file
View File

@ -0,0 +1,44 @@
#pragma once
#include "scanservices_utils.h"
#include <string>
#include "BlockingQueue.h"
class IScanner
{
public:
IScanner(/* args */) {}
virtual ~IScanner() {}
virtual void StartScan(int scancount) = 0;
virtual void StopScan() = 0;
virtual void ConfigScanParam(HG_ScanConfiguration config) = 0;
virtual bool FeederLoaded() = 0;
virtual std::string GetSerial() = 0;
virtual void SetSerial(std::string serial) = 0;
virtual std::string GetFWVersion() = 0;
virtual void SetFwVersion(std::string fwversion) = 0;
virtual int GetRollerNum() = 0;
virtual void ClearRollerNum() = 0;
virtual void InitScanner() = 0;
virtual void ClearImages() = 0;
virtual HG_JpegCompressInfo GetImage() = 0;
virtual HG_Msg GetEvent() = 0;
virtual void ClearErrorEvents() = 0;
virtual void ClearHWError() = 0;
virtual bool GetImagequeueEmpty() = 0;
virtual bool GetEventQueueEmpty() = 0;
virtual HG_JpegCompressInfo GetFrontImage() = 0;
virtual HG_Msg GetEventFront() = 0;
virtual void CreatCorrectData(int correctmode) = 0;
virtual bool IsScanning() = 0;
virtual void SetFlatParam(int type, int *value) = 0;
virtual CaptureParams GetCaptureParams() = 0;
virtual void UpdateScanInfo(int type, void *data) = 0;
virtual ScannerScanInfo GetScanInfo() = 0;
virtual void SetLEDStatus(LedStatus status) = 0;
protected:
BlockingQueue<HG_JpegCompressInfo> m_images;
BlockingQueue<HG_Msg> m_scannerEvents;
std::string m_serial;
std::string m_fwversion;
};

350
ImageProcess_Public.cpp Normal file
View File

@ -0,0 +1,350 @@
// #include "ImageProcess_Public.h"
// #include "opencv2/imgproc/types_c.h"
// #include "opencv2/imgproc/imgproc_c.h"
// namespace hg
// {
// void convexHull(const std::vector<cv::Point>& src, std::vector<cv::Point>& dst, bool clockwise)
// {
// CvMemStorage* storage = cvCreateMemStorage(); //
// CvSeq* ptseq = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2, sizeof(CvContour), sizeof(CvPoint), storage); //ptseqstorage
// //将src的点集填充至ptseq
// for (const cv::Point& item : src)
// {
// CvPoint p;
// p.x = item.x;
// p.y = item.y;
// cvSeqPush(ptseq, &p);
// }
// //获取轮廓点
// CvSeq* hull = cvConvexHull2(ptseq, nullptr, clockwise ? CV_CLOCKWISE : CV_COUNTER_CLOCKWISE, 0);
// if (hull == nullptr)
// {
// //释放storage
// cvReleaseMemStorage(&storage);
// return;
// }
// //填充dst
// dst.clear();
// for (int i = 0, hullCount = hull->total; i < hullCount; i++)
// dst.push_back(**CV_GET_SEQ_ELEM(CvPoint*, hull, i));
// //释放storage
// cvReleaseMemStorage(&storage);
// }
// #define R_COLOR 255
// void fillConvexHull(cv::Mat& image, const std::vector<cv::Point>& points)
// {
// uint index_top = 0;
// uint index_bottom = 0;
// for (size_t i = 0, length = points.size(); i < length; i++)
// {
// if (points[i].y < points[index_top].y)
// index_top = i;
// if (points[i].y > points[index_bottom].y)
// index_bottom = i;
// }
// std::vector<cv::Point> edge_left;
// uint temp = index_top;
// while (temp != index_bottom)
// {
// edge_left.push_back(points[temp]);
// temp = (temp + points.size() - 1) % points.size();
// }
// edge_left.push_back(points[index_bottom]);
// std::vector<cv::Point> edge_right;
// temp = index_top;
// while (temp != index_bottom)
// {
// edge_right.push_back(points[temp]);
// temp = (temp + points.size() + 1) % points.size();
// }
// edge_right.push_back(points[index_bottom]);
// std::vector<int> left_edge_x;
// std::vector<int> left_edge_y;
// for (size_t i = 0, length = edge_left.size() - 1; i < length; i++)
// {
// int y_top = edge_left[i].y;
// int x_top = edge_left[i].x;
// int y_bottom = edge_left[i + 1].y;
// int x_bottom = edge_left[i + 1].x;
// for (int y = y_top; y < y_bottom; y++)
// if (y >= 0 && y_top != y_bottom && y < image.rows)
// {
// left_edge_x.push_back(((x_bottom - x_top) * y + x_top * y_bottom - x_bottom * y_top) / (y_bottom - y_top));
// left_edge_y.push_back(y);
// }
// }
// size_t step = image.step;
// unsigned char* ptr;
// ptr = image.data + static_cast<uint>(left_edge_y[0]) * step;
// for (size_t i = 0, length = left_edge_x.size(); i < length; i++)
// {
// int pix = left_edge_x[i];
// if (pix < image.cols - 1 && pix > 0)
// memset(ptr + i * step, R_COLOR, static_cast<size_t>((pix + 1) * image.channels()));
// }
// std::vector<int> right_edge_x;
// std::vector<int> right_edge_y;
// for (size_t i = 0, length = edge_right.size() - 1; i < length; i++)
// {
// int y_top = edge_right[i].y;
// int x_top = edge_right[i].x;
// int y_bottom = edge_right[i + 1].y;
// int x_bottom = edge_right[i + 1].x;
// for (int y = y_top; y < y_bottom; y++)
// if (y_top != y_bottom && y < image.rows && y >= 0)
// {
// right_edge_x.push_back(((x_bottom - x_top) * y + x_top * y_bottom - x_bottom * y_top) / (y_bottom - y_top));
// right_edge_y.push_back(y);
// }
// }
// ptr = image.data + static_cast<uint>(right_edge_y[0]) * step;
// for (size_t i = 0, length = right_edge_x.size(); i < length; i++)
// {
// int pix = right_edge_x[i];
// if (pix < image.cols - 1 && pix > 0)
// memset(ptr + i * step + pix * image.channels(), R_COLOR, step - static_cast<size_t>(pix * image.channels()));
// }
// if (edge_left[0].y > 0)
// memset(image.data, R_COLOR, static_cast<size_t>(edge_left[0].y) * step);
// if (edge_left.back().y < image.rows - 1)
// memset(image.data + static_cast<size_t>(edge_left.back().y) * step, R_COLOR,
// static_cast<size_t>(image.rows - edge_left.back().y) * step);
// }
// void fillPolys(cv::Mat& image, const std::vector<std::vector<cv::Point>>& contours, const cv::Scalar& color)
// {
// if (contours.empty()) return;
// size_t count = contours.size();
// cv::Point** pointss = new cv::Point*[count];
// int* npts = new int[count];
// for (size_t i = 0; i < count; i++)
// {
// size_t length = contours[i].size();
// npts[i] = length;
// pointss[i] = new cv::Point[length];
// for (size_t j = 0; j < length; j++)
// pointss[i][j] = contours[i][j];
// }
// cv::fillPoly(image, const_cast<const cv::Point**>(pointss), npts, count, color);
// for (size_t i = 0; i < count; i++)
// delete[] pointss[i];
// delete[] pointss;
// delete[] npts;
// }
// void findContours(const cv::Mat& src, std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& hierarchy, int retr, int method, cv::Point offset)
// {
// #if CV_VERSION_REVISION == 6
// CvMat c_image = src;
// #else
// CvMat c_image;
// c_image = cvMat(src.rows, src.cols, src.type(), src.data);
// c_image.step = src.step[0];
// c_image.type = (c_image.type & ~cv::Mat::CONTINUOUS_FLAG) | (src.flags & cv::Mat::CONTINUOUS_FLAG);
// #endif
// cv::MemStorage storage(cvCreateMemStorage());
// CvSeq* _ccontours = nullptr;
// #if CV_VERSION_REVISION == 6
// cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, CvPoint(offset));
// #else
// cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, CvPoint{ offset.x, offset.y });
// #endif
// if (!_ccontours)
// {
// contours.clear();
// return;
// }
// cv::Seq<CvSeq*> all_contours(cvTreeToNodeSeq(_ccontours, sizeof(CvSeq), storage));
// size_t total = all_contours.size();
// contours.resize(total);
// cv::SeqIterator<CvSeq*> it = all_contours.begin();
// for (size_t i = 0; i < total; i++, ++it)
// {
// CvSeq* c = *it;
// reinterpret_cast<CvContour*>(c)->color = static_cast<int>(i);
// int count = c->total;
// int* data = new int[static_cast<size_t>(count * 2)];
// cvCvtSeqToArray(c, data);
// for (int j = 0; j < count; j++)
// {
// contours[i].push_back(cv::Point(data[j * 2], data[j * 2 + 1]));
// }
// delete[] data;
// }
// hierarchy.resize(total);
// it = all_contours.begin();
// for (size_t i = 0; i < total; i++, ++it)
// {
// CvSeq* c = *it;
// int h_next = c->h_next ? reinterpret_cast<CvContour*>(c->h_next)->color : -1;
// int h_prev = c->h_prev ? reinterpret_cast<CvContour*>(c->h_prev)->color : -1;
// int v_next = c->v_next ? reinterpret_cast<CvContour*>(c->v_next)->color : -1;
// int v_prev = c->v_prev ? reinterpret_cast<CvContour*>(c->v_prev)->color : -1;
// hierarchy[i] = cv::Vec4i(h_next, h_prev, v_next, v_prev);
// }
// storage.release();
// }
// cv::RotatedRect getBoundingRect(const std::vector<cv::Point>& contour)
// {
// if (contour.empty()) return {};
// cv::RotatedRect rect = minAreaRect(contour);
// printf("!!!!!!!!!!!!!!!!!!rect width = %f height = %f \n",rect.size.width,rect.size.height);
// if (rect.angle < -45)
// {
// rect.angle += 90;
// float temp = rect.size.width;
// rect.size.width = rect.size.height;
// rect.size.height = temp;
// }
// if (rect.angle > 45)
// {
// rect.angle -= 90;
// float temp = rect.size.width;
// rect.size.width = rect.size.height;
// rect.size.height = temp;
// }
// return rect;
// }
// std::vector<cv::Point> getMaxContour(const std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i>& hierarchy)
// {
// std::vector<cv::Point> maxContour;
// if (contours.size() < 1) return {};
// for (size_t i = 0, length = hierarchy.size(); i < length; i++)
// if (hierarchy[i][3] == -1)
// for (const auto &item : contours[i])
// maxContour.push_back(item);
// return maxContour;
// }
// std::vector<cv::Point> getVertices(const cv::RotatedRect& rect)
// {
// cv::Point2f box[4];
// rect.points(box);
// std::vector<cv::Point> points;
// for (int i = 0; i < 4; i++)
// points.push_back(cv::Point(box[i]));
// return points;
// }
// void polyIndent(std::vector<cv::Point>& points, const cv::Point& center, int indent)
// {
// static cv::Point zero(0, 0);
// for (cv::Point& item : points)
// {
// #if 0
// cv::Point vec = item - center;
// if (vec != zero)
// {
// int length = vec.x * vec.x + vec.y * vec.y;
// float x = cv::sqrt(static_cast<float>(vec.x * vec.x / length)) * indent;
// float y = cv::sqrt(static_cast<float>(vec.y * vec.y / length)) * indent;
// if (vec.x < 0) x *= -1.0f;
// if (vec.y < 0) y *= -1.0f;
// item.x -= static_cast<int>(x);
// item.y -= static_cast<int>(y);
// }
// #else
// if (item.x > center.x)
// item.x -= indent;
// else
// item.x += indent;
// if (item.y > center.y)
// item.y -= indent;
// else
// item.y += indent;
// #endif
// }
// }
// cv::Mat transforColor(const cv::Mat& src)
// {
// if (src.channels() == 1) return src.clone();
// std::vector<cv::Mat> channels(3);
// cv::split(src, channels);
// cv::Mat temp, dst;
// bitwise_or(channels[0], channels[1], temp);
// bitwise_or(channels[2], temp, dst);
// temp.release();
// for (cv::Mat& index : channels)
// index.release();
// return dst;
// }
// void threshold_Mat(const cv::Mat& src, cv::Mat& dst, double thre)
// {
// if (src.channels() == 3)
// {
// #ifdef USE_ONENCL
// if (cl_res.context)
// transforColor_threshold_opencl(src, dst, static_cast<uchar>(thre));
// else
// #endif
// {
// cv::Mat gray = transforColor(src);
// cv::threshold(gray, dst, thre, 255, cv::THRESH_BINARY);
// gray.release();
// }
// }
// else
// cv::threshold(src, dst, thre, 255, cv::THRESH_BINARY);
// }
// cv::Point warpPoint(const cv::Point& p, const cv::Mat& warp_mat)
// {
// double src_data[3] = { static_cast<double>(p.x), static_cast<double>(p.y), 1 };
// cv::Mat src(3, 1, warp_mat.type(), src_data); //warp_mat.type() == CV_64FC1
// cv::Mat dst = warp_mat * src;
// double* ptr = reinterpret_cast<double*>(dst.data);
// return cv::Point(static_cast<int>(ptr[0]), static_cast<int>(ptr[1]));
// }
// int distanceP2P(const cv::Point& p1, const cv::Point& p2)
// {
// return cv::sqrt(cv::pow(p1.x - p2.x, 2) + cv::pow(p1.y - p2.y, 2));
// }
// float distanceP2L(const cv::Point& p, const cv::Point& l1, const cv::Point& l2)
// {
// //求直线方程
// int A = 0, B = 0, C = 0;
// A = l1.y - l2.y;
// B = l2.x - l1.x;
// C = l1.x * l2.y - l1.y * l2.x;
// //代入点到直线距离公式
// return ((float)abs(A * p.x + B * p.y + C)) / ((float)sqrtf(A * A + B * B));
// }
// }

130
ImageProcess_Public.h Normal file
View File

@ -0,0 +1,130 @@
// /*
// * ====================================================
// * 功能公共图像处理算法。部分功能可能会在ImageProcess里面多个类反复使用
// * 作者:刘丁维
// * 生成时间2020/4/21
// * 最近修改时间2020/4/21
// * 2021/07/12 v1.1 getBoundingRect中增加考虑纠正初始 angle > 90 的情况。
// * 2021/07/22 v1.2 convexHull中修复点集为空可能导致崩溃的BUG。
// * 版本号v1.2
// * ====================================================
// */
// #ifndef IMAGE_PROCESS_PUBLIC_H
// #define IMAGE_PROCESS_PUBLIC_H
// #include "opencv2/opencv.hpp"
// #include <vector>
// namespace hg
// {
// /*
// * 功能:计算源点集的凸多边形轮廓,输出轮廓点集
// * src: 源点集
// * dst: 目标点集
// * clockwise: true为顺时针排序false为逆时针排序
// */
// void convexHull(const std::vector<cv::Point>& src, std::vector<cv::Point>& dst, bool clockwise = false);
// /*
// * 功能:填充凸多边形,默认颜色为白色
// * image: 填充图像
// * points: 凸多边形轮廓点集(逆时针排序)
// */
// void fillConvexHull(cv::Mat& image, const std::vector<cv::Point>& points);
// /*
// * 功能:填充凹多边形
// * image: 填充图像
// * contours: 凹多边形轮廓点集(逆时针排序)
// * color: 填充颜色
// */
// void fillPolys(cv::Mat& image, const std::vector<std::vector<cv::Point>>& contours, const cv::Scalar& color);
// /*
// * 功能:获取连通区域轮廓
// * src: 源图像
// * contours: 结果轮廓集
// * hierarchy: 轮廓集的排序关系。与contours的数量对应受retr选项不同排序会有变化
// * retr: 轮廓集排序方式,默认为链式排序
// * method: 查找算法选择,默认为普通查找
// * offset: 查找起始点默认为0,0
// */
// void findContours(const cv::Mat& src, std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& hierarchy,
// int retr = cv::RETR_LIST, int method = cv::CHAIN_APPROX_SIMPLE, cv::Point offset = cv::Point(0, 0));
// /*
// * 功能:获取覆盖点集的最小外接矩形
// * contour: 点集
// * 返回值: 旋转矩形
// */
// cv::RotatedRect getBoundingRect(const std::vector<cv::Point>& contour);
// /*
// * 功能: 获取覆盖轮廓集的最小外接凸多边形轮廓
// * contours: 轮廓集(每个轮廓由点集组成)
// * hierarchy: 轮廓集中轮廓之间的关系。数量与contours对应
// * 返回值: 凸多边形轮廓点集
// */
// std::vector<cv::Point> getMaxContour(const std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i>& hierarchy);
// /*
// * 功能: 获取覆盖轮廓集的最小外接凸多边形轮廓
// * contours: 轮廓集(每个轮廓由点集组成)
// * hierarchy: 轮廓集中轮廓之间的关系。数量与contours对应
// * 返回值: 凸多边形轮廓点集
// */
// std::vector<cv::Point> getVertices(const cv::RotatedRect& rect);
// /*
// * 功能: 轮廓缩进
// * points: 轮廓点集
// * center: 围绕center点缩进
// * indent: 缩进像素
// */
// void polyIndent(std::vector<cv::Point>& points, const cv::Point& center, int indent);
// /*
// * 功能: 二值化能够处理彩色和灰度图像。src为彩色图像时灰度图取三个通道的最大值
// * src: 源图
// * dst: 目标图
// * thre: 阈值
// */
// void threshold_Mat(const cv::Mat& src, cv::Mat& dst, double thre);
// /*
// * 功能: 彩色转灰度,灰度图取三个通道的最大值
// * src: 源图
// * 返回值: 灰度图
// */
// cv::Mat transforColor(const cv::Mat& src);
// /*
// * 功能: 获取点的仿射变换
// * p: 原点
// * warp_mat: 仿射变换系数矩阵
// * 返回值: 变换后的点
// */
// cv::Point warpPoint(const cv::Point& p, const cv::Mat& warp_mat);
// /*
// * 功能: 点到点距离
// * p1: 点1
// * p2: 点2
// * 返回值: 点到点距离
// */
// int distanceP2P(const cv::Point& p1, const cv::Point& p2);
// /*
// * 功能: 点到直线距离
// * p: 点
// * l1: 直线端点1
// * l2: 直线端点2
// * 返回值: 点到直线距离
// */
// float distanceP2L(const cv::Point& p, const cv::Point& l1, const cv::Point& l2);
// }
// #endif // !IMAGE_PROCESS_C_H

43
ImageStiich.cpp Normal file
View File

@ -0,0 +1,43 @@
// #include "ImageStitch.h"
// #include <vector>
// using namespace cv;
// ImageStitch::ImageStitch(int pixtype, int width, int heigth) : m_pixtype(pixtype),
// m_width(width),
// m_height(heigth)
// {
// }
// ImageStitch::~ImageStitch()
// {
// }
// cv::Mat ImageStitch::GetStitchImage(cv::Mat mat)
// {
// //cv::imwrite("orgmat.jpg",mat);
// cv::Mat dst;
// cv::Mat ch_mats[3];
// int dstwidth, dstheight;
// dstwidth = m_width * 3;
// dstheight = m_height / 3;
// if (m_pixtype == IMAGE_COLOR)
// {
// //mat = cv::Mat(m_height / 3, m_width * 9, CV_8UC1, imgdata);
// dst = cv::Mat(dstheight, dstwidth, CV_8UC3);
// cv::Mat mat1 = mat(cv::Rect(m_width * 3 * 1, 0, m_width * 3, m_height / 3)); //R 对应红通道
// cv::Mat mat2 = mat(cv::Rect(m_width * 3 * 2, 0, m_width * 3, m_height / 3)); //G 对应绿通道
// cv::Mat mat3 = mat(cv::Rect(m_width * 3 * 0, 0, m_width * 3, m_height / 3)); //B 对应蓝通道
// ch_mats[0] = mat1;
// ch_mats[1] = mat2;
// ch_mats[2] = mat3;
// cv::merge(ch_mats, 3, dst);
// for (int i = 0; i < 3; i++)
// ch_mats[i].release();
// LOG("merge mats end \n");
// return dst.clone();
// }
// else
// { //gray
// return mat;
// }
// }

19
ImageStitch.h Normal file
View File

@ -0,0 +1,19 @@
// #pragma once
// #include <opencv2/opencv.hpp>
// #include "scanservices_utils.h"
// class ImageStitch
// {
// private:
// /* data */
// public:
// ImageStitch(int pixtype,int width,int heigth);
// ~ImageStitch();
// cv::Mat GetStitchImage(cv::Mat mat);
// private:
// int m_pixtype;
// int m_width;
// int m_height;
// cv::Mat m_mat;
// };

43
Jpegcompress.cpp Normal file
View File

@ -0,0 +1,43 @@
// #include "Jpegcompress.h"
// #include <string>
// JpegCompress::JpegCompress(int quality):tjInstance(NULL)
// ,m_quality(quality)
// {
// }
// JpegCompress::~JpegCompress()
// {
// tjDestroy(tjInstance);
// }
// HG_JpegCompressInfo JpegCompress::GetCompressedImg(cv::Mat& mat)
// {
// HG_JpegCompressInfo info={0};
// if(mat.empty())
// {
// LOG("JpegCompress Empty Mat! warnning !!!!\n");
// return info;
// }
// tjInstance = tjInitCompress();
// int outSubsamp;
// int flags = 0;
// int pixelFormat;
// if (mat.channels() == 1)
// {
// outSubsamp = TJSAMP_GRAY;
// pixelFormat = TJPF_GRAY;
// }
// else
// {
// pixelFormat = TJPF_RGB;
// outSubsamp = TJSAMP_444;
// }
// //std::chrono::steady_clock::time_point _start = std::chrono::steady_clock::now();
// //LOG("image rows= %d cols= %d pixelFormat= %d \n",mat.rows,mat.cols,pixelFormat);
// tjCompress2(tjInstance, mat.data, mat.cols, 0, mat.rows, pixelFormat,
// &info.pJpegData, (long unsigned int*)&info.DataLength, outSubsamp, m_quality, flags);
// //LOG("jpeg compress done \n");
// return info;
// }

15
Jpegcompress.h Normal file
View File

@ -0,0 +1,15 @@
// #pragma once
// #include <turbojpeg.h>
// #include <opencv2/opencv.hpp>
// #include "scanservices_utils.h"
// class JpegCompress
// {
// public:
// JpegCompress(int quality=80);
// ~JpegCompress();
// HG_JpegCompressInfo GetCompressedImg(cv::Mat& mat);
// private:
// tjhandle tjInstance;
// int m_quality;
// };

286
JsonConfig.cpp Normal file
View File

@ -0,0 +1,286 @@
#include "JsonConfig.h"
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#define SCAN_INFO_TITLE "ScanInfo"
#define SCAN_TOTAL "TotalScanned"
#define SCAN_ROLLERNUM "RollerNum"
#define SCAN_CUONUM "CuoNum"
#define SCAN_JAMINNUM "JamInNum"
#define SCAN_JAMOUTNUM "JamOutNum"
#define SCAN_DOUNUM "DoubleNum"
#define SCAN_ERRORNUM "ErrorNum"
#define SCAN_SERIALNUM "SerialNum"
#define SCAN_FWVERSION "FWVersion"
#define SCAN_HRATIO "HRatio"
#define SCAN_VRATIO "VRatio"
#define SCAN_SLEEPTIME "SleepTime"
#define SCAN_TOKEN "ScannerToken"
#define SCAN_SPEEDMODE "SpeedMode"
#define SCAN_VID "VID"
#define SCAN_PID "PID"
#define TOKEN_DEFAULT " "
JsonConfig::JsonConfig()
{
if (access(SCANNER_SCAN_INFO_PATH, F_OK) == -1) //不存在
{
ScannerScanInfo defaultinfo = CreateDefaultScanInfo();
SaveScanInfo(defaultinfo);
}
}
JsonConfig::JsonConfig(ConfigType type) : m_cfgType(type)
{
}
JsonConfig::~JsonConfig()
{
}
// bool JsonConfig::ReadParam(FPGAConfigParam &param)
// {
// bool ret = false;
// if (access(cfgPaths[m_cfgType].c_str(), F_OK) == -1)
// {
// return ret;
// }
// std::ifstream i(cfgPaths[m_cfgType]);
// json j;
// i >> j;
// auto &jobject = j[cfgPrefix[m_cfgType]];
// jobject[cfgPrefix[m_cfgType] + "ExposureF"].get_to(param.ExposureF);
// jobject[cfgPrefix[m_cfgType] + "ExposureB"].get_to(param.ExposureB);
// jobject[cfgPrefix[m_cfgType] + "GainF"].get_to(param.GainF);
// jobject[cfgPrefix[m_cfgType] + "GainB"].get_to(param.GainB);
// jobject[cfgPrefix[m_cfgType] + "OffsetF"].get_to(param.OffsetF);
// jobject[cfgPrefix[m_cfgType] + "OffsetB"].get_to(param.OffsetB);
// return ret;
// }
// void JsonConfig::WriteParam(FPGAConfigParam &t_param)
// {
// FPGAConfigParam param;
// if (access(cfgPaths[m_cfgType].c_str(), F_OK) == -1)
// {
// LOG("Not found config %s \n", cfgPaths[m_cfgType].c_str());
// param = CreateDefault();
// }
// else
// param = t_param;
// LOG("start save %s \n", cfgPaths[m_cfgType].c_str());
// json m_json;
// auto &jobject = m_json[cfgPrefix[m_cfgType]];
// jobject[cfgPrefix[m_cfgType] + "ExposureF"] = {param.ExposureF[0], param.ExposureF[1], param.ExposureF[2]};
// jobject[cfgPrefix[m_cfgType] + "ExposureB"] = {param.ExposureB[0], param.ExposureB[1], param.ExposureB[2]};
// jobject[cfgPrefix[m_cfgType] + "GainF"] = {param.GainF[0], param.GainF[1], param.GainF[2], param.GainF[3], param.GainF[4], param.GainF[5]};
// jobject[cfgPrefix[m_cfgType] + "GainB"] = {param.GainB[0], param.GainB[1], param.GainB[2], param.GainB[3], param.GainB[4], param.GainB[5]};
// jobject[cfgPrefix[m_cfgType] + "OffsetF"] = {param.OffsetF[0], param.OffsetF[1], param.OffsetF[2], param.OffsetF[3], param.OffsetF[4], param.OffsetF[5]};
// jobject[cfgPrefix[m_cfgType] + "OffsetB"] = {param.OffsetB[0], param.OffsetB[1], param.OffsetB[2], param.OffsetB[3], param.OffsetB[4], param.OffsetB[5]};
// std::ofstream o(cfgPaths[m_cfgType]);
// o << std::setw(4) << m_json << std::endl;
// LOG("save config %s down \n", cfgPaths[m_cfgType].c_str());
// }
// FPGAConfigParam JsonConfig::CreateDefault()
// {
// std::string savePath = cfgPaths[m_cfgType];
// FPGAConfigParam param = {0};
// for (size_t i = 0; i < 3; i++)
// {
// param.ExposureF[i] = 259;
// param.ExposureB[i] = 238;
// }
// for (size_t i = 0; i < 6; i++)
// {
// param.GainB[i] = 30;
// param.GainF[i] = 30;
// param.OffsetB[i] = param.OffsetF[i] = 119;
// }
// return param;
// }
ScannerScanInfo JsonConfig::CreateDefaultScanInfo()
{
ScannerScanInfo info;
info.CuoNum = 0;
info.DoubleNum = 0;
info.ErrorNum = 0;
info.JamInNum = 0;
info.JamOutNum = 0;
info.FWVersion = FWVERSION;
info.SerialNum = SERIALNUM;
info.TotalScanned = 0;
info.RollerNum = 0;
info.HRatio = 1065353216;//(=(float)1.0)
info.VRatio = 1065353216;
info.SleepTime=3600;
info.Token=TOKEN_DEFAULT;
info.SpeedMode = 4;
l_it = mapFradme_SP.find(info.SpeedMode);
info.FWVersion = l_it->second.FWVERSIO;
info.VID = 0x3072;
#ifdef G400
info.PID = 0x0400;
#else
info.PID = 0x0300;
#endif
return info;
}
ScannerScanInfo JsonConfig::GetScanInfo()
{
ScannerScanInfo info;
if (access(SCANNER_SCAN_INFO_PATH, F_OK) != 0)
{
printf("/usr/local/huago/jsonconfig.json do not exist!\n");
info = CreateDefaultScanInfo();
SaveScanInfo(info);
return info;
}
std::ifstream i(SCANNER_SCAN_INFO_PATH);
auto pos = i.tellg();
i.seekg(0, ios::end);
cout << "file length =" << i.tellg() << endl;
if(i.tellg()<=2)
{
printf("/usr/local/huago/jsonconfig.json file size < 2!\n");
info = CreateDefaultScanInfo();
SaveScanInfo(info);
return info;
}
json j;
i.seekg(pos);
{
std::lock_guard<std::mutex> m_c(m_lock);
i >> j;
i.close();
}
auto &jobject = j[SCAN_INFO_TITLE];
if (jobject.contains(SCAN_TOTAL))
jobject[SCAN_TOTAL].get_to(info.TotalScanned);
else
info.TotalScanned = 0;
if (jobject.contains(SCAN_ROLLERNUM))
jobject[SCAN_ROLLERNUM].get_to(info.RollerNum);
else
info.RollerNum = 0;
if (jobject.contains(SCAN_CUONUM))
jobject[SCAN_CUONUM].get_to(info.CuoNum);
else
info.CuoNum = 0;
if (jobject.contains(SCAN_JAMINNUM))
jobject[SCAN_JAMINNUM].get_to(info.JamInNum);
else
info.JamInNum = 0;
if (jobject.contains(SCAN_JAMOUTNUM))
jobject[SCAN_JAMOUTNUM].get_to(info.JamOutNum);
else
info.JamOutNum = 0;
if (jobject.contains(SCAN_DOUNUM))
jobject[SCAN_DOUNUM].get_to(info.DoubleNum);
else
info.DoubleNum = 0;
if (jobject.contains(SCAN_ERRORNUM))
jobject[SCAN_ERRORNUM].get_to(info.ErrorNum);
else
info.ErrorNum = 0;
if (jobject.contains(SCAN_SERIALNUM))
jobject[SCAN_SERIALNUM].get_to(info.SerialNum);
else
info.SerialNum = SERIALNUM;
if (jobject.contains(SCAN_FWVERSION))
jobject[SCAN_FWVERSION].get_to(info.FWVersion);
else
info.FWVersion = l_it->second.FWVERSIO;
if (jobject.contains(SCAN_HRATIO))
jobject[SCAN_HRATIO].get_to(info.HRatio);
else
info.HRatio = 1065353216;//默认 1.0f
if (jobject.contains(SCAN_VRATIO))
jobject[SCAN_VRATIO].get_to(info.VRatio);
else
info.VRatio = 1065353216;//默认 1.0f
if (jobject.contains(SCAN_SLEEPTIME))
jobject[SCAN_SLEEPTIME].get_to(info.SleepTime);
else
info.SleepTime = 3600;//默认 1.0f
if(jobject.contains(SCAN_TOKEN))
jobject[SCAN_TOKEN].get_to(info.Token);
else
{
info.Token=TOKEN_DEFAULT;
}
if(jobject.contains(SCAN_SPEEDMODE))
jobject[SCAN_SPEEDMODE].get_to(info.SpeedMode);
else
{
info.SpeedMode = 4;
}
if(jobject.contains(SCAN_VID))
jobject[SCAN_VID].get_to(info.VID);
else
{
info.VID = 0x3072;
}
if(jobject.contains(SCAN_PID))
jobject[SCAN_PID].get_to(info.PID);
else
{
#ifdef G400
info.PID = 0x0400;
#else
info.PID = 0x0300;
#endif
}
return info;
}
void JsonConfig::SaveScanInfo(const ScannerScanInfo &info)
{
json m_json;
auto &jobject = m_json[SCAN_INFO_TITLE];
jobject[SCAN_TOTAL] = info.TotalScanned;
jobject[SCAN_ROLLERNUM] = info.RollerNum;
jobject[SCAN_CUONUM] = info.CuoNum;
jobject[SCAN_JAMINNUM] = info.JamInNum;
jobject[SCAN_JAMOUTNUM] = info.JamOutNum;
jobject[SCAN_DOUNUM] = info.DoubleNum;
jobject[SCAN_ERRORNUM] = info.ErrorNum;
jobject[SCAN_SERIALNUM] = info.SerialNum;
jobject[SCAN_FWVERSION] = info.FWVersion;
jobject[SCAN_HRATIO]= info.HRatio;
jobject[SCAN_VRATIO] = info.VRatio;
jobject[SCAN_SLEEPTIME] = info.SleepTime;
jobject[SCAN_TOKEN] = info.Token;
jobject[SCAN_SPEEDMODE] = info.SpeedMode;
jobject[SCAN_VID] = info.VID;
jobject[SCAN_PID] = info.PID;
std::lock_guard<std::mutex> m_c(m_lock);
std::ofstream o(SCANNER_SCAN_INFO_PATH);
//std::cout<<m_json<<std::endl;
o << std::setw(4) << m_json << std::endl;
o.close();
o.flush();
}

55
JsonConfig.h Normal file
View File

@ -0,0 +1,55 @@
#pragma once
#include <unistd.h>
#include "json.hpp"
#include "scanservices_utils.h"
#include <string>
#include <map>
#include <mutex>
#define SCANNER_SCAN_INFO_PATH "/usr/local/huago/jsonconfig.json"
using namespace std;
using json = nlohmann::json;
class JsonConfig
{
public:
enum class ConfigType
{
Color_Flat,
Color_Correct,
Gray_Flat,
Gray_Correct
};
private:
map<ConfigType,string> cfgPaths={
{ConfigType::Color_Flat,"/usr/local/etc/huago/Color_Flat.json"},
{ConfigType::Color_Correct,"/usr/local/etc/huago/Color_Correct.json"},
{ConfigType::Gray_Flat,"/usr/local/etc/huago/Gray_Flat.json"},
{ConfigType::Gray_Correct,"/usr/local/etc/huago/Gray_Correct.json"}
};
map<ConfigType,string> cfgPrefix={
{ConfigType::Color_Flat,"Color_Flat"},
{ConfigType::Color_Correct,"Color_Correct"},
{ConfigType::Gray_Flat,"Gray_Flat"},
{ConfigType::Gray_Correct,"Gray_Correct"}
};
ConfigType m_cfgType;
public:
JsonConfig();
JsonConfig(ConfigType type);
~JsonConfig();
/*
*false
*/
// bool ReadParam(FPGAConfigParam& param);
// void WriteParam(FPGAConfigParam& t_param);
ScannerScanInfo GetScanInfo();
map<int, sp_COLOR_or_GRAY >::iterator l_it;
void SaveScanInfo(const ScannerScanInfo& info);
private:
//FPGAConfigParam CreateDefault();
std::mutex m_lock;
ScannerScanInfo CreateDefaultScanInfo();
};

192
Keyboard.cpp Normal file
View File

@ -0,0 +1,192 @@
#include "Keyboard.h"
#include <stdio.h>
#include <sys/time.h>
#define KEYCODE_POWER 62
#define KEYCODE_START 60
#define KEYCODE_STOP 61
namespace huagao
{
Keyboard::Keyboard(std::function<void(const int)> buttonevent)
{
m_event = buttonevent;
mInputFd = open("/dev/input/event0", O_RDONLY | O_NONBLOCK);
}
Keyboard::~Keyboard()
{
b_run = false;
if (pollthread.joinable())
pollthread.join();
if (mInputFd > 0)
{
::close(mInputFd);
}
::close(mEpId);
}
void Keyboard::init()
{
mEpId = epoll_create(1);
int err;
int len;
int i;
unsigned char byte;
int bit;
struct input_id id;
unsigned int evbit[2];
std::string ev_name[] = {
"EV_SYN",
"EV_KEY",
"EV_REL",
"EV_ABS",
"EV_MSC",
"EV_SW",
"NULL",
"NULL",
"NULL",
"NULL",
"NULL",
"NULL",
"NULL",
"NULL",
"NULL",
"NULL",
"NULL",
"EV_LED",
"EV_LND",
"NULL",
"EV_REP",
"EV_FF",
"EV_PWR",
};
if (mInputFd == -1)
{
LOG("open kd device or mouse fail! \n");
}
else
{
ev.data.fd = mInputFd;
ev.events = EPOLLIN | EPOLLET;
int ret = epoll_ctl(mEpId, EPOLL_CTL_ADD, mInputFd, &ev);
if (ret == -1)
{
LOG("add kd device in epoll fail! \n");
}
}
err = ioctl(mInputFd, EVIOCGID, &id);
if (err == 0)
{
LOG("bustype = 0x%x\n", id.bustype);
LOG("vendor = 0x%x\n", id.vendor);
LOG("product = 0x%x\n", id.product);
LOG("version = 0x%x\n", id.version);
}
len = ioctl(mInputFd, EVIOCGBIT(0, sizeof(evbit)), &evbit);
if (len > 0 && len <= sizeof(evbit))
{
LOG("support ev type : ");
for (i = 0; i < len; i++)
{
byte = ((unsigned char *)evbit)[i];
for (bit = 0; bit < 8; bit++)
{
if (byte & (1 << bit))
LOG("%s ", ev_name[i * 8 + bit].c_str());
}
}
LOG("\n");
}
b_run = true;
pollthread = std::thread(&Keyboard::poll, this);
}
void Keyboard::poll()
{
int re = 0;
while (b_run)
{
re = epoll_wait(mEpId, events, MAX_EVENTS, 1000);
for (int i = 0; i < re; ++i)
{
if (events[i].events & EPOLLIN)
{
LOG("poll\n");
doInput(events + i);
}
}
re = 0;
}
}
long time_pressed_sec;
long time_pressed_usec;
void Keyboard::doInput(const epoll_event *ev)
{
ssize_t resize = 0;
ssize_t n = 0;
struct input_event input_ev;
while ((resize = read(ev->data.fd, buffer + n, sizeof(struct input_event) - n)) > 0)
{
n += resize;
if (n == sizeof(input_event))
{
memcpy((void *)(&input_ev), buffer, sizeof(input_event));
LOG("keyboard type=%d; code=%d; value=%d, sec=%ld, usec=%ld\n", (int)input_ev.type,
(int)input_ev.code, (int)input_ev.value, input_ev.time.tv_sec, input_ev.time.tv_usec);
if (input_ev.type == 0)
{
n = 0;
continue;
}
if (input_ev.value == 1)
{
LOG("pressed....\n");
time_pressed_sec = (long)input_ev.time.tv_sec;
time_pressed_usec = (long)input_ev.time.tv_usec;
n = 0;
continue;
}
LOG("keyboard press tiem sec=%ld, usec=%ld\n", time_pressed_sec, time_pressed_usec);
long delay = (input_ev.time.tv_usec - time_pressed_usec) / 1000;
delay = delay + (input_ev.time.tv_sec - time_pressed_sec) * 1000;
LOG("press delay:%ld\n", delay);
switch (input_ev.code)
{
case KEYCODE_POWER:
if (delay >= 1000)
{
if (!b_lowpwoer) //未进入低功耗 则触发低功耗模式
{
b_lowpwoer = !b_lowpwoer;
m_event(2);
}
else //已进入低功耗模式
b_lowpwoer = false;
}
else
{
b_lowpwoer = false;
}
break;
case KEYCODE_START:
m_event(0);
break;
case KEYCODE_STOP:
LOG("stop KEYCODE_STOP pressed!\n");
m_event(1);
break;
default:
break;
}
n = 0;
}
}
}
} // namespace huagao

44
Keyboard.h Normal file
View File

@ -0,0 +1,44 @@
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/input.h>
#include <sys/epoll.h>
#include <string.h>
#include <thread>
#include <time.h>
#include <condition_variable>
#include <functional>
#include "scanservices_utils.h"
static const char kDevInput[] = "/dev/input/event0";
#define MAX_EVENTS 10
namespace huagao
{
class Keyboard
{
public:
Keyboard(std::function<void(const int)> buttonevent);
~Keyboard();
void init();
private:
int mInputFd;
int mEpId;
struct epoll_event ev;
struct epoll_event events[MAX_EVENTS];
std::thread pollthread;
char buffer[sizeof(input_event)];
void poll();
void doInput(const epoll_event *ev);
bool b_run =false;
bool b_lowpwoer = false;
private:
std::function<void(const int)> m_event;
};
} // namespace huagao

36
Led.cpp Normal file
View File

@ -0,0 +1,36 @@
#include "Led.h"
#define LEDPATH "%s/%s/%s"
std::string Led::timer = "timer";
std::string Led::none = "none";
Led::Led(std::string name) {
path_brightness = string_format(LEDPATH, path_base.c_str(), name.c_str(), path_brightness.c_str());
path_trigger = string_format(LEDPATH, path_base.c_str(), name.c_str(), path_trigger.c_str());
path_delay_off = string_format(LEDPATH, path_base.c_str(), name.c_str(), path_delay_off.c_str());
path_delay_on = string_format(LEDPATH, path_base.c_str(), name.c_str(), path_delay_on.c_str());
}
Led::~Led() {
}
void Led::on(int time_ms) {
if (time_ms != 0) {
write_dev(path_trigger, timer);
write_dev(path_delay_off, time_ms);
write_dev(path_delay_on, time_ms);
} else {
//if (read_dev_s(path_trigger).find(none) == std::string::npos)
write_dev(path_trigger, none);
}
write_dev(path_brightness, 1);
}
void Led::off() {
write_dev(path_brightness, 0);
}
bool Led::isOn() {
return (bool)read_dev_i(path_brightness);
}

24
Led.h Normal file
View File

@ -0,0 +1,24 @@
#pragma once
#include "DevUtil.h"
class Led
{
public:
static std::string timer;
static std::string none;
public:
Led(std::string name);
~Led();
void on(int time_ms = 0);
void off();
bool isOn();
private:
const std::string path_base = "/sys/class/leds";
std::string path_brightness = "brightness";
std::string path_trigger = "trigger";
std::string path_delay_off = "delay_off";
std::string path_delay_on = "delay_on";
};

85
MemoryInfo.cpp Normal file
View File

@ -0,0 +1,85 @@
#include "MemoryInfo.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
MemoryInfo* MemoryInfo::m_pInstance=nullptr;
MemoryInfo::Garbo MemoryInfo::garbo;
MemoryInfo::MemoryInfo(/* args */)
{
}
// MemoryInfo::~MemoryInfo()
// {
// }
MemoryInfo* MemoryInfo::GetInstance()
{
if(m_pInstance==nullptr)
{
m_pInstance= new MemoryInfo();
}
return m_pInstance;
}
float MemoryInfo::GetMemoryUsed()
{
float ret=0.0f;
Mem_info info;
getMemInfo(info);
if(info.total!=0)
ret=(100.0 * (info.total - info.available) / info.total);
return ret;
}
void MemoryInfo::getMemInfo(Mem_info& info)
{
FILE* fpMemInfo = fopen("/proc/meminfo", "r");
if (NULL == fpMemInfo)
{
return ;
}
int i = 0;
int value;
char name[1024];
char line[1024];
int nFiledNumber = 2;
int nMemberNumber = 5;
while (fgets(line, sizeof(line) - 1, fpMemInfo))
{
if (sscanf(line, "%s%u", name, &value) != nFiledNumber)
{
continue;
}
if (0 == strcmp(name, "MemTotal:"))
{
++i;
info.total = value;
}
else if (0 == strcmp(name, "MemFree:"))
{
++i;
info.free = value;
}
else if (0 == strcmp(name, "MemAvailable:"))
{
++i;
info.available = value;
}
else if (0 == strcmp(name, "Buffers:"))
{
++i;
info.buffers = value;
}
else if (0 == strcmp(name, "Cached:"))
{
++i;
info.cached = value;
}
if (i == nMemberNumber)
{
break;
}
}
fclose(fpMemInfo);
}

41
MemoryInfo.h Normal file
View File

@ -0,0 +1,41 @@
#pragma once
class MemoryInfo
{
private:
struct MEM_INFO
{
unsigned int total;
unsigned int free;
unsigned int buffers;
unsigned int cached;
unsigned int swap_cached;
unsigned int swap_total;
unsigned int swap_free;
unsigned int available;
};
typedef struct MEM_INFO Mem_info;
MemoryInfo(/* args */);
~MemoryInfo(){}
MemoryInfo& operator=(const MemoryInfo &);
void getMemInfo(Mem_info& info);
public:
static MemoryInfo* GetInstance();
float GetMemoryUsed();
private:
class Garbo
{
private:
public:
~Garbo()
{
if(MemoryInfo::m_pInstance!=nullptr)
{
delete MemoryInfo::m_pInstance;
MemoryInfo::m_pInstance=nullptr;
}
}
};
static MemoryInfo* m_pInstance;
static Garbo garbo;
};

141
Motor.cpp Normal file
View File

@ -0,0 +1,141 @@
#include "Motor.h"
#include "DevUtil.h"
#include <vector>
#include <cmath>
#include <exception>
#include "utilsfunc.h"
#include "MotorConfig.h"
#define ZZ_PWM 3
#define CZ_PWM 2
struct MotorMode
{
int mod0 : 1;
int mod1 : 1;
int mod2 : 1;
};
// const MotorPorts motorPorts_Zouzhi = {.reset = ZouZhiMotor_Reset, .sleep = ZouZhiMotor_Sleep, .enable = ZouZhiMotor_Enable, .dir = ZouZhiMotor_Direction, .decay = ZouZhiMotor_Decay, .home = ZouZhiMotor_Home, .fault = ZouZhiMotor_Fault, .mode0 = ZouZhiMotor_Mode0, .mode1 = ZouZhiMotor_Mode1, .mode2 = ZouZhiMotor_Mode2, .pwm = ZZ_PWM};
// const MotorPorts motorPorts_Cuozhi = {.reset = CuoZhiMotor_Reset, .sleep = CuoZhiMotor_Sleep, .enable = CuoZhiMotor_Enable, .dir = CuoZhiMotor_Direction, .decay = CuoZhiMotor_Decay, .home = CuoZhiMotor_Home, .fault = CuoZhiMotor_Fault, .mode0 = CuoZhiMotor_Mode0, .mode1 = CuoZhiMotor_Mode1, .mode2 = CuoZhiMotor_Mode2, .pwm = CZ_PWM};
const MotorPorts motorPorts_Zouzhi = { .power = PIN_PORT_7010::MOTOR_POWER_1,
.reset = PIN_PORT_7010::ZOUZHI_PIN_RESET,
.sleep = PIN_PORT_7010::ZOUZHI_PIN_SLEEP,
.enable = PIN_PORT_7010::ZOUZHI_PIN_ENABEL,
.dir = PIN_PORT_7010::ZOUZHI_PIN_DIR,
.pwm = 1
};
const MotorPorts motorPorts_Cuozhi = { .power =PIN_PORT_7010::MOTOR_POWER_2,
.reset = PIN_PORT_7010::CUOZHI_PIN_RESET,
.sleep = PIN_PORT_7010::CUOZHI_PIN_SLEEP,
.enable = PIN_PORT_7010::CUOZHI_PIN_ENABEL,
.dir = PIN_PORT_7010::CUOZHI_PIN_DIR,
.pwm = 0
};
std::vector<int> speedup_cfg(int finalPeriod, int Fmin, int stepnum, int a, int offset, int finalDelay)
{
std::vector<int> freqs;
int period = 0;
double delay = ((double)finalDelay) / 1000000.0;
double b = stepnum * delay;
for (int i = 0; i < stepnum; i++)
{
period = (int)(finalPeriod + (Fmin - finalPeriod) / (1 + exp(-a * b + offset)));
b = b - delay;
freqs.push_back(period);
}
return freqs;
}
//GpioOut Motor::powerPin(MotorPower);
Motor::Motor(MotorPorts motorPorts):sleepPin(motorPorts.sleep),
resetPin(motorPorts.reset),
enablePin(motorPorts.enable),
dirPin(motorPorts.dir),
pwm(motorPorts.pwm),
motor_power(motorPorts.power)
{
sleepPin.setDirection(Gpio::out);
resetPin.setDirection(Gpio::out);
enablePin.setDirection(Gpio::out);
dirPin.setDirection(Gpio::out);
motor_power.setDirection(Gpio::out);
motor_power.setValue(Gpio::High); //0关闭电机电源 1开启电机电源 //默认一直开启
//默认设置 1 1 1
resetPin.setValue(Gpio::High); //0重启 1电机不重启
sleepPin.setValue(Gpio::High); //0电机停止转动 1电机开始转动
enablePin.setValue(Gpio::High); //0电机芯片打开电源 1电机芯片关闭电源
}
Motor::~Motor()
{
stop();
if (m_mtconfig.get())
m_mtconfig.reset();
}
void Motor::start(std ::vector<int> &delay_s, const MotorSpeedParam &msp)
{
enablePin.setValue(Gpio::Low);
pwm.enable(true);
if (!delay_s.empty())
{
std::vector<int>::iterator iter = delay_s.begin();
while (++iter != delay_s.end())
{
pwm.setFreq(PWM_PERIOD / (*iter));
std::this_thread::sleep_for(std::chrono::microseconds((int)msp.finalDelay));
}
}
pwm.setFreq(PWM_PERIOD / msp.finalPeriod);
//pwm.setFreq((PWM_PERIOD / msp.finalPeriod)/10*10);
//printf("\n-----pwm Freq = %d------\n",PWM_PERIOD / msp.finalPeriod/10*10);
}
void Motor::start()
{
enablePin.setValue(Gpio::Low);
pwm.enable(true);
}
void Motor::stop()
{
enablePin.setValue(Gpio::High);
pwm.enable(false);
}
void Motor::pause()
{
pwm.enable(false);
enablePin.setValue(Gpio::Low);
}
void Motor::setMode(int mode_input)
{
// MotorMode *mode = (MotorMode *)&mode_input;
// mode0.setValue((Gpio::GpioLevel)mode->mod0);
// mode1.setValue((Gpio::GpioLevel)mode->mod1);
// mode2.setValue((Gpio::GpioLevel)mode->mod2);
}
void Motor::setDirection(int dir)
{
dirPin.setValue((Gpio::GpioLevel)dir);
}
void Motor::setSpeed(int value)
{
pwm.setFreq(value);
}
void Motor::enablePower(bool bEnable)
{
LOG("Enable Motor PowerPin %s \n", bEnable ? "true" : "false");
//powerPin.setValue((Gpio::GpioLevel)bEnable);
}

74
Motor.h Normal file
View File

@ -0,0 +1,74 @@
#pragma once
#include "Gpio.h"
#include "Pwm.h"
#include <vector>
#include <thread>
#include <iostream>
#include "scanservices_utils.h"
#include "utilsfunc.h"
#include <exception>
#include "Motordef.h"
#include "MotorConfig.h"
struct MotorPorts
{
int power;
int reset;
int sleep;
int enable;
int dir;
int decay;
int home;
int fault;
int mode0;
int mode1;
int mode2;
int pwm;
};
extern const MotorPorts motorPorts_Zouzhi;
extern const MotorPorts motorPorts_Cuozhi;
class Motor
{
public:
Motor(MotorPorts motorPorts);
virtual ~Motor();
protected:
//static GpioOut powerPin;
Gpio motor_power;
Gpio resetPin;
Gpio sleepPin;
Gpio enablePin;
Gpio dirPin;
Pwm pwm;
std::shared_ptr<MotorConfig> m_mtconfig;
SMBType smbtype;
public:
void start(std::vector<int> &delay_s, const MotorSpeedParam &msp);
virtual void start();
void stop();
void pause();
void setMode(int mode_input);
void setDirection(int dir);
void setSpeed(int value);
static void enablePower(bool bEnable);
static int isPowerOn()
{
return 0;//powerPin.getValue();
};
};
extern std::vector<int> speedup_cfg(int finalPeriod, int Fmin, int stepnum, int a, int offset, int finalDelay);

255
MotorConfig.cpp Normal file
View File

@ -0,0 +1,255 @@
#include "MotorConfig.h"
#include <sys/stat.h>
#include <fstream>
#include <sstream>
#include <iomanip>
using namespace std;
MotorConfig::MotorConfig()
{
initconfigfile();
}
MotorConfig::~MotorConfig()
{
}
std::string MotorConfig::GetParams(bool bzouzhi, MTBDType mttype)
{
std::string j_str;
json j;
if (mttype == MTBDType::MT_TMC)
{
std::ifstream i(bzouzhi ? MT_TMC216_ZOU_PATH : MT_TMC216_CUO_PATH);
i >> j;
j_str = j.dump();
}
else
{
std::ifstream i(bzouzhi ? MT_DRV888_ZOU_PATH : MT_DRV888_CUO_PATH);
i >> j;
j_str = j.dump();
}
return j_str;
}
void MotorConfig::SetParams(bool bzouzhi, MTBDType mttype, MotorSpeedParamEx &param)
{
std::string path;
auto params = GetMotorSpeedParams(bzouzhi, mttype);
for (int i = 0; i < params.size(); i++)
{
if (params[i].dpi == param.dpi &&
params[i].colormode == param.colormode &&
params[i].speed == param.speed)
{
params[i] = param;
}
}
json j = json::array();
for (int i = 0; i < params.size(); i++)
{
json t_j;
to_json(params[i], t_j);
j.push_back(t_j);
}
if (mttype == MTBDType::MT_TMC)
path = bzouzhi ? MT_TMC216_ZOU_PATH : MT_TMC216_CUO_PATH;
else
path = bzouzhi ? MT_DRV888_ZOU_PATH : MT_DRV888_CUO_PATH;
ofstream ofs(path);
ofs << std::setw(4) << j << std::endl;
}
std::vector<MotorSpeedParamEx> MotorConfig::GetMotorSpeedParams(bool bzouzhi, MTBDType mttype)
{
std::vector<MotorSpeedParamEx> ret;
if (mttype == MTBDType::MT_TMC)
{
std::ifstream i(bzouzhi ? MT_TMC216_ZOU_PATH : MT_TMC216_CUO_PATH);
json j;
i >> j;
for (json::iterator it = j.begin(); it != j.end(); ++it)
{
auto tmv = it.value();
MotorSpeedParamEx param;
from_json(tmv, param);
ret.push_back(param);
}
}
else
{
std::ifstream i(bzouzhi ? MT_DRV888_ZOU_PATH : MT_DRV888_CUO_PATH);
json j;
i >> j;
for (json::iterator it = j.begin(); it != j.end(); ++it)
{
auto tmv = it.value();
MotorSpeedParamEx param;
from_json(tmv, param);
ret.push_back(param);
}
}
return ret;
}
void MotorConfig::initconfigfile()
{
struct stat buff;
for (int s = 0; s < m_jsonpaths.size(); s++)
{
if (stat(m_jsonpaths[s].c_str(), &buff) != 0) //不存在
{
{
json j = json::array();
for (int i = 1; i < 6; i++)//speed mode
{
MotorSpeedParamEx param;
for (int k = 1; k < 4; k++) //dpi
{
double ratio = k == 1 ? 1 : (k == 2 ? 1.51 : 2.81);
param.mt_param.finalPeriod = s >= 2 ? 228000 / 4 *ratio: 228000*ratio; // s < 2 drv888
param.mt_param.Fmin = s >= 2 ? 1607750 / 4 : 1607750;
param.mt_param.stepnum = 30;
param.mt_param.a = 200;
param.mt_param.offset = 9;
param.mt_param.finalDelay = 2500;
param.speed = i; // 0 gray 1 color
param.dpi = k; // 1 200dpi 2 300dpi 3 600dpi
param.mt_param.acceleration_time=0;
for (int t = 0; t < 2; t++)//color mode
{
param.colormode = t;
if(t==1&& k== 1) param.sp = 2570;//200 color
else if(t==0&& k== 1) param.sp = 8150;//200 gray
else if(t==1&& k== 2) param.sp = 1719;//300 color
else if(t==0&& k== 2) param.sp = 5452;//300 color
else if(t==1&& k== 3) param.sp = 1700;//600 gray
else if(t==0&& k== 3) param.sp = 4850;//600 color
json t_j;
to_json(param, t_j);
j.push_back(t_j);
}
}
}
ofstream ofs(m_jsonpaths[s]);
ofs << std::setw(4) << j << std::endl;
}
}
}
}
std::vector<MotorSpeedParamEx> MotorConfig::GetMotorSpeedParams(const std::string &json_str)
{
std::vector<MotorSpeedParamEx> ret;
if (json_str.length())
{
json j(json_str);
for (json::iterator it = j.begin(); it != j.end(); ++it)
{
auto tmv = it.value();
MotorSpeedParamEx param;
from_json(tmv, param);
ret.push_back(param);
}
}
return ret;
}
MotorSpeedParamEx MotorConfig::GetMotorSpeedParam(bool bzouzhi,MTBDType mttype,int speed,int colormmode,int dpi)
{
MotorSpeedParamEx retparam;
auto exparams= GetMotorSpeedParams(bzouzhi,mttype);
for(auto &item:exparams)
{
if(item.colormode==colormmode &&
item.dpi==dpi&&
item.speed==speed)
{
retparam = item;
break;
}
}
return retparam;
}
void MotorConfig::to_json(MotorSpeedParamEx &param, json &j)
{
j = json{
{"A", param.mt_param.a},
{"FINALDELAY", param.mt_param.finalDelay},
{"FINALPERIOD", param.mt_param.finalPeriod},
{"FMIN", param.mt_param.Fmin},
{"OFFSET", param.mt_param.offset},
{"STEPNUM", param.mt_param.stepnum},
{"DPI", param.dpi},
{"COLORMODE", param.colormode},
{"ACCELERATIONTIME",param.mt_param.acceleration_time},
{"SPEED", param.speed},
{"SP",param.sp}};
}
void MotorConfig::from_json(json &j, MotorSpeedParamEx &param)
{
if(j.contains("A"))
j.at("A").get_to(param.mt_param.a);
else
param.mt_param.a = 200;
if(j.contains("FINALDELAY"))
j.at("FINALDELAY").get_to(param.mt_param.finalDelay);
else
param.mt_param.finalDelay=2500;
if(j.contains("FINALPERIOD"))
j.at("FINALPERIOD").get_to(param.mt_param.finalPeriod);
else
param.mt_param.finalPeriod = 455000;
if(j.contains("FMIN"))
j.at("FMIN").get_to(param.mt_param.Fmin);
else
param.mt_param.Fmin = 1655000;
if(j.contains("OFFSET"))
j.at("OFFSET").get_to(param.mt_param.offset);
else
param.mt_param.offset=7;
if(j.contains("STEPNUM"))
j.at("STEPNUM").get_to(param.mt_param.stepnum);
else
param.mt_param.stepnum=30;
if(j.contains("DPI"))
j.at("DPI").get_to(param.dpi);
else
param.dpi = 1;
if(j.contains("COLORMODE"))
j.at("COLORMODE").get_to(param.colormode);
else
param.colormode=1;
if(j.contains("ACCELERATIONTIME"))
j.at("ACCELERATIONTIME").get_to(param.mt_param.acceleration_time);
else
param.mt_param.acceleration_time=0;
if(j.contains("SPEED"))
j.at("SPEED").get_to(param.speed);
else
param.speed=4;
if(j.contains("SP"))
j.at("SP").get_to(param.sp);
else
param.sp=1800;
}

48
MotorConfig.h Normal file
View File

@ -0,0 +1,48 @@
#pragma once
#include <vector>
#include "json.hpp"
#include "Motordef.h"
using json= nlohmann::json;
#ifndef WIN32
#define MT_DRV888_CUO_PATH "/usr/local/huago/drv888_cuo.json"
#define MT_DRV888_ZOU_PATH "/usr/local/huago/drv888_zou.json"
#define MT_TMC216_CUO_PATH "/usr/local/huago/tmc216_cuo.json"
#define MT_TMC216_ZOU_PATH "/usr/local/huago/tmc216_zou.json"
#else
#define MT_DRV888_CUO_PATH "drv888_cuo.json"
#define MT_DRV888_ZOU_PATH "drv888_zou.json"
#define MT_TMC216_CUO_PATH "tmc216_cuo.json"
#define MT_TMC216_ZOU_PATH "tmc216_zou.json"
#endif
class MotorConfig
{
private:
const std::vector<std::string> m_jsonpaths={
MT_DRV888_CUO_PATH,
MT_DRV888_ZOU_PATH,
MT_TMC216_CUO_PATH,
MT_TMC216_ZOU_PATH
};
public:
enum class MTBDType
{
MT_TMC,
MT_DRV
};
public:
MotorConfig(/* args */);
~MotorConfig();
std::string GetParams(bool bzouzhi,MTBDType mttype);
void SetParams(bool bzouzhi,MTBDType mttype,MotorSpeedParamEx& param);
std::vector<MotorSpeedParamEx> GetMotorSpeedParams(bool bzouzhi,MTBDType mttype);
std::vector<MotorSpeedParamEx> GetMotorSpeedParams(const std::string& json_str);
MotorSpeedParamEx GetMotorSpeedParam(bool bzouzhi,MTBDType mttype,int speed,int colormmode,int dpi);
private:
void initconfigfile();
void to_json(MotorSpeedParamEx& param,json& j);
void from_json(json& j,MotorSpeedParamEx& param);
};

21
Motordef.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
struct MotorSpeedParam
{
int finalPeriod;
int Fmin;
float stepnum;
float a;
float offset;
float finalDelay;
float acceleration_time;
};
struct MotorSpeedParamEx
{
MotorSpeedParam mt_param;
int speed;
int colormode;
int dpi;
int sp;
};

1290
MultiFrameCapture.cpp Normal file

File diff suppressed because it is too large Load Diff

120
MultiFrameCapture.h Normal file
View File

@ -0,0 +1,120 @@
#include "ICapturer.h"
#include <thread>
#include "autoevent.hpp"
#include "CorrectParam.h"
#include "IPreproc.h"
class FpgaComm;
class gVideo;
class Gpio;
class GpioOut;
class MultiFrameCapture : public ICapturer
{
private:
struct frame_data_info
{
void* pdata;
unsigned int offset;
unsigned int total_dst;
unsigned int frame_count;
};
const int FPGA_MAX_HEIGHT_SUP=1048576;
//const int FRAME_HEIGHT=2700;
int frame_height = 60;
int readframe_timeout = 100;
unsigned int frame_count;
std::shared_ptr<GpioOut> reset_pin; //fpga 逻辑复位以及固件重载初始化。 7010 7/15没有 以防固件跑飞了保证能够不重启就能解决
std::shared_ptr<Gpio> fpgaLoad;
std::shared_ptr<Gpio> fpga_conf_initn;
BlockingQueue<V4L2_DATAINFO_Ex> m_frameinfos;
bool b_snap_run;
bool b_stop_snap;
bool b_end_snap;
bool b_imgproc;
bool is_size_error;
int snaped_index;
bool bScanning;
std::atomic<int> iImageremain;
FPGAConfigParam m_fpgaparam;
std::mutex m_mtx_snap;
std::mutex m_mtx_snapdone;
std::condition_variable m_cv_snap;
std::condition_variable m_cv_snapdone;
std::shared_ptr<std::thread> m_snap_thread;
std::shared_ptr<std::thread> m_imgproc_thread;
//std::vector<cv::Mat> m_frames;
std::vector<std::shared_ptr<IPreproc>> m_preproclist;
std::thread m_correctThread;
frame_data_info pimgdata_info;
ScannerGlue m_glue;
int offsetStep[12];
int expStep[2][3];
double radio = 1;
CamZ_Reg_4 reg_;
private:
void reset_fpga();
void reload_fpga();
void set_gain(int ix, int val);
void set_offset(int ix, int val);
void set_expo(int ix, int val);
void configFPGAParam(int mode,int dpi);
int color();
int width();
void snaprun();
void updatesnapstatus(int papertype);
void procimage();
void formatStep();
bool saveLutImg(int dpi, int mode, bool black);
void creatcorrectconfig(int dpi,int mode);
void correctcolor(int correctmode);
void openDevice(int dpi,int mode);
//void myFloodFill(cv::Mat& image, bool isTwoSide);
void init_imagedatabuffer();
//void update_imgdatainfo(cv::Mat itemmat);
void reset_imagedata();
public:
MultiFrameCapture(ScannerGlue glue, std::shared_ptr<FpgaComm> fpga, CISVendor vendor);
virtual ~MultiFrameCapture();
virtual void SetParent(void *scanner) override;
virtual void open() override;
virtual void snap() override;
virtual void stopsnap(bool autosize) override;
virtual void close() override;
virtual int read(int addr) override;
virtual void *readFrameTest(int timeout);
virtual void UpdateScanParam(HG_ScanConfiguration config) override;
virtual void createCorrect(int correctmode) override;
virtual void setFPGATriggerMode(bool autotrigger, int delay) override;
virtual void setFanMode(int mode) override;
virtual void fpgaReload() override;
virtual bool capturerImage() override;
virtual void waitsnapdone(int state) override;
virtual bool IsImageQueueEmpty() override;
virtual void resetimageremain() override;
virtual std::atomic_int &getimageremain() override;
virtual void clearimages() override;
virtual void setScanFlag(bool brun) override;
};

14
PanelLeds.cpp Normal file
View File

@ -0,0 +1,14 @@
#include "PanelLeds.h"
PanelLeds::PanelLeds()
: white("pwr-white"),
red("pwr-red"),
green("pwr-green")
{
}
PanelLeds::~PanelLeds()
{
}

85
PanelLeds.h Normal file
View File

@ -0,0 +1,85 @@
#pragma once
#include "Led.h"
#include <iostream>
#include "scanservices_utils.h"
class PanelLeds
{
public:
PanelLeds();
~PanelLeds();
void setStatus(LedStatus status)
{
switch (status)
{
case LedStatus::Ready:
{
LOG("LedStatus Ready red off and white off \n");
red.off();
white.on();
}
break;
case LedStatus::Scanning:
{
LOG("LedStatus scanning red off and white on 500 \n");
red.off();
white.on(500);
}
break;
case LedStatus::Abnormal:
{
LOG("LedStatus Abnormal red on and white off \n");
red.on();
white.off();
}
break;
case LedStatus::NoPaper:
{
LOG("LedStatus NoPaper red on 200 and white off \n");
red.on(200);
white.off();
}
break;
case LedStatus::StopScan:
{
LOG("LedStatus NoPaper red off and white on 200 \n");
red.off();
white.on(200);
}
break;
case LedStatus::CoverOpen:
{
LOG("LedStatus NoPaper red on and white off \n");
red.on();
white.off();
}
case LedStatus::Updating:
{
LOG("LedStatus NoPaper red on and white off \n");
red.on(100);
white.off();
}
break;
case LedStatus::UpdateDone:
{
LOG("LedStatus NoPaper red on and white off \n");
red.off();
white.on(200);
}
break;
default:
{
LOG("LedStatus NoPaper red off and white off \n");
red.off();
white.off();
}
break;
}
}
private:
Led white;
Led red;
Led green;
};

101
Parameters.h Normal file
View File

@ -0,0 +1,101 @@
#pragma once
#include <string>
//#define Color 3
typedef enum Scan_Mode
{
SM_GRAY,
SM_COLOR
} ScanMode;
const std::string ScanPaperTypes[] =
{
"A4",
"A3"
};
const int SPTSizes[] = {1728, 1632};
typedef enum Scan_Paper_Type
{
SPT_A4,
SPT_A3
}ScanPaperType;
#ifdef A3
// 图像像素值
#define IMG_HEIGHT 3600
#define IMG_WIDTH 2592 * 2
#define SPI_COLOR 0x04501003 //0x0cf01002, 0x04501003
#define SPI_GRAY 0x0cf01002
// 300 dpi 图像宽度像素值(目前仅为双面扫描故尺寸为单面尺寸乘以2)
#define IMG_WIDTH_300DPI 3672 * 2
// 200 dpi 图像宽度像素值(目前仅为双面扫描故尺寸为单面尺寸乘以2)
#define IMG_WIDTH_200DPI 2448 * 2
#define IMG_WIDTH_150DPI 1836 * 2
#define IMG_HEIGHT_200DPI IMG_HEIGHT
#define IMG_HEIGHT_300DPI IMG_HEIGHT * 1.5
#define IMG_HEIGHT_150DPI IMG_HEIGHT * 0.75
//原始图像相对于200dpi的倍数
#define IMG_W_RADIO 1
#define IMG_H_RADIO 1
#define FRAME_COUNT 4
#else
// 300 dpi 图像宽度像素值(目前仅为双面扫描故尺寸为单面尺寸乘以2)
#define IMG_WIDTH_300DPI 2592 * 2
// 200 dpi 图像宽度像素值(目前仅为双面扫描故尺寸为单面尺寸乘以2)
#define IMG_WIDTH_200DPI 1728 * 2
#define IMG_WIDTH_150DPI 1296 * 2
#define IMG_HEIGHT_200DPI 3600
#define IMG_HEIGHT_300DPI 4050
#define IMG_HEIGHT_150DPI 2025
//原始图像相对于200dpi 系数
#define IMG_W_RADIO 1/1.5
#define IMG_H_RADIO 1
// 图像像素值
#ifdef HAS_UV
// #define SPI_COLOR 0x03D81001
// #define SPI_GRAY 0x13001000
#define SPI_COLOR 0x05181001
#define SPI_GRAY 0x19501000
// 0x19501000, 0x05181001
#else
const int SPI_SP = 0x04b0;
const int SPI_SAMPLE = 256;
const int SPI_COLOR_MODE = SM_COLOR;
const int SCAN_PAPER_TYPE = SPT_A4;
#endif
const int IMG_HEIGHT = 9000;
const int IMG_V4L_WIDTH = SPTSizes[SCAN_PAPER_TYPE];
const int FRAME_COUNT = 3;
const int TEST_FRAME = 1;
const int TEST_ENABLE = 0;
const int LED_ENABLE = 1;
const bool SAVE_ENABLE = true;
#endif

53
Properties.cpp Normal file
View File

@ -0,0 +1,53 @@
#include <algorithm>
#include "Properties.h"
namespace cppproperties {
Properties::Properties() {
}
Properties::~Properties() {
}
std::string Properties::GetProperty(const std::string& key) const {
if (properties.find(key) == properties.end()) {
throw PropertyNotFoundException(key + " does not exist");
}
return properties.at(key);
}
//前面把配置文件参数读取 分成key和val放入map从map取出val
std::string Properties::GetProperty(const std::string& key, const std::string& defaultValue) const {
if (key.compare("fpga.correctColor.BOffset") == 0)
printf("Get Config File Size (path: /usr/local/huago/ “properties” ) = %d \r\n",properties.size());
if (properties.find(key) == properties.end()) {
return defaultValue;
}
return properties.at(key);
}
std::vector<std::string> Properties::GetPropertyNames() const {
return keys;
}
//把配置文件参数写入map
void Properties::AddProperty(const std::string& key, const std::string& value) {
if (properties.find(key) == properties.end()) {
keys.push_back(key);
}
properties[key] = value;
}
void Properties::RemoveProperty(const std::string& key) {
if (properties.find(key) == properties.end()) {
throw PropertyNotFoundException(key + " does not exist");
}
keys.erase(std::remove(keys.begin(), keys.end(), key), keys.end());
properties.erase(key);
}
} /* namespace cppproperties */

55
Properties.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef PROPERTIES_H_
#define PROPERTIES_H_
#include <string>
#include <vector>
#include <map>
#include "PropertiesException.h"
#include "PropertyNotFoundException.h"
namespace cppproperties {
class Properties {
public:
Properties();
virtual ~Properties();
/**
* Gets the property value from a given key.
*
* This method throws a PropertyNotFoundException when a given key does not
* exist.
*/
std::string GetProperty(const std::string& key) const;
/**
* Gets the property value from a given key. Use a default value if not found.
*/
std::string GetProperty(const std::string& key, const std::string& defaultValue) const;
/**
* Gets the list of property names.
*/
std::vector<std::string> GetPropertyNames() const;
/**
* Adds a new property. If the property already exists, it'll overwrite
* the old one.
*/
void AddProperty(const std::string& key, const std::string& value);
/**
* Removes the property from a given key.
*
* If the property doesn't exist a PropertyNotFoundException will be thrown.
*/
void RemoveProperty(const std::string& key);
private:
// to preserve the order
std::vector<std::string> keys;
std::map<std::string, std::string> properties;
};
} /* namespace cppproperties */
#endif /* PROPERTIES_H_ */

26
PropertiesException.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef PROPERTIESEXCEPTION_H_
#define PROPERTIESEXCEPTION_H_
#include <string>
#include <exception>
namespace cppproperties {
class PropertiesException : public std::exception {
public:
PropertiesException() {}
PropertiesException(const std::string& msg) throw() : message(msg) {}
virtual ~PropertiesException() throw() {}
const std::string& str() const throw() { return message; }
virtual const char* what() const throw() { return message.c_str(); }
private:
std::string message;
};
} /* namespace cppproperties */
#endif /* PROPERTIESEXCEPTION_H_ */

78
PropertiesParser.cpp Normal file
View File

@ -0,0 +1,78 @@
#include <iostream>
#include <fstream>
#include <string>
#include <unistd.h>
#include "PropertiesParser.h"
#include "PropertiesUtils.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
namespace cppproperties {
PropertiesParser::PropertiesParser() {
}
PropertiesParser::~PropertiesParser() {
}
//读取配置文件参数放入map // fpga.correctColor.BOffset = 119,119,119,119,119,119
//路径 /usr/local/huago/fpga.properties //key //val
Properties PropertiesParser::Read(const std::string& file) {
Properties properties;
std::ifstream is;
is.open(file.c_str());
if (is.is_open()) {
try {
size_t linenr = 0;
std::string line;
while (getline(is, line)) {
if (PropertiesUtils::IsEmptyLine(line) || PropertiesUtils::IsComment(line)) {
// ignore it
} else if (PropertiesUtils::IsProperty(line)) {
std::pair<std::string, std::string> prop = PropertiesUtils::ParseProperty(line);
properties.AddProperty(prop.first, prop.second);
// if(prop.first == "fpga.correctColor.BOffset")
// printf("uuuuuuuuuuuuuuuuuuuu %s\r\n",prop.second.c_str());
}
++linenr;
}
is.close();
} catch (...) {
// don't forget to close the ifstream
is.close();
}
}
return properties;
}
//写入配置文件
void PropertiesParser::Write(const std::string& file, const Properties& props) {
std::ofstream os;
os.open(file.c_str());
if (!os.is_open()) {
throw PropertiesException("PropertiesParser::Write(" + file + "): Unable to open file for writing.");
}
try {
const std::vector<std::string>& keys = props.GetPropertyNames();
for (std::vector<std::string>::const_iterator i = keys.begin();
i != keys.end(); ++i) {
os << *i << " = " << props.GetProperty(*i) << std::endl;
}
os.close();
} catch (...) {
// don't forget to close the ofstream
os.close();
throw;
}
int fd = open(file.c_str(), O_RDONLY);
if (fd > 0)
{
fchmod(fd,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
close(fd);
}
}
} /* namespace cppproperties */

29
PropertiesParser.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef PROPERTIESPARSER_H_
#define PROPERTIESPARSER_H_
#include <string>
#include <exception>
#include "Properties.h"
namespace cppproperties {
class PropertiesParser {
public:
PropertiesParser();
virtual ~PropertiesParser();
/**
* Reads a properties file and returns a Properties object.
*/
static Properties Read(const std::string& file);
/**
* Writes Properties object to a file.
*/
static void Write(const std::string& file, const Properties& props);
};
} /* namespace cppproperties */
#endif /* PROPERTIESPARSER_H_ */

95
PropertiesUtils.cpp Normal file
View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2014 Fredy Wijaya
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "PropertiesUtils.h"
namespace cppproperties {
namespace PropertiesUtils {
namespace {
const std::string TRIM_DELIMITERS = " \f\n\r\t\v";
std::string ltrim(const std::string& str) {
std::string::size_type s = str.find_first_not_of(TRIM_DELIMITERS);
if (s == std::string::npos) {
return "";
}
return str.substr(s);
}
}
std::string RightTrim(const std::string& str) {
std::string::size_type s = str.find_last_not_of(TRIM_DELIMITERS);
if (s == std::string::npos) {
return "";
}
return str.substr(0, s+1);
}
std::string LeftTrim(const std::string& str) {
std::string rstr = ltrim(str);
while (rstr != ltrim(rstr)) {
rstr = ltrim(rstr);
}
return rstr;
}
std::string Trim(const std::string& str) {
return RightTrim(LeftTrim(str));
}
bool IsProperty(const std::string& str) {
std::string trimmedStr = LeftTrim(str);
std::string::size_type s = trimmedStr.find_first_of("=");
if (s == std::string::npos) {
return false;
}
std::string key = Trim(trimmedStr.substr(0, s));
// key can't be empty
if (key == "") {
return false;
}
return true;
}
std::pair<std::string, std::string> ParseProperty(const std::string& str) {
std::string trimmedStr = LeftTrim(str);
std::string::size_type s = trimmedStr.find_first_of("=");
std::string key = Trim(trimmedStr.substr(0, s));
std::string value = LeftTrim(trimmedStr.substr(s+1));
return std::pair<std::string, std::string>(key, value);
}
bool IsComment(const std::string& str) {
std::string trimmedStr = LeftTrim(str);
return trimmedStr[0] == '#';
}
bool IsEmptyLine(const std::string& str) {
std::string trimmedStr = LeftTrim(str);
return trimmedStr == "";
}
} // namespace PropertiesUtils
} // namespace cppproperties

55
PropertiesUtils.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef PROPERTIESUTILS_H_
#define PROPERTIESUTILS_H_
#include <string>
#include <utility>
namespace cppproperties {
namespace PropertiesUtils {
/**
* Left trims a string.
* This function doesn't modify the given str.
*/
std::string LeftTrim(const std::string& str);
/**
* Right trims a string.
* This function doesn't modify the given str.
*/
std::string RightTrim(const std::string& str);
/**
* Trims a string (perform a left and right trims).
* This function doesn't modify the given str.
*/
std::string Trim(const std::string& str);
/**
* Is a given string a property. A property must have the following format:
* key=value
*/
bool IsProperty(const std::string& str);
/**
* Parses a given property into a pair of key and value.
*
* ParseProperty assumes a given string has a correct format.
*/
std::pair<std::string, std::string> ParseProperty(const std::string& str);
/**
* Is a given string a comment? A comment starts with #
*/
bool IsComment(const std::string& str);
/**
* Is a given string empty?
*/
bool IsEmptyLine(const std::string& str);
} // namespace PropertiesUtils
} // namespace cppproperties
#endif /* PROPERTIESUTILS_H_ */

View File

@ -0,0 +1,27 @@
#ifndef PROPERTYNOTFOUNDEXCEPTION_H_
#define PROPERTYNOTFOUNDEXCEPTION_H_
#include <string>
#include <exception>
namespace cppproperties {
class PropertyNotFoundException : public std::exception {
public:
PropertyNotFoundException() {}
PropertyNotFoundException(const std::string& msg) throw() : message(msg) {}
virtual ~PropertyNotFoundException() throw() {}
const std::string& str() const throw() { return message; }
virtual const char* what() const throw() { return message.c_str(); }
private:
std::string message;
};
} /* namespace cppproperties */
#endif /* PROPERTYNOTFOUNDEXCEPTION_H_ */

38
Pwm.cpp Normal file
View File

@ -0,0 +1,38 @@
#include "Pwm.h"
#include "DevUtil.h"
#define PWMPATH "%s%d/pwm0/%s"
Pwm::Pwm(int port)
{
path_enable = string_format(PWMPATH, path_base.c_str(), port, path_enable.c_str());
path_duty_cycle = string_format(PWMPATH, path_base.c_str(), port, path_duty_cycle.c_str());
path_period = string_format(PWMPATH, path_base.c_str(), port, path_period.c_str());
}
Pwm::~Pwm()
{
}
void Pwm::setFreq(int freq)
{
int value = PWM_PERIOD / freq;
write_dev(path_period, value);
write_dev(path_duty_cycle, value / 2);
}
int Pwm::getFreq()
{
return PWM_PERIOD/read_dev_i(path_period);
}
void Pwm::enable(bool bEnable)
{
write_dev(path_enable, bEnable);
}
bool Pwm::isEnable()
{
return (bool)read_dev_i(path_enable);
}

22
Pwm.h Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include <string>
#define PWM_PERIOD 1000000000
class Pwm
{
public:
Pwm(int port);
~Pwm();
void setFreq(int freq);
int getFreq();
void enable(bool bEnable);
bool isEnable();
private:
const std::string path_base = "/sys/class/pwm/pwmchip";
std::string path_enable = "enable";
std::string path_duty_cycle = "duty_cycle";
std::string path_period = "period";
};

329
ScanConfig.cpp Normal file
View File

@ -0,0 +1,329 @@
#include "ScanConfig.h"
#include <sstream>
#include <unistd.h>
const char * PATH_FPAG_DUNNAN_CONFIG = "/usr/local/huago/dunnan_fpga.properties";
const char * PATH_FPAG_HUALING_CONFIG = "/usr/local/huago/hualing_fpga.properties";
//#define PATH_FPAG_CONFIG "/usr/local/huago/fpga.properties"
#define ETC_FPAG_CONFIG "/etc/fpga.properties"
Properties ScanConfig::fpgaProperties;
CaptureParams ScanConfig::captureParmars;
static const char *keys[] = {
"fpga.correctColor.AExposureR",
"fpga.correctColor.AExposureG",
"fpga.correctColor.AExposureB",
"fpga.correctColor.BExposureR",
"fpga.correctColor.BExposureG",
"fpga.correctColor.BExposureB",
"fpga.correctColor.gainA",
"fpga.correctColor.gainB",
"fpga.correctColor.AOffset",
"fpga.correctColor.BOffset",
"fpga.correctGray.AExposureR",
"fpga.correctGray.AExposureG",
"fpga.correctGray.AExposureB",
"fpga.correctGray.BExposureR",
"fpga.correctGray.BExposureG",
"fpga.correctGray.BExposureB",
"fpga.correctGray.gainA",
"fpga.correctGray.gainB",
"fpga.correctGray.AOffset",
"fpga.correctGray.BOffset",
"fpga.color.AExposureR",
"fpga.color.AExposureG",
"fpga.color.AExposureB",
"fpga.color.BExposureR",
"fpga.color.BExposureG",
"fpga.color.BExposureB",
"fpga.color.gainA",
"fpga.color.gainB",
"fpga.color.AOffset",
"fpga.color.BOffset",
"fpga.gray.AExposureR",
"fpga.gray.AExposureG",
"fpga.gray.AExposureB",
"fpga.gray.BExposureR",
"fpga.gray.BExposureG",
"fpga.gray.BExposureB",
"fpga.gray.gainA",
"fpga.gray.gainB",
"fpga.gray.AOffset",
"fpga.gray.BOffset",
"fpga.correctColor.UVExposureA",
"fpga.correctGray.UVExposureB",
"fpga.color.UVExposureA",
"fpga.gray.UVExposureA",
};
int parseInt(const std::string str){
if(str.compare(0, 2, "0X") == 0 || str.compare(0, 2, "0x") == 0){
return (int)std::strtol(str.c_str(),nullptr,16);
}else{
return std::atoi(str.c_str());
}
}
void ScanConfig::parseIntArray(const std::string& str, std::string split,int* p, int size){
int lastPosition = 0;
int index = -1;
int i = 0;
while(-1 != (index=str.find(split , lastPosition)) && i < size)
{
// vecString.push_back(str.substr(lastPosition, index - lastPosition));
*(p + i) = parseInt(str.substr(lastPosition, index - lastPosition));
lastPosition = index + split.size();
i ++;
}
std::string lastStr = str.substr(lastPosition);
if ( !lastStr.empty() && i < size)
{
*(p + i) = parseInt(lastStr);
}
}
ScanConfig::ScanConfig():cistype(CIS_T_S0,CIS_T_S1,CIS_T_S2,CIS_T_S3){
if(cistype.GetCisType () == CISVendor::DUNNAN_CIS_V0)
{
PATH_FPAG_CONFIG = PATH_FPAG_DUNNAN_CONFIG;
if(access(PATH_FPAG_CONFIG,F_OK) == -1){
PATH_FPAG_CONFIG = "/usr/local/huago/fpga.properties";
}
}
if(cistype.GetCisType () == CISVendor::HUALIN_CIS_V0)
{
PATH_FPAG_CONFIG = PATH_FPAG_HUALING_CONFIG;
if(access(PATH_FPAG_CONFIG,F_OK) == -1){
PATH_FPAG_CONFIG = "/usr/local/huago/fpga.properties";
}
}
//printf("PATH_FPAG_CONFIG == %s \r\n",PATH_FPAG_CONFIG);
if(access(PATH_FPAG_CONFIG,F_OK) !=-1){
fpgaProperties = PropertiesParser::Read(PATH_FPAG_CONFIG);
}else{
fpgaProperties = PropertiesParser::Read(ETC_FPAG_CONFIG);
std::cout<<"error 88888888888888888888"<<std::endl;
}
std::cout << "fpgaProperties:" << fpgaProperties.GetProperty(std::string("fpga.").append("color").append(".gainB"), "200") << std::endl;
parseCaptureParams();
}
ScanConfig::~ScanConfig(){
}
void ScanConfig::parseCaptureParams(){
std::string str = fpgaProperties.GetProperty("fpga.correctColor.gainA", "50,50,50,50,50,50");
printf(" --------1111111111 strstrstr = %s \r\n",str.c_str());
parseIntArray(str, std :: string(","), captureParmars.correctColorGain[0], 6);
str = fpgaProperties.GetProperty("fpga.correctColor.gainB", "50,50,50,50,50,50");
parseIntArray(str, std :: string(","), captureParmars.correctColorGain[1], 6);
str = fpgaProperties.GetProperty("fpga.correctColor.AOffset", "50,50,50,50,50,50");
parseIntArray(str, std :: string(","), captureParmars.correctColorOffset[0], 6);
str = fpgaProperties.GetProperty("fpga.correctColor.BOffset", "50,50,50,50,50,50");
parseIntArray(str, std :: string(","), captureParmars.correctColorOffset[1], 6);
str = fpgaProperties.GetProperty("fpga.correctGray.gainA", "50,50,50,50,50,50");
parseIntArray(str, std :: string(","), captureParmars.correctGrayGain[0], 6);
str = fpgaProperties.GetProperty("fpga.correctGray.gainB", "50,50,50,50,50,50");
parseIntArray(str, std :: string(","), captureParmars.correctGrayGain[1], 6);
str = fpgaProperties.GetProperty("fpga.correctGray.AOffset", "50,50,50,50,50,50");
parseIntArray(str, std :: string(","), captureParmars.correctGrayOffset[0], 6);
str = fpgaProperties.GetProperty("fpga.correctGray.BOffset", "50,50,50,50,50,50");
parseIntArray(str, std :: string(","), captureParmars.correctGrayOffset[1], 6);
str = fpgaProperties.GetProperty("fpga.color.gainA", "50,50,50,50,50,50");
parseIntArray(str, std :: string(","), captureParmars.colorGain[0], 6);
str = fpgaProperties.GetProperty("fpga.color.gainB", "50,50,50,50,50,50");
parseIntArray(str, std :: string(","), captureParmars.colorGain[1], 6);
str = fpgaProperties.GetProperty("fpga.color.AOffset", "50,50,50,50,50,50");
parseIntArray(str, std :: string(","), captureParmars.colorOffset[0], 6);
str = fpgaProperties.GetProperty("fpga.color.BOffset", "50,50,50,50,50,50");
parseIntArray(str, std :: string(","), captureParmars.colorOffset[1], 6);
str = fpgaProperties.GetProperty("fpga.gray.gainA", "50,50,50,50,50,50");
parseIntArray(str, std :: string(","), captureParmars.grayGain[0], 6);
str = fpgaProperties.GetProperty("fpga.gray.gainB", "50,50,50,50,50,50");
parseIntArray(str, std :: string(","), captureParmars.grayGain[1], 6);
str = fpgaProperties.GetProperty("fpga.gray.AOffset", "50,50,50,50,50,50");
parseIntArray(str, std :: string(","), captureParmars.grayOffset[0], 6);
str = fpgaProperties.GetProperty("fpga.gray.BOffset", "50,50,50,50,50,50");
parseIntArray(str, std :: string(","), captureParmars.grayOffset[1], 6);
str = fpgaProperties.GetProperty("fpga.correctColor.AExposureR", "200");
captureParmars.correctColorExposure[0][0] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.correctColor.AExposureG", "200");
captureParmars.correctColorExposure[0][1] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.correctColor.AExposureB", "200");
captureParmars.correctColorExposure[0][2] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.correctColor.BExposureR", "200");
captureParmars.correctColorExposure[1][0] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.correctColor.BExposureG", "200");
captureParmars.correctColorExposure[1][1] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.correctColor.BExposureB", "200");
captureParmars.correctColorExposure[1][2] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.correctGray.AExposureR", "200");
captureParmars.correctGrayExposure[0][0] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.correctGray.AExposureG", "200");
captureParmars.correctGrayExposure[0][1] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.correctGray.AExposureB", "200");
captureParmars.correctGrayExposure[0][2] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.correctGray.BExposureR", "200");
captureParmars.correctGrayExposure[1][0] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.correctGray.BExposureG", "200");
captureParmars.correctGrayExposure[1][1] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.correctGray.BExposureB", "200");
captureParmars.correctGrayExposure[1][2] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.color.AExposureR", "200");
captureParmars.colorExposure[0][0] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.color.AExposureG", "200");
captureParmars.colorExposure[0][1] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.color.AExposureB", "200");
captureParmars.colorExposure[0][2] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.color.BExposureR", "200");
captureParmars.colorExposure[1][0] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.color.BExposureG", "200");
captureParmars.colorExposure[1][1] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.color.BExposureB", "200");
captureParmars.colorExposure[1][2] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.gray.AExposureR", "200");
captureParmars.grayExposure[0][0] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.gray.AExposureG", "200");
captureParmars.grayExposure[0][1] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.gray.AExposureB", "200");
captureParmars.grayExposure[0][2] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.gray.BExposureR", "200");
captureParmars.grayExposure[1][0] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.gray.BExposureG", "200");
captureParmars.grayExposure[1][1] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.gray.BExposureB", "200");
captureParmars.grayExposure[1][2] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.correctColor.UVExposureA", "200");
captureParmars.uvCorrectColorExposure[0] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.correctColor.UVExposureB", "200");
captureParmars.uvCorrectColorExposure[1] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.color.UVExposureA", "200");
captureParmars.uvColorExposure[0] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.color.UVExposureB", "200");
captureParmars.uvColorExposure[1] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.correctGray.UVExposureA", "0");
captureParmars.uvCorrectGrayExposure[0] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.correctGray.UVExposureB", "0");
captureParmars.uvCorrectGrayExposure[1] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.gray.UVExposureA", "0");
captureParmars.uvGrayExposure[0] = parseInt(str);
str = fpgaProperties.GetProperty("fpga.gray.UVExposureB", "0");
captureParmars.uvGrayExposure[1] = parseInt(str);
}
std::string parseString(int value){
std::string s;
std::stringstream ss;
ss << value;
ss >> s;
return s;
}
std::string parseArrayString(int *array, int len){
std::string s;
for(int i= 0; i < len; i ++){
s.append(parseString(array[i]));
if(i < len - 1)s.append(",");
}
return s;
}
//δʹ<CEB4><CAB9>
void ScanConfig::modifyCaptureParams(const char * key, const char * value){
fpgaProperties.AddProperty(key, value);
parseCaptureParams();
PropertiesParser::Write(PATH_FPAG_CONFIG, fpgaProperties);
}
std::string ScanConfig::getCaptureParmas(std::string key){
std::string ret = fpgaProperties.GetProperty(key, "");
if(ret.length() == 0){
fpgaProperties = PropertiesParser::Read(PATH_FPAG_CONFIG);
ret = fpgaProperties.GetProperty(key, "");
}
return ret;
}
void ScanConfig::save(){
int *p = (int *)&captureParmars;
for(int i = 0; i < 4; i ++ ){
int *params = p + 30 * i;
for(int j = 0; j < 6; j ++ ){
fpgaProperties.AddProperty(keys[10 * i + j ], parseString(params[j]));
}
for(int k = 0; k < 4; k ++ ){
fpgaProperties.AddProperty(keys[10 * i + k + 6], parseArrayString(&params[6 + 6 * k], 6));
}
}
PropertiesParser::Write(PATH_FPAG_CONFIG, fpgaProperties);
}
//<2F><><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD>
void ScanConfig::writeParamars(std::string type, int * params){
if(type.compare("color") == 0){
memcpy(captureParmars.colorExposure, params, 6 * sizeof(int));
memcpy(captureParmars.colorGain, &params[6], 12 * sizeof(int));
memcpy(captureParmars.colorOffset, &params[18], 12 * sizeof(int));
}else if(type.compare("correctColor") == 0){
memcpy(captureParmars.correctColorExposure, params, 6 * sizeof(int));
memcpy(captureParmars.correctColorGain, &params[6], 12 * sizeof(int));
memcpy(captureParmars.correctColorOffset, &params[18], 12 * sizeof(int));
}else if(type.compare("gray") == 0){
memcpy(captureParmars.grayExposure, params, 6 * sizeof(int));
memcpy(captureParmars.grayGain, &params[6], 12 * sizeof(int));
memcpy(captureParmars.grayOffset, &params[18], 12 * sizeof(int));
}else if(type.compare("correctGray") == 0){
memcpy(captureParmars.correctGrayExposure, params, 6 * sizeof(int));
memcpy(captureParmars.correctGrayGain, &params[6], 12 * sizeof(int));
memcpy(captureParmars.correctGrayOffset, &params[18], 12 * sizeof(int));
}
fpgaProperties.AddProperty("fpga." + type + ".AExposureR", parseString(params[0]));
fpgaProperties.AddProperty("fpga." + type + ".AExposureG", parseString(params[1]));
fpgaProperties.AddProperty("fpga." + type + ".AExposureB", parseString(params[2]));
fpgaProperties.AddProperty("fpga." + type + ".BExposureR", parseString(params[3]));
fpgaProperties.AddProperty("fpga." + type + ".BExposureG", parseString(params[4]));
fpgaProperties.AddProperty("fpga." + type + ".BExposureB", parseString(params[5]));
fpgaProperties.AddProperty("fpga." + type + ".gainA", parseArrayString(&params[6], 6));
fpgaProperties.AddProperty("fpga." + type + ".gainB", parseArrayString(&params[12], 6));
fpgaProperties.AddProperty("fpga." + type + ".AOffset", parseArrayString(&params[18], 6));
fpgaProperties.AddProperty("fpga." + type + ".BOffset", parseArrayString(&params[24], 6));
PropertiesParser::Write(PATH_FPAG_CONFIG, fpgaProperties);
}

58
ScanConfig.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef SCANCONFIG_H_
#define SCANCONFIG_H_
#include <iostream>
#include <cstdlib>
#include <sstream>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include "scanservices_utils.h"
#include "PropertiesParser.h"
#include "TypeIO.h"
#define PRO_SCAN_MODE "persist.sys.scan.mode"
#define PRO_COLOR_MODE "persist.sys.scan.color"
#define PRO_AUTO_ADJUST "persist.sys.scan.adjust"
#define PRO_AUTO_CUT "persist.sys.scan.cut"
#define PRO_QUALITY "persist.sys.scan.quality"
#define PRO_DOUBLE_CHECKED "persist.sys.scan.doublechk"
#define PRO_SCAN_QUALITY "persist.sys.scan.quality"
#define PRO_SKIP_BLANK "persist.sys.scan.skip"
#define PRO_COMPRESS_FORMAT "persist.sys.scan.compress"
#define PRO_SCAN_SETTING "persist.sys.scan.setting"
#define PRO_SCAN_PAGES "persist.sys.scan.page"
#define PRO_SCAN_TOTAL_PAGES "persist.sys.scan.total_page"
#define PRO_SCAN_CUOZHI "persist.sys.scan.cuozhi"
#define PRO_FPGA_UPDATE "persist.sys.fpga.update"
using namespace cppproperties;
template <class T>
std::string toString(const T &v)
{
std::ostringstream os;
os << v;
return os.str();
}
class ScanConfig{
private:
static Properties fpgaProperties;
void parseCaptureParams();
void parseIntArray(const std::string& str, std::string split,int* p, int size);
public:
ScanConfig();
~ScanConfig();
static CaptureParams captureParmars;
void modifyCaptureParams(const char *key, const char *value);
std::string getCaptureParmas(std::string key);
void writeParamars(std::string type, int * params);
void save();
void cpyCrtParam();
TypeIO cistype;
const char * PATH_FPAG_CONFIG ;
};
#endif

479
Scanner.cpp Normal file
View File

@ -0,0 +1,479 @@
#include "Scanner.h"
#include <iostream>
#include "filetools.h"
#include "fpgacontrol.h"
#include "MemoryInfo.h"
#include "SysInforTool.h"
#include "USBProtocol.h"
#define BTNSTART 0
#define BTNSTOP 1
#define BTNPOWER 2
Scanner::Scanner(ScannerGlue glue)
: motorZouzhi(),
motorCuozhi(),
m_glue(glue),
m_isPulling(false),
m_isDoublePaper(false),
isPaperInit(false),
m_jamPaper(false),
m_jamIn(false),
m_correctting(false),
waitpapertime(200),
m_scansysinfo(nullptr)
{
cisvendor = GetCisType();
LOG("Scanner init --------- \n");
m_scaninfo = GetScanInfoFromJson();
m_fpga = std::make_shared<FpgaComm>();
int version = m_fpga->read(15);
LOG("FPGA Version = %d \n",m_fpga->read(15));
capturer.reset(new MultiFrameCapture(m_glue, m_fpga,cisvendor));
// capturer.reset(new Capturer(m_glue,m_fpga));
capturer->SetParent(this);
fpgacontrol fc(version);
if (fc.ifneedupdatefpga())
{
if (fc.updatefpga())
{
//system("sh /etc/reloadfpga.sh");
system("poweroff");
}
else
{
LOG("error error update fpga error");
}
}
auto btnevent = [this](const int eventtype)
{
if (!IsScanning()) //未扫描
{
LOG("enter low power mode 000000000000 \n");
if (eventtype == BTNPOWER)
{
LOG("enter low power mode \n");
system("echo mem > /sys/power/state");
}
else if (eventtype == BTNSTART)
{
// put(S_EVT_START_SCAN);
}
}
else //扫描中
{
if (eventtype == BTNSTOP)
{
put(S_EVT_STOP_SCAN);
LOG("BTN_STOP put(S_EVT_STOP_SCAN)");
}
}
};
sensor = std::make_shared<Sensor>(sysEvent);
m_keyboard.reset(new huagao::Keyboard(btnevent));
m_keyboard->init();
motorZouzhi.enablePower(true);
motorZouzhi.setSpeed(4000);
motorCuozhi.setSpeed(3000);
motorCuozhi.setDirection(false);
//sensor->isPaperAtScan();
//system("cat /sys/class/gpio/gpio226/value");
sensor->enableDoubleSensor(true);
std::this_thread::sleep_for(std::chrono::milliseconds(50));
sensor->enableDoubleSensor(false);
FsmState::setScanner(this);
threadRunMessageLoop = std::thread(&Scanner::runMessageLoop, this);
Motor::enablePower(true);
//meminfo = MemoryInfo::GetInstance();
//GetSysInfo();
}
Scanner::~Scanner()
{
Motor::enablePower(false);
sysEvent.Clear();
sysEvent.ShutDown();
bMsgLoop = false;
threadRunMessageLoop.join();
m_DstScannum = 0;
if (threadRunScan.joinable())
threadRunScan.join();
}
void Scanner::updateSpeedMode(int speed)
{
m_scaninfo = GetScanInfoFromJson();
if(m_scaninfo.SpeedMode==0)
m_scaninfo.SpeedMode=3;
LOG("Scanner SET updateSpeedMode %d------ \n",m_scaninfo.SpeedMode);
unsigned int t_dpi=m_config.params.dpi;
// if(typeid(*capturer)==typeid(MonoCapturer))
// {
// if(m_config.params.dpi==0x03&& m_scansysinfo->IsSmallRam())
// t_dpi=0x02;
// else
// t_dpi = m_config.params.dpi;
// }
if(typeid(*capturer)==typeid(MultiFrameCapture))
if(m_config.params.pageSize == 17 || m_config.params.pageSize == 19) //长文稿采用600dpi模式扫描
t_dpi = 3;
motorCuozhi.speedChange(m_scaninfo.SpeedMode, t_dpi,m_config.params.isColor);
motorZouzhi.speedChange(m_scaninfo.SpeedMode, t_dpi,m_config.params.isColor);
}
void Scanner::startScan()
{
if (threadRunScan.joinable())
threadRunScan.join();
stop_countdown();
updateSpeedMode(4);
// //开始进行扫描
threadRunScan = std::thread(&Scanner::runScan, this);
writesyslog(LOG_INFO, getmeminfo());
// HG_ScanConfiguration cfg;
// cfg.params.dpi=2;
// cfg.params.isColor = 1;
// cfg.params.pageSize = 1;
// capturer->UpdateScanParam(cfg);
// for(int i = 0;i<1;i++)
// {
// capturer->open();
// capturer->snap();
// capturer->capturerImage();
// capturer->close();
// // std::this_thread::sleep_for(std::chrono::milliseconds(4000));//避免scanpin io 开始异常
// }
// //capturer->close();
}
void Scanner::runMessageLoop()
{
std::this_thread::sleep_for(std::chrono::milliseconds(3000));//避免scanpin io 开始异常
GetSysInfo();//待fpga 重启完成
FsmState *fsmState = FsmStateManagerEx<InitState>::GetState();
while (bMsgLoop)
{
ScanEvent evt = sysEvent.Take();
//LOG("\n---------------------%d--------------------------\n", evt);
fsmState = fsmState->on_event(evt);
//printf("current fsmState =%s ",typeid(*fsmState).name());
processevent(fsmState, evt);
}
}
void Scanner::processevent(FsmState *fsmState, ScanEvent event)
{
LOG("processevent Event:%d\n", (int)event);
if (fsmState == nullptr)
{
LOG("processevent BBBBBBBBBBBBBB Event:%d\n", (int)event);
return;
}
if (typeid(*fsmState) == typeid(CoverOpenState))
{
m_glue.m_deviceevent(1, "Cover Open");
}
else if (event == S_EVT_SCAN_STOPPED)
{
if (!m_correctting)
{
m_glue.m_deviceevent(70, "Scan done");
}
}
else if (event == S_EVT_JAM_IN)
{
m_glue.m_deviceevent(4, "Feed error");
}
else if (event == S_EVT_DOUBLEPAPER)
{
m_glue.m_deviceevent(16, "Double feed");
}
else if (event == S_EVT_JAM_OUT || typeid(*fsmState) == typeid(ErrorJamState))
{
m_glue.m_deviceevent(8, "Jam out");
}
else if (typeid(*fsmState) == typeid(ErrorState) && m_jamIn == true)
{
m_glue.m_deviceevent(4, "Feed error");
}
if (!IsScanning() && (typeid(*fsmState) == typeid(ErrorJamState) ||
typeid(*fsmState) == typeid(CoverOpenState) ||
(typeid(*fsmState) == typeid(ErrorState) && m_jamIn == true)))
{
if (!m_correctting)
{
m_glue.m_deviceevent(70, "Scan Stop");
}
}
}
static int imageindex = 0;
void Scanner::runScan()
{
LOG("-------------Scanner RunScan Start-------------\r\n");
capturer->open();
motorZouzhi.start();
motorCuozhi.pauseWaitForThread();
//capturer->open();
sensor->enableDoubleSensor(false);
if (!isPaperInit)
{
preFeed();
isPaperInit = true;
}
for (size_t i = 0; i < 16; i++)
{
std::cout << string_format("reg[%d] = 0x%08x", i, capturer->read(i)) << std::endl;
}
imageindex = 0;
capturer->setFPGATriggerMode(false, 0);
capturer->setFanMode(3);
sensor->resetPaperPin();
capturer->clearimages();
capturer->resetimageremain();
capturer->setScanFlag(true);
int tmp_recordScannum = 0;
bool b_autosize = m_config.params.pageSize==(int)PaperSize::G400_AUTO ||
m_config.params.pageSize==(int)PaperSize::G400_MAXAUTO ||
m_config.params.pageSize==(int)PaperSize::G400_MAXSIZE;
StopWatch sw;
while (m_DstScannum > 0)
{
m_isDoublePaper = false;
m_jamPaper = false;
m_jamIn = false;
if (!sensor->isPaperStandby()) //无纸
{
if (!sensor->waitPaperStandBy(0))
{
// isPaperInit = false;
// this_thread::sleep_for(std::chrono::milliseconds(200));
LOG("\n ----------------EXIT 0000000000 cnt=%d---------------- \n",m_DstScannum);
put(S_EVT_STOP_SCAN);
LOG("STOP STOP STOP RUNSCAN \n");
writesyslog(LOG_INFO, getmeminfo());
writesyslog(LOG_INFO, "no paper scanner stop scan\n");
}
break;
}
else
{
//LOG(" Detect Feeder loaded ,Paper Ready !!! \n");
}
sensor->enableDoubleSensor(m_config.params.doubleFeeded);
//LOG("enableDoubleSensor QQQQQQQ:%s %s\n", m_config.params.doubleFeeded ? "true" : "false",GetCurrentTimeStamp(2).c_str());
if (m_DstScannum == 0) //被取消扫描了
{
LOG("canceled canceled canceled 999999999999999999999999999999999999999999 \n");
break;
}
motorCuozhi.startAsyn();
if (!sensor->isPaperStandby())
{
put(S_EVT_STOP_SCAN);
LOG("START SCAN LOOP STOP STOP STOP\n");
writesyslog(LOG_INFO, getmeminfo());
writesyslog(LOG_INFO, "no paper scanner stop scan\n");
isRested = false;
break;
}
isRested = false;
if (!sensor->waitPaperIn(3000))
{
LOG("START SCAN LOOP S_EVT_JAM_IN S_EVT_JAM_IN S_EVT_JAM_IN\n");
if (!m_isDoublePaper)
{
m_glue.m_deviceevent(4, "Feed error");
m_jamIn = true;
put(S_EVT_JAM_IN);
m_scaninfo.JamInNum++;
//writesyslog(LOG_INFO, "paper jam in error \n");
}
break;
}
//capturer->snap();
motorCuozhi.pauseWaitForThread();
int i = 0;
int max = 7;
#ifdef G400
if(m_config.params.pageSize >= (int)PaperSize::G400_LONGLETTER)
max = m_scaninfo.SpeedMode>3?10:16;
else
max = m_scaninfo.SpeedMode>3?5:8;
#else
if(m_config.params.pageSize >= (int)PaperSize::G400_LONGLETTER)
max = m_scaninfo.SpeedMode>3?10:25;
else
max = m_scaninfo.SpeedMode>3?5:8;
#endif
max = m_config.params.dpi > 2 ? 30 : max * m_config.params.dpi;
if(m_config.params.pageSize == 17 || m_config.params.pageSize == 19)
max = 200;
LOG("paper pauseWaitForThread \n");
waitpapertime = 400;
while (!sensor->waitPaperOut(waitpapertime) && i < max)
{
i++;
if (!sensor->isPaperIn())
{
LOG("paper 假卡纸了。。。。。\n");
break;
}
}
LOG("paper isPaperIn \n");
if (i == max && sensor->isPaperIn())
{
if (!m_isDoublePaper)
{
m_glue.m_deviceevent(8, "Jam out"); //卡纸
m_jamPaper = true;
put(S_EVT_JAM_OUT);
m_scaninfo.JamOutNum++;
LOG("paper 卡纸了。。。。。\n");
writesyslog(LOG_INFO, "paper jam out error\n");
}
else
{
// m_glue.m_deviceevent(16); //双张
// LOG("paper 双张了。。。。。\n");
m_scaninfo.DoubleNum++;
writesyslog(LOG_INFO, "paper double paper error\n");
}
//capturer->stopsnap(b_autosize);
//capturer->waitsnapdone(1);//等待采集完成
//this_thread::sleep_for(std::chrono::milliseconds(500));//200 80ms 600 260ms
LOG("\n ----------------EXIT 11111---------------- \n");
break;
}
LOG("\nclose double sensor %s\n",GetCurrentTimeStamp(2).c_str());
sensor->enableDoubleSensor(false);
if(b_autosize)
{
int dly_speed= (5 - m_scaninfo.SpeedMode)*10;
int delay = m_config.params.dpi==0x02?70:(m_config.params.dpi==0x03?350: 20);
if((m_config.params.pageSize == 17 || m_config.params.pageSize == 19)&&(delay < 350))
delay = 350;
if(m_config.params.pageSize == 18)
delay = std::max(delay,80);
delay+=dly_speed;
LOG("AutoSize sleep_for delay=%d \n",delay);
this_thread::sleep_for(std::chrono::milliseconds(delay));//200 80ms 600 260ms
}
if(b_autosize)
{
std::this_thread::sleep_for(std::chrono::milliseconds((5 - m_scaninfo.SpeedMode)*10*m_config.params.dpi));
if(sensor->isPaperAtScan())
{
m_glue.m_deviceevent((int)HG_ScannerStatus::PAPER_HOLE,"paper have hole");
capturer->stopsnap(b_autosize);
capturer->waitsnapdone(1);//等待采集完成
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
LOG("\nclose b_autosize %s\n",GetCurrentTimeStamp(2).c_str());
capturer->stopsnap(b_autosize);
capturer->waitsnapdone(m_isDoublePaper || m_jamPaper);//等待采集完成
m_DstScannum--;
m_scaninfo.RollerNum++;
m_scaninfo.TotalScanned++;
tmp_recordScannum++;
writesyslog(LOG_INFO, getmeminfo());
if (m_DstScannum == 0)
{
LOG("\n ----------------EXIT 2222 cnt=%d---------------- \n",m_DstScannum);
this_thread::sleep_for(std::chrono::milliseconds(200));
put(S_EVT_STOP_SCAN);
break;
}
sw.reset();
while (meminfo->GetMemoryUsed() > 70.0f||(m_config.params.dpi ==0x03 && capturer->getimageremain()>1)) //内存占用高于75%
{
if (sw.elapsed_s() < 20.0)
std::this_thread::yield();
else
{
LOG("\n ----------------EXIT 3333---------------- \n");
put(S_EVT_STOP_SCAN);
break;
}
}
}
// motorCuozhi.stop();
// motorZouzhi.stop();
// auto js = GetScanInfoFromJson();
// m_scaninfo.SleepTime = js.SleepTime;
m_DstScannum = 0;
sensor->enableDoubleSensor(false);
sensor->resetPaperPin();
capturer->setScanFlag(false);
capturer->close();
int t_delay = m_config.params.dpi == 0x02 ? 150 : (m_config.params.dpi == 0x03 ? 350 : 100);
this_thread::sleep_for(std::chrono::milliseconds(t_delay)); //走纸多转一会儿 确保扫描传感器过了之后 纸能出完
capturer->setFanMode(0);
LOG("\n--------------------------scan done --------------------------------\n");
std::string loginfo = "current scan session scanned " + to_string(tmp_recordScannum) + " page paper\n";
writesyslog(LOG_INFO, loginfo);
}
void Scanner::CreatCorrectData(int correctmode)
{
m_correctting = true;
LOG("\n-----------------校正模式 %d-----------------------\n",correctmode);
capturer->createCorrect(correctmode);
}
void Scanner::preFeed()
{
int sleeptime = 300;
motorCuozhi.feeding();
std::this_thread::sleep_for(std::chrono::milliseconds(sleeptime));
motorCuozhi.pause();
std::this_thread::sleep_for(std::chrono::milliseconds(300));
}
std::string Scanner::GetSysInfo()
{
meminfo = MemoryInfo::GetInstance();
LOG(" GetSysInfo-------- \n");
auto scannerinfo = GetScanInfo();
auto fwverion = mapFradme_SP[scannerinfo.SpeedMode].FWVERSIO;
ScannerSysInfo info = {
.CPU = SCPU::CPU_3288,
.Systype = SysType::Sys_Linux_Debian,
.Screentype = ScreenType::ST_None,
.MtBoardVersion = 0x20220114,
.MtType = GetSMBType(),
.FPGAVersion = m_fpga->read(15),
.Cistype = (HGCISType)GetCisType(),
.ResSup = {200, 300, 0},
.MemTotal = 0,
.DiskTotal = 100,
.DiskUsed = 0,
.KernelVersion = "",
.Have_EthernPort = 0,
.ServiceVersion = fwverion,
.UsbProtocol = 1.0};
LOG("FPGAVersion=%08x \n",info.FPGAVersion);
m_scansysinfo.reset(new SysInforTool(info));
return m_scansysinfo->GetSysInfo();
}

243
Scanner.h Normal file
View File

@ -0,0 +1,243 @@
#pragma once
#include <memory>
#include <functional>
#include "CuoZhiMotor.h"
#include "ZouZhiMotor.h"
#include "Sensor.h"
#include "PanelLeds.h"
#include "BlockingQueue.h"
#include "FsmState.h"
#include "MultiFrameCapture.h"
#include "scanservices_utils.h"
#include "Keyboard.h"
#include "utilsfunc.h"
#include "filetools.h"
#include "SysInforTool.h"
#include "MotorConfig.h"
#include "correct_ultis.h"
#include "FpgaComm.h"
class ICapturer;
class MemoryInfo;
// class SysInforTool;
class Scanner
{
public:
Scanner(ScannerGlue glue);
~Scanner();
public:
bool isRested = false;
void startScan();
void emergency_stop(int id)
{
sensor->enableDoubleSensor(false);
sensor->cancelWaitPaper();
m_DstScannum = 0;
if (id == 1) //双张
m_glue.m_deviceevent(16, "double feed");
motorCuozhi.stop();
motorZouzhi.stop();
//capturer->close();
put(S_EVT_SCAN_STOPPED);
SaveScaninfo(m_scaninfo);
start_enter_lowpwoer();
LOG("emergency_stop capturer->close() \n");
}
void stop_scan()
{
//LOG("!!!!!!!!!!!!!!!!!!!!!stop_scan() waitting snap session done \n");
sensor->enableDoubleSensor(false);
sensor->cancelWaitPaper();
m_DstScannum = 0;
//LOG("!!!!!!!!!!!!!!!!!!!!!!!!!!stop_scan() waitting snap session done \n");
if (threadRunScan.joinable())
threadRunScan.join();
motorZouzhi.stop();
motorCuozhi.stop();
// std::this_thread::sleep_for(std::chrono::milliseconds(200));
//capturer->close();
put(S_EVT_SCAN_STOPPED);
SaveScaninfo(m_scaninfo);
start_enter_lowpwoer();
//LOG("stop_scan() readimageDone() exit22222222 \n");
}
Sensor &getSensor() { return *sensor.get(); }
PanelLeds &getPanelLeds() { return panelLeds; }
int readreg(int addr) { return capturer->read(addr); }
void put(ScanEvent evt) { sysEvent.Put(evt); }
void reset()
{
if (!sensor->isPaperStandby())
{
motorCuozhi.reset();
isRested = true;
isPaperInit = false;
LOG("Scanner->motorCuozhi is reseted \n");
}
}
void paperReady()
{
LOG("paperReady 22222222 \n");
motorZouzhi.start();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
motorZouzhi.stop();
}
bool isFeederLoaded() { return sensor->isPaperStandby(); }
void ConfigScanParam(HG_ScanConfiguration config)
{
// if (config.params.dpi == 0)
// config.params.dpi = 1;
m_config = config;
LOG("m_config.params.dpi = %d \n \
m_config.params.isColor = %d \n \
m_config.params.pageSize = %d \n \
m_config.params.isCorrect = %d \n",
m_config.params.dpi,
m_config.params.isColor,
m_config.params.pageSize,
m_config.params.isCorrect);
capturer->UpdateScanParam(config);
}
void CreatCorrectData(int correctmode);
void SetDstScanNum(int scannum) { m_DstScannum = scannum; }
void paper_pullout()
{
LOG("paper_pullout 22222222 \n");
if (!m_isPulling)
m_isPulling = true;
motorCuozhi.stop();
motorZouzhi.speedChange(1);
motorZouzhi.setDirection(1);
motorZouzhi.start();
if (sensor->waitPaperOut(5000))
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
motorZouzhi.stop();
motorZouzhi.speedRecover();
m_isPulling = false;
}
void SetIsDoublePaper(bool isdoublepaper)
{
m_isDoublePaper = isdoublepaper;
}
bool GetIsDoublePaper()
{
return m_isDoublePaper;
}
bool GetIsJamPaper()
{
return m_jamPaper;
}
bool GetIsJamIn()
{
return m_jamIn;
}
void ResetJamIn()
{
m_jamIn = false;
}
bool IsScanning()
{
return !capturer->IsImageQueueEmpty();
}
void writeParamars(std::string type, int *value)
{
// capturer->m_configprop->writeParamars(type, value);
}
void UpdateScanInfo()
{
m_scaninfo = GetScanInfoFromJson();
MotorConfig::MTBDType smbtype = GetSMBType() == SMBType::MB_DRV_8825 ? MotorConfig::MTBDType::MT_DRV : MotorConfig::MTBDType::MT_TMC;
auto params = MotorConfig().GetMotorSpeedParams(true, smbtype);
for (int i = 0; i < params.size(); i++)
{
if (params[i].speed == m_scaninfo.SpeedMode)
{
// auto fpgaparam = GetFpgaparam(params[i].dpi, params[i].colormode);
// fpgaparam.Sp = params[i].sp;
// SaveFpgaparam(fpgaparam);
}
}
printf(" UpdateScanInfo speed mode = %d \n",m_scaninfo.SpeedMode);
updateSpeedMode(m_scaninfo.SpeedMode);
}
CaptureParams GetCaptureParams()
{
CaptureParams param;
return param;
// return capturer->m_configprop->captureParmars;
}
ScannerScanInfo &GetScanInfo()
{
return m_scaninfo;
}
void updateSpeedMode(int speed);
void ResetCorrectflags() { m_correctting = false; }
void StopScan(int Evt)
{
put(S_EVT_STOP_SCAN);
//capturer->clearimages();
//capturer->resetimageremain();
//m_glue.m_deviceevent(70, "Scan done");
}
std::string GetSysInfo();
ScannerSysInfo &GetSysinfoStruct() { return m_scansysinfo->GetInfo(); }
private:
//处理事件
void processevent(FsmState *fsmState, ScanEvent event);
void startZouzhi() { motorZouzhi.start(); }
void stopZouzhi() { motorZouzhi.stop(); }
void startCuozhi() { motorCuozhi.start(); }
void stopCuozhi() { motorCuozhi.stop(); }
//运行消息循环
void runMessageLoop();
void runScan();
void preFeed();
private:
ZouZhiMotor motorZouzhi;
CuoZhiMotor motorCuozhi;
std::shared_ptr<Sensor> sensor;
PanelLeds panelLeds;
std::thread threadRunScan;
std::thread threadRunMessageLoop;
volatile bool bMsgLoop = true;
BlockingQueue<ScanEvent> sysEvent;
std::shared_ptr<ICapturer> capturer;
std::shared_ptr<huagao::Keyboard> m_keyboard;
ScannerGlue m_glue;
HG_ScanConfiguration m_config;
ScannerScanInfo m_scaninfo;
std::thread m_correctThread;
volatile int m_DstScannum = 500;
bool m_isPulling;
volatile bool m_isDoublePaper;
volatile bool m_jamPaper;
volatile bool m_jamIn;
bool isPaperInit;
volatile bool m_correctting;
int waitpapertime;
MemoryInfo *meminfo;
CISVendor cisvendor;
std::shared_ptr<SysInforTool> m_scansysinfo;
std::shared_ptr<ICapturer> m_capturer;
std::shared_ptr<FpgaComm> m_fpga;
};

256
Sensor.cpp Normal file
View File

@ -0,0 +1,256 @@
#include "Sensor.h"
#include "DevUtil.h"
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#include <thread>
#include <vector>
#include <iostream>
#include <stdio.h>
#include "filetools.h"
//FileTools ftt("/home/linaro/scanpin.log");
Sensor::Sensor(BlockingQueue<ScanEvent> &sysEvents)
:events(sysEvents),
pwm2(2),
coverPin(PIN_PORT_7010::OPEN_COVER_SENSOR),
paperPin(PIN_PORT_7010::HAVE_OR_NO_PAPER),
scanPin (PIN_PORT_7010::SCAN_SENSOR),
doubleEnablePin(PIN_PORT_7010::ULTRASONIC_SENSORS_ON),
double_out0_Pin(PIN_PORT_7010::ULTRASONIC_SENSORS_OUT0),
double_out1_Pin(PIN_PORT_7010::ULTRASONIC_SENSORS_OUT1),
sensor_power(PIN_PORT_7010::SENSOR_POWER)
{
pwm2.enable(Gpio::High);
pwm2.setFreq(2583);
sensor_power.setDirection(Gpio::in);
sensor_power.setValue(Gpio::High); //默认打开电源
coverPin.setDirection(Gpio::in);
paperPin.setDirection(Gpio::in);
double_out0_Pin.setDirection(Gpio::in);
double_out1_Pin.setDirection(Gpio::in);
//paperJamPin.setDirection(Gpio::in);
scanPin.setDirection(Gpio::in);
scanPin.setEdge(Gpio::both);
doubleEnablePin.setDirection(Gpio::out);
coverPin.setEdge(Gpio::both);
paperPin.setEdge(Gpio::both);
double_out0_Pin.setEdge(Gpio::both);
double_out1_Pin.setEdge(Gpio::both);
//std::cout<<"scanPin "<< scanPin.getValue()<<std::endl;
thread_monitor = std::thread(&Sensor::monitor, this);
thread_monitor2 = std::thread(&Sensor::monitor2, this);
enableDoubleSensor(true);
std::this_thread::sleep_for(std::chrono::milliseconds(10));
enableDoubleSensor(false);
LOG(" init sensor done \n");
}
Sensor::~Sensor()
{
bMonitor = false;
bMonitor2 = false;
if(thread_monitor.joinable())
thread_monitor.join();
if(thread_monitor2.joinable())
thread_monitor2.join();
}
bool Sensor::isCoverClosed()
{
std::cout<<"isCoverClosed "<< coverPin.getValue()<<std::endl;
return coverPin.getValue() == Gpio::Low;
}
void Sensor::resetPaperPin()
{
scanPin.setDirection("in");
}
bool Sensor::isPaperStandby()
{
std::cout<<"isPaperStandby "<< paperPin.getValue()<<std::endl;
return paperPin.getValue();
}
bool Sensor::isPaperAtScan()
{
//std::cout<<"scanPin "<< scanPin.getValue()<<std::endl;
return scanPin.getValue();
}
bool Sensor::isDoublePaper()
{
return doubleEnablePin.getValue();
}
bool Sensor::waitPaperIn(int timeout_ms)
{
std::unique_lock<std::mutex> lck(cv_m);
return cv_scan_at.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::no_timeout;
}
bool Sensor::waitPaperOut(int timeout_ms)
{
std::unique_lock<std::mutex> lck(cv_m);
if (!isPaperIn())
{
LOG("scanPin Value is low! \n");
return true;
}
cv_scan_not_at.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::no_timeout;
return !isPaperIn();
}
bool Sensor::waitPaperStandBy(int timeout_ms)
{
if(!paperPin.getValue()) {
return true;
}
if(timeout_ms <= 0) {
return isPaperStandby();
}
std::unique_lock<std::mutex> lck(cv_m);
return cv_paper_on.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::no_timeout;
}
void Sensor::cancelWaitPaper()
{
cv_paper_on.notify_all();
}
void Sensor::monitor()
{
std::condition_variable *edges[] = {&cv_scan_not_at, &cv_scan_at};
pollfd pfd;
int ret = 0;
pfd.fd = -1;
char buf[8];
int num;
pfd.fd = open(scanPin.getValuePath().c_str(), O_RDONLY);
if (pfd.fd < 0)
{
ret = -1;
}
pfd.events = POLLPRI;
StopWatch sw;
num = read(pfd.fd, buf, 8); // This is to clear the avaible read
std::cout<<"read time "<< sw.elapsed_ms()<<std::endl;
while (bMonitor)
{
ret = poll(&pfd, 1, 1000);
if (ret > 0)
{
if (pfd.revents & POLLPRI)
{
LOG(" ------------------------ scanpin running--------------------- \n");
lseek(pfd.fd, 0, SEEK_SET);
num = read(pfd.fd, buf, 8);
buf[num - 1] = '\0';
ret = atoi(buf);
//ftt.append_log(ret?"in":"out");
edges[ret]->notify_all();
LOG("\n *************scanpin %d time = %s ********* \n",ret,GetCurrentTimeStamp(2).c_str());
//sw.reset();
while(sw.elapsed_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);
}
void Sensor::monitor2()
{
ScanEvent evts[] = {S_EVT_COVER_CLOSED, S_EVT_COVER_OPENED , S_EVT_PAPER_STANDBY, S_EVT_PAPER_NOT_STANDBY,
S_EVT_NOT_DOUBLEPAPER, S_EVT_DOUBLEPAPER, S_EVT_JAM_OUT, S_EVT_NORES};
std::vector<Gpio *> gpios;
gpios.push_back(&coverPin);
gpios.push_back(&paperPin);
//gpios.push_back(&double_out0_Pin);
//gpios.push_back(&double_out1_Pin);
std::vector<pollfd> pollfds;
pollfd pfd;
int ret = 0;
int fd = -1;
char buf[8];
int num;
LOG(" ------------------------ monitor2 running \n");
for (size_t i = 0; i < gpios.size(); ++i)
{
fd = open(gpios[i]->getValuePath().c_str(), O_RDONLY);
LOG(" ------------------------ monitor2 open gpio[%d]=%s \n",i,gpios[i]->getValuePath().c_str());
if (fd < 0)
{
ret = -1;
LOG(" ------------------------ monitor2 open break \n");
break;
}
pfd.fd = fd;
pfd.events = POLLPRI;
num = read(fd, buf, 8); // This is to clear the avaible read
pollfds.push_back(pfd);
}
LOG(" ------------------------ monitor2 while running \n");
if (ret >= 0)
{
bMonitor2 = true;
while (bMonitor2)
{
static int poll_t = 0;
ret = poll(&pollfds[0], pollfds.size(), 1000);
//LOG(" ------------------------ monitor2 while running poll_t=%d ret=%d \n",++poll_t,ret);
if (ret > 0)
{
for (size_t i = 0; i < pollfds.size(); ++i)
{
if (pollfds[i].revents)
{
fd = pollfds[i].fd;
lseek(fd, 0, SEEK_SET);
num = read(fd, buf, 8);
buf[num - 1] = '\0';
ret = atoi(buf);
LOG("event id : %d i= %d \n",evts[i * 2 + ret] , i );
if(evts[i * 2 + ret] == 272)
{
LOG("\n\n---------------double paper ----------------:%s \n\n", GetCurrentTimeStamp(2).c_str());
enableDoubleSensor(false);
}
if(i == 1)
{
LOG("paper sensor ret:%d \n", ret);
cv_paper_on.notify_all();
}
events.Put(evts[i * 2 + ret]);
}
}
}
}
}
for (size_t i = 0; i < pollfds.size(); ++i)
{
close(pollfds[i].fd);
}
}

65
Sensor.h Normal file
View File

@ -0,0 +1,65 @@
#pragma once
#include "Gpio.h"
#include <thread>
#include <condition_variable>
#include "BlockingQueue.h"
#include "FsmState.h"
#include "Pwm.h"
class Sensor
{
public:
Sensor(BlockingQueue<ScanEvent>& sysEvents);
~Sensor();
void enableDoubleSensor(bool enable) {
doubleEnablePin.setValue((Gpio::GpioLevel)enable);
}
void resetPaperPin();
//是否扫描仪盖关上
bool isCoverClosed();
//是否纸张准备好
bool isPaperStandby();
//扫描时是否有纸张
bool isPaperAtScan();
//是否双张
bool isDoublePaper();
//等纸进来
bool waitPaperIn(int timeout_ms);
//等纸出去
bool waitPaperOut(int timeout_ms);
//纸在里面吗
bool isPaperIn(){return scanPin.getValue();}
//等纸,待命
bool waitPaperStandBy(int timeout_ms);
//取消等待纸张
void cancelWaitPaper();
private:
Gpio coverPin; //开盖
Gpio paperPin; //有无纸
Gpio scanPin; //扫描传感器
Gpio double_out0_Pin;
Gpio double_out1_Pin;
Gpio doubleEnablePin;
Gpio sensor_power;
Pwm pwm2;
BlockingQueue<ScanEvent>& events;
std::mutex cv_m;
std::condition_variable cv_cover_opened;
std::condition_variable cv_cover_closed;
std::condition_variable cv_paper_on;
std::condition_variable cv_paper_off;
std::condition_variable cv_scan_at;
std::condition_variable cv_scan_not_at;
std::condition_variable cv_double;
std::thread thread_monitor;
std::thread thread_monitor2;
volatile bool bMonitor = true;
volatile bool bMonitor2 = true;
void monitor();
void monitor2();
};

208
SysInforTool.cpp Normal file
View File

@ -0,0 +1,208 @@
#include "SysInforTool.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/vfs.h>
#include <sys/types.h>
#include <sys/sysinfo.h>
#include <sys/utsname.h>
#include <errno.h>
#include <fstream>
#include <iostream>
#include <iomanip>
extern int errno;
void get_system_output(char *cmd, char *output, int size)
{
FILE *fp = NULL;
fp = popen(cmd, "r");
if (fp)
{
if (fgets(output, size, fp) != NULL)
{
if (output[strlen(output) - 1] == '\n')
output[strlen(output) - 1] = '\0';
}
pclose(fp);
}
}
/*block to kbyte*/
unsigned long kscale(unsigned long m_block, unsigned long m_kbyte)
{
return ((unsigned long long)m_block * m_kbyte + 1024 / 2) / 1024;
}
/*convert size to GB MB KB*/
void convert_size(float m_size, int *dest)
{
if ((((m_size / 1024.0) / 1024.0)) >= 1.0)
{
*dest = (int)((m_size / 1024.0) / 1024.0);
}
else if ((m_size / 1024.0) >= 1.0)
{
*dest = (int)(m_size / 1024);
}
}
SysInforTool::SysInforTool(ScannerSysInfo tinfo)
{
m_sysinfo = tinfo;
}
ScannerSysInfo &SysInforTool::GetInfo()
{
return m_sysinfo;
}
SysInforTool::~SysInforTool()
{
}
/*获取文件系统信息*/
int SysInforTool::get_fileSystem_info(const char *fileSystem_name, struct fileSystem_info *fi)
{
struct statfs buf;
float fileSystem_total_size = 0;
float fileSystem_free_size = 0;
if (statfs(fileSystem_name, &buf))
{
fprintf(stderr, "statfs %s\n", strerror(errno));
return -1;
}
switch (buf.f_type)
{
case 0xEF51:
case 0xEF53:
sprintf(fi->fileSystem_format, "EXT");
break;
case 0x4d44:
sprintf(fi->fileSystem_format, "FAT");
break;
case 0x5346544e:
sprintf(fi->fileSystem_format, "NIFS");
break;
default:
sprintf(fi->fileSystem_format, "unknown");
break;
}
// bzero(&fi->fileSystem_total_capacity,sizeof(fi->fileSystem_total_capacity));
// bzero(&fi->fileSystem_free_capacity,sizeof(fi->fileSystem_free_capacity));
printf("blocks %ld\n", buf.f_blocks);
printf("bfree %ld\n", buf.f_bfree);
printf("bsize %ld\n", buf.f_bsize);
fileSystem_total_size =
(float)(kscale(buf.f_blocks, buf.f_bsize));
fileSystem_free_size =
(float)(kscale(buf.f_bfree, buf.f_bsize));
printf("total %f\n", fileSystem_total_size);
printf("free %f\n", fileSystem_free_size);
fi->fileSystem_total_capacity = fileSystem_total_size;
fi->fileSystem_free_capacity = fileSystem_free_size;
// convert_size(fileSystem_total_size,(int*)(&fi->fileSystem_total_capacity));
// convert_size(fileSystem_free_size,(int*)(&fi->fileSystem_free_capacity));
bzero(fi->fileSystem_permissions, sizeof(fi->fileSystem_permissions));
sprintf(fi->fileSystem_permissions, "rw");
return 0;
}
unsigned int SysInforTool::GetMemTotal()
{
unsigned int totalmem=0;
struct sysinfo memInfo;
sysinfo(&memInfo);
return memInfo.totalram;
}
bool SysInforTool::IsSmallRam()
{
return GetMemTotal()<=2147483648;
}
std::string SysInforTool::GetSysInfo()
{
struct sysinfo memInfo;
sysinfo(&memInfo);
m_sysinfo.MemTotal = memInfo.totalram;
#ifdef G400
m_sysinfo.MemTotal > 2147483648 ? m_sysinfo.ResSup[2] = 600 : m_sysinfo.ResSup[2] = 0;
#else
if(m_sysinfo.FPGAVersion == 0x00060001)
{
m_sysinfo.ResSup[0] = 200;
m_sysinfo.ResSup[1] = m_sysinfo.ResSup[2]=0;
}
else
{
m_sysinfo.ResSup[0]= m_sysinfo.ResSup[1]= m_sysinfo.ResSup[2]=0;
}
#endif
fileSystem_info fileinfo;
get_fileSystem_info("/", &fileinfo);
m_sysinfo.DiskTotal = fileinfo.fileSystem_total_capacity; // KB
m_sysinfo.DiskUsed = fileinfo.fileSystem_free_capacity; // KB
struct utsname t_uname;
if (uname(&t_uname) != 0)
perror("uname doesn't return 0, so there is an error");
printf("System Name = %s\n", t_uname.sysname);
printf("Node Name = %s\n", t_uname.nodename);
printf("Version = %s\n", t_uname.version);
printf("Release = %s\n", t_uname.release);
printf("Machine = %s\n", t_uname.machine);
if (strcmp(t_uname.nodename, "linaro-alip") == 0 && strcmp(t_uname.machine, "armv7l") == 0)
{
m_sysinfo.Systype = SysType::Sys_Linux_Debian;
m_sysinfo.CPU = SCPU::CPU_3288;
printf("Machine = %s CPU = %s \n", "Sys_Linux_Debian", "CPU_3288");
}
else if (strcmp(t_uname.nodename, "linaro-alip") == 0 && strcmp(t_uname.machine, "aarch64") == 0)
{
m_sysinfo.Systype = SysType::Sys_Linux_Debian;
m_sysinfo.CPU = SCPU::CPU_3399;
printf("Machine = %s CPU = %s \n", "Sys_Linux_Debian", "CPU_3399");
}
char output[512];
get_system_output("uname -a", output, sizeof(output));
std::string ver(output);
m_sysinfo.KernelVersion = ver;
printf("system version = %s \n", ver.c_str());
json j;
struct2json(j, m_sysinfo);
std::ofstream o("/usr/local/huago/sysinfo.json");
o << std::setw(4) << j << std::endl;
return j.dump();
}
void SysInforTool::struct2json(json &j, ScannerSysInfo &info)
{
j["CPU"] = info.CPU;
j["Systype"] = info.Systype;
j["Screentype"] = info.Screentype;
j["MtBoardVersion"] = info.MtBoardVersion;
j["MtType"] = info.MtType;
j["FPGAVersion"] = info.FPGAVersion;
j["Cistype"] = info.Cistype;
j["MaxRes"] = info.ResSup;
j["MemTotal"] = info.MemTotal;
j["DiskTotal"] = info.DiskTotal;
j["DiskUsed"] = info.DiskUsed;
j["KernelVersion"] = info.KernelVersion;
j["Have_EthernPort"] = info.Have_EthernPort;
j["ServiceVersion"] = info.ServiceVersion;
j["UsbProtocol"] = info.UsbProtocol;
}

29
SysInforTool.h Normal file
View File

@ -0,0 +1,29 @@
#pragma once
#include "scannersysinfo.h"
#include "json.hpp"
using json=nlohmann::json;
struct fileSystem_info{
char fileSystem_format[8];
unsigned int fileSystem_total_capacity;
unsigned int fileSystem_free_capacity;
char fileSystem_permissions[3];
};
class SysInforTool
{
public:
SysInforTool(ScannerSysInfo tinfo);
~SysInforTool();
std::string GetSysInfo();
ScannerSysInfo& GetInfo();
unsigned int GetMemTotal();
bool IsSmallRam();
private:
int get_fileSystem_info(const char *fileSystem_name,struct fileSystem_info *fi);
void struct2json(json& j,ScannerSysInfo& info);
private:
ScannerSysInfo m_sysinfo;
};

98
ThreadPool.h Normal file
View File

@ -0,0 +1,98 @@
#ifndef THREAD_POOL_H
#define THREAD_POOL_H
#include <vector>
#include <queue>
#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <future>
#include <functional>
#include <stdexcept>
class ThreadPool {
public:
ThreadPool(size_t);
template<class F, class... Args>
auto enqueue(F&& f, Args&&... args)
-> std::future<typename std::result_of<F(Args...)>::type>;
~ThreadPool();
private:
// need to keep track of threads so we can join them
std::vector< std::thread > workers;
// the task queue
std::queue< std::function<void()> > tasks;
// synchronization
std::mutex queue_mutex;
std::condition_variable condition;
bool stop;
};
// the constructor just launches some amount of workers
inline ThreadPool::ThreadPool(size_t threads)
: stop(false)
{
for(size_t i = 0;i<threads;++i)
workers.emplace_back(
[this]
{
for(;;)
{
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(this->queue_mutex);
this->condition.wait(lock,
[this]{ return this->stop || !this->tasks.empty(); });
if(this->stop && this->tasks.empty())
return;
task = std::move(this->tasks.front());
this->tasks.pop();
}
task();
}
}
);
}
// add new work item to the pool
template<class F, class... Args>
auto ThreadPool::enqueue(F&& f, Args&&... args)
-> std::future<typename std::result_of<F(Args...)>::type>
{
using return_type = typename std::result_of<F(Args...)>::type;
auto task = std::make_shared< std::packaged_task<return_type()> >(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
);
std::future<return_type> res = task->get_future();
{
std::unique_lock<std::mutex> lock(queue_mutex);
// don't allow enqueueing after stopping the pool
if(stop)
throw std::runtime_error("enqueue on stopped ThreadPool");
tasks.emplace([task](){ (*task)(); });
}
condition.notify_one();
return res;
}
// the destructor joins all threads
inline ThreadPool::~ThreadPool()
{
{
std::unique_lock<std::mutex> lock(queue_mutex);
stop = true;
}
condition.notify_all();
for(std::thread &worker: workers)
worker.join();
}
#endif

92
TypeIO.cpp Normal file
View File

@ -0,0 +1,92 @@
#include "TypeIO.h"
TypeIO::TypeIO(PORTS s0, PORTS s1, PORTS s2, PORTS s3) : gpio_s0(s0),
gpio_s1(s1),
gpio_s2(s2),
gpio_s3(s3)
{
}
TypeIO::~TypeIO()
{
}
CISVendor TypeIO::GetCisType()
{
auto s0 = gpio_s0.getValue();
auto s1 = gpio_s1.getValue();
auto s2 = gpio_s2.getValue();
auto s3 = gpio_s3.getValue();
std::string type;
CISVendor vender;
if (s0 == 0 && s1 == 0 && s2 == 0 && s3 == 1)
{
type = "DUNNAN_CIS_V0";
vender = CISVendor::DUNNAN_CIS_V0;
}
else if (s0 == 0 && s1 == 0 && s2 == 1 && s3 == 1)
{
type = "HUALIN_CIS_V0";
vender = CISVendor::HUALIN_CIS_V0;
}
else if (s0 == 0 && s1 == 0 && s2 == 0 && s3 == 0)
{
type = "DUNNAN_CIS_V0";
vender = CISVendor::DUNNAN_CIS_V0;
}
else if (s0 == 0 && s1 == 0 && s2 == 1 && s3 == 0)
{
type = "HUALIN_CIS_V0";
vender = CISVendor::HUALIN_CIS_V0;
}
else
{
type = "unknowun CIS TYPE";
vender = CISVendor::CIS_UNKNOWUN;
}
LOG("CIS Type :%s \n", type.c_str());
return vender;
}
SMBType TypeIO::GetMotorType()
{
SMBType type = SMBType::MB_DRV_8825;
auto s0 = gpio_s0.getValue();
auto s1 = gpio_s1.getValue();
auto s2 = gpio_s2.getValue();
auto s3 = gpio_s3.getValue();
std::string typeinfo;
if (s0 == 0 && s1 == 0 && s2 == 0 && s3 == 1)
{
typeinfo = "MB_DRV_8825";
LOG("SMBType = MB_DRV_8825\n");
type = SMBType::MB_DRV_8825;
}
else if (s0 == 0 && s1 == 0 && s2 == 1 && s3 == 1)
{
typeinfo = "MB_DRV_8825";
LOG("SMBType = MB_DRV_8825\n");
type = SMBType::MB_DRV_8825;
}
else if (s0 == 0 && s1 == 0 && s2 == 0 && s3 == 0)
{
typeinfo = "MB_DRV_TMC216";
LOG("SMBType = MB_DRV_TMC216\n");
type = SMBType::MB_DRV_TMC216;
}
else if (s0 == 0 && s1 == 0 && s2 == 1 && s3 == 0)
{
typeinfo = "MB_DRV_TMC216";
LOG("SMBType = MB_DRV_TMC216\n");
type = SMBType::MB_DRV_TMC216;
type = SMBType::MB_DRV_TMC216;
}
else
{
typeinfo = "unknowun Motor TYPE";
LOG("SMBType =unknowun Motor TYPE\n");
type = SMBType::MB_DRV_UNKNOWUN;
}
return type;
}

24
TypeIO.h Normal file
View File

@ -0,0 +1,24 @@
#pragma once
#include "Gpio.h"
#include "DevUtil.h"
#include "scanservices_utils.h"
#include <vector>
#include "scannersysinfo.h"
class TypeIO
{
private:
/* data */
public:
TypeIO(PORTS s0,PORTS s1,PORTS s2,PORTS s3);
CISVendor GetCisType();
SMBType GetMotorType();
~TypeIO();
private:
Gpio gpio_s0;
Gpio gpio_s1;
Gpio gpio_s2;
Gpio gpio_s3;
CISVendor cisven;
SMBType smbtype;
};

224
USBProtocol.h Normal file
View File

@ -0,0 +1,224 @@
#pragma once
typedef struct
{
int Command;
int Data;
int Length;
} USBCB;
enum class USBCommand : unsigned int
{
//无命令
NO_COMMAND = 0,
//获取dsp 状态
GET_DSP_STATUS = 1,
//取图
GET_IMAGE = 2,
//销毁DSP中驻存的图
POP_IMAGE = 3,
//开始扫描命令
START_COMMAND = 4,
//停止扫描命令
STOP = 5,
//获取扫描仪扫描模式
GET_SCAN_MODE = 6,
//获取固件版本号
GET_FW_VERSION = 7,
//返回PC端的状态
SEND_STATUS_PC = 8,
//下发扫描配置参数
CONFIGURED_DATA = 9,
//下发固件信息
SEND_FW = 10,
//获取扫描参数
GET_CONFIG_DATA = 11,
//获取扫描总张数
GET_SCANN_NUM = 12,
//获取有无纸的状态
GET_PAPERFEEDER_STATUS = 13,
//DSP初始化
INIT_HARDWARE_SYS = 14,
//下发元器件配置参数灰度LED R曝光时间
SEND_COMPONENTS_GR = 15,
//下发元器件配置参数LED G/B曝光时间
SEND_COMPONENTS_GB = 16,
//下发扫描模式
SEND_SCAN_MODE = 17,
//开始进行平场矫正
START_FLAT = 18,
//停止平场矫正
STOP_FLAT = 19,
//下发200dpi彩色平场矫正参数
SEND_200_COLOR_FLAT_DATA = 20,
//下发300dpi彩色平场矫正参数
SEND_300_COLOR_FLAT_DATA = 21,
//获取200dpi彩色平场矫正参数
GET_200_COLOR_FLAT_DATA = 22,
//获取300dpi彩色平场矫正参数
GET_300_COLOR_FLAT_DATA = 23,
//下发200dpi灰度平场校正参数
SEND_200_GRAY_FLAT_DATA = 24,
//下发300dpi灰度平场校正参数
SEND_300_GRAY_FLAT_DATA = 25,
//获取200DPI灰度平场校正参数
GET_200_GRAY_FLAT_DATA = 26,
//获取300DPI灰度平场校正参数
GET_300_GRAY_FLAT_DATA = 27,
//下发序列号命令
SEND_SERIAL = 28,
//获取序列号命令
GET_SERIAL = 29,
//获取滚轴数
GET_ROLLER_NUM = 0x1e,
//清零滚轴数
CLR_ROLLER_NUM = 0x1f,
//清除扫描总张数
CLR_SCAN_NUM = 0x20,
//准备更新固件
PRE_UPGRADE = 0X21,
//开始更新固件
START_UPGRADE = 0x22,
//彩色的AD参数
RGB_ADI_PARA = 0x23,
//灰度的AD参数
ADI_PARA = 0x24,
//获取CIS参数曝光时间ad参数)
GET_CIS_PARA = 0x25,
//扫描张数
START_COMMAND_COUNT = 0x26,
//下发休眠时间
SET_SLEEP_TIME = 0x27,
//获取休眠时间
GET_SLEEP_TIME = 0x28,
//清除缓存
CLR_CACHE = 0x29,
//下发速度模式
SET_SPEED_MODE = 0x2a,
//获取扫描速度模式
GET_SPEED_MODE = 0X2b,
//设置固件版本一共8个字节
SET_FW_VERSION = 0X2c,
//获取DSP版本
GET_DSP_VERSION = 0X2d,
//采集板FPGA固件版本
GET_SCANFPGA_VERSION = 0x2e,
//电机板FPGA固件版本
GET_MOTORFPGA_VERSION = 0X2f,
//设置制造商信息
SET_USB_INFOR_MANUFACTURE = 0X30,
//获取制造商信息
GET_USB_INFOR_MANUFACTURE = 0X31,
//设置产品型号信息
SET_USB_INFOR_MODEL_NAME = 0X32,
//获取产品型号信息
GET_USB_INFOR_MODEL_NAME = 0X33,
//设置USB PID / VID信息
SET_USB_INFOR_VIDPID = 0X34,
GET_USB_INFOR_VIDPID = 0X35,
//设置卡纸急停检测灵敏度
SET_JAM_DETECT_SENSITIVE = 0X36,
//获取卡纸急停检测灵敏度
GET_JAM_DETECT_SENSITIVE = 0X37,
//设置横向畸变系数
SET_JUST_COF_H = 0x38,
//读取横向畸变系数
GET_JUST_COF_H = 0x39,
//G400 清除硬件异常
CLEAR_HWERROR = 0x40,
//设置纵向畸变系数
SET_JUST_COF_V = 0x41,
//读取纵向畸变系数
GET_JUST_COF_V = 0x42,
//设置彩色校正参数
SEND_COLOR_FLAT = 0x43,
//设置彩色平场校正参数
SEND_COLORCORRECT_FLAT = 0x44,
//设置灰度校正参数
SEND_GRAY_FLAT = 0x45,
//设置灰度平场校正参数
SEND_GRAYCORRECT_FLAT = 0x46,
//设置平场校正参数
GET_FLAT_DATA =0x47,
//更新完成
UPDATE_FINISHED = 0x48,
//重启
REBOOT = 0x49,
//获取日志
GET_LOG_FILES_INFO = 0x50,
//发送log文件完成
GET_UPDATE_RESULT=0x51,
//清空日志
CLEAR_LOG_FILES = 0x52,
//获取搓纸失败
GET_CUO_ERROR,
//获取双张失败次数
GET_DOU_ERROR,
//获取卡纸次数
GET_JAM_ERROR,
ACTIVE_SCANNER=0x100,
//图像处理参数下发
GETSYSINFO_LEN =0x200,
GETSYSINFO =0x201,
GETMOTORPARAM = 0x202,
GETMOTORPARMLEN=0x203,
SETMOTORPARAM = 0x204,
SETMOTORPARAMLEN =0x205
};
enum class HG_ScannerStatus
{
//异常
HAVE_ERROR = -1,
//正常状态
NORMAL = 0,
//开盖
OPEN_COVER = 1,
// 无纸
NO_FEED = 2,
// 搓纸失败
FEED_IN_ERROR = 4,
// 卡纸
PAPER_JAM = 8,
// 检测到双张
DETECT_DOUBLE_FEED = 16,
// 检测到订书钉
DETECT_STAPLE = 32,
// 纸张倾斜
PAPER_SKEW = 64,
// 自动模式
AUTO_SCAN_MODE = 65,
// 手动模式
MANAUL_SCAN_MODE = 66,
// 计数模式
COUNT_MODE = 67,
// 硬件错误
HARDWARE_ERROR = 68,
// FPGA崩溃
FPGA_ERROR = 68,
// 开始
START_SCAN = 69,
//停止
STOP_SCAN = 70,
//有图
HAVE_IMAGE = 71,
// 更新扫描参数
UPDATE_SCAN_PARAMETER = 72,
// PC繁忙或出错
PC_SCAN_BUSY_or_ERROR = 73,
// 更新完成
UPDATE_FINISHED = 74,
//尺寸检测错误
SIZE_ERROR=75,
//纸张有孔
PAPER_HOLE = 84,
//自动校正中
AUTO_FLATTING=198,
//USB 未连接
USB_DISCONNECTED = 200,
//用户点击停止
USER_STOP = 201,
//自动平场校正完成
AUTO_FLAT_FINISHED = 202,
SCANNER_ACTIVED=0x10
};

86
UsbEndpoint.cpp Normal file
View File

@ -0,0 +1,86 @@
#include "UsbEndpoint.h"
#include <errno.h>
#include <sys/select.h>
extern int errno;
UsbEndPoint::UsbEndPoint(EndpointType eptype):m_fd(-1)
{
m_endpointtype=eptype;
}
UsbEndPoint::~UsbEndPoint()
{
if(m_fd)
{
::close(m_fd);
LOG("try close %s \n",map_endpoints[m_endpointtype].c_str());
}
}
int UsbEndPoint::open()
{
int ret=(int)HGUSB_ErrorCode::HG_USBSuccess;
if(m_endpointtype!=EndpointType::EP_Undefine)
{
LOG("try open %s \n",map_endpoints[m_endpointtype].c_str());
m_fd = ::open(map_endpoints[m_endpointtype].c_str(),O_RDWR);
if(m_fd ==-1)
{
ret=(int)HGUSB_ErrorCode::HG_USBOpenFailed;
LOG("try open %s fialed errorcode %d \n",map_endpoints[m_endpointtype].c_str(),errno);
}
else
{
LOG("try open %s success \n",map_endpoints[m_endpointtype].c_str());
}
}
return ret;
}
void UsbEndPoint::close()
{
if(m_fd)
{
::close(m_fd);
}
}
int UsbEndPoint::read(void* pdata,int length)
{
int ret = (int)HGUSB_ErrorCode::HG_USBSuccess;
if(!pdata)
return (int)HGUSB_ErrorCode::HG_USBInvalidePtr;
if(m_fd!=-1)
{
//DEBUG("try reading USB %s endpoint data\n",map_endpoints[m_endpointtype].c_str());
return ::read(m_fd,pdata,length);
}
return ret;
}
int UsbEndPoint::write(void* pdata,int length)
{
int ret = 0;
if(!pdata)
return (int)HGUSB_ErrorCode::HG_USBInvalidePtr;
if(m_fd!=-1)
{
//DEBUG("try writing USB %s endpoint data\n",map_endpoints[m_endpointtype].c_str());
return ::write(m_fd,pdata,length);
}
return ret;
}
int UsbEndPoint::getEndpointType()
{
return (int)m_endpointtype;
}
bool UsbEndPoint::is_open()
{
return m_fd != -1;
}

66
UsbEndpoint.h Normal file
View File

@ -0,0 +1,66 @@
/*
* ====================================================
* linux USB device USB通信
*
* 2020/8/18
* v1.0
* ====================================================
*/
#ifndef IUSBENDPOINT_H
#define IUSBENDPOINT_H
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <map>
#include <errno.h>
#include "scanservices_utils.h"
using namespace std;
enum class HGUSB_ErrorCode
{
HG_USBSuccess=-1,
HG_USBOpenFailed,
HG_USBInvalidePtr,
HG_USBPCUnConnected
};
class UsbEndPoint
{
public:
enum class EndpointType
{
EP_Undefine,
EP_Control,
EP_Bulk_In,
EP_Bulk_Out,
Ep_Int
};
public:
UsbEndPoint(EndpointType eptype);
~UsbEndPoint();
int open();
void close();
int read(void* pdata,int length);
int write(void* pdata,int length);
int getEndpointType();
bool is_open();
private:
int m_fd;
EndpointType m_endpointtype;
std::map<EndpointType,std::string> map_endpoints={
{EndpointType::EP_Bulk_In,BULK_IN_PATH},
{EndpointType::EP_Bulk_Out,BULK_OUT_PATH},
{EndpointType::EP_Control,BULK_CTL_PATH},
{EndpointType::Ep_Int,BULK_INT_PATH}
};
};
#endif //IUSBENDPOINT_H

548
UsbScanner.cpp Normal file
View File

@ -0,0 +1,548 @@
#include "UsbScanner.h"
#include <turbojpeg.h>
#include "JsonConfig.h"
#include "USBProtocol.h"
#define USB_REQ_GET_FPGA_REGS 0x40
#define USB_REQ_SET_FPGA_REGS 0x41
#define USB_REQ_GET_MOTOR_REGS 0x42
#define USB_REQ_SET_MOTOR_REGS 0x43
#define USB_REQ_ACCES_DEV_LOG 0x50
#define USB_REQ_GET_DEV_STATUS 0x60
#define USB_REQ_GET_DEV_CONFIGURATION 0x61
#define USB_REQ_SET_DEV_CONFIGURATION 0x62
#define USB_REQ_GET_DEV_REGS 0x63
#define USB_REQ_SET_DEV_REGS 0x64
#define USB_REQ_GET_DEV_LOG 0x65
#define USB_REQ_SET_DEV_LOG 0x66
static int enqueueindex = 0;
const int SPEED_MODE_MAX = 5;
UsbScanner::UsbScanner() : m_startscan(false),
imageremain(0),
eventsramain(0)
{
DeviceExport();
m_serial = ("G20018000298OO");
m_fwversion = ("12345613");
mount_usb_device();
printf("mount usb ing \n");
auto ctrl_req_handler = [&](int fd, struct usb_ctrlrequest *setup, unsigned char *buffer) -> bool
{
if (!(setup->bRequestType & USB_TYPE_VENDOR) || (setup->bRequestType & USB_RECIP_MASK) != USB_RECIP_DEVICE)
return false;
static std::string logstring;
unsigned int *regs = (unsigned int *)buffer;
int creg = 0;
if (!(setup->wLength % 4))
creg = setup->wLength / 4;
int regindex = setup->wValue;
switch (setup->bRequest)
{
case USB_REQ_GET_FPGA_REGS:
if ((setup->bRequestType & USB_DIR_IN) && creg)
{
if (regindex < 0 || regindex >= 18)
return false;
unsigned int regv = m_hgScanner->readreg(regindex);
memcpy(buffer, &regv, sizeof(regv));
::write(fd, buffer, setup->wLength);
return true;
}
break;
case USB_REQ_SET_FPGA_REGS:
if (!(setup->bRequestType & USB_DIR_IN) && creg)
{
::read(fd, buffer, setup->wLength);
LOG("USB_REQ_SET_FPGA_REGS set val = %d \n", *(unsigned int *)buffer);
// if (!write_regs(regs, regindex, creg, this->fgparegs))
// return false;
/*
fpga寄存器操作
*/
return true;
}
break;
case USB_REQ_GET_MOTOR_REGS:
if ((setup->bRequestType & USB_DIR_IN))
{
// if (!read_regs(regs, regindex, creg, this->motorregs))
// return false;
/*
*/
::write(fd, buffer, setup->wLength);
return true;
}
break;
case USB_REQ_SET_MOTOR_REGS:
if (!(setup->bRequestType & USB_DIR_IN))
{
::read(fd, buffer, setup->wLength);
// if (!write_regs(regs, regindex, creg, this->motorregs))
// return false;
/*
*/
return true;
}
break;
// case USB_REQ_GET_DEV_REGS:
// if ((setup->bRequestType & USB_DIR_IN) && creg && this->devregs)
// {
// if (!read_regs(regs, regindex, creg, this->devregs))
// return false;
// ::write(fd, buffer, setup->wLength);
// return true;
// }
// break;
// case USB_REQ_SET_DEV_REGS:
// if (!(setup->bRequestType & USB_DIR_IN) && creg && this->devregs)
// {
// ::read(fd, buffer, setup->wLength);
// if (!write_regs(regs, regindex, creg, this->devregs))
// return false;
// return true;
// }
// break;
// case USB_REQ_ACCES_DEV_LOG:
// if (setup->wLength != 64)
// return false;
// if (!(setup->bRequestType & USB_DIR_IN))
// {
// ::read(fd, buffer, setup->wLength);
// buffer[64 - 1] = 0;
// logstring = (char *)buffer;
// return true;
// }
// else
// {
// memset(buffer, 0, 64);
// if (!logstring.empty())
// memcpy(buffer, logstring.data(), logstring.size());
// ::write(fd, buffer, setup->wLength);
// return true;
// }
// break;
// case USB_REQ_GET_DEV_LOG:
// if ((setup->wLength == 4) && (setup->bRequestType & USB_DIR_IN) && log_get_level(logstring, regindex, *((int *)regs)))
// {
// ::write(fd, buffer, setup->wLength);
// return true;
// }
// break;
// case USB_REQ_SET_DEV_LOG:
// if ((setup->wLength == 4) && !(setup->bRequestType & USB_DIR_IN))
// {
// ::read(fd, buffer, setup->wLength);
// return log_set_level(logstring, regindex, *((int *)regs));
// }
// break;
default:
break;
}
return false;
};
auto hotplug_handler = [&](bool isconnect)
{
LOG("usb hotplug_handler is connect : %s \n", isconnect ? "true" : "false");
};
m_usb.reset(new UsbDevice(ctrl_req_handler, hotplug_handler));
// m_usb.get();
auto imageready = [this](const HG_JpegCompressInfo &imageinfo)
{
imageremain++;
m_images.Put(imageinfo);
// LOG("Enqueue image index :%d ptr:%p length:%d\n", ++enqueueindex,imageinfo.pJpegData, imageinfo.DataLength);
};
auto deviceevent = [this](const int eventID, std::string capmsg)
{
{
LOG("\n 222222222 Enqueue event %d \n", eventID);
eventsramain++;
// unsigned char buff[64]={0};
//printf("--------------------------66 = %d\r\n",eventsramain);
m_scannerEvents.Put({eventID, capmsg});
if (eventID == (int)HG_ScannerStatus::STOP_SCAN)
{
m_startscan = false;
writesyslog(LOG_INFO, getmeminfo());
}
if (eventID == (int)(HG_ScannerStatus::AUTO_FLAT_FINISHED))
{
m_hgScanner->ResetCorrectflags();
}
else if ((eventID == (int)HG_ScannerStatus::SIZE_ERROR) || (eventID == (int)HG_ScannerStatus::PAPER_HOLE))
{
m_hgScanner->StopScan(0);
// m_usb->
}
}
};
ScannerGlue glue = {imageready, deviceevent};
m_hgScanner.reset(new Scanner(glue));
}
UsbScanner::~UsbScanner()
{
if (!m_images.IsShutDown())
m_images.ShutDown();
if (!m_scannerEvents.IsShutDown())
m_scannerEvents.ShutDown();
if (m_hgScanner.get())
m_hgScanner.reset();
if(m_usb.get())
m_usb.reset();
}
void UsbScanner::StartScan(int scancount)
{
ClearImages();
LOG("m_scannerEvents size %d\n", m_scannerEvents.Size());
ClearErrorEvents();
LOG("m_images size %d\n", m_images.Size());
m_hgScanner->SetDstScanNum(9999);//scancount <= 0 ? 1 : scancount);
printf("1111111111111111111 %d \r\n", scancount);
m_hgScanner->put(S_EVT_START_SCAN);
// m_hgScanner->startScan();
LOG("Put Event S_EVT_START_SCAN\n");
}
void UsbScanner::StopScan()
{
m_hgScanner->put(S_EVT_STOP_SCAN);
LOG("Put Event S_EVT_STOP_SCAN\n");
}
void UsbScanner::ConfigScanParam(HG_ScanConfiguration config)
{
m_startscan = true;
imageremain = 0;
eventsramain = 0;
m_hgScanner->ConfigScanParam(config);
}
bool UsbScanner::FeederLoaded()
{
return m_hgScanner->isFeederLoaded();
}
std::string UsbScanner::GetSerial()
{
auto info = GetScanInfoFromJson();
return info.SerialNum;
}
void UsbScanner::SetSerial(std::string serial)
{
if (m_serial.length() != 14)
{
LOG("SetSerial error length,length must be 14 \n");
return;
}
m_serial = serial;
}
std::string UsbScanner::GetFWVersion()
{
LOG(" GetFWVersion----------------- \n");
// JsonConfig js;
auto info = js_config.GetScanInfo();
return mapFradme_SP[info.SpeedMode].FWVERSIO;
}
void UsbScanner::SetFwVersion(std::string fwversion)
{
if (fwversion.length() != 10)
{
LOG("SetFwVersion error length \n");
return;
}
m_fwversion = fwversion;
}
int UsbScanner::GetRollerNum()
{
return 1;
}
void UsbScanner::ClearRollerNum()
{
}
void UsbScanner::InitScanner()
{
}
void UsbScanner::ClearImages()
{
while (m_images.Size() > 0)
{
auto jpeg = m_images.Take();
// tjFree(jpeg.pJpegData);
}
imageremain = 0;
}
static int aquiredimgindex = 0;
HG_JpegCompressInfo UsbScanner::GetImage()
{
HG_JpegCompressInfo ret = {nullptr, 0};
if (m_images.Size() > 0 && !m_images.IsShutDown())
{
ret = m_images.Take();
imageremain--;
// LOG("aquired image index %d \n",++aquiredimgindex);
}
return ret;
}
HG_Msg UsbScanner::GetEvent()
{
HG_Msg ret = {(int)HG_ScannerStatus::NORMAL, ""};
if (m_scannerEvents.Size() > 0 && !m_scannerEvents.IsShutDown())
{
ret = m_scannerEvents.Take();
eventsramain--;
}
return ret;
}
void UsbScanner::ClearErrorEvents()
{
while (m_scannerEvents.Size() > 0)
{
m_scannerEvents.Take();
}
eventsramain = 0;
}
void UsbScanner::ClearHWError()
{
m_hgScanner->put(S_EVT_CLEAR_ERR);
LOG("Put Event S_EVT_CLEAR_ERR\n");
}
bool UsbScanner::GetImagequeueEmpty()
{
return imageremain == 0;
}
bool UsbScanner::GetEventQueueEmpty()
{
return eventsramain == 0;
}
HG_JpegCompressInfo UsbScanner::GetFrontImage()
{
HG_JpegCompressInfo ret = {nullptr, 0};
if (m_images.Size() > 0)
ret = m_images.Front();
return ret;
}
HG_Msg UsbScanner::GetEventFront()
{
HG_Msg ret = {(int)HG_ScannerStatus::NORMAL, ""};
if (m_scannerEvents.Size() > 0 && !m_scannerEvents.IsShutDown())
{
ret = m_scannerEvents.Front();
}
return ret;
}
void UsbScanner::CreatCorrectData(int correctmode)
{
ClearErrorEvents();
m_hgScanner->CreatCorrectData(correctmode);
}
bool UsbScanner::IsScanning()
{
return m_hgScanner->IsScanning();
}
void UsbScanner::SetFlatParam(int type, int *value)
{
std::string ttype;
switch ((USBCommand)type)
{
case USBCommand::SEND_COLOR_FLAT:
ttype = "color";
break;
case USBCommand::SEND_COLORCORRECT_FLAT:
ttype = "correctColor";
break;
case USBCommand::SEND_GRAY_FLAT:
ttype = "gray";
break;
case USBCommand::SEND_GRAYCORRECT_FLAT:
ttype = "correctGray";
break;
default:
break;
}
if (!ttype.empty())
m_hgScanner->writeParamars(ttype, value);
}
CaptureParams UsbScanner::GetCaptureParams()
{
return m_hgScanner->GetCaptureParams();
}
void UsbScanner::UpdateScanInfo(int type, void *data)
{
auto info = GetScanInfoFromJson();
switch ((USBCommand)type)
{
case USBCommand::SEND_SERIAL:
{
char serial[15];
serial[14] = '\0';
memcpy(serial, data, 14);
std::string serial_s(serial);
m_hgScanner->GetScanInfo().SerialNum = serial_s;
info.SerialNum = serial_s;
SaveScaninfo(info);
}
break;
case USBCommand::SET_JUST_COF_H:
info.HRatio = *(unsigned int *)(data);
break;
case USBCommand::SET_JUST_COF_V:
info.VRatio = *(unsigned int *)(data);
printf("SET_JUST_COF_V = %d %f\n", info.VRatio, *(float *)(data));
break;
case USBCommand::CLR_ROLLER_NUM:
info.RollerNum = 0;
break;
case USBCommand::CLR_SCAN_NUM:
info.TotalScanned = 0;
break;
case USBCommand::SET_SLEEP_TIME:
info.SleepTime = *(unsigned int *)(data);
printf("set sleep time = %d \n", info.SleepTime);
SaveScaninfo(info);
stop_countdown();
start_enter_lowpwoer();
return;
case USBCommand::SET_SPEED_MODE:
if (*(unsigned int *)(data) > SPEED_MODE_MAX)
{
info.SpeedMode = 3;
}
else
{
info.SpeedMode = *(unsigned int *)(data);
}
LOG("UsbScanner SET SpeedMode == %d------ \n", info.SpeedMode);
iter = mapFradme_SP.find(info.SpeedMode);
if (iter != mapFradme_SP.end())
info.FWVersion = iter->second.FWVERSIO;
SaveScaninfo(info);
m_hgScanner->updateSpeedMode(info.SpeedMode);
LOG("UsbScanner SET SpeedMode == %d-------info.FWVersion = %s \n", info.SpeedMode, info.FWVersion.c_str());
break;
default:
break;
}
SaveScaninfo(info);
m_hgScanner->UpdateScanInfo();
}
ScannerScanInfo UsbScanner::GetScanInfo()
{
return m_hgScanner->GetScanInfo();
}
void UsbScanner::SetLEDStatus(LedStatus status)
{
m_hgScanner->getPanelLeds().setStatus(status);
}
std::string UsbScanner::GetSysInfo()
{
return m_hgScanner->GetSysInfo();
}
int UsbScanner::read_bulk(void *pdata, int length)
{
int ret=0;
if(pdata==nullptr || length == 0)
return ret;
if(m_usb.get()&& m_usb->is_connected())
{
ret = m_usb->read_bulk(pdata,length,1000);
}
return ret;
}
int UsbScanner::write_bulk(void *pdata, int length)
{
int ret=0;
if(pdata==nullptr || length == 0)
return ret;
if(m_usb.get()&& m_usb->is_connected())
{
ret = m_usb->write_bulk(pdata,length);
}
return ret;
}
bool UsbScanner::is_connect()
{
if(!m_usb.get())
return false;
return m_usb->is_connected();
}
void UsbScanner::mount_usb_device()
{
if ((access("/dev/ffs-camtp/ep0", F_OK)) != -1)
return;
int result = system("modprobe libcomposite\n \
mkdir /var/cfg\n \
mount none /var/cfg -t configfs\n \
mkdir /var/cfg/usb_gadget/g1\n \
cd /var/cfg/usb_gadget/g1\n \
mkdir configs/c.1 \n \
mkdir functions/ffs.camtp\n \
mkdir strings/0x409\n \
mkdir configs/c.1/strings/0x409\n \
echo 0x0300 > idProduct\n \
echo 0x3072 > idVendor\n \
echo \"01234567AABBCCDDEE\" > strings/0x409/serialnumber\n \
echo \"Holdtecs Technologies\" > strings/0x409/manufacturer\n \
echo \"The Holdtecs Product !\" > strings/0x409/product\n \
echo \"Conf 1\" > configs/c.1/strings/0x409/configuration\n \
echo 120 > configs/c.1/MaxPower\n \
ln -s functions/ffs.camtp configs/c.1\n \
mkdir /dev/ffs-camtp\n \
mount -t functionfs camtp /dev/ffs-camtp");
}

55
UsbScanner.h Normal file
View File

@ -0,0 +1,55 @@
#pragma once
#include "IScanner.h"
#include "Scanner.h"
#include <memory>
#include "FsmState.h"
#include "usbdevice.h"
using namespace std;
class UsbScanner : public IScanner
{
public:
UsbScanner();
virtual ~UsbScanner();
virtual void StartScan(int scancount) override;
virtual void StopScan() override;
virtual void ConfigScanParam(HG_ScanConfiguration config) override;
virtual bool FeederLoaded() override;
virtual std::string GetSerial() override;
virtual void SetSerial(std::string serial) override;
virtual std::string GetFWVersion() override;
virtual void SetFwVersion(std::string fwversion) override;
virtual int GetRollerNum() override;
virtual void ClearRollerNum() override;
virtual void InitScanner() override;
virtual void ClearImages() override;
virtual HG_JpegCompressInfo GetImage() override;
virtual HG_Msg GetEvent() override;
virtual void ClearErrorEvents() override;
virtual void ClearHWError() override;
virtual bool GetImagequeueEmpty() override;
virtual bool GetEventQueueEmpty() override;
virtual HG_JpegCompressInfo GetFrontImage() override;
virtual HG_Msg GetEventFront() override;
virtual void CreatCorrectData(int correctmode) override;
virtual bool IsScanning() override;
virtual void SetFlatParam(int type,int* value) override;
virtual CaptureParams GetCaptureParams() override;
virtual void UpdateScanInfo(int type,void* data) override;
virtual ScannerScanInfo GetScanInfo() override;
virtual void SetLEDStatus(LedStatus status) override;
std::string GetSysInfo();
int read_bulk(void *pdata, int length);
int write_bulk(void *pdata, int length);
bool is_connect();
private:
void mount_usb_device();
private:
map<int, sp_COLOR_or_GRAY >::iterator iter;
std::shared_ptr<Scanner> m_hgScanner;
std::shared_ptr<UsbDevice> m_usb;
bool m_startscan;
volatile int imageremain;
volatile int eventsramain;
};

13
UsbmsgHandler.cpp Normal file
View File

@ -0,0 +1,13 @@
#include "UsbmsgHandler.h"
#include "Scanner.h"
bool read_regs(unsigned int *regs, int regindex, int creg, void* scanner)
{
return true;
}
bool write_regs(unsigned int *regs, int regindex, int creg, void* scanner)
{
return true;
}

5
UsbmsgHandler.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
bool read_regs(unsigned int *regs, int regindex, int creg, void* scanner);
bool write_regs(unsigned int *regs, int regindex, int creg, void* scanner);

52
ZouZhiMotor.cpp Normal file
View File

@ -0,0 +1,52 @@
#include "ZouZhiMotor.h"
#include <thread>
ZouZhiMotor::ZouZhiMotor()
: Motor(motorPorts_Zouzhi)
{
auto t_smbtype = smbtype == SMBType::MB_DRV_TMC216 ? MotorConfig::MTBDType::MT_TMC : MotorConfig::MTBDType::MT_DRV;
m_zouparamex = m_mtconfig->GetMotorSpeedParam(true, t_smbtype, 4, 1, 1);
speedConfig();
}
ZouZhiMotor::~ZouZhiMotor()
{
}
void ZouZhiMotor::start()
{
Motor::setDirection(0);
Motor::start(delays, m_zouparamex.mt_param);
}
void ZouZhiMotor::speedChange(int speed, int dpi, int colormode) // speed should be in range [0,5] (by ply,at 2019.5.23)
{
auto t_smbtype = smbtype == SMBType::MB_DRV_TMC216 ? MotorConfig::MTBDType::MT_TMC : MotorConfig::MTBDType::MT_DRV;
m_zouparamex = m_mtconfig->GetMotorSpeedParam(true, t_smbtype, 4, colormode, dpi);
speedConfig();
}
void ZouZhiMotor::speedRecover()
{
speedConfig();
}
void ZouZhiMotor::speedConfig()
{
LOG("ZouZhiMotor speed=%d \n dpi=%d \n colormode=%d \n finalPeriod=%d \n Fmin=%d \n a=%.2f \n offset=%.2f \n stepnum=%.2f \n finalDelay=%.2f \n ",
m_zouparamex.speed,
m_zouparamex.dpi,
m_zouparamex.colormode,
m_zouparamex.mt_param.finalPeriod,
m_zouparamex.mt_param.Fmin,
m_zouparamex.mt_param.a,
m_zouparamex.mt_param.offset,
m_zouparamex.mt_param.stepnum,
m_zouparamex.mt_param.finalDelay);
delays.clear();
delays = speedup_cfg(m_zouparamex.mt_param.finalPeriod, m_zouparamex.mt_param.Fmin, m_zouparamex.mt_param.stepnum, m_zouparamex.mt_param.a,
m_zouparamex.mt_param.offset, m_zouparamex.mt_param.finalDelay);
}

16
ZouZhiMotor.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include "Motor.h"
class ZouZhiMotor : public Motor
{
public:
ZouZhiMotor();
~ZouZhiMotor();
virtual void start();
void speedChange(int speed, int dpi = 1,int colormode = 1);
void speedRecover();
private:
std::vector<int> delays;
MotorSpeedParamEx m_zouparamex;
void speedConfig();
};

70
autoevent.hpp Normal file
View File

@ -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;
};

12
buildconf.h Executable file
View File

@ -0,0 +1,12 @@
//#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
//#define CONFIG_USB_NON_BLOCKING_WRITE 1
#define CONFIG_USB_FS_SUPPORT 1 // USB 1.1 Full speed
#define CONFIG_USB_HS_SUPPORT 1 // USB 2.0 High speed
// #define CONFIG_USB_SS_SUPPORT 1 // USB 3.0 SuperSpeed
#define CONFIG_READ_FILE_BUFFER_SIZE (1024*1024) // Must be a 2^x value.
#define CONFIG_MAX_TX_USB_BUFFER_SIZE (16*512) // Must be a multiple of 512 and be less than CONFIG_READ_FILE_BUFFER_SIZE
#define CONFIG_MAX_RX_USB_BUFFER_SIZE (16*512) // Must be a multiple of 512

80
camtp.h Executable file
View File

@ -0,0 +1,80 @@
/*
* CAMTP Responder
* Copyright (c) 2020 Holdtecs Technologies
*
* CAMTP Responder is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* CAMTP Responder is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 3 for more details.
*
* You should have received a copy of the GNU General Public License
* along with CAMTP Responder; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file camtp.h
* @brief Main CAMMTP protocol functions.
* @author Barry Ruan <cubex@foxmail.com>
*/
#ifndef _INC_CAMTP_H_
#define _INC_CAMTP_H_
#define MAX_STORAGE_NB 16
#define MAX_CFG_STRING_SIZE 512
#pragma pack()
typedef struct mtp_usb_cfg_
{
uint16_t usb_vendor_id;
uint16_t usb_product_id;
uint8_t usb_class;
uint8_t usb_subclass;
uint8_t usb_protocol;
uint16_t usb_dev_version;
uint16_t usb_max_packet_size;
uint8_t usb_functionfs_mode;
char usb_device_path[MAX_CFG_STRING_SIZE + 1];
char usb_endpoint_in[MAX_CFG_STRING_SIZE + 1];
char usb_endpoint_out[MAX_CFG_STRING_SIZE + 1];
char usb_endpoint_intin[MAX_CFG_STRING_SIZE + 1];
char usb_string_manufacturer[MAX_CFG_STRING_SIZE + 1];
char usb_string_product[MAX_CFG_STRING_SIZE + 1];
char usb_string_serial[MAX_CFG_STRING_SIZE + 1];
char usb_string_version[MAX_CFG_STRING_SIZE + 1];
char usb_string_interface[MAX_CFG_STRING_SIZE + 1];
int wait_connection;
int loop_on_disconnect;
int show_hidden_files;
int val_umask;
}camtp_usb_cfg;
typedef struct camtp_ctx_
{
uint32_t session_id;
camtp_usb_cfg usb_cfg;
void * usb_ctx;
volatile int cancel_req;
}camtp_ctx;
int camtp_load_config_file(camtp_ctx * context, const char * conffile);
#endif

113
changelog.txt Normal file
View File

@ -0,0 +1,113 @@
此修改说明适用于华高G300~G400系列扫描仪scanservice
2020年9月26日
G300/G400 scanservice更新日志
1.scanservice中增加进程ID唯一性判断避免系统存在多个scanservice
2.USB升级增加更改update包权限更改
2020年10月17日
G300/G400 scanservice更新日志
1.增加平场校正完成通知功能;
2.增加平场校正参数配置功能;
3.增加USB控制重启功能
4.增加横向纵向修正系数;
5.增加PC配置序列号功能
2020年10月29日19:39:32
1.增加jpeg图像bulk传输分包传输以避免出现传输失败
2020年11月26日20:59:05
1.增加ADC reset功能
2.调整USB write bulk接口传输包大小避免传输失败丢图问题
2020年11月29日16:14:10G300 UV
1.UV机器修复socket 端口重用问题
2.开盖异常显示复位显示不正确问题
3.修复双张显示卡纸问题
2021年1月11日13:18:14
1.增加教育版与通用版本,针对两种模式校正算法调整;
2.调整校正算法 曝光最大为3300对应FPGA版本也为3300
3.增加RSA固件校验
4.升级流程调整固件下载下去先做校验然后由PC发出指令进行重启
5.优化main函数整合冗余代码读写scaninfo文件
2021年2月28日
修改说明:
1.增加scanservice控制休眠
2.增加检测CIS类型代码
3.增加休眠时间控制与终结休眠脚本;
4.增加USB休眠时间设置读取
5.重构main函数部分代码
2021年3月5日
修改说明:
1.增加fpga固件升级功能fpga升级包名称为fpgaupdatefile.bin。存放位置为/etc/fpgaupdatefile.bin
2.系统固件需要升级为支持mtp的内核版本否则将会导致升级失败
3.修改cmakelists文件增加解决mtp源码编译问题
2021年3月29日
修改说明:
1.增加32字节buffer token设置 读取 存取功能
2.修改G400 70 ppm下 走纸电机 FMin频率以解决电机扭矩偏小问题
2021年6月5日
1.修复程序退出时,报段错误问题;
2.增加低功耗唤醒协议用于区分scanservice运行着或usbmonitor运行着PC软件针对这两种模式做调整
3.fpga升级方式调整若需更新只需将文件拷贝至etc下即可
4.增加尺寸检测功能修复210418版本只能扫描一次第二次启动异常问题
5.修复CIS类型检测错误问题
6.countdown.sh脚本低功耗控制调整
7.G300 扫描增加60ppm
2021年10月20日
1.片上增加PC速度可配置功能
2.增加USBVID PID可调整功能
3.修复校正offset控制色条宽度不正确问题导致条纹现象432->288;
4.校正实时输出校正信息到PC功能;
2021-11-23
1.将明场目标值提高到200暗场最大值提高到10避免敦南cis无法校正通过
2.校正扫描增益一致校正查值表采用数字增益放大1.2倍;
2022-01-14
1.增加获取系统信息通信接口sysinfo;
2.增加设置200 300 600 dpi 横纵修正系数,兼容以前协议;
3.重构部分代码;
4.明场均值降低至180数字增益系数放大至1.42
5.电机板版本 CIS类型增加自动识别接口
6.由于板子自带内存2GB600DPI会导致内存崩溃现仅支持真实200 300DPI
7.调整校正暗场校正算法使用最低暗场值最低大于3即满足暗场校过标准
8.由于尺寸检测精度问题,本版本暂时屏蔽尺寸检测功能;
2022-01-15
1. 修复校正完成后位至校正标志位复位,导致上层取图报取图超时问题;
2. 修复300dpi 长纸不能走完问题;
3. 修复设置休眠时间后,扫描一张设置进入低功耗的时间不生效问题;
2022-01-17
1. 由于匹配原始尺寸采集存在误触发过纸信号情况,屏蔽掉自适应幅面功能;
2. 70ppm 速度提升至75ppm
2022年2月15日
1. 更新校正算法(支持文本模式和图片模式)
2. 变更扫描配置结构体成员增加lutmode模式
3. 增加Scansysinfo信息输出接口
2022年3月21日
1. 重构电机版本自动识别以及cis识别ICapturer和IMotor接口
2. 开放增加电机板调速接口;
3. 增加main函数传参 启动校正功能;
4. 开放尺寸检测代码,更新尺寸检测代码;
5. 修复固件版本号更新延迟问题;
6. 校正未开线程导致校正完成后pc端才能收到校正信息输出日志
7. 电机参数增加sp关联项设置速度模式时更新调速sp至camerparams.json文件中
8. 适配不同内存大小 300 600 dpi 扫描时配置fpga分辨率2GB 配置600dpi 则按照300 dpi采集
9. 修复尺寸检测图像计数复位异常导致PC取图超时未上报stopscan
2022年3月24日
1. 适配3288 300机器
2. 基于3月21日版本代码基础上丢弃以前扫描参数配置保存方式目前300 400 按照统一的方式配置
2022年3月31日
1. 修复电机复位随机转动时间,避免搓纸轮磨损位置固定;
2. 修复尺寸检测double letter 以及 letter尺寸异常问题
3. Monocapturer 类增加多线程进行处理
4. 更正double letter 尺寸8.5inc * 22 inc以及采集高度
5. 优化json存储避免json对象key不存在时导致程序崩溃问题
2022年4月11日 pm
1. g300 电机复位部分不到位问题修复;
2. 优化校正部分 sp与曝光上限限制问题
3. 修复Capturer类PC配置畸变校正参数不生效问题
2022年4月20日
1. 修复长纸模式下,卡纸问题;
2. 增加搓纸电机减速过程;
2022年6月5日 蒋志强
1. d8版本尺寸检测问题修复
2022年11月6日 彭明
1. 针对G300 增加真实300DPI 模式;
2. 调整Capture 类增加300DPI彩色灰度校正模式
3. 调整300DPI 配置fpga 以及v4l2 高度配置;

402
correct_ultis.cpp Normal file
View File

@ -0,0 +1,402 @@
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "correct_ultis.h"
#include "CImageMerge.h"
#define USE_NEWFLAT
//using namespace cv;
//设置一面的offset值
void setOffset(int *config, int step)
{
for (int i = 0; i < 6; i++)
{
int *offset = config + i;
*offset += step;
if (*offset < 0)
*offset = 1;
if (*offset > 255)
*offset = 255;
}
}
// cv::Mat extractRepresentRow2(const cv::Mat &src)
// {
// cv::Mat BWbalenceSrc(1, src.cols * src.channels(), CV_8UC1);
// cv::Mat temp_imageBW(src.rows, src.cols * src.channels(), CV_8UC1, src.data);
// for (size_t i = 0; i < BWbalenceSrc.cols; i++)
// BWbalenceSrc.at<u_char>(0, i) = cv::mean(temp_imageBW(cv::Rect(i, 0, 1, temp_imageBW.rows)))[0];
// return BWbalenceSrc;
// }
// cv::Mat loadLUT(const std::string &file)
// {
// cv::Mat dataFile = cv::imread(file, cv::IMREAD_ANYCOLOR);
// long total = dataFile.total();
// int step = total / 256;
// int channel = 1;
// #ifndef USE_NEWFLAT
// if (step == 4896 || step == 7344)
// channel = 408;
// else if (step == 14688 || step == 22032 || step == 44064)
// channel = 432; // 486
// #else
// #ifdef G400
// channel = 408;
// #else
// channel = 432;
// #endif
// #endif
// cv::Mat lut(step / channel, 256, CV_8UC(channel));
// memcpy(lut.data, dataFile.data, total);
// return lut;
// }
void initLut(const std::string lutpath, bool iscolor)
{
// if (!lutpath.empty() && (access(lutpath.c_str(), F_OK) == 0))
// {
// if (iscolor)
// {
// lutColorMat = loadLUT(lutpath); //彩色校正值
// }
// else
// lutGrayMat = loadLUT(lutpath); //灰色校正值
// }
}
// void correctColor(cv::Mat &src, int dpi, int mode, bool lutgraghic)
// {
// Mat lutMat;
// #ifdef USE_NEWFLAT
// FPGAConfigParam param = GetFpgaparam(dpi, mode);
// std::string path = lutgraghic ? param.LutPath : param.TextLutPath;
// #else
// std::string path = param.LutPath;
// #endif
// if (src.type() == CV_8UC3)
// {
// if (lutColorMat.empty())
// {
// if (access(path.c_str(), F_OK) != -1)
// {
// lutColorMat = loadLUT(path);
// }
// else
// {
// printf("error error error %s NOT FOUND \n", path.c_str());
// return;
// }
// }
// lutMat = lutColorMat;
// }
// else
// {
// if (lutGrayMat.empty())
// {
// if (access(path.c_str(), F_OK) != -1)
// {
// lutGrayMat = loadLUT(path);
// }
// else
// {
// printf("error error error %s NOT FOUND", path.c_str());
// return;
// }
// }
// lutMat = lutGrayMat;
// }
// if (lutMat.empty())
// {
// return;
// }
// cv::Mat image_temp(src.rows, src.cols * src.channels() / lutMat.channels(), CV_8UC(lutMat.channels()), src.data);
// for (size_t i = 0; i < image_temp.cols; i++)
// cv::LUT(image_temp(cv::Rect(i, 0, 1, image_temp.rows)), lutMat(cv::Rect(0, i, 256, 1)), image_temp(cv::Rect(i, 0, 1, image_temp.rows)));
// }
// void creatLUTData(int dpi, int mode)
// {
// printf("eneter creatLUTData \n");
// FPGAConfigParam param = GetFpgaparam(dpi, mode);
// auto colormode = mode == 1 ? IMREAD_COLOR : IMREAD_GRAYSCALE;
// std::string blackPath = param.Flat_BwPath;
// std::string whitePath = param.Flat_WhitePath;
// cv::Mat lut;
// cv::Mat twMat = cv::imread(whitePath, colormode);
// cv::Mat tbMat = cv::imread(blackPath, colormode);
// cv::Mat wMat, bMat;
// if (mode == 1)
// {
// wMat = cv::Mat(twMat.rows, twMat.cols * 3, CV_8UC1, twMat.data);
// bMat = cv::Mat(twMat.rows, twMat.cols * 3, CV_8UC1, tbMat.data);
// }
// else
// {
// wMat = twMat;
// bMat = tbMat;
// }
// #ifdef USE_NEWFLAT
// //lut = calcLUT(extractRepresentRow2(bMat), extractRepresentRow2(wMat), false);
// //cv::imwrite(param.LutPath, lut);
// lut = calcLUT(extractRepresentRow2(bMat), extractRepresentRow2(wMat), true);
// cv::imwrite(param.TextLutPath, lut);
// #else
// lut = create_lut(extractRepresentRow2(bMat), extractRepresentRow2(wMat), dpi, mode);
// // Mat dst(bMat.cols * bMat.channels(), 256, CV_8UC1);
// // memcpy(dst.data, lut.data, bMat.cols * bMat.channels() * 256);
// cv::imwrite(param.LutPath, lut);
// #endif
// printf("exit creatLUTData \n");
// }
FPGAConfigParam GetFpgaparam(int dpi, int mode)
{
//FPGAConfigParam param = CorrectParam().GetFpgaparam(dpi, mode);
return correctparam.GetFpgaparam(dpi, mode);
}
void SaveFpgaparam(FPGAConfigParam &param)
{
correctparam.SaveCorrectParam(param);
//CorrectParam().SaveCorrectParam(param);
}
// cv::Mat colMean(const cv::Mat &image)
// {
// cv::Mat meanMat(1, image.step, CV_8UC1);
// cv::Mat tempMat(image.rows, image.step, CV_8UC1, image.data);
// for (int i = 0; i < tempMat.step; i++)
// meanMat.data[i] = cv::mean(tempMat(cv::Rect(i, 0, 1, tempMat.rows)))[0];
// return meanMat;
// }
float gamma(float value, float ex)
{
return 0.0;//cv::pow(value / 255.0f, 1.0f / ex) * 255.0f + 0.5f;
}
#define GAMMA_EX 1.7f
#define BLACK_OFFSET 0
void fittingLUT(const std::vector<u_char> &points, u_char min_value, u_char max_value, u_char *data)
{
// float step = max_value - min_value + 1;
// memset(data, min_value, 127);
// memset(data + 127, max_value, 129);
// int b = points[0];
// int w = points[1];
// int tb = min_value;
// int tw = max_value;
// step = cv::max((float)(tw - tb + 1) / (float)(w - b + 1), 0.0f);
// float temp;
// for (int j = 0, length = (255 - b + 1); j < length; j++)
// {
// temp = gamma(tb + step * j, GAMMA_EX) - BLACK_OFFSET;
// data[j + b] = cv::min(255, cv::max(0, static_cast<int>(temp)));
// }
}
// std::vector<double> caculate(const std::vector<double> &points_x, const std::vector<double> &points_y)
// {
// int MaxElement = points_x.size() - 1;
// //计算常数f
// double f = points_y[0];
// //求解
// int n, m;
// // double a[MaxElement][MaxElement+1];
// std::vector<std::vector<double>> a;
// // a.resize(MaxElement);
// for (int i = 0; i < MaxElement; i++)
// {
// std::vector<double> b;
// b.resize(MaxElement + 1);
// a.push_back(b);
// }
// for (int i = 0; i < MaxElement; i++)
// {
// for (int j = 0; j < MaxElement; j++)
// a[i][j] = cv::pow(points_x[i + 1], MaxElement - j);
// a[i][MaxElement] = points_y[i + 1] - f;
// }
// int i, j;
// n = MaxElement;
// for (j = 0; j < n; j++)
// {
// double max = 0;
// double imax = 0;
// for (i = j; i < n; i++)
// {
// if (imax < cv::abs(a[i][j]))
// {
// imax = cv::abs(a[i][j]);
// max = a[i][j]; //得到各行中所在列最大元素
// m = i;
// }
// }
// if (cv::abs(a[j][j]) != max)
// {
// double b = 0;
// for (int k = j; k < n + 1; k++)
// {
// b = a[j][k];
// a[j][k] = a[m][k];
// a[m][k] = b;
// }
// }
// for (int r = j; r < n + 1; r++)
// {
// a[j][r] = a[j][r] / max; //让该行的所在列除以所在列的第一个元素目的是让首元素为1
// }
// for (i = j + 1; i < n; i++)
// {
// double c = a[i][j];
// if (c == 0.0)
// continue;
// for (int s = j; s < n + 1; s++)
// {
// a[i][s] = a[i][s] - a[j][s] * c; //前后行数相减使下一行或者上一行的首元素为0
// }
// }
// }
// for (i = n - 2; i >= 0; i--)
// {
// for (j = i + 1; j < n; j++)
// {
// a[i][n] = a[i][n] - a[j][n] * a[i][j];
// }
// }
// std::vector<double> result;
// for (int k = 0; k < n; k++)
// result.push_back(a[k][n]);
// result.push_back(f);
// return result;
// }
// cv::Mat createLUT(const std::vector<cv::Mat> &mats, bool isTextCorrect)
// {
// int rows = mats[0].cols;
// cv::Mat lut(rows, 256, CV_8UC1);
// double max_val, min_val;
// cv::minMaxIdx(mats[0], &min_val, nullptr);
// cv::minMaxIdx(mats[1], nullptr, &max_val);
// for (size_t i = 0; i < rows; i++)
// {
// std::vector<u_char> grayPoints;
// for (size_t j = 0; j < mats.size(); j++)
// grayPoints.push_back(mats[j].data[i]);
// fittingLUT(grayPoints, static_cast<u_char>(min_val), static_cast<u_char>(max_val), lut.data + i * 256);
// }
// if (isTextCorrect)
// {
// std::vector<double> points_x = {0, 25, 205, 255}, points_y = {0, 0, 230, 255};
// std::vector<double> coefficient = caculate(points_x, points_y);
// u_char buffer[256];
// for (int i = 0; i < 256; i++)
// {
// int temp = coefficient[0] * i * i * i + coefficient[1] * i * i + coefficient[2] * i + coefficient[3];
// buffer[i] = static_cast<u_char>(cv::min(255, cv::max(0, temp)));
// }
// cv::Mat lut_lut(256, 1, CV_8UC1, buffer);
// cv::LUT(lut, lut_lut, lut);
// }
// return lut;
// }
#ifdef G400
#define CHANNEL 408
#else
#define CHANNEL 432
#endif
// cv::Mat calcLUT(const cv::Mat &black, const cv::Mat &white, bool isTextCorrection)
// {
// std::vector<cv::Mat> w;
// w.push_back(colMean(black));
// w.push_back(colMean(white));
// cv::Mat lut = createLUT(w, isTextCorrection);
// for (size_t i = 0, block = lut.rows / CHANNEL; i < block; i++)
// {
// cv::Mat lutROI = lut(cv::Rect(0, i * CHANNEL, 256, CHANNEL));
// cv::Mat tran;
// cv::transpose(lutROI, tran);
// memcpy(lutROI.data, tran.data, tran.total());
// }
// return lut;
// }
// cv::Mat create_lut(const cv::Mat &black, const cv::Mat &white, int dpi, bool colormode)
// {
// #ifndef USE_NEWFLAT
// if (black.empty() || white.empty() || black.channels() != 1 || white.channels() != 1 || black.step != white.step)
// return cv::Mat();
// int channel = 1;
// if (black.step == 4896 || black.step == 7344)
// channel = 408;
// else if (black.step == 14688 || black.step == 22032 || black.step == 44064)
// channel = 432; // 486
// if (channel == 1)
// return cv::Mat();
// const int rows = black.cols / channel;
// const int cols = 256;
// auto cc = CV_8UC(channel);
// Mat lut(rows, cols, CV_8UC(channel));
// for (size_t i = 0; i < rows; i++)
// {
// Mat lut_row = lut(cv::Rect(0, i, cols, 1));
// unsigned char *ptr_buffer = lut_row.data;
// unsigned char *ptr_black = black.data + i * channel;
// unsigned char *ptr_white = white.data + i * channel;
// for (size_t j = 0; j < cols; j++)
// for (size_t k = 0; k < channel; k++)
// {
// if (ptr_black[k] >= ptr_white[k])
// {
// ptr_buffer[j * channel + k] = 0;
// continue;
// }
// if (j <= ptr_black[k])
// ptr_buffer[j * channel + k] = 0;
// else if (j >= ptr_white[k])
// ptr_buffer[j * channel + k] = 255;
// else
// {
// float val = 255.0f * (j - ptr_black[k]) / (ptr_white[k] - ptr_black[k]) * 1.275; //
// ptr_buffer[j * channel + k] = (unsigned char)cv::max(0.0f, cv::min(val, 255.0f));
// }
// }
// }
// cv::Mat saveMat(black.step, 256, CV_8UC1, lut.data);
// return saveMat.clone();
// #else
// return calcLUT(black, white, false);
// #endif
// }
// cv::Mat GetMergeMat(int dstwidth, int dstheight, int type, cv::Mat &mat)
// {
// return CImageMerge().MergeImage(type == CV_8UC3, mat, dstwidth, dstheight);
// }

33
correct_ultis.h Normal file
View File

@ -0,0 +1,33 @@
#pragma once
#include <sstream>
//#include <opencv2/opencv.hpp>
#include "CameraParam.h"
#include "CorrectParam.h"
#include "CImageMerge.h"
//static cv::Mat lutGrayMat; //灰色校正值
//static cv::Mat lutColorMat; //彩色校正值
static CorrectParam correctparam;
void initStep();
void setOffset(int *config, int step);
//cv::Mat calcLUT(const cv::Mat& black, const cv::Mat& white, bool isTextCorrection);
//cv::Mat extractRepresentRow2(const cv::Mat& src);
void initLut(const std::string lutpath,bool iscolor);
//void correctColor(cv::Mat& src, int dpi,int mode,bool isTextCorrect=true);
void creatLUTData(int dpi , int mode);
FPGAConfigParam GetFpgaparam(int dpi,int mode);
void SaveFpgaparam(FPGAConfigParam& param);
//cv::Mat create_lut(const cv::Mat& black, const cv::Mat& white,int dpi, bool colormode);
//cv::Mat GetMergeMat(int dstwidth ,int dstheight,int type,cv::Mat& mat);

54
countdown.sh Normal file
View File

@ -0,0 +1,54 @@
#!/bin/sh
# A countdown timer
# GNU GPLv3
value_num=$#
HOU=$2
MIN=$3
SEC=$4
start(){
# If there are 3 arguments given, they become H, M, and S. Otherwise, the user is asked
if [ $HOU -eq 0 ] && [ $MIN -eq 0 ] && [ $SEC -eq 0 ] ; then
HOU=0
MIN=30
SEC=0
fi
if [ $SEC -lt 60 ] ; then
SEC=60
fi
# Convert input to seconds
TIMER=$(( ($HOU*3600) + ($MIN*60) + $SEC ))
# Count down and output remaining time to temp file
while [ $TIMER -gt 0 ]
do
#printf "%02dh:%02dm:%02ds\n" $((TIMER/3600)) $((TIMER%3600/60)) $((TIMER%60))
printf "%02d:%02d:%02d\n" $((TIMER/3600)) $((TIMER%3600/60)) $((TIMER%60))
sleep 10
TIMER=$(( TIMER - 10 ))
done
if [ $SEC -gt 0 ] ; then
#echo freeze > /sys/power/state
echo sleep > /etc/kernel_state
pkill scanservice
/etc/usbmonitor &
/etc/pm_control off
echo 0 > /sys/class/leds/red/brightness
echo 0 > /sys/class/leds/white/brightness
echo 0 > /sys/class/leds/green/brightness
echo 1 > /sys/class/leds/green/brightness
fi
}
stop(){
echo "timer need to be killed"
}
if [ "$1" != "" ]; then
case $1 in
start|stop) "$1" ;;
esac
fi

65
default_cfg.h Executable file
View File

@ -0,0 +1,65 @@
/*
* @Author: Zhaozhonmin 1656963645@qq.com
* @Date: 2022-06-24 17:48:35
* @LastEditors: Zhaozhonmin 1656963645@qq.com
* @LastEditTime: 2023-02-06 19:04:54
* @FilePath: \zynq_ps\usb\inc\default_cfg.h
* @Description: ,`customMade`, koroFileHeader查看配置 : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
/*
* CAMTP Responder
* Copyright (c) 2020 Holdtecs Technologies
*
* CAMTP Responder is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* CAMTP Responder is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 3 for more details.
*
* You should have received a copy of the GNU General Public License
* along with CAMTP Responder; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file default.h
* @brief Main CAMMTP protocol functions.
* @author Barry Ruan <cubex@foxmail.com>
*/
#ifndef _INC_DEFAULT_CFG_H_
#define _INC_DEFAULT_CFG_H_
#ifndef CAMTPR_CONF_FILE
#define CAMTPR_CONF_FILE "/etc/camtprd/camtprd.conf"
#endif
#define MAX_PACKET_SIZE 512
#define USB_DEV_VENDOR_ID 0x3072 //0x04B4 // Linux Foundation
#define USB_DEV_PRODUCT_ID 0x0300 // PTP Gadget
#define USB_DEV_CLASS 0xFF // Still Imaging device
#define USB_DEV_SUBCLASS 0x1 //
#define USB_DEV_PROTOCOL 0x1 //
#define USB_DEV_VERSION 0x3008
#define USB_FFS_MODE 1
#define USB_FFS_AIO_MODE 2
#define USB_DEV "/dev/ffs-camtp/ep0"
#define USB_EPIN "/dev/ffs-camtp/ep1"
#define USB_EPOUT "/dev/ffs-camtp/ep2"
#define USB_EPINTIN "/dev/ffs-camtp/ep3"
#define MANUFACTURER "HOLDTECS Technologies"
#define PRODUCT "HOLDTECS"
#define SERIALNUMBER "01234567ABCDEFG"
#endif

158
filetools.h Normal file
View File

@ -0,0 +1,158 @@
#pragma once
#include <vector>
#include <iostream>
#include <fstream>
#include <time.h>
#include <sstream>
#include <chrono>
#include <sys/timeb.h>
#include <chrono>
#include <iostream>
#include <ctime>
class FileTools
{
private:
std::string mPath;
public:
FileTools(std::string path)
{
mPath = path;
}
void createLog(std::string log)
{
time_t now = time(0);
tm *ltm = localtime(&now);
char loc_date[30];
sprintf(loc_date, "%d%02d%02d %d:%d:%d", 1900 + ltm->tm_year, 1 + ltm->tm_mon, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec);
std::ofstream ofs(mPath);
ofs << loc_date << ": " << log << std::endl;
ofs.close();
}
void append_log(std::string log, bool printTime = true)
{
std::ofstream ofs(mPath, std::ios::app);
if (printTime)
{
// time_t now = time(0);
// struct timeb stTimeb;
// ftime(&stTimeb);
// tm *ltm = localtime(&now);
// char loc_date[30];
// sprintf(loc_date, "%d%02d%02d %d:%d:%d", 1900 + ltm->tm_year, 1 + ltm->tm_mon, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec);
struct tm *ptm;
struct timeb stTimeb;
static char loc_date[30];
ftime(&stTimeb);
ptm = localtime(&stTimeb.time);
sprintf(loc_date, "%02d-%02d %02d:%02d:%02d.%03d",
ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, stTimeb.millitm);
ofs << loc_date << ": " << log << std::endl;
}
else
{
ofs << " " << log << std::endl;
}
ofs.close();
}
void clear()
{
try
{
std::fstream fout(mPath, std::ios::out | std::ios::trunc);
fout.close();
}
catch (std::exception &e)
{
//LOG("error happened: %s \n", e.what());
}
}
};
static std::string GetCurrentTimeStamp(int time_stamp_type )
{
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::time_t now_time_t = std::chrono::system_clock::to_time_t(now);
std::tm* now_tm = std::localtime(&now_time_t);
char buffer[128];
strftime(buffer, sizeof(buffer), "%F %T", now_tm);
std::ostringstream ss;
ss.fill('0');
std::chrono::milliseconds ms;
std::chrono::microseconds cs;
std::chrono::nanoseconds ns;
switch (time_stamp_type)
{
case 0:
ss << buffer;
break;
case 1:
ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
ss << buffer << ":" << ms.count();
break;
case 2:
ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
cs = std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()) % 1000000;
ss << buffer << ":" << ms.count() << ":" << cs.count() % 1000;
break;
case 3:
ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
cs = std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()) % 1000000;
ns = std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()) % 1000000000;
ss << buffer << ":" << ms.count() << ":" << cs.count() % 1000 << ":" << ns.count() % 1000;
break;
default:
ss << buffer;
break;
}
return ss.str();
}
class StopWatch
{
public:
StopWatch()
{
_start = std::chrono::steady_clock::now();
}
void reset()
{
_start = std::chrono::steady_clock::now();
}
double elapsed_s()
{
return std::chrono::duration<double>(std::chrono::steady_clock::now() - _start).count();
}
double elapsed_ms()
{
return std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now() - _start).count();
}
double elapsed_us()
{
return std::chrono::duration<double, std::micro>(std::chrono::steady_clock::now() - _start).count();
}
double elapsed_ns()
{
return std::chrono::duration<double, std::nano>(std::chrono::steady_clock::now() - _start).count();
}
private:
std::chrono::steady_clock::time_point _start;
};

20
fpga/CMakeLists.txt Normal file
View File

@ -0,0 +1,20 @@
project(fpgaupdate)
add_compile_options(-std=c++14)
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -O2")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O2")
aux_source_directory(${PROJECT_SOURCE_DIR} DIR_SRCS)
file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h" "${PROJECT_SOURCE_DIR}/*.hpp")
set(DIR_SRCS ${DIR_SRCS} ${DIR_HEADS})
add_library(${PROJECT_NAME} STATIC ${DIR_SRCS})
# target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR}
# ${PROJECT_SOURCE_DIR}/../3rdparty/nick
# ${PROJECT_SOURCE_DIR}/../ImageProcess
# ${PROJECT_SOURCE_DIR}/../3rdparty/opencv/include
# ${PROJECT_SOURCE_DIR}/../3rdparty/tiff/include
# ${PROJECT_SOURCE_DIR}/../../../sdk/include
# ${PROJECT_SOURCE_DIR}/../wrapper
# )
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../bin)

122
fpga/fpgacontrol.cpp Normal file
View File

@ -0,0 +1,122 @@
#include "fpgacontrol.h"
#include "libmtd.h"
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <thread>
#define MTD_NODE "/dev/mtd0"
#define FPGAFILEPATH "/etc/fpgaupdatefile.bin"
fpgacontrol::fpgacontrol() :
m_fpgafile_fd(0),
m_updateEnable(false)
{
//printf("fpga version : %d \n", fpgaversion);
}
fpgacontrol::~fpgacontrol()
{
}
bool fpgacontrol::ifneedupdatefpga()
{
if ((access(FPGAFILEPATH, F_OK)) != -1)
{
m_updateEnable = true;
printf("found %s file ,will update fpga later!\n", FPGAFILEPATH);
}
else
{
m_updateEnable = false;
printf("%s file do not exist!\n", FPGAFILEPATH);
}
return m_updateEnable;
}
bool fpgacontrol::updatefpga()
{
if (!m_updateEnable)
{
printf("checked don't need to update fpga\n");
return false;
}
return updatefpgafirmware(FPGAFILEPATH);
}
bool fpgacontrol::updatefpgafirmware(std::string fpgafirmpath)
{
system("echo 68 > /sys/class/gpio/export");
system("echo out > /sys/class/gpio/gpio68/direction");
system("echo 0 > /sys/class/gpio/gpio68/value");
if ((m_fpgafile_fd = open(MTD_NODE, O_RDWR)) <= 0)
{
printf("update fpga error,on open mtd node!\n");
return false;
}
libmtd_t desc;
desc = libmtd_open();
if (NULL == desc)
{
printf("libmtd_open error...\n");
return false;
}
mtd_dev_info dev_info;
mtd_get_dev_info(desc, MTD_NODE, &dev_info);
printf("mtd_num = %x\n", dev_info.mtd_num);
printf("major = %x\n", dev_info.major);
printf("minor = %x\n", dev_info.minor);
printf("type_str = %s\n", dev_info.type_str);
printf("name = %s\n", dev_info.name);
printf("size = %d\n", dev_info.size);
printf("eb_cnt = %d\n", dev_info.eb_cnt);
printf("eb_size = %d\n", dev_info.eb_size);
printf("min_io_size = %d\n", dev_info.min_io_size);
printf("subpage_size = %d\n", dev_info.subpage_size);
printf("oob_size = %d\n", dev_info.oob_size);
printf("region_cnt = %d\n", dev_info.region_cnt);
printf("writable = %d\n", dev_info.writable);
printf("bb_allowed = %d\n", dev_info.bb_allowed);
for (int i = 0; i < dev_info.eb_cnt; i++)
{
if (mtd_erase(desc, &dev_info, m_fpgafile_fd, i) != 0)
{
printf("mtd_erase error...........\n");
if (desc)
{
libmtd_close(desc);
desc = NULL;
}
if (m_fpgafile_fd)
{
close(m_fpgafile_fd);
m_fpgafile_fd = NULL;
}
//system("echo 1 > /sys/class/gpio/gpio221/value");
std::this_thread::sleep_for(std::chrono::milliseconds(100));
return false;
}
}
int ret = mtd_write_img(&dev_info, m_fpgafile_fd, 0, 0, fpgafirmpath.c_str());
libmtd_close(desc);
if (ret < 0)
{
printf("mtd_write_img failed...........\n");
return false;
}
else
{
printf("mtd_write_img success...........\n");
std::string rmcmd = "rm -f /etc/fpgaupdatefile.bin";
system(rmcmd.c_str());
return true;
}
}

21
fpga/fpgacontrol.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#include <string>
class FpgaComm;
class fpgacontrol
{
private:
/* data */
public:
fpgacontrol();
~fpgacontrol();
bool ifneedupdatefpga();
bool updatefpga();
private:
bool updatefpgafirmware(std::string fpgafirmpath);
private:
int m_fpgaversion;
int m_fpgafile_fd;
bool m_updateEnable;
};

1443
fpga/libmtd.c Normal file

File diff suppressed because it is too large Load Diff

357
fpga/libmtd.h Normal file
View File

@ -0,0 +1,357 @@
/*
* Copyright (C) 2008, 2009 Nokia Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Author: Artem Bityutskiy
*
* MTD library.
*/
/* Imported from mtd-utils by dehrenberg */
#ifndef __LIBMTD_H__
#define __LIBMTD_H__
#ifdef __cplusplus
extern "C" {
#endif
// Needed for uint8_t, uint64_t
#include <stdint.h>
/* Maximum MTD device name length */
#define MTD_NAME_MAX 127
/* Maximum MTD device type string length */
#define MTD_TYPE_MAX 64
/* MTD library descriptor */
typedef void * libmtd_t;
/* Forward decls */
struct region_info_user;
/**
* @mtd_dev_cnt: count of MTD devices in system
* @lowest_mtd_num: lowest MTD device number in system
* @highest_mtd_num: highest MTD device number in system
* @sysfs_supported: non-zero if sysfs is supported by MTD
*/
struct mtd_info
{
int mtd_dev_cnt;
int lowest_mtd_num;
int highest_mtd_num;
unsigned int sysfs_supported:1;
};
/**
* struct mtd_dev_info - information about an MTD device.
* @mtd_num: MTD device number
* @major: major number of corresponding character device
* @minor: minor number of corresponding character device
* @type: flash type (constants like %MTD_NANDFLASH defined in mtd-abi.h)
* @type_str: static R/O flash type string
* @name: device name
* @size: device size in bytes
* @eb_cnt: count of eraseblocks
* @eb_size: eraseblock size
* @min_io_size: minimum input/output unit size
* @subpage_size: sub-page size
* @oob_size: OOB size (zero if the device does not have OOB area)
* @region_cnt: count of additional erase regions
* @writable: zero if the device is read-only
* @bb_allowed: non-zero if the MTD device may have bad eraseblocks
*/
struct mtd_dev_info
{
int mtd_num;
int major;
int minor;
int type;
char type_str[MTD_TYPE_MAX + 1];
char name[MTD_NAME_MAX + 1];
long long size;
int eb_cnt;
int eb_size;
int min_io_size;
int subpage_size;
int oob_size;
int region_cnt;
unsigned int writable:1;
unsigned int bb_allowed:1;
};
/**
* libmtd_open - open MTD library.
*
* This function initializes and opens the MTD library and returns MTD library
* descriptor in case of success and %NULL in case of failure. In case of
* failure, errno contains zero if MTD is not present in the system, or
* contains the error code if a real error happened.
*/
libmtd_t libmtd_open(void);
/**
* libmtd_close - close MTD library.
* @desc: MTD library descriptor
*/
void libmtd_close(libmtd_t desc);
/**
* mtd_dev_present - check whether a MTD device is present.
* @desc: MTD library descriptor
* @mtd_num: MTD device number to check
*
* This function returns %1 if MTD device is present and %0 if not.
*/
int mtd_dev_present(libmtd_t desc, int mtd_num);
/**
* mtd_get_info - get general MTD information.
* @desc: MTD library descriptor
* @info: the MTD device information is returned here
*
* This function fills the passed @info object with general MTD information and
* returns %0 in case of success and %-1 in case of failure. If MTD subsystem is
* not present in the system, errno is set to @ENODEV.
*/
int mtd_get_info(libmtd_t desc, struct mtd_info *info);
/**
* mtd_get_dev_info - get information about an MTD device.
* @desc: MTD library descriptor
* @node: name of the MTD device node
* @mtd: the MTD device information is returned here
*
* This function gets information about MTD device defined by the @node device
* node file and saves this information in the @mtd object. Returns %0 in case
* of success and %-1 in case of failure. If MTD subsystem is not present in the
* system, or the MTD device does not exist, errno is set to @ENODEV.
*/
int mtd_get_dev_info(libmtd_t desc, const char *node, struct mtd_dev_info *mtd);
/**
* mtd_get_dev_info1 - get information about an MTD device.
* @desc: MTD library descriptor
* @mtd_num: MTD device number to fetch information about
* @mtd: the MTD device information is returned here
*
* This function is identical to 'mtd_get_dev_info()' except that it accepts
* MTD device number, not MTD character device.
*/
int mtd_get_dev_info1(libmtd_t desc, int mtd_num, struct mtd_dev_info *mtd);
/**
* mtd_lock - lock eraseblocks.
* @desc: MTD library descriptor
* @mtd: MTD device description object
* @fd: MTD device node file descriptor
* @eb: eraseblock to lock
*
* This function locks eraseblock @eb. Returns %0 in case of success and %-1
* in case of failure.
*/
int mtd_lock(const struct mtd_dev_info *mtd, int fd, int eb);
/**
* mtd_unlock - unlock eraseblocks.
* @desc: MTD library descriptor
* @mtd: MTD device description object
* @fd: MTD device node file descriptor
* @eb: eraseblock to lock
*
* This function unlocks eraseblock @eb. Returns %0 in case of success and %-1
* in case of failure.
*/
int mtd_unlock(const struct mtd_dev_info *mtd, int fd, int eb);
/**
* mtd_erase - erase an eraseblock.
* @desc: MTD library descriptor
* @mtd: MTD device description object
* @fd: MTD device node file descriptor
* @eb: eraseblock to erase
*
* This function erases eraseblock @eb of MTD device described by @fd. Returns
* %0 in case of success and %-1 in case of failure.
*/
int mtd_erase(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb);
/**
* mtd_regioninfo - get information about an erase region.
* @fd: MTD device node file descriptor
* @regidx: index of region to look up
* @reginfo: the region information is returned here
*
* This function gets information about an erase region defined by the
* @regidx index and saves this information in the @reginfo object.
* Returns %0 in case of success and %-1 in case of failure. If the
* @regidx is not valid or unavailable, errno is set to @ENODEV.
*/
int mtd_regioninfo(int fd, int regidx, struct region_info_user *reginfo);
/**
* mtd_is_locked - see if the specified eraseblock is locked.
* @mtd: MTD device description object
* @fd: MTD device node file descriptor
* @eb: eraseblock to check
*
* This function checks to see if eraseblock @eb of MTD device described
* by @fd is locked. Returns %0 if it is unlocked, %1 if it is locked, and
* %-1 in case of failure. If the ioctl is not supported (support was added in
* Linux kernel 2.6.36) or this particular device does not support it, errno is
* set to @ENOTSUPP.
*/
int mtd_is_locked(const struct mtd_dev_info *mtd, int fd, int eb);
/**
* mtd_torture - torture an eraseblock.
* @desc: MTD library descriptor
* @mtd: MTD device description object
* @fd: MTD device node file descriptor
* @eb: eraseblock to torture
*
* This function tortures eraseblock @eb. Returns %0 in case of success and %-1
* in case of failure.
*/
int mtd_torture(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb);
/**
* mtd_is_bad - check if eraseblock is bad.
* @mtd: MTD device description object
* @fd: MTD device node file descriptor
* @eb: eraseblock to check
*
* This function checks if eraseblock @eb is bad. Returns %0 if not, %1 if yes,
* and %-1 in case of failure.
*/
int mtd_is_bad(const struct mtd_dev_info *mtd, int fd, int eb);
/**
* mtd_mark_bad - mark an eraseblock as bad.
* @mtd: MTD device description object
* @fd: MTD device node file descriptor
* @eb: eraseblock to mark as bad
*
* This function marks eraseblock @eb as bad. Returns %0 in case of success and
* %-1 in case of failure.
*/
int mtd_mark_bad(const struct mtd_dev_info *mtd, int fd, int eb);
/**
* mtd_read - read data from an MTD device.
* @mtd: MTD device description object
* @fd: MTD device node file descriptor
* @eb: eraseblock to read from
* @offs: offset withing the eraseblock to read from
* @buf: buffer to read data to
* @len: how many bytes to read
*
* This function reads @len bytes of data from eraseblock @eb and offset @offs
* of the MTD device defined by @mtd and stores the read data at buffer @buf.
* Returns %0 in case of success and %-1 in case of failure.
*/
int mtd_read(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
void *buf, int len);
/**
* mtd_write - write data to an MTD device.
* @desc: MTD library descriptor
* @mtd: MTD device description object
* @fd: MTD device node file descriptor
* @eb: eraseblock to write to
* @offs: offset withing the eraseblock to write to
* @data: data buffer to write
* @len: how many data bytes to write
* @oob: OOB buffer to write
* @ooblen: how many OOB bytes to write
* @mode: write mode (e.g., %MTD_OOB_PLACE, %MTD_OOB_RAW)
*
* This function writes @len bytes of data to eraseblock @eb and offset @offs
* of the MTD device defined by @mtd. Returns %0 in case of success and %-1 in
* case of failure.
*
* Can only write to a single page at a time if writing to OOB.
*/
int mtd_write(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb,
int offs, void *data, int len, void *oob, int ooblen,
uint8_t mode);
/**
* mtd_read_oob - read out-of-band area.
* @desc: MTD library descriptor
* @mtd: MTD device description object
* @fd: MTD device node file descriptor
* @start: page-aligned start address
* @length: number of OOB bytes to read
* @data: read buffer
*
* This function reads @length OOB bytes starting from address @start on
* MTD device described by @fd. The address is specified as page byte offset
* from the beginning of the MTD device. This function returns %0 in case of
* success and %-1 in case of failure.
*/
int mtd_read_oob(libmtd_t desc, const struct mtd_dev_info *mtd, int fd,
uint64_t start, uint64_t length, void *data);
/**
* mtd_write_oob - write out-of-band area.
* @desc: MTD library descriptor
* @mtd: MTD device description object
* @fd: MTD device node file descriptor
* @start: page-aligned start address
* @length: number of OOB bytes to write
* @data: write buffer
*
* This function writes @length OOB bytes starting from address @start on
* MTD device described by @fd. The address is specified as page byte offset
* from the beginning of the MTD device. Returns %0 in case of success and %-1
* in case of failure.
*/
int mtd_write_oob(libmtd_t desc, const struct mtd_dev_info *mtd, int fd,
uint64_t start, uint64_t length, void *data);
/**
* mtd_write_img - write a file to MTD device.
* @mtd: MTD device description object
* @fd: MTD device node file descriptor
* @eb: eraseblock to write to
* @offs: offset withing the eraseblock to write to
* @img_name: the file to write
*
* This function writes an image @img_name the MTD device defined by @mtd. @eb
* and @offs are the starting eraseblock and offset on the MTD device. Returns
* %0 in case of success and %-1 in case of failure.
*/
int mtd_write_img(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
const char *img_name);
/**
* mtd_probe_node - test MTD node.
* @desc: MTD library descriptor
* @node: the node to test
*
* This function tests whether @node is an MTD device node and returns %1 if it
* is, and %-1 if it is not (errno is %ENODEV in this case) or if an error
* occurred.
*/
int mtd_probe_node(libmtd_t desc, const char *node);
#ifdef __cplusplus
}
#endif
#endif /* __LIBMTD_H__ */

224
fpga/libmtd_common.h Normal file
View File

@ -0,0 +1,224 @@
/*
* Copyright (c) Artem Bityutskiy, 2007, 2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Imported from mtd-utils by dehrenberg */
#ifndef __MTD_UTILS_COMMON_H__
#define __MTD_UTILS_COMMON_H__
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <features.h>
#include <inttypes.h>
#include <sys/sysmacros.h>
#ifndef PROGRAM_NAME
# error "You must define PROGRAM_NAME before including this header"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef MIN /* some C lib headers define this for us */
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#define min(a, b) MIN(a, b) /* glue for linux kernel source */
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
#define min_t(t,x,y) ({ \
typeof((x)) _x = (x); \
typeof((y)) _y = (y); \
(_x < _y) ? _x : _y; \
})
#define max_t(t,x,y) ({ \
typeof((x)) _x = (x); \
typeof((y)) _y = (y); \
(_x > _y) ? _x : _y; \
})
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
/* define a print format specifier for off_t */
#ifdef __USE_FILE_OFFSET64
#define PRIxoff_t PRIx64
#define PRIdoff_t PRId64
#else
#define PRIxoff_t "l" PRIx32
#define PRIdoff_t "l" PRId32
#endif
/* Verbose messages */
#define bareverbose(verbose, fmt, ...) do { \
if (verbose) \
printf(fmt, ##__VA_ARGS__); \
} while(0)
#define verbose(verbose, fmt, ...) \
bareverbose(verbose, "%s: " fmt "\n", PROGRAM_NAME, ##__VA_ARGS__)
/* Normal messages */
#define normsg_cont(fmt, ...) do { \
printf("%s: " fmt, PROGRAM_NAME, ##__VA_ARGS__); \
} while(0)
#define normsg(fmt, ...) do { \
normsg_cont(fmt "\n", ##__VA_ARGS__); \
} while(0)
/* Error messages */
#define errmsg(fmt, ...) ({ \
fprintf(stderr, "%s: error!: " fmt "\n", PROGRAM_NAME, ##__VA_ARGS__); \
-1; \
})
#define errmsg_die(fmt, ...) do { \
exit(errmsg(fmt, ##__VA_ARGS__)); \
} while(0)
/* System error messages */
#define sys_errmsg(fmt, ...) ({ \
int _err = errno; \
errmsg(fmt, ##__VA_ARGS__); \
fprintf(stderr, "%*serror %d (%s)\n", (int)sizeof(PROGRAM_NAME) + 1,\
"", _err, strerror(_err)); \
-1; \
})
#define sys_errmsg_die(fmt, ...) do { \
exit(sys_errmsg(fmt, ##__VA_ARGS__)); \
} while(0)
/* Warnings */
#define warnmsg(fmt, ...) do { \
fprintf(stderr, "%s: warning!: " fmt "\n", PROGRAM_NAME, ##__VA_ARGS__); \
} while(0)
#if defined(__UCLIBC__)
/* uClibc versions before 0.9.34 don't have rpmatch() */
#if __UCLIBC_MAJOR__ == 0 && \
(__UCLIBC_MINOR__ < 9 || \
(__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ < 34))
#undef rpmatch
#define rpmatch __rpmatch
static inline int __rpmatch(const char *resp)
{
return (resp[0] == 'y' || resp[0] == 'Y') ? 1 :
(resp[0] == 'n' || resp[0] == 'N') ? 0 : -1;
}
#endif
#endif
/**
* prompt the user for confirmation
*/
static inline bool prompt(const char *msg, bool def)
{
char *line = NULL;
size_t len;
bool ret = def;
do {
normsg_cont("%s (%c/%c) ", msg, def ? 'Y' : 'y', def ? 'n' : 'N');
fflush(stdout);
while (getline(&line, &len, stdin) == -1) {
printf("failed to read prompt; assuming '%s'\n",
def ? "yes" : "no");
break;
}
if (strcmp("\n", line) != 0) {
switch (rpmatch(line)) {
case 0: ret = false; break;
case 1: ret = true; break;
case -1:
puts("unknown response; please try again");
continue;
}
}
break;
} while (1);
free(line);
return ret;
}
static inline int is_power_of_2(unsigned long long n)
{
return (n != 0 && ((n & (n - 1)) == 0));
}
/**
* simple_strtoX - convert a hex/dec/oct string into a number
* @snum: buffer to convert
* @error: set to 1 when buffer isn't fully consumed
*
* These functions are similar to the standard strtoX() functions, but they are
* a little bit easier to use if you want to convert full string of digits into
* the binary form. The typical usage:
*
* int error = 0;
* unsigned long num;
*
* num = simple_strtoul(str, &error);
* if (error || ... if needed, your check that num is not out of range ...)
* error_happened();
*/
#define simple_strtoX(func, type) \
static inline type simple_##func(const char *snum, int *error) \
{ \
char *endptr; \
type ret = func(snum, &endptr, 0); \
\
if (error && (!*snum || *endptr)) { \
errmsg("%s: unable to parse the number '%s'", #func, snum); \
*error = 1; \
} \
\
return ret; \
}
simple_strtoX(strtol, long int)
simple_strtoX(strtoll, long long int)
simple_strtoX(strtoul, unsigned long int)
simple_strtoX(strtoull, unsigned long long int)
/* Simple version-printing for utils */
#define common_print_version() \
do { \
printf("%s %s\n", PROGRAM_NAME, VERSION); \
} while (0)
#include "libmtd_xalloc.h"
#ifdef __cplusplus
}
#endif
#endif /* !__MTD_UTILS_COMMON_H__ */

109
fpga/libmtd_int.h Normal file
View File

@ -0,0 +1,109 @@
/*
* Copyright (c) International Business Machines Corp., 2006
* Copyright (C) 2009 Nokia Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Author: Artem Bityutskiy
*
* MTD library.
*/
/* Imported from mtd-utils by dehrenberg */
#ifndef __LIBMTD_INT_H__
#define __LIBMTD_INT_H__
#ifdef __cplusplus
extern "C" {
#endif
#define PROGRAM_NAME "libmtd"
#define SYSFS_MTD "class/mtd"
#define MTD_NAME_PATT "mtd%d"
#define MTD_DEV "dev"
#define MTD_NAME "name"
#define MTD_TYPE "type"
#define MTD_EB_SIZE "erasesize"
#define MTD_SIZE "size"
#define MTD_MIN_IO_SIZE "writesize"
#define MTD_SUBPAGE_SIZE "subpagesize"
#define MTD_OOB_SIZE "oobsize"
#define MTD_REGION_CNT "numeraseregions"
#define MTD_FLAGS "flags"
#define OFFS64_IOCTLS_UNKNOWN 0
#define OFFS64_IOCTLS_NOT_SUPPORTED 1
#define OFFS64_IOCTLS_SUPPORTED 2
/**
* libmtd - MTD library description data structure.
* @sysfs_mtd: MTD directory in sysfs
* @mtd: MTD device sysfs directory pattern
* @mtd_dev: MTD device major/minor numbers file pattern
* @mtd_name: MTD device name file pattern
* @mtd_type: MTD device type file pattern
* @mtd_eb_size: MTD device eraseblock size file pattern
* @mtd_size: MTD device size file pattern
* @mtd_min_io_size: minimum I/O unit size file pattern
* @mtd_subpage_size: sub-page size file pattern
* @mtd_oob_size: MTD device OOB size file pattern
* @mtd_region_cnt: count of additional erase regions file pattern
* @mtd_flags: MTD device flags file pattern
* @sysfs_supported: non-zero if sysfs is supported by MTD
* @offs64_ioctls: %OFFS64_IOCTLS_SUPPORTED if 64-bit %MEMERASE64,
* %MEMREADOOB64, %MEMWRITEOOB64 MTD device ioctls are
* supported, %OFFS64_IOCTLS_NOT_SUPPORTED if not, and
* %OFFS64_IOCTLS_UNKNOWN if it is not known yet;
*
* Note, we cannot find out whether 64-bit ioctls are supported by MTD when we
* are initializing the library, because this requires an MTD device node.
* Indeed, we have to actually call the ioctl and check for %ENOTTY to find
* out whether it is supported or not.
*
* Thus, we leave %offs64_ioctls uninitialized in 'libmtd_open()', and
* initialize it later, when corresponding libmtd function is used, and when
* we actually have a device node and can invoke an ioctl command on it.
*/
struct libmtd
{
char *sysfs_mtd;
char *mtd;
char *mtd_dev;
char *mtd_name;
char *mtd_type;
char *mtd_eb_size;
char *mtd_size;
char *mtd_min_io_size;
char *mtd_subpage_size;
char *mtd_oob_size;
char *mtd_region_cnt;
char *mtd_flags;
unsigned int sysfs_supported:1;
unsigned int offs64_ioctls:2;
};
int legacy_libmtd_open(void);
int legacy_dev_present(int mtd_num);
int legacy_mtd_get_info(struct mtd_info *info);
int legacy_get_dev_info(const char *node, struct mtd_dev_info *mtd);
int legacy_get_dev_info1(int dev_num, struct mtd_dev_info *mtd);
#ifdef __cplusplus
}
#endif
#endif /* !__LIBMTD_INT_H__ */

384
fpga/libmtd_legacy.c Normal file
View File

@ -0,0 +1,384 @@
/*
* Copyright (C) 2009 Nokia Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Author: Artem Bityutskiy
*
* This file is part of the MTD library. Implements pre-2.6.30 kernels support,
* where MTD did not have sysfs interface. The main limitation of the old
* kernels was that the sub-page size was not exported to user-space, so it was
* not possible to get sub-page size.
*/
/* Imported from mtd-utils by dehrenberg */
#include <limits.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <mtd/mtd-user.h>
#include "libmtd.h"
#include "libmtd_int.h"
#include "libmtd_common.h"
#define MTD_PROC_FILE "/proc/mtd"
#define MTD_DEV_PATT "/dev/mtd%d"
#define MTD_DEV_MAJOR 90
#define PROC_MTD_FIRST "dev: size erasesize name\n"
#define PROC_MTD_FIRST_LEN (sizeof(PROC_MTD_FIRST) - 1)
#define PROC_MTD_MAX_LEN 4096
#define PROC_MTD_PATT "mtd%d: %llx %x"
/**
* struct proc_parse_info - /proc/mtd parsing information.
* @mtd_num: MTD device number
* @size: device size
* @eb_size: eraseblock size
* @name: device name
* @buf: contents of /proc/mtd
* @data_size: how much data was read into @buf
* @pos: next string in @buf to parse
*/
struct proc_parse_info
{
int mtd_num;
long long size;
char name[MTD_NAME_MAX + 1];
int eb_size;
char *buf;
int data_size;
char *next;
};
static int proc_parse_start(struct proc_parse_info *pi)
{
int fd, ret;
fd = open(MTD_PROC_FILE, O_RDONLY);
if (fd == -1)
return -1;
pi->buf = xmalloc(PROC_MTD_MAX_LEN);
ret = read(fd, pi->buf, PROC_MTD_MAX_LEN);
if (ret == -1) {
sys_errmsg("cannot read \"%s\"", MTD_PROC_FILE);
goto out_free;
}
if (ret < PROC_MTD_FIRST_LEN ||
memcmp(pi->buf, PROC_MTD_FIRST, PROC_MTD_FIRST_LEN)) {
errmsg("\"%s\" does not start with \"%s\"", MTD_PROC_FILE,
PROC_MTD_FIRST);
goto out_free;
}
pi->data_size = ret;
pi->next = pi->buf + PROC_MTD_FIRST_LEN;
close(fd);
return 0;
out_free:
free(pi->buf);
close(fd);
return -1;
}
static int proc_parse_next(struct proc_parse_info *pi)
{
int ret, len, pos = pi->next - pi->buf;
char *p, *p1;
if (pos >= pi->data_size) {
free(pi->buf);
return 0;
}
ret = sscanf(pi->next, PROC_MTD_PATT, &pi->mtd_num, &pi->size,
&pi->eb_size);
if (ret != 3)
return errmsg("\"%s\" pattern not found", PROC_MTD_PATT);
p = memchr(pi->next, '\"', pi->data_size - pos);
if (!p)
return errmsg("opening \" not found");
p += 1;
pos = p - pi->buf;
if (pos >= pi->data_size)
return errmsg("opening \" not found");
p1 = memchr(p, '\"', pi->data_size - pos);
if (!p1)
return errmsg("closing \" not found");
pos = p1 - pi->buf;
if (pos >= pi->data_size)
return errmsg("closing \" not found");
len = p1 - p;
if (len > MTD_NAME_MAX)
return errmsg("too long mtd%d device name", pi->mtd_num);
memcpy(pi->name, p, len);
pi->name[len] = '\0';
if (p1[1] != '\n')
return errmsg("opening \"\n\" not found");
pi->next = p1 + 2;
return 1;
}
/**
* legacy_libmtd_open - legacy version of 'libmtd_open()'.
*
* This function is just checks that MTD is present in the system. Returns
* zero in case of success and %-1 in case of failure. In case of failure,
* errno contains zero if MTD is not present in the system, or contains the
* error code if a real error happened. This is similar to the 'libmtd_open()'
* return conventions.
*/
int legacy_libmtd_open(void)
{
int fd;
fd = open(MTD_PROC_FILE, O_RDONLY);
if (fd == -1) {
if (errno == ENOENT)
errno = 0;
return -1;
}
close(fd);
return 0;
}
/**
* legacy_dev_presentl - legacy version of 'mtd_dev_present()'.
* @info: the MTD device information is returned here
*
* When the kernel does not provide sysfs files for the MTD subsystem,
* fall-back to parsing the /proc/mtd file to determine whether an mtd device
* number @mtd_num is present.
*/
int legacy_dev_present(int mtd_num)
{
int ret;
struct proc_parse_info pi;
ret = proc_parse_start(&pi);
if (ret)
return -1;
while (proc_parse_next(&pi)) {
if (pi.mtd_num == mtd_num)
return 1;
}
return 0;
}
/**
* legacy_mtd_get_info - legacy version of 'mtd_get_info()'.
* @info: the MTD device information is returned here
*
* This function is similar to 'mtd_get_info()' and has the same conventions.
*/
int legacy_mtd_get_info(struct mtd_info *info)
{
int ret;
struct proc_parse_info pi;
ret = proc_parse_start(&pi);
if (ret)
return -1;
info->lowest_mtd_num = INT_MAX;
while (proc_parse_next(&pi)) {
info->mtd_dev_cnt += 1;
if (pi.mtd_num > info->highest_mtd_num)
info->highest_mtd_num = pi.mtd_num;
if (pi.mtd_num < info->lowest_mtd_num)
info->lowest_mtd_num = pi.mtd_num;
}
return 0;
}
/**
* legacy_get_dev_info - legacy version of 'mtd_get_dev_info()'.
* @node: name of the MTD device node
* @mtd: the MTD device information is returned here
*
* This function is similar to 'mtd_get_dev_info()' and has the same
* conventions.
*/
int legacy_get_dev_info(const char *node, struct mtd_dev_info *mtd)
{
struct stat st;
struct mtd_info_user ui;
int fd, ret;
loff_t offs = 0;
struct proc_parse_info pi;
if (stat(node, &st)) {
sys_errmsg("cannot open \"%s\"", node);
if (errno == ENOENT)
normsg("MTD subsystem is old and does not support "
"sysfs, so MTD character device nodes have "
"to exist");
}
if (!S_ISCHR(st.st_mode)) {
errno = EINVAL;
return errmsg("\"%s\" is not a character device", node);
}
memset(mtd, '\0', sizeof(struct mtd_dev_info));
mtd->major = major(st.st_rdev);
mtd->minor = minor(st.st_rdev);
if (mtd->major != MTD_DEV_MAJOR) {
errno = EINVAL;
return errmsg("\"%s\" has major number %d, MTD devices have "
"major %d", node, mtd->major, MTD_DEV_MAJOR);
}
mtd->mtd_num = mtd->minor / 2;
fd = open(node, O_RDONLY);
if (fd == -1)
return sys_errmsg("cannot open \"%s\"", node);
if (ioctl(fd, MEMGETINFO, &ui)) {
sys_errmsg("MEMGETINFO ioctl request failed");
goto out_close;
}
ret = ioctl(fd, MEMGETBADBLOCK, &offs);
if (ret == -1) {
if (errno != EOPNOTSUPP) {
sys_errmsg("MEMGETBADBLOCK ioctl failed");
goto out_close;
}
errno = 0;
mtd->bb_allowed = 0;
} else
mtd->bb_allowed = 1;
mtd->type = ui.type;
mtd->size = ui.size;
mtd->eb_size = ui.erasesize;
mtd->min_io_size = ui.writesize;
mtd->oob_size = ui.oobsize;
if (mtd->min_io_size <= 0) {
errmsg("mtd%d (%s) has insane min. I/O unit size %d",
mtd->mtd_num, node, mtd->min_io_size);
goto out_close;
}
if (mtd->eb_size <= 0 || mtd->eb_size < mtd->min_io_size) {
errmsg("mtd%d (%s) has insane eraseblock size %d",
mtd->mtd_num, node, mtd->eb_size);
goto out_close;
}
if (mtd->size <= 0 || mtd->size < mtd->eb_size) {
errmsg("mtd%d (%s) has insane size %lld",
mtd->mtd_num, node, mtd->size);
goto out_close;
}
mtd->eb_cnt = mtd->size / mtd->eb_size;
switch(mtd->type) {
case MTD_ABSENT:
errmsg("mtd%d (%s) is removable and is not present",
mtd->mtd_num, node);
goto out_close;
case MTD_RAM:
strcpy((char *)mtd->type_str, "ram");
break;
case MTD_ROM:
strcpy((char *)mtd->type_str, "rom");
break;
case MTD_NORFLASH:
strcpy((char *)mtd->type_str, "nor");
break;
case MTD_NANDFLASH:
strcpy((char *)mtd->type_str, "nand");
break;
case MTD_MLCNANDFLASH:
strcpy((char *)mtd->type_str, "mlc-nand");
break;
case MTD_DATAFLASH:
strcpy((char *)mtd->type_str, "dataflash");
break;
case MTD_UBIVOLUME:
strcpy((char *)mtd->type_str, "ubi");
break;
default:
goto out_close;
}
if (ui.flags & MTD_WRITEABLE)
mtd->writable = 1;
mtd->subpage_size = mtd->min_io_size;
close(fd);
/*
* Unfortunately, the device name is not available via ioctl, and
* we have to parse /proc/mtd to get it.
*/
ret = proc_parse_start(&pi);
if (ret)
return -1;
while (proc_parse_next(&pi)) {
if (pi.mtd_num == mtd->mtd_num) {
strcpy((char *)mtd->name, pi.name);
return 0;
}
}
errmsg("mtd%d not found in \"%s\"", mtd->mtd_num, MTD_PROC_FILE);
errno = ENOENT;
return -1;
out_close:
close(fd);
return -1;
}
/**
* legacy_get_dev_info1 - legacy version of 'mtd_get_dev_info1()'.
* @node: name of the MTD device node
* @mtd: the MTD device information is returned here
*
* This function is similar to 'mtd_get_dev_info1()' and has the same
* conventions.
*/
int legacy_get_dev_info1(int mtd_num, struct mtd_dev_info *mtd)
{
char node[sizeof(MTD_DEV_PATT) + 20];
sprintf(node, MTD_DEV_PATT, mtd_num);
return legacy_get_dev_info(node, mtd);
}

106
fpga/libmtd_xalloc.h Normal file
View File

@ -0,0 +1,106 @@
/*
* memory wrappers
*
* Copyright (c) Artem Bityutskiy, 2007, 2008
* Copyright 2001, 2002 Red Hat, Inc.
* 2001 David A. Schleef <ds@lineo.com>
* 2002 Axis Communications AB
* 2001, 2002 Erik Andersen <andersen@codepoet.org>
* 2004 University of Szeged, Hungary
* 2006 KaiGai Kohei <kaigai@ak.jp.nec.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __MTD_UTILS_XALLOC_H__
#define __MTD_UTILS_XALLOC_H__
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
/*
* Mark these functions as unused so that gcc does not emit warnings
* when people include this header but don't use every function.
*/
__attribute__((unused))
static void *xmalloc(size_t size)
{
void *ptr = malloc(size);
if (ptr == NULL && size != 0)
sys_errmsg_die("out of memory");
return ptr;
}
__attribute__((unused))
static void *xcalloc(size_t nmemb, size_t size)
{
void *ptr = calloc(nmemb, size);
if (ptr == NULL && nmemb != 0 && size != 0)
sys_errmsg_die("out of memory");
return ptr;
}
__attribute__((unused))
static void *xzalloc(size_t size)
{
return xcalloc(1, size);
}
__attribute__((unused))
static void *xrealloc(void *ptr, size_t size)
{
ptr = realloc(ptr, size);
if (ptr == NULL && size != 0)
sys_errmsg_die("out of memory");
return ptr;
}
__attribute__((unused))
static char *xstrdup(const char *s)
{
char *t;
if (s == NULL)
return NULL;
t = strdup(s);
if (t == NULL)
sys_errmsg_die("out of memory");
return t;
}
#ifdef _GNU_SOURCE
__attribute__((unused))
static int xasprintf(char **strp, const char *fmt, ...)
{
int cnt;
va_list ap;
va_start(ap, fmt);
cnt = vasprintf(strp, fmt, ap);
va_end(ap);
if (cnt == -1)
sys_errmsg_die("out of memory");
return cnt;
}
#endif
#endif /* !__MTD_UTILS_XALLOC_H__ */

Some files were not shown because too many files have changed in this diff Show More