zynq_7010/zynq_7010_code/Scanner.cpp

627 lines
18 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "Scanner.h"
#include <iostream>
#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<Sensor>(sysEvent);
seria_ = std::make_shared<seria_com>(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<InitState>::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<std::mutex> 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<NoPaperState>::GetState(data);
}
FsmState *Scanner::status_change_paper_ready(void *data)
{
return FsmStateManagerEx<PaperReadyState>::GetState(data);
}
FsmState* Scanner::status_change_scanning(void *data)
{
return FsmStateManagerEx<ScanningState>::GetState(data);
}
FsmState* Scanner::status_change_paperjam(void *data)
{
return FsmStateManagerEx<ErrorJamState>::GetState(data);
}
FsmState* Scanner::status_change_feed_in_error(void *data)
{
return FsmStateManagerEx<ErrorState>::GetState(data);
}
FsmState* Scanner::status_change_double_paper(void *data)
{
return FsmStateManagerEx<Double_Paper_State>::GetState(data);
}
FsmState* Scanner::status_change_open_cover(void *data)
{
return FsmStateManagerEx<CoverOpenState>::GetState(data);
}
FsmState* Scanner::status_change_close_cover(void *data)
{
return FsmStateManagerEx<CoverCloseState>::GetState(data);
}
FsmState* Scanner::status_change_stop_scan(void *data)
{
return FsmStateManagerEx<StopScanState>::GetState(data);
}
FsmState* Scanner::status_change_emergency_stop_scan(void *data)
{
return FsmStateManagerEx<EmergencyStopScanState>::GetState(data);
}
FsmState* Scanner::status_change_screw_detection(void *data)
{
return FsmStateManagerEx<ScrewDetectionState>::GetState(data);
}
FsmState* Scanner::status_change_init_status(void *data)
{
return FsmStateManagerEx<InitState>::GetState(data);
}
FsmState* Scanner::status_change_boundary_detection(void *data)
{
return FsmStateManagerEx<Boundary_Detection_State>::GetState(data);
}
FsmState* Scanner::status_change_seria_stop(void *data)
{
return FsmStateManagerEx<seria_stop>::GetState(data);
}
FsmState* Scanner::status_change_seria_start(void *data)
{
return FsmStateManagerEx<seria_start>::GetState(data);
}
FsmState* Scanner::status_change_seria_get_status(void *data)
{
return FsmStateManagerEx<seria_get_status>::GetState(data);
}
FsmState* Scanner::status_change_seria_set_speed_mode(void *data)
{
return FsmStateManagerEx<seria_set_speed_mode>::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<InitState>::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;
}
}