#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), m_iscrew(false),m_isoutBoundary(false), seria_is_wait_(false) { frame_time_ = 3000; m_scaninfo = GetScanInfoFromJson(); status_change_init(); 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(HG_EVT_STOP_SCAN); printf("keyboard cancel scan\r\n"); } } }; sensor = std::make_shared(sysEvent); seria_ = 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; UpdateScanInfo(); 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(200));//避免scanpin io 开始异常 GetSysInfo();//待fpga 重启完成 void *data = NULL; FsmState *fsm = FsmStateManagerEx::GetState(data); while (bMsgLoop) { ScanEvent evt = sysEvent.Take(); fsm = fsm->on_event(evt); processevent(evt); } } void Scanner::processevent(ScanEvent event) { if (event == HG_EVT_START_SCAN || event == HG_EVT_COVER_CLOSED || event == HG_EVT_PAPER_STANDBY || event == HG_EVT_NORES || event == HG_EVT_NOT_OUT_BOUNDS || event == HG_EVT_SCREW_NOT_DETECTION) //可以过滤没有用的信息 { return; } //printf("插入事件 001 ID:%d\r\n",event); if (event_2_hg_map_.count(event) > 0) m_glue.m_deviceevent(event_2_hg_map_[event], ""); } void Scanner::runScan() { LOG("-------------Scanner RunScan Start-------------\r\n"); sensor->resetPaperPin(); capturer->open(); motorCuozhi.pauseWaitForThread(); if (!isPaperInit) { //preFeed(); //isPaperInit = true; } motorZouzhi.start(); capturer->setScanFlag(true); StopWatch sw; isScaning = true; m_isDoublePaper = false; m_iscrew = false; m_isoutBoundary = false; m_jamPaper = false; m_jamIn = false; int error_code = 0; while (m_DstScannum > 0) { sensor->enableDoubleSensor(m_config.params.doubleFeeded); sensor->width_detect_enable(m_config.params.width_detect_enable); sensor->screw_detect_enable(m_config.params.screw_detect_enable); if (m_DstScannum == 0) //被取消扫描了 { isScaning = false; break; } if (seria_is_wait_) { seria_wait_notify(); if (!sensor->isPaperStandby()) { break; } } motorCuozhi.startAsyn(); if (!sensor->waitPaperIn(3000))// { if (!m_isDoublePaper && !m_iscrew && !m_isoutBoundary) { m_jamIn = true; put(HG_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()) //中途开盖 笑麻了 { error_code = (int)HG_ScannerStatus::OPEN_COVER; capturer->waitsnapdone(error_code);//等待采集完成 break; } printf("一张纸所需要的采集时间:%dms\r\n",frame_time_); if (auto_size_ || m_config.params.dpi == 3) { frame_time_ += 2000; } if (sensor->waitPaperOut(frame_time_)) { if (!m_isDoublePaper && !m_iscrew && !m_isoutBoundary) { error_code = (int)HG_ScannerStatus::PAPER_JAM; m_jamPaper = true; put(HG_EVT_JAM_OUT); m_scaninfo.JamOutNum++; } else error_code = m_isDoublePaper?(int)HG_ScannerStatus::DETECT_DOUBLE_FEED:(int)HG_ScannerStatus::PAPER_SKEW; //printf("error_code:%d\r\n",error_code); capturer->waitsnapdone(error_code);//等待采集完成 isScaning = false; break; } sensor->enableDoubleSensor(false); sensor->width_detect_enable(false); sensor->screw_detect_enable(false); capturer->stopsnap(auto_size_); 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(HG_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_ >= 12 && 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 == 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(HG_EVT_STOP_SCAN); isScaning = false; break; } } } isScaning = false; m_DstScannum = 0; sensor->enableDoubleSensor(false); sensor->width_detect_enable(false); sensor->screw_detect_enable(false); sensor->resetPaperPin(); capturer->setScanFlag(false); capturer->stopsnap(auto_size_); 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 = 150; 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) { seria_cancel_wait(); sensor->cancelWaitPaper(); sensor->enableDoubleSensor(false); sensor->width_detect_enable(false); sensor->screw_detect_enable(false); m_DstScannum = 0; motorCuozhi.stop(); motorZouzhi.stop(); capturer->stopsnap(true); SaveScaninfo(m_scaninfo); start_enter_lowpwoer(); } void Scanner::stop_scan() { seria_cancel_wait(); sensor->cancelWaitPaper(); sensor->enableDoubleSensor(false); sensor->width_detect_enable(false); sensor->screw_detect_enable(false); m_DstScannum = 0; if (threadRunScan.joinable()) threadRunScan.join(); motorZouzhi.stop(); motorCuozhi.stop(); SaveScaninfo(m_scaninfo); start_enter_lowpwoer(); } void Scanner::reset() { if (!sensor->isPaperStandby()) { motorCuozhi.reset(); isPaperInit = false; LOG("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; } void Scanner::seria_wait_notify() { std::unique_lock lock(seria_lock_); wait_seria_.wait(lock); } void Scanner::seria_cancel_wait() { wait_seria_.notify_all(); seria_is_wait_ = false; } void Scanner::seria_send(void * data,int len) { seria_->cc_seria_send(data,len); } void Scanner::seria_set_speed(int sp) { m_scaninfo.SpeedMode = sp; SaveScaninfo(m_scaninfo); } void Scanner::status_change_init() { status_change_map_[HG_EVT_PAPER_NOT_STANDBY] = &Scanner::status_change_standby ; status_change_map_[HG_EVT_PAPER_STANDBY] = &Scanner::status_change_paper_ready; status_change_map_[HG_EVT_JAM_OUT] = &Scanner::status_change_paperjam; status_change_map_[HG_EVT_JAM_IN] = &Scanner::status_change_feed_in_error; status_change_map_[HG_EVT_COVER_OPENED] = &Scanner::status_change_open_cover; status_change_map_[HG_EVT_COVER_CLOSED] = &Scanner::status_change_close_cover; status_change_map_[HG_EVT_ERROR_DOUBLEPAPER] = &Scanner::status_change_double_paper; status_change_map_[HG_EVT_START_SCAN] = &Scanner::status_change_scanning; status_change_map_[HG_EVT_STOP_SCAN] = &Scanner::status_change_stop_scan; status_change_map_[HG_EVT_STOP_SCAN_EMERGENCY] = &Scanner::status_change_emergency_stop_scan; status_change_map_[HG_EVT_DOUBLEPAPER] = &Scanner::status_change_double_paper; status_change_map_[HG_EVT_SCREW_DETECTION] = &Scanner::status_change_screw_detection; status_change_map_[HG_EVT_OUT_BOUNDS] = &Scanner::status_change_boundary_detection; status_change_map_[HG_EVT_SERIA_STOP_FEEDING] = &Scanner::status_change_seria_stop; status_change_map_[HG_EVT_SERIA_START_FEEDING] = &Scanner::status_change_seria_start; status_change_map_[HG_EVT_SERIA_GET_STATUS] = &Scanner::status_change_seria_get_status; status_change_map_[HG_EVT_SERIA_SPEED_MODE_1] = &Scanner::status_change_seria_set_speed_mode; status_change_map_[HG_EVT_SERIA_SPEED_MODE_2] = &Scanner::status_change_seria_set_speed_mode; status_change_map_[HG_EVT_SERIA_SPEED_MODE_3] = &Scanner::status_change_seria_set_speed_mode; status_change_map_[HG_EVT_SERIA_SPEED_MODE_4] = &Scanner::status_change_seria_set_speed_mode; status_change_map_[HG_EVT_SERIA_SPEED_MODE_5] = &Scanner::status_change_seria_set_speed_mode; event_2_hg_map_[HG_EVT_PAPER_NOT_STANDBY] = (int)HG_ScannerStatus::NO_FEED; event_2_hg_map_[HG_EVT_JAM_OUT] = (int)HG_ScannerStatus::PAPER_JAM; event_2_hg_map_[HG_EVT_JAM_IN] = (int)HG_ScannerStatus::FEED_IN_ERROR; event_2_hg_map_[HG_EVT_COVER_OPENED] = (int)HG_ScannerStatus::OPEN_COVER; event_2_hg_map_[HG_EVT_ERROR_DOUBLEPAPER] = (int)HG_ScannerStatus::DETECT_DOUBLE_FEED; event_2_hg_map_[HG_EVT_STOP_SCAN] = (int)HG_ScannerStatus::STOP_SCAN; event_2_hg_map_[HG_EVT_STOP_SCAN_EMERGENCY] = (int)HG_ScannerStatus::STOP_SCAN; event_2_hg_map_[HG_EVT_SCREW_DETECTION] = (int)HG_ScannerStatus::PAPER_SKEW; event_2_hg_map_[HG_EVT_OUT_BOUNDS] = (int)HG_ScannerStatus::BOUNDS_OUT_TEST; } FsmState* Scanner::status_change_standby(void *data) { return FsmStateManagerEx::GetState(data); } FsmState *Scanner::status_change_paper_ready(void *data) { return FsmStateManagerEx::GetState(data); } FsmState* Scanner::status_change_scanning(void *data) { return FsmStateManagerEx::GetState(data); } FsmState* Scanner::status_change_paperjam(void *data) { return FsmStateManagerEx::GetState(data); } FsmState* Scanner::status_change_feed_in_error(void *data) { return FsmStateManagerEx::GetState(data); } FsmState* Scanner::status_change_double_paper(void *data) { return FsmStateManagerEx::GetState(data); } FsmState* Scanner::status_change_open_cover(void *data) { return FsmStateManagerEx::GetState(data); } FsmState* Scanner::status_change_close_cover(void *data) { return FsmStateManagerEx::GetState(data); } FsmState* Scanner::status_change_stop_scan(void *data) { return FsmStateManagerEx::GetState(data); } FsmState* Scanner::status_change_emergency_stop_scan(void *data) { return FsmStateManagerEx::GetState(data); } FsmState* Scanner::status_change_screw_detection(void *data) { return FsmStateManagerEx::GetState(data); } FsmState* Scanner::status_change_init_status(void *data) { return FsmStateManagerEx::GetState(data); } FsmState* Scanner::status_change_boundary_detection(void *data) { return FsmStateManagerEx::GetState(data); } FsmState* Scanner::status_change_seria_stop(void *data) { return FsmStateManagerEx::GetState(data); } FsmState* Scanner::status_change_seria_start(void *data) { return FsmStateManagerEx::GetState(data); } FsmState* Scanner::status_change_seria_get_status(void *data) { return FsmStateManagerEx::GetState(data); } FsmState* Scanner::status_change_seria_set_speed_mode(void *data) { return FsmStateManagerEx::GetState(data); } FsmState *Scanner::test(ScanEvent e) { void * data = NULL; int r = 0; if (e == HG_EVT_SERIA_SPEED_MODE_1 || e == HG_EVT_SERIA_SPEED_MODE_2 ||e == HG_EVT_SERIA_SPEED_MODE_3 ||e == HG_EVT_SERIA_SPEED_MODE_4 ||e == HG_EVT_SERIA_SPEED_MODE_5 ) { seria_protocol s = hgevt_2_seria(e); r = (int)s; } //printf("插入事件 000 ID:%d\r\n",e); //data = &(hgevt_2_seria(e)); if (status_change_map_.count(e) > 0) { FsmState *fsm = (this->*status_change_map_[e])((void*)&r); //printf("当前状态事件:%s\r\n",typeid(*fsm).name()); return fsm; } return FsmStateManagerEx::GetState(data); } seria_protocol Scanner::hgevt_2_seria(ScanEvent p) { switch (p) { case HG_EVT_SERIA_SPEED_MODE_1: return HG_SERIA_SPEED_MODE_1 ; case HG_EVT_SERIA_SPEED_MODE_2: return HG_SERIA_SPEED_MODE_2; case HG_EVT_SERIA_SPEED_MODE_3: return HG_SERIA_SPEED_MODE_3; case HG_EVT_SERIA_SPEED_MODE_4: return HG_SERIA_SPEED_MODE_4; case HG_EVT_SERIA_SPEED_MODE_5: return HG_SERIA_SPEED_MODE_5; } }