add start scan flow

This commit is contained in:
gb 2024-01-03 17:39:16 +08:00
parent 96ecacb861
commit be23610bae
10 changed files with 163 additions and 16 deletions

View File

@ -321,6 +321,7 @@ void FpgaComm::setDelayTime(int value) {
void FpgaComm::update() void FpgaComm::update()
{ {
// spends 6.5s
for(int i = 0; i < MAX_REGS; i++) for(int i = 0; i < MAX_REGS; i++)
{ {
read(i, fpgaParams.regs[i]); read(i, fpgaParams.regs[i]);

View File

@ -158,6 +158,10 @@ int gVideo::add_v4l2_memory(int ind)
return ret; return ret;
} }
int gVideo::get_mem_count(void)
{
return n_buffers;
}
void gVideo::set_size(int width,int height){ void gVideo::set_size(int width,int height){
if(!buffers.empty()) if(!buffers.empty())

View File

@ -21,6 +21,7 @@ public:
bool hasframe(); 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 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 add_v4l2_memory(int ind);
int get_mem_count(void);
void set_size(int width, int height); void set_size(int width, int height);
protected: protected:

View File

@ -248,20 +248,31 @@ void scanner_hw::init(void)
} }
void scanner_hw::thread_image_capture(void) void scanner_hw::thread_image_capture(void)
{ {
PACKIMAGE img; PACKIMAGE img;
safe_fifo<int> 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)); memset(&img, 0, sizeof(img));
do while(1) // auto scan cycle ...
{ {
size_t size = 0; size_t size = 0;
int ind = -1; int ind = -1;
void* frame = camera_->read_frame(1000, size, ind); void* frame = camera_->read_frame(1000, size, ind);
// scanning ONE turn ...
while(frame) 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.paper_ind++;
img.pos.status = IMG_STATUS_OK; img.pos.status = IMG_STATUS_OK;
img_handler_(mem, true, &img); 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()) if(img.pos.paper_ind == scan_count_ || is_scan_fatal())
break; 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(); motor_->pick_paper();
frame = camera_->read_frame(1000, size, ind); 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) bool scanner_hw::is_scan_fatal(void)
{ {
return false; return false;
} }
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;
}
// sane_opt_provider // sane_opt_provider
char* scanner_hw::get_value(const char* name, void* value, size_t* size, int* err) 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_PROTO> image_handler)
} }
int scanner_hw::start_scan(void) int scanner_hw::start_scan(void)
{ {
unsigned int val = 0;
if(!camera_.get() || !motor_.get() || !img_controller_.get()) if(!camera_.get() || !motor_.get() || !img_controller_.get())
return SCANNER_ERR_DEVICE_NOT_READY; return DEV_ERR(NOT_READY);
motor_->clear_error(); motor_->clear_error();
if(!motor_->paper_ready() && !auto_scan_) if(!motor_->read(PORT_STATUS, val))
return SCANNER_ERR_DEVICE_NO_PAPER; 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(); camera_->start();

View File

@ -71,6 +71,7 @@ class scanner_hw : public sane_opt_provider
void init(void); void init(void);
void thread_image_capture(void); void thread_image_capture(void);
bool is_scan_fatal(void); bool is_scan_fatal(void);
void retrieve_v4l2_mem(safe_fifo<int>* mem, int* used);
public: public:
scanner_hw(); scanner_hw();
@ -556,4 +557,4 @@ public:
// }, // },
// "depend": "is-check-askew==true" // "depend": "is-check-askew==true"
// } // }
// } // }

View File

@ -427,6 +427,10 @@ dyn_mem_ptr async_scanner::handle_scan_start(LPPACK_BASE pack, uint32_t* used, p
scan_err_ = cis_->open(receiver); scan_err_ = cis_->open(receiver);
if(scan_err_ == 0) if(scan_err_ == 0)
scan_err_ = cis_->start_scan(); 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_); BASE_PACKET_REPLY(*((LPPACK_BASE)reply->ptr()), pack->cmd + 1, pack->pack_id, scan_err_);
*used |= INT32_MAX + 1; *used |= INT32_MAX + 1;

View File

@ -322,22 +322,28 @@ data_source::~data_source()
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// dyn_mem // dyn_mem
#ifdef STAT_MEM
uint64_t dyn_mem::mem_used_bytes_ = 0; uint64_t dyn_mem::mem_used_bytes_ = 0;
MUTEX dyn_mem::mem_lock_; MUTEX dyn_mem::mem_lock_;
#endif
dyn_mem::dyn_mem(size_t size) : buf_(nullptr), len_(0), space_(ALIGN_TO(size, 16)) dyn_mem::dyn_mem(size_t size) : buf_(nullptr), len_(0), space_(ALIGN_TO(size, 16))
{ {
buf_ = (uint8_t*)malloc(space_); buf_ = (uint8_t*)malloc(space_);
if (buf_) if (buf_)
{ {
SIMPLE_LOCK(dyn_mem::mem_lock_); #ifdef STAT_MEM
dyn_mem::mem_used_bytes_ += space_; {
SIMPLE_LOCK(dyn_mem::mem_lock_);
dyn_mem::mem_used_bytes_ += space_;
}
#endif
memset(buf_, 0, space_); 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() dyn_mem::~dyn_mem()
@ -345,17 +351,22 @@ dyn_mem::~dyn_mem()
if (buf_) if (buf_)
{ {
free(buf_); free(buf_);
#ifdef STAT_MEM
{ {
SIMPLE_LOCK(dyn_mem::mem_lock_); SIMPLE_LOCK(dyn_mem::mem_lock_);
dyn_mem::mem_used_bytes_ -= space_; dyn_mem::mem_used_bytes_ -= space_;
} }
#endif
} }
} }
#ifdef STAT_MEM
uint64_t dyn_mem::mem_used(void) uint64_t dyn_mem::mem_used(void)
{ {
return dyn_mem::mem_used_bytes_; return dyn_mem::mem_used_bytes_;
} }
#endif
dyn_mem_ptr dyn_mem::memory(size_t size) dyn_mem_ptr dyn_mem::memory(size_t size)
{ {
return new dyn_mem(size); return new dyn_mem(size);
@ -424,10 +435,12 @@ dyn_mem& dyn_mem::operator+=(dyn_mem& r)
memcpy(buf, buf_, len_); memcpy(buf, buf_, len_);
free(buf_); free(buf_);
buf_ = buf; buf_ = buf;
#ifdef STAT_MEM
{ {
SIMPLE_LOCK(dyn_mem::mem_lock_); SIMPLE_LOCK(dyn_mem::mem_lock_);
dyn_mem::mem_used_bytes_ += size - space_; dyn_mem::mem_used_bytes_ += size - space_;
} }
#endif
space_ = size; space_ = size;
} }
memcpy(buf_ + len_, r.buf_, r.get_rest()); memcpy(buf_ + len_, r.buf_, r.get_rest());
@ -475,6 +488,17 @@ int dyn_mem::fetch_data(void* buf, uint32_t* size)
return 0; 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) file_reader::file_reader() : len_(0), src_(nullptr), path_(""), consume_(0)

View File

@ -205,6 +205,10 @@ public:
virtual int fetch_data(void* buf, uint32_t* size) = 0; 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<BEFORE_DESTROY_RET(BEFORE_DESTROY_PARAM)>
class dyn_mem : public data_source 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 space_; // occupy space in bytes
size_t len_; // data length in bytes size_t len_; // data length in bytes
#ifdef STAT_MEM
static MUTEX mem_lock_; static MUTEX mem_lock_;
static uint64_t mem_used_bytes_; static uint64_t mem_used_bytes_;
#endif
public: public:
dyn_mem(size_t size); dyn_mem(size_t size);
dyn_mem(void* buf, size_t size); dyn_mem(void* buf, size_t size);
#ifdef STAT_MEM
static uint64_t mem_used(void); static uint64_t mem_used(void);
#endif
static dyn_mem* memory(size_t size); static dyn_mem* memory(size_t size);
protected: protected:
~dyn_mem(); virtual ~dyn_mem();
public: public:
uint32_t space(void); uint32_t space(void);
@ -246,6 +254,17 @@ public:
// following API valid when is_memory_block() return false // following API valid when is_memory_block() return false
virtual int fetch_data(void* buf, uint32_t* size) override; 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 class file_reader : public data_source
{ {
@ -284,6 +303,7 @@ CLS_PTR(data_holder);
CLS_PTR(mem_holder); CLS_PTR(mem_holder);
CLS_PTR(data_source); CLS_PTR(data_source);
CLS_PTR(dyn_mem); CLS_PTR(dyn_mem);
CLS_PTR(dyn_mem_shared);
CLS_PTR(file_reader); CLS_PTR(file_reader);

View File

@ -11,6 +11,8 @@
#define RETURN_DESC_IF(var, hgerr) \ #define RETURN_DESC_IF(var, hgerr) \
if(var == hgerr) \ if(var == hgerr) \
return from_default_language(STATU_DESC_##hgerr); return from_default_language(STATU_DESC_##hgerr);
#define DEV_ERR(err) \
SCANNER_ERR_DEVICE_##err
enum scanner_err enum scanner_err
{ {
@ -77,6 +79,7 @@ enum scanner_err
SCANNER_ERR_DEVICE_UNKNOWN_STATUS, // 设备处于未知状态 SCANNER_ERR_DEVICE_UNKNOWN_STATUS, // 设备处于未知状态
SCANNER_ERR_DEVICE_NOT_READY, // 设备未准备好(执行某操作的前置条件未准备好) SCANNER_ERR_DEVICE_NOT_READY, // 设备未准备好(执行某操作的前置条件未准备好)
SCANNER_ERR_DEVICE_GET_STATUS_FAILED, // 获取电机板状态失败
}; };
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -59,8 +59,8 @@ add_packagedirs("sdk")
add_defines("VER_MAIN=2") add_defines("VER_MAIN=2")
add_defines("VER_FAMILY=300") add_defines("VER_FAMILY=300")
add_defines("VER_DATE=20231229") add_defines("VER_DATE=20240103")
add_defines("VER_BUILD=12") add_defines("VER_BUILD=7")
target("conf") target("conf")
set_kind("phony") set_kind("phony")