From be23610bae752672d7deb24ac3528e55adac3bd0 Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Wed, 3 Jan 2024 17:39:16 +0800 Subject: [PATCH] add start scan flow --- hardware/cis/FpgaComm.cpp | 1 + hardware/cis/gvideo.cpp | 4 ++ hardware/cis/gvideo.h | 1 + hardware/hardware.cpp | 105 ++++++++++++++++++++++++++++++++--- hardware/hardware.h | 3 +- scanner/async_scanner.cpp | 4 ++ sdk/base/data.cpp | 32 +++++++++-- sdk/base/data.h | 22 +++++++- sdk/huagao/hgscanner_error.h | 3 + xmake.lua | 4 +- 10 files changed, 163 insertions(+), 16 deletions(-) diff --git a/hardware/cis/FpgaComm.cpp b/hardware/cis/FpgaComm.cpp index 6548e02..44f05df 100644 --- a/hardware/cis/FpgaComm.cpp +++ b/hardware/cis/FpgaComm.cpp @@ -321,6 +321,7 @@ void FpgaComm::setDelayTime(int value) { void FpgaComm::update() { + // spends 6.5s for(int i = 0; i < MAX_REGS; i++) { read(i, fpgaParams.regs[i]); diff --git a/hardware/cis/gvideo.cpp b/hardware/cis/gvideo.cpp index ec7c395..22eb9c8 100644 --- a/hardware/cis/gvideo.cpp +++ b/hardware/cis/gvideo.cpp @@ -158,6 +158,10 @@ int gVideo::add_v4l2_memory(int ind) return ret; } +int gVideo::get_mem_count(void) +{ + return n_buffers; +} void gVideo::set_size(int width,int height){ if(!buffers.empty()) diff --git a/hardware/cis/gvideo.h b/hardware/cis/gvideo.h index 82def41..972a85e 100644 --- a/hardware/cis/gvideo.h +++ b/hardware/cis/gvideo.h @@ -21,6 +21,7 @@ public: bool hasframe(); virtual void *read_frame(int timeout, size_t& size, int& ind); // call add_v4l2_memory to put the buffer into the V4L2 queue again int add_v4l2_memory(int ind); + int get_mem_count(void); void set_size(int width, int height); protected: diff --git a/hardware/hardware.cpp b/hardware/hardware.cpp index cf9c238..e2517cd 100644 --- a/hardware/hardware.cpp +++ b/hardware/hardware.cpp @@ -248,20 +248,31 @@ void scanner_hw::init(void) } void scanner_hw::thread_image_capture(void) { - PACKIMAGE img; + PACKIMAGE img; + safe_fifo avail_mem("v4l2-mem"); + int used_v4l2_mem = 0; + auto put_v4l2_mem = [&](BEFORE_DESTROY_PARAM) -> BEFORE_DESTROY_RET + { + int ind = (int)(long)param; + mem->detach(nullptr); + avail_mem.save(ind); + }; + + utils::to_log(LOG_LEVEL_DEBUG, "scanning thread working ...\n"); memset(&img, 0, sizeof(img)); - do + while(1) // auto scan cycle ... { size_t size = 0; int ind = -1; void* frame = camera_->read_frame(1000, size, ind); + // scanning ONE turn ... while(frame) { - dyn_mem_ptr mem = dyn_mem::memory(size); + dyn_mem_shared_ptr mem = new dyn_mem_shared(frame, size, put_v4l2_mem, (void*)ind); - camera_->add_v4l2_memory(ind); + used_v4l2_mem++; img.pos.paper_ind++; img.pos.status = IMG_STATUS_OK; img_handler_(mem, true, &img); @@ -269,16 +280,78 @@ void scanner_hw::thread_image_capture(void) if(img.pos.paper_ind == scan_count_ || is_scan_fatal()) break; + // 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; + } + motor_->pick_paper(); frame = camera_->read_frame(1000, size, ind); } - }while(auto_scan_); + // retrieve v4l2-mem ... + while(avail_mem.take(ind, false)) + { + used_v4l2_mem--; + camera_->add_v4l2_memory(ind); + } + + if(!auto_scan_) + break; + + // wait paper ... + } + + int times = 0; + 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"); } bool scanner_hw::is_scan_fatal(void) { return false; } +void scanner_hw::retrieve_v4l2_mem(safe_fifo* 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; +} // sane_opt_provider char* scanner_hw::get_value(const char* name, void* value, size_t* size, int* err) @@ -392,12 +465,28 @@ int scanner_hw::open(std::function image_handler) } int scanner_hw::start_scan(void) { + unsigned int val = 0; + if(!camera_.get() || !motor_.get() || !img_controller_.get()) - return SCANNER_ERR_DEVICE_NOT_READY; + return DEV_ERR(NOT_READY); motor_->clear_error(); - if(!motor_->paper_ready() && !auto_scan_) - return SCANNER_ERR_DEVICE_NO_PAPER; + if(!motor_->read(PORT_STATUS, val)) + 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); + + if(!motor_->read(PORT_MODE, val)) + return DEV_ERR(GET_STATUS_FAILED); + + utils::to_log(LOG_LEVEL_DEBUG, "start scan: mode-status = 0x%08x.\n", val); + if(val & 0x1c0000) + return DEV_ERR(PAPER_JAMMED); + + if(((SMBMODE*)&val)->feeding_paper_ready == 0 && !auto_scan_) + return DEV_ERR(NO_PAPER); camera_->start(); diff --git a/hardware/hardware.h b/hardware/hardware.h index 0e1aec2..64e1fe3 100644 --- a/hardware/hardware.h +++ b/hardware/hardware.h @@ -71,6 +71,7 @@ class scanner_hw : public sane_opt_provider void init(void); void thread_image_capture(void); bool is_scan_fatal(void); + void retrieve_v4l2_mem(safe_fifo* mem, int* used); public: scanner_hw(); @@ -556,4 +557,4 @@ public: // }, // "depend": "is-check-askew==true" // } -// } \ No newline at end of file +// } diff --git a/scanner/async_scanner.cpp b/scanner/async_scanner.cpp index 478616a..68b8c4c 100644 --- a/scanner/async_scanner.cpp +++ b/scanner/async_scanner.cpp @@ -427,6 +427,10 @@ dyn_mem_ptr async_scanner::handle_scan_start(LPPACK_BASE pack, uint32_t* used, p scan_err_ = cis_->open(receiver); if(scan_err_ == 0) scan_err_ = cis_->start_scan(); + if(scan_err_) + { + cis_->stop_scan(); + } BASE_PACKET_REPLY(*((LPPACK_BASE)reply->ptr()), pack->cmd + 1, pack->pack_id, scan_err_); *used |= INT32_MAX + 1; diff --git a/sdk/base/data.cpp b/sdk/base/data.cpp index c13c361..cc33c22 100644 --- a/sdk/base/data.cpp +++ b/sdk/base/data.cpp @@ -322,22 +322,28 @@ data_source::~data_source() ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // dyn_mem +#ifdef STAT_MEM uint64_t dyn_mem::mem_used_bytes_ = 0; MUTEX dyn_mem::mem_lock_; +#endif dyn_mem::dyn_mem(size_t size) : buf_(nullptr), len_(0), space_(ALIGN_TO(size, 16)) { buf_ = (uint8_t*)malloc(space_); if (buf_) { - SIMPLE_LOCK(dyn_mem::mem_lock_); - dyn_mem::mem_used_bytes_ += space_; +#ifdef STAT_MEM + { + SIMPLE_LOCK(dyn_mem::mem_lock_); + dyn_mem::mem_used_bytes_ += space_; + } +#endif memset(buf_, 0, space_); } } -dyn_mem::dyn_mem(void* buf, size_t size) : buf_((uint8_t*)buf), space_(size), len_(size) +dyn_mem::dyn_mem(void* buf, size_t size) + : buf_((uint8_t*)buf), space_(size), len_(size) { - } dyn_mem::~dyn_mem() @@ -345,17 +351,22 @@ dyn_mem::~dyn_mem() if (buf_) { free(buf_); +#ifdef STAT_MEM { SIMPLE_LOCK(dyn_mem::mem_lock_); dyn_mem::mem_used_bytes_ -= space_; } +#endif } } +#ifdef STAT_MEM uint64_t dyn_mem::mem_used(void) { return dyn_mem::mem_used_bytes_; } +#endif + dyn_mem_ptr dyn_mem::memory(size_t size) { return new dyn_mem(size); @@ -424,10 +435,12 @@ dyn_mem& dyn_mem::operator+=(dyn_mem& r) memcpy(buf, buf_, len_); free(buf_); buf_ = buf; +#ifdef STAT_MEM { SIMPLE_LOCK(dyn_mem::mem_lock_); dyn_mem::mem_used_bytes_ += size - space_; } +#endif space_ = size; } memcpy(buf_ + len_, r.buf_, r.get_rest()); @@ -475,6 +488,17 @@ int dyn_mem::fetch_data(void* buf, uint32_t* size) return 0; } +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +dyn_mem_shared::dyn_mem_shared(void* buf, size_t size, BEFORE_DESTROY_FUNC destroy, void* param) + : dyn_mem(buf, size), destroy_(destroy), param_(param) +{} +dyn_mem_shared::~dyn_mem_shared() +{ + if(destroy_) + destroy_(this, param_); +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // file_reader::file_reader() : len_(0), src_(nullptr), path_(""), consume_(0) diff --git a/sdk/base/data.h b/sdk/base/data.h index 1dd5fde..5a2d5e5 100644 --- a/sdk/base/data.h +++ b/sdk/base/data.h @@ -205,6 +205,10 @@ public: virtual int fetch_data(void* buf, uint32_t* size) = 0; }; +// #define STAT_MEM +#define BEFORE_DESTROY_RET void +#define BEFORE_DESTROY_PARAM dyn_mem* mem, void* param +#define BEFORE_DESTROY_FUNC std::function class dyn_mem : public data_source { @@ -212,18 +216,22 @@ class dyn_mem : public data_source size_t space_; // occupy space in bytes size_t len_; // data length in bytes +#ifdef STAT_MEM static MUTEX mem_lock_; static uint64_t mem_used_bytes_; +#endif public: dyn_mem(size_t size); dyn_mem(void* buf, size_t size); +#ifdef STAT_MEM static uint64_t mem_used(void); +#endif static dyn_mem* memory(size_t size); protected: - ~dyn_mem(); + virtual ~dyn_mem(); public: uint32_t space(void); @@ -246,6 +254,17 @@ public: // following API valid when is_memory_block() return false virtual int fetch_data(void* buf, uint32_t* size) override; }; +class dyn_mem_shared : public dyn_mem +{ + BEFORE_DESTROY_FUNC destroy_ = BEFORE_DESTROY_FUNC(); + void* param_ = nullptr; + +public: + dyn_mem_shared(void* buf, size_t size, BEFORE_DESTROY_FUNC destroy = BEFORE_DESTROY_FUNC(), void* param = nullptr); + +protected: + ~dyn_mem_shared(); +}; class file_reader : public data_source { @@ -284,6 +303,7 @@ CLS_PTR(data_holder); CLS_PTR(mem_holder); CLS_PTR(data_source); CLS_PTR(dyn_mem); +CLS_PTR(dyn_mem_shared); CLS_PTR(file_reader); diff --git a/sdk/huagao/hgscanner_error.h b/sdk/huagao/hgscanner_error.h index bf1ff84..c00bb26 100644 --- a/sdk/huagao/hgscanner_error.h +++ b/sdk/huagao/hgscanner_error.h @@ -11,6 +11,8 @@ #define RETURN_DESC_IF(var, hgerr) \ if(var == hgerr) \ return from_default_language(STATU_DESC_##hgerr); +#define DEV_ERR(err) \ + SCANNER_ERR_DEVICE_##err enum scanner_err { @@ -77,6 +79,7 @@ enum scanner_err SCANNER_ERR_DEVICE_UNKNOWN_STATUS, // 设备处于未知状态 SCANNER_ERR_DEVICE_NOT_READY, // 设备未准备好(执行某操作的前置条件未准备好) + SCANNER_ERR_DEVICE_GET_STATUS_FAILED, // 获取电机板状态失败 }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/xmake.lua b/xmake.lua index 4905b07..2a0b2ca 100644 --- a/xmake.lua +++ b/xmake.lua @@ -59,8 +59,8 @@ add_packagedirs("sdk") add_defines("VER_MAIN=2") add_defines("VER_FAMILY=300") -add_defines("VER_DATE=20231229") -add_defines("VER_BUILD=12") +add_defines("VER_DATE=20240103") +add_defines("VER_BUILD=7") target("conf") set_kind("phony")