2023-12-19 07:27:16 +00:00
|
|
|
#include "hardware.h"
|
|
|
|
|
|
|
|
#include "./cis/FpgaComm.h"
|
2023-12-20 07:23:24 +00:00
|
|
|
#include "./cis/gvideoisp1.h"
|
|
|
|
#include "./motor/motorboard.h"
|
2023-12-19 07:27:16 +00:00
|
|
|
#include <huagao/hgscanner_error.h>
|
|
|
|
#include <sane/sane_ex.h>
|
2024-01-05 09:36:50 +00:00
|
|
|
#include <json/gb_json.h>
|
2023-12-19 07:27:16 +00:00
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// scanner_hw
|
|
|
|
static std::string device_opt_json[] = {
|
2024-01-02 07:18:42 +00:00
|
|
|
"{\"mode\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u989c\\u8272\\u6a21\\u5f0f\",\"desc\":\"\\u9009\\u62e9\\u955c\\u5934\\u8272\\u5f69\\u5de5\\u4f5c\\u6a21\\u5f0f\",\"type\":\"string\",\"fix-id\":34819,\"ui-pos\":10,\"auth\":0,\"size\":12,\"cur\":\"\\u5f69\\u8272\",\"default\":\"\\u5f69\\u8272\",\"range\":[\"\\u5f69\\u8272\",\"\\u7070\\u5ea6\"]},\"resolution\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u5206\\u8fa8\\u7387\",\"desc\":\"\\u8bbe\\u7f6e\\u955c\\u5934\\u5de5\\u4f5c\\u7684\\u5206\\u8fa8\\u7387\",\"type\":\"int\",\"fix-id\":34840,\"ui-pos\":11,\"auth\":0,\"size\":4,\"cur\":300,\"default\":300,\"range\":[200,300]},\"is-wait-scan\":{\"cat\":\"base\",\"group\":\"feeder\",\"title\":\"\\u5f85\\u7eb8\\u626b\\u63cf\",\"desc\":\"\\u542f\\u7528\\u540e\\uff0c\\u6587\\u7a3f\\u653e\\u5165\\u626b\\u63cf\\u4eea\\u65f6\\u5c06\\u81ea\\u52a8\\u542f\\u52a8\\u626b\\u63cf\",\"type\":\"bool\",\"fix-id\":34873,\"ui-pos\":12,\"auth\":0,\"size\":4,\"cur\":false,\"default\":false},\"wait-scan-exit\":{\"cat\":\"base\",\"group\":\"feeder\",\"title\":\"\\u5f85\\u7eb8\\u626b\\u63cf\\u9000\\u51fa\\u65f6\\u95f4\",\"desc\":\"\\u8bbe\\u7f6e\\u7ed3\\u675f\\u5f85\\u7eb8\\u626b\\u63cf\\u7684\\u65f6\\u95f4\",\"type\":\"string\",\"fix-id\":34920,\"ui-pos\":13,\"auth\":0,\"size\":16,\"cur\":\"60s\",\"default\":\"60s\",\"range\":[\"15s\",\"30s\",\"60s\",\"2min\",\"4min\",\"8min\"],\"depend\":\"is-wait-scan==true\"},\"scan-mode\":{\"cat\":\"base\",\"group\":\"feeder\",\"title\":\"\\u626b\\u63cf\\u5f20\\u6570\",\"desc\":\"\\u9009\\u62e9\\u6307\\u5b9a\\u6570\\u91cf\\u626b\\u63cf\\u6216\\u8fde\\u7eed\\u626b\\u63cf\",\"type\":\"string\",\"fix-id\":34862,\"ui-pos\":15,\"auth\":0,\"size\":24,\"cur\":\"\\u8fde\\u7eed\\u626b\\u63cf\",\"default\":\"\\u8fde\\u7eed\\u626b\\u63cf\",\"range\":[\"\\u8fde\\u7eed\\u626b\\u63cf\",\"\\u626b\\u63cf\\u6307\\u5b9a\\u5f20\\u6570\"],\"depend\":\"is-wait-scan==false\"},\"scan-count\":{\"cat\":\"base\",\"group\":\"feeder\",\"title\":\" \\u626b\\u63cf\\u6570\\u91cf\",\"desc\":\"\\u626b\\u63cf\\u6307\\u5b9a\\u6570\\u91cf\",\"type\":\"int\",\"fix-id\":34863,\"ui-pos\":16,\"auth\":0,\"size\":4,\"cur\":-1,\"default\":-1,\"depend\":\"scan-mode.enabled&&scan-mode==\\u626b\\u63cf\\u6307\\u5b9a\\u5f20\\u6570\"},\"is-auto-strength\":{\"cat\":\"base\",\"group\":\"feeder\",\"title\":\"\\u81ea\\u52a8\\u5206\\u7eb8\\u5f3a\\u5ea6\",\"desc\":\"\\u626b\\u63cf\\u4eea\\u81ea\\u52a8\\u4fee\\u6b63\\u5206\\u7eb8\\u529b\\u5ea6\",\"type\":\"bool\",\"fix-id\":34876,\"ui-pos\":27,\"auth\":0,\"size\":4,\"cur\":false,\"default\":false},\"feed-strength-value\":{\"cat\":\"base\",\"group\":\"feeder\",\"title\":\" \\u8fdb\\u7eb8\\u5931\\u8d25\\u7387\",\"desc\":\"\\u9ad8\\u4e8e\\u8be5\\u503c\\u65f6\\u626b\\u63cf\\u4eea\\u5c06\\u8c03\\u6574\\u5206\\u7eb8\\u529b\\u5ea6\",\"type\":\"float\",\"fix-id\":34877,\"ui-pos\":28,\"auth\":0,\"size\":8,\"cur\":0.000000,\"default\":0.000000,\"range\":{\"min\":0.100000,\"max\":0.900000,\"step\":0.080000},\"depend\":\"is-auto-strength==true\"},\"feed-strength\":{\"cat\":\"base\",\"group\":\"feeder\",\"title\":\"\\u5206\\u7eb8\\u5f3a\\u5ea6\",\"desc\":\"\\u8bbe\\u7f6e\\u626b\\u63cf\\u4eea\\u7684\\u5206\\u7eb8\\u529b\\u5ea6\",\"type\":\"string\",\"fix-id\":34874,\"ui-pos\":30,\"auth\":0,\"size\":12,\"cur\":\"\\u4e00\\u822c\",\"default\":\"\\u4e00\\u822c\",\"range\":[\"\\u5f31\",\"\\u4e00\\u822c\",\"\\u5f3a\"],\"depend\":\"is-auto-strength!=true\"},\"time-to-sleep\":{\"cat\":\"base\",\"group\":\"feeder\",\"title\":\"\\u4f11\\u7720\\u65f6\\u95f4\",\"desc\":\"\\u8bbe\\u7f6e\\u626b\\u63cf\\u4eea\\u7684\\u4f11\\u7720\\u65f6\\u95f4\",\"type\":\"string\",\"fix-id\":34875,\"ui-pos\":33,\"auth\":0,\"size\":16,\"cur\":\"\\u4e0d\\u4f11\\u7720\",\"default\":\"\\u4e0d\\u4f11\\u7720\",\"range\":[\"\\u4e0d\\u4f11\\u7720\",\"\\u4e94\\u5206\\u949f\",\"\\u5341\\u5206\\u949f\",\"\\u534a\\u5c0f\\u65f6\",\"\\u4e00\\u5c0f\\u65f6\",\"\\u4e24\\u5c0f\\u65f6\",\"\\u56db\\u5c0f\\u65f6\"]},\"baud\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u6ce2\\u7279\\u7387\",\"desc\":\"CIS\\u63a7\\u5236\\u901a\\u4fe1\\u901f\\u7387\",\"type
|
2024-01-09 06:26:46 +00:00
|
|
|
"\",\"title\":\"\\u6b6a\\u659c\\u5bb9\\u5fcd\\u5ea6\",\"desc\":\"\\u503c\\u8d8a\\u5c0f\\uff0c\\u80fd\\u5bb9\\u5fcd\\u5f97\\u9001\\u5165\\u6587\\u7a3f\\u6b6a\\u659c\\u89d2\\u5ea6\\u8d8a\\u5c0f\",\"type\":\"int\",\"fix-id\":34869,\"ui-pos\":23,\"auth\":0,\"size\":4,\"cur\":3,\"default\":3,\"range\":{\"min\":1,\"max\":7,\"step\":1},\"depend\":\"is-check-askew==true\"},\"cis-len\":{\"cat\":\"base\",\"group\":\"\\u5173\\u4e8e\",\"title\":\"\\u955c\\u5934\\u957f\",\"desc\":\"\\u56fe\\u50cf\\u91c7\\u96c6\\u955c\\u5934\\u7684\\u957f\\u5ea6\\uff0c\\u5355\\u4f4d\\u4e3a\\u6beb\\u7c73\\uff08mm\\uff09\",\"type\":\"int\",\"ui-pos\":30,\"auth\":0,\"unit\":\"mm\",\"readonly\":true,\"size\":4,\"auto\":false,\"cur\":1632,\"default\":1632},\"motor-ver\":{\"cat\":\"none\",\"group\":\"\\u5173\\u4e8e\",\"title\":\"\\u7535\\u673a\\u9a71\\u52a8\\u7248\\u672c\",\"desc\":\"\\u7535\\u673a\\u677f\\u9a71\\u52a8\\u7a0b\\u5e8f\\u7248\\u672c\\u53f7\",\"type\":\"string\",\"fix-id\":34909,\"ui-pos\":16,\"auth\":0,\"readonly\":true,\"size\":24,\"auto\":false,\"cur\":\"\",\"default\":\"\"},\"fpga-ver\":{\"cat\":\"none\",\"group\":\"\\u5173\\u4e8e\",\"title\":\"CIS\\u63a7\\u5236\\u5668\\u7248\\u672c\",\"desc\":\"\\u955c\\u5934\\u53c2\\u6570\\u63a7\\u5236\\u9a71\\u52a8\\u7a0b\\u5e8f\\u7248\\u672c\\u53f7\",\"type\":\"string\",\"ui-pos\":17,\"auth\":0,\"readonly\":true,\"size\":24,\"auto\":false,\"cur\":\"\",\"default\":\"\"}}"
|
2023-12-19 07:27:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// scanner_hw
|
2024-01-09 07:32:03 +00:00
|
|
|
scanner_hw::scanner_hw() : mb_events_("motorboard-event")
|
2023-12-19 07:27:16 +00:00
|
|
|
{
|
|
|
|
set_where("hardware");
|
2024-01-09 07:32:03 +00:00
|
|
|
mb_events_.enable_wait_log(false);
|
|
|
|
|
2023-12-19 07:27:16 +00:00
|
|
|
init();
|
|
|
|
}
|
|
|
|
scanner_hw::~scanner_hw()
|
|
|
|
{
|
|
|
|
close();
|
|
|
|
}
|
|
|
|
|
|
|
|
void scanner_hw::init(void)
|
|
|
|
{
|
|
|
|
std::string text("");
|
|
|
|
|
|
|
|
for(auto& v: device_opt_json)
|
|
|
|
text += v;
|
2024-01-05 09:36:50 +00:00
|
|
|
init_version(text);
|
2023-12-19 07:27:16 +00:00
|
|
|
set_opt_json_text(&text[0]);
|
|
|
|
|
2024-01-02 07:18:42 +00:00
|
|
|
#define OPT_HANDLER(name) \
|
|
|
|
auto name = [this](void* value) -> void
|
|
|
|
|
2023-12-19 09:11:41 +00:00
|
|
|
auto a = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
auto_scan_ = *(bool*)value;
|
|
|
|
};
|
|
|
|
auto e = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
if(strcmp((char*)value, "15s") == 0)
|
|
|
|
time_to_exit_auto_scan_ = 15;
|
|
|
|
else if(strcmp((char*)value, "30s") == 0)
|
|
|
|
time_to_exit_auto_scan_ = 30;
|
|
|
|
else if(strcmp((char*)value, "2min") == 0)
|
|
|
|
time_to_exit_auto_scan_ = 120;
|
|
|
|
else if(strcmp((char*)value, "4min") == 0)
|
|
|
|
time_to_exit_auto_scan_ = 240;
|
|
|
|
else if(strcmp((char*)value, "8min") == 0)
|
|
|
|
time_to_exit_auto_scan_ = 480;
|
|
|
|
else
|
|
|
|
time_to_exit_auto_scan_ = 60;
|
|
|
|
};
|
|
|
|
|
2023-12-19 07:27:16 +00:00
|
|
|
auto m = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
if(strcmp((char*)value, "\347\201\260\345\272\246") == 0)
|
|
|
|
mode_ = (char*)value;
|
|
|
|
else
|
|
|
|
mode_ = "\345\275\251\350\211\262";
|
|
|
|
};
|
|
|
|
auto r = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
if(*(int*)value <= 200)
|
|
|
|
dpi_ = 200;
|
|
|
|
else
|
|
|
|
dpi_ = 300;
|
|
|
|
};
|
|
|
|
auto b = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
baud_ = *(int*)value;
|
|
|
|
};
|
|
|
|
auto d = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
delay_ = *(int*)value;
|
|
|
|
};
|
|
|
|
auto f = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
frame_h_ = *(int*)value;
|
|
|
|
};
|
|
|
|
auto s = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
sample_ = *(int*)value;
|
|
|
|
};
|
|
|
|
|
|
|
|
auto efb = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
exposure_[SIDE_FRONT][COLOR_IND_BLUE] = *(int*)value;
|
|
|
|
};
|
|
|
|
auto efg = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
exposure_[SIDE_FRONT][COLOR_IND_GREEN] = *(int*)value;
|
|
|
|
};
|
|
|
|
auto efr = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
exposure_[SIDE_FRONT][COLOR_IND_RED] = *(int*)value;
|
|
|
|
};
|
|
|
|
auto ebb = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
exposure_[SIDE_BACK][COLOR_IND_BLUE] = *(int*)value;
|
|
|
|
};
|
|
|
|
auto ebg = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
exposure_[SIDE_BACK][COLOR_IND_GREEN] = *(int*)value;
|
|
|
|
};
|
|
|
|
auto ebr = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
exposure_[SIDE_BACK][COLOR_IND_RED] = *(int*)value;
|
|
|
|
};
|
|
|
|
|
|
|
|
auto gf = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
gain_[SIDE_FRONT] = *(int*)value;
|
|
|
|
};
|
|
|
|
auto gb = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
gain_[SIDE_BACK] = *(int*)value;
|
|
|
|
};
|
|
|
|
|
|
|
|
auto of = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
off_[SIDE_FRONT] = *(int*)value;
|
|
|
|
};
|
|
|
|
auto ob = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
off_[SIDE_BACK] = *(int*)value;
|
|
|
|
};
|
|
|
|
|
2023-12-19 09:11:41 +00:00
|
|
|
CLEAN_ARRAY(exposure_);
|
|
|
|
CLEAN_ARRAY(gain_);
|
|
|
|
CLEAN_ARRAY(off_);
|
|
|
|
|
|
|
|
opt_handler_[SANE_FULL_NAME(WAIT_TO_SCAN)] = a;
|
|
|
|
opt_handler_[SANE_FULL_NAME(WAIT_SCAN_EXIT)] = e;
|
|
|
|
|
2023-12-19 07:27:16 +00:00
|
|
|
opt_handler_[SANE_FULL_NAME(COLOR_MODE)] = m;
|
|
|
|
opt_handler_[SANE_FULL_NAME(RESOLUTION)] = r;
|
|
|
|
opt_handler_[SANE_FULL_NAME(CIS_BAUD)] = b;
|
|
|
|
opt_handler_[SANE_FULL_NAME(CIS_DELAY)] = d;
|
|
|
|
opt_handler_[SANE_FULL_NAME(CIS_FRAME_H)] = f;
|
|
|
|
opt_handler_[SANE_FULL_NAME(CIS_SAMPLE)] = s;
|
|
|
|
|
|
|
|
opt_handler_[SANE_FULL_NAME(CIS_EXPO_FB)] = efb;
|
|
|
|
opt_handler_[SANE_FULL_NAME(CIS_EXPO_FG)] = efg;
|
|
|
|
opt_handler_[SANE_FULL_NAME(CIS_EXPO_FR)] = efr;
|
|
|
|
opt_handler_[SANE_FULL_NAME(CIS_EXPO_BB)] = ebb;
|
|
|
|
opt_handler_[SANE_FULL_NAME(CIS_EXPO_BG)] = ebg;
|
|
|
|
opt_handler_[SANE_FULL_NAME(CIS_EXPO_BR)] = ebr;
|
|
|
|
|
|
|
|
opt_handler_[SANE_FULL_NAME(CIS_GAIN_FRONT)] = gf;
|
|
|
|
opt_handler_[SANE_FULL_NAME(CIS_GAIN_BACK)] = gb;
|
2023-12-19 09:11:41 +00:00
|
|
|
|
2023-12-19 07:27:16 +00:00
|
|
|
opt_handler_[SANE_FULL_NAME(CIS_OFFSET_FRONT)] = of;
|
|
|
|
opt_handler_[SANE_FULL_NAME(CIS_OFFSET_BACK)] = ob;
|
2023-12-20 08:44:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
auto staple = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
staple_chk_ = *(bool*)value;
|
|
|
|
};
|
|
|
|
auto screw = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
screw_chk_ = *(bool*)value;
|
|
|
|
};
|
2023-12-29 02:53:04 +00:00
|
|
|
auto screwl = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
screw_chk_level_ = *(int*)value;
|
|
|
|
};
|
2023-12-20 08:44:39 +00:00
|
|
|
auto dbchk = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
double_chk_ = strcmp((char*)value, "\347\246\201\347\224\250") != 0;
|
|
|
|
};
|
|
|
|
auto motsp = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
int speed = *(int*)value;
|
2023-12-29 08:58:41 +00:00
|
|
|
if(family_ == "G200")
|
2023-12-29 02:53:04 +00:00
|
|
|
{
|
2023-12-29 08:58:41 +00:00
|
|
|
speed -= 100; // 100 110 120 130
|
2023-12-29 02:53:04 +00:00
|
|
|
}
|
2023-12-20 08:44:39 +00:00
|
|
|
else
|
2023-12-29 02:53:04 +00:00
|
|
|
{
|
2023-12-29 08:58:41 +00:00
|
|
|
speed -= 70; // 70 80 90 100
|
2023-12-29 02:53:04 +00:00
|
|
|
}
|
|
|
|
switch(speed)
|
|
|
|
{
|
|
|
|
case 10:
|
|
|
|
motor_speed_ = SPEED_PPM_BASE_10;
|
|
|
|
break;
|
|
|
|
case 20:
|
|
|
|
motor_speed_ = SPEED_PPM_BASE_20;
|
|
|
|
break;
|
|
|
|
case 30:
|
|
|
|
motor_speed_ = SPEED_PPM_BASE_30;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
motor_speed_ = SPEED_PPM_BASE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
auto fm = [this](void* value) -> void
|
|
|
|
{
|
|
|
|
family_ = (char*)value;
|
|
|
|
utils::to_log(LOG_LEVEL_DEBUG, "Device family set as: %s\n", family_.c_str());
|
2023-12-20 08:44:39 +00:00
|
|
|
};
|
2024-01-02 07:18:42 +00:00
|
|
|
OPT_HANDLER(cntm)
|
|
|
|
{
|
|
|
|
|
|
|
|
};
|
|
|
|
OPT_HANDLER(cnt)
|
|
|
|
{
|
|
|
|
scan_count_ = *(int*)value;
|
|
|
|
};
|
|
|
|
OPT_HANDLER(afs)
|
|
|
|
{
|
|
|
|
|
|
|
|
};
|
|
|
|
OPT_HANDLER(ff)
|
|
|
|
{
|
|
|
|
|
|
|
|
};
|
|
|
|
OPT_HANDLER(fs)
|
|
|
|
{
|
|
|
|
|
|
|
|
};
|
|
|
|
OPT_HANDLER(slp)
|
|
|
|
{
|
|
|
|
|
|
|
|
};
|
2023-12-20 08:44:39 +00:00
|
|
|
|
|
|
|
opt_handler_[SANE_FULL_NAME(IS_CHECK_STAPLE)] = staple;
|
|
|
|
opt_handler_[SANE_FULL_NAME(IS_CHECK_ASKEW)] = screw;
|
2023-12-29 02:53:04 +00:00
|
|
|
opt_handler_[SANE_FULL_NAME(ASKEW_RANGE)] = screwl;
|
2023-12-20 08:44:39 +00:00
|
|
|
opt_handler_[SANE_FULL_NAME(DOUBLE_CHECK)] = dbchk;
|
|
|
|
opt_handler_[SANE_FULL_NAME(MOTOR_SPEED)] = motsp;
|
2023-12-29 02:53:04 +00:00
|
|
|
opt_handler_[SANE_FULL_NAME(DEVICE_MODEL)] = fm;
|
2024-01-02 07:18:42 +00:00
|
|
|
opt_handler_[SANE_FULL_NAME(SCAN_MODE)] = cntm;
|
|
|
|
opt_handler_[SANE_FULL_NAME(SCAN_COUNT)] = cnt;
|
|
|
|
opt_handler_[SANE_FULL_NAME(IS_AUTO_FEED_STRENGTH)] = afs;
|
|
|
|
opt_handler_[SANE_FULL_NAME(FEED_STRENGTH_VALUE)] = ff;
|
|
|
|
opt_handler_[SANE_FULL_NAME(FEED_STRENGTH)] = fs;
|
|
|
|
opt_handler_[SANE_FULL_NAME(TIME_TO_SLEEP)] = slp;
|
|
|
|
}
|
2024-01-05 09:36:50 +00:00
|
|
|
void scanner_hw::init_version(std::string& text)
|
|
|
|
{
|
|
|
|
gb_json *jsn = new gb_json();
|
|
|
|
|
|
|
|
if(jsn->attach_text(&text[0]))
|
|
|
|
{
|
|
|
|
gb_json *child = nullptr;
|
|
|
|
jsn->get_value(SANE_FULL_NAME(MOTOR_VER), child);
|
|
|
|
if(child)
|
|
|
|
{
|
|
|
|
unsigned int val = 0;
|
|
|
|
char buf[20] = {0};
|
|
|
|
|
2024-01-09 06:26:46 +00:00
|
|
|
motor_.reset(new MotorBoard(nullptr));
|
|
|
|
motor_->read(MB_PORT_VERSION, val);
|
2024-01-05 09:36:50 +00:00
|
|
|
motor_.reset();
|
|
|
|
|
|
|
|
sprintf(buf, "%u", val);
|
|
|
|
child->set_value("cur", buf);
|
|
|
|
child->set_value("default", buf);
|
|
|
|
child->release();
|
|
|
|
}
|
|
|
|
|
|
|
|
jsn->get_value(SANE_FULL_NAME(FPGA_VER), child);
|
|
|
|
if(child)
|
|
|
|
{
|
|
|
|
unsigned int val = 0;
|
|
|
|
char buf[20] = {0};
|
|
|
|
|
|
|
|
img_controller_.reset(new FpgaComm(baud_, true));
|
|
|
|
img_controller_->read(MAX_REGS - 1, val);
|
|
|
|
img_controller_.reset();
|
|
|
|
|
|
|
|
sprintf(buf, "0x%08x", val);
|
|
|
|
child->set_value("cur", buf);
|
|
|
|
child->set_value("default", buf);
|
|
|
|
child->release();
|
|
|
|
}
|
2024-01-09 06:26:46 +00:00
|
|
|
|
|
|
|
jsn->get_value(SANE_FULL_NAME(CIS_LENGTH), child);
|
|
|
|
if(child)
|
|
|
|
{
|
|
|
|
child->get_value("default", cis_length_);
|
|
|
|
child->release();
|
|
|
|
}
|
|
|
|
|
2024-01-05 09:36:50 +00:00
|
|
|
text = jsn->to_string();
|
|
|
|
}
|
|
|
|
jsn->release();
|
|
|
|
}
|
2024-01-02 07:18:42 +00:00
|
|
|
void scanner_hw::thread_image_capture(void)
|
|
|
|
{
|
2024-01-03 09:39:16 +00:00
|
|
|
PACKIMAGE img;
|
|
|
|
safe_fifo<int> avail_mem("v4l2-mem");
|
2024-01-09 06:26:46 +00:00
|
|
|
int used_v4l2_mem = 0, times = 0;
|
2024-01-09 07:32:03 +00:00
|
|
|
std::pair<int, int> mbev;
|
|
|
|
|
2024-01-03 09:39:16 +00:00
|
|
|
auto put_v4l2_mem = [&](BEFORE_DESTROY_PARAM) -> BEFORE_DESTROY_RET
|
|
|
|
{
|
|
|
|
int ind = (int)(long)param;
|
|
|
|
|
|
|
|
mem->detach(nullptr);
|
|
|
|
avail_mem.save(ind);
|
|
|
|
};
|
2024-01-02 07:18:42 +00:00
|
|
|
|
2024-01-03 09:39:16 +00:00
|
|
|
utils::to_log(LOG_LEVEL_DEBUG, "scanning thread working ...\n");
|
2024-01-02 07:18:42 +00:00
|
|
|
memset(&img, 0, sizeof(img));
|
2024-01-09 06:26:46 +00:00
|
|
|
motor_->clear_error();
|
|
|
|
camera_->start();
|
2024-01-09 07:32:03 +00:00
|
|
|
img_controller_->capture();
|
2024-01-05 09:36:50 +00:00
|
|
|
motor_->start();
|
2024-01-09 07:32:03 +00:00
|
|
|
mb_events_.take(mbev, true);
|
|
|
|
while(scanning_ && mbev.first == MOTOR_BORD_EVENT_LIFTER_READY) // auto scan cycle ...
|
2024-01-02 07:18:42 +00:00
|
|
|
{
|
2024-01-05 09:36:50 +00:00
|
|
|
motor_->pick_paper();
|
2024-01-09 06:26:46 +00:00
|
|
|
|
2024-01-03 09:39:16 +00:00
|
|
|
// scanning ONE turn ...
|
2024-01-09 06:26:46 +00:00
|
|
|
while(scanning_ && motor_->wait_paper_out(3000))
|
2024-01-02 07:18:42 +00:00
|
|
|
{
|
2024-01-05 09:36:50 +00:00
|
|
|
size_t size = 0;
|
|
|
|
int ind = -1;
|
2024-01-09 07:32:03 +00:00
|
|
|
void* frame = camera_->read_frame(10 * 1000, size, ind);
|
|
|
|
dyn_mem_shared_ptr mem = nullptr;
|
2024-01-02 07:18:42 +00:00
|
|
|
|
2024-01-09 07:32:03 +00:00
|
|
|
if(!frame)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
mem = new dyn_mem_shared(frame, size, put_v4l2_mem, (void*)ind);
|
2024-01-03 09:39:16 +00:00
|
|
|
used_v4l2_mem++;
|
2024-01-02 07:18:42 +00:00
|
|
|
img.pos.paper_ind++;
|
|
|
|
img.pos.status = IMG_STATUS_OK;
|
|
|
|
img_handler_(mem, true, &img);
|
|
|
|
|
|
|
|
if(img.pos.paper_ind == scan_count_ || is_scan_fatal())
|
|
|
|
break;
|
|
|
|
|
2024-01-03 09:39:16 +00:00
|
|
|
// retrieve V4L2 memory ...
|
|
|
|
retrieve_v4l2_mem(&avail_mem, &used_v4l2_mem);
|
|
|
|
if(used_v4l2_mem >= camera_->get_mem_count())
|
|
|
|
{
|
|
|
|
stop_scan();
|
|
|
|
utils::to_log(LOG_LEVEL_FATAL, "Scanning stopped for that V4L2 is out of memory!\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2024-01-02 07:18:42 +00:00
|
|
|
motor_->pick_paper();
|
|
|
|
}
|
|
|
|
|
2024-01-03 09:39:16 +00:00
|
|
|
// retrieve v4l2-mem ...
|
2024-01-09 06:26:46 +00:00
|
|
|
int ind = -1;
|
2024-01-03 09:39:16 +00:00
|
|
|
while(avail_mem.take(ind, false))
|
|
|
|
{
|
|
|
|
used_v4l2_mem--;
|
|
|
|
camera_->add_v4l2_memory(ind);
|
|
|
|
}
|
|
|
|
|
2024-01-09 06:26:46 +00:00
|
|
|
if(!auto_scan_ || !scanning_)
|
2024-01-03 09:39:16 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
// wait paper ...
|
|
|
|
}
|
|
|
|
|
2024-01-09 06:26:46 +00:00
|
|
|
stop_scan();
|
2024-01-03 09:39:16 +00:00
|
|
|
while(used_v4l2_mem)
|
|
|
|
{
|
|
|
|
if(times++ == 0)
|
|
|
|
utils::to_log(LOG_LEVEL_DEBUG, "Wait to retrieve %d V4L2 memory(s) ...\n", used_v4l2_mem);
|
|
|
|
else if(times >= 1000)
|
|
|
|
{
|
|
|
|
utils::to_log(LOG_LEVEL_FATAL, "Wait %d times, but %d V4L2 memory(s) has not returned yet!\n", times, used_v4l2_mem);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
retrieve_v4l2_mem(&avail_mem, &used_v4l2_mem);
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
|
|
|
}
|
|
|
|
utils::to_log(LOG_LEVEL_DEBUG, "scanning thread exited.\n");
|
2024-01-05 09:36:50 +00:00
|
|
|
|
|
|
|
scanning_ = false;
|
2024-01-02 07:18:42 +00:00
|
|
|
}
|
|
|
|
bool scanner_hw::is_scan_fatal(void)
|
|
|
|
{
|
|
|
|
return false;
|
2023-12-19 07:27:16 +00:00
|
|
|
}
|
2024-01-03 09:39:16 +00:00
|
|
|
void scanner_hw::retrieve_v4l2_mem(safe_fifo<int>* mem, int* used)
|
|
|
|
{
|
|
|
|
int u = *used,
|
|
|
|
ind = 0;
|
|
|
|
|
|
|
|
while(u >= camera_->get_mem_count())
|
|
|
|
{
|
|
|
|
if(mem->size())
|
|
|
|
{
|
|
|
|
if(ind)
|
|
|
|
utils::to_log(LOG_LEVEL_WARNING, "V4L2 memory returned.\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(ind == 0)
|
|
|
|
utils::to_log(LOG_LEVEL_WARNING, "V4L2 is out of memory, wait image processor return ...\n");
|
|
|
|
|
|
|
|
if(ind++ > 1000) // 3 seconds ...
|
|
|
|
break;
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(3));
|
|
|
|
}
|
|
|
|
while(mem->take(ind, false))
|
|
|
|
{
|
|
|
|
u--;
|
|
|
|
camera_->add_v4l2_memory(ind);
|
|
|
|
}
|
|
|
|
*used = u;
|
|
|
|
}
|
2023-12-19 07:27:16 +00:00
|
|
|
|
|
|
|
// sane_opt_provider
|
|
|
|
char* scanner_hw::get_value(const char* name, void* value, size_t* size, int* err)
|
|
|
|
{
|
|
|
|
char *ret = nullptr;
|
|
|
|
|
2023-12-20 08:44:39 +00:00
|
|
|
if(err)
|
|
|
|
*err = SCANNER_ERR_OK;
|
|
|
|
|
|
|
|
if(strcmp(name, SANE_FULL_NAME(PAPER_ON)) == 0)
|
|
|
|
{
|
2023-12-25 02:08:37 +00:00
|
|
|
ret = (char*)malloc(sizeof(int));
|
|
|
|
*(int*)ret = 0;
|
2023-12-20 08:44:39 +00:00
|
|
|
*(bool*)ret = paper_on_;
|
|
|
|
if(size)
|
|
|
|
*size = sizeof(bool);
|
|
|
|
}
|
|
|
|
else if(err)
|
|
|
|
*err = SCANNER_ERR_DEVICE_NOT_FOUND;
|
|
|
|
|
2023-12-19 07:27:16 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
int scanner_hw::set_value(const char* name, void* val)
|
|
|
|
{
|
2024-01-02 07:18:42 +00:00
|
|
|
if(scanning_) // working, no set
|
2023-12-29 02:53:04 +00:00
|
|
|
{
|
|
|
|
return SCANNER_ERR_DEVICE_BUSY;
|
|
|
|
}
|
|
|
|
|
2023-12-19 07:27:16 +00:00
|
|
|
if(opt_handler_.count(name))
|
|
|
|
{
|
|
|
|
opt_handler_[name](val);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// operation ...
|
|
|
|
int scanner_hw::open(std::function<IMAGE_HANDLER_PROTO> image_handler)
|
|
|
|
{
|
2023-12-29 02:53:04 +00:00
|
|
|
this->close();
|
|
|
|
|
|
|
|
if(!image_handler)
|
|
|
|
return SCANNER_ERR_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
img_handler_ = image_handler;
|
2023-12-19 07:27:16 +00:00
|
|
|
img_controller_.reset(new FpgaComm(baud_));
|
2024-01-05 09:36:50 +00:00
|
|
|
if(!img_controller_->is_ok())
|
|
|
|
return DEV_ERR(HD_001);
|
2023-12-19 07:27:16 +00:00
|
|
|
|
|
|
|
img_controller_->setColorMode(mode_ == "\345\275\251\350\211\262" ? COLOR_MODE : GRAY_MODE);
|
|
|
|
img_controller_->setDpi(dpi_ == 200 ? DPI_200 : DPI_300);
|
|
|
|
img_controller_->setFrameHeight(frame_h_);
|
|
|
|
img_controller_->setDelayTime(delay_);
|
|
|
|
img_controller_->setSample(sample_);
|
|
|
|
|
|
|
|
void(FpgaComm::* exposure[])(int) = {&FpgaComm::setAExposureB, &FpgaComm::setAExposureG
|
|
|
|
, &FpgaComm::setAExposureR, &FpgaComm::setBExposureB, &FpgaComm::setBExposureG, &FpgaComm::setBExposureR};
|
|
|
|
for(int i = 0; i < SIDE_COUNT; ++i)
|
|
|
|
{
|
|
|
|
for(int j = 0; j < COLOR_IND_COUNT; ++j)
|
|
|
|
(img_controller_.get()->*exposure[i * SIDE_COUNT + j])(exposure_[i][j]);
|
|
|
|
}
|
|
|
|
|
2023-12-20 07:23:24 +00:00
|
|
|
for(int i = 0; i < FpgaComm::CIS_SECTOR_COUNT; ++i)
|
2023-12-19 07:27:16 +00:00
|
|
|
img_controller_->setAGain(i, gain_[SIDE_FRONT]);
|
2023-12-20 07:23:24 +00:00
|
|
|
for(int i = 0; i < FpgaComm::CIS_SECTOR_COUNT; ++i)
|
2023-12-19 07:27:16 +00:00
|
|
|
img_controller_->setBGain(i, gain_[SIDE_BACK]);
|
|
|
|
|
2023-12-20 07:23:24 +00:00
|
|
|
for(int i = 0; i < FpgaComm::CIS_SECTOR_COUNT; ++i)
|
2023-12-19 07:27:16 +00:00
|
|
|
img_controller_->setAOffset(i, off_[SIDE_FRONT]);
|
2023-12-20 07:23:24 +00:00
|
|
|
for(int i = 0; i < FpgaComm::CIS_SECTOR_COUNT; ++i)
|
2023-12-19 07:27:16 +00:00
|
|
|
img_controller_->setBOffset(i, off_[SIDE_BACK]);
|
|
|
|
|
2023-12-20 07:23:24 +00:00
|
|
|
camera_.reset(new GVideoISP1());
|
2024-01-09 06:26:46 +00:00
|
|
|
camera_->open(cis_length_, 1000);
|
2023-12-20 07:23:24 +00:00
|
|
|
|
2024-01-09 07:32:03 +00:00
|
|
|
auto cb = [this](int ev, unsigned int data) -> void
|
|
|
|
{
|
|
|
|
mb_events_.save(std::make_pair(ev, data), true);
|
|
|
|
};
|
|
|
|
mb_events_.clear();
|
|
|
|
motor_.reset(new MotorBoard(cb));
|
2023-12-20 08:44:39 +00:00
|
|
|
motor_->set_double_inpect(double_chk_);
|
|
|
|
motor_->set_staple_inpect(staple_chk_);
|
|
|
|
motor_->set_screw_inpect(screw_chk_);
|
2023-12-29 02:53:04 +00:00
|
|
|
motor_->set_screw_level(screw_chk_level_);
|
2023-12-20 08:44:39 +00:00
|
|
|
motor_->set_speed_mode(motor_speed_);
|
2024-01-09 06:26:46 +00:00
|
|
|
motor_->set_auto_paper(auto_scan_, true);
|
2023-12-20 07:23:24 +00:00
|
|
|
|
2023-12-29 02:53:04 +00:00
|
|
|
unsigned int val = 0;
|
2024-01-09 06:26:46 +00:00
|
|
|
if(motor_->read(MB_PORT_CONFIG, val))
|
2023-12-29 02:53:04 +00:00
|
|
|
utils::to_log(LOG_LEVEL_DEBUG, "MotorBoard config : %p\n", val);
|
|
|
|
else
|
|
|
|
utils::to_log(LOG_LEVEL_FATAL, "Get motor-board config failed.\n");
|
2024-01-09 06:26:46 +00:00
|
|
|
if(motor_->read(MB_PORT_STATUS, val))
|
2023-12-29 02:53:04 +00:00
|
|
|
utils::to_log(LOG_LEVEL_DEBUG, "MotorBoard status : %p\n", val);
|
|
|
|
else
|
|
|
|
utils::to_log(LOG_LEVEL_FATAL, "Get motor-board status failed.\n");
|
2024-01-09 06:26:46 +00:00
|
|
|
if(motor_->read(MB_PORT_MODE, val))
|
2023-12-29 02:53:04 +00:00
|
|
|
utils::to_log(LOG_LEVEL_DEBUG, "MotorBoard mode : %p\n", val);
|
|
|
|
else
|
|
|
|
utils::to_log(LOG_LEVEL_FATAL, "Get motor-board mode failed.\n");
|
2024-01-09 06:26:46 +00:00
|
|
|
if(motor_->read(MB_PORT_VERSION, val))
|
2023-12-29 02:53:04 +00:00
|
|
|
utils::to_log(LOG_LEVEL_DEBUG, "MotorBoard version: %p\n", val);
|
|
|
|
else
|
|
|
|
utils::to_log(LOG_LEVEL_FATAL, "Get motor-board version failed.\n");
|
2024-01-09 06:26:46 +00:00
|
|
|
if(motor_->read(MB_PORT_CONFIG_EX, val))
|
2023-12-29 02:53:04 +00:00
|
|
|
utils::to_log(LOG_LEVEL_DEBUG, "MotorBoard confige: %p\n", val);
|
|
|
|
else
|
|
|
|
utils::to_log(LOG_LEVEL_FATAL, "Get motor-board confige failed.\n");
|
|
|
|
|
|
|
|
return SCANNER_ERR_OK;
|
2023-12-19 07:27:16 +00:00
|
|
|
}
|
|
|
|
int scanner_hw::start_scan(void)
|
|
|
|
{
|
2024-01-03 09:39:16 +00:00
|
|
|
unsigned int val = 0;
|
|
|
|
|
2023-12-29 02:53:04 +00:00
|
|
|
if(!camera_.get() || !motor_.get() || !img_controller_.get())
|
2024-01-03 09:39:16 +00:00
|
|
|
return DEV_ERR(NOT_READY);
|
2023-12-26 01:33:05 +00:00
|
|
|
|
2023-12-29 02:53:04 +00:00
|
|
|
motor_->clear_error();
|
2024-01-09 06:26:46 +00:00
|
|
|
if(!motor_->read(MB_PORT_STATUS, val))
|
2024-01-03 09:39:16 +00:00
|
|
|
return DEV_ERR(GET_STATUS_FAILED);
|
|
|
|
|
|
|
|
utils::to_log(LOG_LEVEL_DEBUG, "start scan: status = 0x%08x.\n", val);
|
|
|
|
if (((SMBSTATUS*)&val)->open_machine) // 0x700fe
|
|
|
|
return DEV_ERR(COVER_OPENNED);
|
|
|
|
|
2024-01-09 06:26:46 +00:00
|
|
|
if(!motor_->read(MB_PORT_MODE, val))
|
2024-01-03 09:39:16 +00:00
|
|
|
return DEV_ERR(GET_STATUS_FAILED);
|
|
|
|
|
|
|
|
utils::to_log(LOG_LEVEL_DEBUG, "start scan: mode-status = 0x%08x.\n", val);
|
2024-01-05 09:36:50 +00:00
|
|
|
if(((SMBMODE*)&val)->paper_jammed_in ||
|
|
|
|
((SMBMODE*)&val)->paper_jammed_out)
|
2024-01-03 09:39:16 +00:00
|
|
|
return DEV_ERR(PAPER_JAMMED);
|
|
|
|
|
|
|
|
if(((SMBMODE*)&val)->feeding_paper_ready == 0 && !auto_scan_)
|
|
|
|
return DEV_ERR(NO_PAPER);
|
2024-01-02 07:18:42 +00:00
|
|
|
|
2024-01-09 06:26:46 +00:00
|
|
|
scanning_ = true;
|
|
|
|
scan_thread_.reset(new std::thread(&scanner_hw::thread_image_capture, this));
|
2023-12-20 07:23:24 +00:00
|
|
|
|
2024-01-02 07:18:42 +00:00
|
|
|
return SCANNER_ERR_OK;
|
2023-12-19 07:27:16 +00:00
|
|
|
}
|
|
|
|
int scanner_hw::stop_scan(void)
|
|
|
|
{
|
2024-01-09 06:26:46 +00:00
|
|
|
scanning_ = auto_scan_ = false;
|
2023-12-29 02:53:04 +00:00
|
|
|
if(motor_.get())
|
2024-01-02 07:18:42 +00:00
|
|
|
{
|
2024-01-09 06:26:46 +00:00
|
|
|
motor_->set_auto_paper(false, false);
|
2023-12-29 02:53:04 +00:00
|
|
|
motor_->stop();
|
2024-01-02 07:18:42 +00:00
|
|
|
}
|
2023-12-29 02:53:04 +00:00
|
|
|
|
2023-12-26 01:33:05 +00:00
|
|
|
if(camera_.get())
|
|
|
|
camera_->stop();
|
2023-12-20 07:23:24 +00:00
|
|
|
|
2023-12-19 07:27:16 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int scanner_hw::close(void)
|
|
|
|
{
|
2023-12-29 02:53:04 +00:00
|
|
|
img_controller_.reset();
|
|
|
|
if(motor_.get())
|
2023-12-19 07:27:16 +00:00
|
|
|
{
|
2023-12-29 02:53:04 +00:00
|
|
|
motor_->stop();
|
|
|
|
motor_.reset();
|
|
|
|
}
|
|
|
|
if(camera_.get())
|
|
|
|
{
|
|
|
|
camera_->stop();
|
|
|
|
camera_->close();
|
|
|
|
camera_.reset();
|
2023-12-19 07:27:16 +00:00
|
|
|
}
|
2024-01-09 06:26:46 +00:00
|
|
|
if(scan_thread_.get() && scan_thread_->joinable())
|
|
|
|
scan_thread_->join();
|
|
|
|
scan_thread_.reset();
|
2023-12-19 07:27:16 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2024-01-05 09:36:50 +00:00
|
|
|
bool scanner_hw::is_scanning(void)
|
|
|
|
{
|
|
|
|
return scanning_;
|
|
|
|
}
|