512 lines
12 KiB
C++
512 lines
12 KiB
C++
#include "stdafx.h"
|
|
#include "GDevice.h"
|
|
#include "IUsb.h"
|
|
#include <cstdio>
|
|
#include <iostream>
|
|
#include <algorithm>
|
|
#include <set>
|
|
#include <string.h>
|
|
#include <fstream>
|
|
#include <iterator>
|
|
#include <sstream>
|
|
#include "StopWatch.h"
|
|
#include "device_common.h"
|
|
#ifndef WIN32
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
|
|
#define DSP_CODE_ADDR 0
|
|
#define USER_ADDR 0x4000
|
|
|
|
using namespace std;
|
|
|
|
GDevice::GDevice(std::shared_ptr<IUsb> usb)
|
|
{
|
|
m_bScan = false;
|
|
m_bListen = false;
|
|
m_usb = usb;
|
|
event_call = NULL;
|
|
image_call = NULL;
|
|
m_imagecall_userdata = NULL;
|
|
m_eventcall_userdata = NULL;
|
|
m_threadInt = NULL;
|
|
m_threadrecv = NULL;
|
|
m_run = false;
|
|
}
|
|
|
|
GDevice::~GDevice()
|
|
{
|
|
close();
|
|
}
|
|
|
|
bool GDevice::open()
|
|
{
|
|
if (is_open())
|
|
return true;
|
|
|
|
if (m_usb && m_usb->open()) {
|
|
m_usb->set_timeout(1000);
|
|
init_cam();
|
|
m_bListen = true;
|
|
m_bScan = true;
|
|
|
|
if (m_threadInt) {
|
|
m_bListen = false;
|
|
m_threadInt->join();
|
|
}
|
|
|
|
if (m_threadrecv) {
|
|
m_bScan = false;
|
|
m_threadrecv->join();
|
|
}
|
|
m_bListen = true;
|
|
m_bScan = true;
|
|
m_threadInt = std::shared_ptr<std::thread>(new std::thread(&GDevice::Int_main, this));
|
|
m_threadrecv = std::shared_ptr<std::thread>(new std::thread(&GDevice::recv_main, this));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void GDevice::close()
|
|
{
|
|
if (m_usb.get() && m_usb->is_open()) {
|
|
m_usb->set_timeout(100);
|
|
stop();
|
|
|
|
if (m_threadInt && m_threadInt->joinable()) {
|
|
m_bListen = false;
|
|
this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
m_threadInt->join();
|
|
m_threadInt = NULL;
|
|
}
|
|
|
|
if (m_threadrecv && m_threadrecv->joinable()) {
|
|
m_bScan = false;
|
|
image_indexs.ShutDown();
|
|
m_threadrecv->join();
|
|
m_threadrecv = NULL;
|
|
}
|
|
m_usb->close();
|
|
}
|
|
}
|
|
|
|
bool GDevice::is_open()
|
|
{
|
|
if (m_usb.get())
|
|
return m_usb->is_open();
|
|
return false;
|
|
}
|
|
|
|
bool GDevice::start(image_callback callfunc, void* userdata)
|
|
{
|
|
if (is_run())
|
|
return false;
|
|
|
|
image_call = callfunc;
|
|
m_imagecall_userdata = userdata;
|
|
MotorSetting ms;
|
|
ms.value = read_reg(MOTOR_BOARD, 0x00);
|
|
ms.scan_enable = 0;
|
|
write_reg(MOTOR_BOARD, 0x00, ms.value);
|
|
ms.scan_enable = 1;
|
|
write_reg(MOTOR_BOARD, 0x00, ms.value);
|
|
m_run = true;
|
|
return true;
|
|
}
|
|
|
|
void GDevice::set_event_call(event_callback callfunc, void* userdata)
|
|
{
|
|
m_eventcall_userdata = userdata;
|
|
event_call = callfunc;
|
|
}
|
|
|
|
void GDevice::stop()
|
|
{
|
|
|
|
set_option(Cam_Options::scanner_stop_motor, 0);
|
|
}
|
|
|
|
int GDevice::is_run()
|
|
{
|
|
return m_run;
|
|
}
|
|
|
|
void GDevice::reset()
|
|
{
|
|
|
|
}
|
|
|
|
static std::string read_all_from(std::string path)
|
|
{
|
|
int t;
|
|
FILE* file = fopen(path.c_str(), "rb");
|
|
fseek(file, 0, SEEK_END);
|
|
t = ftell(file);
|
|
std::string buf(t, 0);
|
|
fseek(file, 0, SEEK_SET);
|
|
fread((void*)buf.c_str(), t, 1, file);
|
|
fclose(file);
|
|
return buf;
|
|
}
|
|
|
|
void GDevice::write_dsp_fw(std::string path)
|
|
{
|
|
std::string buf = read_all_from(path);
|
|
write_flash(DSP_CODE_ADDR, (void*)buf.c_str(), buf.size());
|
|
}
|
|
|
|
void GDevice::write_pid(unsigned short pid)
|
|
{
|
|
write_flash(PID_ADDR, &pid, sizeof(pid));
|
|
}
|
|
|
|
unsigned short GDevice::read_pid()
|
|
{
|
|
unsigned short pid;
|
|
read_flash(PID_ADDR, &pid, sizeof(pid));
|
|
return pid;
|
|
}
|
|
|
|
|
|
void GDevice::write_devname(std::string name)
|
|
{
|
|
if (name.size() > 64)
|
|
return;
|
|
|
|
write_flash(DEVNAME_ADDR, (void*)name.c_str(), name.size());
|
|
}
|
|
|
|
std::string GDevice::read_devname()
|
|
{
|
|
char devname[65] = {0};
|
|
read_flash(DEVNAME_ADDR, devname, sizeof(devname) - 1);
|
|
return devname;
|
|
}
|
|
|
|
bool GDevice::write_flash(unsigned int addr, void* data, int size)
|
|
{
|
|
unsigned int writeAddr = addr;
|
|
int writed = 0;
|
|
int writing = 0;
|
|
while (writed < size) {
|
|
writing = min(crtlBufferSize, size - writed);
|
|
writeAddr = addr + writed;
|
|
{
|
|
std::lock_guard<std::mutex> lck(m_mtxCtrl);
|
|
m_usb->control_msg(to_device, flash_access, ((Reg2Short*)&writeAddr)->short2, ((Reg2Short*)&writeAddr)->short1, writing, (unsigned char*)data + writed);
|
|
}
|
|
writed += writing;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool GDevice::read_flash(unsigned int addr, void* data, int size)
|
|
{
|
|
unsigned int readAddr = addr;
|
|
int readed = 0;
|
|
int reading = 0;
|
|
while (readed < size) {
|
|
reading = min(crtlBufferSize, size - readed);
|
|
readAddr = addr + readed;
|
|
{
|
|
std::lock_guard<std::mutex> lck(m_mtxCtrl);
|
|
m_usb->control_msg(from_device, flash_access, ((Reg2Short*)&readAddr)->short2, ((Reg2Short*)&readAddr)->short1, reading, (unsigned char*)data + readed);
|
|
}
|
|
readed += reading;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
const int int_buffer_size = 1024;
|
|
int index_count = 0;
|
|
#include <windows.h>
|
|
static void write_log(std::string fullname, std::string log)
|
|
{
|
|
std::string savepath;
|
|
savepath = fullname;
|
|
std::ofstream ofs(savepath, std::ios::app);
|
|
|
|
SYSTEMTIME sys;
|
|
GetLocalTime(&sys);
|
|
ofs << sys.wYear << "/" << sys.wMonth << "/" << sys.wDay << " " << sys.wHour << ":" << sys.wMinute << ":" << sys.wSecond << ":" << sys.wMilliseconds << " " << log << std::endl;
|
|
}
|
|
int image_index_c = 0;
|
|
void GDevice::recv_main()
|
|
{
|
|
const double timeout_ratio = (1000.0 / (15.0 * 1024 * 1024)); //!< s / Mbyte
|
|
int image_index = 0;
|
|
int buffer_size = 0;
|
|
int b_buffer_size = 0;
|
|
int f_buffer_size = 0;
|
|
unsigned char* bbuf = 0;
|
|
unsigned char* fbuf = 0;
|
|
unsigned char* buf;
|
|
int buffer_reading = 0;
|
|
int buffer_readed = 0;
|
|
const int read_timeout = 5000;
|
|
std::vector<unsigned char> image_data;
|
|
StopWatch sw;
|
|
while (m_bScan) {
|
|
image_index = image_indexs.Take();
|
|
if (!image_indexs.IsShutDown() && image_index >= 0)
|
|
{
|
|
buffer_reading = 0;
|
|
buffer_readed = 0;
|
|
buffer_size = frame_size(image_index);
|
|
image_data.resize(buffer_size * 2 + int_buffer_size);
|
|
buf = image_data.data() + int_buffer_size;
|
|
|
|
sw.reset();
|
|
while (sw.elapsed_ms() < read_timeout) {
|
|
while (DataOn() && sw.elapsed_ms() < read_timeout);
|
|
read_frame(image_index, buffer_readed);
|
|
buffer_reading = max(0, buffer_size - buffer_readed);
|
|
buffer_reading = read_data(buf + buffer_readed, buffer_reading, (int)(buffer_reading * timeout_ratio));
|
|
if (buffer_reading > 0)
|
|
buffer_readed += buffer_reading;
|
|
|
|
if (buffer_readed >= buffer_size) {
|
|
write_log("d:\\1.txt", std::to_string(image_index_c) + " time1 = " + std::to_string(sw.elapsed_ms()));
|
|
break;
|
|
}
|
|
}
|
|
|
|
image_index_c++;
|
|
if (buffer_readed != buffer_size)
|
|
{
|
|
write_log("d:\\1.txt", std::to_string(image_index_c) + " error readed:" + std::to_string(buffer_readed) + " per read:" + std::to_string(buffer_size) + " time = " + std::to_string(sw.elapsed_ms()));
|
|
}
|
|
else {
|
|
write_log("d:\\1.txt", std::to_string(image_index_c) + " get" + " time = " + std::to_string(sw.elapsed_ms()));
|
|
}
|
|
|
|
b_buffer_size = 0;
|
|
f_buffer_size = 0;
|
|
bbuf = buf - int_buffer_size;
|
|
fbuf = buf + buffer_size;
|
|
for (int i = 0; i < (buffer_size / int_buffer_size); i++)
|
|
{
|
|
if (buf[(i + 1) * int_buffer_size - 1] == 0)
|
|
{
|
|
memcpy(bbuf + b_buffer_size, buf + i * int_buffer_size, int_buffer_size - 1);
|
|
b_buffer_size += (int_buffer_size - 1);
|
|
}
|
|
else if (buf[(i + 1) * int_buffer_size - 1] == 255)
|
|
{
|
|
memcpy(fbuf + f_buffer_size, buf + i * int_buffer_size, int_buffer_size - 1);
|
|
f_buffer_size += (int_buffer_size - 1);
|
|
}
|
|
}
|
|
|
|
if (image_call)
|
|
{
|
|
if ((bbuf != NULL && b_buffer_size > 0)&&(fbuf != NULL && f_buffer_size > 0))
|
|
{
|
|
image_call(bbuf, b_buffer_size, fbuf, f_buffer_size, m_imagecall_userdata);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GDevice::Int_main()
|
|
{
|
|
unsigned int int_buffer[4];
|
|
int size = 0;
|
|
while (m_bListen) {
|
|
size = m_usb->read_int(int_buffer, sizeof(int_buffer));
|
|
if (size >= 16)
|
|
{
|
|
if (int_buffer[2] != 0)
|
|
{
|
|
image_indexs.Put(int_buffer[1]);
|
|
}
|
|
MotorStatus ms;
|
|
ms.value =int_buffer[0];
|
|
if (event_call)
|
|
{
|
|
//0x3fe ==>b 1111 1111 10
|
|
if (ms.value & 0x3fe) {
|
|
event_call(ms.value, m_eventcall_userdata);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GDevice::init_cam()
|
|
{
|
|
}
|
|
|
|
int GDevice::read_data(void* data, int length, int timeout)
|
|
{
|
|
int readed = 0;
|
|
int reading = 0;
|
|
StopWatch sw;
|
|
while (readed < length && sw.elapsed_ms() < timeout) {
|
|
reading = max(0, min(length - readed, buffer_size));
|
|
reading = m_usb->read_bulk((unsigned char*)data + readed, reading);
|
|
if (reading > 0) {
|
|
readed += reading;
|
|
}
|
|
}
|
|
return readed;
|
|
}
|
|
|
|
void GDevice::read_frame(int index, int offset)
|
|
{
|
|
write_reg(3, index, offset);
|
|
}
|
|
|
|
int GDevice::frame_size(int index)
|
|
{
|
|
return read_reg(3, index);
|
|
}
|
|
|
|
int GDevice::read_reg(int type, int addr)
|
|
{
|
|
int value;
|
|
std::lock_guard<std::mutex> lck(m_mtxCtrl);
|
|
m_usb->control_msg(from_device, regs_access, type, addr, sizeof(value), &value);
|
|
return value;
|
|
}
|
|
|
|
|
|
void GDevice::write_reg(int type, int addr, int value)
|
|
{
|
|
std::lock_guard<std::mutex> lck(m_mtxCtrl);
|
|
m_usb->control_msg(to_device, regs_access, type, addr, sizeof(value), &value);
|
|
}
|
|
|
|
void GDevice::set_option(Cam_Options option, unsigned int value)
|
|
{
|
|
unsigned int val = 0;
|
|
switch (option)
|
|
{
|
|
case scanner_config:
|
|
write_reg(USERDEFINE, ModeParam, value);
|
|
break;
|
|
case scanner_scan_skrew:
|
|
val = read_reg(MOTOR_BOARD, 0x00);
|
|
((MotorSetting*)& val)->skew_enable = value;
|
|
write_reg(MOTOR_BOARD, 0x00, val);
|
|
break;
|
|
case scanner_stample_enable:
|
|
val = read_reg(MOTOR_BOARD, 0x00);
|
|
((MotorSetting*)& val)->staple_enable = value;
|
|
write_reg(MOTOR_BOARD, 0x00, val);
|
|
break;
|
|
case scanner_doublePape_enable:
|
|
val = read_reg(MOTOR_BOARD, 0x00);
|
|
((MotorSetting*)& val)->double_paper = value;
|
|
write_reg(MOTOR_BOARD, 0x00, val);
|
|
break;
|
|
case scanner_stop_motor:
|
|
val = read_reg(MOTOR_BOARD, 0x00);
|
|
((MotorSetting*)& val)->scan_enable = value;
|
|
write_reg(MOTOR_BOARD, 0x00, val);
|
|
break;
|
|
case scanner_error_clean:
|
|
val = read_reg(MOTOR_BOARD, 0x00);
|
|
((MotorSetting*)& val)->error_clean = value;
|
|
write_reg(MOTOR_BOARD, 0x00, val);
|
|
break;
|
|
case scanner_Init_Status:
|
|
val = read_reg(MOTOR_BOARD, 0x00);
|
|
((MotorSetting*)& val)->status_init = value;
|
|
write_reg(MOTOR_BOARD, 0x00, val);
|
|
break;
|
|
case scanner_IIC_Config:
|
|
val = read_reg(MOTOR_BOARD, 0x00);
|
|
((MotorSetting*)& val)->iic_config = value;
|
|
write_reg(MOTOR_BOARD, 0x00, val);
|
|
break;
|
|
case scanner_Speed_Config:
|
|
val = read_reg(MOTOR_BOARD, 0x00);
|
|
((MotorSetting*)& val)->speed_set_enable = value;
|
|
write_reg(MOTOR_BOARD, 0x00, val);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
int GDevice::get_option(Cam_Options option)
|
|
{
|
|
int value = 0;
|
|
switch (option)
|
|
{
|
|
case scanner_cover_status:
|
|
value = read_reg(1, 0x01);
|
|
value = ((MotorStatus*)& value)->open_machine;
|
|
break;
|
|
case scanner_pick_paper_stauts:
|
|
value = read_reg(1, 0x01);
|
|
value = ((MotorStatus*)& value)->pick_failed;
|
|
break;
|
|
case scanner_jam_stauts:
|
|
value = read_reg(1, 0x01);
|
|
value = ((MotorStatus*)& value)->stop_jam;
|
|
break;
|
|
case scanner_paper_count:
|
|
value = read_reg(1, 0x02);
|
|
value = ((MotorMode*)& value)->scan_num;
|
|
break;
|
|
case scanner_double_paper:
|
|
value = read_reg(1, 0x01);
|
|
value= ((MotorStatus*)& value)->double_paper;
|
|
break;
|
|
case scanner_staple_state:
|
|
value = read_reg(1, 0x01);
|
|
value = ((MotorStatus*)& value)->staple;
|
|
break;
|
|
case scanner_skrew_state:
|
|
value = read_reg(1, 0x01);
|
|
value = ((MotorStatus*)& value)->papertilted;
|
|
break;
|
|
case scanner_paper_have:
|
|
value = read_reg(MOTOR_BOARD, 0x02);
|
|
value = ((Motor_Mode*)& value)->feeding_paper_ready;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
std::vector<Cam_Options> GDevice::support_options()
|
|
{
|
|
std::set<Cam_Options> options;
|
|
options.insert(Cam_Options::scanner_exposure_blue);
|
|
options.insert(Cam_Options::scanner_exposure_gray);
|
|
options.insert(Cam_Options::scanner_exposure_red);
|
|
|
|
return std::vector<Cam_Options>(options.begin(), options.end());
|
|
}
|
|
|
|
void GDevice::pick_paper(void)
|
|
{
|
|
MotorSetting ms;
|
|
ms.value = read_reg(MOTOR_BOARD, 0x00);
|
|
ms.pick_paper = 0;
|
|
write_reg(MOTOR_BOARD, 0x00, ms.value);
|
|
ms.pick_paper = 1;
|
|
write_reg(MOTOR_BOARD, 0x00, ms.value);
|
|
}
|
|
|
|
void GDevice::trigger_scan(void)
|
|
{
|
|
ScanTriger st;
|
|
st.value = 0;
|
|
write_reg(MAIN_BOARD, 0x02, st.value);
|
|
st.triger = 1;
|
|
write_reg(MAIN_BOARD, 0x02, st.value);
|
|
}
|
|
|
|
bool GDevice::DataOn()
|
|
{
|
|
return read_reg(USERDEFINE, IMAGEREGS);
|
|
}
|