#include "Scanner.h" #include #include "MemoryInfo.h" #include "SysInforTool.h" #include "StopWatch.h" #define BTN_START 0 #define BTN_STOP 1 //按键停止扫描 #define BTN_LOW_POWER 2 //按键低功耗 #define BTN_NORMAL_POWER 3 //按键正常模式 (退出低功耗) Scanner::Scanner(ScannerGlue glue) : motorZouzhi(),motorCuozhi(),motor_cfg_(), m_glue(glue),m_isPulling(false), m_isDoublePaper(false),isPaperInit(false), m_jamPaper(false),m_jamIn(false), m_correctting(false),waitpapertime(200), m_scansysinfo(nullptr),auto_size_(false) { frame_time_ = 3000; m_scaninfo = GetScanInfoFromJson(); capturer.reset(new MultiFrameCapture(m_glue)); capturer->SetParent(this); capturer->set_image_callback(&have_img_callback); //固件版本 int version=7010; auto btnevent = [this](const int eventtype) { if (!IsScanning()) //未扫描 { switch (eventtype) { case BTN_LOW_POWER: stop_countdown(); system("sh /mnt/flash-disk/low_power.sh 1"); break; case BTN_NORMAL_POWER: system("sh /mnt/flash-disk/low_power.sh 0"); start_enter_lowpwoer(); break; case BTN_START: /* code */ break; default: break; } } else //扫描中 { if (eventtype == BTN_STOP) { put(S_EVT_STOP_SCAN); printf("keyboard cancel scan\r\n"); } } }; sensor = std::make_shared(sysEvent); m_keyboard.reset(new huagao::Keyboard(btnevent)); m_keyboard->init(); motorZouzhi.enablePower(true); motorZouzhi.setSpeed(4000); motorCuozhi.setSpeed(3000); motorCuozhi.setDirection(false); FsmState::setScanner(this); threadRunMessageLoop = std::thread(&Scanner::runMessageLoop, this); Motor::enablePower(true); UpdateScanInfo(); } Scanner::~Scanner() { Motor::enablePower(false); sysEvent.Clear(); sysEvent.ShutDown(); bMsgLoop = false; threadRunMessageLoop.join(); m_DstScannum = 0; if (threadRunScan.joinable()) threadRunScan.join(); } void Scanner::updateSpeedMode() { m_scaninfo = GetScanInfoFromJson(); int speed = m_scaninfo.SpeedMode; printf("JSON文件获取当前速度:%d\r\n",speed); if(speed == 0) speed = 3; unsigned int t_dpi = m_config.params.dpi; if(m_config.params.pageSize == (unsigned int)PaperSize::G400_MAXSIZE || m_config.params.pageSize == (unsigned int)PaperSize::G400_MAXAUTO ) //长文稿采用600dpi模式扫描 t_dpi = 3; if (m_config.params.slow_moire) //摩尔纹特殊处理 t_dpi = speed = 16; Zouzhi_ParamEx_ = motor_cfg_.GetMotorSpeedParam(true,MotorConfig::MTBDType::MT_TMC,speed,m_config.params.isColor,t_dpi); Cuozhi_ParamEx_ = motor_cfg_.GetMotorSpeedParam(false,MotorConfig::MTBDType::MT_TMC,speed,m_config.params.isColor,t_dpi); motorCuozhi.speedChange(Cuozhi_ParamEx_); motorZouzhi.speedChange(Zouzhi_ParamEx_); } void Scanner::ConfigScanParam(HG_ScanConfiguration config) { m_config = config; auto_size_ = m_config.params.pageSize==(int)PaperSize::G400_AUTO || m_config.params.pageSize==(int)PaperSize::G400_MAXAUTO || m_config.params.pageSize==(int)PaperSize::G400_MAXSIZE; updateSpeedMode(); capturer->UpdateScanParam(m_config); } void Scanner::UpdateScanInfo() { m_scaninfo = GetScanInfoFromJson(); auto params = motor_cfg_.GetMotorSpeedParams(true,MotorConfig::MTBDType::MT_TMC); for (int i = 0; i < params.size(); i++) { if (params[i].speed == m_scaninfo.SpeedMode) { auto fpgaparam = GetFpgaparam(params[i].dpi, params[i].colormode); fpgaparam.Sp = params[i].sp; SaveFpgaparam(fpgaparam); if (params[i].dpi == 3 && params[i].colormode) { printf("sp sp sp sp sp sp sp sp sp:%d :%d\r\n",params[i].sp,fpgaparam.Sp); } } // if(params[i].speed == 0x10) // { // auto fpgaparam = GetFpgaparam(params[i].dpi, params[i].colormode); // fpgaparam.Sp = params[i].sp; // SaveFpgaparam(fpgaparam); // } } updateSpeedMode(); } void Scanner::have_img_callback(int val) { if (val < 0) { frame_time_ = 3000; } frame_time_ = val ; } void Scanner::startScan() { if (threadRunScan.joinable()) threadRunScan.join(); stop_countdown(); updateSpeedMode(); // //开始进行扫描 threadRunScan = std::thread(&Scanner::runScan, this); } void Scanner::runMessageLoop() { std::this_thread::sleep_for(std::chrono::milliseconds(3000));//避免scanpin io 开始异常 GetSysInfo();//待fpga 重启完成 FsmState *fsmState = FsmStateManagerEx::GetState(); while (bMsgLoop) { ScanEvent evt = sysEvent.Take(); fsmState = fsmState->on_event(evt); processevent(fsmState, evt); } } void Scanner::processevent(FsmState *fsmState, ScanEvent event) { if (fsmState == nullptr) { return; } //开盖模式:1 扫描中开盖 2 未扫描的时候开盖 ,目前我想不到更好的方法,暂时先这样处理 if (event == S_EVT_COVER_OPENED && isScaning) { //printf("回调:开盖1111\r\n"); m_glue.m_deviceevent(1, "Cover Open"); } else if (typeid(*fsmState) == typeid(CoverOpenState) && !isScaning) { //printf("回调:开盖2222\r\n"); m_glue.m_deviceevent(1, "Cover Open"); } else if (event == S_EVT_SCAN_STOPPED) { //printf("回调:停止1111\r\n"); if (!m_correctting) { m_glue.m_deviceevent(70, "Scan done"); } } else if (event == S_EVT_JAM_IN) { //printf("回调:搓纸失败11111\r\n"); m_glue.m_deviceevent(4, "Feed error"); } else if (event == S_EVT_DOUBLEPAPER) { //printf("回调:双张\r\n"); m_glue.m_deviceevent(16, "Double feed"); } else if (event == S_EVT_JAM_OUT || typeid(*fsmState) == typeid(ErrorJamState)) { //printf("回调:卡纸\r\n"); m_glue.m_deviceevent(8, "Jam out"); } else if (typeid(*fsmState) == typeid(ErrorState) && m_jamIn == true) { //printf("回调:搓纸失败22222\r\n"); m_glue.m_deviceevent(4, "Feed error"); } if (!IsScanning() && (typeid(*fsmState) == typeid(ErrorJamState) || typeid(*fsmState) == typeid(CoverOpenState) || (typeid(*fsmState) == typeid(ErrorState) && m_jamIn == true))) { if (!m_correctting) { //printf("回调:停止2222\r\n"); m_glue.m_deviceevent(70, "Scan Stop"); } } } void Scanner::runScan() { LOG("-------------Scanner RunScan Start-------------\r\n"); capturer->open(); motorZouzhi.start(); motorCuozhi.pauseWaitForThread(); if (!isPaperInit) { preFeed(); isPaperInit = true; } this_thread::sleep_for(std::chrono::milliseconds(200)); sensor->resetPaperPin(); capturer->resetimageremain(); capturer->setScanFlag(true); bool b_autosize = m_config.params.pageSize==(int)PaperSize::G400_AUTO || m_config.params.pageSize==(int)PaperSize::G400_MAXAUTO || m_config.params.pageSize==(int)PaperSize::G400_MAXSIZE; StopWatch sw; StopWatch sw1; isScaning = true; int error_code = 0; while (m_DstScannum > 0) { isScaning = true; sw1.reset(); m_isDoublePaper = false; m_jamPaper = false; m_jamIn = false; if (!sensor->isPaperStandby()) //无纸 { if (!sensor->waitPaperStandBy(0)) { put(S_EVT_STOP_SCAN); } isScaning = false; break; } sensor->enableDoubleSensor(m_config.params.doubleFeeded); if (m_DstScannum == 0) //被取消扫描了 { isScaning = false; break; } motorCuozhi.startAsyn(); // if (!sensor->isPaperStandby()) { put(S_EVT_STOP_SCAN); isRested = false; isScaning = false; break; } isRested = false; if (!sensor->waitPaperIn(3000))// { if (!m_isDoublePaper) { m_jamIn = true; put(S_EVT_JAM_IN); m_scaninfo.JamInNum++; } isScaning = false; break; } printf("检测到纸张的时间:%f\r\n",sw.elapsed_ms());//检测到纸张 capturer->snap(); motorCuozhi.pauseWaitForThread(); capturer->wait_image_notify(); if (!sensor->isCoverClosed()) //中途开盖 笑麻了 { break; } printf("一张纸所需要的采集时间:%dms\r\n",frame_time_); if (sensor->waitPaperOut(frame_time_)) { if (!m_isDoublePaper) { error_code = (int)HG_ScannerStatus::PAPER_JAM; m_jamPaper = true; put(S_EVT_JAM_OUT); m_scaninfo.JamOutNum++; printf("paper 卡纸了。。。。。\n"); } else error_code = (int)HG_ScannerStatus::DETECT_DOUBLE_FEED; printf("error_code:%d\r\n",error_code); capturer->waitsnapdone(error_code);//等待采集完成 isScaning = false; break; } sensor->enableDoubleSensor(false); capturer->stopsnap(b_autosize); error_code = m_isDoublePaper ? (int)HG_ScannerStatus::DETECT_DOUBLE_FEED : m_jamPaper ? (int)HG_ScannerStatus::PAPER_JAM :0; capturer->waitsnapdone(error_code);//等待采集完成 { m_DstScannum--; m_scaninfo.RollerNum++; m_scaninfo.TotalScanned++; } if (m_DstScannum == 0) { put(S_EVT_STOP_SCAN); isScaning = false; break; } sw.reset(); ////必须控制队列帧数。 while ( m_config.params.dpi == 0x01 && image_num_>=15) { printf("200DPI 图像队列过多,正在等待图像取走:%d\r\n",image_num_); this_thread::sleep_for(std::chrono::milliseconds(300)); } while ( m_config.params.dpi == 0x02 && image_num_ >= 8 && m_config.params.isColor == 1) { printf("300DPI 图像队列过多,正在等待图像取走:%d\r\n",image_num_); this_thread::sleep_for(std::chrono::milliseconds(300)); } // while ( m_config.params.dpi == 0x02 && image_num_ >= 20 && m_config.params.isColor == 0) // { // printf("300DPI 图像队列过多,正在等待图像取走:%d\r\n",image_num_); // this_thread::sleep_for(std::chrono::milliseconds(300)); // } while ( m_config.params.dpi == 0x03 && image_num_ >= 2) { printf("600DPI 图像队列过多,正在等待图像取走:%d\r\n",image_num_); this_thread::sleep_for(std::chrono::milliseconds(300)); } while (meminfo->GetMemoryUsed() > 90.0f) //内存占用高于75% 其实我觉得开发人员应该自己控制好这个内存大小,让他绝对不可能超过这个内存大小 { if (sw.elapsed_s() < 50.0) std::this_thread::yield(); else { put(S_EVT_STOP_SCAN); isScaning = false; break; } } } isScaning = false; m_DstScannum = 0; sensor->enableDoubleSensor(false); sensor->resetPaperPin(); capturer->setScanFlag(false); capturer->stopsnap(b_autosize); int t_delay = 500; this_thread::sleep_for(std::chrono::milliseconds(t_delay)); //走纸多转一会儿 确保扫描传感器过了之后 纸能出完 LOG("\n--------------------------scan done --------------------------------\n"); } void Scanner::CreatCorrectData(int correctmode) { m_correctting = true; capturer->createCorrect(correctmode); } void Scanner::preFeed() { int sleeptime = 300; motorCuozhi.feeding(); std::this_thread::sleep_for(std::chrono::milliseconds(sleeptime)); motorCuozhi.pause(); std::this_thread::sleep_for(std::chrono::milliseconds(300)); } std::string Scanner::GetSysInfo() { meminfo = MemoryInfo::GetInstance(); auto scannerinfo = GetScanInfo(); auto fwverion = mapFradme_SP[scannerinfo.SpeedMode].FWVERSIO; ScannerSysInfo info = { .CPU = SCPU::CPU_3288, .Systype = SysType::Sys_Linux_Debian, .Screentype = ScreenType::ST_None, .MtBoardVersion = 0x20220114, .MtType = SMBType::MB_DRV_UNKNOWUN, .FPGAVersion = 0, .Cistype = HGCISType::CIS_UNKOWNUN, .ResSup = {200, 300, 0}, .MemTotal = 0, .DiskTotal = 100, .DiskUsed = 0, .KernelVersion = "", .Have_EthernPort = 0, .ServiceVersion = fwverion, .UsbProtocol = 1.0}; m_scansysinfo.reset(new SysInforTool(info)); return m_scansysinfo->GetSysInfo(); } void Scanner::emergency_stop(int id) { sensor->cancelWaitPaper(); sensor->enableDoubleSensor(false); m_DstScannum = 0; motorCuozhi.stop(); motorZouzhi.stop(); capturer->stopsnap(true); put(S_EVT_SCAN_STOPPED); SaveScaninfo(m_scaninfo); start_enter_lowpwoer(); printf("emergency_stop capturer->close() \n"); } void Scanner::stop_scan() { sensor->cancelWaitPaper(); sensor->enableDoubleSensor(false); m_DstScannum = 0; if (threadRunScan.joinable()) threadRunScan.join(); motorZouzhi.stop(); motorCuozhi.stop(); put(S_EVT_SCAN_STOPPED); SaveScaninfo(m_scaninfo); start_enter_lowpwoer(); printf("stop_scan stop_scan stop_scan\r\n"); } void Scanner::reset() { if (!sensor->isPaperStandby()) { motorCuozhi.reset(); isRested = true; isPaperInit = false; printf("Scanner->motorCuozhi is reseted \n"); } } void Scanner::paper_pullout() { if (!m_isPulling) m_isPulling = true; motorCuozhi.stop(); MotorSpeedParamEx ParamEx = motor_cfg_.GetMotorSpeedParam(true,MotorConfig::MTBDType::MT_TMC,1,1,1); motorZouzhi.speedChange(ParamEx); motorZouzhi.setDirection(1); motorZouzhi.start(); if (sensor->waitPaperOut(5000)) std::this_thread::sleep_for(std::chrono::milliseconds(2000)); motorZouzhi.stop(); motorZouzhi.speedRecover(); m_isPulling = false; }