613 lines
14 KiB
C++
613 lines
14 KiB
C++
// hardware drivers
|
||
//
|
||
// Contains: CIS, MotorBoard, ...
|
||
//
|
||
// Date: 2023-12-18
|
||
|
||
#include <sane_opt_json/base_opt.h>
|
||
#include <functional>
|
||
#include <base/packet.h>
|
||
#include <base/data.h>
|
||
#include <memory>
|
||
#include <map>
|
||
#include <utility>
|
||
|
||
// image handler callback proto
|
||
//
|
||
// dyn_mem_ptr: image data buffer, or be uint32_t if bool was false
|
||
//
|
||
// bool: true - image, dyn_mem_ptr is image data buffer; false - dyn_mem_ptr is an uint32_t code of hardware event
|
||
//
|
||
// LPPACKIMAGE: image information, ignored when bool is false
|
||
#define IMAGE_HANDLER_PROTO void(dyn_mem_ptr, bool, LPPACKIMAGE)
|
||
|
||
class FpgaComm;
|
||
class GVideoISP1;
|
||
class gVideo;
|
||
class MotorBoard;
|
||
|
||
class scanner_hw : public sane_opt_provider
|
||
{
|
||
std::function<IMAGE_HANDLER_PROTO> img_handler_ = std::function<IMAGE_HANDLER_PROTO>();
|
||
volatile bool scanning_ = false;
|
||
int time_to_exit_auto_scan_ = 60; // seconds
|
||
std::unique_ptr<FpgaComm> img_controller_;
|
||
std::unique_ptr<gVideo> camera_;
|
||
std::unique_ptr<MotorBoard> motor_;
|
||
std::unique_ptr<std::thread> scan_thread_;
|
||
safe_fifo<std::pair<int, int>> mb_events_;
|
||
|
||
enum
|
||
{
|
||
SIDE_FRONT = 0,
|
||
SIDE_BACK,
|
||
SIDE_COUNT,
|
||
};
|
||
enum
|
||
{
|
||
COLOR_IND_BLUE = 0,
|
||
COLOR_IND_GREEN,
|
||
COLOR_IND_RED,
|
||
COLOR_IND_COUNT,
|
||
};
|
||
std::string mode_;
|
||
std::string family_ = "G200";
|
||
volatile bool auto_scan_ = false;
|
||
int scan_count_ = -1;
|
||
int cis_length_ = 3888;
|
||
int dpi_ = 300;
|
||
int baud_ = 921600;
|
||
int delay_ = 1000;
|
||
int frame_h_ = 12;
|
||
int sample_ = 256;
|
||
int exposure_[SIDE_COUNT][COLOR_IND_COUNT];
|
||
int gain_[SIDE_COUNT];
|
||
int off_[SIDE_COUNT];
|
||
|
||
bool staple_chk_ = true;
|
||
bool screw_chk_ = true;
|
||
int screw_chk_level_ = 3;
|
||
bool paper_on_ = false;
|
||
bool double_chk_ = true;
|
||
int motor_speed_ = /*SPEED_PPM_100*/0;
|
||
std::map<std::string, std::function<void(void*)>> opt_handler_;
|
||
|
||
|
||
void init(void);
|
||
void init_version(std::string& text);
|
||
void thread_image_capture(void);
|
||
bool is_scan_fatal(void);
|
||
void retrieve_v4l2_mem(safe_fifo<int>* mem, int* used);
|
||
|
||
public:
|
||
scanner_hw();
|
||
protected:
|
||
~scanner_hw();
|
||
|
||
// sane_opt_provider
|
||
public:
|
||
// return malloc(), real data size stored in parameter 'size'. invoker should free() the returned value
|
||
virtual char* get_value(const char* name, void* value, size_t* size, int* err = nullptr) override;
|
||
virtual int set_value(const char* name, void* val) override;
|
||
|
||
// operation ...
|
||
public:
|
||
int open(std::function<IMAGE_HANDLER_PROTO> image_handler);
|
||
int start_scan(void);
|
||
int stop_scan(void);
|
||
int close(void);
|
||
bool is_scanning(void);
|
||
};
|
||
// {
|
||
// "mode": {
|
||
// "cat": "none",
|
||
// "group": "CIS",
|
||
// "title": "颜色模式",
|
||
// "desc": "选择镜头色彩工作模式",
|
||
// "type": "string",
|
||
// "fix-id": 34819,
|
||
// "ui-pos": 10,
|
||
// "auth": 0,
|
||
// "size": 12,
|
||
// "cur": "彩色",
|
||
// "default": "彩色",
|
||
// "range": ["彩色", "灰度"]
|
||
// },
|
||
// "resolution": {
|
||
// "cat": "none",
|
||
// "group": "CIS",
|
||
// "title": "分辨<E58886><E8BEA8>?,
|
||
// "desc": "设置镜头工作的分辨率",
|
||
// "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": "待纸扫描",
|
||
// "desc": "启用后,文稿放入扫描仪时将自动启动扫<E58AA8><E689AB>?,
|
||
// "type": "bool",
|
||
// "fix-id": 34873,
|
||
// "ui-pos": 12,
|
||
// "auth": 0,
|
||
// "size": 4,
|
||
// "cur": false,
|
||
// "default": false
|
||
// },
|
||
// "wait-scan-exit": {
|
||
// "cat": "base",
|
||
// "group": "feeder",
|
||
// "title": "待纸扫描退出时<E587BA><E697B6>?,
|
||
// "desc": "设置结束待纸扫描的时<E79A84><E697B6>?,
|
||
// "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": "扫描张数",
|
||
// "desc": "选择指定数量扫描或连续扫<E7BBAD><E689AB>?,
|
||
// "type": "string",
|
||
// "fix-id": 34862,
|
||
// "ui-pos": 15,
|
||
// "auth": 0,
|
||
// "size": 24,
|
||
// "cur": "连续扫描",
|
||
// "default": "连续扫描",
|
||
// "range": ["连续扫描", "扫描指定张数"],
|
||
// "depend": "is-wait-scan==false"
|
||
// },
|
||
// "scan-count": {
|
||
// "cat": "base",
|
||
// "group": "feeder",
|
||
// "title": " 扫描数量",
|
||
// "desc": "扫描指定数量",
|
||
// "type": "int",
|
||
// "fix-id": 34863,
|
||
// "ui-pos": 16,
|
||
// "auth": 0,
|
||
// "size": 4,
|
||
// "cur": -1,
|
||
// "default": -1,
|
||
// "depend": "scan-mode.enabled&&scan-mode==扫描指定张数"
|
||
// },
|
||
// "is-auto-strength": {
|
||
// "cat": "base",
|
||
// "group": "feeder",
|
||
// "title": "自动分纸强度",
|
||
// "desc": "扫描仪自动修正分纸力<E7BAB8><E58A9B>?,
|
||
// "type": "bool",
|
||
// "fix-id": 34876,
|
||
// "ui-pos": 27,
|
||
// "auth": 0,
|
||
// "size": 4,
|
||
// "cur": false,
|
||
// "default": false
|
||
// },
|
||
// "feed-strength-value": {
|
||
// "cat": "base",
|
||
// "group": "feeder",
|
||
// "title": " 进纸失败<E5A4B1><E8B4A5>?,
|
||
// "desc": "高于该值时扫描仪将调整分纸力度",
|
||
// "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": "分纸强度",
|
||
// "desc": "设置扫描仪的分纸力度",
|
||
// "type": "string",
|
||
// "fix-id": 34874,
|
||
// "ui-pos": 30,
|
||
// "auth": 0,
|
||
// "size": 12,
|
||
// "cur": "一<><E4B880>?,
|
||
// "default": "一<><E4B880>?,
|
||
// "range": ["<22><>?, "一<><E4B880>?, "<22><>?],
|
||
// "depend": "is-auto-strength!=true"
|
||
// },
|
||
// "time-to-sleep": {
|
||
// "cat": "base",
|
||
// "group": "feeder",
|
||
// "title": "休眠时间",
|
||
// "desc": "设置扫描仪的休眠时间",
|
||
// "type": "string",
|
||
// "fix-id": 34875,
|
||
// "ui-pos": 33,
|
||
// "auth": 0,
|
||
// "size": 16,
|
||
// "cur": "不休<E4B88D><E4BC91>?,
|
||
// "default": "不休<E4B88D><E4BC91>?,
|
||
// "range": ["不休<E4B88D><E4BC91>?, "五分<E4BA94><E58886>?, "十分<E58D81><E58886>?, "半小<E58D8A><E5B08F>?, "一小时", "两小<E4B8A4><E5B08F>?, "四小<E59B9B><E5B08F>?]
|
||
// },
|
||
// "baud": {
|
||
// "cat": "none",
|
||
// "group": "CIS",
|
||
// "title": "波特<E6B3A2><E789B9>?,
|
||
// "desc": "CIS控制通信速率",
|
||
// "type": "int",
|
||
// "ui-pos": 20,
|
||
// "auth": 0,
|
||
// "size": 4,
|
||
// "cur": 921600,
|
||
// "default": 921600,
|
||
// "range": [110, 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 500000, 921600, 1500000]
|
||
// },
|
||
// "act-after": {
|
||
// "cat": "none",
|
||
// "group": "CIS",
|
||
// "title": "延迟响应",
|
||
// "desc": "采集头接受命令后的动作延迟时<E8BF9F><E697B6>?,
|
||
// "type": "int",
|
||
// "ui-pos": 21,
|
||
// "auth": 0,
|
||
// "unit": "microsec",
|
||
// "size": 4,
|
||
// "cur": 1000,
|
||
// "default": 1000
|
||
// },
|
||
// "frame-h": {
|
||
// "cat": "none",
|
||
// "group": "CIS",
|
||
// "title": "帧高<E5B8A7><E9AB98>?,
|
||
// "desc": "采集头每一帧的采集高度",
|
||
// "type": "int",
|
||
// "ui-pos": 22,
|
||
// "auth": 0,
|
||
// "size": 4,
|
||
// "cur": 12,
|
||
// "default": 12
|
||
// },
|
||
// "sample": {
|
||
// "cat": "none",
|
||
// "group": "CIS",
|
||
// "title": "采样频率",
|
||
// "desc": "采样频率",
|
||
// "type": "int",
|
||
// "ui-pos": 23,
|
||
// "auth": 0,
|
||
// "size": 4,
|
||
// "cur": 256,
|
||
// "default": 256
|
||
// },
|
||
// "expo-fb": {
|
||
// "cat": "none",
|
||
// "group": "CIS",
|
||
// "title": "曝光度(正面蓝色通道<E9809A><E98193>?,
|
||
// "desc": "正面蓝色通道的曝光强<E58589><E5BCBA>?,
|
||
// "type": "int",
|
||
// "ui-pos": 32,
|
||
// "auth": 0,
|
||
// "size": 4,
|
||
// "cur": 0,
|
||
// "default": 0,
|
||
// "range": {
|
||
// "min": -1000,
|
||
// "max": 1000,
|
||
// "step": 1
|
||
// }
|
||
// },
|
||
// "expo-fg": {
|
||
// "cat": "none",
|
||
// "group": "CIS",
|
||
// "title": "曝光度(正面绿色通道<E9809A><E98193>?,
|
||
// "desc": "正面绿色通道的曝光强<E58589><E5BCBA>?,
|
||
// "type": "int",
|
||
// "ui-pos": 31,
|
||
// "auth": 0,
|
||
// "size": 4,
|
||
// "cur": 0,
|
||
// "default": 0,
|
||
// "range": {
|
||
// "min": -1000,
|
||
// "max": 1000,
|
||
// "step": 1
|
||
// }
|
||
// },
|
||
// "expo-fr": {
|
||
// "cat": "none",
|
||
// "group": "CIS",
|
||
// "title": "曝光度(正面红色通道<E9809A><E98193>?,
|
||
// "desc": "正面红色通道的曝光强<E58589><E5BCBA>?,
|
||
// "type": "int",
|
||
// "ui-pos": 30,
|
||
// "auth": 0,
|
||
// "size": 4,
|
||
// "cur": 0,
|
||
// "default": 0,
|
||
// "range": {
|
||
// "min": -1000,
|
||
// "max": 1000,
|
||
// "step": 1
|
||
// }
|
||
// },
|
||
// "expo-bb": {
|
||
// "cat": "none",
|
||
// "group": "CIS",
|
||
// "title": "曝光度(背面蓝色通道<E9809A><E98193>?,
|
||
// "desc": "背面蓝色通道的曝光强<E58589><E5BCBA>?,
|
||
// "type": "int",
|
||
// "ui-pos": 35,
|
||
// "auth": 0,
|
||
// "size": 4,
|
||
// "cur": 0,
|
||
// "default": 0,
|
||
// "range": {
|
||
// "min": -1000,
|
||
// "max": 1000,
|
||
// "step": 1
|
||
// }
|
||
// },
|
||
// "expo-bg": {
|
||
// "cat": "none",
|
||
// "group": "CIS",
|
||
// "title": "曝光度(背面绿色通道<E9809A><E98193>?,
|
||
// "desc": "背面绿色通道的曝光强<E58589><E5BCBA>?,
|
||
// "type": "int",
|
||
// "ui-pos": 34,
|
||
// "auth": 0,
|
||
// "size": 4,
|
||
// "cur": 0,
|
||
// "default": 0,
|
||
// "range": {
|
||
// "min": -1000,
|
||
// "max": 1000,
|
||
// "step": 1
|
||
// }
|
||
// },
|
||
// "expo-br": {
|
||
// "cat": "none",
|
||
// "group": "CIS",
|
||
// "title": "曝光度(背面红色通道<E9809A><E98193>?,
|
||
// "desc": "背面红色通道的曝光强<E58589><E5BCBA>?,
|
||
// "type": "int",
|
||
// "ui-pos": 33,
|
||
// "auth": 0,
|
||
// "size": 4,
|
||
// "cur": 0,
|
||
// "default": 0,
|
||
// "range": {
|
||
// "min": -1000,
|
||
// "max": 1000,
|
||
// "step": 1
|
||
// }
|
||
// },
|
||
// "gain-f": {
|
||
// "cat": "none",
|
||
// "group": "CIS",
|
||
// "title": "增益(正面)",
|
||
// "desc": "正面的增益量",
|
||
// "type": "int",
|
||
// "ui-pos": 40,
|
||
// "auth": 0,
|
||
// "size": 4,
|
||
// "cur": 0,
|
||
// "default": 0,
|
||
// "range": {
|
||
// "min": -1000,
|
||
// "max": 1000,
|
||
// "step": 1
|
||
// }
|
||
// },
|
||
// "gain-b": {
|
||
// "cat": "none",
|
||
// "group": "CIS",
|
||
// "title": "增益(背面)",
|
||
// "desc": "背面的增益量",
|
||
// "type": "int",
|
||
// "ui-pos": 41,
|
||
// "auth": 0,
|
||
// "size": 4,
|
||
// "cur": 0,
|
||
// "default": 0,
|
||
// "range": {
|
||
// "min": -1000,
|
||
// "max": 1000,
|
||
// "step": 1
|
||
// }
|
||
// },
|
||
// "off-f": {
|
||
// "cat": "none",
|
||
// "group": "CIS",
|
||
// "title": "增益补偿(正面)",
|
||
// "desc": "正面的增益补偿量",
|
||
// "type": "int",
|
||
// "ui-pos": 45,
|
||
// "auth": 0,
|
||
// "size": 4,
|
||
// "cur": 0,
|
||
// "default": 0,
|
||
// "range": {
|
||
// "min": -100,
|
||
// "max": 100,
|
||
// "step": 1
|
||
// }
|
||
// },
|
||
// "off-b": {
|
||
// "cat": "none",
|
||
// "group": "CIS",
|
||
// "title": "增益补偿(背面)",
|
||
// "desc": "背面的增益补偿量",
|
||
// "type": "int",
|
||
// "ui-pos": 46,
|
||
// "auth": 0,
|
||
// "size": 4,
|
||
// "cur": 0,
|
||
// "default": 0,
|
||
// "range": {
|
||
// "min": -100,
|
||
// "max": 100,
|
||
// "step": 1
|
||
// }
|
||
// },
|
||
// "paper-on": {
|
||
// "cat": "none",
|
||
// "group": "feeder",
|
||
// "title": "纸张就绪",
|
||
// "desc": "纸张已经在进纸台上放置好",
|
||
// "type": "bool",
|
||
// "fix-id": 34912,
|
||
// "ui-pos": 10,
|
||
// "auth": 0,
|
||
// "readonly": true,
|
||
// "size": 4,
|
||
// "auto": false,
|
||
// "ownread": true,
|
||
// "cur": false,
|
||
// "default": false
|
||
// },
|
||
// "double-chk": {
|
||
// "cat": "none",
|
||
// "group": "feeder",
|
||
// "title": "双张检<E5BCA0><E6A380>?,
|
||
// "desc": "检测是否有两张或者多张纸同时搓进",
|
||
// "type": "string",
|
||
// "ui-pos": 18,
|
||
// "auth": 0,
|
||
// "size": 16,
|
||
// "cur": "超声<E8B685><E5A3B0>?,
|
||
// "default": "超声<E8B685><E5A3B0>?,
|
||
// "range": ["超声<E8B685><E5A3B0>?, "禁用"]
|
||
// },
|
||
// "is-staple": {
|
||
// "cat": "none",
|
||
// "group": "feeder",
|
||
// "title": "装订检<E8AEA2><E6A380>?,
|
||
// "desc": "检测是否有订书钉存<E99289><E5AD98>?,
|
||
// "type": "bool",
|
||
// "fix-id": 34861,
|
||
// "ui-pos": 20,
|
||
// "auth": 0,
|
||
// "size": 4,
|
||
// "cur": true,
|
||
// "default": true
|
||
// },
|
||
// "motor-speed": {
|
||
// "cat": "none",
|
||
// "group": "feeder",
|
||
// "title": "走纸速度",
|
||
// "desc": "设置走纸电机的速度,张\/分(PPM<50><4D>?,
|
||
// "type": "int",
|
||
// "ui-pos": 25,
|
||
// "auth": 0,
|
||
// "size": 4,
|
||
// "cur": 100,
|
||
// "default": 100,
|
||
// "range": [{
|
||
// "dev-model!=G200": 70
|
||
// }, {
|
||
// "dev-model!=G200": 80
|
||
// }, {
|
||
// "dev-model!=G200": 90
|
||
// }, 100, {
|
||
// "dev-model==G200": 110
|
||
// }, {
|
||
// "dev-model==G200": 120
|
||
// }, {
|
||
// "dev-model==G200": 130
|
||
// }]
|
||
// },
|
||
// "is-check-askew": {
|
||
// "cat": "none",
|
||
// "group": "feeder",
|
||
// "title": "歪斜检<E6969C><E6A380>?,
|
||
// "desc": "检测进纸是否歪<E590A6><E6ADAA>?,
|
||
// "type": "bool",
|
||
// "fix-id": 34868,
|
||
// "ui-pos": 22,
|
||
// "auth": 0,
|
||
// "size": 4,
|
||
// "cur": true,
|
||
// "default": true
|
||
// },
|
||
// "askew-range": {
|
||
// "cat": "none",
|
||
// "group": "feeder",
|
||
// "title": "歪斜容忍<E5AEB9><E5BF8D>?,
|
||
// "desc": "值越小,能容忍得送入文稿歪斜角度越小",
|
||
// "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": "关于",
|
||
// "title": "镜头<E9959C><E5A4B4>?,
|
||
// "desc": "图像采集镜头的长度,单位为毫米(mm<6D><6D>?,
|
||
// "type": "int",
|
||
// "ui-pos": 30,
|
||
// "auth": 0,
|
||
// "unit": "mm",
|
||
// "readonly": true,
|
||
// "size": 4,
|
||
// "auto": false,
|
||
// "cur": 1632,
|
||
// "default": 1632
|
||
// },
|
||
// "motor-ver": {
|
||
// "cat": "none",
|
||
// "group": "关于",
|
||
// "title": "电机驱动版本",
|
||
// "desc": "电机板驱动程序版本号",
|
||
// "type": "string",
|
||
// "fix-id": 34909,
|
||
// "ui-pos": 16,
|
||
// "auth": 0,
|
||
// "readonly": true,
|
||
// "size": 24,
|
||
// "auto": false,
|
||
// "cur": "",
|
||
// "default": ""
|
||
// },
|
||
// "fpga-ver": {
|
||
// "cat": "none",
|
||
// "group": "关于",
|
||
// "title": "CIS控制器版<E599A8><E78988>?,
|
||
// "desc": "镜头参数控制驱动程序版本<E78988><E69CAC>?,
|
||
// "type": "string",
|
||
// "ui-pos": 17,
|
||
// "auth": 0,
|
||
// "readonly": true,
|
||
// "size": 24,
|
||
// "auto": false,
|
||
// "cur": "",
|
||
// "default": ""
|
||
// }
|
||
// }
|
||
|