#include "stdafx.h" #include "GScanO400.h" #include "UsbScanEx.h" #include "StopWatch.h" #include "scn_config.h" #include "ImageMatQueue.h" #include "ImageProcess/ImageApplyDogEarDetection.h" #include "filetools.h" #include "GetMemoryUsage.h" #include "G400ScanConfig.h" //u32_CMD typedef enum tagUsbKeyWords : UINT32 { //无命令 NO_COMMAND = 0, //获取dsp 状态 GET_DSP_STATUS = 1, //取图 GET_IMAGE = 2, //销毁DSP中驻存的图 POP_IMAGE = 3, //开始扫描命令 START_COMMAND = 4, //停止扫描命令 STOP = 5, //获取扫描仪扫描模式 GET_SCAN_MODE = 6, //获取固件版本号 GET_FW_VERSION = 7, //返回PC端的状态 SEND_STATUS_PC = 8, //下发扫描配置参数 CONFIGURED_DATA = 9, //下发固件信息 SEND_FW = 10, //获取扫描参数 GET_CONFIG_DATA = 11, //获取扫描总张数 GET_SCANN_NUM = 12, //获取有无纸的状态 GET_PAPERFEEDER_STATUS = 13, //DSP初始化 INIT_HARDWARE_SYS = 14, //获取有无纸的状态 GET_PAPER_STATUS = 0x0d, //下发元器件配置参数(灰度,LED R曝光时间) SEND_COMPONENTS_GR = 15, //下发元器件配置参数(LED G/B曝光时间) SEND_COMPONENTS_GB = 16, //下发扫描模式 SEND_SCAN_MODE = 17, //开始进行平场矫正 START_FLAT = 18, //停止平场矫正 STOP_FLAT = 19, //下发200dpi彩色平场矫正参数 SEND_200_COLOR_FLAT_DATA = 20, //下发300dpi彩色平场矫正参数 SEND_300_COLOR_FLAT_DATA = 21, //获取200dpi彩色平场矫正参数 GET_200_COLOR_FLAT_DATA = 22, //获取300dpi彩色平场矫正参数 GET_300_COLOR_FLAT_DATA = 23, //下发200dpi灰度平场校正参数 SEND_200_GRAY_FLAT_DATA = 24, //下发300dpi灰度平场校正参数 SEND_300_GRAY_FLAT_DATA = 25, //获取200DPI灰度平场校正参数 GET_200_GRAY_FLAT_DATA = 26, //获取300DPI灰度平场校正参数 GET_300_GRAY_FLAT_DATA = 27, //下发序列号命令 SEND_SERIAL = 28, //获取序列号命令 GET_SERIAL = 29, //获取滚轴数 GET_ROLLER_NUM = 0x1e, //清零滚轴数 CLR_ROLLER_NUM = 0x1f, //清除扫描总张数 CLR_SCAN_NUM = 0x20, //准备更新固件 PRE_UPGRADE = 0X21, //开始更新固件 START_UPGRADE = 0x22, //彩色的AD参数 RGB_ADI_PARA = 0x23, //灰度的AD参数 ADI_PARA = 0x24, //获取CIS参数(曝光时间,ad参数) GET_CIS_PARA = 0x25, //扫描张数 START_COMMAND_COUNT = 0x26, //下发休眠时间 SET_SLEEP_TIME = 0x27, //获取休眠时间 GET_SLEEP_TIME = 0x28, //清除缓存 CLR_CACHE = 0x29, //下发速度模式 SET_SPEED_MODE = 0x2a, //获取扫描速度模式 GET_SPEED_MODE = 0X2b, //设置固件版本一共8个字节 SET_FW_VERSION = 0X2c, //获取DSP版本 GET_DSP_VERSION = 0X2d, //采集板FPGA固件版本 GET_SCANFPGA_VERSION = 0x2e, //电机板FPGA固件版本 GET_MOTORFPGA_VERSION = 0X2f, //设置制造商信息 SET_USB_INFOR_MANUFACTURE = 0X30, //获取制造商信息 GET_USB_INFOR_MANUFACTURE = 0X31, //设置产品型号信息 SET_USB_INFOR_MODEL_NAME = 0X32, //获取产品型号信息 GET_USB_INFOR_MODEL_NAME = 0X33, //设置USB PID / VID信息 SET_USB_INFOR_VIDPID = 0X34, GET_USB_INFOR_VIDPID = 0X35, //设置卡纸急停检测灵敏度 SET_JAM_DETECT_SENSITIVE = 0X36, //获取卡纸急停检测灵敏度 GET_JAM_DETECT_SENSITIVE = 0X37, //设置横向畸变系数 SET_JUST_COF_H = 0x38, //读取横向畸变系数 GET_JUST_COF_H = 0x39, CLEAR_HWERROR = 0x40,//G400 清除硬件异常 //设置纵向畸变系数 SET_JUST_COF_V = 0x41, //读取纵向畸变系数 GET_JUST_COF_V=0x42, //设置扫描仪编码 GET_CODE_G400 = 0x59, //读取扫描仪编码 SET_CODE_G400 = 0x60, //设置扫描仪编码 SET_CODE_G200 = 0x63, //读取扫描仪编码 GET_CODE_G200 = 0x64, } UsbKeyWords, * PUsbKeyWords; GScanO400::GScanO400() : huagods(NULL), image_num(0), m_bread_fixed_ratio_fromDSP(false) { m_pImages.reset(new ImageMatQueue()); m_pImages->Getimagenumber = std::bind(&GScanO400::Getimagenumber,this, std::placeholders::_1); } GScanO400::~GScanO400() { if (m_threadUsb && m_threadUsb->joinable()) { devState = DEV_STOP; m_threadUsb->join(); m_threadUsb.reset(); } if (m_usb.get()) m_usb.reset(); } void GScanO400::Getimagenumber(bool isadd) { if (isadd) { image_num++; } else { image_num--; } } void GScanO400::DogEar_callback(std::function fun) { m_pImages->DogEarDetection_callback = fun; } void GScanO400::open(int vid, int pid) { auto usbs = UsbScan_List::find_vid_pid(vid, pid); if (!usbs.empty()) { m_usb = *usbs.begin(); m_usb->set_usbhotplug_callback(usbhotplug_callback, this); bool ret = m_usb->open(); USBCB status = { GET_DSP_STATUS ,0,0 }; if (m_usb.get() && m_usb->is_connected()) m_usb->write_bulk(&status, sizeof(status)); if (m_usb.get() && m_usb->is_connected()) m_usb->read_bulk(&status, sizeof(status)); } } void GScanO400::regist_deviceevent_callback(deviceevent_callback callback, void* usrdata) { huagods = usrdata; dev_callback = callback; } #ifdef LOG_NORMAL fstream fsaquire; static int aquiretimes = 1; #endif // LOG int GScanO400::aquire_bmpdata(std::vector& bmpdata) { StopWatch sw; while (true) { if (m_pImages->empty()) { DoEvents(); this_thread::sleep_for(chrono::milliseconds(1)); if (sw.elapsed_s() > 20.00) { if (m_threadUsb && m_threadUsb->joinable()) { devState = DEV_STOP; m_threadUsb->join(); m_threadUsb.reset(); //writelog("aquire_bmpdata m_threadUsb.reset();"); } Stop_scan();//停止扫描 ResetScanner(); return HARDWARE_ERROR; } if (!is_scan()) { if (devState == DEV_WRONG) { return get_ErrorCode(); } return -1; } } else { if (m_pImages->valid()) { bmpdata = *(m_pImages->popBmpdata()); //static int aqimgindex = 0; //writelog("aquireed image " + to_string(++aqimgindex)); //FileTools::write_log("C:\\Users\\huagao\\Desktop\\out.txt", "aquired procced image "+ to_string(++aqimgindex)); #ifdef LOG_NORMAL static int aquireindex = 0; FileTools::write_log("out.txt", "aquire image index " + std::to_string(++aquireindex)); #endif // LOG return 0; } DoEvents(); this_thread::sleep_for(chrono::milliseconds(2)); } } } BOOL GScanO400::IsConnected() { return m_usb.get() && m_usb->is_connected(); } std::string GScanO400::GetFWVersion() { if (m_usb.get() && m_usb->is_connected()) { lock_guard< mutex> lock(m_imgLocker); if (fwVersion.empty()) { fwVersion.resize(10); USBCB cmd = { GET_FW_VERSION,fwVersion.size(),0, }; m_usb->write_bulk(&cmd, sizeof(cmd)); if(m_usb.get()&&m_usb->is_connected()) m_usb->read_bulk(&fwVersion[0], fwVersion.size()); } return fwVersion; } return ""; } std::string GScanO400::GetSerialNum() { //return "G20018000298"; if (m_usb.get() && m_usb->is_connected()) { std::lock_guard lck(m_imgLocker); if (SerialNum.empty()) { SerialNum.resize(14); USBCB usbcb = { GET_SERIAL,SerialNum.size(),0 }; m_usb->write_bulk(&usbcb, sizeof(usbcb)); if(m_usb.get()&&m_usb->is_connected()) m_usb->read_bulk(&SerialNum[0], SerialNum.size()); } return SerialNum; } return ""; } bool GScanO400::is_scan() { //std::lock_guard lck(m_imgLocker); return devState == DEV_ISRUNNING; } BOOL GScanO400::Get_Scanner_PaperOn() { if (!(m_usb.get() && m_usb->is_open())) { Set_ErrorCode(USB_DISCONNECTED); return true; } //return false; USBCB usbcb = { GET_PAPER_STATUS ,2,0 }; std::lock_guard lck(m_imgLocker); m_usb->write_bulk(&usbcb, sizeof(usbcb)); if (m_usb.get() && m_usb->is_connected()) { m_usb->read_bulk(&usbcb, sizeof(usbcb)); if (usbcb.u32_Data == 2) { Set_ErrorCode(USB_DISCONNECTED); return true; } } else{ Set_ErrorCode(USB_DISCONNECTED); return true; } return usbcb.u32_Data != 0; } int GScanO400::Get_Roller_num() { if (!(m_usb.get() && m_usb->is_open())) return false; USBCB usbcb = { GET_ROLLER_NUM ,0,0 }; std::lock_guard lck(m_imgLocker); m_usb->write_bulk(&usbcb, sizeof(usbcb)); m_usb->read_bulk(&usbcb, sizeof(usbcb)); return usbcb.u32_Data; } void GScanO400::config_params(GScanCap& params) { if (m_usb.get() && m_usb->is_connected()) { G400ScanConfig cfg = G400ScanConfig(params); gcap = params; UINT32 cfgdata = cfg.GetData(); USBCB usbcb = { CONFIGURED_DATA,cfgdata,0 }; //FileTools::write_log("开始下发硬件参数 ===> \n\tUSB config_params:"+to_string(cfgdata)+"\n\tpaper:"+to_string(cfgdata&0x1f) // + "\n\tcolor:" + to_string((cfgdata>>5) & 0x1) // + "\n\tdpi:" + to_string((cfgdata>>6) & 0x3) // + "\n\tdouble_feed_enbale:" + to_string((cfgdata>>8) & 0x1) // + "\n\tstable_enbale:" + to_string((cfgdata>>9) & 0x1) // + "\n\tenableLed:" + to_string((cfgdata>>10) & 0x1) // + "\n\treversed1:" + to_string((cfgdata>>11) & 0x3F) // + "\n\tisCorrect:" + to_string((cfgdata>>17) & 0x1) // + "\n\tdstHeight:" + to_string((cfgdata>>18) & 0xFF) // + "\n\treversed2:" + to_string((cfgdata>>26) & 0x3F)); FileTools::writelog(log_INFO, "config hardware param"); m_usb->write_bulk(&usbcb, sizeof(USBCB)); this_thread::sleep_for(std::chrono::milliseconds(200)); m_pImages->setparam(params); } } void GScanO400::Scanner_StartScan(UINT16 count) { roller_num= Get_Roller_num(); std::lock_guard lck(m_imgLocker); if (m_threadUsb && m_threadUsb->joinable()) { devState = DEV_STOP; m_threadUsb->join(); } USBCB status = { GET_DSP_STATUS ,0,0 }; if (m_usb.get() && m_usb->is_connected()) m_usb->write_bulk(&status, sizeof(status)); if (m_usb.get() && m_usb->is_connected()) m_usb->read_bulk(&status, sizeof(status)); switch (status.u32_Data) { case COUNT_MODE: case NO_FEED: case OPEN_COVER: case FEED_IN_ERROR: case PAPER_JAM: case DETECT_DOUBLE_FEED: case DETECT_STAPLE: case PAPER_SKEW: case HARDWARE_ERROR: case PC_SCAN_BUSY_or_ERROR: m_pImages->setscanflags(false); devState = DEV_WRONG; Set_ErrorCode(status.u32_Data); if (huagods) dev_callback(status.u32_Data, huagods); return; default: break; } int readlenght = 0; USBCB paperstatus = { GET_PAPER_STATUS ,0,0 }; if (m_usb.get() && m_usb->is_connected()) m_usb->write_bulk(&paperstatus, sizeof(paperstatus)); if (m_usb.get() && m_usb->is_connected()) readlenght= m_usb->read_bulk(&paperstatus, sizeof(paperstatus)); if (paperstatus.u32_Data == 0) { m_pImages->setscanflags(false); devState = DEV_WRONG; int errorcode = 0; readlenght == 0 ? errorcode = USB_DISCONNECTED : errorcode = NO_FEED; Set_ErrorCode(errorcode); if (huagods) dev_callback(errorcode, huagods); return; } m_pImages->reset_DogEar(); if (gcap.is_duplex) count = count == 65535 ? 65535 : count / 2; USBCB usbcb = { START_COMMAND,(UINT32)count ,0 }; if (m_usb.get() && m_usb->is_connected()) m_usb->write_bulk(&usbcb, sizeof(usbcb)); this_thread::sleep_for(std::chrono::milliseconds(200)); if (m_usb.get() && m_usb->is_connected()) { m_pImages->setscanflags(true); m_threadUsb.reset(new std::thread(&GScanO400::usbmain, this)); m_pImages->run(); } } void GScanO400::Stop_scan() { std::lock_guard lck(m_imgLocker); USBCB usbcb = { STOP ,0,0 }; if (m_usb.get() && m_usb->is_connected()) m_usb->write_bulk(&usbcb, sizeof(usbcb)); } void GScanO400::ResetScanner() { if (!(m_usb.get() && m_usb->is_connected())) return; std::lock_guard lck(m_imgLocker); USBCB usbcb = { INIT_HARDWARE_SYS ,0,0 }; if (m_usb.get() && m_usb->is_connected()) m_usb->write_bulk(&usbcb, sizeof(usbcb)); } bool GScanO400::Get_IsImageQueueEmpty() { return m_pImages->empty(); } void GScanO400::reset() { while (!m_pImages->empty()) m_pImages->clear(); } void GScanO400::setdecodepixtype(int twpixtype) { } UINT32 GScanO400::get_ErrorCode() { return Error_Code; } void GScanO400::Set_ErrorCode(UINT32 value) { Error_Code = value; } int GScanO400::get_scanned_num() { std::lock_guard lck(m_imgLocker); USBCB usbcb = { GET_SCANN_NUM ,0,0 }; if (m_usb.get() && m_usb->is_connected()) m_usb->write_bulk(&usbcb, sizeof(usbcb)); return usbcb.u32_Count; } void GScanO400::clear_hwerror() { std::lock_guard lck(m_imgLocker); USBCB usbcb = { CLEAR_HWERROR ,0,0 }; if (m_usb.get() && m_usb->is_connected()) m_usb->write_bulk(&usbcb, sizeof(usbcb)); } void GScanO400::set_sleep_time(int mode) { return ; } bool GScanO400::set_scannercode(std::string str) { if (str.size() != 32) return false; if (!(m_usb.get() && m_usb->is_connected())) return false; for (int i = 0; i < str.size(); i += 4) { USBCB usbcb = { SET_CODE_G400,UINT32(str[i]) + ((UINT32(str[i + 1])) << 8) + (((UINT32)str[i + 2]) << 16) + (((UINT32)str[i + 3]) << 24),i }; m_usb->write_bulk(&usbcb, sizeof(usbcb)); } return true; } std::string GScanO400::get_scannercode() { if (!(m_usb.get() && m_usb->is_connected())) return NULL; USBCB usb{ GET_CODE_G400,0,32 }; m_usb->write_bulk(&usb, sizeof(USBCB)); std::this_thread::sleep_for(std::chrono::milliseconds(20)); scannercode.resize(32); m_usb->read_bulk(&scannercode[0], 32); return scannercode.c_str(); } void GScanO400::usbhotplug_callback(bool isconnect, void* userdata) { GScanO400* This = (GScanO400*)userdata; This->usbhotplug(isconnect); } void GScanO400::usbhotplug(bool isleft) { FileTools::writelog(log_ERROR, "enable usb callback "); if (isleft) { devState = DEV_WRONG; Error_Code = USB_DISCONNECTED; m_pImages->setscanflags(false); if (m_usb.get()) m_usb.reset(); if (huagods) dev_callback(USB_DISCONNECTED, huagods); } } void GScanO400::updateHVRatio() { if (!(m_usb.get() && m_usb->is_connected())) return; if (m_bread_fixed_ratio_fromDSP) { USBCB usbcb = { GET_JUST_COF_H ,0,0 }; m_usb->write_bulk(&usbcb, sizeof(usbcb)); m_usb->read_bulk(&usbcb, sizeof(usbcb)); float hratio = *((float*)(&usbcb.u32_Data)); usbcb = { GET_JUST_COF_V ,0,0 }; m_usb->write_bulk(&usbcb, sizeof(usbcb)); m_usb->read_bulk(&usbcb, sizeof(usbcb)); float vratio = *((float*)(&usbcb.u32_Data)); m_pImages->updatefixratio(hratio, vratio); } } void GScanO400::usbmain() { std::shared_ptr> imgData; devState = DEV_ISRUNNING; bool haveError = false; try { StopWatch sw; while (devState == DEV_ISRUNNING) { if (!(m_usb.get() && m_usb->is_connected())) { this_thread::sleep_for(chrono::milliseconds(200)); break; } if (sw.elapsed_ms() > 30000) { m_pImages->setscanflags(false); Set_ErrorCode(AQUIRE_IMAGE_TIMEOUT); devState = haveError ? DevState::DEV_WRONG : DevState::DEV_STOP; FileTools::writelog(log_ERROR, "USBmain aquire image timeout"); return; } if(gcap.resolution_dst>200.0f) { if (m_pImages->orginimgcount() > 2) { this_thread::sleep_for(chrono::milliseconds(10)); continue; } } else { if (m_pImages->orginimgcount() > 10) { this_thread::sleep_for(chrono::milliseconds(10)); continue; } } USBCB usbcb = Get_Scanner_Status(); switch (usbcb.u32_Data) { case HAVE_IMAGE: { int totalNum = usbcb.u32_Count; m_usb->set_timeout(2000); imgData = Get_Img_Data(totalNum); if (!imgData->size()) { Stop_scan(); FileTools::writelog(log_ERROR,"imgData->size() error"); break; } if(!m_pImages->get_isDogEar()) m_pImages->pushMat(std::shared_ptr(new G400Decode(imgData))); m_usb->set_timeout(200); set_aquire_image_count(get_aquire_image_count() + 1,get_updata_image_count()); FileTools::writelog(log_INFO, "从扫描仪接收" + to_string(get_aquire_image_count()) + "份文件。"); Pop_Image(); sw.reset(); break; } case STOP_SCAN: m_pImages->setscanflags(false); if (get_aquire_image_count() != (Get_Roller_num() - roller_num)) { Set_ErrorCode(LOSE_IMAGE); set_lose_image_num(std::abs((Get_Roller_num() - roller_num) - get_aquire_image_count())); haveError = true; } devState = haveError ? DevState::DEV_WRONG : DevState::DEV_STOP; //m_pImages->setscanflags(false); //devState = DEV_STOP; break; case COUNT_MODE: case NO_FEED: case OPEN_COVER: case FEED_IN_ERROR: case PAPER_JAM: case DETECT_DOUBLE_FEED: case DETECT_STAPLE: case PAPER_SKEW: case HARDWARE_ERROR: case PC_SCAN_BUSY_or_ERROR: case SIZE_ERROR: if (!haveError) { haveError = true; devState = DEV_WRONG; m_pImages->setscanflags(false); Set_ErrorCode(usbcb.u32_Data); if (get_aquire_image_count() != (Get_Roller_num() - roller_num)) set_lose_image_num(std::abs((Get_Roller_num() - roller_num) - get_aquire_image_count())); if (huagods) dev_callback(usbcb.u32_Data, huagods); } break; case NORMAL: break; default: break; } this_thread::sleep_for(chrono::milliseconds(10)); } } catch (const std::exception& e) { //writelog(e.what()); FileTools::writelog(log_ERROR,e.what()); } ////FileTools::write_log("D:\\1.txt", "thread usb exit"); } /////////////////////////////////////////////////////////////////////////// USBCB GScanO400::Get_Scanner_Status() { if (!(m_usb.get() && m_usb->is_connected())) { return { NO_COMMAND ,PC_SCAN_BUSY_or_ERROR ,0 }; } USBCB usbcb = { GET_DSP_STATUS ,0,0 }; if (m_usb.get() && m_usb->is_connected()) m_usb->write_bulk(&usbcb, sizeof(usbcb)); if (m_usb.get() && m_usb->is_connected()) m_usb->read_bulk(&usbcb, sizeof(usbcb)); return usbcb; } std::shared_ptr> GScanO400::Get_Img_Data(int bufferSize) { try { if (!(m_usb.get() && m_usb->is_connected())) return std::shared_ptr>(new std::vector()); std::shared_ptr> imData(new std::vector(bufferSize)); StopWatch sw; int readed = 0; USBCB usbcb = { GET_IMAGE,0,bufferSize }; m_usb->write_bulk(&usbcb, sizeof(usbcb)); int totalength = bufferSize; int startindex = 0; while (totalength > 0) { int dstlength = 1024 * 1024; if (totalength <= dstlength) { dstlength = totalength; totalength = 0; } else totalength -= dstlength; int tt = m_usb->read_bulk(imData->data() + startindex, dstlength); startindex += dstlength; } if (sw.elapsed_ms() > 5000) { FileTools::writelog(log_ERROR,"Usb read data timeout\n"); } return imData; } catch (const std::exception& e) { FileTools::writelog(log_ERROR, e.what()); } } /////////////////////////////////////////////////////////////////////////// void GScanO400::Pop_Image() { if (!(m_usb.get() && m_usb->is_open())) return; USBCB usbcb = { POP_IMAGE ,0,0 }; m_usb->write_bulk(&usbcb, sizeof(usbcb)); }