From 2fe046b85771d53373a312e5e41bbd41053828ae Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Sun, 23 Apr 2023 11:50:17 +0800 Subject: [PATCH] from dunnan-400, complete base flow of scanning --- device/gxx-linux/capimage/CImageMerge.cpp | 75 ++ device/gxx-linux/capimage/CImageMerge.h | 14 + device/gxx-linux/capimage/CameraParam.h | 40 + device/gxx-linux/capimage/Capturer.cpp | 144 +-- device/gxx-linux/capimage/Capturer.h | 44 +- device/gxx-linux/capimage/CorrectParam.cpp | 279 ++++++ device/gxx-linux/capimage/CorrectParam.h | 21 + device/gxx-linux/capimage/FpgaComm.cpp | 67 +- device/gxx-linux/capimage/FpgaComm.h | 25 +- device/gxx-linux/capimage/ICapturer.h | 39 + device/gxx-linux/capimage/MonoCapturer.cpp | 924 ++++++++++++++++++ device/gxx-linux/capimage/MonoCapturer.h | 67 ++ device/gxx-linux/capimage/SysInforTool.cpp | 183 ++++ device/gxx-linux/capimage/SysInforTool.h | 26 + device/gxx-linux/capimage/correct_ultis.cpp | 427 ++++++++ device/gxx-linux/capimage/correct_ultis.h | 33 + device/gxx-linux/capimage/gvideo.h | 2 +- device/gxx-linux/capimage/gvideoisp1.cpp | 1 + device/gxx-linux/capimage/hgutils.cpp | 55 +- device/gxx-linux/capimage/hgutils.h | 11 +- device/gxx-linux/capimage/jsonconfig.cpp | 33 +- device/gxx-linux/capimage/jsonconfig.h | 2 + device/gxx-linux/capimage/scannersysinfo.h | 69 ++ device/gxx-linux/capimage/xmake.lua | 2 +- device/gxx-linux/deviceio/DevUtil.h | 1 - device/gxx-linux/deviceio/PinMonitor.cpp | 80 +- device/gxx-linux/imgproc/imageencode.cpp | 30 +- device/gxx-linux/imgproc/imageencode.h | 2 +- device/gxx-linux/motor_run/CuoZhiMotor.cpp | 64 ++ device/gxx-linux/motor_run/CuoZhiMotor.h | 92 ++ device/gxx-linux/motor_run/DevUtil.cpp | 30 + device/gxx-linux/motor_run/DevUtil.h | 57 ++ device/gxx-linux/motor_run/Gpio.cpp | 79 ++ device/gxx-linux/motor_run/Gpio.h | 53 + device/gxx-linux/motor_run/Motor.cpp | 69 ++ device/gxx-linux/motor_run/Motor.h | 72 ++ device/gxx-linux/motor_run/MotorConfig.cpp | 195 ++++ device/gxx-linux/motor_run/MotorConfig.h | 367 +++++++ device/gxx-linux/motor_run/MotorControl.cpp | 60 ++ device/gxx-linux/motor_run/MotorControl.h | 28 + device/gxx-linux/motor_run/Pwm.cpp | 40 + device/gxx-linux/motor_run/Pwm.h | 22 + device/gxx-linux/motor_run/ZouZhiMotor.cpp | 48 + device/gxx-linux/motor_run/ZouZhiMotor.h | 51 + device/gxx-linux/motor_run/main.cpp | 56 ++ device/gxx-linux/motor_run/xmake.lua | 89 ++ device/gxx-linux/motorboard/Imotorboard.cpp | 16 + device/gxx-linux/motorboard/Imotorboard.h | 98 ++ device/gxx-linux/motorboard/Led.cpp | 95 ++ device/gxx-linux/motorboard/Led.h | 50 + device/gxx-linux/motorboard/motorboard.cpp | 119 +-- device/gxx-linux/motorboard/motorboard.h | 144 +-- device/gxx-linux/motorboard/motormanager.cpp | 320 ++++++ device/gxx-linux/motorboard/motormanager.h | 72 ++ device/gxx-linux/motorboard/sensormonitor.cpp | 127 +++ device/gxx-linux/motorboard/sensormonitor.h | 29 + device/gxx-linux/motorboard/xmake.lua | 2 +- device/gxx-linux/scanner/deviceconfig.cpp | 4 - device/gxx-linux/scanner/fsmstate.cpp | 4 +- device/gxx-linux/scanner/fsmstate.h | 6 +- device/gxx-linux/scanner/iimagehandler.h | 169 ++-- device/gxx-linux/scanner/imagesavehandler.cpp | 2 +- device/gxx-linux/scanner/imagesavehandler.h | 2 +- device/gxx-linux/scanner/imageusbhandler.cpp | 389 +++++--- .../gxx-linux/scanner/imageusbtesthandler.cpp | 2 +- .../gxx-linux/scanner/imageusbtesthandler.h | 2 +- device/gxx-linux/scanner/iscanner.cpp | 344 +++++++ device/gxx-linux/scanner/iscanner.h | 71 ++ device/gxx-linux/scanner/scanner.cpp | 367 +------ device/gxx-linux/scanner/scanner.h | 79 +- device/gxx-linux/scanner/scannero300.cpp | 293 ++++++ device/gxx-linux/scanner/scannero300.h | 23 + device/gxx-linux/scanner/scannerregs.cpp | 3 +- device/gxx-linux/scanner/wakeup.hpp | 65 +- device/gxx-linux/scanner/xmake.lua | 2 +- device/gxx-linux/scanservice/main.cpp | 294 +++++- device/gxx-linux/testcapimage/main.cpp | 3 +- device/gxx-linux/testimgproc/main.cpp | 15 +- device/gxx-linux/testmotorboard/main.cpp | 2 +- .../testusb/usb-rk3399/usbimageprocqueue.h | 2 + device/gxx-linux/usb/src/common/packet.h | 22 +- device/gxx-linux/usb/src/common/sane_cfg.cpp | 37 + device/gxx-linux/usb/src/common/sane_cfg.h | 16 +- .../gxx-linux/usb/src/hardware/hardware.cpp | 432 ++++++++ device/gxx-linux/usb/src/hardware/hardware.h | 56 ++ device/gxx-linux/usb/src/usbdevice.cpp | 54 +- device/gxx-linux/usb/xmake.lua | 2 +- device/gxx-linux/xmake.lua | 2 +- pc/code_twain/device/scanner.vcxproj | 2 +- .../sln/usb_tools/Debug/usb_tools.exe | Bin 1746944 -> 1746944 bytes pc/code_twain/sln/usb_tools/DlgScanner.cpp | 55 +- pc/code_twain/sln/usb_tools/DlgScanner.h | 1 + .../sln/usb_tools/scanner/scanner_handler.cpp | 12 +- .../sln/usb_tools/scanner/scanner_handler.h | 3 + 94 files changed, 6910 insertions(+), 1167 deletions(-) create mode 100644 device/gxx-linux/capimage/CImageMerge.cpp create mode 100644 device/gxx-linux/capimage/CImageMerge.h create mode 100644 device/gxx-linux/capimage/CameraParam.h create mode 100644 device/gxx-linux/capimage/CorrectParam.cpp create mode 100644 device/gxx-linux/capimage/CorrectParam.h create mode 100644 device/gxx-linux/capimage/ICapturer.h create mode 100644 device/gxx-linux/capimage/MonoCapturer.cpp create mode 100644 device/gxx-linux/capimage/MonoCapturer.h create mode 100644 device/gxx-linux/capimage/SysInforTool.cpp create mode 100644 device/gxx-linux/capimage/SysInforTool.h create mode 100644 device/gxx-linux/capimage/correct_ultis.cpp create mode 100644 device/gxx-linux/capimage/correct_ultis.h create mode 100644 device/gxx-linux/capimage/scannersysinfo.h create mode 100644 device/gxx-linux/motor_run/CuoZhiMotor.cpp create mode 100644 device/gxx-linux/motor_run/CuoZhiMotor.h create mode 100644 device/gxx-linux/motor_run/DevUtil.cpp create mode 100644 device/gxx-linux/motor_run/DevUtil.h create mode 100644 device/gxx-linux/motor_run/Gpio.cpp create mode 100644 device/gxx-linux/motor_run/Gpio.h create mode 100644 device/gxx-linux/motor_run/Motor.cpp create mode 100644 device/gxx-linux/motor_run/Motor.h create mode 100644 device/gxx-linux/motor_run/MotorConfig.cpp create mode 100644 device/gxx-linux/motor_run/MotorConfig.h create mode 100644 device/gxx-linux/motor_run/MotorControl.cpp create mode 100644 device/gxx-linux/motor_run/MotorControl.h create mode 100644 device/gxx-linux/motor_run/Pwm.cpp create mode 100644 device/gxx-linux/motor_run/Pwm.h create mode 100644 device/gxx-linux/motor_run/ZouZhiMotor.cpp create mode 100644 device/gxx-linux/motor_run/ZouZhiMotor.h create mode 100644 device/gxx-linux/motor_run/main.cpp create mode 100644 device/gxx-linux/motor_run/xmake.lua create mode 100644 device/gxx-linux/motorboard/Imotorboard.cpp create mode 100644 device/gxx-linux/motorboard/Imotorboard.h create mode 100644 device/gxx-linux/motorboard/Led.cpp create mode 100644 device/gxx-linux/motorboard/Led.h create mode 100644 device/gxx-linux/motorboard/motormanager.cpp create mode 100644 device/gxx-linux/motorboard/motormanager.h create mode 100644 device/gxx-linux/motorboard/sensormonitor.cpp create mode 100644 device/gxx-linux/motorboard/sensormonitor.h create mode 100644 device/gxx-linux/scanner/iscanner.cpp create mode 100644 device/gxx-linux/scanner/iscanner.h create mode 100644 device/gxx-linux/scanner/scannero300.cpp create mode 100644 device/gxx-linux/scanner/scannero300.h create mode 100644 device/gxx-linux/usb/src/hardware/hardware.cpp create mode 100644 device/gxx-linux/usb/src/hardware/hardware.h diff --git a/device/gxx-linux/capimage/CImageMerge.cpp b/device/gxx-linux/capimage/CImageMerge.cpp new file mode 100644 index 0000000..a7d5f53 --- /dev/null +++ b/device/gxx-linux/capimage/CImageMerge.cpp @@ -0,0 +1,75 @@ +#include "CImageMerge.h" + +CImageMerge::CImageMerge() +{ +} +CImageMerge::~CImageMerge() +{ +} +cv::Mat CImageMerge::MergeImage(cv::Mat &srcMat, int dstwidth, int dstheight) +{ + cv::Mat retMat(dstheight, dstwidth, CV_8UC3); + + if (!srcMat.empty()) + { + std::vector ch_mats; + int blockcnt = 12; + int spitWidth = srcMat.cols / blockcnt; + + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 3; j++) + { + std::cout << " index " << (i * 3 + j) << " x " << spitWidth * (i * 3 + j) << " y " << 0 << " width " << spitWidth << " height " << dstheight << std::endl; + ch_mats.push_back(srcMat(cv::Rect(spitWidth * (i * 3 + j), 0, spitWidth, dstheight))); + } + cv::merge(ch_mats, retMat(cv::Rect(spitWidth * i, 0, spitWidth, dstheight))); + ch_mats.clear(); + } + return retMat; + } +} + +cv::Mat CImageMerge::MergeImage(bool iscolor, cv::Mat &srcMat, int dstwidth, int dstheight,std::uint32_t fpga_vs) +{ + 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(); + } + else + { + std::vector m_splits; + std::vector m_index = {0, 3, 8, 11, 2, 5, 6, 9, 1, 4, 7, 10}; + 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; +} \ No newline at end of file diff --git a/device/gxx-linux/capimage/CImageMerge.h b/device/gxx-linux/capimage/CImageMerge.h new file mode 100644 index 0000000..e93214e --- /dev/null +++ b/device/gxx-linux/capimage/CImageMerge.h @@ -0,0 +1,14 @@ +#pragma once +#include + +class CImageMerge +{ +private: + /* data */ +public: + CImageMerge(/* args */); + ~CImageMerge(); +public: + cv::Mat MergeImage(cv::Mat& srcMat,int dstwidth,int dstheight); + cv::Mat MergeImage(bool iscolor,cv::Mat& srcMat,int dstwidth,int dstheight,std::uint32_t fpga_vs); +}; diff --git a/device/gxx-linux/capimage/CameraParam.h b/device/gxx-linux/capimage/CameraParam.h new file mode 100644 index 0000000..789e6a3 --- /dev/null +++ b/device/gxx-linux/capimage/CameraParam.h @@ -0,0 +1,40 @@ +#pragma once +#include + + +#define LIGHT_DIFF(maxthre, x) ((maxthre)-x) +#define BLACK_DIFF(x) (8 - 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; +}; \ No newline at end of file diff --git a/device/gxx-linux/capimage/Capturer.cpp b/device/gxx-linux/capimage/Capturer.cpp index dc5cf06..0fa1f3a 100644 --- a/device/gxx-linux/capimage/Capturer.cpp +++ b/device/gxx-linux/capimage/Capturer.cpp @@ -14,6 +14,8 @@ #include #include #include "filetools.h" +#include "CameraParam.h" +#include "correct_ultis.h" using namespace std; #define LOG_PATH "/usr/local/correct.log" @@ -22,65 +24,14 @@ FileTools ft(LOG_PATH); static std::string loggername = "Capturer"; bool isAutoCorrect = true; -int offsetStep[12]; -int expStep[2][3]; -double radio = 1; +double Radio = 1; cv::Mat mBuffMat; cv::Mat out; -#define LIGHT_DIFF(maxthre, x) ((maxthre)-x) -#define BLACK_DIFF(x) (10 - x) -#define FMT_STEP(x) \ - do \ - { \ - if (x < 1 && x > 0) \ - { \ - x = 1; \ - } \ - if (step < 0 && step > -1) \ - { \ - x = -1; \ - } \ - } while (0) - -void initStep() -{ - for (int i = 0; i < 12; i++) - { - offsetStep[i] = 256; - } - for (int i = 0; i < 2; i++) - { - for (int j = 0; j < 3; j++) - { - expStep[i][j] = 1200; - } - } -} - -//设置一面的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; - } -} - Capturer::Capturer() - : vdd_cis_3voff_pin(new GpioOut(CIS_3v3_Off)), - vdd_vis_5ven_pin(new GpioOut(CIS_5v_En)), - reset_pin(new GpioOut(Fpga_Reset)), - image_in_transfer_pin(new Gpio(Image_In_Transfer)), - initDone_pin(new Gpio(Fpga_InitDone)), - fpgaLoad(new Gpio(70)), - fpga_conf_done(new Gpio(69)),//gpio init 导出 scanservice 仅操作IO - fpga_conf_initn(new Gpio(71)),//gpio init 导出 scanservice 仅操作IO + : reset_pin(new GpioOut(Fpga_Reset)), + initDone_pin(new Gpio(71)), + fpgaLoad(new GpioOut(70)), bcorrecting(false) { LOG_INIT(); @@ -94,12 +45,6 @@ Capturer::Capturer() Capturer::~Capturer() { - -} - -void Capturer::Fpga_regsAccess_reset(bool enable){ - if(fpgaComm.get()) - fpgaComm->regsAccess_reset(enable); } void Capturer::open() @@ -144,7 +89,7 @@ void Capturer::open() } static int val = 0; static double exp_ratio = 0.1; -void Capturer::open(HGScanConfig config) +void Capturer::open(HGScanConfig config,FPGAConfigParam fpgaparam) { if (val > 4000) val = 0; @@ -152,8 +97,7 @@ void Capturer::open(HGScanConfig config) if (exp_ratio > 2.0) exp_ratio = 0.1; cisconfigs = getcisparams(); - auto hgsize = papersMap[(PaperSize)config.g200params.paper]; - int height = hgsize.height; + int height = 1632; fpgaComm->setColorMode(config.g200params.color ? 1 : 0); auto info = jsonconfig().getscannerinfo(); //set_sp(config.g200params.color ? cisconfigs.color.sp : cisconfigs.gray.sp); //0x03fa : 0x0bf0 @@ -176,11 +120,10 @@ void Capturer::open(HGScanConfig config) clrsp=info.color_sp; graysp = info.gray_sp; set_sp(config.g200params.color ? clrsp : graysp); - HG_LOG("\n capture color sp =%d, gray sp =%d",clrsp,graysp); + printf("\n capture color sp =%d, gray sp =%d",clrsp,graysp); //set_sp(config.g200params.color ? 0x335 : 0x99f); //G100 0x438 0xca8 60 ppm 0x335 : 0x99f 100ppm //G200 SP极限值205 0x27c 0x775 140ppm - //fpgaComm->setDpi(config.g200params.dpi); //0 300dpi 1 200dpi - fpgaComm->setDpi(1); + fpgaComm->setDpi(config.g200params.dpi); //0 300dpi 1 200dpi fpgaComm->setSample(256); fpgaComm->enableLed(true); //设置曝光值等 @@ -209,7 +152,6 @@ void Capturer::close() { video->close(); } - fpga_reload(); } void Capturer::start() { @@ -256,15 +198,15 @@ void Capturer::fpga_reset() std::this_thread::sleep_for(std::chrono::milliseconds(50)); } -// void Capturer::fpga_reload() -// { -// //fpga 代码重载 -// fpgaLoad->setValue(Gpio::Low); -// std::this_thread::sleep_for(std::chrono::milliseconds(15)); -// fpgaLoad->setValue(Gpio::High); -// std::this_thread::sleep_for(std::chrono::milliseconds(15)); -// fpgaComm->resetADC(); -// } +void Capturer::fpga_reload() +{ + //fpga 代码重载 + fpgaLoad->setValue(Gpio::Low); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpgaLoad->setValue(Gpio::High); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpgaComm->resetADC(); +} void Capturer::set_expo(int ix, int val) { @@ -358,11 +300,12 @@ void Capturer::configFPGAParam(bool iscorrect, int mode) // val+=step; // exp_ratio += 0.1; + // printf("\n\n\n----------------\n"); // for (int i = 0; i < 2; i++) // { // for (int j = 0; j < 6; j++) // { - + // offsets[i][j]=j==4?200:0; // printf("gains[%d][%d] = %d \r\n", i, j, gains[i][j]); // printf("offsets[%d][%d] = %d \r\n", i, j, offsets[i][j]); // if (j < 3) @@ -472,7 +415,7 @@ void Capturer::autocorrect(int colormode) m_captureCallback(4, colormode ? "------彩色校正完成------\r\n" : "------灰度校正完成------\r\n"); reset(); bcorrecting = false; - HG_LOG("init_autocorrect exit \n"); + printf("init_autocorrect exit \n"); } void Capturer::creatcorrectconfig(int mode) @@ -515,7 +458,7 @@ void Capturer::creatcorrectconfig(int mode) ft.append_log(log); std::this_thread::sleep_for(std::chrono::milliseconds(100)); fpgaComm->enableLed(true); - fpgaComm->update(); + //fpgaComm->update(); std::this_thread::sleep_for(std::chrono::milliseconds(200)); fpgaComm->capture(); std::this_thread::sleep_for(std::chrono::milliseconds(500)); @@ -567,7 +510,7 @@ bool Capturer::saveLutImg(int mode, int index) void *data = video->read_frame(1500); if (data == NULL) { - log = "图像采集失败!\r\n"; + log = "图像采集失败!\r\n"; ft.append_log(log); isNeedSave = false; if (m_captureCallback) @@ -631,7 +574,7 @@ bool Capturer::saveLutImg(int mode, int index) int diff = LIGHT_DIFF(scannerinfo.clr_maxbright, *((double *)values + k)); log += " 明场:" + std::to_string(k) + ";diff:" + std::to_string(diff) + "\r\n"; - double step = diff * radio; + double step = diff * Radio; int preStep = *((int *)expStep + k); if (step * preStep < 0) { @@ -643,7 +586,7 @@ bool Capturer::saveLutImg(int mode, int index) isOutBounds |= exposures[x] <= 0 && step < 0; if (isOutBounds) log += " 第" + to_string(x) + "个明场校正异常 \r\n"; - else if (abs(diff) >= 2 || isMinStep) + else if (abs(diff) >= 1 || isMinStep) { *((int *)expStep + k) = (int)(step); exposures[x] += step; @@ -677,7 +620,7 @@ bool Capturer::saveLutImg(int mode, int index) { int k = s * 6 + j; double diff = BLACK_DIFF(offValues[k]); - double step = radio * diff; + double step = Radio * diff; int preStep = offsetStep[k]; if (step * preStep < 0) { @@ -685,7 +628,7 @@ bool Capturer::saveLutImg(int mode, int index) } else { - radio = 1; + Radio = 1; } FMT_STEP(step); bool isMinStep = abs(step) == 1 && step == offsetStep[k]; @@ -787,7 +730,7 @@ bool Capturer::saveLutImg(int mode, int index) { int *exposures = (int *)(s == 0 ? cisconfigs.grayCorrect.expF : cisconfigs.grayCorrect.expB); int diff = LIGHT_DIFF(scannerinfo.gray_maxbright, values[s]); - double step = diff * radio; + double step = diff * Radio; log += " 明场:" + to_string(s) + ";diff:" + to_string(diff) + "\r\n"; int preStep = expStep[s][0]; if (step * preStep < 0) @@ -796,7 +739,7 @@ bool Capturer::saveLutImg(int mode, int index) } else { - radio = 1; + Radio = 1; } FMT_STEP(step); @@ -808,7 +751,7 @@ bool Capturer::saveLutImg(int mode, int index) isOutBounds |= exp <= 0 && step < 0; if (isOutBounds) log += " 第" + to_string(s) + "个明场校正异常 \r\n"; - else if (abs(diff) > 2 || isMinStep) + else if (abs(diff) > 1 || isMinStep) { exp += step; if (exp < 0) @@ -843,7 +786,7 @@ bool Capturer::saveLutImg(int mode, int index) { int k = s * 6 + j; double diff = BLACK_DIFF(offValues[k]); - double step = radio * diff; + double step = Radio * diff; int preStep = offsetStep[k]; if (step * preStep < 0) { @@ -851,7 +794,7 @@ bool Capturer::saveLutImg(int mode, int index) } else { - radio = 1; + Radio = 1; } FMT_STEP(step); bool isMinStep = abs(step) == 1 && step == offsetStep[k]; @@ -892,25 +835,4 @@ bool Capturer::saveLutImg(int mode, int index) } } return isNeedSave; -} - -void Capturer::fpga_reload() -{ - // fpga 代码重载 - fpgaLoad->setValue(Gpio::Low); - std::this_thread::sleep_for(std::chrono::milliseconds(15)); - fpga_conf_initn->setValue(Gpio::Low); - std::this_thread::sleep_for(std::chrono::milliseconds(15)); - printf("\n fpga_conf_done value %d",fpga_conf_done->getValue()); - fpgaLoad->setValue(Gpio::High); - std::this_thread::sleep_for(std::chrono::milliseconds(15)); - fpga_conf_initn->setValue(Gpio::High); - //std::this_thread::sleep_for(std::chrono::milliseconds(5)); - printf("\n fpga_conf_done value %d",fpga_conf_done->getValue()); - // while(fpga_conf_done->getValue() == Gpio::GpioLevel::Low) - // std::this_thread::sleep_for(std::chrono::milliseconds(5)); - std::this_thread::sleep_for(std::chrono::seconds(3)); - printf("\n fpga_conf_done value %d",fpga_conf_done->getValue()); - fpgaComm->resetADC(); - fpgaComm->update(); } \ No newline at end of file diff --git a/device/gxx-linux/capimage/Capturer.h b/device/gxx-linux/capimage/Capturer.h index 9f760ec..3df8c93 100644 --- a/device/gxx-linux/capimage/Capturer.h +++ b/device/gxx-linux/capimage/Capturer.h @@ -1,58 +1,26 @@ #pragma once -#include -#include -#include -#include "regsaccess.h" -#include "commondef.h" +#include #include "hgutils.h" class FpgaComm; class gVideo; class Gpio; -class ICapturer -{ -public: - virtual ~ICapturer() {} - virtual void open() = 0; - virtual void Fpga_regsAccess_reset(bool enable) = 0 ; - virtual void open(HGScanConfig config) = 0; - virtual void close() = 0; - virtual void start() = 0; - virtual void stop() = 0; - virtual bool is_runing() = 0; - virtual void snap() = 0; - - virtual void set_size(int width, int height) = 0; - virtual void* readFrame(int timeout) = 0; - - virtual void set_gain(int ix, int val) = 0; - virtual void set_offset(int ix, int val) = 0; - virtual void set_expo(int ix, int val) = 0; - - virtual std::shared_ptr regs() = 0; - virtual void reset() = 0; - virtual int width() = 0; - virtual int height() = 0; - virtual int color() = 0; - virtual void init_autocorrect(int colormode) = 0; - virtual void setcapturecall(std::function callback) = 0; -}; - class Capturer : public ICapturer { public: Capturer(); virtual ~Capturer(); - virtual void Fpga_regsAccess_reset(bool enable); + virtual void open(); - virtual void open(HGScanConfig config); + virtual void open(HGScanConfig config,FPGAConfigParam fpgaparam); virtual void close(); virtual void start(); virtual void stop(); virtual bool is_runing(); virtual void snap(); - + virtual void stopsnap(){} + virtual int getautosizeheight(){return 0;} virtual void set_size(int width, int height); virtual void set_sp(int sp); @@ -89,8 +57,6 @@ private: std::shared_ptr image_in_transfer_pin; std::shared_ptr initDone_pin; std::shared_ptr fpgaLoad; - std::shared_ptr fpga_conf_initn; - std::shared_ptr fpga_conf_done; std::shared_ptr fpgaComm; std::shared_ptr video; diff --git a/device/gxx-linux/capimage/CorrectParam.cpp b/device/gxx-linux/capimage/CorrectParam.cpp new file mode 100644 index 0000000..bc51dc6 --- /dev/null +++ b/device/gxx-linux/capimage/CorrectParam.cpp @@ -0,0 +1,279 @@ +#include "CorrectParam.h" +#include +#include +#include +#include +#include +#include "commondef.h" + +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 CorrectParam::GetCorrectParams() +{ + std::ifstream i(JSONPATH); + json j; + i >> j; + std::vector 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); + } + 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 +#ifdef G200 + param.MaxBright = 190; +#else + param.MaxBright = 200; +#endif + param.MaxExp = 1100; + param.HRatio = 1065353216; + param.VRatio = 1065353216; + param.LutPath = LUT300COLORPATH; + param.TextLutPath = TEXTLUT300COLORPATH; + param.Flat_BwPath = LUT300_COLOR_BLACKPATH; + param.Flat_WhitePath = LUT300_COLOR_WHITEPATH; + param.Sp = 1200; + for (size_t i = 0; i < 6; i++) + { + if(i<3) + param.ExposureB[i] = param.ExposureF[i] = 700;//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.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 +#ifdef G200 + param.MaxBright = 190; +#else + param.MaxBright = 200; +#endif + 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] = 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); + + //灰度 200dpi + param.MaxBright = 200; + 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 +#ifdef G200 + param.MaxBright = 190; +#else + param.MaxBright = 200; +#endif + param.ColorMode = 1;//彩色 + param.DpiMode = 0x03;//200 dpi + 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] = 1350;//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.MaxBright = 200; + param.ColorMode = 0;//灰度 + 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) +{ + j.at("ExposureF").get_to(param.ExposureF); + j.at("GainF").get_to(param.GainF); + j.at("OffsetF").get_to(param.OffsetF); + j.at("ExposureB").get_to(param.ExposureB); + j.at("GainB").get_to(param.GainB); + j.at("OffsetB").get_to(param.OffsetB); + j.at("DpiMode").get_to(param.DpiMode); + j.at("ColorMode").get_to(param.ColorMode); + j.at("MaxBright").get_to(param.MaxBright); + j.at("MaxExp").get_to(param.MaxExp); + j.at("Sp").get_to(param.Sp); + j.at("HRatio").get_to(param.HRatio); + j.at("VRatio").get_to(param.VRatio); + j.at("LutPath").get_to(param.LutPath); + j.at("TextLutPath").get_to(param.TextLutPath); + j.at("FlatBlackPath").get_to(param.Flat_BwPath); + j.at("FlatWhitePath").get_to(param.Flat_WhitePath); +} \ No newline at end of file diff --git a/device/gxx-linux/capimage/CorrectParam.h b/device/gxx-linux/capimage/CorrectParam.h new file mode 100644 index 0000000..185b2aa --- /dev/null +++ b/device/gxx-linux/capimage/CorrectParam.h @@ -0,0 +1,21 @@ +#pragma once +#include "json.hpp" +#include +#include +#include "CameraParam.h" + +using json = nlohmann::json; + +class CorrectParam +{ +public: + CorrectParam(/* args */); + ~CorrectParam(); + FPGAConfigParam GetFpgaparam(int dpi,int mode); + void SaveCorrectParam(FPGAConfigParam& parms); +private: + void initdefaultpapram(); + std::vector GetCorrectParams(); + void to_json(json& j, FPGAConfigParam& param); + void from_json(json& j, FPGAConfigParam& param); +}; diff --git a/device/gxx-linux/capimage/FpgaComm.cpp b/device/gxx-linux/capimage/FpgaComm.cpp index 8f1ac70..0c88f22 100644 --- a/device/gxx-linux/capimage/FpgaComm.cpp +++ b/device/gxx-linux/capimage/FpgaComm.cpp @@ -17,13 +17,26 @@ FpgaComm::FpgaComm() { - m_regsAccess.reset(new UartRegsAccess(FPGA_UART, 921600, 0x03, 0x83)); - update(); + m_regsAccess.reset(new UartRegsAccess(MOTOR_UART, 921600, 0x03, 0x83)); + update(0); Reg(AledR).sample = 256; WR_Reg(AledR); + } +void FpgaComm::regsAccess_reset(bool enable){ + if(enable) + { + if(!m_regsAccess.get()) + m_regsAccess.reset(new UartRegsAccess(MOTOR_UART, 921600, 0x03, 0x83)); + update(0); + return; + } + if(m_regsAccess.get()) + m_regsAccess.reset(); +} + bool FpgaComm::read(unsigned int addr, unsigned int& val) { return m_regsAccess->read(addr, val); } @@ -32,18 +45,6 @@ bool FpgaComm::write(unsigned int addr, unsigned int val) { return m_regsAccess->write(addr, val); } -void FpgaComm::regsAccess_reset(bool enable){ - if(enable) - { - if(!m_regsAccess.get()) - m_regsAccess.reset(new UartRegsAccess(FPGA_UART, 921600, 0x03, 0x83)); - update(); - return; - } - if(m_regsAccess.get()) - m_regsAccess.reset(); -} - void FpgaComm::setFrameHeight(int height){ Reg(frame).height = height; WR_Reg(frame); @@ -66,7 +67,7 @@ void FpgaComm::enableLed(bool bEnable) { Reg(BledR).ledEnable = bEnable; WR_Reg(BledR); #else - Reg(BledR).ledEnable = bEnable; + Reg(BledR).ledEnable = !bEnable; WR_Reg(BledR); #endif } @@ -275,12 +276,13 @@ void FpgaComm::setDelayTime(int value) { WR_Reg(DelayTime); } -void FpgaComm::update() +void FpgaComm::update(int times) { - for(int i = 0; i < MAX_REGS; i++) + std::uint32_t tmp_reg = 0; + for(int i = 0; i < 16; i++) { - read(i, fpgaParams.regs[i]); - printf("reg[%d] = 0x%08x \n",i,fpgaParams.regs[i]); + read(i, tmp_reg); + printf("times[%d] reg[%d] = 0x%08x \n",times,i,tmp_reg); } } @@ -358,4 +360,31 @@ void FpgaComm::resetADC() { WR_Reg(mode); fpgaParams.mode.adcB = 0; WR_Reg(mode); +} + + +void FpgaComm::setEnTestCol(bool en) +{ + Reg(AledR).en_test_color = en?1:0; + WR_Reg(AledR); +} + +void FpgaComm::setEnTestBit(bool en) +{ + Reg(AledR).en_test = en?1:0; + WR_Reg(AledR); +} + +void FpgaComm::setVsp(unsigned int Aside,unsigned int BSide) +{ + unsigned int regv; + CISVSP vsp; + read(13,regv); + vsp.value = regv; + 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); + WR_Reg(AledR); } \ No newline at end of file diff --git a/device/gxx-linux/capimage/FpgaComm.h b/device/gxx-linux/capimage/FpgaComm.h index 4b2a0c7..9e5df19 100644 --- a/device/gxx-linux/capimage/FpgaComm.h +++ b/device/gxx-linux/capimage/FpgaComm.h @@ -6,7 +6,7 @@ #ifdef HAS_UV #define MAX_REGS 0x0e #else -#define MAX_REGS 0x0d +#define MAX_REGS 0x0e #endif typedef struct Frame_FPGA @@ -75,7 +75,9 @@ typedef struct CIS_LED_R { unsigned short int ledEnable : 1; unsigned short int sample : 9; - unsigned short int reserved : 6; + unsigned short int en_test_color :1; + unsigned short int en_test : 1; + unsigned short int reserved : 4; unsigned short int ledR; } CisLedR; @@ -91,6 +93,8 @@ typedef struct CIS_LED_UV unsigned short int ledBSide; } CisLedUv; + + typedef union Fpga_Params { struct @@ -118,6 +122,17 @@ typedef union Fpga_Params } FpgaParams; +typedef union CIS_VSP +{ + struct + { + unsigned int ASide_VSP:8; + unsigned int BSide_VSP:8; + unsigned int reserved : 16; + } bits; + int value; +} CISVSP; + class FpgaComm : public IRegsAccess { public: @@ -149,6 +164,9 @@ public: void setBExposureB(int value); void setBExpousreUV(int value); + void setEnTestCol(bool en); + void setEnTestBit(bool en); + void setSp(int value); int getSp(); @@ -168,9 +186,10 @@ public: void setDelayTime(int value); void setTrigMode(bool isArmMode); - void update(); + void update(int times); void enableJamCheck(bool b); void resetADC(); + void setVsp(unsigned int Aside,unsigned int BSide); virtual bool write(unsigned int addr, unsigned int val); virtual bool read(unsigned int addr, unsigned int& val); diff --git a/device/gxx-linux/capimage/ICapturer.h b/device/gxx-linux/capimage/ICapturer.h new file mode 100644 index 0000000..dbb3c5e --- /dev/null +++ b/device/gxx-linux/capimage/ICapturer.h @@ -0,0 +1,39 @@ +#pragma once +#include +#include +#include +#include +#include "regsaccess.h" +#include "commondef.h" +#include "CorrectParam.h" + +class ICapturer +{ +public: + virtual ~ICapturer() {} + virtual void open() = 0; + virtual void open(HGScanConfig config,FPGAConfigParam fpgaparam) = 0; + virtual void close() = 0; + virtual void start() = 0; + virtual void stop() = 0; + virtual bool is_runing() = 0; + virtual void snap() = 0; + virtual void stopsnap() = 0; + virtual int getautosizeheight() = 0; + virtual void set_size(int width, int height) = 0; + virtual void* readFrame(int timeout) = 0; + + virtual void set_gain(int ix, int val) = 0; + virtual void set_offset(int ix, int val) = 0; + virtual void set_expo(int ix, int val) = 0; + + virtual std::shared_ptr regs() = 0; + virtual void reset() = 0; + virtual int width() = 0; + virtual int height() = 0; + virtual int color() = 0; + virtual void init_autocorrect(int colormode=0) = 0; + virtual void setcapturecall(std::function callback) = 0; + + +}; \ No newline at end of file diff --git a/device/gxx-linux/capimage/MonoCapturer.cpp b/device/gxx-linux/capimage/MonoCapturer.cpp new file mode 100644 index 0000000..d1bd23d --- /dev/null +++ b/device/gxx-linux/capimage/MonoCapturer.cpp @@ -0,0 +1,924 @@ +#include "MonoCapturer.h" +#include "config.h" +#include "applog.h" +#include "gvideoisp1.h" +#include "Gpio.h" +#include "DevUtil.h" +#include "FpgaComm.h" +#include "CorrectParam.h" +#include "correct_ultis.h" +#include "stringex.hpp" +#include "filetools.h" +#include "CImageMerge.h" +#include "commondef.h" +#include "hgutils.h" +#include "dailex.hpp" +#include "jsonconfig.h" +#include "ThreadPool.h" + +using namespace std; +using namespace cv; + +#define LOG_PATH "/usr/local/correct.log" +FileTools ft_log(LOG_PATH); + +static std::string loggername = "MonoCapturer"; +static double radio = 1.0; +static int offsetStep1[12]; +static int expStep1[2][3]; + +void initStep1() +{ + printf("initStep aaaaaaaaaaa \n"); + for (int i = 0; i < 2; i++) + { + for (int j = 0; j < 3; j++) + { + expStep1[i][j] = 600; + } + } + for (int i = 0; i < 12; i++) + { + offsetStep1[i] = 256; + printf("offsetStep[%d]=%d \n",i,offsetStep1[i]); + } +} + +MonoCapturer::MonoCapturer() : vdd_cis_3voff_pin(new GpioOut(CIS_3v3_Off)), + vdd_vis_5ven_pin(new GpioOut(CIS_5v_En)), + reset_pin(new GpioOut(50)), + image_in_transfer_pin(new Gpio(Image_In_Transfer)), + initDone_pin(new Gpio(Fpga_InitDone)), + fpgaLoad(new Gpio(70)), + fpga_conf_done(new Gpio(69)),//gpio init 导出 scanservice 仅操作IO + fpga_conf_initn(new Gpio(71)),//gpio init 导出 scanservice 仅操作IO + bcorrecting(false) +{ + LOG_INIT(); + fpga_conf_done->setDirection(Gpio::in); + fpgaComm.reset(new FpgaComm()); + fpga_reset(); + fpgaComm->resetADC(); + fpgaComm->setDelayTime(0X3e8); + // fpgaComm->update(); + video.reset(new VIDEO_CLASS()); + // GetFpgaparam(0x01,0); +} + +MonoCapturer::~MonoCapturer() +{ + if (video.get()) + video.reset(); + + printf("Exit ~MonoCapturer() \n"); +} + +void MonoCapturer::open() +{ +} + +void MonoCapturer::open(HGScanConfig config,FPGAConfigParam fpgaparam) +{ + fpgaComm->update(1); + // reset_pin->setValue(Gpio::Low); + // std::this_thread::sleep_for(std::chrono::milliseconds(50)); + // reset_pin->setValue(Gpio::High); + bool dunnancis = true; + int dpi; + if (dunnancis) + dpi = config.g200params.dpi == 0x02 ? 2 : (config.g200params.dpi == 0x03 ? 3 : 2); + else + dpi = config.g200params.dpi; + + int mode = config.g200params.color; + int channelwidth = dpi == 0x02 ? 1296 : (dpi == 0x03 ? 2592 : 864); + int channels = mode == 0x01 ? 3 : 1; + int width = channelwidth * channels; + auto phyHeight = paperHeight[(PaperSize)config.g200params.paper]; + int pixheight; // = ((int)((phyHeight / 25.4 * (dpi == 0x02 ? 300 : (dpi == 0x03 ? 600 : 200)) + 2) / 3)) * 3 * 2; + if (dunnancis) + { + int tdpi = config.g200params.dpi == 0x02 ? 300 : (config.g200params.dpi == 0x03 ? 600 : 200); + //int tdpi = config.g200params.dpi == 0x02 ? 285 : (config.g200params.dpi == 0x03 ? 570 : 190); + pixheight = ((int)((phyHeight / 25.4 * tdpi + 2) / 3)) * 3 * 2; + } + else + pixheight = ((int)((phyHeight / 25.4 * (config.g200params.dpi == 0x02 ? 300 : (config.g200params.dpi == 0x03 ? 600 : 200)) + 2) / 3) * 3) * 2; + + if (config.g200params.paper == (unsigned int)(PaperSize::G400_AUTO)||pixheight > 16380) // isp sup max height config 16383 + pixheight = 16380; + + int dstheight = pixheight; + + int fpgaheight = mode == 0x1 ? dstheight / 2 * 3 : dstheight / 2; //彩色配置fpga 高度要为目标图像高度的3倍 + //FPGAConfigParam fpgaparam = GetFpgaparam(config.g200params.dpi, mode);// == 0x02 ? 2 : (config.g200params.dpi == 0x03 ? 3 : 2) + // FPGAConfigParam fpgaparam = GetFpgaparam(dpi, mode); + printf("dpi = %d fpgaparam.sp=%d exp=%d gain=%d offset=%d LUT=%s \n", dpi, fpgaparam.Sp, fpgaparam.ExposureB[0], fpgaparam.GainB[0], fpgaparam.OffsetB[0], fpgaparam.LutPath.c_str()); + // int startsample= cistype.GetCisType()==CISVendor::DUNNAN_CIS_V0?205:262; +#ifdef G300 + int startsample = 202; + dpi = 0; + width = 1728; + if (papersMap.count((PaperSize)config.g200params.paper) > 0) + { + dstheight = papersMap[(PaperSize)config.g200params.paper].height; + } + else + { + dstheight = papersMap[PaperSize::G400_A4].height; //不区分G300 G400 + } + dstheight = config.g200params.color ? dstheight : dstheight /3; + if(config.g200params.dpi != 1) + dstheight = std::min(16002,dstheight*3/2); + fpgaheight = dstheight; +#else + int startsample = 208; + std::uint32_t m_fpgaversion = 0; + fpgaComm->read(15,m_fpgaversion); + if(Dail().GetValue().dails.in_voltage3 == 0) + startsample = 262; + else + startsample = m_fpgaversion == 0x90002? 205 : 208; +#endif + + float v_ratio = *((float*)(&fpgaparam.VRatio)); + fpgaparam.Sp /= v_ratio; + printf("\n apply sp = %d, v_ratio =%f",fpgaparam.Sp,v_ratio); + ModeFpga fpgamod = { + .colorMode = mode, + .dpi = dpi, + .led = 1, + .sample = startsample, // 256+39 + .adcA = 0, + .adcB = 0, + .selftest = 0, + .sp = fpgaparam.Sp}; // 600DPI 0x1450 300DPI 0xe10 + fpgaComm->setRegs(0x01, *((int *)(&fpgamod))); + fpgaComm->setSample(startsample); + fpgaComm->enableLed(true); + fpgaComm->setEnTestCol(false); + fpgaComm->setEnTestBit(false); + auto vsp_value = jsonconfig().getscannerinfo(); + if(vsp_value.clr_maxbright > 20 || vsp_value.clr_maxbright < 1) + vsp_value.clr_maxbright = 2; + if(vsp_value.gray_maxbright > 20 || vsp_value.gray_maxbright < 1) + vsp_value.gray_maxbright = 2; + fpgaComm->setVsp(vsp_value.clr_maxbright,vsp_value.gray_maxbright); + // fpgaComm->update(2); + configFPGAParam(mode, config.g200params.dpi); + // fpgaComm->update(3); + // fpgaComm->setFrameHeight(12); + // fpgaComm->capture(); + // auto data = video->read_frame(100); + // fpgaComm->enableLed(false); + video->open(width, dstheight); // 300dpi 7344/2 600dpi 7344 + printf("opened video with width = %d height = %d \n", width, dstheight); + fpgaComm->setFrameHeight(12); + for (int i = 0; i < 1; i++) + { + fpgaComm->capture(); // abort first frame + video->read_frame(100); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + printf("abort first frame \n"); + } + fpgaComm->setFrameHeight(fpgaheight); + printf("fpgaComm set height = %d \n", fpgaheight); + fpgaComm->update(3); + //initLut(fpgaparam.LutPath, config.g200params.color); + initLut(config.g200params.is_textcorrect?fpgaparam.LutPath:fpgaparam.TextLutPath,config.g200params.color); +} + +void MonoCapturer::close() +{ + if (video.get()) + video->close(); + //fpga_reload(); +} + +void MonoCapturer::Fpga_regsAccess_reset(bool enable){ + if(fpgaComm.get()) + fpgaComm->regsAccess_reset(enable); +} + +void MonoCapturer::start() +{ + if (video.get()) + video->start(); +} + +void MonoCapturer::MonoCapturer::stop() +{ + if (video.get()) + video->stop(); +} + +bool MonoCapturer::is_runing() +{ + return false; +} + +void MonoCapturer::snap() +{ + fpgaComm->capture(); +} + +void MonoCapturer::stopsnap() +{ +} + +int MonoCapturer::getautosizeheight() +{ + unsigned int val; + unsigned int reg8 = 0; + + fpgaComm->read(8, reg8); + // std::cout << "1 reg[8]:" << string_format("0x%08x", reg8) << std::endl; + // fpgaComm->update(4); + fpgaComm->read(14, val); + int regv = val; + val &= 0x0000ffff; + // std::cout << string_format("ONE height = %d reg[14] = %d \n", val, regv); + // fpgaComm->update(5); + fpgaComm->write(8, reg8 & 0xfffffff7); + // std::cout << string_format("ONE reg[8] = %d \n", reg8 & 0xfffffff7); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + // fpgaComm->update(6); + fpgaComm->read(14, val); + regv = val; + val &= 0x0000ffff; + fpgaComm->read(8, reg8); + // std::cout << "2 reg[8]:" << string_format("0x%08x", reg8) << std::endl; + std::cout << string_format("TWO height = %d reg[14] = %d \n", val, regv); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + fpgaComm->write(8, reg8 | 0x8); + // fpgaComm->write(8,0x02260008); + // fpgaComm->update(7); + // fpgaComm->read(8, reg8); + // std::cout << "2 reg[8]:" << string_format("0x%08x", reg8) << std::endl; + return val; + + // return fpgaComm->getFrameHeight(); +} +void MonoCapturer::set_size(int width, int height) +{ + if (video.get()) + video->set_size(width, height); +} + +void MonoCapturer::set_sp(int sp) +{ + fpgaComm->setSp(sp); +} + +void *MonoCapturer::readFrame(int timeout) +{ + return video->read_frame(timeout); +} + +void MonoCapturer::set_gain(int ix, int val) +{ + for (int i = 0; i < 6; i++) + { + if (ix) + fpgaComm->setAGain(i, val); + else + fpgaComm->setBGain(i, val); + } +} + +void MonoCapturer::set_offset(int ix, int val) +{ + for (int i = 0; i < 6; i++) + { + if (ix) + fpgaComm->setAOffset(i, val); + else + fpgaComm->setBOffset(i, val); + + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } +} + +void MonoCapturer::set_expo(int ix, int val) +{ + switch (ix) + { + case 0: + fpgaComm->setAExposureR(val); + break; + case 1: + fpgaComm->setAExposureG(val); + break; + case 2: + fpgaComm->setAExposureB(val); + break; + case 3: + fpgaComm->setBExposureR(val); + break; + case 4: + fpgaComm->setBExposureG(val); + break; + case 5: + fpgaComm->setBExposureB(val); + break; + default: + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(1)); +} + +std::shared_ptr MonoCapturer::regs() +{ + return fpgaComm; +} + +void MonoCapturer::reset() +{ + fpga_reset(); + // fpgaComm->resetADC(); + // fpgaComm->setDelayTime(0X3e8); + // fpgaComm->setRegs(0x00, fpgaComm->getRegs(0x00)); + // fpgaComm->setRegs(0x01, fpgaComm->getRegs(0x01)); +} + +int MonoCapturer::width() +{ +#ifdef G300 + return 1728; +#else + int dpi = fpgaComm->getDpi(); + int channel = 1; + int width = dpi == 0x02 ? 1296 * channel : (dpi == 0x03 ? (2592 * channel) : (864 * channel)); + // printf("get width = %d \n", width); + return width; +#endif +} + +int MonoCapturer::height() +{ + return fpgaComm->getFrameHeight(); +} + +int MonoCapturer::color() +{ + return fpgaComm->getColorMode() ? 16 : 0; +} + +void MonoCapturer::init_autocorrect(int colormode) +{ + std::thread t_correctthread = std::thread(&MonoCapturer::correctcolor, this); + t_correctthread.detach(); +} + +void MonoCapturer::configFPGAParam(int mode, int dpi) +{ + printf("dpi = %d mode = %d \n", dpi, mode); + //fpgaComm->resetADC(); + FPGAConfigParam fpgaparam = GetFpgaparam(dpi, mode); + // int offF[6]={0,0,0,0,0,200}; + // int offB[6]={0,0,0,0,0,0}; + for (int i = 0; i < 6; i++) + { + if (i < 3) + { + set_expo(i, fpgaparam.ExposureF[i]); + printf("fpgaparam.ExposureF[%d] = %d \n", i, fpgaparam.ExposureF[i]); + } + else + { + set_expo(i, fpgaparam.ExposureB[i % 3]); + printf("fpgaparam.ExposureB[%d] = %d \n", i, fpgaparam.ExposureB[i % 3]); + } + + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->setAOffset(i, fpgaparam.OffsetF[i]); + // fpgaComm->setAOffset(i,offF[i]); + printf("fpgaparam.setAOffset[%d] = %d \n", i, fpgaparam.OffsetF[i]); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->setBOffset(i, fpgaparam.OffsetB[i]); + // fpgaComm->setBOffset(i, offB[i]); + printf("fpgaparam.OffsetB[%d] = %d \n", i, fpgaparam.OffsetB[i]); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->setAGain(i, fpgaparam.GainF[i]); + printf("fpgaparam.GainF[%d] = %d \n", i, fpgaparam.GainF[i]); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->setBGain(i, fpgaparam.GainB[i]); + printf("fpgaparam.GainB[%d] = %d \n", i, fpgaparam.GainB[i]); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + } +} + +void MonoCapturer::openDevice(int dpi, int mode) +{ + // reset_pin->setValue(Gpio::Low); + // std::this_thread::sleep_for(std::chrono::milliseconds(50)); + // reset_pin->setValue(Gpio::High); + int config_dpi = dpi == 1 ? 2 : dpi; + int channelwidth = config_dpi == 0x02 ? 1296 : (config_dpi == 0x03 ? 2592 : 864); + int channels = mode == 0x01 ? 3 : 1; + int width = channelwidth * channels; + int dstheight = 200; + int fpgaheight = mode == 0x1 ? dstheight / 2 * 3 : dstheight; //彩色配置fpga 高度要为目标图像高度的3倍 + + FPGAConfigParam fpgaparam = GetFpgaparam(dpi, mode); +#ifdef G300 + int startsample = 202; + config_dpi = 0; + width = 1728; + dstheight = mode ? 6000 : 2000; + fpgaheight = dstheight; +#else + int startsample = 208; + std::uint32_t m_fpgaversion = 0; + fpgaComm->read(15,m_fpgaversion); + if(Dail().GetValue().dails.in_voltage3 == 0) + startsample = 262; + else + startsample = m_fpgaversion == 0x90002? 205 : 208; +#endif + printf("fpgaparam.sp=%d exp=%d gain=%d offset=%d LUT=%s", fpgaparam.Sp, fpgaparam.ExposureB[0], fpgaparam.GainB[0], fpgaparam.OffsetB[0], fpgaparam.LutPath.c_str()); + // int startsample= cistype.GetCisType()==CISVendor::DUNNAN_CIS_V0?205:262; + float v_ratio = *((float*)(&fpgaparam.VRatio)); + fpgaparam.Sp *= v_ratio; + printf("\n openDevice apply sp = %d, v_ratio =%f",fpgaparam.Sp,v_ratio); + ModeFpga fpgamod = { + .colorMode = mode, + .dpi = config_dpi, + .led = 1, + .sample = startsample, // 256+39 + .adcA = 0, + .adcB = 0, + .selftest = 0, + .sp = fpgaparam.Sp}; // 600DPI 0x1450 300DPI 0xe10 + fpgaComm->setRegs(0x01, *((int *)(&fpgamod))); + fpgaComm->setSample(startsample); + fpgaComm->enableLed(true); + fpgaComm->setEnTestCol(false); + fpgaComm->setEnTestBit(false); + auto vsp_value = jsonconfig().getscannerinfo(); + if(vsp_value.clr_maxbright > 20 || vsp_value.clr_maxbright < 1) + vsp_value.clr_maxbright = 2; + if(vsp_value.gray_maxbright > 20 || vsp_value.gray_maxbright < 1) + vsp_value.gray_maxbright = 2; + fpgaComm->setVsp(vsp_value.clr_maxbright,vsp_value.gray_maxbright); + configFPGAParam(mode, dpi); + + video->open(width, dstheight); // 300dpi 7344/2 600dpi 7344 + printf("opened video with width = %d height = %d \n", width, dstheight); + fpgaComm->setFrameHeight(12); + for (int i = 0; i < 1; i++) + { + fpgaComm->capture(); // abort first frame + video->read_frame(100); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + printf("abort first frame \n"); + } + fpgaComm->setFrameHeight(fpgaheight); +} + +void MonoCapturer::creatcorrectconfig(int dpi, int mode) +{ + printf(" opendevice"); + openDevice(dpi, mode); + printf(" opendevice end "); + bool isDone = false; + int i = 1; + initStep1(); + while (!isDone) //先暗场 + { + string log = "==============================第" + to_string(i) + "次==============================="; + ft_log.append_log(log); + configFPGAParam(mode, dpi); + ft_log.append_log(log); + fpgaComm->enableLed(false); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->capture(); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + isDone = saveLutImg(dpi, mode, true); // 0 color_black 1 color_white 2 gray_balck 3 gray_white + i++; + } + i = 1; + isDone = false; + initStep1(); + while (!isDone) //后明场 + { + configFPGAParam(mode, dpi); + string log = "==============================第" + to_string(i) + "次==============================="; + ft_log.append_log(log); + fpgaComm->enableLed(true); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->capture(); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + isDone = saveLutImg(dpi, mode, false); + i++; + } + printf("creatcorrectconfig %s \n", (mode == IMAGE_COLOR ? " Color" : " Gray")); + //creatLUTData(dpi, mode); + video->close(); +} + +static int savelutindex = 0; +bool MonoCapturer::saveLutImg(int dpi, int mode, bool black) +{ + int config_dpi = dpi == 1 ? 2 : dpi; +#ifdef G300 + int offset_indexs[] = {3, 4, 5, 2, 1, 0, 0, 1, 2, 5, 4, 3}; +#else + int offset_indexs[] = {0, 1, 2, 5, 4, 3, 3, 4, 5, 2, 1, 0}; +#endif + int channels = mode == IMAGE_COLOR ? 3 : 1; + int height = 100; + int width = config_dpi == 0x02 ? 1296 : (config_dpi == 0x03 ? 2592 : 864); + int orgimgwidth = width * 2 * 3 * channels; + int dstwidth = width * 2 * 3; +#ifdef G300 + orgimgwidth = 1728 * channels * 3; + height = 6000 / 9 *3 ; +#endif + bool isNeedSave = true; + string log; + void *data = video->read_frame(10000); + if (data == NULL) + { + isNeedSave = false; + log = "WARNNING WARNNING WARNNING FAILDED TO READ IMAGE DATA !!!!!!!!!!!!!!!!!!!\r\n"; + ft_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + return isNeedSave; + } + cv::Mat src(height, orgimgwidth, CV_8UC1, data); + //cv::imwrite(std::to_string(savelutindex++) + ".jpg", src); +#ifdef G300 + cv::Mat mrgmat = GetStitchMat(mode ==1?1:0,orgimgwidth,height,src); +#else + CImageMerge t_marge; + cv::Mat mrgmat = t_marge.MergeImage(mode == 0x01, src, dstwidth, height,0x90001); +#endif + mrgmat = mrgmat(cv::Rect(0,20,mrgmat.cols,mrgmat.rows-20)); + // return false; + FPGAConfigParam param = GetFpgaparam(dpi, mode); + + if (black) //暗场 + { + double offValues[12]; + std::vector bflags; + for (volatile int n = 0; n < 2; n++) + { + cv::Mat img = mrgmat(cv::Rect(mrgmat.cols * n / 2, 10, mrgmat.cols / 2, mrgmat.rows - 10)).clone(); + int offset_total = 0; + for (volatile int s = 0; s < 6; s++) // + { + int k = n * 6 + s; + int offset_wdth; + if ((k == 5) || (k == 6)) + { + offset_wdth = config_dpi == 0x03 ? 864 : (config_dpi == 0x02 ? 432 : 288); + } + else + { + offset_wdth = config_dpi == 0x03 ? 1296 : (config_dpi == 0x02 ? 648 : 432); + } +#ifdef G300 + offset_wdth =432; +#endif + double min,max; + //auto t_mat= img(cv::Rect(offset_total, 10, offset_wdth, img.rows - 10)); + //cv::minMaxLoc(t_mat,&min,&max); + cv::Scalar mean = cv::mean(img(cv::Rect(offset_total, 10, offset_wdth, img.rows - 10))); + //printf("AAAAAAAAAAAAAAAAAAAAAAAAAAA min = %.2f max= %.2f mean = %0.2f \n",min,max); + offset_total += offset_wdth; + offValues[k] = mean.val[0]; + printf("\noffValues[%d] = %f",k,mean.val[0]); + bflags.push_back(false); + //offValues[k] = min; + } + } + + // std::string clrmode = (mode == 0x01 ? "彩色" : " 灰度"); + // log = "开始" + clrmode + "暗场校正 \n"; + for (volatile int s = 0; s < 2; s++) + { + int offsets[6]; // = (int *)(s == 0 ? ¶m.OffsetF[0] : ¶m.OffsetB[0]); + memcpy(offsets, (s == 0 ? ¶m.OffsetF[0] : ¶m.OffsetB[0]), sizeof(param.OffsetF)); + for (volatile int j = 0; j < 6; j++) + { + int k = s * 6 + j; + double diff = BLACK_DIFF(offValues[k]); + //double diff = 3-offValues[k]; + double step = radio * diff; + int preStep = offsetStep1[k]; + printf("offsetStep1[%d]=%d \n",k,offsetStep1[k]); + if (step * preStep < 0) + { + step = 0 - preStep / 2; + } + else + { + radio = 1; + } + + if (step < 1 && step > 0) + step = 1; + if (step < 0 && step > -1) + step = -1; + + + // FMT_STEP(step); + bool isMinStep = abs(step) == 1 && step == offsetStep1[k]; + bool isOutBounds = offsets[j] >= 255 && step > 0; + isOutBounds |= offsets[j] <= 0 && step < 0; + log += " 暗场校正 :" + std::to_string(k) + ";diff:" + std::to_string(diff) + ";light:" + std::to_string(offValues[k]) + ";offset:" + std::to_string(offsets[j]) + ";step:" + std::to_string(step) + "\r\n"; + if (isOutBounds) + log += " 第" + std::to_string(k) + "条带暗场校正异常,暗场值无法降低 \r\n"; + else if (abs(step) > 1 || isMinStep) + { + offsetStep1[k] = (int)(step); + offsets[offset_indexs[k]] += step; + log += "offsetStep1" + std::to_string(k) + " = " + std::to_string(offsetStep1[k]) + ", offset_indexs" + std::to_string(k) + " =" + std::to_string(offset_indexs[k]) + "\r\n"; + + if (offsets[offset_indexs[k]] < 1) + offsets[offset_indexs[k]] = 1; + if (offsets[offset_indexs[k]] > 255) + offsets[offset_indexs[k]] = 255; + //isNeedSave = false; + bflags[k] = false; + } + else + { + bflags[k] = true; + printf("channel[%d] black correct done\n",k); + } + + + log += (s == 0 ? "彩色正面" : "彩色背面"); + log += "偏移值:" + std::to_string(offsets[0]) + "," + std::to_string(offsets[1]) + "," + std::to_string(offsets[2]) + "," + std::to_string(offsets[3]) + "," + std::to_string(offsets[4]) + "," + std::to_string(offsets[5]) + "\r\n"; + // log += (s == 0 ? "彩色正面暗场校正完成 \r\n" : "彩色背面暗场校正完成 \r\n"); + ft_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + log = ""; + } + auto siez = sizeof(param.OffsetF); + memcpy((s == 0 ? ¶m.OffsetF[0] : ¶m.OffsetB[0]), offsets, sizeof(param.OffsetF)); + } + + for(int i = 0;i 30) + radio = 2; + else + radio = 1; + double step = diff * radio; + int preStep = *((int *)expStep + k); + if (step * preStep < 0) + { + step = 0 - preStep / 2; + } + if (step < 1 && step > 0) + step = 1; + if (step < 0 && step > -1) + step = -1; + + bool isMinStep = abs(step) == 1 && step == *((int *)expStep + k); + bool isOutBounds = exposures[x] >= (param.Sp -5) && step > 0; + isOutBounds |= exposures[x] <= 0 && step < 0; + if (isOutBounds) + log += " 第" + to_string(x) + "个明场校正异常 \r\n"; + else if (abs(diff) >= 1 || isMinStep) + { + *((int *)expStep + k) = (int)(step); + exposures[x] += step; + if (exposures[x] > (param.Sp -5)) + { + exposures[x] = (param.Sp -5); + } + if (exposures[x] < 0) + exposures[x] = 0; + isNeedSave = false; + } + log += " 曝光值:" + to_string(exposures[x]) + "\r\n"; + log += " 调整步长:" + to_string(*((int *)expStep + k)) + "\r\n"; + } + memcpy((s == 0 ? ¶m.ExposureF[0] : ¶m.ExposureB[0]), exposures, sizeof(param.ExposureB)); + } + ft_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + + if (isNeedSave) + { + log = "彩色明场校正完成\r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + // log =""; + imwrite(param.Flat_WhitePath, mrgmat); + } + } + else + { + double values[2]; + values[0] = cv::mean(mrgmat(cv::Rect(0, 0, mrgmat.cols / 2, mrgmat.rows))).val[0]; + values[1] = cv::mean(mrgmat(cv::Rect(mrgmat.cols / 2, 0, mrgmat.cols / 2, mrgmat.rows))).val[0]; + log = "-----开始灰色明场校正-----\r\n"; + log += " 灰色扫描灰度明场均值:" + to_string(values[0]) + "," + to_string(values[1]) + "\r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + for (int s = 0; s < 2; s++) + { + int *exposures = (int *)(s == 0 ? param.ExposureF : param.ExposureB); + int diff = LIGHT_DIFF(param.MaxBright, values[s]); + if(abs(diff) > 30) + radio = 2; + else + radio = 1; + double step = diff * radio; + log += " 明场:" + to_string(s) + ";diff:" + to_string(diff) + "\r\n"; + int preStep = expStep[s][0]; + if (step * preStep < 0) + { + step = 0 - preStep / 2; + } + else + { + radio = 1; + } + if (step < 1 && step > 0) + step = 1; + if (step < 0 && step > -1) + step = -1; + + int exp = *(exposures + 1); + // std::string ss1(string_format("exp[%d] = %d step = %.3f \r\n", s, exp, step)); + // log += ss1; + bool isMinStep = abs(step) == 1 && step == expStep[s][0]; + bool isOutBounds = exp >= (param.Sp -5) && step > 0; + isOutBounds |= exp <= 0 && step < 0; + if (isOutBounds) + log += " 第" + to_string(s) + "个明场校正异常 \r\n"; + else if (abs(diff) > 1 || isMinStep) + { + exp += step; + if (exp < 0) + exp = 0; + if (exp >(param.Sp -5)) + exp = (param.Sp -5); + + float coffe[3] = {1, 1, 1}; // 0.2, 1,0.51 + for (int k = 0; k < 3; k++) + { + *(exposures + k) = (int)(exp * coffe[k]); + expStep[s][k] = (int)(step); + std::string exps(string_format("expStep[%d][%d] = %.3f\r\n", s, k, step)); + log += exps; + std::string ss(string_format("exposures[%d] = %0.3f \r\n", k, exposures[k])); + log += ss; + } + isNeedSave = false; + } + } + ft_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + if (isNeedSave) + { + printf("Save LUT image path :%s \n", param.Flat_WhitePath.c_str()); + log = "灰度明场校正完成\r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + log = ""; + imwrite(param.Flat_WhitePath, mrgmat); + } + } + } + SaveFpgaparam(param); + printf("exit Save_lut \n"); + return isNeedSave; +} + +void MonoCapturer::correctcolor() +{ + printf(" correctcolor start \n"); + auto _start = std::chrono::steady_clock::now(); + ThreadPool pool(2); + std::queue> fu_correct; + std::string loginfo = "Start Correctcolor 200DPI COLOR \r\n"; + // if (m_captureCallback) + // m_captureCallback(0x01, loginfo); + creatcorrectconfig(0x01, IMAGE_COLOR); + auto param = GetFpgaparam(0x01,IMAGE_COLOR); + fu_correct.emplace(pool.enqueue([param](){creatLUTData(0x01,IMAGE_COLOR,param);})); + loginfo = "-----------200DPI COLOR Correct Done----------- \r\n\r\n Start Correctcolor 200DPI GRAY \r\n"; + if (m_captureCallback) + m_captureCallback(0x01, loginfo); + creatcorrectconfig(0x01, IMAGE_GRAY); + param = GetFpgaparam(0x01,IMAGE_GRAY); + fu_correct.emplace(pool.enqueue([param](){creatLUTData(0x01,IMAGE_GRAY,param);})); + loginfo = "-----------200DPI Gray Correct Done----------- \r\n\r\n Start Correctcolor 200DPI COLOR \r\n"; + if (m_captureCallback) + m_captureCallback(0x02, loginfo); + + creatcorrectconfig(0x02, IMAGE_COLOR); + param = GetFpgaparam(0x02,IMAGE_COLOR); + fu_correct.emplace(pool.enqueue([param](){creatLUTData(0x02,IMAGE_COLOR,param);})); + loginfo = "-----------300DPI COLOR Correct Done----------- \r\n\r\n Start Correctcolor 300DPI GRAY \r\n"; + if (m_captureCallback) + m_captureCallback(0x02, loginfo); + creatcorrectconfig(0x02, IMAGE_GRAY); + param = GetFpgaparam(0x02,IMAGE_GRAY); + fu_correct.emplace(pool.enqueue([param](){creatLUTData(0x02,IMAGE_GRAY,param);})); + loginfo = "-----------300DPI Gray Correct Done----------- \r\n\r\n Start Correctcolor 600DPI COLOR \r\n"; +#ifndef G300 + if (m_captureCallback) + m_captureCallback(0x03, loginfo); + creatcorrectconfig(0x03, IMAGE_COLOR); + param = GetFpgaparam(0x03,IMAGE_COLOR); + fu_correct.emplace(pool.enqueue([param](){creatLUTData(0x03,IMAGE_COLOR,param);})); + loginfo = "-----------600DPI COLOR Correct Done----------- \r\n\r\n Start Correctcolor 600DPI GRAY \r\n"; + if (m_captureCallback) + m_captureCallback(0x03, loginfo); + creatcorrectconfig(0x03, IMAGE_GRAY); + param = GetFpgaparam(0x03,IMAGE_GRAY); + fu_correct.emplace(pool.enqueue([param](){creatLUTData(0x03,IMAGE_GRAY,param);})); + loginfo = "-----------600DPI Gray Correct Done----------- \r\n\r\n "; + if (m_captureCallback) + m_captureCallback(0x03, loginfo); +#endif + while(fu_correct.size()) + { + fu_correct.front().get(); + fu_correct.pop(); + } + loginfo = "******Correct Done****** time " + std::to_string(std::chrono::duration(std::chrono::steady_clock::now() - _start).count())+"s"; + if (m_captureCallback) + m_captureCallback(0x03, loginfo); +} + +void MonoCapturer::fpga_reset() +{ + reset_pin->setValue(Gpio::Low); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + reset_pin->setValue(Gpio::High); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); +} + +void MonoCapturer::fpga_reload() +{ + // fpga 代码重载 + fpgaLoad->setValue(Gpio::Low); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpga_conf_initn->setValue(Gpio::Low); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + printf("\n fpga_conf_done value %d",fpga_conf_done->getValue()); + fpgaLoad->setValue(Gpio::High); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpga_conf_initn->setValue(Gpio::High); + //std::this_thread::sleep_for(std::chrono::milliseconds(5)); + printf("\n fpga_conf_done value %d",fpga_conf_done->getValue()); + // while(fpga_conf_done->getValue() == Gpio::GpioLevel::Low) + // std::this_thread::sleep_for(std::chrono::milliseconds(5)); + std::this_thread::sleep_for(std::chrono::seconds(3)); + printf("\n fpga_conf_done value %d",fpga_conf_done->getValue()); + fpgaComm->resetADC(); + fpgaComm->update(0); +} \ No newline at end of file diff --git a/device/gxx-linux/capimage/MonoCapturer.h b/device/gxx-linux/capimage/MonoCapturer.h new file mode 100644 index 0000000..136c76d --- /dev/null +++ b/device/gxx-linux/capimage/MonoCapturer.h @@ -0,0 +1,67 @@ +#pragma once +#include "ICapturer.h" + +class FpgaComm; +class gVideo; +class Gpio; + +class MonoCapturer : public ICapturer +{ +private: + /* data */ +public: + MonoCapturer(/* args */); + virtual ~MonoCapturer(); + virtual void open(); + virtual void open(HGScanConfig config,FPGAConfigParam fpgaparam); + virtual void close(); + virtual void start(); + virtual void stop(); + virtual bool is_runing(); + virtual void snap(); + virtual void stopsnap(); + virtual int getautosizeheight(); + virtual void set_size(int width, int height); + virtual void set_sp(int sp); + + virtual void *readFrame(int timeout); + + virtual void set_gain(int ix, int val); + virtual void set_offset(int ix, int val); + virtual void set_expo(int ix, int val); + + virtual std::shared_ptr regs(); + virtual void reset(); + virtual int width(); + virtual int height(); + virtual int color(); + virtual void init_autocorrect(int colormode); + virtual void setcapturecall(std::function callback) + { + m_captureCallback = callback; + }; + virtual void Fpga_regsAccess_reset(bool enable); +private: + void configFPGAParam(int mode, int dpi); + void openDevice(int dpi, int mode); + void creatcorrectconfig(int dpi, int mode); + bool saveLutImg(int dpi, int mode, bool black); + void correctcolor(); + void fpga_reset(); + void fpga_reload(); + +private: + std::function m_captureCallback; + std::shared_ptr video; + std::shared_ptr vdd_cis_3voff_pin; + std::shared_ptr vdd_vis_5ven_pin; + std::shared_ptr reset_pin; + std::shared_ptr image_in_transfer_pin; + std::shared_ptr initDone_pin; + std::shared_ptr fpgaLoad; + std::shared_ptr fpgaComm; + std::shared_ptr fpga_conf_initn; + std::shared_ptr fpga_conf_done; + bool bcorrecting; + std::thread m_correctthread; +}; diff --git a/device/gxx-linux/capimage/SysInforTool.cpp b/device/gxx-linux/capimage/SysInforTool.cpp new file mode 100644 index 0000000..68219bd --- /dev/null +++ b/device/gxx-linux/capimage/SysInforTool.cpp @@ -0,0 +1,183 @@ +#pragma once +#include "SysInforTool.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int errno; +static 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*/ +static 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*/ +static 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; +} + +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; +} + +std::string SysInforTool::GetSysInfo() +{ + struct sysinfo memInfo; + sysinfo(&memInfo); + m_sysinfo.MemTotal = memInfo.totalram; + 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"); + } + m_sysinfo.MtType = SMBType::MB_DRV_8825; + m_sysinfo.Cistype = HGCISType::CIS_DUNNAN_MONO_V0; + 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; +} \ No newline at end of file diff --git a/device/gxx-linux/capimage/SysInforTool.h b/device/gxx-linux/capimage/SysInforTool.h new file mode 100644 index 0000000..ac924ba --- /dev/null +++ b/device/gxx-linux/capimage/SysInforTool.h @@ -0,0 +1,26 @@ +#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(); +private: + int get_fileSystem_info(const char *fileSystem_name,struct fileSystem_info *fi); + void struct2json(json& j,ScannerSysInfo& info); +private: + ScannerSysInfo m_sysinfo; +}; diff --git a/device/gxx-linux/capimage/correct_ultis.cpp b/device/gxx-linux/capimage/correct_ultis.cpp new file mode 100644 index 0000000..1774ccd --- /dev/null +++ b/device/gxx-linux/capimage/correct_ultis.cpp @@ -0,0 +1,427 @@ +#include +#include +#include +#include +#include "correct_ultis.h" +#include "CorrectParam.h" +#include "commondef.h" +#define USE_NEWFLAT +using namespace cv; + +void initStep() +{ + for (int i = 0; i < 2; i++) + { + for (int j = 0; j < 3; j++) + { + expStep[i][j] = 600; + } + } + for (int i = 0; i < 12; i++) + { + offsetStep[i] = 256; + printf("offsetStep[%d]=%d \n",i,offsetStep[i]); + } + +} + + +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(0, i) = cv::mean(temp_imageBW(cv::Rect(i, 0, 1, temp_imageBW.rows)))[0]; + + return BWbalenceSrc; +} +#ifdef G300 +#define CHANNEL 432 +#else +#define CHANNEL 408 +#endif +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 + channel = CHANNEL; + #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) +{ + printf("\n-----------------------------"); + lutColorMat.release(); + lutGrayMat.release(); + if (!lutpath.empty() && (access(lutpath.c_str(), F_OK) == 0)) + { + printf("\n %s",lutpath.c_str()); + if(iscolor) + lutColorMat = loadLUT(lutpath); //彩色校正值 + else + lutGrayMat = loadLUT(lutpath); //灰色校正值 + } +} + + +void correctColor(cv::Mat& src, int dpi, int mode,bool isText) +{ + Mat lutMat; + FPGAConfigParam param = GetFpgaparam(dpi, mode); + std::string path = isText?param.TextLutPath : param.LutPath; + printf("\n %s",path.c_str()); + 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,FPGAConfigParam param) +{ + printf("eneter creatLUTData \n"); + auto colormode = mode == 1 ? IMREAD_COLOR : IMREAD_GRAYSCALE; + std::string blackPath = param.Flat_BwPath; + std::string whitePath = param.Flat_WhitePath; + std::string lutsavePath = param.LutPath; + printf("\n blackPath =%s \ + whitePath =%s \ + lutsavePath =%s \n",param.Flat_BwPath.c_str(),param.Flat_WhitePath.c_str(),param.LutPath.c_str()); + cv::Mat lut; + cv::Mat twMat = cv::imread(whitePath, IMREAD_ANYCOLOR); + cv::Mat tbMat = cv::imread(blackPath, IMREAD_ANYCOLOR); + 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; + } + + //lut = create_lut(extractRepresentRow2(bMat), extractRepresentRow2(wMat), dpi, mode); // add by liuyong: 刘丁维提供 2019/4/12 + lut = calcLUT(extractRepresentRow2(bMat), extractRepresentRow2(wMat),false); + // Mat dst(bMat.cols * bMat.channels(), 256, CV_8UC1); + // memcpy(dst.data, lut.data, bMat.cols * bMat.channels() * 256); + cv::imwrite(param.LutPath, lut); + lut = calcLUT(extractRepresentRow2(bMat), extractRepresentRow2(wMat),true); + cv::imwrite(param.TextLutPath, lut); + printf("exit creatLUTData \n"); +} + +void creatLUTData(int dpi, int mode) +{ + printf("eneter creatLUTData \n"); + auto param = GetFpgaparam(dpi, mode); + auto colormode = mode == 1 ? IMREAD_COLOR : IMREAD_GRAYSCALE; + std::string blackPath = param.Flat_BwPath; + std::string whitePath = param.Flat_WhitePath; + std::string lutsavePath = param.LutPath; + cv::Mat lut; + cv::Mat twMat = cv::imread(whitePath, IMREAD_ANYCOLOR); + cv::Mat tbMat = cv::imread(blackPath, IMREAD_ANYCOLOR); + 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; + } + + //lut = create_lut(extractRepresentRow2(bMat), extractRepresentRow2(wMat), dpi, mode); // add by liuyong: 刘丁维提供 2019/4/12 + lut = calcLUT(extractRepresentRow2(bMat), extractRepresentRow2(wMat),false); + // Mat dst(bMat.cols * bMat.channels(), 256, CV_8UC1); + // memcpy(dst.data, lut.data, bMat.cols * bMat.channels() * 256); + cv::imwrite(param.LutPath, lut); + lut = calcLUT(extractRepresentRow2(bMat), extractRepresentRow2(wMat),true); + cv::imwrite(param.TextLutPath, lut); + printf("exit creatLUTData \n"); +} + +FPGAConfigParam GetFpgaparam(int dpi, int mode) +{ + FPGAConfigParam param = CorrectParam().GetFpgaparam(dpi, mode); + return param; +} + +void SaveFpgaparam(FPGAConfigParam ¶m) +{ + 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 cv::pow(value / 255.0f, 1.0f / ex) * 255.0f + 0.5f; +} + +#define GAMMA_EX 1.7f +#define BLACK_OFFSET 5 +void fittingLUT(const std::vector& points, uchar min_value, uchar max_value, uchar* 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(temp))); + } +} + +cv::Mat calcLUT(const cv::Mat& black, const cv::Mat& white, bool isTextCorrection) +{ + std::vector 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)); + const double gain = 255.0/((double)CorrectParam().GetFpgaparam(dpi,colormode).MaxBright); + 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]) * gain; + 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 +} + +std::vector caculate(const std::vector& points_x, const std::vector& points_y) +{ + int MaxElement = points_x.size() - 1; + //计算常数f + double f = points_y[0]; + //求解 + int n, m; + //double a[MaxElement][MaxElement+1]; + std::vector> a; + //a.resize(MaxElement); + for (int i = 0; i < MaxElement; i++) + { + std::vector 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 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& 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 grayPoints; + for (size_t j = 0; j < mats.size(); j++) + grayPoints.push_back(mats[j].data[i]); + + fittingLUT(grayPoints, static_cast(min_val), static_cast(max_val), lut.data + i * 256); + } + if (isTextCorrect) + { + std::vector points_x = { 0, 25, 230, 255 }, points_y = { 0, 0, 255, 255 }; + std::vector coefficient = caculate(points_x, points_y); + + uchar 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(cv::min(255, cv::max(0, temp))); + } + + cv::Mat lut_lut(256, 1, CV_8UC1, buffer); + cv::LUT(lut, lut_lut, lut); + } + return lut; +} \ No newline at end of file diff --git a/device/gxx-linux/capimage/correct_ultis.h b/device/gxx-linux/capimage/correct_ultis.h new file mode 100644 index 0000000..27859fd --- /dev/null +++ b/device/gxx-linux/capimage/correct_ultis.h @@ -0,0 +1,33 @@ +#pragma once +#include +#include +#include "CameraParam.h" + +static cv::Mat lutGrayMat; //灰色校正值 +static cv::Mat lutColorMat; //彩色校正值 +static int offsetStep[12]; +static int expStep[2][3]; + +void initStep(); + +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); + +cv::Mat createLUT(const std::vector& mats, bool isTextCorrect); + +void correctColor(cv::Mat& src, int dpi,int mode,bool isText); + +void creatLUTData(int dpi , int mode); + +void creatLUTData(int dpi , int mode,FPGAConfigParam param); + +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); + +void correctColor(cv::Mat& src, int dpi, int mode,bool isText); \ No newline at end of file diff --git a/device/gxx-linux/capimage/gvideo.h b/device/gxx-linux/capimage/gvideo.h index e0da620..5e07a63 100644 --- a/device/gxx-linux/capimage/gvideo.h +++ b/device/gxx-linux/capimage/gvideo.h @@ -38,7 +38,7 @@ protected: size_t length; }; - const int v4l_buffer_count = 5; + const int v4l_buffer_count = 3; int v4l_width = 3100; int v4l_height = 3100; std::string dev_name; diff --git a/device/gxx-linux/capimage/gvideoisp1.cpp b/device/gxx-linux/capimage/gvideoisp1.cpp index e9df0f7..89ff4d8 100644 --- a/device/gxx-linux/capimage/gvideoisp1.cpp +++ b/device/gxx-linux/capimage/gvideoisp1.cpp @@ -172,6 +172,7 @@ void* GVideoISP1::read_frame(int timeout) { LOG_TRACE(string_format("VIDIOC_QBUF sucess")); } LOG_TRACE(string_format("buf.index = %d,buf.addr = %p\n",buf.index,buffers[buf.index].start)); + printf("\n readframe size = %d ",buffers[buf.index].length); return buffers[buf.index].start; } diff --git a/device/gxx-linux/capimage/hgutils.cpp b/device/gxx-linux/capimage/hgutils.cpp index cc01014..48dfd06 100644 --- a/device/gxx-linux/capimage/hgutils.cpp +++ b/device/gxx-linux/capimage/hgutils.cpp @@ -3,10 +3,11 @@ #include #include #include +#include "CImageMerge.h" using namespace cv; -cv::Mat extractRepresentRow2(const cv::Mat &src) +cv::Mat extractRepresentRow(const cv::Mat &src) { printf("extractRepresentRow2 enter \n"); Mat src_temp(src.rows, src.step, CV_8UC1, src.data); @@ -137,9 +138,9 @@ cv::Mat create_lut(const cv::Mat &black, const cv::Mat &white, bool colormode, C void initLut() { if(access(LUT_GRAY_LUT_PATH, F_OK) != -1) - lutGrayMat = cv::imread(LUT_GRAY_LUT_PATH, IMREAD_GRAYSCALE); //灰色校正值 + lutGrayMat_old = cv::imread(LUT_GRAY_LUT_PATH, IMREAD_GRAYSCALE); //灰色校正值 if(access(LUT_COLOR_LUT_PATH, F_OK) != -1) - lutColorMat = cv::imread(LUT_COLOR_LUT_PATH, IMREAD_GRAYSCALE); //彩色校正值 + lutColorMat_old = cv::imread(LUT_COLOR_LUT_PATH, IMREAD_GRAYSCALE); //彩色校正值 } void correctColor(cv::Mat src, bool enhance) @@ -153,11 +154,11 @@ void correctColor(cv::Mat src, bool enhance) if (src.type() == CV_8UC3) { patch = (src.cols * 3) / SIZE; - if (lutColorMat.empty()) + if (lutColorMat_old.empty()) { if (access(LUT_COLOR_LUT_PATH, F_OK) != -1) { - lutColorMat = imread(LUT_COLOR_LUT_PATH, IMREAD_GRAYSCALE); + lutColorMat_old = imread(LUT_COLOR_LUT_PATH, IMREAD_GRAYSCALE); } else { @@ -165,16 +166,16 @@ void correctColor(cv::Mat src, bool enhance) return; } } - lutMat = lutColorMat; + lutMat = lutColorMat_old; } else { patch = (src.cols) / SIZE; - if (lutGrayMat.empty()) + if (lutGrayMat_old.empty()) { if (access(LUT_GRAY_LUT_PATH, F_OK) != -1) { - lutGrayMat = imread(LUT_GRAY_LUT_PATH, IMREAD_GRAYSCALE); + lutGrayMat_old = imread(LUT_GRAY_LUT_PATH, IMREAD_GRAYSCALE); } else { @@ -182,7 +183,7 @@ void correctColor(cv::Mat src, bool enhance) return; } } - lutMat = lutGrayMat; + lutMat = lutGrayMat_old; } if (lutMat.empty()) { @@ -218,7 +219,7 @@ void creatLUTData(int mode, CISVendor vendor) bMat = tbMat; } - lut = create_lut(extractRepresentRow2(bMat), extractRepresentRow2(wMat), mode, vendor); // add by liuyong: 刘丁维提供 2019/4/12 + lut = create_lut(extractRepresentRow(bMat), extractRepresentRow(wMat), mode, vendor); // add by liuyong: 刘丁维提供 2019/4/12 Mat dst(bMat.cols * bMat.channels(), 256, CV_8UC1); memcpy(dst.data, lut.data, bMat.cols * bMat.channels() * 256); cv::imwrite(lutsavePath, dst); @@ -261,7 +262,7 @@ cv::Mat GetMergeMat(void *data, int width, int height, int type) return saveMat.clone(); } - +//3399 旧版本 华凌cis拼接算法 cv::Mat GetMergeMat(cv::Mat& mat, int width, int height, int type) { if (mat.empty()) @@ -288,6 +289,38 @@ cv::Mat GetMergeMat(cv::Mat& mat, int width, int height, int type) return mat; } +cv::Mat GetStitchMat(int pixtype,int width,int height,cv::Mat& mat){ + cv::Mat dst; + cv::Mat ch_mats[3]; + int dstwidth, dstheight; + width = width /3 /(pixtype == 1? 3:1); + height *=3; + dstwidth = width * 3; + dstheight = height / 3; + if (pixtype == IMAGE_COLOR) + { + //mat = cv::Mat(m_height / 3, m_width * 9, CV_8UC1, imgdata); + dst = cv::Mat(dstheight, dstwidth, CV_8UC3); + ch_mats[2] = mat(cv::Rect(width * 3 * 1, 0, width * 3, height / 3)); //R 对应红通道 + ch_mats[1] = mat(cv::Rect(width * 3 * 2, 0, width * 3, height / 3)); //G 对应绿通道 + ch_mats[0] = mat(cv::Rect(width * 3 * 0, 0, width * 3, height / 3)); //B 对应蓝通道 + cv::merge(ch_mats, 3, dst); + for (int i = 0; i < 3; i++) + ch_mats[i].release(); + return dst.clone(); + } + else + { //gray + return mat; + } +} + +//3399 敦南cis 300 600 拼接算法 +cv::Mat GetMergeMat(int dstwidth ,int dstheight,int type,cv::Mat& mat,std::uint32_t fpga_vs) +{ + return CImageMerge().MergeImage(type==CV_8UC3,mat,dstwidth,dstheight,0x90001); +} + void savescannerinfo(ScannerNativeParam params) { jsonconfig().savescannerinfo(params); diff --git a/device/gxx-linux/capimage/hgutils.h b/device/gxx-linux/capimage/hgutils.h index 912f1fb..471c30d 100644 --- a/device/gxx-linux/capimage/hgutils.h +++ b/device/gxx-linux/capimage/hgutils.h @@ -4,10 +4,10 @@ #include "commondef.h" -static cv::Mat lutGrayMat; //灰色校正值 -static cv::Mat lutColorMat; //彩色校正值 +static cv::Mat lutGrayMat_old; //灰色校正值 +static cv::Mat lutColorMat_old; //彩色校正值 -cv::Mat extractRepresentRow2(const cv::Mat& src); +cv::Mat extractRepresentRow(const cv::Mat& src); cv::Mat create_lut(const cv::Mat& black, const cv::Mat& white,bool colormode,CISVendor vendor); @@ -19,8 +19,13 @@ cv::Mat GetMergeMat(void* data,int width ,int height,int type); cv::Mat GetMergeMat(cv::Mat& mat,int width ,int height,int type); +cv::Mat GetMergeMat(int dstwidth ,int dstheight,int type,cv::Mat& mat,std::uint32_t fpga_vs); + +cv::Mat GetStitchMat(int pixtype,int width,int height,cv::Mat& mat); + void correctColor(cv::Mat src, bool enhance); + void creatLUTData(int mode,CISVendor vendor); void savescannerinfo(ScannerNativeParam params); diff --git a/device/gxx-linux/capimage/jsonconfig.cpp b/device/gxx-linux/capimage/jsonconfig.cpp index 842d322..0f67b80 100644 --- a/device/gxx-linux/capimage/jsonconfig.cpp +++ b/device/gxx-linux/capimage/jsonconfig.cpp @@ -9,6 +9,7 @@ #define SP_COLOR_DEFAULT 0x438 #define SP_GRAY_DEFAULT 0xca8 + jsonconfig::jsonconfig() { } @@ -24,7 +25,7 @@ void jsonconfig::savecisconfig(HGCorrectConfigs configs) auto ret = mkdir(JSON_CORRECTDIR_PATH, 0777); if (ret != 0) { - HG_LOG("make dir failed .path=%s \n", JSON_CORRECTDIR_PATH); + printf("make dir failed .path=%s \n", JSON_CORRECTDIR_PATH); } } json m_json; @@ -100,6 +101,7 @@ HGCorrectConfigs jsonconfig::getcorrectconfigs() std::ifstream i(JSON_CORRECTFILE_PATH); auto pos = i.tellg(); i.seekg(0, std::ios::end); + //printf("file length =%d ", i.tellg()); if (i.tellg() <= 2) { cfs = getdefaultconfigs(); @@ -226,17 +228,19 @@ void jsonconfig::savescannerinfo(ScannerNativeParam param) m_json[S_INFO_PID] = (param.Pid); std::ofstream o(JSON_SCANNER_INFO_FILE); o << std::setw(4) << m_json << std::endl; + //printf("\n %s speedmode value = %d",JSON_SCANNER_INFO_FILE,param.speedmode); } ScannerNativeParam jsonconfig::getscannerinfo() { + std::lock_guard lc(mtx); ScannerNativeParam snp; if (access(JSON_SCANNER_INFO_DIR, 0) == -1) { auto ret = mkdir(JSON_SCANNER_INFO_DIR, 0777); if (ret != 0) { - HG_LOG("make dir failed .path=%s \n", JSON_SCANNER_INFO_DIR); + printf("make dir failed .path=%s \n", JSON_SCANNER_INFO_DIR); } } @@ -253,6 +257,7 @@ ScannerNativeParam jsonconfig::getscannerinfo() i.seekg(0, std::ios::end); + //printf("file length =%d ", i.tellg()); if (i.tellg() <= 2) { snp = getdefaultscannerinfo(); @@ -333,7 +338,7 @@ ScannerNativeParam jsonconfig::getscannerinfo() if(!m_json[S_INFO_SLEEPTIME].is_null()) m_json[S_INFO_SLEEPTIME].get_to(snp.sleeptime); else - snp.sleeptime = 900; + snp.sleeptime = 10800; if(!m_json[S_INFO_CLR_MAXBRT].is_null()) m_json[S_INFO_CLR_MAXBRT].get_to(snp.clr_maxbright); @@ -357,8 +362,12 @@ ScannerNativeParam jsonconfig::getscannerinfo() { #ifdef G100 snp.Pid = 0x139; - #else + #elif defined G200 snp.Pid = 0x239; + #elif defined G300 + snp.Pid = 0x339; + #else + snp.Pid = 0x439; #endif } @@ -366,6 +375,8 @@ ScannerNativeParam jsonconfig::getscannerinfo() m_json[S_INFO_VID].get_to(snp.Vid); else snp.Vid = 0x3072; + + //printf("vid = %d pid =%d \n",snp.Vid,snp.Pid ); return snp; } @@ -385,14 +396,24 @@ ScannerNativeParam jsonconfig::getdefaultscannerinfo() param.color_sp=0x27C; param.speedmode = 100; param.Pid = 0x0239; -#else +#elif defined G100 param.gray_sp=0x822; //G200 140 ppm 0x27c 0x781 G100 100 ppm 0x2B6 0x822 param.color_sp=0x2B6; param.speedmode = 70; param.Pid = 0x0139; +#elif defined G300 + param.gray_sp=0x822; + param.color_sp=0x2B6; + param.speedmode = 40; + param.Pid = 0x0339; +#else + param.gray_sp=0x822; + param.color_sp=0x2B6; + param.speedmode = 50; + param.Pid = 0x0439; #endif param.Vid = 0x3072; - param.sleeptime=3600; + param.sleeptime=10800; param.clr_maxbright = param.gray_maxbright = 200; return param; diff --git a/device/gxx-linux/capimage/jsonconfig.h b/device/gxx-linux/capimage/jsonconfig.h index deffaca..1a43092 100644 --- a/device/gxx-linux/capimage/jsonconfig.h +++ b/device/gxx-linux/capimage/jsonconfig.h @@ -1,6 +1,7 @@ #pragma once #include "json.hpp" #include "commondef.h" +#include using json = nlohmann::json; @@ -18,4 +19,5 @@ public: ScannerNativeParam getscannerinfo(); HGCorrectConfigs getdefaultconfigs(); ScannerNativeParam getdefaultscannerinfo(); + std::mutex mtx; }; diff --git a/device/gxx-linux/capimage/scannersysinfo.h b/device/gxx-linux/capimage/scannersysinfo.h new file mode 100644 index 0000000..23d8ac1 --- /dev/null +++ b/device/gxx-linux/capimage/scannersysinfo.h @@ -0,0 +1,69 @@ +#pragma once +#include + +enum class SysType +{ + Sys_Linux_Debian=1, + Sys_Linux_Uos, + Sys_Android +}; + +enum class Scanner_Serial{ + S_G100=1, + S_G200, + S_G300, + S_G300_UV, + S_G400 +}; + +enum class SCPU +{ + CPU_3288=1, + CPU_3399 +}; + + +enum class SMBType +{ + MB_DRV_UNKNOWUN, + MB_DRV_8825, + MB_DRV_TMC216, + MB_DRV_ANLU, + MB_DRV_LATIACE +}; + +enum class HGCISType +{ + CIS_UNKOWNUN, + CIS_HUALIN_MONO_V0, + CIS_DUNNAN_MONO_V0, + CIS_DUNNAN_COLOR_V0 +}; + +enum class ScreenType +{ + ST_None=1, + ST_SmallLcd, + ST_BigLcd, + ST_8Inch, + ST_7Inch +}; + +typedef struct Scanner_SysInfo +{ + SCPU CPU;//3288 3399 + SysType Systype; + ScreenType Screentype; + unsigned int MtBoardVersion; + SMBType MtType; + unsigned int FPGAVersion; + HGCISType Cistype; + unsigned int ResSup[3];//分辨率支持 + unsigned int MemTotal;//单位 MB + unsigned int DiskTotal;//单位 MB + unsigned int DiskUsed;//已使用空间 + std::string KernelVersion; + unsigned int Have_EthernPort; + std::string ServiceVersion; + float UsbProtocol;//1.0 2.0 2.xx +}ScannerSysInfo; diff --git a/device/gxx-linux/capimage/xmake.lua b/device/gxx-linux/capimage/xmake.lua index 09de6fe..8465f32 100644 --- a/device/gxx-linux/capimage/xmake.lua +++ b/device/gxx-linux/capimage/xmake.lua @@ -5,6 +5,6 @@ target("capimage") add_files("*.cpp") add_deps("regs", "deviceio", "conf", "applog", {public = true}) add_includedirs(".", { public = true}) - add_links("opencv_core", "opencv_highgui", "opencv_imgproc", { public = true }) + add_links("opencv_core", "opencv_imgcodecs", "opencv_highgui", "opencv_imgproc", { public = true }) add_syslinks("pthread") add_packages("common") \ No newline at end of file diff --git a/device/gxx-linux/deviceio/DevUtil.h b/device/gxx-linux/deviceio/DevUtil.h index 553f747..4ec2b08 100644 --- a/device/gxx-linux/deviceio/DevUtil.h +++ b/device/gxx-linux/deviceio/DevUtil.h @@ -3,7 +3,6 @@ #include #include -#define G300 template void write_dev(std::string path, T value) diff --git a/device/gxx-linux/deviceio/PinMonitor.cpp b/device/gxx-linux/deviceio/PinMonitor.cpp index cd48c13..2c7249e 100644 --- a/device/gxx-linux/deviceio/PinMonitor.cpp +++ b/device/gxx-linux/deviceio/PinMonitor.cpp @@ -3,35 +3,30 @@ #include #include #include -#include #include #include #include "StopWatch.h" -#include -#include -#include "applog.h" -#include "stringex.hpp" -static const std::string loggername = "PinMonitor"; PinMonitor::PinMonitor(unsigned int pinNum, std::function call_back) - : pin(pinNum) +: pin(pinNum) { - LOG_INIT(); pin.setDirection(Gpio::in); pin.setEdge(Gpio::falling); this->call_back = call_back; thread_monitor = std::thread(&PinMonitor::monitor, this); //printf("PinMonitor threadid = %d \n",thread_monitor.get_id()); - // int priority=sched_get_priority_max(SCHED_FIFO); - // if(priority==-1) - // { - // printf("sched_get_priority_max error \n"); - // } - // thparm.sched_priority = priority; - // if(pthread_setschedparam(thread_monitor.native_handle(),SCHED_FIFO,&thparm)) - // { - // printf("failed to error set pthread_setschedparam \n"); - // } + sched_param thparm; + int priority=sched_get_priority_max(SCHED_FIFO); + if(priority==-1) + { + printf("sched_get_priority_max error \n"); + } + thparm.sched_priority = priority; + if(pthread_setschedparam(thread_monitor.native_handle(),SCHED_FIFO,&thparm)) + { + printf("failed to error set pthread_setschedparam \n"); + } + } PinMonitor::~PinMonitor() @@ -66,20 +61,15 @@ void PinMonitor::monitor() { lseek(pfd.fd, 0, SEEK_SET); num = read(pfd.fd, buf, 8); - + buf[num - 1] = '\0'; ret = atoi(buf); - //LOG_TRACE("poll call"); - if (call_back) - { - sw.reset(); - call_back(pin.getPort()); - LOG_TRACE(string_format("poll call times = %.2f \n",sw.elapsed_ms())); - } - + if (call_back) + call_back(pin.getPort()); + sw.reset(); - while(sw.elapsed_ms() < 10) + while(sw.elapsed_ms() < 30) { ret = poll(&pfd, 1, 1); if (ret > 0) @@ -88,43 +78,11 @@ void PinMonitor::monitor() buf[num - 1] = '\0'; ret = atoi(buf); //printf("pMonitor nread = %d ret val = %d \n",num,ret); - } + } } } } } close(pfd.fd); - - // int n; - // int epfd = epoll_create(1); - // int fd = open(pin.getValuePath().c_str(), O_RDONLY); - // char buf[8]; - // //printf("open returned %d: %s\n", fd, strerror(errno)); - // if (fd > 0) - // { - // struct epoll_event ev; - // struct epoll_event events; - // ev.events = EPOLLPRI; - // ev.data.fd = fd; - - // n = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev); - - // while (bMonitor) - // { - // n = epoll_wait(epfd, &events, 1, 1000); - - // if (n > 0) - // { - // n = lseek(fd, 0, SEEK_SET); - // n = read(fd, buf, 8); - - // buf[n - 1] = '\0'; - // auto ret = atoi(buf); - // if (call_back) - // call_back(pin.getPort()); - // } - // } - // } - // close(fd); } \ No newline at end of file diff --git a/device/gxx-linux/imgproc/imageencode.cpp b/device/gxx-linux/imgproc/imageencode.cpp index 2390c94..68b4c8a 100644 --- a/device/gxx-linux/imgproc/imageencode.cpp +++ b/device/gxx-linux/imgproc/imageencode.cpp @@ -22,18 +22,22 @@ MemoryPtr BmpImageEncode::encode(cv::Mat &image) return mem; } -JpegImageEncode::JpegImageEncode(bool bwimg) +JpegImageEncode::JpegImageEncode(bool bwimg, int dpi) { - // if (!bwimg) - // { - // compression_params.push_back(cv::IMWRITE_JPEG_QUALITY); - // compression_params.push_back(100); - // } - // else{ - // compression_params.push_back(/*CV_IMWRITE_PNG_STRATEGY*/17); - // compression_params.push_back(cv::IMWRITE_PNG_STRATEGY_FIXED); - // } - // m_bwimg = bwimg; + if (!bwimg) + { + compression_params.push_back(cv::IMWRITE_JPEG_QUALITY); + compression_params.push_back(100); + compression_params.push_back(/*cv::CV_IMWRITE_JPEG_RESOLUTION_X*/7); + compression_params.push_back(dpi); + compression_params.push_back(/*cv::CV_IMWRITE_JPEG_RESOLUTION_Y*/8); + compression_params.push_back(dpi); + } + else{ + compression_params.push_back(/*CV_IMWRITE_PNG_STRATEGY*/17); + compression_params.push_back(cv::IMWRITE_PNG_STRATEGY_FIXED); + } + m_bwimg = bwimg; } JpegImageEncode::~JpegImageEncode() @@ -42,11 +46,11 @@ JpegImageEncode::~JpegImageEncode() MemoryPtr JpegImageEncode::encode(cv::Mat &image) { VectorMemroyPtr mem = VectorMemroyPtr(new VectorMemroy()); - StopWatch sw; + // StopWatch sw; printf("encode image(%d * %d): %p - %p\n", image.cols, image.rows, image.data, image.dataend); // cv::imwrite("beforcompress.jpg",image); // cv::imencode(m_bwimg ? ".png" : ".jpg", image, mem->buf(), compression_params); - cv::imencode(".png", image, mem->buf(), compression_params); + cv::imencode(".jpg", image, mem->buf(), compression_params); //printf("encode time = %0.2f \n", sw.elapsed_ms()); return mem; diff --git a/device/gxx-linux/imgproc/imageencode.h b/device/gxx-linux/imgproc/imageencode.h index f98b62f..6b3f3b7 100644 --- a/device/gxx-linux/imgproc/imageencode.h +++ b/device/gxx-linux/imgproc/imageencode.h @@ -21,7 +21,7 @@ public: class JpegImageEncode : public IImageEncode { public: - JpegImageEncode(bool bwimg); + JpegImageEncode(bool bwimg, int dpi); virtual ~JpegImageEncode(); virtual MemoryPtr encode(cv::Mat& image); diff --git a/device/gxx-linux/motor_run/CuoZhiMotor.cpp b/device/gxx-linux/motor_run/CuoZhiMotor.cpp new file mode 100644 index 0000000..de9bf86 --- /dev/null +++ b/device/gxx-linux/motor_run/CuoZhiMotor.cpp @@ -0,0 +1,64 @@ +#include "CuoZhiMotor.h" +#include + +CuoZhiMotor::CuoZhiMotor() : Motor(motorPorts_Cuozhi) +{ + m_cfg.GetParams(0,MotorConfig::MTBDType::MT_DRV); + if(Dail().GetValue().dails.in_voltage4 == 0) + m_mttype = MotorConfig::MTBDType::MT_DRV; + else + m_mttype = MotorConfig::MTBDType::MT_TMC; + speedChange(0,1,1); + printf("\nCuo speed = %d ",m_mttype); +} + +CuoZhiMotor::~CuoZhiMotor() +{ + std::cout << "CuoZhiMotor::~CuoZhiMotor()" << std::endl; +} + +void CuoZhiMotor::speedChange(int speed,int dpi ,int iscolor) +{ + printf("\nCuo speed = %d dpi = %d iscolor = %d",speed,dpi,iscolor); + if(speed == 0xff) + { + if(m_mttype == MotorConfig::MTBDType::MT_DRV) + mspCuozhiForward = { .finalPeriod = 1427500,.Fmin = 2027500 ,.stepnum = 30 ,.a = 100 , + .offset = 4 ,.finalDelay = 3000 }; + else + mspCuozhiForward = { .finalPeriod = 1427500/4,.Fmin = 2027500/4 ,.stepnum = 30 ,.a = 100 , + .offset = 4 ,.finalDelay = 3000 }; + } + else{ + auto params = m_cfg.GetMotorSpeedParams(false,m_mttype); + m_speedmode = speed; + for (int i = 0; i < params.size(); i++) + { + if (params[i].dpi == dpi && + params[i].colormode == iscolor && + params[i].speed == (speed+1)) + { + mspCuozhiForward = { .finalPeriod = params[i].mt_param.finalPeriod,.Fmin = params[i].mt_param.Fmin,.stepnum = params[i].mt_param.stepnum,.a = params[i].mt_param.a, + .offset = params[i].mt_param.offset,.finalDelay = params[i].mt_param.finalDelay }; + } + } + } + + printf("\n mspCuozhiForward.finalPeriod %d, mspCuozhiForward.Fmin %d, mspCuozhiForward.stepnum %f , mspCuozhiForward.a %f, mspCuozhiForward.offset %f , mspCuozhiForward.finalDelay %f", + mspCuozhiForward.finalPeriod, mspCuozhiForward.Fmin, mspCuozhiForward.stepnum, mspCuozhiForward.a, mspCuozhiForward.offset, mspCuozhiForward.finalDelay); + delays_forward = speedup_cfg(mspCuozhiForward.finalPeriod, mspCuozhiForward.Fmin, mspCuozhiForward.stepnum, mspCuozhiForward.a, mspCuozhiForward.offset, mspCuozhiForward.finalDelay); + + // if(cuoZhiForwardFinalPeriod.find(dpi) == cuoZhiForwardFinalPeriod.end()) + // dpi = 1; + // mspCuozhiForward = { .finalPeriod = cuoZhiForwardFinalPeriod.at(dpi)[m_speedmode],.Fmin = cuoZhiFmin.at(dpi)[m_speedmode], + // .stepnum = cuoZhiStepNum.at(dpi)[m_speedmode],.a = cuoZhiA.at(dpi)[m_speedmode],.offset = cuoZhiOffset.at(dpi)[m_speedmode], + // .finalDelay = cuoZhiFinalDelay.at(dpi)[m_speedmode] }; + mspCuozhiBackward = { .finalPeriod = cuoZhiBackwardFinalPeriod.at(dpi)[m_speedmode],.Fmin = cuoZhiFmin.at(dpi)[m_speedmode], + .stepnum = cuoZhiStepNum.at(dpi)[m_speedmode],.a = cuoZhiA.at(dpi)[m_speedmode],.offset = cuoZhiOffset.at(dpi)[m_speedmode], + .finalDelay = cuoZhiFinalDelay.at(dpi)[m_speedmode] }; + // delays_forward = speedup_cfg(mspCuozhiForward.finalPeriod, mspCuozhiForward.Fmin, mspCuozhiForward.stepnum, mspCuozhiForward.a, + // mspCuozhiForward.offset, mspCuozhiForward.finalDelay); + delays_backward = speedup_cfg(mspCuozhiBackward.finalPeriod, mspCuozhiBackward.Fmin, mspCuozhiBackward.stepnum, mspCuozhiBackward.a, + mspCuozhiBackward.offset, mspCuozhiBackward.finalDelay); + + } \ No newline at end of file diff --git a/device/gxx-linux/motor_run/CuoZhiMotor.h b/device/gxx-linux/motor_run/CuoZhiMotor.h new file mode 100644 index 0000000..dd89e44 --- /dev/null +++ b/device/gxx-linux/motor_run/CuoZhiMotor.h @@ -0,0 +1,92 @@ +#pragma once +#include "Motor.h" +#include + +class CuoZhiMotor : public Motor +{ +public: + CuoZhiMotor(); + ~CuoZhiMotor(); + void speedChange(int speed,int dpi ,int iscolor); + void reset() { + mspCuozhiBackward = {.finalPeriod = 827500, .Fmin = 1407750, .stepnum = 25, .a = 150, .offset = 8, .finalDelay = 3000}; + mspCuozhiForward = {.finalPeriod = 627500, .Fmin = 1407750, .stepnum = 25, .a = 150, .offset = 8, .finalDelay = 3000}; + if(m_mttype == MotorConfig::MTBDType::MT_TMC) + { + mspCuozhiBackward.finalPeriod /= 4; + mspCuozhiBackward.Fmin /= 4; + mspCuozhiForward.finalPeriod /= 4; + mspCuozhiForward.Fmin /= 4; + } + delays_forward = speedup_cfg(mspCuozhiForward.finalPeriod, mspCuozhiForward.Fmin, mspCuozhiForward.stepnum, mspCuozhiForward.a, + mspCuozhiForward.offset, mspCuozhiForward.finalDelay); + forward(); + std::this_thread::sleep_for(std::chrono::milliseconds(300)); + stop(); + delays_backward = speedup_cfg(mspCuozhiBackward.finalPeriod, mspCuozhiBackward.Fmin, mspCuozhiBackward.stepnum, mspCuozhiBackward.a, + mspCuozhiBackward.offset, mspCuozhiBackward.finalDelay); + backward(); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + stop(); + } + + virtual void start() { + forward(); + } + + void forward() { + setDirection(1); + Motor::start(delays_forward, mspCuozhiForward); + } + + void backward() { + setDirection(0); + Motor::start(delays_backward, mspCuozhiBackward); + } + +private: + MotorConfig m_cfg; + const std::map> cuoZhiStepNum = { + {1,{23,25,30,30,30 }}, + {2,{23,25,30,30,30 }}, + {3,{23,25,30,30,30 }}, + }; + const std::map> cuoZhiForwardFinalPeriod = { + {1,{607500,537500,477500,435500,435500}}, + {2,{607500,537500,517500,497500,477500}}, + {3,{607500,537500,527500,477500,307500}}, + };//627500,607500,587500,567500,547500,527500 + const std::map> cuoZhiBackwardFinalPeriod = { + {1,{607500,537500,477500,395500,307500}}, + {2,{607500,587500,527500,477500,307500}}, + {3,{607500,587500,527500,477500,307500}}, + };//707500,607500,587500,567500,547500,527500 + const std::map> cuoZhiFmin = { + {1,{ 1407750,1407750,1407750,1407750,1407750 }}, + {2,{ 1407750,1407750,1407750,1407750,1407750 }}, + {3,{ 1407750,1407750,1407750,1407750,1407750 }}, + }; + const std::map> cuoZhiA = { + {1,{ 180,150,150,130,130 }}, + {2,{ 180,150,150,130,130 }}, + {3,{ 180,150,150,150,150 }}, + }; + const std::map> cuoZhiOffset = { + {1,{ 7,7,7,12,12 }}, + {2,{ 7,7,7,7,7 }}, + {3,{ 7,7,7,7,7 }}, + }; + const std::map> cuoZhiFinalDelay = { + {1,{ 3000,3000,3000,3000,3000 }}, + {2,{ 3000,3000,3000,3000,3000 }}, + {3,{ 3000,3000,3000,3000,3000 }}, + }; + + MotorSpeedParam mspCuozhiForward; + MotorSpeedParam mspCuozhiBackward; + std::vector delays_forward; + std::vector delays_backward; + int m_speedmode; +}; + + diff --git a/device/gxx-linux/motor_run/DevUtil.cpp b/device/gxx-linux/motor_run/DevUtil.cpp new file mode 100644 index 0000000..310aca3 --- /dev/null +++ b/device/gxx-linux/motor_run/DevUtil.cpp @@ -0,0 +1,30 @@ +#include "DevUtil.h" +#include + +#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); + printf("DeviceExport::DeviceExport().\n"); +} diff --git a/device/gxx-linux/motor_run/DevUtil.h b/device/gxx-linux/motor_run/DevUtil.h new file mode 100644 index 0000000..9018f16 --- /dev/null +++ b/device/gxx-linux/motor_run/DevUtil.h @@ -0,0 +1,57 @@ +#pragma once +#include +#include +#include +#include "stringex.hpp" + +template +void write_dev(std::string path, T value) { + std::ofstream ofout(path); + ofout << value; + ofout.close(); +} + +extern int read_dev_i(std::string path); + +extern std::string read_dev_s(std::string path); + +enum PORTS +{ + /* //RK3288 Motor GPIO + CuoZhiMotor_Reset = 56, // GPIO2_A0 MOTO_BOT_RESET_N + CuoZhiMotor_Sleep = 57, // GPIO2_A1 MOTO_BOT_SLEEP_N + CuoZhiMotor_Enable = 58, // GPIO2_A2 MOTO_BOT_ENBL_N + CuoZhiMotor_Direction = 62, // GPIO2_A6 MOTO_BOT_DIR + CuoZhiMotor_Home = 184, // GPIO6_A0 MOTO_BOT_HOME_N + CuoZhiMotor_Fault = 185, // GPIO6_A1 MOTO_BOT_FAULT_N + + ZouZhiMotor_Reset = 64, // GPIO2_B0 MOTO_TOP_RESET_N + ZouZhiMotor_Sleep = 65, // GPIO2_B1 MOTO_TOP_SLEEP_N + ZouZhiMotor_Enable = 66, // GPIO2_B2 MOTO_TOP_ENBL_N + ZouZhiMotor_Direction = 70, // GPIO2_B6 MOTO_TOP_DIR + ZouZhiMotor_Home = 186, // GPIO6_A2 + ZouZhiMotor_Fault = 187, // GPIO6_A3 + */ + + //RK3399 Motor GPIO + MotorPower = 157, // GPIO4_D5 motor power + + CuoZhiMotor_Reset = 151, // GPIO4_C7 BOT + CuoZhiMotor_Enable = 153, // GPIO4_D1 BOT + CuoZhiMotor_Direction = 152, // GPIO4_D0 BOT + + ZouZhiMotor_Reset = 155, // GPIO4_D3 TOP + ZouZhiMotor_Enable = 154, // GPIO4_D2 TOP + ZouZhiMotor_Direction = 52, // GPIO1_C4 TOP +}; + +class DeviceExport { +public: + DeviceExport(); +private: + const int ports[7] = { MotorPower, CuoZhiMotor_Reset, CuoZhiMotor_Enable, CuoZhiMotor_Direction, + ZouZhiMotor_Reset, ZouZhiMotor_Enable, ZouZhiMotor_Direction, + }; + const int pwms[2] = { 1, 2 }; +}; + diff --git a/device/gxx-linux/motor_run/Gpio.cpp b/device/gxx-linux/motor_run/Gpio.cpp new file mode 100644 index 0000000..8fa9e8d --- /dev/null +++ b/device/gxx-linux/motor_run/Gpio.cpp @@ -0,0 +1,79 @@ +#include +#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()); + printf("Gpio::Gpio(int port = %d) \n",port); +} + +Gpio::~Gpio() +{ + std::cout << "Gpio::~Gpio()" << std::endl; +} + +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); +} + + diff --git a/device/gxx-linux/motor_run/Gpio.h b/device/gxx-linux/motor_run/Gpio.h new file mode 100644 index 0000000..ba785c5 --- /dev/null +++ b/device/gxx-linux/motor_run/Gpio.h @@ -0,0 +1,53 @@ +#pragma once +#include + +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); + ~Gpio(); + 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); +}; + + diff --git a/device/gxx-linux/motor_run/Motor.cpp b/device/gxx-linux/motor_run/Motor.cpp new file mode 100644 index 0000000..637ea44 --- /dev/null +++ b/device/gxx-linux/motor_run/Motor.cpp @@ -0,0 +1,69 @@ +#include "Motor.h" +#include "DevUtil.h" +#include +#include +#include + + +const MotorPorts motorPorts_Zouzhi = { .reset = ZouZhiMotor_Reset, .enable = ZouZhiMotor_Enable, .dir = ZouZhiMotor_Direction, + .pwm = 1}; +const MotorPorts motorPorts_Cuozhi = {.reset = CuoZhiMotor_Reset, .enable = CuoZhiMotor_Enable, .dir = CuoZhiMotor_Direction, + .pwm = 2 }; + +std::vector speedup_cfg(int finalPeriod, int Fmin, int stepnum, int a, int offset, int finalDelay) { + std::vector freqs; + int period = 0; + double delay = ((double)finalDelay) / 1000000.0; + double b = stepnum * delay; + for (int i = 0; i < stepnum; i++) { + b = b - delay; + period = (int)(finalPeriod + (Fmin - finalPeriod) / (1 + exp(-a * b + offset))); + freqs.push_back(period); + //printf("\n period %d",period); + } + return freqs; +} + +Motor::Motor(MotorPorts motorPorts) + : powerpin(MotorPower),resetPin(motorPorts.reset),enablePin(motorPorts.enable),dirPin(motorPorts.dir),pwm(motorPorts.pwm) +{ + powerpin.setDirection(Gpio::out); + resetPin.setDirection(Gpio::out); + enablePin.setDirection(Gpio::out); + dirPin.setDirection(Gpio::out); + powerpin.setValue(Gpio::High); + resetPin.setValue(Gpio::High); + enablePin.setValue(Gpio::High); + std::cout << "Motor::Motor(MotorPorts motorPorts)" << std::endl; +} + +Motor:: ~Motor() +{ + stop(); + std::cout << "Motor::~Motor()" << std::endl; +} + +void Motor::start() { + enablePin.setValue(Gpio::Low); + pwm.enable(true); +} + +void Motor::stop() { + enablePin.setValue(Gpio::High); + pwm.enable(false); +} + +void Motor::pause() { + enablePin.setValue(Gpio::Low); + pwm.enable(false); +} + +void Motor::setDirection(int dir) { + dirPin.setValue((Gpio::GpioLevel)dir); +} + +void Motor::setSpeed(int value) { + pwm.setFreq(value); +} + + diff --git a/device/gxx-linux/motor_run/Motor.h b/device/gxx-linux/motor_run/Motor.h new file mode 100644 index 0000000..101d201 --- /dev/null +++ b/device/gxx-linux/motor_run/Motor.h @@ -0,0 +1,72 @@ +#pragma once +#include +#include +#include +#include "Gpio.h" +#include "Pwm.h" +#include "MotorConfig.h" +#include "commondef.h" +#include "dailex.hpp" + + +struct MotorPorts +{ + int reset; + int enable; + int dir; + int pwm; +}; + +extern const MotorPorts motorPorts_Zouzhi; +extern const MotorPorts motorPorts_Cuozhi; + +class Motor +{ +public: + Motor(MotorPorts motorPorts); + virtual ~Motor(); +protected: + Gpio powerpin; + Gpio resetPin; + //Gpio sleepPin; + Gpio enablePin; + Gpio dirPin; + //Gpio homePin; + //Gpio faultPin; + + Pwm pwm; + + MotorConfig::MTBDType m_mttype; + void start(std::vector& delay_s, const MotorSpeedParam& msp) + { + if (!delay_s.empty()) { + std::vector::iterator iter = delay_s.begin(); + enablePin.setValue(Gpio::Low); + pwm.setFreq(PWM_PERIOD / (*iter)); + pwm.enable(true); + std::this_thread::sleep_for(std::chrono::microseconds((int)msp.finalDelay)); + 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); + } + +public: + virtual void start(); + + void stop(); + + void pause(); + + void setDirection(int dir); + + void setSpeed(int value); + + static void enablePower(bool bEnable); + +}; +extern std::vector speedup_cfg(int finalPeriod, int Fmin, int stepnum, int a, int offset, int finalDelay); + + diff --git a/device/gxx-linux/motor_run/MotorConfig.cpp b/device/gxx-linux/motor_run/MotorConfig.cpp new file mode 100644 index 0000000..102d038 --- /dev/null +++ b/device/gxx-linux/motor_run/MotorConfig.cpp @@ -0,0 +1,195 @@ +#include "MotorConfig.h" +#include +#include +#include +#include + +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 ¶m) +{ + 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 MotorConfig::GetMotorSpeedParams(bool bzouzhi, MTBDType mttype) +{ + std::vector 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++) + { + MotorSpeedParamEx param; + for (int k = 1; k < 4; k++) + { + // //float ratio = k == 1 ? 1 : (k == 2 ? 1.51 : 2.81); + // param.mt_param.finalPeriod = s >= 2 ? 586500 / 4 : 586500; // s < 2 drv888 + // //param.mt_param.finalPeriod = s >= 2 ? 2000 / 4 : 2000; // 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 = 7; + // param.mt_param.finalDelay = 2500; + // param.mt_param.acceleration_time = 2; + // param.speed = i; // 0 gray 1 color + // param.dpi = k; // 1 200dpi 2 300dpi 3 600dpi + // param.sp = 1200; + for(int t = 0;t<2;t++) + { + //param.colormode = t; + param = m_motor_params[s*30+(i-1)*6+(k-1)*2+t]; + 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; + } + } + } +} + +void MotorConfig::reset_json(){ + // for(int i =0;i MotorConfig::GetMotorSpeedParams(const std::string& json_str) +{ + std::vector ret; + if(json_str.length()) + { + json j = json::parse(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; +} + +void MotorConfig::to_json(MotorSpeedParamEx ¶m, 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 ¶m) +{ + j.at("A").get_to(param.mt_param.a); + j.at("FINALDELAY").get_to(param.mt_param.finalDelay); + j.at("FINALPERIOD").get_to(param.mt_param.finalPeriod); + j.at("FMIN").get_to(param.mt_param.Fmin); + j.at("OFFSET").get_to(param.mt_param.offset); + j.at("STEPNUM").get_to(param.mt_param.stepnum); + j.at("DPI").get_to(param.dpi); + j.at("ACCELERATIONTIME").get_to(param.mt_param.acceleration_time); + j.at("COLORMODE").get_to(param.colormode); + j.at("SPEED").get_to(param.speed), + j.at("SP").get_to(param.sp); +} \ No newline at end of file diff --git a/device/gxx-linux/motor_run/MotorConfig.h b/device/gxx-linux/motor_run/MotorConfig.h new file mode 100644 index 0000000..bf0f96d --- /dev/null +++ b/device/gxx-linux/motor_run/MotorConfig.h @@ -0,0 +1,367 @@ +#pragma once +#include +#include "json.hpp" +#include +#include + +using json= nlohmann::json; + +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; +}; + + + + +#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 +#ifdef G300 + +static std::vector m_motor_params{ + //drv_888 + {{.finalPeriod = 754200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 1,.sp = 5910},//40 ppm 搓纸 + {{.finalPeriod = 754200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 1,.sp = 1970}, + {{.finalPeriod = 804300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 2,.sp = 3942}, + {{.finalPeriod = 804300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 2,.sp = 1314}, + {{.finalPeriod = 804300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 3,.sp = 3942}, + {{.finalPeriod = 804300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 3,.sp = 1314}, + + {{.finalPeriod = 705300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 1,.sp = 4509},//50 ppm 搓纸 + {{.finalPeriod = 705300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 1,.sp = 1503}, + {{.finalPeriod = 705300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 2,.sp = 3009}, + {{.finalPeriod = 705300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 2,.sp = 1003}, + {{.finalPeriod = 705300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 3,.sp = 3009}, + {{.finalPeriod = 705300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 3,.sp = 1003}, + + {{.finalPeriod = 656200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 1,.sp = 3702},//60 ppm 搓纸 + {{.finalPeriod = 656200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 1,.sp = 1234}, + {{.finalPeriod = 656300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 2,.sp = 2446}, + {{.finalPeriod = 656300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 2,.sp = 822}, + {{.finalPeriod = 656300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 3,.sp = 2446}, + {{.finalPeriod = 656300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 3,.sp = 822}, + + {{.finalPeriod = 527200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 1,.sp = 3129},//70 ppm 搓纸 + {{.finalPeriod = 527200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 1,.sp = 1043}, + {{.finalPeriod = 527300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 2,.sp = 2446}, + {{.finalPeriod = 527300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 2,.sp = 859}, + {{.finalPeriod = 527300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 3,.sp = 2446}, + {{.finalPeriod = 527300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 3,.sp = 859}, + + {{.finalPeriod = 527200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 1,.sp = 3129},//80 ppm 搓纸 + {{.finalPeriod = 527200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 1,.sp = 1043}, + {{.finalPeriod = 527300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 2,.sp = 2446}, + {{.finalPeriod = 527300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 2,.sp = 859}, + {{.finalPeriod = 527300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 3,.sp = 2446}, + {{.finalPeriod = 527300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 3,.sp = 859}, + + {{.finalPeriod = 504200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 1,.sp = 5910},//40 ppm 走纸 + {{.finalPeriod = 504200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 1,.sp = 1970}, + {{.finalPeriod = 504300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 2,.sp = 3942}, + {{.finalPeriod = 504300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 2,.sp = 1314}, + {{.finalPeriod = 504300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 3,.sp = 3942}, + {{.finalPeriod = 504300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 3,.sp = 1314}, + + {{.finalPeriod = 385300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 1,.sp = 4509},//50 ppm 走纸 + {{.finalPeriod = 385300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 1,.sp = 1503}, + {{.finalPeriod = 385300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 2,.sp = 3009}, + {{.finalPeriod = 385300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 2,.sp = 1003}, + {{.finalPeriod = 385300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 3,.sp = 3009}, + {{.finalPeriod = 385300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 3,.sp = 1003}, + + {{.finalPeriod = 316200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 1,.sp = 3702},//60 ppm 走纸 + {{.finalPeriod = 316200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 1,.sp = 1234}, + {{.finalPeriod = 316300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 2,.sp = 2466}, + {{.finalPeriod = 316300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 2,.sp = 822}, + {{.finalPeriod = 316300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 3,.sp = 2466}, + {{.finalPeriod = 316300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 3,.sp = 822}, + + {{.finalPeriod = 267200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 1,.sp = 3129},//70 ppm 走纸 + {{.finalPeriod = 267200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 1,.sp = 1043}, + {{.finalPeriod = 316300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 2,.sp = 2466}, + {{.finalPeriod = 316300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 2,.sp = 822}, + {{.finalPeriod = 316300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 3,.sp = 2466}, + {{.finalPeriod = 316300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 3,.sp = 822}, + + {{.finalPeriod = 267200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 1,.sp = 3129},//80 ppm 走纸 + {{.finalPeriod = 267200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 1,.sp = 1043}, + {{.finalPeriod = 316300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 2,.sp = 2466}, + {{.finalPeriod = 316300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 2,.sp = 822}, + {{.finalPeriod = 316300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 3,.sp = 2466}, + {{.finalPeriod = 316300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 3,.sp = 822}, + + //tmc + {{.finalPeriod = 184200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 1,.sp = 5814},//40 ppm 搓纸 + {{.finalPeriod = 184200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 1,.sp = 1938}, + {{.finalPeriod = 204300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 2,.sp = 3879}, + {{.finalPeriod = 204300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 2,.sp = 1293}, + {{.finalPeriod = 204300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 3,.sp = 3879}, + {{.finalPeriod = 204300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 3,.sp = 1293}, + + {{.finalPeriod = 185200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 1,.sp = 4455},//50 ppm 搓纸 + {{.finalPeriod = 185200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 1,.sp = 1485}, + {{.finalPeriod = 185200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 2,.sp = 2975}, + {{.finalPeriod = 185200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 2,.sp = 991}, + {{.finalPeriod = 185200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 3,.sp = 2972}, + {{.finalPeriod = 185200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 3,.sp = 991}, + + {{.finalPeriod = 166200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 1,.sp = 3570},//60 ppm 搓纸 + {{.finalPeriod = 166200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 1,.sp = 1190}, + {{.finalPeriod = 166300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 2,.sp = 2445}, + {{.finalPeriod = 166300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 2,.sp = 815}, + {{.finalPeriod = 166300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 3,.sp = 2445}, + {{.finalPeriod = 166300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 3,.sp = 815}, + + {{.finalPeriod = 137200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 1,.sp = 3126},//70 ppm 搓纸 + {{.finalPeriod = 137200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 1,.sp = 1042}, + {{.finalPeriod = 166300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 2,.sp = 2445}, + {{.finalPeriod = 166300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 2,.sp = 815}, + {{.finalPeriod = 166300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 3,.sp = 2445}, + {{.finalPeriod = 166300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 3,.sp = 815}, + + {{.finalPeriod = 137200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 1,.sp = 3126},//80 ppm 搓纸 + {{.finalPeriod = 137200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 1,.sp = 1042}, + {{.finalPeriod = 166300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 2,.sp = 2445}, + {{.finalPeriod = 166300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 2,.sp = 815}, + {{.finalPeriod = 166300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 3,.sp = 2445}, + {{.finalPeriod = 166300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 3,.sp = 815}, + + {{.finalPeriod = 124200, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 1,.sp = 5814},//40 ppm 走纸 + {{.finalPeriod = 124200, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 1,.sp = 1938}, + {{.finalPeriod = 124300, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 2,.sp = 3879}, + {{.finalPeriod = 124300, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 2,.sp = 1293}, + {{.finalPeriod = 124300, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 3,.sp = 3879}, + {{.finalPeriod = 124300, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 3,.sp = 1293}, + + {{.finalPeriod = 95200, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 1,.sp = 4455},//50 ppm 走纸 + {{.finalPeriod = 95200, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 1,.sp = 1485}, + {{.finalPeriod = 95200, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 2,.sp = 2975}, + {{.finalPeriod = 95200, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 2,.sp = 991}, + {{.finalPeriod = 95200, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 3,.sp = 2975}, + {{.finalPeriod = 95200, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 3,.sp = 991}, + + {{.finalPeriod = 76200, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 1,.sp = 3570},//60 ppm 走纸 + {{.finalPeriod = 76200, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 1,.sp = 1190}, + {{.finalPeriod = 78300, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 2,.sp = 2445}, + {{.finalPeriod = 78300, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 2,.sp = 815}, + {{.finalPeriod = 78300, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 3,.sp = 2445}, + {{.finalPeriod = 78300, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 3,.sp = 815}, + + {{.finalPeriod = 66720, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 1,.sp = 3126},//70 ppm 走纸 + {{.finalPeriod = 66720, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 1,.sp = 1042}, + {{.finalPeriod = 78300, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 2,.sp = 2445}, + {{.finalPeriod = 78300, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 2,.sp = 815}, + {{.finalPeriod = 78300, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 3,.sp = 2445}, + {{.finalPeriod = 78300, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 3,.sp = 815}, + + {{.finalPeriod = 66720, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 1,.sp = 3126},//80 ppm 走纸 + {{.finalPeriod = 66720, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 1,.sp = 1042}, + {{.finalPeriod = 78300, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 2,.sp = 2445}, + {{.finalPeriod = 78300, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 2,.sp = 815}, + {{.finalPeriod = 78300, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 3,.sp = 2445}, + {{.finalPeriod = 78300, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 3,.sp = 815}, +}; +#else + +static std::vector m_motor_params{ + //drv_888 + {{.finalPeriod = 754200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 1,.sp = 7290},//40 ppm 搓纸 + {{.finalPeriod = 754200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 1,.sp = 2430}, + {{.finalPeriod = 804300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 2,.sp = 4869}, + {{.finalPeriod = 804300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 2,.sp = 1623}, + {{.finalPeriod = 1006000, .Fmin = 1407500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 3000, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 3,.sp = 4749}, + {{.finalPeriod = 1006000, .Fmin = 1407500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 3000, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 3,.sp = 1583}, + + {{.finalPeriod = 735200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 1,.sp = 5870},//50 ppm 搓纸 + {{.finalPeriod = 735200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 1,.sp = 1950}, + {{.finalPeriod = 735300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 2,.sp = 3909}, + {{.finalPeriod = 735300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 2,.sp = 1303}, + {{.finalPeriod = 1006000, .Fmin = 1407500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 3000, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 3,.sp = 4749}, + {{.finalPeriod = 1006000, .Fmin = 1407500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 3000, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 3,.sp = 1583}, + + {{.finalPeriod = 686200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 1,.sp = 5004},//60 ppm 搓纸 + {{.finalPeriod = 686200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 1,.sp = 1688}, + {{.finalPeriod = 706300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 2,.sp = 3248}, + {{.finalPeriod = 706300, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 2,.sp = 1080}, + {{.finalPeriod = 1006000, .Fmin = 1407500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 3000, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 3,.sp = 4749}, + {{.finalPeriod = 1006000, .Fmin = 1407500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 3000, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 3,.sp = 1583}, + + {{.finalPeriod = 527200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 1,.sp = 3864},//70 ppm 搓纸 + {{.finalPeriod = 527200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 1,.sp = 1287}, + {{.finalPeriod = 527200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 2,.sp = 2580}, + {{.finalPeriod = 527200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 2,.sp = 859}, + {{.finalPeriod = 1006000, .Fmin = 1407500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 3000, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 3,.sp = 4749}, + {{.finalPeriod = 1006000, .Fmin = 1407500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 3000, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 3,.sp = 1583}, + + {{.finalPeriod = 508200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 1,.sp = 3735},//80 ppm 搓纸 + {{.finalPeriod = 508200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 1,.sp = 1245}, + {{.finalPeriod = 508200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 2,.sp = 2490}, + {{.finalPeriod = 508200, .Fmin = 1407500, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 2,.sp = 830}, + {{.finalPeriod = 1006000, .Fmin = 1407500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 3000, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 3,.sp = 4749}, + {{.finalPeriod = 1006000, .Fmin = 1407500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 3000, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 3,.sp = 1583}, + + {{.finalPeriod = 504200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 1,.sp = 7290},//40 ppm 走纸 + {{.finalPeriod = 504200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 1,.sp = 2430}, + {{.finalPeriod = 504300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 2,.sp = 4869}, + {{.finalPeriod = 504300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 2,.sp = 1623}, + {{.finalPeriod = 656000, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 7, .finalDelay = 3000, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 3,.sp = 4749}, + {{.finalPeriod = 656000, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 7, .finalDelay = 3000, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 3,.sp = 1583}, + + {{.finalPeriod = 385200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 1,.sp = 6050},//50 ppm 走纸 + {{.finalPeriod = 405200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 1,.sp = 1950}, + {{.finalPeriod = 405300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 2,.sp = 3909}, + {{.finalPeriod = 405300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 2,.sp = 1303}, + {{.finalPeriod = 656000, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 7, .finalDelay = 3000, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 3,.sp = 4749}, + {{.finalPeriod = 656000, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 7, .finalDelay = 3000, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 3,.sp = 1583}, + + {{.finalPeriod = 346200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 1,.sp = 5004},//60 ppm 走纸 + {{.finalPeriod = 346200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 1,.sp = 1688}, + {{.finalPeriod = 336300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 2,.sp = 3248}, + {{.finalPeriod = 336300, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 2,.sp = 1080}, + {{.finalPeriod = 656000, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 7, .finalDelay = 3000, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 3,.sp = 4749}, + {{.finalPeriod = 656000, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 7, .finalDelay = 3000, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 3,.sp = 1583}, + + {{.finalPeriod = 267200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 1,.sp = 3864},//70 ppm 走纸 + {{.finalPeriod = 267200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 1,.sp = 1287}, + {{.finalPeriod = 267200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 2,.sp = 2580}, + {{.finalPeriod = 267200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 2,.sp = 859}, + {{.finalPeriod = 656000, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 7, .finalDelay = 3000, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 3,.sp = 4749}, + {{.finalPeriod = 656000, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 7, .finalDelay = 3000, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 3,.sp = 1583}, + + {{.finalPeriod = 258200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 1,.sp = 3735},//80 ppm 走纸 + {{.finalPeriod = 258200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 1,.sp = 1245}, + {{.finalPeriod = 258200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 2,.sp = 2490}, + {{.finalPeriod = 258200, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2000, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 2,.sp = 830}, + {{.finalPeriod = 656000, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 7, .finalDelay = 3000, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 3,.sp = 4749}, + {{.finalPeriod = 656000, .Fmin = 1607500, .stepnum = 30, .a = 200, .offset = 7, .finalDelay = 3000, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 3,.sp = 1583}, + + //tmc + {{.finalPeriod = 184200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 1,.sp = 7200},//40 ppm 搓纸 + {{.finalPeriod = 184200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 1,.sp = 2400}, + {{.finalPeriod = 204300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 2,.sp = 4800}, + {{.finalPeriod = 204300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 2,.sp = 1598}, + {{.finalPeriod = 251600, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 3,.sp = 4760}, + {{.finalPeriod = 251600, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 3,.sp = 1586}, + + {{.finalPeriod = 185200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 1,.sp = 6050},//50 ppm 搓纸 + {{.finalPeriod = 185200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 1,.sp = 2026}, + {{.finalPeriod = 185200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 2,.sp = 4053}, + {{.finalPeriod = 185200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 2,.sp = 1350}, + {{.finalPeriod = 251600, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 3,.sp = 4760}, + {{.finalPeriod = 251600, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 3,.sp = 1586}, + + {{.finalPeriod = 176200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 1,.sp = 4978},//60 ppm 搓纸 + {{.finalPeriod = 176200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 1,.sp = 1659}, + {{.finalPeriod = 176300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 2,.sp = 3330}, + {{.finalPeriod = 176300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 2,.sp = 1110}, + {{.finalPeriod = 251600, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 3,.sp = 4760}, + {{.finalPeriod = 251600, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 3,.sp = 1586}, + + {{.finalPeriod = 137200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 1,.sp = 3858},//70 ppm 搓纸 + {{.finalPeriod = 137200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 1,.sp = 1286}, + {{.finalPeriod = 137300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 2,.sp = 2570}, + {{.finalPeriod = 137300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 2,.sp = 857}, + {{.finalPeriod = 251600, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 3,.sp = 4760}, + {{.finalPeriod = 251600, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 3,.sp = 1586}, + + {{.finalPeriod = 128200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 1,.sp = 3750},//80 ppm 搓纸 + {{.finalPeriod = 128200, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 1,.sp = 1250}, + {{.finalPeriod = 128300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 2,.sp = 2498}, + {{.finalPeriod = 128300, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 2,.sp = 832}, + {{.finalPeriod = 251600, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 3,.sp = 4760}, + {{.finalPeriod = 251600, .Fmin = 351875, .stepnum = 30, .a = 150, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 3,.sp = 1586}, + + {{.finalPeriod = 124200, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 1,.sp = 7200},//40 ppm 走纸 + {{.finalPeriod = 124200, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 1,.sp = 2400}, + {{.finalPeriod = 124300, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 2,.sp = 4800}, + {{.finalPeriod = 124300, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 2,.sp = 1598}, + {{.finalPeriod = 164600, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 0,.dpi = 3,.sp = 4760}, + {{.finalPeriod = 164600, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 1,.colormode = 1,.dpi = 3,.sp = 1586}, + + {{.finalPeriod = 105200, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 1,.sp = 6050},//50 ppm 走纸 + {{.finalPeriod = 105200, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 1,.sp = 2026}, + {{.finalPeriod = 105200, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 2,.sp = 4053}, + {{.finalPeriod = 105200, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 2,.sp = 1350}, + {{.finalPeriod = 164600, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 0,.dpi = 3,.sp = 4760}, + {{.finalPeriod = 164600, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 2,.colormode = 1,.dpi = 3,.sp = 1586}, + + {{.finalPeriod = 86200, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 1,.sp = 4978},//60 ppm 走纸 + {{.finalPeriod = 86200, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 1,.sp = 1659}, + {{.finalPeriod = 86300, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 2,.sp = 3330}, + {{.finalPeriod = 86300, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 2,.sp = 1110}, + {{.finalPeriod = 164600, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 0,.dpi = 3,.sp = 4760}, + {{.finalPeriod = 164600, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 3,.colormode = 1,.dpi = 3,.sp = 1586}, + + {{.finalPeriod = 66720, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 1,.sp = 3858},//70 ppm 走纸 + {{.finalPeriod = 66720, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 1,.sp = 1286}, + {{.finalPeriod = 66730, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 2,.sp = 2572}, + {{.finalPeriod = 66730, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 2,.sp = 857}, + {{.finalPeriod = 164600, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 0,.dpi = 3,.sp = 4760}, + {{.finalPeriod = 164600, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 4,.colormode = 1,.dpi = 3,.sp = 1586}, + + {{.finalPeriod = 64820, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 1,.sp = 3750},//80 ppm 走纸 + {{.finalPeriod = 64820, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 1,.sp = 1250}, + {{.finalPeriod = 64830, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 2,.sp = 2498}, + {{.finalPeriod = 64830, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 2,.sp = 832}, + {{.finalPeriod = 164600, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 0,.dpi = 3,.sp = 4760}, + {{.finalPeriod = 164600, .Fmin = 401875, .stepnum = 30, .a = 200, .offset = 9, .finalDelay = 2500, .acceleration_time =2},.speed = 5,.colormode = 1,.dpi = 3,.sp = 1586}, +}; +#endif + + +class MotorConfig +{ +private: + std::vector m_cuoParams; + std::vector m_zouParams; + const std::vector 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 + }; + MotorConfig(/* args */); + ~MotorConfig(); + std::string GetParams(bool bzouzhi,MTBDType mttype); + void SetParams(bool bzouzhi,MTBDType mttype,MotorSpeedParamEx& param); + std::vector GetMotorSpeedParams(bool bzouzhi,MTBDType mttype); + std::vector GetMotorSpeedParams(const std::string& json_str); + void to_json(MotorSpeedParamEx& param,json& j); + void from_json(json& j,MotorSpeedParamEx& param); + void reset_json(); +private: + void initconfigfile(); + +}; + diff --git a/device/gxx-linux/motor_run/MotorControl.cpp b/device/gxx-linux/motor_run/MotorControl.cpp new file mode 100644 index 0000000..42b9dfc --- /dev/null +++ b/device/gxx-linux/motor_run/MotorControl.cpp @@ -0,0 +1,60 @@ +#pragma once + +#include "CuoZhiMotor.h" +#include "ZouZhiMotor.h" +#include "MotorControl.h" + +MotorControl::MotorControl() +{ + m_zzm.reset(new ZouZhiMotor()); + m_czm.reset(new CuoZhiMotor()); + //m_czm->reset(); +} +MotorControl::~MotorControl() +{ + m_zzm->stop(); + m_czm->stop(); + m_czm.reset(); + m_zzm.reset(); +} +void MotorControl::MotorRun(MotorOption option) +{ + switch (option) + { + case MotorOption::CZ_Reset : + m_czm->reset(); + break; + case MotorOption::CZ_Forward : + m_czm->forward(); + break; + case MotorOption::CZ_Backward : + m_czm->backward(); + break; + case MotorOption::CZ_Pause: + m_czm->pause(); + break; + case MotorOption::CZ_Stop : + m_czm->stop(); + break; + case MotorOption::ZZ_Backward : + m_zzm->setDirection(1); + m_zzm->start(); + break; + case MotorOption::ZZ_Forward : + m_zzm->setDirection(0); + m_zzm->start(); + break; + case MotorOption::ZZ_Stop : + m_zzm->stop(); + break; + default: + break; + } +} + +void MotorControl::setzzspeed(int zuo_spmode,int dpi,int iscolor){ + m_zzm->speedChange(zuo_spmode,dpi,iscolor); +} +void MotorControl::setczspeed(int cuo_spmode,int dpi,int iscolor){ + m_czm->speedChange(cuo_spmode,dpi,iscolor); +} diff --git a/device/gxx-linux/motor_run/MotorControl.h b/device/gxx-linux/motor_run/MotorControl.h new file mode 100644 index 0000000..9111b90 --- /dev/null +++ b/device/gxx-linux/motor_run/MotorControl.h @@ -0,0 +1,28 @@ +#pragma once +class CuoZhiMotor; +class ZouZhiMotor; +struct MotorSpeedParam; + + +class MotorControl +{ +public: + enum MotorOption : int{ + CZ_Reset, + CZ_Forward, + CZ_Backward, + CZ_Pause, + CZ_Stop, + ZZ_Forward, + ZZ_Backward, + ZZ_Stop, + }; + MotorControl(); + ~MotorControl(); + void setzzspeed(int zuo_spmode,int dpi,int iscolor); + void setczspeed(int cuo_spmode,int dpi,int iscolor); + void MotorRun(MotorOption option); +private: + std::unique_ptr m_czm; + std::unique_ptr m_zzm; +}; diff --git a/device/gxx-linux/motor_run/Pwm.cpp b/device/gxx-linux/motor_run/Pwm.cpp new file mode 100644 index 0000000..2125069 --- /dev/null +++ b/device/gxx-linux/motor_run/Pwm.cpp @@ -0,0 +1,40 @@ +#include "Pwm.h" +#include "DevUtil.h" +#include + +#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()); + printf("Pwm::Pwm(int port = %d)\n",port); +} + +Pwm::~Pwm() +{ + std::cout << "Pwm::~Pwm()" << std::endl; +} + +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); +} diff --git a/device/gxx-linux/motor_run/Pwm.h b/device/gxx-linux/motor_run/Pwm.h new file mode 100644 index 0000000..c31bfbf --- /dev/null +++ b/device/gxx-linux/motor_run/Pwm.h @@ -0,0 +1,22 @@ +#pragma once +#include +#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"; +}; \ No newline at end of file diff --git a/device/gxx-linux/motor_run/ZouZhiMotor.cpp b/device/gxx-linux/motor_run/ZouZhiMotor.cpp new file mode 100644 index 0000000..c497615 --- /dev/null +++ b/device/gxx-linux/motor_run/ZouZhiMotor.cpp @@ -0,0 +1,48 @@ +#include "ZouZhiMotor.h" +#include +#include + +ZouZhiMotor::ZouZhiMotor() : Motor(motorPorts_Zouzhi) +{ + speedChange(0,1,1); + if(Dail().GetValue().dails.in_voltage4 == 0) + m_mttype = MotorConfig::MTBDType::MT_DRV; + else + m_mttype = MotorConfig::MTBDType::MT_TMC; +} + +ZouZhiMotor::~ZouZhiMotor() +{ + std::cout << "ZouZhiMotor::~ZouZhiMotor()" << std::endl; +} + +void ZouZhiMotor::start() +{ + Motor::start(delays, mspZhouzhi); +} + +void ZouZhiMotor::speedChange(int speed,int dpi ,int iscolor) +{ + // if(zouZhiFinalDelay.find(dpi)==zouZhiFinalDelay.end()) + // dpi = 1; + // m_speedmode = speed; + // printf(" \n speed %d",speed); + // mspZhouzhi = { .finalPeriod = zouZhiFinalPeriod.at(dpi)[m_speedmode],.Fmin = zouZhiFmin.at(dpi)[m_speedmode],.stepnum = zouZhiStepNum.at(dpi)[m_speedmode],.a = zouZhiA.at(dpi)[m_speedmode], + // .offset = zouZhiOffset.at(dpi)[m_speedmode],.finalDelay = zouZhiFinalDelay.at(dpi)[m_speedmode] }; + // std::cout<< ".finalPeriod = "< delays; + MotorSpeedParam mspZhouzhi; + MotorConfig m_cfg; + int m_speedmode; + + const std::map> zouZhiFinalPeriod ={ + {1,{ 586500,420500,330000,245000,205000 }}, + {2,{ 916500,656500,530500,386500,347000 }}, + {3,{ 756500,756500,756500,756500,756500 }}, + };//756500,556500,426500,336500,286500,230500 //265000 + const std::map> zouZhiFmin ={ + {1,{ 1607750,1607750,1607750,1607750,1607750 }}, + {2,{ 1607750,1607750,1607750,1607750,1607750 }}, + {3,{ 1607750,1607750,1607750,1607750,1607750 }}, + };//1607750,1607750,1607750,1607750,1607750,1607750 + const std::map> zouZhiStepNum ={ + { 1, { 23,23,30,30,30 }}, + { 2, { 30,30,30,30,30 }}, + { 3, { 30,30,30,30,30 }}, + }; + const std::map> zouZhiA = { + {1,{ 200,200,200,200,200 }}, + {2,{ 200,200,200,200,200 }}, + {3,{ 200,200,200,200,200 }}, + }; + const std::map> zouZhiOffset = { + {1,{ 7,7,7,7,9 }}, + {2,{ 7,7,7,7,7 }}, + {3,{ 7,7,7,7,7 }}, + }; + const std::map> zouZhiFinalDelay = { + {1,{ 2500,2500,2500,2500,2500 }}, + {2,{ 2500,2500,2500,2500,2500 }}, + {3,{ 2500,2500,2500,2500,2500 }}, + }; +}; + + + diff --git a/device/gxx-linux/motor_run/main.cpp b/device/gxx-linux/motor_run/main.cpp new file mode 100644 index 0000000..4bb4863 --- /dev/null +++ b/device/gxx-linux/motor_run/main.cpp @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include +#include +#include +#include "DevUtil.h" +#include "Pwm.h" +#include "ZouZhiMotor.h" +#include "CuoZhiMotor.h" + + +int main(int argc,char **argv) { + + //DeviceExport(); /*类里面的构造函数可以直接调用*/ + DeviceExport d1; + ZouZhiMotor zzm; + CuoZhiMotor czm; + std::string instring; + do { + printf("1.cuozhi motor reset\n"); + printf("2.cuozhi motor forward\n"); + printf("3.cuozhi motor reverse\n"); + printf("4.cuozhi motor stop\n"); + printf("5.zouzhi motor forward\n"); + printf("6.zouzhi motor reverse\n"); + printf("7.zouzhi motor stop\n"); + printf(":"); + std::getline(std::cin, instring); + if (instring == "1") { + czm.reset(); + } + if (instring == "2") { + czm.forward(); + } + if (instring == "3") { + czm.backward(); + } + if (instring == "4") { + czm.stop(); + } + if (instring == "5") { + zzm.setDirection(0); + zzm.start(); + } + if (instring == "6") { + zzm.setDirection(1); + zzm.start(); + } + if (instring == "7") { + zzm.stop(); + } + }while(1); + return 0; +} diff --git a/device/gxx-linux/motor_run/xmake.lua b/device/gxx-linux/motor_run/xmake.lua new file mode 100644 index 0000000..68a3eeb --- /dev/null +++ b/device/gxx-linux/motor_run/xmake.lua @@ -0,0 +1,89 @@ +add_rules("mode.debug", "mode.release") + +target("motor_run") + set_kind("static") + add_files("Motor.cpp") + add_files("DevUtil.cpp") + add_files("ZouZhiMotor.cpp") + add_files("CuoZhiMotor.cpp") + add_files("Gpio.cpp") + add_files("Pwm.cpp") + add_files("MotorControl.cpp") + add_files("MotorConfig.cpp") + add_includedirs(".", { public = true}) + add_includedirs("../packages/common.pkg/include", { public = true}) + --add_packages("common") +target("main") + set_kind("binary") + add_files("main.cpp") + add_deps("motor_run") + +-- +-- If you want to known more usage about xmake, please see https://xmake.io +-- +-- ## FAQ +-- +-- You can enter the project directory firstly before building project. +-- +-- $ cd projectdir +-- +-- 1. How to build project? +-- +-- $ xmake +-- +-- 2. How to configure project? +-- +-- $ xmake f -p [macosx|linux|iphoneos ..] -a [x86_64|i386|arm64 ..] -m [debug|release] +-- +-- 3. Where is the build output directory? +-- +-- The default output directory is `./build` and you can configure the output directory. +-- +-- $ xmake f -o outputdir +-- $ xmake +-- +-- 4. How to run and debug target after building project? +-- +-- $ xmake run [targetname] +-- $ xmake run -d [targetname] +-- +-- 5. How to install target to the system directory or other output directory? +-- +-- $ xmake install +-- $ xmake install -o installdir +-- +-- 6. Add some frequently-used compilation flags in xmake.lua +-- +-- @code +-- -- add debug and release modes +-- add_rules("mode.debug", "mode.release") +-- +-- -- add macro defination +-- add_defines("NDEBUG", "_GNU_SOURCE=1") +-- +-- -- set warning all as error +-- set_warnings("all", "error") +-- +-- -- set language: c99, c++11 +-- set_languages("c99", "c++11") +-- +-- -- set optimization: none, faster, fastest, smallest +-- set_optimize("fastest") +-- +-- -- add include search directories +-- add_includedirs("/usr/include", "/usr/local/include") +-- +-- -- add link libraries and search directories +-- add_links("tbox") +-- add_linkdirs("/usr/local/lib", "/usr/lib") +-- +-- -- add system link libraries +-- add_syslinks("z", "pthread") +-- +-- -- add compilation and link flags +-- add_cxflags("-stdnolib", "-fno-strict-aliasing") +-- add_ldflags("-L/usr/local/lib", "-lpthread", {force = true}) +-- +-- @endcode +-- + diff --git a/device/gxx-linux/motorboard/Imotorboard.cpp b/device/gxx-linux/motorboard/Imotorboard.cpp new file mode 100644 index 0000000..134f59c --- /dev/null +++ b/device/gxx-linux/motorboard/Imotorboard.cpp @@ -0,0 +1,16 @@ +#include +#include "Imotorboard.h" +#include "PinMonitor.h" +#include "uartregsaccess.h" +#include +#include "stringex.hpp" +#include "config.h" +#include "StopWatch.h" +#include "applog.h" +#include "Capturer.h" + +IMotorBoard::IMotorBoard() : mb_ev_cb_(std::function()) +{} +IMotorBoard::~IMotorBoard(){ + +} diff --git a/device/gxx-linux/motorboard/Imotorboard.h b/device/gxx-linux/motorboard/Imotorboard.h new file mode 100644 index 0000000..bf3b4fe --- /dev/null +++ b/device/gxx-linux/motorboard/Imotorboard.h @@ -0,0 +1,98 @@ +#pragma once +#include +#include +#include +#include +#include "autoevent.hpp" +#include "commondef.h" +#include "Led.h" +#include "StopWatch.h" +#include "ThreadPool.h" + +class IRegsAccess; +class PinMonitor; +class Gpio; +class ICapturer; + +#include "../usb/src/common/packet.h" + + +class IMotorBoard{ +public: + IMotorBoard(); + virtual ~IMotorBoard(); + virtual void start() = 0; + virtual void stop() = 0; + virtual void clear_error() = 0; + virtual void pick_paper() = 0; + virtual void stop_pick_paper() = 0; + virtual int os_mode() = 0; + virtual bool paper_ready() = 0; + virtual bool is_converopen() = 0; + virtual bool is_scanning() = 0; + virtual bool is_jam() = 0; + virtual int paper_counter() = 0; + virtual bool set_long_paper(bool enable) = 0; + virtual bool set_double_inpect(bool enable) = 0; + virtual bool set_staple_inpect(bool enable) = 0; + virtual bool set_auto_paper(bool enable) = 0; + virtual bool set_color_mode(int mode) = 0; + virtual int get_speed_mode() = 0; + virtual bool set_speed_mode(int mode,int dpi,int iscolor) = 0; + virtual bool set_screw_inpect(bool enable) = 0; + virtual bool get_screw_inpect() = 0; + virtual bool set_screw_level(int level) = 0; + virtual int get_screw_level() = 0; + virtual bool wait_paper_out(int timeout_ms) = 0; + virtual bool wait_paper_in(int timeout_ms) = 0; + virtual bool read(unsigned int addr, unsigned int &val) = 0; + virtual bool write(unsigned int addr, unsigned int val) = 0; + virtual bool set_cuospeed(unsigned int speed,uint dpi,uint iscolor) = 0; + virtual void set_callbacks(MotorBoardGlue glue) = 0; + virtual bool get_keeplastpaper() = 0; + virtual std::shared_ptr regs() = 0; + virtual void set_capture(std::shared_ptr cap) = 0; + virtual void motor_reset() = 0; + virtual void LedControlOption(HG_LedOption option,uint32_t time) = 0; + virtual void clean_paper_road() = 0; + + void set_error(int value){ + mb_error = value; + } + void set_scancap(GScanCap cap) + { + m_scancap = cap; + } + void set_motorboard_event_callback(std::function cb) + { + mb_ev_cb_ = cb; + } + + static scanner_status scanner_status_from_raw(int raw) + { + switch(raw) + { + case 1: + return SCANNER_STATUS_PAPER_JAMMED; + case 2: + return SCANNER_STATUS_NO_PAPER; + case 4: + return SCANNER_STATUS_COVER_OPENNED; + case 0x20: + return SCANNER_STATUS_DOUBLE_FEEDED; + case 0x2000000: + return SCANNER_STATUS_PAPER_ON; + case 0x4000000: + return SCANNER_STATUS_COVER_CLOSED; + case 0: + default: + return SCANNER_STATUS_READY; // jam has resolved + } + } + +protected: + volatile int mb_error = 0; + GScanCap m_scancap; + + std::function mb_ev_cb_; +}; \ No newline at end of file diff --git a/device/gxx-linux/motorboard/Led.cpp b/device/gxx-linux/motorboard/Led.cpp new file mode 100644 index 0000000..577fc41 --- /dev/null +++ b/device/gxx-linux/motorboard/Led.cpp @@ -0,0 +1,95 @@ +#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); +} + + +LedControl::LedControl():m_led_green(Led("green")),m_led_red(Led("red")),m_led_white(Led("white")){ +} +LedControl::~LedControl(){ + option(HG_LedOption::HG_OFF_ALL,0); +} + +HG_LedOption LedControl::get_state(){ + return m_state; +} +void LedControl::option(HG_LedOption option,uint32_t time){ + m_state = option; + switch (option) + { + case HG_LedOption::HG_OFF_ALL: + m_led_red.off(); + m_led_green.off(); + m_led_white.off(); + break; + case HG_LedOption::HG_ON_ALL: + m_led_green.on(time); + m_led_red.on(time); + m_led_white.on(time); + break; + case HG_LedOption::HG_RED_ON: + m_led_red.on(time); + m_led_green.off(); + m_led_white.off(); + break; + case HG_LedOption::HG_GREEN_ON: + m_led_green.on(time); + m_led_red.off(); + m_led_white.off(); + break; + case HG_LedOption::HG_WHITE_ON: + m_led_red.off(); + m_led_green.off(); + m_led_white.on(time); + break; + case HG_LedOption::HG_RED_WHITR_ON: + m_led_green.off(); + m_led_red.on(time); + m_led_white.on(time); + break; + case HG_LedOption::HG_RED_GREEN_ON: + m_led_red.on(time); + m_led_green.on(time); + m_led_white.off(); + break; + case HG_LedOption::HG_GREEN_WHITR_ON: + m_led_green.on(time); + m_led_red.off(); + m_led_white.on(time); + break; + default: + break; + } +} diff --git a/device/gxx-linux/motorboard/Led.h b/device/gxx-linux/motorboard/Led.h new file mode 100644 index 0000000..054ca82 --- /dev/null +++ b/device/gxx-linux/motorboard/Led.h @@ -0,0 +1,50 @@ +#pragma once +#include "DevUtil.h" +#include "stringex.hpp" + +enum HG_LedOption : uint8_t{ + HG_OFF_ALL = 0, + HG_RED_ON, + HG_GREEN_ON, + HG_WHITE_ON, + HG_RED_GREEN_ON, + HG_RED_WHITR_ON, + HG_GREEN_WHITR_ON, + HG_ON_ALL, +}; + +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"; +}; + +class LedControl{ +public: + + LedControl(); + ~LedControl(); + void option(HG_LedOption option,uint32_t time = 0); + HG_LedOption get_state(); + +private: + Led m_led_red; + Led m_led_green; + Led m_led_white; + HG_LedOption m_state; +}; diff --git a/device/gxx-linux/motorboard/motorboard.cpp b/device/gxx-linux/motorboard/motorboard.cpp index 58b590b..1c6cb0f 100644 --- a/device/gxx-linux/motorboard/motorboard.cpp +++ b/device/gxx-linux/motorboard/motorboard.cpp @@ -8,7 +8,6 @@ #include "StopWatch.h" #include "applog.h" #include "Capturer.h" - static const std::string loggername = "MotorBoard"; @@ -87,15 +86,6 @@ bool MotorBoard::wait_paper_out(int timeout_ms) return cv_paper_out.wait(timeout_ms); } -bool MotorBoard::wait_error(int timeout_ms) -{ - return cv_error.wait(timeout_ms); -} - -bool MotorBoard::wait_done(int timeout_ms) -{ - return cv_scan_done.wait(timeout_ms); -} int MotorBoard::os_mode() { @@ -112,7 +102,13 @@ bool MotorBoard::paper_ready() SMB_MODE *smb_mode = (SMB_MODE *)&val; return smb_mode->feeding_paper_ready; } - +bool MotorBoard::is_converopen() +{ + unsigned int val; + read(0x02, val); + SMBSTATUS *smb_mode = (SMBSTATUS *)&val; + return smb_mode->open_machine; +} bool MotorBoard::is_scanning() { unsigned int val; @@ -121,6 +117,31 @@ bool MotorBoard::is_scanning() return smb_mode->work_status; } +bool MotorBoard::is_jam() +{ + return false; +} + +void MotorBoard::motor_reset(){ +} + +void MotorBoard::clean_paper_road() +{ + unsigned int val; + SMB_FUNC *smbc = (SMB_FUNC *)(&val); + read(6, val); + if(smbc->param.work_mode == 0) + { + smbc->param.func_clean_passthro = 1; + write(6, val); + smbc->param.func_clean_passthro = 0; + write(6, val); + } + else{ + printf("\n 非空闲模式不允许清理纸道!!!!"); + } +} + int MotorBoard::paper_counter() { unsigned int val; @@ -129,39 +150,11 @@ int MotorBoard::paper_counter() return smb_mode->scan_num; } -bool MotorBoard::set_paper_inspect_param(unsigned int value /* = 1000 */) -{ - unsigned int val; - if (!read(0x04, val)) - return false; - SMBCONFIGEXT *smb_config_ext = (SMBCONFIGEXT *)&val; - smb_config_ext->error_range_set = value; - return write(0x04, val); -} bool MotorBoard::get_keeplastpaper(){ return keep_last_paper; } -bool MotorBoard::set_paper_inpect_info(unsigned int value) -{ - unsigned int val; - if (!read(0x04, val)) - return false; - SMBCONFIGEXT *smb_config_ext = (SMBCONFIGEXT *)&val; - smb_config_ext->paper_infor = value; - return write(0x04, val); -} - -bool MotorBoard::set_paper_inspect(bool enable /* = true */) -{ - unsigned int val; - if (!read(0x04, val)) - return false; - SMBCONFIGEXT *smb_config_ext = (SMBCONFIGEXT *)&val; - smb_config_ext->paper_size_check_en = enable; - return write(0x04, val); -} bool MotorBoard::set_double_inpect(bool enable) { @@ -172,16 +165,13 @@ bool MotorBoard::set_double_inpect(bool enable) smb_config->double_paper = enable; return write(0x00, val); } -bool MotorBoard::get_doublle_inpect() -{ -} bool MotorBoard::set_auto_paper(bool enable){ unsigned int val; if (!read(0x00, val)) return false; SMBCONFIG *smb_config = (SMBCONFIG *)&val; - smb_config->paper_auto_module = enable; + smb_config->autofeed_mode = enable; return write(0x00, val); } @@ -195,9 +185,7 @@ bool MotorBoard::set_staple_inpect(bool enable) return write(0x00, val); } -bool MotorBoard::get_staple_inpect() -{ -} + bool MotorBoard::set_color_mode(int mode) { unsigned int val; @@ -207,11 +195,8 @@ bool MotorBoard::set_color_mode(int mode) smb_config->color_mode = mode; return write(0x00, val); } -int MotorBoard::get_color_mode() -{ -} -bool MotorBoard::set_speed_mode(int mode) +bool MotorBoard::set_speed_mode(int mode,int dpi,int iscolor) { unsigned int val; if (!read(0x00, val)) @@ -234,7 +219,7 @@ int MotorBoard::get_speed_mode() return smb_config->v_setting; } -bool MotorBoard::set_cuospeed(unsigned int speed) +bool MotorBoard::set_cuospeed(unsigned int speed,uint dpi,uint iscolor) { unsigned int val; if (!read(0x04, val)) @@ -259,7 +244,6 @@ void MotorBoard::pin_call(unsigned int pinNum) if (m_os_mode != os_m) { m_os_mode = os_m; - cv_os_mode.notify_all(); if (m_glue.m_os_mode_call) m_glue.m_os_mode_call(m_os_mode); } @@ -290,14 +274,13 @@ void MotorBoard::pin_call(unsigned int pinNum) if(m_glue.m_mltop_call) m_glue.m_mltop_call(val); } - if(smb_status->paper_auto) + if(smb_status->auto_feed) { if(m_glue.m_auto_paper) m_glue.m_auto_paper(1); } if (val & 0xAFE) { - cv_error.notify_all(); if (m_glue.m_error_call) m_glue.m_error_call(val & 0x30efe); //0xefe index of 16:aquireimage error index of bit 17 :size check error @@ -323,7 +306,6 @@ void MotorBoard::pin_call(unsigned int pinNum) if (val & 0x400) { LOG_TRACE("done"); - cv_scan_done.notify_all(); if (m_glue.m_scan_done_call) m_glue.m_scan_done_call(); } @@ -403,30 +385,3 @@ int MotorBoard::get_screw_level() SMBCONFIG *smb_mode = (SMBCONFIG *)&val; return smb_mode->skew_parameter; } - -bool MotorBoard::en_testbit(bool en) -{ - unsigned int val; - auto ret= read(0x00, val); - if(!ret) - return -1; - SMBCONFIG *smb_mode = (SMBCONFIG *)&val; - smb_mode->testbit = en?1:0; - return write(0x00,val); -} - -void MotorBoard::release_statecontrol() -{ - set_auto_paper(false); - m_regsAccess.reset(); - m_intPinMonitor.reset(); - -} - -void MotorBoard::init_statecontrol() -{ - m_regsAccess.reset(new UartRegsAccess(devPort, bauds, 0x07, 0x87)); - m_intPinMonitor.reset(new PinMonitor(intport, std::bind(&MotorBoard::pin_call, this, std::placeholders::_1))); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - m_os_mode = os_mode(); -} \ No newline at end of file diff --git a/device/gxx-linux/motorboard/motorboard.h b/device/gxx-linux/motorboard/motorboard.h index f8c10fb..87d0def 100644 --- a/device/gxx-linux/motorboard/motorboard.h +++ b/device/gxx-linux/motorboard/motorboard.h @@ -1,15 +1,6 @@ #pragma once -#include -#include -#include -#include -#include "autoevent.hpp" -#include "commondef.h" +#include "Imotorboard.h" -class IRegsAccess; -class PinMonitor; -class Gpio; -class ICapturer; typedef struct SMB_CONFIG { @@ -17,23 +8,23 @@ typedef struct SMB_CONFIG unsigned int color_mode : 1; unsigned int paper : 1; unsigned int double_paper : 1; - unsigned int staple_enable : 1; // 5 + unsigned int staple_enable : 1;//5 unsigned int error_clean : 1; unsigned int status_init : 1; unsigned int pick_paper : 1; unsigned int skew_enable : 1; - unsigned int skew_parameter : 3; // 7 - unsigned int key_staple_enable : 1; + unsigned int skew_parameter : 3; + unsigned int key_staple_enable : 1;//8 unsigned int iic_config_addr : 7; unsigned int iic_config : 1; - unsigned int v_setting : 2; // 11 + unsigned int v_setting : 2;//10 unsigned int speed_set_enable : 1; unsigned int scan_busy_motor_stop : 1; - unsigned int sleep_state : 1; - unsigned int sleep_parameter : 3; // 6 - unsigned int _600dpi : 1; - unsigned int paper_auto_module : 1; // 2 - unsigned int testbit : 1; + unsigned int dpi_mode : 2; + unsigned int sleep_parameter : 2;//6 + unsigned int dpi600:1; + unsigned int autofeed_mode:1; + unsigned int lifter_en:1; } SMBCONFIG; typedef struct SMB_STATUS @@ -54,10 +45,10 @@ typedef struct SMB_STATUS unsigned int sleep_conf : 3; unsigned int dsp_get_paper_error : 1; unsigned int paper_check_result : 1; - unsigned int top_wuzhi : 1; - unsigned int ml_top_sin : 1; // 10 - unsigned int paper_auto : 1; - unsigned int paper_left : 1; + unsigned int arrival_top:1;//������ֽ + unsigned int arrival_top_int:1;//���ﶥ���ж� + unsigned int auto_feed:1;//4 + unsigned int paper_left:1; } SMBSTATUS; typedef struct SMB_MODE @@ -76,50 +67,74 @@ typedef struct SMB_CONFIG_EXT unsigned int cuo_speed : 7; } SMBCONFIGEXT; -class MotorBoard +typedef struct SMB_CONFIG_TIME +{ + unsigned int error_time_set : 7; +} SMBCONFIGTIME; + + +//Reg 6 +typedef union SMB_FUNC +{ + struct{ + unsigned int work_mode : 3; + unsigned int func_clean_passthro : 1; + unsigned int func_feed_low : 1; + unsigned int func_feed_mid : 1; + unsigned int func_feed_high : 1; + unsigned int key_sound : 1; + unsigned int key_endouble_feed : 1; + unsigned int func_encount : 1; + unsigned int func_clear_count : 1; + unsigned int motor_choose : 2; + unsigned int wr_en : 1; + unsigned int motor_addr : 8; + unsigned int key_stop_enable : 1; + unsigned int lift_init_set: 2; + }param; + unsigned int value; +} SMBFUNC; + +class MotorBoard : public IMotorBoard { public: MotorBoard(); - void start(); - void stop(); - void clear_error(); - void pick_paper(); - int os_mode(); - bool paper_ready(); - bool is_scanning(); - int paper_counter(); - bool set_long_paper(bool enable); - bool set_double_inpect(bool enable); - bool get_doublle_inpect(); - bool set_staple_inpect(bool enable); - bool set_auto_paper(bool enable); - bool get_staple_inpect(); - bool set_color_mode(int mode); - int get_color_mode(); - int get_speed_mode(); - bool set_speed_mode(int mode); - bool set_screw_inpect(bool enable); - bool get_screw_inpect(); - bool set_screw_level(int level); - int get_screw_level(); - bool wait_paper_out(int timeout_ms); - bool wait_paper_in(int timeout_ms); - bool wait_error(int timeout_ms); - bool wait_done(int timeout_ms); - bool read(unsigned int addr, unsigned int &val); - bool write(unsigned int addr, unsigned int val); - bool set_paper_inspect_param(unsigned int value = 1000); - bool set_paper_inpect_info(unsigned int value); - bool set_paper_inspect(bool enable = true); - bool set_cuospeed(unsigned int speed); - void set_callbacks(MotorBoardGlue glue); - bool get_keeplastpaper(); - bool en_testbit(bool en); - std::shared_ptr regs(); - void set_capture(std::shared_ptr cap); - void release_statecontrol(); - void init_statecontrol(); + void start() override; + void stop() override; + void clear_error() override; + void pick_paper() override; + void stop_pick_paper() override{}; + int os_mode() override; + bool paper_ready() override; + bool is_scanning() override; + bool is_jam() override; + int paper_counter() override; + bool is_converopen() override; + bool set_long_paper(bool enable) override; + bool set_double_inpect(bool enable) override; + bool set_staple_inpect(bool enable) override; + bool set_auto_paper(bool enable) override; + bool set_color_mode(int mode) override; + int get_speed_mode() override; + bool set_speed_mode(int mode,int dpi,int iscolor) override; + bool set_screw_inpect(bool enable) override; + bool get_screw_inpect() override; + bool set_screw_level(int level) override; + int get_screw_level() override; + bool wait_paper_out(int timeout_ms) override; + bool wait_paper_in(int timeout_ms) override; + bool read(unsigned int addr, unsigned int &val) override; + bool write(unsigned int addr, unsigned int val) override; + bool set_cuospeed(unsigned int speed,uint dpi = 0,uint iscolor = 1) override; + void set_callbacks(MotorBoardGlue glue) override; + bool get_keeplastpaper() override; + std::shared_ptr regs() override; + void set_capture(std::shared_ptr cap) override; + void motor_reset() override; + void LedControlOption(HG_LedOption option,uint32_t time) override{}; + void clean_paper_road() override; + private: void pin_call(unsigned int pinNum); void scansensor_call(unsigned int pinNum); @@ -133,9 +148,6 @@ private: std::shared_ptr m_uartEnable; AutoSemaphore cv_paper_out; AutoSemaphore cv_paper_in; - AutoSemaphore cv_error; - AutoSemaphore cv_scan_done; - AutoSemaphore cv_os_mode; unsigned int m_os_mode; volatile bool keep_last_paper; MotorBoardGlue m_glue; diff --git a/device/gxx-linux/motorboard/motormanager.cpp b/device/gxx-linux/motorboard/motormanager.cpp new file mode 100644 index 0000000..d46d4f7 --- /dev/null +++ b/device/gxx-linux/motorboard/motormanager.cpp @@ -0,0 +1,320 @@ +#include "motormanager.h" +#include "MotorControl.h" +#include "sensormonitor.h" +#include +#include "Led.h" + +MotorManager::MotorManager():m_motorcontrol(new MotorControl()), + m_ledcontrol(new LedControl()), + is_usb_connect(false), + is_sleeping(false), + is_autopaper(false), + is_motor_run(false), + autopaper_state_change(false), + autopaperthread(1), + m_glue({nullptr,nullptr,nullptr,nullptr,nullptr,nullptr}) +{ + GetorSetSysClassValue(false,HG_PWM_FAN,false); + GetorSetSysClassValue(false,HG_MOTOR_FAN,false); + m_sensormonitor.reset(new SensorMonitor([&](int value){pincall(value);})); + m_ledcontrol->option(HG_WHITE_ON,300); +} + +MotorManager::~MotorManager() +{ + +} +bool MotorManager::GetOrSetUsbConnectFlag(bool isGet,bool value){ + if(isGet) + return is_usb_connect; + if(value == false) + m_ledcontrol->option(HG_LedOption::HG_WHITE_ON,300); + return is_usb_connect = value; +} + +bool MotorManager::GetOrSetSleepFlag(bool isGet,bool value){ + if(isGet) + return is_sleeping; + if(value == false) + { + if(!(m_sensormonitor->Is_ConverOpen()||m_sensormonitor->Is_Jam())) + { + if(!m_sensormonitor->Is_PaperOn()) + m_motorcontrol->MotorRun(MotorControl::MotorOption::CZ_Reset); + m_ledcontrol->option(HG_WHITE_ON,0); + } + else{ + if(m_sensormonitor->Is_ConverOpen()) + m_ledcontrol->option(HG_RED_ON,300); + else + m_ledcontrol->option(HG_RED_ON,0); + } + } + else + is_autopaper = false; + if(mb_ev_cb_) + mb_ev_cb_(value ? SCANNER_STATUS_SLEEPING : SCANNER_STATUS_WAKED_UP); + + return is_sleeping = value; +} + +void MotorManager::set_capture(std::shared_ptr cap) +{ + m_cap = cap; +} +std::shared_ptr MotorManager::regs() +{ + return nullptr; +} +int MotorManager::os_mode(){ + return 0; +} +bool MotorManager::paper_ready(){ + return m_sensormonitor->Is_PaperOn(); +} +void MotorManager::clear_error(){ + mb_error = 0; +} + +void MotorManager::start(){ + is_motor_run = true; + m_papperout_time = std::chrono::steady_clock::now(); + m_motorcontrol->MotorRun(MotorControl::MotorOption::ZZ_Forward); + m_motorcontrol->MotorRun(MotorControl::MotorOption::CZ_Forward); + GetorSetSysClassValue(false,HG_PWM_FAN,true); + GetorSetSysClassValue(false,HG_MOTOR_FAN,true); + m_ledcontrol->option(HG_WHITE_ON,0); +} +void MotorManager::stop(){ + is_motor_run = false; + m_motorcontrol->MotorRun(MotorControl::MotorOption::CZ_Stop); + m_motorcontrol->MotorRun(MotorControl::MotorOption::ZZ_Stop); + GetorSetSysClassValue(false,HG_PWM_FAN,false); + GetorSetSysClassValue(false,HG_MOTOR_FAN,false); +} +bool MotorManager::wait_paper_out(int timeout_ms){ + return cv_paperout.wait(timeout_ms); +} +bool MotorManager::wait_paper_in(int timeout_ms){ + bool ret = cv_paperin.wait(timeout_ms); + std::cout<<"wait_paper_in timeout:"<MotorRun(MotorControl::MotorOption::CZ_Pause); + return ret; +} +void MotorManager::pick_paper(){ + m_motorcontrol->MotorRun(MotorControl::MotorOption::CZ_Forward); +} + +void MotorManager::stop_pick_paper(){ + m_motorcontrol->MotorRun(MotorControl::MotorOption::CZ_Pause); +} + +bool MotorManager::is_scanning(){ + return false; +} +bool MotorManager::is_jam(){ + return GetorSetSysClassValue(true,"/sys/class/gpio/gpio54/value",true); +} +int MotorManager::paper_counter(){ + return -1; +} +bool MotorManager::set_long_paper(bool enable){ + return false; +} +bool MotorManager::set_double_inpect(bool enable){ + if(enable) + //system("echo 1 > /sys/class/gpio/gpio139/value"); + GetorSetSysClassValue(false,"/sys/class/gpio/gpio139/value",true); + else + //system("echo 0 > /sys/class/gpio/gpio139/value"); + GetorSetSysClassValue(false,"/sys/class/gpio/gpio139/value",false); + return true; +} +bool MotorManager::set_staple_inpect(bool enable){ + return false; +} +bool MotorManager::set_auto_paper(bool enable){ + is_autopaper = enable; + return false; +} +bool MotorManager::set_color_mode(int mode){ + return false; +} + +int MotorManager::get_speed_mode(){ + return -1; +} + +bool MotorManager::set_speed_mode(int mode,int dpi,int iscolor){ + m_motorcontrol->setczspeed(mode,dpi,iscolor); + m_motorcontrol->setzzspeed(mode,dpi,iscolor); + return true; +} +bool MotorManager::set_screw_inpect(bool enable){ + return false; +} +bool MotorManager::get_screw_inpect(){ + return false; +} +bool MotorManager::set_screw_level(int level){ + return false; +} +int MotorManager::get_screw_level(){ + return -1; +} + +bool MotorManager::read(unsigned int addr, unsigned int &val){ + return false; +} +bool MotorManager::write(unsigned int addr, unsigned int val){ + return false; +} +bool MotorManager::set_cuospeed(unsigned int speed,uint dpi,uint iscolor){ + m_motorcontrol->setczspeed(speed,dpi,iscolor); + return true; +} +void MotorManager::set_callbacks(MotorBoardGlue glue){ + m_glue = glue; +} +bool MotorManager::get_keeplastpaper(){ + return false; +} +void MotorManager::motor_reset(){ + m_motorcontrol->MotorRun(MotorControl::CZ_Reset); +} + +void MotorManager::pincall(int value){ + if(mb_ev_cb_) + { + mb_ev_cb_(IMotorBoard::scanner_status_from_raw(value)); + } + if(is_sleeping || !is_usb_connect) + return; + printf("\npin call value %d",value); + if(value == 1){ + cv_paperin.notify_all(); + if(std::chrono::duration(std::chrono::steady_clock::now() - m_papperout_time).count() < 60) + m_glue.m_error_call?m_glue.m_error_call(0x40000):void(0); + printf("\n-------------- paper out time %f ---------------------------",std::chrono::duration(std::chrono::steady_clock::now() - m_papperout_time).count()); + m_papperout_time = std::chrono::steady_clock::now(); + } + else if(value == 0){ + cv_paperout.notify_all(); + m_papperout_time = std::chrono::steady_clock::now(); + } + if(value &0x24) + { + if(m_glue.m_error_call) + m_glue.m_error_call(value); + cv_paperin.notify_all(); + cv_paperout.notify_all(); + + } + if(value == 0x20) + { + this->stop(); + set_double_inpect(false); + } + if(value == 4 && is_converopen()) + m_ledcontrol->option(HG_RED_ON,300); + if(value ==0x4000000 && !is_motor_run) + { + f_motorreset = std::async(std::launch::async,[&](){ + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + if(is_usb_connect && !is_converopen() && (!paper_ready())) + motor_reset(),printf("\n conver reset"); + }); + printf("\n conver ******************************"); + if(is_jam()) + m_ledcontrol->option(HG_RED_ON,0); + else if(!is_usb_connect) + m_ledcontrol->option(HG_WHITE_ON,500); + else + m_ledcontrol->option(HG_WHITE_ON,0); + } + if(is_autopaper && value == 0x2000000 && !is_motor_run) + { + printf("\n ---------------------------------------------------"); + autopaper_state_change = true; + autopaperthread.enqueue([&]{ + StopWatch sw; + while (sw.elapsed_ms()<1000) + { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + if(!autopaper_state_change) + return; + } + m_glue.m_auto_paper(true); + printf("\n -----------------m_glue.m_auto_paper(true);----------------------------------"); + }); + } + if(is_autopaper && value == 2 && !is_motor_run) + { + autopaper_state_change = false; + } + if(value == 2){ + if(is_motor_run == false && is_converopen() == false && is_jam() == false && m_ledcontrol->get_state() == HG_LedOption::HG_RED_ON) + { + m_ledcontrol->option(HG_WHITE_ON,0); + if(mb_error == 8 || mb_error == 79 || mb_error == 82) + motor_reset(),mb_error = 0; + } + } +} +bool MotorManager::is_converopen() +{ + return m_sensormonitor->Is_ConverOpen(); +} + +void MotorManager::LedControlOption(HG_LedOption option,uint32_t time){ + m_ledcontrol?m_ledcontrol->option(option,time):void(1); +} + +void MotorManager::clean_paper_road(){ + set_speed_mode(1,2,0); + StopWatch sw; + m_motorcontrol->MotorRun(MotorControl::MotorOption::ZZ_Forward); + std::this_thread::sleep_for(std::chrono::milliseconds(1500)); + bool b_clean_ = false; + while(sw.elapsed_s() < 5) + { + if(!is_jam()) + { + b_clean_ = true; + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(700)); + } + m_motorcontrol->MotorRun(MotorControl::MotorOption::ZZ_Stop); + if(is_sleeping || !is_usb_connect) + return; + if(is_motor_run == false && is_converopen() == false && is_jam() == false && m_ledcontrol->get_state() == HG_LedOption::HG_RED_ON || b_clean_) + { + m_ledcontrol->option(HG_WHITE_ON,0); + } +} + +bool MotorManager::GetorSetSysClassValue(bool isGet,std::string path,bool value){ + if(isGet) + { + FILE *fp = fopen(path.c_str(),"r"); + if(fp != NULL) + { + fscanf(fp,"%d",&value); + fclose(fp); + return value; + } + return false; + } + else{ + FILE *fp = fopen(path.c_str(),"w"); + if(fp != NULL) + { + fprintf(fp,"%d",value); + fclose(fp); + return true; + } + return false; + } +} \ No newline at end of file diff --git a/device/gxx-linux/motorboard/motormanager.h b/device/gxx-linux/motorboard/motormanager.h new file mode 100644 index 0000000..1352e8e --- /dev/null +++ b/device/gxx-linux/motorboard/motormanager.h @@ -0,0 +1,72 @@ +#pragma once +#include "Imotorboard.h" +#include "autoevent.hpp" + +const std::string HG_PWM_FAN = "/sys/class/fv_en_class/fv_en/pwm_fan"; +const std::string HG_MOTOR_FAN = "/sys/class/fv_en_class/fv_en/motor_fan"; + +class MotorControl; +class SensorMonitor; +class LedControl; +enum HG_LedOption : uint8_t; + +class MotorManager : public IMotorBoard +{ +public: + MotorManager(); + virtual ~MotorManager(); + void start() override; + void stop() override; + void clear_error() override; + void pick_paper() override; + void stop_pick_paper() override; + int os_mode() override; + bool paper_ready() override; + bool is_converopen() override; + bool is_scanning() override; + bool is_jam() override; + int paper_counter() override; + bool set_long_paper(bool enable) override; + bool set_double_inpect(bool enable) override; + bool set_staple_inpect(bool enable) override; + bool set_auto_paper(bool enable) override; + bool set_color_mode(int mode) override; + int get_speed_mode() override; + bool set_speed_mode(int mode,int dpi,int iscolor) override; + bool set_screw_inpect(bool enable) override; + bool get_screw_inpect() override; + bool set_screw_level(int level) override; + int get_screw_level() override; + bool wait_paper_out(int timeout_ms) override; + bool wait_paper_in(int timeout_ms) override; + bool read(unsigned int addr, unsigned int &val) override; + bool write(unsigned int addr, unsigned int val) override; + bool set_cuospeed(unsigned int speed,uint dpi,uint iscolor) override; + void set_callbacks(MotorBoardGlue glue) override; + bool get_keeplastpaper() override; + std::shared_ptr regs() override; + void set_capture(std::shared_ptr cap) override; + void motor_reset() override; + bool GetOrSetUsbConnectFlag(bool isGet,bool value); + bool GetOrSetSleepFlag(bool isGet,bool value); + void LedControlOption(HG_LedOption option,uint32_t time) override; + void clean_paper_road() override; +private: + void pincall(int value); + bool GetorSetSysClassValue(bool isGet,std::string path,bool value); + std::unique_ptr m_motorcontrol; + std::unique_ptr m_sensormonitor; + std::unique_ptr m_ledcontrol; + MotorBoardGlue m_glue; + volatile bool is_usb_connect; + volatile bool is_sleeping; + volatile bool is_autopaper; + volatile bool is_motor_run; + volatile bool autopaper_state_change; + std::shared_ptr m_cap; + ThreadPool autopaperthread; + AutoSemaphore cv_paperin; + AutoSemaphore cv_paperout; + std::future f_motorreset; + std::chrono::steady_clock::time_point m_papperout_time; +}; diff --git a/device/gxx-linux/motorboard/sensormonitor.cpp b/device/gxx-linux/motorboard/sensormonitor.cpp new file mode 100644 index 0000000..09d9ac1 --- /dev/null +++ b/device/gxx-linux/motorboard/sensormonitor.cpp @@ -0,0 +1,127 @@ +#include "sensormonitor.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +SensorMonitor::SensorMonitor(std::function callback):m_callback(callback), + _C6(54),//扫描传感器 + _A4(36),//有无纸传感器 + _C7(55),//开盖传感器 + Double_out0(137)//超声波传感器 +{ + _C6.setDirection(Gpio::in); + _A4.setDirection(Gpio::in); + _C7.setDirection(Gpio::in); + Double_out0.setDirection(Gpio::in); + _C7.setEdge(Gpio::both); + _A4.setEdge(Gpio::both); + _C6.setEdge(Gpio::both); + Double_out0.setEdge(Gpio::rising); + is_paperon = _A4.getValue() == Gpio::GpioLevel::High ? false : true; + is_converopen = _C7.getValue() == Gpio::GpioLevel::High ? false : true; + is_jam = _C6.getValue() == Gpio::GpioLevel::High? true : false; + b_monitor = true; + m_monitor = std::thread(&SensorMonitor::monitor,this); +} + +SensorMonitor::~SensorMonitor() +{ + b_monitor =false; + if(m_monitor.joinable()) + m_monitor.join(); +} +bool SensorMonitor::Is_PaperOn() +{ + return is_paperon; +} + +bool SensorMonitor::Is_ConverOpen() +{ + return is_converopen; +} + +bool SensorMonitor::Is_Jam() +{ + return is_jam; +} + +void SensorMonitor::monitor(){ + pollfd fds[4]{}; + fds[0].fd = open(_C6.getValuePath().c_str(),O_RDONLY); + fds[1].fd = open(_A4.getValuePath().c_str(),O_RDONLY); + fds[2].fd = open(_C7.getValuePath().c_str(),O_RDONLY); + fds[3].fd = open(Double_out0.getValuePath().c_str(),O_RDONLY); + int ret=0; + char buf[8]{}; + int num =0; + num = read(fds[0].fd, buf, 8); + num = read(fds[1].fd, buf, 8); + num = read(fds[2].fd, buf, 8); + num = read(fds[3].fd, buf, 8); + while(b_monitor) + { + ret = poll(fds,4,1000); + if(ret>0) + { + if(fds[0].revents) + { + if(ret = readfile(fds[0].fd,num,buf)){ + if(m_callback) + m_callback(true); + is_jam = true; + } + else{ + if(m_callback) + m_callback(false); + is_jam = false; + } + printf("\n 扫描传感器 %d ",ret); + } + if(fds[1].revents) + { + if(readfile(fds[1].fd,num,buf)){ + is_paperon = false; + m_callback(2); + } + else{ + is_paperon = true; + m_callback(0x2000000); + } + printf("\n 有无纸传感器 %d ",!is_paperon); + } + if(fds[2].revents) + { + if(readfile(fds[2].fd,num,buf)){ + is_converopen = false; + m_callback(0x4000000); + } + else{ + is_converopen = true; + m_callback(4); + } + printf("\n 开盖传感器 %d ",!is_converopen); + } + if(fds[3].revents) + { + if(ret = readfile(fds[3].fd,num,buf)){ + m_callback(0x20); + } + printf("\n 双张 %d ",ret); + } + } + } +} +int SensorMonitor::readfile(int fd,int num , char* buf){ + lseek(fd, 0, SEEK_SET); + num = read(fd, buf, 8); + buf[num - 1] = '\0'; + return atoi(buf); +} \ No newline at end of file diff --git a/device/gxx-linux/motorboard/sensormonitor.h b/device/gxx-linux/motorboard/sensormonitor.h new file mode 100644 index 0000000..ee9e924 --- /dev/null +++ b/device/gxx-linux/motorboard/sensormonitor.h @@ -0,0 +1,29 @@ +#pragma once +#include "Gpio.h" +#include +#include +#include + +class SensorMonitor +{ +public: + SensorMonitor(std::function callback); + ~SensorMonitor(); + bool Is_PaperOn(); + bool Is_ConverOpen(); + bool Is_Jam(); +private: + void monitor(); + int readfile(int fd,int num , char* buf); + Gpio _C6; + Gpio _A4; + Gpio _C7; + Gpio Double_out0; + std::thread m_monitor; + std::function m_callback; + volatile bool b_monitor; + volatile bool is_converopen; + volatile bool is_paperon; + volatile bool is_jam; + +}; \ No newline at end of file diff --git a/device/gxx-linux/motorboard/xmake.lua b/device/gxx-linux/motorboard/xmake.lua index 62a0e90..6cca12f 100644 --- a/device/gxx-linux/motorboard/xmake.lua +++ b/device/gxx-linux/motorboard/xmake.lua @@ -4,6 +4,6 @@ target("motorboard") set_kind("static") add_syslinks("pthread") add_files("*.cpp") - add_deps("regs", "deviceio", "conf", "applog", "capimage",{public = true}) + add_deps("regs", "motor_run" ,"deviceio", "conf", "applog", "capimage",{public = true}) add_includedirs(".", { public = true}) add_packages("common") \ No newline at end of file diff --git a/device/gxx-linux/scanner/deviceconfig.cpp b/device/gxx-linux/scanner/deviceconfig.cpp index f4dbae2..ff654f9 100644 --- a/device/gxx-linux/scanner/deviceconfig.cpp +++ b/device/gxx-linux/scanner/deviceconfig.cpp @@ -61,11 +61,8 @@ json DeviceConfig::getdefaultjson() void DeviceConfig::savejson(json js) { - //std::lock_guard lc(m_lock); std::ofstream o(ParamPath); o << std::setw(4) << js <> m_json; - i.close(); return m_json; } diff --git a/device/gxx-linux/scanner/fsmstate.cpp b/device/gxx-linux/scanner/fsmstate.cpp index 526a466..57a9f90 100644 --- a/device/gxx-linux/scanner/fsmstate.cpp +++ b/device/gxx-linux/scanner/fsmstate.cpp @@ -1,7 +1,7 @@ #include "fsmstate.h" -#include "scanner.h" +#include "iscanner.h" -Scanner *FsmState::scanner = NULL; +IScanner *FsmState::scanner = NULL; #ifndef LOG #define LOG printf #endif diff --git a/device/gxx-linux/scanner/fsmstate.h b/device/gxx-linux/scanner/fsmstate.h index 6091e79..1b8e55d 100644 --- a/device/gxx-linux/scanner/fsmstate.h +++ b/device/gxx-linux/scanner/fsmstate.h @@ -4,7 +4,7 @@ #include #include -class Scanner; +class IScanner; enum ScanEvent { @@ -47,12 +47,12 @@ public: virtual FsmState* on_event(ScanEvent event) = 0; virtual void initial() {} - static void setScanner(Scanner* scan) { + static void setScanner(IScanner* scan) { scanner = scan; } std::string typeName = "FsmState"; protected: - static Scanner* scanner; + static IScanner* scanner; }; diff --git a/device/gxx-linux/scanner/iimagehandler.h b/device/gxx-linux/scanner/iimagehandler.h index e5e3a2e..eaf1c9b 100644 --- a/device/gxx-linux/scanner/iimagehandler.h +++ b/device/gxx-linux/scanner/iimagehandler.h @@ -2,6 +2,7 @@ #include "commondef.h" #include "ImageApplyHeaders.h" #include "CSizedetect.h" +#include "CorrectParam.h" #include #include #include @@ -15,8 +16,13 @@ static std::map papersize{ {B4, Size{250, 353}}, {B5, Size{176, 250}}, {B6, Size{125, 176}}, - {MaxSize, Size{297, 420 * 2}}, +#ifdef G300 + {MaxSize, Size{210, (long)(420 * 1.5)}}, + {USStatement, Size{210, (long)(420 * 1.5)}}, +#else + {MaxSize, Size{297, 1040}}, {USStatement, Size{297, (long)(420 * 1.5)}}, +#endif {USLetter, Size{216, 279}}, {USLegal, Size{216, 356}}, {USLedger, Size{279, 432}}, @@ -31,11 +37,12 @@ class IImageHandler { public: virtual ~IImageHandler() {} - virtual void add_image(void *data, int width, int height, int type,int scannnum) = 0; + virtual void add_image(void *data, int width, int height, int type,int scannnum,std::uint32_t fpga_vs,CISVendor cistype) = 0; virtual void config_procparams(HGImgProcParms params) = 0; virtual void add_scanevent(HGIntInfo status) = 0; virtual void clear() = 0; virtual bool done() = 0; + virtual bool is_limit() = 0; virtual void Set_ratio(u32 h_ratio,u32 v_ratio) = 0; ImgStatus getimgstatus() { return m_imgstatus;} void resetimgstatus() { m_imgstatus={.status=NO_error,.sannum=0};} @@ -64,25 +71,47 @@ public: { m_scanconfig = config; } + bool set_config(GScanCap config) { m_hgimgconfig = config; + if(config.resolution_dst<300.0f) + m_hgimgconfig.resolution_native = 200.0f; +#ifdef G300 + else + m_hgimgconfig.resolution_native = 300.0f; +#else + else if(config.resolution_dst <500.0f) + m_hgimgconfig.resolution_native = 300.0f; + else + m_hgimgconfig.resolution_native = 600.0f; +#endif m_ials.clear(); if(m_dog.get()) { if(m_hgimgconfig.dogeardistabce>=10 && m_hgimgconfig.dogeardistabce <=300) m_dog->setDistance(m_hgimgconfig.dogeardistabce); else - m_dog->setDistance(50); + m_dog->setDistance(70); } if(config.fillhole.is_fillhole) { - float ratio=config.fillhole.fillholeratio/100.0; - m_ials.push_back(std::shared_ptr(new CImageApplyOutHole(200.0f,ratio,50.0))); + if((config.fillholeratio_down+config.fillholeratio_up+config.fillholeratio_left+config.fillholeratio_right)>0) + { + m_ials.push_back(std::shared_ptr(new CImageApplyOutHole( + 25.0f, + {config.fillholeratio_up/100.0f,config.fillholeratio_down/100.0f,config.fillholeratio_left/100.0f,config.fillholeratio_right/100.0f}, + 50.0))); + } + else if(config.fillhole.fillholeratio > 0){ + float ratio=config.fillhole.fillholeratio/100.0; + m_ials.push_back(std::shared_ptr(new CImageApplyOutHole(25.0f,{ratio,ratio,ratio,ratio},50.0))); + } } - bool islongcustomcrop = config.papertype == 52; + bool islongcustomcrop = config.papertype == 52 || config.papertype == 0; //bool isautocrop = config.papertype == TwSS::None; Size fixedSize; + printf(" \nconfig.dogeardistabce=%d", config.dogeardistabce); printf(" \nconfig.papertype=%d", config.papertype); printf(" \nconfig.AutoCrop_threshold=%d", config.AutoCrop_threshold); printf(" \nconfig.autodescrew=%d", config.autodescrew); @@ -100,6 +129,7 @@ public: printf(" \nconfig.hardwarecaps.capturepixtype=%d", config.hardwarecaps.capturepixtype); printf(" \nconfig.hardwarecaps.en_doublefeed=%d", config.hardwarecaps.en_doublefeed); printf(" \nconfig.hsvcorrect=%d", config.hsvcorrect); + printf(" \nconfig.HsvFilterType=%d", config.HsvFilterType); printf(" \nconfig.imageRotateDegree=%d", config.imageRotateDegree); printf(" \nconfig.indent=%d", config.indent); printf(" \nconfig.is_autocontrast=%d", config.is_autocontrast); @@ -116,77 +146,28 @@ public: printf(" \nconfig.noise=%d", config.noise); printf(" \nconfig.hardwarecaps.paperAlign=%d", config.paperAlign); printf(" \nconfig.hardwarecaps.pixtype=%d", config.pixtype); - printf(" \nconfig.resolution_dst=%d", config.resolution_dst); - printf(" \nconfig.resolution_native=%d", config.resolution_native); + printf(" \nconfig.resolution_dst=%f", config.resolution_dst); + printf(" \nconfig.resolution_native=%f", config.resolution_native); printf(" \nconfig.scannum=%d", config.scannum); - printf(" \nconfig.sharpen=%d", config.sharpen); + printf(" \nconfig.sharpen=%d",config.sharpen); printf(" \nconfig.is_dogeardetection=%d", config.is_dogeardetection); - fixedSize = GetPaperSize(config.papertype, 200.0f, config.paperAlign); - // m_ials.push_back(shared_ptr(new CImageApplyAutoCrop(islongcustomcrop ? islongcustomcrop : config.is_autocrop, - // config.autodescrew, config.fillbackground, cv::Size(fixedSize.x, fixedSize.y), config.is_convex,false,config.AutoCrop_threshold,config.noise,config.indent))); + fixedSize = GetPaperSize(config.papertype, m_hgimgconfig.resolution_native, config.paperAlign); + printf( " \n fixedSize x %d fixedSize y %d ",fixedSize.x,fixedSize.y); + config.is_autocrop = 1; + islongcustomcrop = false; + m_ials.push_back(shared_ptr(new CImageApplyAutoCrop(islongcustomcrop ? islongcustomcrop : config.is_autocrop, + config.autodescrew, config.fillbackground, cv::Size(fixedSize.x, fixedSize.y), config.is_convex,false,config.AutoCrop_threshold,config.noise,config.indent))); if (config.is_autodiscradblank_normal || config.is_autodiscradblank_vince) { - //m_ials.push_back(shared_ptr(new CImageApplyDiscardBlank())); - CImageApplyDiscardBlank *disBlank = new CImageApplyDiscardBlank(); - //跳过空白页阈值 - int area = 200; - int intensity = 15; - int maxHeight = 3307; //A3 height - //页面最大高度获取 - if (config.papertype == 54) - maxHeight = 6614; - //阈值参数赋值 - if (config.discardblank_percent < 10) - { - area = 70 + (int)((config.discardblank_percent - 1) * 13.33); - intensity = 8 + config.discardblank_percent / 2; - } - else if (config.discardblank_percent < 20) - { - area = 190 + (config.discardblank_percent - 10) * 14; - intensity = 15; - } - else if (config.discardblank_percent < 40) - { - area = 400 + (config.discardblank_percent - 20) * 10; - intensity = 20; - } - else if (config.discardblank_percent < 60) - { - area = 600 + (config.discardblank_percent - 40) * 20; - intensity = 20; - } - else if (config.discardblank_percent < 80) - { - area = 1000 + (config.discardblank_percent - 60) * 55; - intensity = 30; - } + if (config.is_autodiscradblank_normal) + m_ials.push_back(shared_ptr(new CImageApplyDiscardBlank(40, 30, config.discardblank_percent, 200))); else - { - area = 2100 + (config.discardblank_percent - 80) * (maxHeight - 2100) / 20; - intensity = 40; - } - //判断是否为跳过空白页发票 - if (config.is_autodiscradblank_vince) - { - area *= 1.5; - intensity *= 1.5; - } - //设置参数阈值 - // disBlank->setMinArea(area); - // disBlank->setIntensity(intensity); - printf("\n area =%d,intensity =%d ",area,intensity); - m_ials.push_back(shared_ptr(disBlank)); - //m_ials.push_back(shared_ptr(new CImageApplyDiscardBlank(config.areanum,config.devnmax))); + m_ials.push_back(shared_ptr(new CImageApplyDiscardBlank(40, 30, config.discardblank_percent * 15 / 10, 150))); } m_ials.push_back(shared_ptr(new CImageApplyAutoCrop(islongcustomcrop ? islongcustomcrop : config.is_autocrop, - config.autodescrew, config.fillbackground, cv::Size(fixedSize.x, fixedSize.y), config.is_convex,false,config.AutoCrop_threshold,config.noise,config.indent))); - - //除底色 - if(config.fadeback && config.pixtype == 2) - m_ials.push_back(shared_ptr(new CImageApplyFadeBackGroudColor(100,0,config.fadebackrange))); + config.autodescrew, config.fillbackground, cv::Size(fixedSize.x, fixedSize.y), config.is_convex,config.isfillcolor,config.AutoCrop_threshold,config.noise,config.indent,config.normalCrop,config.HsvFilterType == 0))); //自定义裁切 if(config.cropRect.enable &&!config.is_autocrop) @@ -194,7 +175,19 @@ public: printf("\n 自定义裁切"); m_ials.push_back(shared_ptr(new CImageApplyCustomCrop(cv::Rect(config.cropRect.x,config.cropRect.y,config.cropRect.width,config.cropRect.height)))); } + + m_hgimgconfig.is_colorcast = 0; + // if((config.pixtype == 2)&&(config.is_colorcast)) + // { + // printf("\n 色偏"); + // m_ials.push_back(m_colorcast); + // } + // if (config.fadeback && config.pixtype > 0)// && config.pixtype == 2 + { + printf("\n 除底色"); + m_ials.push_back(shared_ptr(new CImageApplyFadeBackGroudColor(50,0,config.fadebackrange))); + } // if (config.customGamma.enable) // { // m_iaList.push_back(shared_ptr(new CImageApplyCustomGamma(imgparams.customGamma.table, imgparams.customGamma.tableLength))); @@ -228,10 +221,16 @@ public: m_ials.push_back(shared_ptr(new CImageApplyAdjustColors(bright, contrast, config.gamma))); } //答题卡除红 - if (config.hsvcorrect && config.pixtype==2) + if ((config.hsvcorrect|| config.HsvFilterType!=0)&& config.pixtype==2) { printf("\n 答题卡除红"); - m_ials.push_back(shared_ptr(new CImageApplyHSVCorrect(CImageApplyHSVCorrect::CorrectOption::Red_Removal))); + CImageApplyHSVCorrect::CorrectOption hsv;//= config.hsvcorrect?CImageApplyHSVCorrect::CorrectOption::Red_Removal: + if(config.hsvcorrect) + hsv = CImageApplyHSVCorrect::CorrectOption::Red_Removal; + else + hsv = CImageApplyHSVCorrect::CorrectOption::FXB_Color_Cast; + + m_ials.push_back(shared_ptr(new CImageApplyHSVCorrect(hsv))); } //防止渗透 if (config.refuseInflow) @@ -269,7 +268,7 @@ public: islongcustomcrop = true; if (config.is_autocrop || islongcustomcrop) { - double ratio = config.resolution_dst / 200.0; // + double ratio = config.resolution_dst /m_hgimgconfig.resolution_native; // apply = new CImageApplyResize(CImageApplyResize::ResizeType::RATIO, cv::Size(0, 0), ratio, ratio); } else @@ -300,24 +299,29 @@ public: if (config.en_fold) { - m_ials.push_back(shared_ptr(new CImageApplyConcatenation(CImageApplyConcatenation::horizontal, cv::Scalar(255, 255, 255)))); + if(!(config.fold_concatmode >=0 && config.fold_concatmode <3)) + config.fold_concatmode = 0; + m_ials.push_back(shared_ptr(new CImageApplyConcatenation(CImageApplyConcatenation::ConcatMode(config.fold_concatmode), cv::Scalar(255, 255, 255)))); } + if (config.imageRotateDegree != 0.0 || config.is_backrotate180) { - CImageApplyRotation::RotationType type; - if (config.imageRotateDegree > 89.0f && config.imageRotateDegree < 91.0f) - type = CImageApplyRotation::RotationType::Rotate_90_clockwise; - else if (config.imageRotateDegree > 269.0f && config.imageRotateDegree < 271.0f) - type = CImageApplyRotation::RotationType::Rotate_90_anti_clockwise; - else if (config.imageRotateDegree > 179.0f && config.imageRotateDegree < 181.0f) - type = CImageApplyRotation::RotationType::Rotate_180; - else - type = CImageApplyRotation::RotationType::Invalid; + // CImageApplyRotation::RotationType type; + // if (config.imageRotateDegree > 89.0f && config.imageRotateDegree < 91.0f) + // type = CImageApplyRotation::RotationType::Rotate_90_clockwise; + // else if (config.imageRotateDegree > 269.0f && config.imageRotateDegree < 271.0f) + // type = CImageApplyRotation::RotationType::Rotate_90_anti_clockwise; + // else if (config.imageRotateDegree > 179.0f && config.imageRotateDegree < 181.0f) + // type = CImageApplyRotation::RotationType::Rotate_180; + // else + // type = CImageApplyRotation::RotationType::Invalid; - m_ials.push_back(shared_ptr(new CImageApplyRotation(type, config.is_backrotate180, config.resolution_dst, NULL))); + // m_ials.push_back(shared_ptr(new CImageApplyRotation(type, config.is_backrotate180, config.resolution_dst, NULL))); } + printf("Image processors: %d\n", m_ials.size()); + return true; } @@ -328,4 +332,5 @@ protected: std::vector> m_ials; std::shared_ptr m_dog; std::shared_ptr m_sizedetect; + // std::shared_ptr m_colorcast; }; diff --git a/device/gxx-linux/scanner/imagesavehandler.cpp b/device/gxx-linux/scanner/imagesavehandler.cpp index 97f9613..be9cda1 100644 --- a/device/gxx-linux/scanner/imagesavehandler.cpp +++ b/device/gxx-linux/scanner/imagesavehandler.cpp @@ -14,7 +14,7 @@ ImageSaveHandler::~ImageSaveHandler() } -void ImageSaveHandler::add_image(void *data, int width, int height, int type, int scannnum) +void ImageSaveHandler::add_image(void *data, int width, int height, int type, int scannnum,std::uint32_t fpga_vs,CISVendor cistype) { static int indexx = 0; std::string path = std::to_string(++indexx) + ".png"; diff --git a/device/gxx-linux/scanner/imagesavehandler.h b/device/gxx-linux/scanner/imagesavehandler.h index 82fc009..5bf1c81 100644 --- a/device/gxx-linux/scanner/imagesavehandler.h +++ b/device/gxx-linux/scanner/imagesavehandler.h @@ -8,7 +8,7 @@ class ImageSaveHandler : public IImageHandler public: ImageSaveHandler(); virtual ~ImageSaveHandler(); - virtual void add_image(void* data, int width, int height, int type ,int scannnum); + virtual void add_image(void* data, int width, int height, int type ,int scannnum,std::uint32_t fpga_vs,CISVendor cistype); virtual bool done(); private: diff --git a/device/gxx-linux/scanner/imageusbhandler.cpp b/device/gxx-linux/scanner/imageusbhandler.cpp index b6f103b..7d127ae 100644 --- a/device/gxx-linux/scanner/imageusbhandler.cpp +++ b/device/gxx-linux/scanner/imageusbhandler.cpp @@ -12,122 +12,161 @@ #include "ImageApplyAutoCrop.h" #include "hgutils.h" #include "correct_ultis.h" +#include +#include "../usb/src/common/packet.h" +#include "../usb/src/common/sys_util.h" + +namespace bmp +{ +#pragma pack(push) +#pragma pack(1) + typedef struct BITMAPFILEHEADER + { + u_int16_t bfType; + u_int32_t bfSize; + u_int16_t bfReserved1; + u_int16_t bfReserved2; + u_int32_t bfOffBits; + } BITMAPFILEHEADER; + + typedef struct BITMAPINFOHEADER + { + u_int32_t biSize; + u_int32_t biWidth; + u_int32_t biHeight; + u_int16_t biPlanes; + u_int16_t biBitCount; + u_int32_t biCompression; + u_int32_t biSizeImage; + u_int32_t biXPelsPerMeter; + u_int32_t biYPelsPerMeter; + u_int32_t biClrUsed; + u_int32_t biClrImportant; + } BITMAPINFODEADER; +#pragma pack(pop) + + int save_2_bmp_file(const char *bmp_file, void *buf, int w, int h, int resolution) + { + BITMAPINFOHEADER bih = {0}; + BITMAPFILEHEADER fh = {0}; + int pal_size = 0, line_len = (w * 24 + 31) / 32 * 4; + FILE *dst = fopen(bmp_file, "wb"); + + if (!dst) + return errno; + + bih.biSize = sizeof(bih); + bih.biWidth = w; + bih.biBitCount = 24; + bih.biSizeImage = h * line_len; + bih.biPlanes = 1; + bih.biHeight = h; + bih.biCompression = 0; + bih.biXPelsPerMeter = bih.biYPelsPerMeter = resolution * 39.37f + .5f; + + fh.bfType = 'B' | ('M' << 8); + fh.bfOffBits = sizeof(fh) + sizeof(bih) + pal_size; + fh.bfSize = fh.bfOffBits + bih.biSizeImage; + + fwrite(&fh, 1, sizeof(fh), dst); + fflush(dst); + + printf("width * 3 = %d, line bytes = %d\n", w * 3, line_len); + unsigned char *ptr = (unsigned char *)buf; + unsigned int pad = 0; + int pad_l = 4 - ((w * 3) % 4), step = w * 3; + + if (0) + { + ptr += w * 3 * (h - 1); + step *= -1; + } + if (line_len == w * 3) + { + bih.biHeight *= -1; + fwrite(&bih, 1, sizeof(bih), dst); + fwrite(buf, 1, bih.biSizeImage, dst); + } + else + { + fwrite(&bih, 1, sizeof(bih), dst); + for (int i = 0; i < h; ++i) + { + fwrite(ptr, w * 3, 1, dst); + fwrite(&pad, 1, pad_l, dst); + ptr += step; + } + } + fclose(dst); + + return 0; + } + +} static const std::string loggername = "imageusbhandler"; ImageUsbHandler::ImageUsbHandler(std::shared_ptr images) - : pool(1), encodepools(6),pushpool(1), que_len_(0) + : pool(1), encodepools(6), pushpool(1), que_len_(0) { LOG_INIT(); this->images = images; - m_dog.reset(new CImageApplyDogEarDetection(40,1.0,50)); + m_dog.reset(new CImageApplyDogEarDetection(40, 1.0, 50)); // m_colorcast.reset(new CImageApplyColorCastCorrect()); m_sizedetect.reset(new CSizedetect(1)); initLut(); - auto info= jsonconfig().getscannerinfo(); - H_ratio =*((float*)(&info.H_ratio)); - V_ratio =*((float*)(&info.V_ratio)); + auto info = jsonconfig().getscannerinfo(); + H_ratio = *((float *)(&info.H_ratio)); + V_ratio = *((float *)(&info.V_ratio)); } ImageUsbHandler::~ImageUsbHandler() { - } +static int push_img_data_times = 0; +static int take_img_data_times = 0; static int num = 0; -void ImageUsbHandler::add_image(void *data, int width, int height, int type, int scannnum,std::uint32_t fpga_vs,CISVendor cistype) +void ImageUsbHandler::add_image(void *data, int width, int height, int type, int scannnum, std::uint32_t fpga_vs, CISVendor cistype) { - printf("add_image(%u * %u)\n", width, height); + printf("\nadd_image(%u * %u), memory usage = %s\n", width, height, sys_util::format_readable_bytes(sys_util::get_memory_usage("scan")).c_str()); + + images->push(nullptr, false); + // bmp::save_2_bmp_file((std::string("/root/.scanner/log/cap_") + std::to_string(scannnum) + ".bmp").c_str(), data, width / 3, height, 200); + PACKIMAGE pkimg; + + memset(&pkimg, 0, sizeof(pkimg)); + pkimg.pos.paper_ind = scannnum; + pkimg.pos.status = IMG_STATUS_OK; + pkimg.pos.paper_side = PAPER_SIDE_LEFT; + std::string ext = ".jpg"; { if (m_imgstatus.status != NO_error) return; cv::Mat mat; - if(m_scanconfig.g200params.dpi == 3) + if (m_scanconfig.g200params.dpi == 3) mat = cv::Mat(height, width, CV_8UC1, data); else - mat = cv::Mat(height, width, CV_8UC1, data).clone(); + mat = cv::Mat(height, width, CV_8UC1, data).clone(); + printf("Image %d parameters: %d * %d * %d\n", scannnum, mat.cols, mat.rows, mat.channels() * 8); capture_data.Put(mat); StopWatch checktime; - if (m_hgimgconfig.is_dogeardetection || m_hgimgconfig.en_sizecheck) - { - cv::Mat tmp = cv::Mat(height, width, CV_8UC1, data); - if (tmp.empty()) - return; - m_imgstatus.status = Img_Detecting; -#ifdef G300 - auto mergemat = GetStitchMat(type == 16?1:0,width,height,tmp); -#else - auto mergemat = GetMergeMat(type == CV_8UC1 ? width : width / 3, height, type, tmp,0x90001); -#endif - if (m_scanconfig.g200params.dpi == 1) - cv::resize(mergemat, mergemat, cv::Size(0, 0), 200.0 / 300.0, 1.0); - else if (m_scanconfig.g200params.dpi == 2) - cv::resize(mergemat, mergemat, cv::Size(0, 0), 200.0 / 300.0, 200.0 / 300.0); - else - { -#ifdef G200 - cv::resize(mergemat,mergemat,cv::Size(0,0),200.0 / 600.0,1.43434/3); // 600 dpi ��������ʵ600�ɼ� -#elif defined G300 - cv::resize(mergemat,mergemat,cv::Size(0,0),200.0 / 600.0,1.432323/3); -#elif defined G400 - cv::resize(mergemat,mergemat,cv::Size(0,0),200.0 / 600.0,1.5/3); -#else - cv::resize(mergemat,mergemat,cv::Size(0,0),200.0 / 600.0,1.432323/3); -#endif - } - - if (m_hgimgconfig.is_dogeardetection) - { - printf("\n is_dogeardetection"); - if(!m_scanconfig.g200params.pc_correct) - correctColor(mergemat, false); - auto dogmat=mergemat(cv::Rect(mergemat.cols/2, 0, mergemat.cols/2, mergemat.rows)); - m_dog->apply(dogmat,0); - if(m_dog->getResult()) - { - m_imgstatus.status=Dog_error; - m_imgstatus.sannum=scannnum; - add_scanevent({.From=IMG,.Code=m_imgstatus.status,.Img_Index=m_imgstatus.sannum}); - return; - } - } - if(m_hgimgconfig.en_sizecheck) - { - auto sizemat=mergemat(cv::Rect(mergemat.cols/2, 0, mergemat.cols/2, mergemat.rows)); - printf("\n en_sizecheck %d",m_scanconfig.g200params.paper); - m_sizedetect->SetPapertype(m_scanconfig.g200params.paper); - if(m_sizedetect->preprocess(sizemat,NULL)) - { - m_imgstatus.status=Size_error; - m_imgstatus.sannum=scannnum; - add_scanevent({.From=IMG,.Code=m_imgstatus.status,.Img_Index=m_imgstatus.sannum}); - return; - } - } - m_imgstatus.status = NO_error; - } - //tmp.release(); - - //std::lock_guard guard(mtx); add_que_count(); results.emplace( - pool.enqueue([this, width, height, type, ext, scannnum, data,cistype] + pool.enqueue([this, width, height, type, ext, scannnum, data, cistype] { - printf("enqueue image index %d \n",scannnum); - StopWatch sw; - cv::Mat mat = capture_data.Take(); - if(m_scanconfig.g200params.dpi == 3) - mat = cv::Mat(height, width, CV_8UC1, data); - else - mat = cv::Mat(height, width, CV_8UC1, data).clone(); - capture_data.Put(mat); + printf("\nenqueue image index %d \n",scannnum); + StopWatch sw; + cv::Mat mat = capture_data.Take(); #ifdef G300 cv::Mat saveMat = GetStitchMat(type == 16?1:0,width,height,mat); #else int dstwidth = type==CV_8UC1?width:width/3; cv::Mat saveMat =GetMergeMat(dstwidth, height, type,mat,0x90001); #endif - printf("\n GetMergeMat time %f \n",sw.elapsed_ms()); + printf("Merged image: %d * %d * %d\n", saveMat.cols, saveMat.rows, saveMat.channels() * 8); + + //printf("\n GetMergeMat time %f \n",sw.elapsed_ms()); //cv::imwrite("/home/"+to_string(scannnum)+".png",saveMat); int dpi = saveMat.cols==7344?2:3; if(!m_scanconfig.g200params.pc_correct) @@ -137,7 +176,7 @@ void ImageUsbHandler::add_image(void *data, int width, int height, int type, int add_que_count(); encodeimgs.push(encodepools.enqueue([this,width,height,type,cistype]() -> std::vector { - auto saveMat = encode_data.Take(); + auto saveMat = encode_data.Take(); if(H_ratio>1.2f ||H_ratio<0.8f) H_ratio=1.0f; if(V_ratio>1.2f || V_ratio <0.8f) @@ -152,15 +191,17 @@ void ImageUsbHandler::add_image(void *data, int width, int height, int type, int cv::resize(saveMat,saveMat,cv::Size(),H_ratio,V_ratio); } if(m_scanconfig.g200params.dpi == 3) - #ifdef G200 - cv::resize(saveMat,saveMat,cv::Size(0,0),1.0*H_ratio,1.43434*V_ratio); // 600 dpi ��������ʵ600�ɼ� - #elif defined G300 +#ifdef G200 + cv::resize(saveMat,saveMat,cv::Size(0,0),1.0*H_ratio,1.43434*V_ratio); // 600 dpi ��������ʵ600�ɼ� +#elif defined G300 cv::resize(saveMat,saveMat,cv::Size(0,0),1.0*H_ratio,1.432323*V_ratio); - #elif defined G400 +#elif defined G400 cv::resize(saveMat,saveMat,cv::Size(0,0),1.0*H_ratio,1.5*V_ratio); - #else +#else cv::resize(saveMat,saveMat,cv::Size(0,0),1.0*H_ratio,1.432323*V_ratio); - #endif +#endif + printf("dpi = %d, image = %d * %d * %d\n", m_scanconfig.g200params.dpi, saveMat.cols, saveMat.rows, saveMat.channels() * 8); + cv::Mat imageMat; std::vector imgs; int actwidth = saveMat.cols / 2; @@ -173,13 +214,12 @@ void ImageUsbHandler::add_image(void *data, int width, int height, int type, int imgs.push_back(imageMat); } } - // cv::imwrite("/home/proc.jpg",saveMat); - imgs.push_back(saveMat); - std::shared_ptr imageencode; //(new BmpImageEncode()); - std::vector encodedata; - bool iscorrect_mode =true; - if(!iscorrect_mode) - //if (!m_scanconfig.g200params.iscorrect_mode) + // imgs.push_back(saveMat); + std::shared_ptr imageencode; //(new BmpImageEncode()); + std::vector encodedata; + //bool iscorrect_mode =true; + //if(!iscorrect_mode) + if (!m_scanconfig.g200params.iscorrect_mode) { if (!m_hgimgconfig.is_switchfrontback && (imgs.size() > 1)) std::swap(imgs[0], imgs[1]); @@ -213,9 +253,10 @@ void ImageUsbHandler::add_image(void *data, int width, int height, int type, int cv::cvtColor(enMat,enMat,cv::COLOR_BGR2GRAY); } if(m_scanconfig.g200params.iscorrect_mode) - imageencode.reset(new JpegImageEncode(false)); + imageencode.reset(new JpegImageEncode(false, m_hgimgconfig.resolution_dst)); else - imageencode.reset(new JpegImageEncode(false)); + imageencode.reset(new JpegImageEncode(m_scanconfig.g200params.color?false:true, m_hgimgconfig.resolution_dst)); + encodedata.push_back(imageencode->encode(enMat)); } } @@ -229,20 +270,28 @@ void ImageUsbHandler::add_image(void *data, int width, int height, int type, int for (auto &data : mem) { if (data.get()) - images->push(data, true); + { + images->push(data, true); + } + else add_scanevent({.From = V4L2, .Code = 1}); } } + else + printf("!!!!!!!!! mem proc = empty vector \n"); + add_que_count(-1); }); - printf("imgproce time = %f \n", sw.elapsed_ms()); - LOG_TRACE(string_format("imgproce time = %f\n", sw.elapsed_ms())); })); - add_que_count(-1); + //printf("imgproce time = %f \n", sw.elapsed_ms()); + //LOG_TRACE(string_format("imgproce time = %f\n", sw.elapsed_ms())); + })); + add_que_count(-1); } } -bool ImageUsbHandler::is_limit(){ +bool ImageUsbHandler::is_limit() +{ if (m_hgimgconfig.resolution_dst > 200.0 || m_hgimgconfig.papertype == 52 || m_hgimgconfig.papertype == 54 || m_hgimgconfig.papertype == 131) { @@ -250,7 +299,7 @@ bool ImageUsbHandler::is_limit(){ { results.front().get(); { - //std::lock_guard guard(mtx); + // std::lock_guard guard(mtx); results.pop(); } } @@ -265,7 +314,7 @@ bool ImageUsbHandler::is_limit(){ { results.front().get(); { - //std::lock_guard guard(mtx); + // std::lock_guard guard(mtx); results.pop(); } } @@ -277,11 +326,10 @@ bool ImageUsbHandler::is_limit(){ return false; } - void ImageUsbHandler::thread_push_stop_event(HGIntInfo ev) { printf("Received STOPSCAN event, but image-process is busying, wait real stop in thread ...\n"); - while(!done()) + while (!done()) { std::this_thread::sleep_for(std::chrono::milliseconds(3)); } @@ -307,9 +355,9 @@ int32_t ImageUsbHandler::add_que_count(int adden) void ImageUsbHandler::add_scanevent(HGIntInfo status) { printf("add_scanevent(%d)\n", status.From); - if(status.From == STOPSCAN && !done()) + if (status.From == STOPSCAN && !done()) { - if(stop_event_thread_.get() && stop_event_thread_->joinable()) + if (stop_event_thread_.get() && stop_event_thread_->joinable()) stop_event_thread_->join(); stop_event_thread_.reset(new std::thread(&ImageUsbHandler::thread_push_stop_event, this, status)); } @@ -330,39 +378,58 @@ void ImageUsbHandler::clear() capture_data.Clear(); } -void ImageUsbHandler::Set_ratio(u32 h_ratio,u32 v_ratio) +void ImageUsbHandler::Set_ratio(u32 h_ratio, u32 v_ratio) { - H_ratio =*((float*)(&h_ratio)); - //V_ratio =*((float*)(&v_ratio)); + H_ratio = *((float *)(&h_ratio)); + // V_ratio =*((float*)(&v_ratio)); V_ratio = 1.0f; } bool ImageUsbHandler::done() { - return add_que_count(0) == 0; + // return add_que_count(0) == 0; - bool over = true; - { - std::lock_guard guard(mtx); - if(results.size() >= 1){ - auto &fu_run = results.back(); - if((fu_run.valid() && (fu_run.wait_for(std::chrono::seconds(0)) != std::future_status::ready))) - over = false; - } - if(over && encodeimgs.size()>=1) - { - auto &fu_encode = encodeimgs.back(); - over = !fu_encode.valid() || encodeimgs.size() == 0; - // if((!fu_encode.valid()) && encodeimgs.size() == 1) - // over = true; - // else - // over = false; - // return !(fu_encode.wait_for(std::chrono::seconds(0)) != std::future_status::ready); - //return (!(fu_run.wait_for(std::chrono::seconds(0)) != std::future_status::ready))&&(!(fu_encode.wait_for(std::chrono::seconds(0)) != std::future_status::ready)); - } + // bool over = true; + // { + // std::lock_guard guard(mtx); + // if (results.size() >= 1) + // { + // auto &fu_run = results.back(); + // if ((fu_run.valid() && (fu_run.wait_for(std::chrono::seconds(0)) != std::future_status::ready))) + // over = false; + // } + // if (over && encodeimgs.size() >= 1) + // { + // auto &fu_encode = encodeimgs.back(); + // over = !fu_encode.valid() || encodeimgs.size() == 0; + // // if((!fu_encode.valid()) && encodeimgs.size() == 1) + // // over = true; + // // else + // // over = false; + // // return !(fu_encode.wait_for(std::chrono::seconds(0)) != std::future_status::ready); + // // return (!(fu_run.wait_for(std::chrono::seconds(0)) != std::future_status::ready))&&(!(fu_encode.wait_for(std::chrono::seconds(0)) != std::future_status::ready)); + // } + // } + + // return over; + std::lock_guard guard(mtx); + if(results.size() >= 1){ + auto &fu_run = results.back(); + if((fu_run.valid() && (fu_run.wait_for(std::chrono::seconds(0)) != std::future_status::ready))) + return false; } + if(encodeimgs.size()>=1) + { + auto &fu_encode = encodeimgs.back(); + if((!fu_encode.valid()) && encodeimgs.size() == 1) + return true; + else + return false; + return !(fu_encode.wait_for(std::chrono::seconds(0)) != std::future_status::ready); + //return (!(fu_run.wait_for(std::chrono::seconds(0)) != std::future_status::ready))&&(!(fu_encode.wait_for(std::chrono::seconds(0)) != std::future_status::ready)); - return over; + } + return true; } void ImageUsbHandler::config_procparams(HGImgProcParms params) @@ -376,3 +443,61 @@ void ImageUsbHandler::config_procparams(HGImgProcParms params) LOG_TRACE(string_format("HGImgProcParms.fillhole = %d \n", params.imgprocparams.fillhole)); m_procparams = params; } + +//{ +// "montage": { +// "category": "base", +// "readonly" : false, +// "affect" : 0, +// "group" : "base", +// "visible" : false, +// "field" : "cis", +// "pos" : 10, +// "unit" : "None", +// "title" : "图像拼接", +// "desc" : "将CIS采集的原始数据恢复为正常的图像", +// "type" : "bool", +// "cur" : true, +// "default" : true, +// "size" : 4, +// }, +// "fb-split": { +// "category": "base", +// "readonly" : false, +// "affect" : 0, +// "group" : "base", +// "visible" : false, +// "field" : "cis", +// "pos" : 20, +// "unit" : "None", +// "title" : "拆分正反面", +// "desc" : "将正反面合成的一张图片,拆分成正面和反面图片", +// "type" : "bool", +// "cur" : true, +// "default" : true, +// "size" : 4, +// "depend_and": ["montage==true"] +// } +//} +// +// +// +//{ +// "compress": { +// "category": "base", +// "readonly" : false, +// "affect" : 0, +// "group" : "base", +// "visible" : false, +// "field" : "imgproc", +// "pos" : 9999, +// "unit" : "None", +// "title" : "图像压缩", +// "desc" : "图片压缩成指定文件格式", +// "type" : "string", +// "cur" : "jpeg", +// "default" : "jpeg", +// "size" : 32, +// "range": ["none", "zip", "jpeg", "png", "bmp"] // none & zip 方式的数据为PACKIMAGE + 图像点阵数据 +// } +//} diff --git a/device/gxx-linux/scanner/imageusbtesthandler.cpp b/device/gxx-linux/scanner/imageusbtesthandler.cpp index 43912d4..2ebd7bc 100644 --- a/device/gxx-linux/scanner/imageusbtesthandler.cpp +++ b/device/gxx-linux/scanner/imageusbtesthandler.cpp @@ -14,7 +14,7 @@ ImageUsbTestHandler::ImageUsbTestHandler(std::shared_ptr imag { } -void ImageUsbTestHandler::add_image(void* data, int width, int height, int type ,int scannnum) +void ImageUsbTestHandler::add_image(void* data, int width, int height, int type ,int scannnum,std::uint32_t fpga_vs,CISVendor cistype) { // results.emplace_back( // pool.enqueue([this, data, width, height, type] diff --git a/device/gxx-linux/scanner/imageusbtesthandler.h b/device/gxx-linux/scanner/imageusbtesthandler.h index b056ebf..7d87b5d 100644 --- a/device/gxx-linux/scanner/imageusbtesthandler.h +++ b/device/gxx-linux/scanner/imageusbtesthandler.h @@ -6,5 +6,5 @@ class ImageUsbTestHandler : public ImageUsbHandler { public: ImageUsbTestHandler(std::shared_ptr images = nullptr); - virtual void add_image(void* data, int width, int height, int type,int scannnum); + virtual void add_image(void* data, int width, int height, int type,int scannnum,std::uint32_t fpga_vs,CISVendor cistype); }; \ No newline at end of file diff --git a/device/gxx-linux/scanner/iscanner.cpp b/device/gxx-linux/scanner/iscanner.cpp new file mode 100644 index 0000000..4c1cef0 --- /dev/null +++ b/device/gxx-linux/scanner/iscanner.cpp @@ -0,0 +1,344 @@ +#include "iscanner.h" +#include +#include "Imotorboard.h" +#include "Capturer.h" +#include +#include "StopWatch.h" +#include "iimagehandler.h" +#include "correct_ultis.h" +#include "applog.h" +#include "stringex.hpp" +#include "fpgacontrol.h" +#include "scannerregs.h" +#include "fpgacontrol.h" +#include "Gpio.h" +#include "deviceconfig.h" +#include +#include +#include +#include + +static const std::string loggername = "IScanner"; + +IScanner::IScanner(std::shared_ptr capturer, std::shared_ptr mb, std::shared_ptr wake) + : bMsgLoop(true), + scancount(1024) +// testGpio(new Gpio(153)) +{ + LOG_INIT(); + this->wake = wake; + this->mb = mb; + this->capturer = capturer; + mb->set_capture(capturer); + scannerinfo = getscannerinfo(); + auto capturecallback = [&](int cap_call_code, std::string s_info) + { + HGIntInfo info = {.From = AutoCorrect, .Code = cap_call_code, .Img_Index = s_info.length()}; + imagehandler->add_scanevent(info); + if (s_info.length() > 0) + ((ScannerRegAccess *)m_parent)->write_info(s_info); + }; + this->capturer->setcapturecall(capturecallback); +} + +IScanner::~IScanner() +{ + bMsgLoop = false; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + sysEvent.Put(ScanEvent::S_EVT_STOP_SCAN); + + if (threadRunMessageLoop.joinable()) + threadRunMessageLoop.join(); +} +bool IScanner::check_scan(std::string encodehexstr){ + bool is_scan = true; + if(DeviceConfig().GetParam().is_lock) + { + auto tmp_token = DeviceConfig().GetParam().token; + if((encodehexstr.length() != 32) || (tmp_token.length() !=32)) + is_scan = false; + else{ + AES_KEY aes_key; + std::uint8_t key[16] ={0}; + //tmp_token = "C34E58CD5F3F2FF703E1AA24892FBD69"; + printf("tmp_token %s",tmp_token); + for(int i =0;i<16;i++) + { + key[i] = std::strtol(tmp_token.substr(i*2,2).c_str(),nullptr,16); + } + if(AES_set_decrypt_key(key,128,&aes_key)< 0) + { + is_scan = false; + } + std::uint8_t cipher[16] ={0}; + std::uint8_t decode[16] ={0}; + for(int i =0;i<16;i++) + { + cipher[i] = std::strtol(encodehexstr.substr(i*2,2).c_str(),nullptr,16); + } + + AES_ecb_encrypt(cipher,decode,&aes_key,AES_DECRYPT); + for(int i =0;iadd_scanevent({.From = MtBoard, 0x100}); + if (m_config.g200params.is_autopaper) + imagehandler->add_scanevent({.From = STOPSCAN, 1}); + imagehandler->add_scanevent({.From = STOPSCAN, 0}); + } + return is_scan; +} + +std::string IScanner::getmbversion() +{ + return mbversion; +} + +void IScanner::add_scansever(HGIntInfo event) +{ + if (imagehandler.get()) + imagehandler->add_scanevent(event); +} + +bool IScanner::set_hgimgconfig(GScanCap config) +{ + printf("enter config set_hgimgconfig \n"); + scancount = config.is_duplex ? config.scannum / 2 : config.scannum; + m_cap = config; + mb->set_scancap(config); + if(config.resolution_dst < 300) + m_config.g200params.dpi = 1; +#ifdef G300 + else + m_config.g200params.dpi = 2; +#else + else if ((config.resolution_dst >= 300) &&(config.resolution_dst < 500)) + m_config.g200params.dpi = 2; + else + m_config.g200params.dpi = 3; +#endif + if(config.HsvFilterType!=0 || config.filter!=3 ||config.fadeback!=0) + m_config.g200params.color = 1; + + printf("\n m_config.g200params.dpi =%d",m_config.g200params.dpi); + imagehandler->set_scanconfig(m_config); + if (config.is_autocrop && (config.papertype == 0)&&m_config.g200params.en_autosize) + m_config.g200params.paper = 16; + if(config.papertype == 54) + m_config.g200params.paper = m_config.g200params.en_autosize? 16 : 17; + if(config.papertype == 52 || config.papertype == 131) + m_config.g200params.paper = m_config.g200params.en_autosize? 16 : 18; + if (imagehandler.get()) + { + imagehandler->clear(); + return imagehandler->set_config(config); + } + return false; +} + +void IScanner::configparam(HGScanConfig config) +{ + LOG_TRACE(string_format("******HGScanConfig******\n config.g200params.color = %d \n config.g200params.dpi = %d \n config.g200params.paper =%d \n config.g200params.double_feed_enbale = %d \n config.g200params.stable_enbale = %d \n config.g200params.iscorrect_mode = %d \n config.g200params.pc_correct = %d\n ", + config.g200params.color, + config.g200params.dpi, + config.g200params.paper, + config.g200params.double_feed_enbale, + config.g200params.stable_enbale, + config.g200params.iscorrect_mode, + config.g200params.pc_correct)); + printf("******HGScanConfig******\n config.g200params.color = %d \n config.g200params.dpi = %d \n config.g200params.paper =%d \n config.g200params.double_feed_enbale = %d \n config.g200params.stable_enbale = %d \n config.g200params.iscorrect_mode = %d \n config.g200params.pc_correct = %d\n ", + config.g200params.color, + config.g200params.dpi, + config.g200params.paper, + config.g200params.double_feed_enbale, + config.g200params.stable_enbale, + config.g200params.iscorrect_mode, + config.g200params.pc_correct); + imagehandler->set_scanconfig(config); + m_config = config; + if (config.g200params.iscorrect_mode) + { + scancount = 65535; + } +} + + + +int IScanner::getimageprocedone() +{ + if (imagehandler.get()) + return imagehandler->done(); + return true; +} + +void IScanner::test_autocorrect(int colormode) +{ + printf("color mode =%s \n", colormode == 1 ? "COLOR" : "GRAY"); + capturer->init_autocorrect(colormode); +} +bool IScanner::is_runscan() +{ + return (fu_runscan && fu_runscan->is_runing()) || (imagehandler && !imagehandler->done()); +} + +void IScanner::set_imagehandler(std::shared_ptr handler) +{ + imagehandler = handler; +} + +void IScanner::clear_error() +{ + mb->clear_error(); +} + +void IScanner::runMessageLoop() +{ + FsmState *fsmState = FsmStateManagerEx::GetState(); + FsmState::setScanner(this); + do + { + ScanEvent evt = sysEvent.Take(); + fsmState = fsmState->on_event(evt); + } while (bMsgLoop); +} + +bool IScanner::paper_ready() +{ + return mb->paper_ready(); +} + +bool IScanner::get_keeplastpaper() +{ + return mb->get_keeplastpaper(); +} + +void IScanner::startcapimage() +{ + FILE * fp =fopen("/sys/class/tty/ttyUSB0/device/huagao_scanner","w"); + if (fp == NULL) + perror("startcapimage open filed"); + else + fprintf(fp,"%d",1); + + fclose(fp); +} + +void IScanner::set_motorboardcallback(MotorBoardGlue glue) +{ + + mb->set_callbacks(glue); +} + +void IScanner::set_imgprocparams(HGImgProcParms params) +{ + imagehandler->config_procparams(params); +} + +void IScanner::test_cap(HGScanConfig config) +{ + printf("capturer openning \n"); + FPGAConfigParam fpgaparam = GetFpgaparam(m_config.g200params.dpi, m_config.g200params.color); + capturer->open(config,fpgaparam); + capturer->snap(); + void *data; + if (data = capturer->readFrame(2000)) + { + int imtype = capturer->color() ? CV_8UC3 : CV_8UC1; + cv::Mat mat; + cv::Mat saveMat; + std::vector ch_mats; + int dstwidth, dstheight; + int width = capturer->width(); + int height = capturer->height(); + dstwidth = width * 3; + dstheight = height / 3; + + if (imtype == CV_8UC3) + { + mat = cv::Mat(height / 3, width * 9, CV_8UC1, data); + saveMat = cv::Mat(dstheight, dstwidth, CV_8UC3); + } + + else + { // gray + saveMat = cv::Mat(height, width * 3, CV_8UC1, data); + } + static int savenum; + if (imtype == CV_8UC3) + { + for (int i = 0; i < 3; i++) + { // B G R + cv::Mat mattemp = mat(cv::Rect(dstwidth * i, 0, dstwidth, dstheight)); + ch_mats.push_back(mattemp); + } + swap(ch_mats[1], ch_mats[2]); + cv::merge(ch_mats, saveMat); + } + //cv::imwrite(std::to_string(++savenum) + ".jpg", saveMat); + } + else + { + printf("LOST Image \n"); + } + capturer->close(); + printf("capturer closed \n"); +} +void IScanner::set_sleeptime(int val) +{ + if (wake.get()) + wake->settime(val); +} + +int IScanner::get_sleeptime() +{ + if (wake.get()) + return wake->gettime(); + return 0; +} + +void IScanner::resettime() +{ + if (wake.get()) + wake->resettime(); +} + +int IScanner::get_sleepstatus() +{ + if (wake.get()) + return wake->get_status(); + return 0; +} + +void IScanner::set_paprent(void *parent) +{ + if (parent) + m_parent = parent; +} +void IScanner::set_sleepstatus(bool off) +{ + if (wake.get()) + { + if (off) + wake->power_on(); + else + wake->power_off(); + } +} + + +void IScanner::clean_paper_road(){ + if(mb.get()) + mb->clean_paper_road(); +} \ No newline at end of file diff --git a/device/gxx-linux/scanner/iscanner.h b/device/gxx-linux/scanner/iscanner.h new file mode 100644 index 0000000..5abc5ff --- /dev/null +++ b/device/gxx-linux/scanner/iscanner.h @@ -0,0 +1,71 @@ +#pragma once +#include +#include +#include "BlockingQueue.h" +#include "fsmstate.h" +#include +#include "commondef.h" +#include "wakeup.hpp" +#include + + +class IMotorBoard; +class ICapturer; +class IImageHandler; +class Gpio; + +class IScanner +{ +public: + IScanner(std::shared_ptr capturer, std::shared_ptr mb, std::shared_ptr wake); + virtual ~IScanner(); + virtual void start_scan() = 0; + virtual void stop_scan() = 0; + virtual int count() = 0; + virtual int mode() = 0; + virtual int getmbstatus() = 0; + virtual bool getpaperon() = 0; + virtual void runScan() = 0; + void clean_paper_road(); + bool check_scan(std::string encodehexstr); + void configparam(HGScanConfig config); + void put(ScanEvent evt) { sysEvent.Put(evt); } + bool is_runscan(); + void set_imagehandler(std::shared_ptr handler = nullptr); + void clear_error(); + bool paper_ready(); + bool get_keeplastpaper(); + void set_motorboardcallback(MotorBoardGlue glue); + void set_imgprocparams(HGImgProcParms parmas); + void test_autocorrect(int colormode); + void test_cap(HGScanConfig config); + bool set_hgimgconfig(GScanCap config); + void add_scansever(HGIntInfo event); + void set_sleeptime(int val); + int get_sleeptime(); + void resettime(); + int get_sleepstatus(); + void set_sleepstatus(bool off); + int getimageprocedone(); + void set_paprent(void* parent); + std::string getmbversion(); + void runMessageLoop(); + void startcapimage(); +protected: + std::thread threadRunMessageLoop; + volatile bool bMsgLoop = true; + BlockingQueue sysEvent; + std::shared_ptr mb; + std::shared_ptr capturer; + std::shared_ptr wake; + std::shared_ptr fu_runscan; + std::shared_ptr m_capturereload; + std::shared_ptr imagehandler; + std::function m_mtcallback; + int scancount=0; + HGScanConfig m_config; + GScanCap m_cap; + ScannerNativeParam scannerinfo; + void* m_parent; + std::string mbversion; +}; diff --git a/device/gxx-linux/scanner/scanner.cpp b/device/gxx-linux/scanner/scanner.cpp index d543c3b..abbf90b 100644 --- a/device/gxx-linux/scanner/scanner.cpp +++ b/device/gxx-linux/scanner/scanner.cpp @@ -1,6 +1,6 @@ #include "scanner.h" #include -#include "motorboard.h" +#include "Imotorboard.h" #include "Capturer.h" #include #include "StopWatch.h" @@ -11,24 +11,13 @@ #include "scannerregs.h" #include "fpgacontrol.h" #include "Gpio.h" -#include "deviceconfig.h" -#include -#include -#include -#include +#include "correct_ultis.h" static const std::string loggername = "Scanner"; -Scanner::Scanner(std::shared_ptr capturer, std::shared_ptr mb, std::shared_ptr wake) - : bMsgLoop(true), - scancount(1024) -// testGpio(new Gpio(153)) +Scanner::Scanner(std::shared_ptr capturer, std::shared_ptr mb, std::shared_ptr wake):IScanner(capturer,mb,wake) { LOG_INIT(); - this->wake = wake; - this->mb = mb; - this->capturer = capturer; - // threadRunMessageLoop = std::move(std::thread(&Scanner::runMessageLoop, this)); auto mb_error_call = [&](unsigned int error_code) { int code = 0; @@ -140,7 +129,7 @@ Scanner::Scanner(std::shared_ptr capturer, std::shared_ptr capturer, std::shared_ptrset_callbacks(mb_glue); - mb->set_capture(capturer); - scannerinfo = getscannerinfo(); - auto capturecallback = [&](int cap_call_code, std::string s_info) - { - HGIntInfo info = {.From = AutoCorrect, .Code = cap_call_code, .Img_Index = s_info.length()}; - imagehandler->add_scanevent(info); - if (s_info.length() > 0) - ((ScannerRegAccess *)m_parent)->write_info(s_info); - }; - this->capturer->setcapturecall(capturecallback); - mb->set_auto_paper(m_config.g200params.is_autopaper); //防止程序异常死掉后未关闭连续扫描导致升降台抬升扫�? + mb->set_auto_paper(m_config.g200params.is_autopaper); //防止程序异常死掉后未关闭连续扫描导致升降台抬升扫描 u32 value; mb->read(0x00, value); - printf("mb reg[0] = 0x%x \n", value); + printf("mb reg[0] = %d \n", value); value = 0; mb->read(0x03, value); if (value >= 35211210) @@ -174,143 +153,12 @@ Scanner::Scanner(std::shared_ptr capturer, std::shared_ptropen(); + printf("mb reg[0] = %d \n", value); } Scanner::~Scanner() { - bMsgLoop = false; - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - sysEvent.Put(ScanEvent::S_EVT_STOP_SCAN); - if (threadRunMessageLoop.joinable()) - threadRunMessageLoop.join(); -} - -void Scanner::try_scan(const std::string encodehexstr) -{ - bool is_scan = true; - printf("\n encodehexstr = "); - for(int i =0;iadd_scanevent({.From = MtBoard, 0x100}); - if (m_config.g200params.is_autopaper) - imagehandler->add_scanevent({.From = STOPSCAN, 1}); - imagehandler->add_scanevent({.From = STOPSCAN, 0}); - } -} - -std::string Scanner::getmbversion() -{ - return mbversion; -} - -void Scanner::add_scansever(HGIntInfo event) -{ - if (imagehandler.get()) - imagehandler->add_scanevent(event); -} - -bool Scanner::set_hgimgconfig(GScanCap config) -{ - printf("enter config set_hgimgconfig \n"); - scancount = config.is_duplex ? config.scannum / 2 : config.scannum; - m_cap = config; - if (imagehandler.get()) - { - imagehandler->clear(); - return imagehandler->set_config(config); - } - return false; -} - -void Scanner::configparam(HGScanConfig config) -{ - LOG_TRACE(string_format("******HGScanConfig******\n config.g200params.color = %d \n config.g200params.dpi = %d \n config.g200params.paper =%d \n config.g200params.double_feed_enbale = %d \n config.g200params.stable_enbale = %d \n config.g200params.iscorrect_mode = %d \n config.g200params.pc_correct = %d\n ", - config.g200params.color, - config.g200params.dpi, - config.g200params.paper, - config.g200params.double_feed_enbale, - config.g200params.stable_enbale, - config.g200params.iscorrect_mode, - config.g200params.pc_correct)); - printf("******HGScanConfig******\n config.g200params.color = %d \n config.g200params.dpi = %d \n config.g200params.paper =%d \n config.g200params.double_feed_enbale = %d \n config.g200params.stable_enbale = %d \n config.g200params.iscorrect_mode = %d \n config.g200params.pc_correct = %d\n ", - config.g200params.color, - config.g200params.dpi, - config.g200params.paper, - config.g200params.double_feed_enbale, - config.g200params.stable_enbale, - config.g200params.iscorrect_mode, - config.g200params.pc_correct); - imagehandler->set_scanconfig(config); - m_config = config; - if (config.g200params.iscorrect_mode) - { - scancount = 65535; - } } void Scanner::start_scan() @@ -321,7 +169,8 @@ void Scanner::start_scan() if (wake.get()) wake->setsleepfalg(true); mb_error_code = is_ml_top = handstop = false; - capturer->open(m_config); + FPGAConfigParam fpgaparam = GetFpgaparam(m_config.g200params.dpi, m_config.g200params.color); + capturer->open(m_config,fpgaparam); scannerinfo = getscannerinfo(); int spdmode = 0; if (scannerSp.count((SpeedMode)scannerinfo.speedmode) <= 0) @@ -336,10 +185,8 @@ void Scanner::start_scan() { spdmode = scannerSp[(SpeedMode)scannerinfo.speedmode].motorSpeed; } - mb->set_speed_mode(spdmode); - imagehandler->Set_ratio(scannerinfo.H_ratio,scannerinfo.V_ratio); + mb->set_speed_mode(spdmode,1,1); printf("\n set speedmode %d read speedmode %d", spdmode, mb->get_speed_mode()); - // capturer->open(); imagehandler->resetimgstatus(); mb->clear_error(); fu_runscan.reset(new ThreadEx(&Scanner::runScan, this)); @@ -362,14 +209,6 @@ int Scanner::mode() { return mb->os_mode(); } - -int Scanner::getimageprocedone() -{ - if (imagehandler.get()) - return imagehandler->done(); - return true; -} - int Scanner::getmbstatus() { mb->clear_error(); @@ -379,57 +218,6 @@ int Scanner::getmbstatus() return val & 0x700fe; } -void Scanner::test_autocorrect(int colormode) -{ - printf("color mode =%s \n", colormode == 1 ? "COLOR" : "GRAY"); - capturer->init_autocorrect(colormode); -} -bool Scanner::is_runscan() -{ - return (fu_runscan && fu_runscan->is_runing()) || (imagehandler && !imagehandler->done()); -} - -void Scanner::set_imagehandler(std::shared_ptr handler) -{ - imagehandler = handler; -} - -void Scanner::clear_error() -{ - mb->clear_error(); -} - -void Scanner::runMessageLoop() -{ - FsmState *fsmState = FsmStateManagerEx::GetState(); - FsmState::setScanner(this); - do - { - ScanEvent evt = sysEvent.Take(); - fsmState = fsmState->on_event(evt); - } while (bMsgLoop); -} - -bool Scanner::paper_ready() -{ - return mb->paper_ready(); -} - -bool Scanner::get_keeplastpaper() -{ - return mb->get_keeplastpaper(); -} - -void Scanner::startcapimage() -{ - FILE * fp =fopen("/sys/class/tty/ttyUSB0/device/huagao_scanner","w"); - if (fp == NULL) - perror("startcapimage open filed"); - else - fprintf(fp,"%d",1); - - fclose(fp); -} static int pickpapernum = 0; void Scanner::runScan() @@ -457,11 +245,9 @@ void Scanner::runScan() imagehandler->add_scanevent({.From = MtBoard, .Code = 4}); LOG_TRACE("\nCover Open status"); imagehandler->add_scanevent({.From = STOPSCAN, 0}); - } - if (m_config.g200params.is_autopaper) - { - imagehandler->add_scanevent({.From = STOPSCAN, 1}); - mb->set_auto_paper(false); + if (mb_error_code != 0 && m_config.g200params.is_autopaper) + mb->set_auto_paper(false); + return; } imagehandler->add_scanevent({.From = MtBoard, .Code = val & 0x700fe}); printf("\n scan stop code =%d ", val & 0x700fe); @@ -480,14 +266,8 @@ void Scanner::runScan() } if (!is_ml_top || mb_error_code || handstop) { - if (mb_error_code == 0 && handstop == 0) // 无其他异常时,发送升降台未到达指定位置异�? - { + if (mb_error_code == 0 && handstop == 0) // 无其他异常时,发送升降台未到达指定位置异常 imagehandler->add_scanevent({.From = MtBoard, 0x80000}); - if (m_config.g200params.is_autopaper) - mb->set_auto_paper(false); - } - capturer->stop(); - capturer->close(); capturer->reset(); this_thread::sleep_for(chrono::milliseconds(20)); imagehandler->add_scanevent({.From = STOPSCAN, 0}); @@ -509,126 +289,25 @@ void Scanner::runScan() wake->resettime(); wake->setsleepfalg(false); } - - capturer->reset(); imagehandler->add_scanevent({.From = STOPSCAN, 0}); - if ((mb_error_code != 0 || imagehandler->getimgstatus().status != NO_error ) && m_config.g200params.is_autopaper) + capturer->reset(); + if (mb_error_code != 0 && m_config.g200params.is_autopaper) mb->set_auto_paper(false); printf("\n-------scanner done-------\n"); } -void Scanner::set_motorboardcallback(MotorBoardGlue glue) -{ - - mb->set_callbacks(glue); -} - -void Scanner::set_imgprocparams(HGImgProcParms params) -{ - imagehandler->config_procparams(params); -} - -void Scanner::test_cap(HGScanConfig config) -{ - printf("capturer openning \n"); - capturer->open(config); - capturer->snap(); - void *data; - if (data = capturer->readFrame(2000)) - { - int imtype = capturer->color() ? CV_8UC3 : CV_8UC1; - cv::Mat mat; - cv::Mat saveMat; - std::vector ch_mats; - int dstwidth, dstheight; - int width = capturer->width(); - int height = capturer->height(); - dstwidth = width * 3; - dstheight = height / 3; - - if (imtype == CV_8UC3) - { - mat = cv::Mat(height / 3, width * 9, CV_8UC1, data); - saveMat = cv::Mat(dstheight, dstwidth, CV_8UC3); - } - - else - { // gray - saveMat = cv::Mat(height, width * 3, CV_8UC1, data); - } - static int savenum; - if (imtype == CV_8UC3) - { - for (int i = 0; i < 3; i++) - { // B G R - cv::Mat mattemp = mat(cv::Rect(dstwidth * i, 0, dstwidth, dstheight)); - ch_mats.push_back(mattemp); - } - swap(ch_mats[1], ch_mats[2]); - cv::merge(ch_mats, saveMat); - } - cv::imwrite(std::to_string(++savenum) + ".jpg", saveMat); - } - else - { - printf("LOST Image \n"); - } - capturer->close(); - printf("capturer closed \n"); -} -void Scanner::set_sleeptime(int val) -{ - if (wake.get()) - wake->settime(val); -} - -int Scanner::get_sleeptime() -{ - if (wake.get()) - return wake->gettime(); - return 0; -} - -void Scanner::resettime() -{ - if (wake.get()) - wake->resettime(); -} - -int Scanner::get_sleepstatus() -{ - if (wake.get()) - return wake->get_status(); - return 0; -} - -void Scanner::set_paprent(void *parent) -{ - if (parent) - m_parent = parent; -} -void Scanner::set_sleepstatus(bool off) -{ - if (wake.get()) - { - if (off) - wake->power_on(); - else - wake->power_off(); - } -} - bool Scanner::getpaperon() { +#ifdef G200 if (mb.get()) { uint val = 0; mb->read(2, val); - if ((val & 0x10000) && m_config.g200params.is_autopaper) - mb->set_auto_paper(false); return val & 0x10000; } return 0; +#endif + return 1; } void Scanner::scanpaperout() { @@ -648,7 +327,7 @@ void Scanner::scanpaperout() //LOG_TRACE(string_format("+++++paper on:%fms+++++++++++ ", swCap.elapsed_ms())); if (mb->wait_paper_out(3000)) { - HG_LOG("wait_paper_out time =%f \n",sw.elapsed_ms()); + printf("wait_paper_out time =%f \n",sw.elapsed_ms()); sw.reset(); swCap.reset(); if (data = capturer->readFrame(2000)) @@ -656,13 +335,11 @@ void Scanner::scanpaperout() printf("\n readFrame time =%f pickpapernum = %d",swCap.elapsed_ms(),pickpapernum++); if (imagehandler) { - imagehandler->add_image(data, capturer->width(), capturer->height() / 3 * 3, capturer->color(), scannum++); + imagehandler->add_image(data, capturer->width(), capturer->height() / 3 * 3, capturer->color(), scannum++,0x90001,CISVendor::DUNNAN_CIS_V0); data = NULL; } - //std::this_thread::sleep_for(std::chrono::milliseconds(100)); swCap.reset(); scannerinfo.RollerNum++; - scannerinfo.TotalScanned++; LOG_TRACE(string_format("capture one=%fms", swCap.elapsed_ms())); } else @@ -755,7 +432,7 @@ void Scanner::scanold() swCap.reset(); if (imagehandler) { - imagehandler->add_image(data, capturer->width(), capturer->height() / 3 * 3, capturer->color(), scannum++); + imagehandler->add_image(data, capturer->width(), capturer->height() / 3 * 3, capturer->color(), scannum++,0x90001,CISVendor::DUNNAN_CIS_V0); data = NULL; } LOG_TRACE(string_format("readFrame time =%f ",swCap.elapsed_ms())); diff --git a/device/gxx-linux/scanner/scanner.h b/device/gxx-linux/scanner/scanner.h index ffcd811..2afab49 100644 --- a/device/gxx-linux/scanner/scanner.h +++ b/device/gxx-linux/scanner/scanner.h @@ -1,11 +1,5 @@ #pragma once -#include -#include -#include "BlockingQueue.h" -#include "fsmstate.h" -#include -#include "commondef.h" -#include "wakeup.hpp" +#include "iscanner.h" enum MotorVersion : uint{ Motor_old, @@ -13,72 +7,25 @@ enum MotorVersion : uint{ Motor_paperout, }; -class MotorBoard; -class ICapturer; -class IImageHandler; -class Gpio; - -class Scanner +class Scanner : public IScanner { public: - Scanner(std::shared_ptr capturer, std::shared_ptr mb, std::shared_ptr wake); - ~Scanner(); - void try_scan(const std::string encodehexstr); - void configparam(HGScanConfig config); - void start_scan(); - void stop_scan(); - - int count(); - int mode(); - void put(ScanEvent evt) { sysEvent.Put(evt); } - bool is_runscan(); - void set_imagehandler(std::shared_ptr handler = nullptr); - void clear_error(); - bool paper_ready(); - bool get_keeplastpaper(); - void set_motorboardcallback(MotorBoardGlue glue); - void set_imgprocparams(HGImgProcParms parmas); - void test_autocorrect(int colormode); - void test_cap(HGScanConfig config); - bool set_hgimgconfig(GScanCap config); - void add_scansever(HGIntInfo event); - void set_sleeptime(int val); - int get_sleeptime(); - void resettime(); - int get_sleepstatus(); - void set_sleepstatus(bool off); - int getimageprocedone(); - void set_paprent(void* parent); - bool getpaperon(); - int getmbstatus(); - std::string getmbversion(); + Scanner(std::shared_ptr capturer, std::shared_ptr mb, std::shared_ptr wake); + virtual ~Scanner(); + virtual void start_scan() override; + virtual void stop_scan() override; + virtual int count() override; + virtual int mode() override; + virtual int getmbstatus() override; + virtual bool getpaperon() override; + virtual void runScan() override; private: - void runMessageLoop(); - void runScan(); - void startcapimage(); void scanold(); void scanpaperout(); - //std::shared_ptr testGpio; - std::thread threadRunMessageLoop; - volatile bool bMsgLoop = true; - BlockingQueue sysEvent; - - std::shared_ptr mb; - std::shared_ptr capturer; - std::shared_ptr wake; - - std::shared_ptr fu_runscan; - std::shared_ptr imagehandler; - std::function m_mtcallback; volatile int done_scan = 0; volatile bool is_ml_top = 0; volatile bool handstop = 0; - int scancount=0; - volatile unsigned int mb_error_code; + volatile int mb_error_code = 0; MotorVersion m_mbver; - HGScanConfig m_config; - GScanCap m_cap; - ScannerNativeParam scannerinfo; - void* m_parent; - std::string mbversion; + }; diff --git a/device/gxx-linux/scanner/scannero300.cpp b/device/gxx-linux/scanner/scannero300.cpp new file mode 100644 index 0000000..e4849ee --- /dev/null +++ b/device/gxx-linux/scanner/scannero300.cpp @@ -0,0 +1,293 @@ +#include +#include "Imotorboard.h" +#include "Capturer.h" +#include +#include "StopWatch.h" +#include "iimagehandler.h" +#include "applog.h" +#include "stringex.hpp" +#include "fpgacontrol.h" +#include "scannerregs.h" +#include "fpgacontrol.h" +#include "Gpio.h" +#include "scannero300.h" +#include "SysInforTool.h" +#include "correct_ultis.h" +#include "dailex.hpp" +static const std::string loggername = "ScannerO300"; +ScannerO300::ScannerO300(std::shared_ptr capturer, std::shared_ptr mb, std::shared_ptr wake) : IScanner(capturer, mb, wake), mfpgaversion(0x90001) +{ + LOG_INIT(); + capturer->regs()->read(15, mfpgaversion); + SysInforTool(ScannerSysInfo()).GetSysInfo(); + auto mb_error_call = [&](std::uint32_t code) + { + if (done_scan) + return; + if (code == 0x40000 && m_config.g200params.paper != 16) + return; + if (code != 0) + { + imagehandler->add_scanevent({.From = MtBoard, .Code = code}); + mb_error = code; + if (code == 0x20) + scannerinfo.DoubleFeedTimes++; + done_scan = true; + } + printf("\n scan done 1 code = %d ", code); + }; + auto mb_scandone_call = [&]() + { + printf("\n scan done 2"); + done_scan = true; + }; + + auto mb_auto_paper = [&](unsigned int value) + { + printf("连续扫描模式检测到有纸"); + if (fu_runscan && fu_runscan->is_runing()) + return; + start_scan(); + }; + mb->set_callbacks({mb_error_call, mb_scandone_call, nullptr, nullptr, nullptr, mb_auto_paper}); + scannerinfo = getscannerinfo(); + + auto mb_ev_cb = [&](uint32_t ev) -> void + { + if(imagehandler) + imagehandler->add_scanevent({.From = MBEvent, .Code = ev}); + }; + mb->set_motorboard_event_callback(mb_ev_cb); +} +ScannerO300::~ScannerO300() +{ +} +void ScannerO300::start_scan() +{ + printf("m_config.g200params.color= %d ,m_config.g200params.dpi = %d ,m_config.g200params.paper = %d ", m_config.g200params.color, m_config.g200params.dpi, m_config.g200params.paper); + mb->clear_error(); + capturer->regs()->read(15, mfpgaversion); + if (m_capturereload && m_capturereload->is_runing()) + { + while (m_capturereload->is_runing()) + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + m_capturereload.reset(); + } + if (fu_runscan && fu_runscan->is_runing()) + return; + if (wake.get()) + wake->setsleepfalg(true); + m_cistype = Dail().GetValue().dails.in_voltage3 == 1 ? CISVendor::DUNNAN_CIS_V0 : CISVendor::HUALIN_CIS_V0; + FPGAConfigParam fpgaparam = GetFpgaparam(m_config.g200params.dpi, m_config.g200params.color); + capturer->open(m_config, fpgaparam); + scannerinfo = getscannerinfo(); + imagehandler->Set_ratio(fpgaparam.HRatio, fpgaparam.VRatio); + imagehandler->resetimgstatus(); + mb->clear_error(); + mb_error = 0; + scancount = 0; + fu_runscan.reset(new ThreadEx(&ScannerO300::runScan, this)); +} +void ScannerO300::stop_scan() +{ + done_scan = true; + mb->set_auto_paper(false); +} +int ScannerO300::count() +{ + return scannerinfo.RollerNum; +} +int ScannerO300::mode() +{ + return 0; +} +int ScannerO300::getmbstatus() +{ + return 0; +} +bool ScannerO300::getpaperon() +{ + return mb->paper_ready(); +} +void ScannerO300::runScan() +{ + int spdmode = 0; + if (scannerSp.find((SpeedMode)scannerinfo.speedmode) != scannerSp.end()) + spdmode = scannerSp.at((SpeedMode)scannerinfo.speedmode).motorSpeed; + mb->set_speed_mode(spdmode, m_config.g200params.dpi, m_config.g200params.color); + system("echo performance > /sys/devices/system/cpu/cpu5/cpufreq/scaling_governor"); + mb->set_double_inpect(m_config.g200params.double_feed_enbale); + mb->set_auto_paper(m_config.g200params.is_autopaper); + + StopWatch sw; + if (mb->is_converopen()) + { + imagehandler->add_scanevent({.From = MtBoard, .Code = 4}); + mb_error = 4; + printf("\n------------------converopen-------------------"); + } + else if (mb->is_jam()) + { + imagehandler->add_scanevent({.From = MtBoard, .Code = 16}); + mb_error = 16; + printf("\n------------------jam-------------------"); + } + else if (!mb->paper_ready()) + { + imagehandler->add_scanevent({.From = MtBoard, .Code = 2}); + mb_error = 2; + printf("\n-------------------no paper---------------"); + } + else + { + done_scan = false; + printf("\n------------------motor run ------------------- %f ", sw.elapsed_ms()); + std::thread m_startthread([this, spdmode] + { + std::this_thread::sleep_for(std::chrono::milliseconds(20));//20ms再启动 保证到达 wait paper in 之后才有传感器信号 + mb->set_cuospeed(0xff,m_config.g200params.dpi,m_config.g200params.color); + mb->start(); + std::this_thread::sleep_for(std::chrono::milliseconds(90)); + mb->stop_pick_paper(); + mb->set_cuospeed(spdmode,m_config.g200params.dpi,m_config.g200params.color); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + mb->pick_paper(); }); + void *data = NULL; + while (!done_scan) + { + if (mb->wait_paper_in(5000)) + { + printf("\n------------------wait_paper_in------------------- %f ", sw.elapsed_ms()); + if (mb_error != 0) + break; + capturer->snap(); + if (mb->wait_paper_out(7000)) + { + printf("\n------------------wait_paper_out------------------- %f ", sw.elapsed_ms()); + if (mb_error != 0) + break; + scannerinfo.RollerNum++; + scannerinfo.TotalScanned++; +#ifdef G300 + HGSize size; + size = papersMap[(PaperSize)m_config.g200params.paper]; + size.width = size.width == 0 ? papersMap[PaperSize::G400_A4].width : size.width; + size.height = size.height == 0 ? papersMap[PaperSize::G400_A4].height : size.height; + if (m_config.g200params.dpi != 1) + size.height = std::min((unsigned int)16002, size.height * 3 / 2); + int channels = m_config.g200params.color ? 3 : 1; + int dstwith = size.width * channels * 3; + int dstHeight = size.height / 9 * 3; +#else + int height; // + if (m_config.g200params.paper == (unsigned int)PaperSize::G400_AUTO) + { + int delaytime = m_config.g200params.dpi == 0x02 ? 150 : (m_config.g200params.dpi == 0x03 ? 250 : 100); + this_thread::sleep_for(chrono::milliseconds(delaytime)); // 纸张过了 多采集几张 + height = capturer->getautosizeheight(); + } + else + height = capturer->height(); + int channel = capturer->color() == 16 ? 3 : 1; + int dstwith = capturer->width() * 2 * 3 * channel; + int dstHeight = m_config.g200params.paper == (unsigned int)PaperSize::G400_AUTO ? height : height / channel; +#endif + printf("\n------------------readFrame------------------- %f", sw.elapsed_ms()); + if (data = capturer->readFrame(7000)) + { + printf("\n addimage %f ", sw.elapsed_ms()); + while (imagehandler->is_limit()) + { + this_thread::sleep_for(chrono::milliseconds(10)); + continue; + } + printf("\n dstwith = %d ,dstHeight = %d color type = %d", dstwith, dstHeight, capturer->color()); + imagehandler->add_image(data, dstwith, dstHeight, capturer->color(), ++scancount, mfpgaversion, m_cistype); + } + else + { + imagehandler->add_scanevent({.From = V4L2, .Code = 0}); + done_scan = true; + mb_error = 79; // 79异常取图失败 + printf("capture error \n"); + break; + } + if (imagehandler->getimgstatus().status != Error_Status::NO_error && (m_cap.is_dogeardetection || m_cap.en_sizecheck)) + { + done_scan = true; + mb_error = 82; + break; + } + if ((!mb->paper_ready()) || (scancount >= (m_cap.is_duplex ? m_cap.scannum / 2 : m_cap.scannum))) + { + done_scan = true; + break; + } + printf("\n scancount =%d m_cap.scannum =%d addimage %f", scancount, m_cap.scannum, sw.elapsed_ms()); + if (!done_scan) + mb->pick_paper(); + else + { + done_scan = true; + break; + } + printf("\n pick paper done %f ", sw.elapsed_ms()); + } + else + { + printf("\n scan done 16"); + if (mb_error == 0) + { + scannerinfo.JamTimes++; + imagehandler->add_scanevent({.From = MtBoard, .Code = 16}); + mb_error = 16; + } + break; + } + } + else + { + printf("\n scan done 8"); + imagehandler->add_scanevent({.From = MtBoard, .Code = 8}); + mb_error = 8; + scannerinfo.FeedErrorTimes++; + break; + } + } + printf("\n scan done 5"); + if (m_startthread.joinable()) + m_startthread.join(); + if ((mb_error == 0) || (mb_error == 82)) + std::this_thread::sleep_for(std::chrono::milliseconds(2000)); + mb->stop(); + } + mb->set_double_inpect(false); + m_capturereload.reset(new ThreadEx([&] + { + capturer->stop(); + capturer->close(); + capturer->reset(); })); + while (!imagehandler->done()) + this_thread::sleep_for(chrono::milliseconds(10)); + printf("-------scanner done------- %f \n", sw.elapsed_ms()); + imagehandler->add_scanevent({.From = STOPSCAN, 0}); + system("sudo cpufreq-set -g ondemand"); + if (wake.get()) + { + wake->resettime(); + wake->setsleepfalg(false); + } + savescannerinfo(scannerinfo); + done_scan = true; + if (mb_error && mb_error != 2) + { + mb->LedControlOption(HG_LedOption::HG_RED_ON, 0); + } + if (mb_error) + { + mb->set_auto_paper(false); + } + mb->set_error(mb_error); + if (!mb->paper_ready() && (mb_error == 0 || (mb->is_converopen() == false && mb->is_jam() == false && mb_error != 2))) + mb->motor_reset(); +} \ No newline at end of file diff --git a/device/gxx-linux/scanner/scannero300.h b/device/gxx-linux/scanner/scannero300.h new file mode 100644 index 0000000..62a2615 --- /dev/null +++ b/device/gxx-linux/scanner/scannero300.h @@ -0,0 +1,23 @@ +#pragma once +#include "iscanner.h" + + +class ScannerO300 : public IScanner +{ +public: + ScannerO300(std::shared_ptr capturer, std::shared_ptr mb, std::shared_ptr wake); + virtual ~ScannerO300(); + virtual void start_scan() override; + virtual void stop_scan() override; + virtual int count() override; + virtual int mode() override; + virtual int getmbstatus() override; + virtual bool getpaperon() override; + virtual void runScan() override; +private: + volatile bool done_scan = true; + volatile int mb_error = 0; + std::uint32_t mfpgaversion; + CISVendor m_cistype; + //std::future m_addimg_future; +}; \ No newline at end of file diff --git a/device/gxx-linux/scanner/scannerregs.cpp b/device/gxx-linux/scanner/scannerregs.cpp index de49d86..0c813d8 100644 --- a/device/gxx-linux/scanner/scannerregs.cpp +++ b/device/gxx-linux/scanner/scannerregs.cpp @@ -188,7 +188,8 @@ bool ScannerRegAccess::write(unsigned int addr, const unsigned int val) std::string cfg(load_mini_file("/root/.scanner/log/cfg_4308.bin")); GScanCap cap = *(GScanCap*)&cfg[0]; - cap.resolution_dst = cap.resolution_native = scan_dpi; + cap.resolution_dst = scan_dpi; + cap.resolution_native = 200; cap.scannum = scan_cnt; printf("DPI: %d, Count: %d\n", scan_dpi, scan_cnt); #else diff --git a/device/gxx-linux/scanner/wakeup.hpp b/device/gxx-linux/scanner/wakeup.hpp index 5c6487a..ee94a59 100644 --- a/device/gxx-linux/scanner/wakeup.hpp +++ b/device/gxx-linux/scanner/wakeup.hpp @@ -23,8 +23,7 @@ public: WakeUp() { b_run=true; - if(get_status()==0) - power_on(); + update_state(); m_thread.reset(new std::thread(&WakeUp::input,this)); m_time =std::chrono::steady_clock::now(); sleeptime = jsonconfig().getscannerinfo().sleeptime; @@ -46,7 +45,7 @@ public: return; char buf=0x55; if((m_status == 1)&&releasecallback) - releasecallback(); + releasecallback(); write(fd,&buf,1); close(fd); m_status=0; @@ -54,17 +53,23 @@ public: void power_on(){ int fd=open(dev_name,O_RDWR); + resettime(); if(fd == -1) return; char buf=0xaa; write(fd,&buf,1); close(fd); - if((m_status == 0)&&initcallback) + if((m_status == 0)&&initcallback) initcallback(); m_status=1; } int get_status() + { + return m_status; + } + + int update_state() { int fd= open(dev_name,O_RDWR); if(fd == -1) @@ -88,14 +93,14 @@ public: sleeptime= val; auto var = jsonconfig().getscannerinfo(); var.sleeptime = val; - printf("\nwakeup time %d",val); jsonconfig().savescannerinfo(var); + resettime(); } void setinitcallback(std::function init,std::function release){ this->initcallback = init; this->releasecallback = release; - } + } int gettime() {return sleeptime;} @@ -137,21 +142,33 @@ private: while (read(fd, &event, sizeof(event)) == sizeof(event)) { printf("get event: type = 0x%x, code = 0x%x, value = 0x%x\n", event.type, event.code, event.value); - if(event.type == 0x01 && event.code == 0x3e && event.value == 0x00) + if(event.type == 0x01 && event.code == 0x3e && event.value == 0x01) { - int val= get_status(); - if(val == 1) { - printf("system in sleep.\n"); - power_off(); - } - else if(val == 0) { - printf("system wakeup.\n"); - power_on(); - resettime(); - } - else { - printf("error sleep index.\n"); - } + pressed_time = std::chrono::steady_clock::now(); + } + if(event.type == 0x01 && event.code == 0x3e && event.value == 0x00) + { + + if(std::chrono::duration(std::chrono::steady_clock::now() - pressed_time).count() > 5000){ + printf("wake up poweroff .\n"); + system("poweroff"); + } + if(std::chrono::duration(std::chrono::steady_clock::now() - pressed_time).count() > 2000) + { + int val= update_state(); + if(val == 1) { + printf("system in sleep.\n"); + power_off(); + } + else if(val == 0) { + printf("system wakeup.\n"); + power_on(); + resettime(); + } + else { + printf("error sleep index.\n"); + } + } } } } @@ -164,12 +181,13 @@ private: { printf("wakeup_process.c::poll err...\n"); } - if((sleeptime!=-1) && std::chrono::duration(std::chrono::steady_clock::now()-m_time).count()>sleeptime && m_status==1 && !sleep_falg ) + if((sleeptime!=-1) && (std::chrono::duration(std::chrono::steady_clock::now()-m_time).count()>sleeptime) && (m_status==1) && (!sleep_falg) ) { - if(get_status()==1) + if(update_state()==1) power_off(); printf("\nwakeup_process sleep...\n"); } + //printf("\n wake up time ----- %f sleep_flag =%d sleeptime %d",std::chrono::duration(std::chrono::steady_clock::now()-m_time).count(),sleep_falg,sleeptime); std::this_thread::sleep_for(std::chrono::milliseconds(500)); } @@ -177,9 +195,10 @@ private: bool b_run; int sleeptime; bool sleep_falg; - std::atomic m_status; + volatile bool m_status; std::function initcallback; std::function releasecallback; std::shared_ptr m_thread; std::chrono::steady_clock::time_point m_time; + std::chrono::steady_clock::time_point pressed_time; }; \ No newline at end of file diff --git a/device/gxx-linux/scanner/xmake.lua b/device/gxx-linux/scanner/xmake.lua index 98adcf0..f33dd5c 100644 --- a/device/gxx-linux/scanner/xmake.lua +++ b/device/gxx-linux/scanner/xmake.lua @@ -4,8 +4,8 @@ target("gscanner") set_kind("static") add_files("*.cpp") add_syslinks("pthread") - -- add_links("turbojpeg") add_links("ssl","crypto") + -- add_links("turbojpeg") add_deps("motorboard", "capimage", "gusb", "gimgproc", "applog","fpgaupdate") add_packages("common") add_includedirs(".", { public = true}) \ No newline at end of file diff --git a/device/gxx-linux/scanservice/main.cpp b/device/gxx-linux/scanservice/main.cpp index 886c3d2..d5f1d85 100644 --- a/device/gxx-linux/scanservice/main.cpp +++ b/device/gxx-linux/scanservice/main.cpp @@ -1,3 +1,239 @@ +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include "filetools.h" +// #include "stringex.hpp" +// #include +// #include "usbservice.h" +// #include "Capturer.h" +// #include "motorboard.h" +// #include "itransmit.h" +// #include "scannerregs.h" +// #include "scanner.h" +// #include "inotify.h" +// #include "memoryex.h" +// #include "usbimageprocqueue.h" +// #include "imageusbtesthandler.h" +// #include "applog.h" +// #include "jsonconfig.h" +// #include "wakeup.hpp" + +// using namespace std; +// #define MY_PID_FILE "/tmp/scanservice_pid" +// #define BUF_LEN_FOR_PID 64 + +// static int write_pid_into_fd(int fd, pid_t pid) +// { +// int ret = -1; +// char buf[BUF_LEN_FOR_PID] = {0}; + +// /* Move cursor to the start of file. */ +// lseek(fd, 0, SEEK_SET); + +// sprintf(buf, "%d", pid); +// ret = write(fd, buf, strlen(buf)); +// if (ret <= 0) +// { /* Write fail or write 0 byte */ +// if (ret == -1) +// perror("Write " MY_PID_FILE " fail\n"); + +// ret = -1; +// } +// else +// { +// printf("Create " MY_PID_FILE " ok, pid=%d\n", pid); +// ret = 0; +// } + +// return ret; +// } + +// static int create_pid_file(pid_t pid) +// { +// int fd, ret; +// char buf[BUF_LEN_FOR_PID] = {0}; + +// fd = open(MY_PID_FILE, O_WRONLY | O_CREAT | O_EXCL, 0666); /* rw-rw-rw- */ +// if (fd == -1) +// { +// perror("Create " MY_PID_FILE " fail\n"); +// return -1; +// } + +// ret = flock(fd, LOCK_EX); +// if (ret == -1) +// { +// perror("flock " MY_PID_FILE " fail\n"); +// close(fd); +// return -1; +// } + +// ret = write_pid_into_fd(fd, pid); + +// flock(fd, LOCK_UN); +// close(fd); + +// return ret; +// } + +// static int check_pid_file(int fd, pid_t pid) +// { +// int ret = -1; +// pid_t old_pid; +// char buf[BUF_LEN_FOR_PID] = {0}; + +// ret = flock(fd, LOCK_EX); +// if (ret == -1) +// { +// perror("flock " MY_PID_FILE " fail\n"); +// return -1; +// } + +// ret = read(fd, buf, sizeof(buf) - 1); +// if (ret < 0) +// { /* read error */ +// perror("read from " MY_PID_FILE " fail\n"); +// ret = -1; +// } +// else if (ret > 0) +// { /* read ok */ +// old_pid = atol(buf); + +// /* Check if old_pid is running */ +// ret = kill(old_pid, 0); +// if (ret < 0) +// { +// if (errno == ESRCH) +// { /* old_pid is not running. */ +// ret = write_pid_into_fd(fd, pid); +// } +// else +// { +// perror("send signal fail\n"); +// ret = -1; +// } +// } +// else +// { /* running */ +// printf("Program already exists, pid=%d\n", old_pid); +// ret = -1; +// } +// } +// else if (ret == 0) +// { /* read 0 byte from file */ +// ret = write_pid_into_fd(fd, pid); +// } + +// flock(fd, LOCK_UN); + +// return ret; +// } + +// static int init_pid_file() +// { +// pid_t pid; +// int fd, ret; + +// pid = getpid(); + +// fd = open(MY_PID_FILE, O_RDWR); +// if (fd == -1) +// { /* open file fail */ +// if (errno == ENOENT) +// { /* No such file. Create one for this program. */ +// ret = create_pid_file(pid); +// } +// else +// { +// perror("open " MY_PID_FILE " fail\n"); +// ret = -1; +// } +// } +// else +// { /* pid file already exists */ +// ret = check_pid_file(fd, pid); +// close(fd); +// } + +// return ret; +// } + + + +// static void sigHandler(int sig) +// { +// if (sig == SIGINT || sig == SIGTERM) +// remove(MY_PID_FILE); +// printf("exit now \n"); +// _exit(0); +// } + + +// int main() +// { + +// if (-1 == init_pid_file()) +// { +// exit(-1); +// } + +// /* Ctrl + C */ +// if (signal(SIGINT, sigHandler) == SIG_ERR) +// { +// exit(-1); +// } + +// /* kill pid / killall name */ +// if (signal(SIGTERM, sigHandler) == SIG_ERR) +// { +// exit(-1); +// } +// auto wake = std::shared_ptr(new WakeUp()); +// auto cap = std::shared_ptr(new Capturer()); +// auto mt = std::shared_ptr(new MotorBoard()); + +// wake->setinitcallback([&mt,&cap]{ +// std::this_thread::sleep_for(std::chrono::milliseconds(5000)); +// cap->Fpga_regsAccess_reset(true); +// mt->init_statecontrol(); +// },[&mt,&cap]{ +// cap->Fpga_regsAccess_reset(false); +// mt->release_statecontrol(); +// }); +// auto scanner = std::shared_ptr(new Scanner(cap, mt,wake)); +// UsbService us(cap->regs(), mt->regs()); +// auto usbhotplugcall = [&](bool connect){ +// if(connect){ +// printf("USB Connect\n"); +// }else +// { +// scanner->stop_scan(); +// printf("USB Disconnect Scanner STOP SCAN\n"); +// exit(0); +// } + +// }; +// us.set_onconnect_call(usbhotplugcall); +// auto notify = us.notify(); + +// std::shared_ptr usbImage(new UsbImageProcQueue(notify)); +// auto transfer = us.transmiter(); +// auto receiver = us.receiver(); +// std::shared_ptr regs = std::shared_ptr(new ScannerRegAccess(scanner, usbImage, transfer,receiver)); +// scanner->set_imagehandler(std::shared_ptr(new ImageUsbHandler(usbImage))); +// us.set_scannerregs(regs); +// while(1) {std::this_thread::sleep_for(std::chrono::milliseconds(2));} +// return 0; +// } + #include #include #include @@ -10,10 +246,14 @@ #include #include #include "filetools.h" -#include "stringex.hpp" #include #include "usbservice.h" #include "Capturer.h" +#include "Imotorboard.h" +#include "motormanager.h" +#include "iscanner.h" +#include "scannero300.h" +#include "MonoCapturer.h" #include "motorboard.h" #include "itransmit.h" #include "scannerregs.h" @@ -25,6 +265,8 @@ #include "applog.h" #include "jsonconfig.h" #include "wakeup.hpp" +#include "Led.h" +#include "dailex.hpp" using namespace std; #define MY_PID_FILE "/tmp/scanservice_pid" @@ -196,35 +438,59 @@ int main() { exit(-1); } + //auto deviceinfo = jsonconfig().getdeviceinfo(); auto wake = std::shared_ptr(new WakeUp()); - auto cap = std::shared_ptr(new Capturer()); - auto mt = std::shared_ptr(new MotorBoard()); - - wake->setinitcallback([&mt,&cap]{ - std::this_thread::sleep_for(std::chrono::milliseconds(5000)); - cap->Fpga_regsAccess_reset(true); - mt->init_statecontrol(); - },[&mt,&cap]{ - cap->Fpga_regsAccess_reset(false); - mt->release_statecontrol(); - }); - auto scanner = std::shared_ptr(new Scanner(cap, mt,wake)); + //auto cap = std::shared_ptr(new Capturer()); + auto cap = std::shared_ptr(new MonoCapturer()); + std::shared_ptr mt; + std::shared_ptr scanner; + mt = std::shared_ptr(new MotorManager()); + scanner = std::shared_ptr(new ScannerO300(cap, mt,wake)); + mt->GetOrSetSleepFlag(false,wake->get_status() == 0 ?true : false); + printf("\n Scan_G300"); + printf("\n 鎷ㄧ爜寮€鍏?%d",Dail().GetValue().value); UsbService us(cap->regs(), mt->regs()); auto usbhotplugcall = [&](bool connect){ if(connect){ printf("USB Connect\n"); + mt->GetOrSetUsbConnectFlag(false,true); }else { scanner->stop_scan(); + StopWatch sw; + while(scanner->is_runscan() || sw.elapsed_s() < 10) + { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + mt->GetOrSetUsbConnectFlag(false,false); printf("USB Disconnect Scanner STOP SCAN\n"); exit(0); } }; + us.set_onconnect_call(usbhotplugcall); auto notify = us.notify(); - std::shared_ptr usbImage(new UsbImageProcQueue(notify)); + wake->setinitcallback([&cap,&mt]{ + std::this_thread::sleep_for(std::chrono::milliseconds(5000)); + cap->Fpga_regsAccess_reset(true); + mt->LedControlOption(HG_LedOption::HG_WHITE_ON,0); + mt->GetOrSetSleepFlag(false,false); + },[&mt,&cap,&usbImage,&scanner]{ + scanner->stop_scan(); + scanner->add_scansever({.From = STOPSCAN , .Code = 1}); + cap->Fpga_regsAccess_reset(false); + mt->LedControlOption(HG_LedOption::HG_GREEN_ON,0); + mt->GetOrSetSleepFlag(false,true); + + }); + if(wake->get_status() == 0) + { + cap->Fpga_regsAccess_reset(false); + mt->LedControlOption(HG_LedOption::HG_GREEN_ON,0); + mt->GetOrSetSleepFlag(false,true); + } auto transfer = us.transmiter(); auto receiver = us.receiver(); std::shared_ptr regs = std::shared_ptr(new ScannerRegAccess(scanner, usbImage, transfer,receiver)); diff --git a/device/gxx-linux/testcapimage/main.cpp b/device/gxx-linux/testcapimage/main.cpp index a81562a..b92c5a3 100644 --- a/device/gxx-linux/testcapimage/main.cpp +++ b/device/gxx-linux/testcapimage/main.cpp @@ -121,7 +121,8 @@ int main() config.g200params.dpi=1; config.g200params.paper=(unsigned int)PaperSize::G400_A4; void *data; - cap->open(config); + // cap->open(config); + cap->open(); int ch = 0; int ixx = 0; diff --git a/device/gxx-linux/testimgproc/main.cpp b/device/gxx-linux/testimgproc/main.cpp index 8a136ca..e49f495 100644 --- a/device/gxx-linux/testimgproc/main.cpp +++ b/device/gxx-linux/testimgproc/main.cpp @@ -26,9 +26,16 @@ int main() //std::string straa = read_all_from("/mnt/d/3.tif"); //fipMemoryIO mio((unsigned char*)straa.c_str(), straa.size()); //auto filet = mio.getFileType(); - std::string imgpath = "/home/linaro/gxx-linux/2.jpg"; - cv::Mat mat=cv::imread(imgpath,cv::IMREAD_GRAYSCALE); - ImageEncodePtr encoder(new BmpImageEncode()); - encoder->encode(mat); + std::string imgpath = "/root/.scanner/log/raw.bmp"; + cv::Mat mat=cv::imread(imgpath,cv::IMREAD_COLOR); + if(mat.empty()) + { + std::cout<<" empty image "< buffer; + cv::imencode(".jpg", mat,buffer); + std::cout<<" imencode image done"< lck(mx); if(images.size()>0) { + printf("UsbImageProcQueue::pop\n"); auto front = images.front(); images.pop(); //auto front=images.Take(); diff --git a/device/gxx-linux/usb/src/common/packet.h b/device/gxx-linux/usb/src/common/packet.h index 839abd0..c30b7bd 100644 --- a/device/gxx-linux/usb/src/common/packet.h +++ b/device/gxx-linux/usb/src/common/packet.h @@ -82,6 +82,7 @@ enum packet_cmd PACK_CMD_SCAN_BASE = 200, PAIR_COMMAND(PACK_CMD_SCAN_START), // start scanning, [in]: PACK_BASE, [out]: PACK_BASE PAIR_COMMAND(PACK_CMD_SCAN_IMG), // device -> host, PACK_BASE::payload - LPPACKIMAGE + PAIR_COMMAND(PACK_CMD_SCAN_PAPER), // device -> host, ONE paper has passed through the CIS. PACK_BASE::data - status of this paper PACK_CMD_SCAN_FINISHED_ROGER, // device -> host, PACK_BASE::data is scanner_status PAIR_COMMAND(PACK_CMD_SCAN_STOP), // stop scanning, [in]: PACK_BASE, [out]: PACK_BASE //PAIR_COMMAND(PACK_CMD_SCAN_IMAGE_REQ), // get image request, [in]: PACK_BASE, [out] PACK_BASE on error, or PACK_BASE::payload - LPPACKIMAGE @@ -155,12 +156,13 @@ enum img_compression }; enum img_status { - IMG_STATUS_OK = 0, - IMG_STATUS_DOUBLE, - IMG_STATUS_JAM, + IMG_STATUS_OK = 0, // normal + IMG_STATUS_DOUBLE, // double-feeded paper + IMG_STATUS_JAM, // jammed paper IMG_STATUS_STAPLE, // staples on the paper IMG_STATUS_SIZE_ERR, // size check failed IMG_STATUS_DOGEAR, // paper has dogear + IMG_STATUS_BLANK, // blank image }; enum data_type { @@ -190,6 +192,16 @@ enum rot_angle ROT_ANGLE_180, ROT_ANGLE_270, }; +enum clr_channel +{ + COLOR_CHANNEL_RGB = 0, + COLOR_CHANNEL_RGBA, + COLOR_CHANNEL_GRAY, + COLOR_CHANNEL_RED, + COLOR_CHANNEL_GREEN, + COLOR_CHANNEL_BLUE, + COLOR_CHANNEL_ALPHA, +}; #pragma pack(push) #pragma pack(1) @@ -251,7 +263,7 @@ typedef struct _img_pos uint64_t img_over : 1; // 0 - has data yet; 1 - END for the image. (image-collector set) uint64_t paper_side : 3; // enum paper_side. front of paper(When scanning multiple sheets, the paper feeding side is the front side). (image-collector set) uint64_t back_rot : 2; // back rotation angle, enum rot_angle. (image-collector set) - uint64_t channel_ind : 4; // index of color channel, based ZERO, 0x0f for all channels. (image-collector set) + uint64_t channel_ind : 4; // index of color channel, enum clr_channel. (image-collector set) uint64_t status : 4; // img_status. (image-collector set) uint64_t split_ind : 7; // splitting order, from left to right and then top to bottom, based ZERO uint64_t multiout_ind : 4; // index of multi-out @@ -274,7 +286,7 @@ typedef struct _pack_img uint32_t reserve : 2; // unused now uint32_t info_size; // image information size in bytes, information part is used for quality of JPEG, pallete of BMP .... (image-collector set) uint64_t data_size; // image data size in 'data' with bytes. (image-collector set) - char data[0]; // two parts: image info (info_size) + image data (data_size) +// char data[0]; // two parts: image info (info_size) + image data (data_size) STRUCT_CONSTRUCTOR(_pack_img) }PACKIMAGE, * LPPACKIMAGE; diff --git a/device/gxx-linux/usb/src/common/sane_cfg.cpp b/device/gxx-linux/usb/src/common/sane_cfg.cpp index 45174e9..b84c9a3 100644 --- a/device/gxx-linux/usb/src/common/sane_cfg.cpp +++ b/device/gxx-linux/usb/src/common/sane_cfg.cpp @@ -102,7 +102,44 @@ bool sane_cfg_provider::sane_option_value_set(json* jsn, void* data, const char* return ret; } +int32_t sane_cfg_provider::inner_get_config(json* root, void* buf, size_t* len, const char* cfg_name, std::string* strval) +{ + int ret = 0; + std::string val(""); + if (!len) + return EINVAL; + + if (cfg_name) + { + json* child = nullptr; + if (root->get_value(cfg_name, child) && child) + { + val = sane_cfg_provider::sane_option_value_get(child, "cur", strval); + child->release(); + } + } + else + { + val = root->to_string(); + } + + if (ret == 0) + { + if (*len < val.length()) + { + *len = val.length() + 4; + ret = ENOMEM; + } + else + { + memcpy(buf, val.c_str(), val.length()); + *len = val.length(); + } + } + + return ret; +} diff --git a/device/gxx-linux/usb/src/common/sane_cfg.h b/device/gxx-linux/usb/src/common/sane_cfg.h index 31ceab6..5ba98fc 100644 --- a/device/gxx-linux/usb/src/common/sane_cfg.h +++ b/device/gxx-linux/usb/src/common/sane_cfg.h @@ -46,6 +46,9 @@ public: static std::string sane_option_value_get(json* jsn, const char* key = "cur"/*cur, default*/, std::string* strval = nullptr/*convert value into string*/); static bool sane_option_value_set(json* jsn, void* data, const char* key = "cur"/*cur, default*/); +protected: + int32_t inner_get_config(json* root, void* buf, size_t* len, const char* cfg_name, std::string* strval); + public: // Function: get all or given name configuration value // @@ -116,19 +119,6 @@ public: int32_t set_config(const char* cfg_name, void* data, size_t* len, uint32_t* afterdo); }; -class hardware : public sane_cfg_provider -{ -public: - hardware(); - -protected: - ~hardware(); - -public: - virtual int32_t get_config(void* buf, size_t* len, const char* cfg_name = nullptr, std::string* str = nullptr) override; - virtual int32_t set_config(const char* cfg_name, void* data, size_t* len, uint32_t* afterdo) override; -}; - class img_processor : public sane_cfg_provider diff --git a/device/gxx-linux/usb/src/hardware/hardware.cpp b/device/gxx-linux/usb/src/hardware/hardware.cpp new file mode 100644 index 0000000..074583a --- /dev/null +++ b/device/gxx-linux/usb/src/hardware/hardware.cpp @@ -0,0 +1,432 @@ +#include "hardware.h" + +#include +//{ +// "cis-mode": { +// "category": "base", +// "readonly" : false, +// "affect" : 2, +// "group" : "base", +// "visible" : false, +// "field" : "cis", +// "pos" : 0, +// "unit" : "None", +// "title" : "CIS����ģʽ", +// "desc" : "����CIS��ɫ���߻ҶȵĹ���ģʽ", +// "type" : "string", +// "cur" : "��ɫ", +// "default" : "��ɫ", +// "size" : 12, +// "range": ["��ɫ", "�Ҷ�"] +// }, +// "cis-dpi": { +// "category": "base", +// "readonly" : false, +// "affect" : 2, +// "group" : "base", +// "visible" : false, +// "field" : "cis", +// "pos" : 0, +// "unit" : "None", +// "title" : "CIS�ֱ���", +// "desc" : "����CIS�ɼ��ķֱ���", +// "type" : "int", +// "cur" : 200, +// "default" : 200, +// "size" : 4, +// "range": [200, 300] +// }, +// "cis-sample": { +// "category": "base", +// "readonly" : false, +// "affect" : 0, +// "group" : "base", +// "visible" : false, +// "field" : "cis", +// "pos" : 0, +// "unit" : "None", +// "title" : "CIS����Ƶ��", +// "desc" : "����CIS��ͷ�����Ĺ���Ƶ��", +// "type" : "int", +// "cur" : 256, +// "default" : 256, +// "size" : 4, +// "range": [128, 256, 512] +// }, +// "frame-h": { +// "category": "base", +// "readonly" : false, +// "affect" : 0, +// "group" : "base", +// "visible" : false, +// "field" : "cis", +// "pos" : 0, +// "unit" : "None", +// "title" : "CIS֡�߶�", +// "desc" : "����CISÿһ֡�ĸ߶�", +// "type" : "int", +// "cur" : 12, +// "default" : 12, +// "size" : 4, +// "range": [4, 8, 12, 16] +// }, +// "gain-front": { +// "category": "base", +// "readonly" : false, +// "affect" : 0, +// "group" : "base", +// "visible" : false, +// "field" : "cis", +// "pos" : 0, +// "unit" : "None", +// "title" : "��������", +// "desc" : "����CIS���澵ͷ������", +// "type" : "int", +// "cur" : 256, +// "default" : 256, +// "size" : 4, +// "range": [100, 200, 300, 600] +// }, +// "gain-back": { +// "category": "base", +// "readonly" : false, +// "affect" : 0, +// "group" : "base", +// "visible" : false, +// "field" : "cis", +// "pos" : 0, +// "unit" : "None", +// "title" : "��������", +// "desc" : "����CIS���澵ͷ������", +// "type" : "int", +// "cur" : 256, +// "default" : 256, +// "size" : 4, +// "range": [100, 200, 300, 600] +// }, +// "offset-front": { +// "category": "base", +// "readonly" : false, +// "affect" : 0, +// "group" : "base", +// "visible" : false, +// "field" : "cis", +// "pos" : 0, +// "unit" : "None", +// "title" : "����ƫ��", +// "desc" : "����CIS�����ƫ�ƾ���", +// "type" : "int", +// "cur" : 150, +// "default" : 150, +// "size" : 4, +// "range": [0, 50, 100, 150, 200] +// }, +// "offset-back": { +// "category": "base", +// "readonly" : false, +// "affect" : 0, +// "group" : "base", +// "visible" : false, +// "field" : "cis", +// "pos" : 0, +// "unit" : "None", +// "title" : "����ƫ��", +// "desc" : "����CIS�����ƫ�ƾ���", +// "type" : "int", +// "cur" : 150, +// "default" : 150, +// "size" : 4, +// "range": [0, 50, 100, 150, 200] +// }, +// "exposure-f-r": { +// "category": "base", +// "readonly" : false, +// "affect" : 0, +// "group" : "base", +// "visible" : false, +// "field" : "cis", +// "pos" : 0, +// "unit" : "None", +// "title" : "�����ɫ�����ع��", +// "desc" : "���������ɫ�������ع�ǿ��", +// "type" : "int", +// "cur" : 0, +// "default" : 0, +// "size" : 4, +// "range": { +// "min": -1000, +// "max": 1000, +// "step": 200 +// } +// }, +// "exposure-f-g": { +// "category": "base", +// "readonly" : false, +// "affect" : 0, +// "group" : "base", +// "visible" : false, +// "field" : "cis", +// "pos" : 0, +// "unit" : "None", +// "title" : "������ɫ�����ع��", +// "desc" : "����������ɫ�������ع�ǿ��", +// "type" : "int", +// "cur" : 0, +// "default" : 0, +// "size" : 4, +// "range": { +// "min": -1000, +// "max": 1000, +// "step": 200 +// } +// }, +// "exposure-f-b": { +// "category": "base", +// "readonly" : false, +// "affect" : 0, +// "group" : "base", +// "visible" : false, +// "field" : "cis", +// "pos" : 0, +// "unit" : "None", +// "title" : "������ɫ�����ع��", +// "desc" : "����������ɫ�������ع�ǿ��", +// "type" : "int", +// "cur" : 0, +// "default" : 0, +// "size" : 4, +// "range": { +// "min": -1000, +// "max": 1000, +// "step": 200 +// } +// }, +// "exposure-b-r": { +// "category": "base", +// "readonly" : false, +// "affect" : 0, +// "group" : "base", +// "visible" : false, +// "field" : "cis", +// "pos" : 0, +// "unit" : "None", +// "title" : "�����ɫ�����ع��", +// "desc" : "�����������ɫ�������ع�ǿ��", +// "type" : "int", +// "cur" : 0, +// "default" : 0, +// "size" : 4, +// "range": { +// "min": -1000, +// "max": 1000, +// "step": 200 +// } +// }, +// "exposure-b-g": { +// "category": "base", +// "readonly" : false, +// "affect" : 0, +// "group" : "base", +// "visible" : false, +// "field" : "cis", +// "pos" : 0, +// "unit" : "None", +// "title" : "������ɫ�����ع��", +// "desc" : "���ñ�����ɫ�������ع�ǿ��", +// "type" : "int", +// "cur" : 0, +// "default" : 0, +// "size" : 4, +// "range": { +// "min": -1000, +// "max": 1000, +// "step": 200 +// } +// }, +// "exposure-b-b": { +// "category": "base", +// "readonly" : false, +// "affect" : 0, +// "group" : "base", +// "visible" : false, +// "field" : "cis", +// "pos" : 0, +// "unit" : "None", +// "title" : "������ɫ�����ع��", +// "desc" : "���ñ�����ɫ�������ع�ǿ��", +// "type" : "int", +// "cur" : 0, +// "default" : 0, +// "size" : 4, +// "range": { +// "min": -1000, +// "max": 1000, +// "step": 200 +// } +// }, +//} +static std::string json_text = + "{\"cis-mode\":{\"category\":\"base\",\"readonly\":false,\"affect\":2,\"group\":\"base\",\"visible\":false,\"field\":\"cis\",\"pos\":0,\"ver\":1,\"unit\":\"None\",\"title\":\"CIS\\u5de5\\u4f5c\\u6a21\\u5f0f\",\"desc\":\"\\u8bbe\\u7f6eCIS\\u5f69\\u8272\\u6216\\u8005\\u7070\\u5ea6\\u7684\\u5de5\\u4f5c\\u6a21\\u5f0f\",\"type\":\"string\",\"cur\":\"\\u5f69\\u8272\",\"default\":\"\\u5f69\\u8272\",\"size\":12,\"range\":[\"\\u5f69\\u8272\",\"\\u7070\\u5ea6\"]},\"cis-dpi\":{\"category\":\"base\",\"readonly\":false,\"affect\":2,\"group\":\"base\",\"visible\":false,\"field\":\"cis\",\"pos\":0,\"ver\":1,\"unit\":\"None\",\"title\":\"CIS\\u5206\\u8fa8\\u7387\",\"desc\":\"\\u8bbe\\u7f6eCIS\\u91c7\\u96c6\\u7684\\u5206\\u8fa8\\u7387\",\"type\":\"int\",\"cur\":200,\"default\":200,\"size\":4,\"range\":[200,300]},\"cis-sample\":{\"category\":\"base\",\"readonly\":false,\"affect\":0,\"group\":\"base\",\"visible\":false,\"field\":\"cis\",\"pos\":0,\"ver\":1,\"unit\":\"None\",\"title\":\"CIS\\u91c7\\u6837\\u9891\\u7387\",\"desc\":\"\\u8bbe\\u7f6eCIS\\u955c\\u5934\\u91c7\\u6837\\u7684\\u5de5\\u4f5c\\u9891\\u7387\",\"type\":\"int\",\"cur\":256,\"default\":256,\"size\":4,\"range\":[128,256,512]},\"frame-h\":{\"category\":\"base\",\"readonly\":false,\"affect\":0,\"group\":\"base\",\"visible\":false,\"field\":\"cis\",\"pos\":0,\"ver\":1,\"unit\":\"None\",\"title\":\"CIS\\u5e27\\u9ad8\\u5ea6\",\"desc\":\"\\u8bbe\\u7f6eCIS\\u6bcf\\u4e00\\u5e27\\u7684\\u9ad8\\u5ea6\",\"type\":\"int\",\"cur\":12,\"default\":12,\"size\":4,\"range\":[4,8,12,16]},\"gain-front\":{\"category\":\"base\",\"readonly\":false,\"affect\":0,\"group\":\"base\",\"visible\":false,\"field\":\"cis\",\"pos\":0,\"ver\":1,\"unit\":\"None\",\"title\":\"\\u6b63\\u9762\\u589e\\u76ca\",\"desc\":\"\\u8bbe\\u7f6eCIS\\u6b63\\u9762\\u955c\\u5934\\u7684\\u589e\\u76ca\",\"type\":\"int\",\"cur\":200,\"default\":200,\"size\":4,\"range\":[100,200,300,600]},\"gain-back\":{\"category\":\"base\",\"readonly\":false,\"affect\":0,\"group\":\"base\",\"visible\":false,\"field\":\"cis\",\"pos\":0,\"ver\":1,\"unit\":\"None\",\"title\":\"\\u80cc\\u9762\\u589e\\u76ca\",\"desc\":\"\\u8bbe\\u7f6eCIS\\u80cc\\u9762\\u955c\\u5934\\u7684\\u589e\\u76ca\",\"type\":\"int\",\"cur\":200,\"default\":200,\"size\":4,\"range\":[100,200,300,600]},\"offset-front\":{\"category\":\"base\",\"readonly\":false,\"affect\":0,\"group\":\"base\",\"visible\":false,\"field\":\"cis\",\"pos\":0,\"ver\":1,\"unit\":\"None\",\"title\":\"\\u6b63\\u9762\\u504f\\u79fb\",\"desc\":\"\\u8bbe\\u7f6eCIS\\u6b63\\u9762\\u7684\\u504f\\u79fb\\u8ddd\\u79bb\",\"type\":\"int\",\"cur\":150,\"default\":150,\"size\":4,\"range\":[0,50,100,150,200]},\"offset-back\":{\"category\":\"base\",\"readonly\":false,\"affect\":0,\"group\":\"base\",\"visible\":false,\"field\":\"cis\",\"pos\":0,\"ver\":1,\"unit\":\"None\",\"title\":\"\\u80cc\\u9762\\u504f\\u79fb\",\"desc\":\"\\u8bbe\\u7f6eCIS\\u80cc\\u9762\\u7684\\u504f\\u79fb\\u8ddd\\u79bb\",\"type\":\"int\",\"cur\":150,\"default\":150,\"size\":4,\"range\":[0,50,100,150,200]},\"exposure-f-r\":{\"category\":\"base\",\"readonly\":false,\"affect\":0,\"group\":\"base\",\"visible\":false,\"field\":\"cis\",\"pos\":0,\"ver\":1,\"unit\":\"None\",\"title\":\"\\u6b63\\u9762\\u7ea2\\u8272\\u5206\\u91cf\\u66dd\\u5149\\u5ea6\",\"desc\":\"\\u8bbe\\u7f6e\\u6b63\\u9762\\u7ea2\\u8272\\u5206\\u91cf\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"cur\":0,\"default\":0,\"size\":4,\"range\":{\"min\":-1000,\"max\":1000,\"step\":200}},\"exposure-f-g\":{\"category\":\"base\",\"readonly\":false,\"affect\":0,\"group\":\"base\",\"visible\":false,\"field\":\"cis\",\"pos\":0,\"ver\":1,\"unit\":\"None\",\"title\":\"\\u6b63\\u9762\\u7eff\\u8272\\u5206\\u91cf\\u66dd\\u5149\\u5ea6\",\"desc\":\"\\u8bbe\\u7f6e\\u6b63\\u9762\\u7eff\\u8272\\u5206\\u91cf\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"cur\":0,\"default\":0,\"size\":4,\"range\":{\"min\":-1000,\"max\":1000,\"step\":200}},\"exposure-f-b\":{\"category\":\"base\",\"readonly\":false,\"affect\":0,\"group\":\"base\",\"visible\":false,\"field\":\"cis\",\"pos\":0,\"ver\":1,\"unit\":\"None\",\"title\":\"\\u6b63\\u9762\\u84dd\\u8272\\u5206\\u91cf\\u66dd\\u5149\\u5ea6\",\"desc\":\"\\u8bbe\\u7f6e\\u6b63\\u9762\\u84dd\\u8272\\u5206\\u91cf\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"cur\":0,\"default\":0,\"size\":4,\"range\":{\"min\":-1000,\"max\":1000,\"step\":200}},\"exposure-b-r\":{\"category\":\"base\",\"readonly\":false,\"affect\":0,\"group\":\"base\",\"visible\":false,\"field\":\"cis\",\"pos\":0,\"ver\":1,\"unit\":\"None\",\"title\":\"\\u80cc\\u9762\\u7ea2\\u8272\\u5206\\u91cf\\u66dd\\u5149\\u5ea6\",\"desc\":\"\\u8bbe\\u7f6e\\u6b63\\u80cc\\u9762\\u7ea2\\u8272\\u5206\\u91cf\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"cur\":0,\"default\":0,\"size\":4,\"range\":{\"min\":-1000,\"max\":1000,\"step\":200}},\"exposure-b-g\":{\"category\":\"base\",\"readonly\":false,\"affect\":0,\"group\":\"base\",\"visible\":false,\"field\":\"cis\",\"pos\":0,\"ver\":1,\"unit\":\"None\",\"title\":\"\\u80cc\\u9762\\u7eff\\u8272\\u5206\\u91cf\\u66dd\\u5149\\u5ea6\",\"desc\":\"\\u8bbe\\u7f6e\\u80cc\\u9762\\u7eff\\u8272\\u5206\\u91cf\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"cur\":0,\"default\":0,\"size\":4,\"range\":{\"min\":-1000,\"max\":1000,\"step\":200}},\"exposure-b-b\":{\"category\":\"base\",\"readonly\":false,\"affect\":0,\"group\":\"base\",\"visible\":false,\"field\":\"cis\",\"pos\":0,\"ver\":1,\"unit\":\"None\",\"title\":\"\\u80cc\\u9762\\u84dd\\u8272\\u5206\\u91cf\\u66dd\\u5149\\u5ea6\",\"desc\":\"\\u8bbe\\u7f6e\\u80cc\\u9762\\u84dd\\u8272\\u5206\\u91cf\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"cur\":0,\"default\":0,\"size\":4,\"range\":{\"min\":-1000,\"max\":1000,\"step\":200}}}"; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// class hardware +hardware::hardware() : cfg_(new json()) +{ + printf("parse hardware json: %s\n", cfg_->attach_text(&json_text[0]) ? "OK" : "Failed"); + memset(&api_, 0, sizeof(api_)); +} +hardware::~hardware() +{ + cfg_->release(); +} + +int32_t hardware::get_config(void* buf, size_t* len, const char* cfg_name, std::string* strval) +{ + return inner_get_config(cfg_, buf, len, cfg_name, strval); +} +int32_t hardware::set_config(const char* cfg_name, void* data, size_t* len, uint32_t* afterdo) +{ + int ret = ENOENT; + json* child = nullptr; + + if (cfg_->get_value(cfg_name, child) && child) + { + ret = set(cfg_name, data, len); + if (ret == 0 || ret == EUCLEAN) + { + sane_option_value_set(child, data); + if (afterdo) + { + child->get_value("affect", ret); + *afterdo = ret; + ret = 0; + } + } + child->release(); + } + + return ret; +} + +void hardware::set_api(LPCISAPI api) +{ + memset(&api_, 0, sizeof(api_)); + if (api) + memcpy(&api_, api, sizeof(api_)); +} + +int32_t hardware::set(const char* name, void* data, size_t* len) +{ + int32_t ret = ENOENT; + int val = *(int*)data; + std::string n(name); + CIS_API api = CIS_API(); + + if (n == "cis-mode") + { + int clr = 1; + std::string gray("\xE7\x81\xB0\xE5\xBA\xA6"), + color("\xE5\xBD\xA9\xE8\x89\xB2"); + + n = std::string((char*)data); + if (n == gray) // �Ҷ� + { + clr = 0; + } + else + { + if (n != color) + { + ret = EUCLEAN; + strcpy((char*)data, color.c_str()); + *len = color.length(); + } + } + + val = clr; + if (api_.set_color_mode) + { + ret = 0; + api_.set_color_mode(&val); + if (val != clr) + { + if (val == 0) + { + strcpy((char*)data, gray.c_str()); + *len = gray.length(); + } + else + { + strcpy((char*)data, color.c_str()); + *len = color.length(); + } + ret = EUCLEAN; + } + } + } + else if (n == "cis-dpi") + { + api = api_.set_dpi; + } + else if (n == "cis-sample") + { + api = api_.set_sample; + } + else if (n == "frame-h") + { + api = api_.set_frame_height; + } + else if (n == "gain-front") + { + api = api_.set_gain_front; + } + else if (n == "gain-back") + { + api = api_.set_gain_back; + } + else if (n == "offset-front") + { + api = api_.set_offset_front; + } + else if (n == "offset-back") + { + api = api_.set_offset_back; + } + else if (n == "exposure-f-r") + { + api = api_.set_exposure_front_red; + } + else if (n == "exposure-f-g") + { + api = api_.set_exposure_front_green; + } + else if (n == "exposure-f-b") + { + api = api_.set_exposure_front_blue; + } + else if (n == "exposure-b-r") + { + api = api_.set_exposure_back_red; + } + else if (n == "exposure-b-g") + { + api = api_.set_exposure_back_green; + } + else if (n == "exposure-b-b") + { + api = api_.set_exposure_back_blue; + } + + if (api) + { + ret = 0; + api(&val); + if (val != *(int*)data) + { + *(int*)data = val; + ret = EUCLEAN; + } + } + + return ret; +} diff --git a/device/gxx-linux/usb/src/hardware/hardware.h b/device/gxx-linux/usb/src/hardware/hardware.h new file mode 100644 index 0000000..a257def --- /dev/null +++ b/device/gxx-linux/usb/src/hardware/hardware.h @@ -0,0 +1,56 @@ +#pragma once + +// image process interface classes +// +// created on 2023-04-19 +// + +#include +#include +#include +#include + +class json; + +#define CIS_API std::function // return error code, set real value to parameter if in-value was not exact + +typedef struct _cis_api +{ + CIS_API set_color_mode; + CIS_API set_dpi; + CIS_API set_sample; + CIS_API set_frame_height; + CIS_API set_gain_front; + CIS_API set_gain_back; + CIS_API set_offset_front; + CIS_API set_offset_back; + CIS_API set_exposure_front_red; + CIS_API set_exposure_front_green; + CIS_API set_exposure_front_blue; + CIS_API set_exposure_back_red; + CIS_API set_exposure_back_green; + CIS_API set_exposure_back_blue; +}CISAPI, *LPCISAPI; + +class hardware : public sane_cfg_provider +{ + json* cfg_; + CISAPI api_; + + int32_t set(const char* name, void* data, size_t* len); + +public: + hardware(); + +protected: + ~hardware(); + + // sane_cfg_provider +public: + virtual int32_t get_config(void* buf, size_t* len, const char* cfg_name = nullptr, std::string* strval = nullptr) override; + virtual int32_t set_config(const char* cfg_name, void* data, size_t* len, uint32_t* afterdo) override; + +public: + void set_api(LPCISAPI api); +}; + diff --git a/device/gxx-linux/usb/src/usbdevice.cpp b/device/gxx-linux/usb/src/usbdevice.cpp index 4bbc0fe..990beb2 100644 --- a/device/gxx-linux/usb/src/usbdevice.cpp +++ b/device/gxx-linux/usb/src/usbdevice.cpp @@ -15,6 +15,7 @@ #ifdef ASYNC_EP #include "common/sys_util.h" #include "common/json/json.h" +#include "hardware/hardware.h" #include "commondef.h" #endif @@ -1558,6 +1559,7 @@ protected: virtual ~image_packet() { uint32_t size = img_->size(); + head_->release(); img_.reset(); log_cls::log(LOG_LEVEL_ALL, "Image-%04u sending complete: %u/%u, memory usage %s\n", ind_, offset_, size, sys_util::format_readable_bytes(sys_util::get_memory_usage("scan")).c_str()); @@ -1726,7 +1728,7 @@ dyn_mem_ptr UsbDevice::handle_bulk_cmd(LPPACK_BASE pack, uint32_t* used, packet_ cfg->val_off = 0; cfg->name_off = val.length() + 1; pk->payload_len = sizeof(CFGVAL) + strlen(pack->payload) + 1 + val.length() + 1; - strcpy(cfg->data, val.c_str()); + memcpy(cfg->data, val.c_str(), val.length()); strcpy(cfg->data + cfg->name_off, pack->payload); reply->set_len(base_head_size + pk->payload_len); *used = base_head_size + pack->payload_len; @@ -1903,6 +1905,8 @@ void UsbDevice::do_system_command(const char* cmd) void UsbDevice::init(void) { readonly_cfg* r = new readonly_cfg(); + hardware *hrd = new hardware(); + size_t l = sizeof(dpi_); cfg_text_ = "{\"resolution\":{\"category\":\"base\",\"readonly\":false,\"affect\":2,\"ver\":1,\"group\":\"base\",\"visible\":true,\"field\":\"Common\",\"pos\":0,\"unit\":\"None\",\"title\":\"\\u5206\\u8fa8\\u7387\",\"desc\":\"\\u8bbe\\u7f6e\\u626b\\u63cf\\u56fe\\u50cf\\u7684\\u5206\\u8fa8\\u7387\",\"type\":\"int\",\"cur\":200,\"default\":200,\"size\":4,\"range\":[100,150,200,300,600]},\"count\":{\"category\":\"base\",\"readonly\":false,\"affect\":0,\"ver\":1,\"group\":\"base\",\"visible\":true,\"field\":\"Common\",\"pos\":0,\"unit\":\"None\",\"title\":\"\\u626b\\u63cf\\u5f20\\u6570\",\"desc\":\"\\u8bbe\\u7f6e\\u626b\\u63cf\\u7684\\u7eb8\\u5f20\\u6570\\u91cf\",\"type\":\"int\",\"cur\":-1,\"default\":-1,\"size\":4,\"range\":[-1,1]}}"; @@ -1912,6 +1916,8 @@ void UsbDevice::init(void) cfg_ = new sane_cfg_mgr(); cfg_->reg_sane_provider(dynamic_cast(r)); l = cfg_->reg_sane_provider(dynamic_cast(this)); + l = cfg_->reg_sane_provider(dynamic_cast(hrd)); + hrd->release(); r->release(); } void UsbDevice::save_image(MemoryPtr data, bool img) @@ -1942,7 +1948,7 @@ void UsbDevice::save_image(MemoryPtr data, bool img) } } } - else + else if(data) { HGIntInfo* info = (HGIntInfo*)data->data(); dyn_mem_ptr reply = dyn_mem::memory(sizeof(PACK_BASE)); @@ -2035,6 +2041,15 @@ void UsbDevice::save_image(MemoryPtr data, bool img) } reply->release(); } + else + { + // paper count ... + dyn_mem_ptr reply = dyn_mem::memory(sizeof(PACK_BASE)); + BASE_PACKET_REPLY(*((LPPACK_BASE)reply->ptr()), PACK_CMD_SCAN_PAPER_ROGER, 0, 0); + reply->set_len(sizeof(PACK_BASE)); + usb_->write_bulk(reply); + reply->release(); + } } int32_t UsbDevice::get_config(void* buf, size_t* len, const char* cfg_name, std::string* strval) @@ -2049,25 +2064,26 @@ int32_t UsbDevice::get_config(void* buf, size_t* len, const char* cfg_name, std: json *jsn = new json(); if(jsn->attach_text(&cfg_text_[0])) { - json* child = nullptr; + ret = inner_get_config(jsn, buf, len, cfg_name, strval); + // json* child = nullptr; - ret = ENOENT; - if(jsn->get_value(cfg_name, child) && child) - { - std::string val(sane_cfg_provider::sane_option_value_get(child, "cur", strval)); - child->release(); + // ret = ENOENT; + // if(jsn->get_value(cfg_name, child) && child) + // { + // std::string val(sane_cfg_provider::sane_option_value_get(child, "cur", strval)); + // child->release(); - if(*len < val.length()) - { - *len = val.length(); - ret = ENOMEM; - } - else - { - memcpy(buf, val.c_str(), val.length()); - *len = val.length(); - } - } + // if(*len < val.length()) + // { + // *len = val.length(); + // ret = ENOMEM; + // } + // else + // { + // memcpy(buf, val.c_str(), val.length()); + // *len = val.length(); + // } + // } jsn->release(); } } diff --git a/device/gxx-linux/usb/xmake.lua b/device/gxx-linux/usb/xmake.lua index 92a8321..b487997 100644 --- a/device/gxx-linux/usb/xmake.lua +++ b/device/gxx-linux/usb/xmake.lua @@ -3,7 +3,7 @@ add_rules("mode.debug", "mode.release") target("gusb") set_kind("static") add_syslinks("pthread") - add_files("*.cpp", "src/*.cpp", "src/common/*.cpp", "src/common/json/*.c*") + add_files("*.cpp", "src/*.cpp", "src/common/*.cpp", "src/common/json/*.c*", "src/hardware/*.cpp") add_includedirs("inc") add_includedirs("src/common") add_includedirs(".", { public = true}) diff --git a/device/gxx-linux/xmake.lua b/device/gxx-linux/xmake.lua index 179f1d6..dd76911 100644 --- a/device/gxx-linux/xmake.lua +++ b/device/gxx-linux/xmake.lua @@ -66,7 +66,7 @@ target("conf") add_includedirs("$(buildir)/config/header", { public = true }) target_end("conf") -includes("regs", "deviceio", "motorboard", "capimage", "usb", "service", "scanner", "imgproc", "applog","scanservice","fpgaupdate") +includes("regs", "deviceio", "motor_run", "motorboard", "capimage", "usb", "service", "scanner", "imgproc", "applog","scanservice","fpgaupdate") add_includedirs("/usr/local/include/opencv4", "imgproc/ImageProcess") add_linkdirs("/usr/local/lib/") diff --git a/pc/code_twain/device/scanner.vcxproj b/pc/code_twain/device/scanner.vcxproj index 4260684..d2644e4 100644 --- a/pc/code_twain/device/scanner.vcxproj +++ b/pc/code_twain/device/scanner.vcxproj @@ -102,7 +102,7 @@ Level3 true - WIN32;HGSCANNER_EXPORT;CUSTOM_USBVIEW;_DIRECT_BUILD;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + WIN32;OEM_NONE;HGSCANNER_EXPORT;CUSTOM_USBVIEW;_DIRECT_BUILD;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true 4996 MultiThreadedDebug diff --git a/pc/code_twain/sln/usb_tools/Debug/usb_tools.exe b/pc/code_twain/sln/usb_tools/Debug/usb_tools.exe index f5d34e4a5acea108aa8eb3058800f6bb34880cd7..16c2333062baa973edf0f7060646f79e55c64cc6 100644 GIT binary patch delta 39580 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 delta 37288 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�&#?Whm&<@^F^Q|@zT}elF?=q+ihqm$6#79Grd0}ygl8bbHV9jUH-$sO3E?B* zbKxuDs$dZl#o>?%`QlcwM?5F?iC>DNrOi^jtjSB{M!8i!A%7^Jl{=I|^}IS#uY+)g z2NnmO33LWN36vYX#^XVPaS|&bpponZ_9&ao>D*NA5iXxA;-2OZ_j~R$PKo9nd@7&K zKgKVC+}OnL=8y3o@qPRiK2~rG8A4E)2_aSp>xHetUg2%X*mJ@K;hKQf-gJ+FQNQn| zn~q|ob?Ed>_s`SoaK7a@;U_wRSPnzVV+1tyD~##*>H z`41t^9^sbYfDF!%GSRAA?h%!_L88n_2%r+jBs1w8$5n7IaGl&IT(;7v3NmF%5Lb}s)LID&b?V&Pfg1!1GGP1r5;2)6~Nc%S&1*dXo^ z_lvD!n|NG&SL_r&5synZB|*-VJ7nx4OSSmt`AhsS_&56x`M>tNHBFnZRcTGyY3(1H zT_30C>BV|_pfvEHK{Pmt9B`b?3^0v+ws2NR7b`2kXo|F0YLnvRWXO}t{wdn8wY6H8 z_LX*18?Wc;?fRHNL7+0w5V#hY5A8o-_yzoOev!~1Gzo3ODWOATxvZV$EoSyRNa^ods z$@UaYu9x4Dd*s`4vN}?opz7*0HAj6^U82_exBBn+)3m3wGHs7`K%1vG>bG?(WMYwV ze|VDmagJ&?S55V-w^&x9A=5n1!s)NsJ zg7bqPK>q(MGyr3merWDQb}D4^0rowX;b-#C@-Opt@kuEAzl52(O|r--a+*9_UM+8y z4?;bet87vllqRK3Ii++dy~==cRUuTnnxgtt23nD=&Qc51Qnf;bBZ}Ui@A+541>S(- zbxknDSH&;U$$Zb><6eTV&D`tk^Hwr4*@HDwQf=4r`QJrCzCDx+qRp?&jsfmT`om=Cn PG`(v)eWOqpqVoP9%jXAt diff --git a/pc/code_twain/sln/usb_tools/DlgScanner.cpp b/pc/code_twain/sln/usb_tools/DlgScanner.cpp index 9381e24..6520473 100644 --- a/pc/code_twain/sln/usb_tools/DlgScanner.cpp +++ b/pc/code_twain/sln/usb_tools/DlgScanner.cpp @@ -630,7 +630,7 @@ IMPLEMENT_DYNAMIC(CDlgScanner, CDialogEx) CDlgScanner::CDlgScanner(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_SCANNER, pParent) , scanner_(NULL), auto_tx_file_(-1), auto_tx_(false) - , setting_ui_(NULL), img_cnt_(0) + , setting_ui_(NULL), img_cnt_(0), paper_cnt_(0) { g_my_inst = GetModuleHandle(NULL); @@ -695,10 +695,10 @@ void CDlgScanner::set_device(usb::LPUSBPNP pnp) if (err) //::SetDlgItemTextW(m_hWnd, IDC_EDIT_COUNT, (L"Receive image " + std::to_wstring(img_cnt_) + L" error: " + std::to_wstring(err)).c_str()); - dlg->set_text(IDC_EDIT_COUNT, (L"Receive image " + std::to_wstring(img_cnt_) + L" error: " + std::to_wstring(err)).c_str()); + dlg->set_text(IDC_EDIT_COUNT, (L"Receive image " + (std::to_wstring(dlg->img_cnt_) + L"/" + std::to_wstring(dlg->paper_cnt_)) + L" error: " + std::to_wstring(err)).c_str()); else if (cur >= total) { - dlg->set_text(IDC_EDIT_COUNT, std::to_wstring(dlg->img_cnt_).c_str()); + dlg->set_text(IDC_EDIT_COUNT, (std::to_wstring(dlg->img_cnt_) + L"/" + std::to_wstring(dlg->paper_cnt_)).c_str()); if (dlg->is_checked(IDC_CHECK_AUTO_OPEN_IMG)) ShellExecuteA(dlg->m_hWnd, "Open", cur_img_file.c_str(), NULL, NULL, SW_SHOWNORMAL); @@ -708,7 +708,33 @@ void CDlgScanner::set_device(usb::LPUSBPNP pnp) }; auto img_keeper = [&](LPPACKIMAGE img, uint64_t size) -> data_holder_ptr { - if (img) + if (img == IMG_RECEIVER_FINISHED) + { + // scan stopped ... + wchar_t buf[40] = { 0 }; + HWND wnd = GetDlgItem(IDC_EDIT_COUNT)->m_hWnd; + HDC dc = ::GetDC(wnd); + + set_text(IDC_BUTTON_SCAN, L"Scan"); + ::SetTextColor(dc, size ? RGB(255, 0, 0) : RGB(0, 0, 0)); + ::ReleaseDC(wnd, dc); + + log_cls::log(LOG_LEVEL_DEBUG, "Scan stopped with error %s\r\n", usb::u2a(scanner_status(size, buf)).c_str()); + + set_text(IDC_EDIT_COUNT, (std::to_wstring(img_cnt_) + L"/" + std::to_wstring(paper_cnt_)).c_str()); + if (size == 0) + size = SCANNER_STATUS_READY; + ::PostMessage(m_hWnd, WM_DEVICE_STATTUS, 0, (LPARAM)size); + + return NULL; + } + else if (img == IMG_RECEIVER_PAPER_CNT) + { + set_text(IDC_EDIT_COUNT, (std::to_wstring(img_cnt_) + L"/" + std::to_wstring(++paper_cnt_)).c_str()); + + return NULL; + } + else { file_saver* saver = new file_saver(); std::string root(usb::u2a(img_root_.c_str())); @@ -731,26 +757,6 @@ void CDlgScanner::set_device(usb::LPUSBPNP pnp) return dynamic_cast(saver); } - else - { - // scan stopped ... - wchar_t buf[40] = { 0 }; - HWND wnd = GetDlgItem(IDC_EDIT_COUNT)->m_hWnd; - HDC dc = ::GetDC(wnd); - - set_text(IDC_BUTTON_SCAN, L"Scan"); - ::SetTextColor(dc, size ? RGB(255, 0, 0) : RGB(0, 0, 0)); - ::ReleaseDC(wnd, dc); - - log_cls::log(LOG_LEVEL_DEBUG, "Scan stopped with error %s\r\n", usb::u2a(scanner_status(size, buf)).c_str()); - - set_text(IDC_EDIT_COUNT, std::to_wstring(img_cnt_).c_str()); - if (size == 0) - size = SCANNER_STATUS_READY; - ::PostMessage(m_hWnd, WM_DEVICE_STATTUS, 0, (LPARAM)size); - - return NULL; - } }; auto status_cb = [&](uint32_t status) -> void { @@ -1198,6 +1204,7 @@ void CDlgScanner::OnBnClickedButtonScan() if (wcsicmp(title, L"Scan") == 0) { img_cnt_ = 0; + paper_cnt_ = 0; SetDlgItemInt(IDC_EDIT_COUNT, img_cnt_); if (scanner_) { diff --git a/pc/code_twain/sln/usb_tools/DlgScanner.h b/pc/code_twain/sln/usb_tools/DlgScanner.h index 0c1dc1d..965e46f 100644 --- a/pc/code_twain/sln/usb_tools/DlgScanner.h +++ b/pc/code_twain/sln/usb_tools/DlgScanner.h @@ -59,6 +59,7 @@ class CDlgScanner : public CDialogEx SANEAPI sane_api_; std::wstring img_root_; uint32_t img_cnt_; + uint32_t paper_cnt_; public: CDlgScanner(CWnd* pParent = nullptr); // 标准构造函数 diff --git a/pc/code_twain/sln/usb_tools/scanner/scanner_handler.cpp b/pc/code_twain/sln/usb_tools/scanner/scanner_handler.cpp index b9d0789..b681a2d 100644 --- a/pc/code_twain/sln/usb_tools/scanner/scanner_handler.cpp +++ b/pc/code_twain/sln/usb_tools/scanner/scanner_handler.cpp @@ -191,11 +191,21 @@ scanner_handler::scanner_handler(void) : usb_(nullptr), status_(SCANNER_STATUS_N *more = dynamic_cast(receiver); } } + else if (pack->cmd == PACK_CMD_SCAN_PAPER_ROGER) + { + if (img_receiver_) + { + data_holder_ptr receiver = img_receiver_(IMG_RECEIVER_PAPER_CNT, pack->data); + if (receiver) + receiver->release(); + } + *used = sizeof(PACK_BASE); + } else if (pack->cmd == PACK_CMD_SCAN_FINISHED_ROGER) { if (img_receiver_) { - data_holder_ptr receiver = img_receiver_(NULL, pack->data); + data_holder_ptr receiver = img_receiver_(IMG_RECEIVER_FINISHED, pack->data); if (receiver) receiver->release(); } diff --git a/pc/code_twain/sln/usb_tools/scanner/scanner_handler.h b/pc/code_twain/sln/usb_tools/scanner/scanner_handler.h index 118fb2f..ba58747 100644 --- a/pc/code_twain/sln/usb_tools/scanner/scanner_handler.h +++ b/pc/code_twain/sln/usb_tools/scanner/scanner_handler.h @@ -14,6 +14,9 @@ #include #include +#define IMG_RECEIVER_FINISHED ((LPPACKIMAGE)NULL) +#define IMG_RECEIVER_PAPER_CNT ((LPPACKIMAGE)1) + class async_usb_host; struct libusb_device;