add start scan flow
This commit is contained in:
parent
96ecacb861
commit
be23610bae
|
@ -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]);
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -248,20 +248,31 @@ void scanner_hw::init(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));
|
||||
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<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
|
||||
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)
|
||||
{
|
||||
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();
|
||||
|
||||
|
|
|
@ -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<int>* mem, int* used);
|
||||
|
||||
public:
|
||||
scanner_hw();
|
||||
|
@ -556,4 +557,4 @@ public:
|
|||
// },
|
||||
// "depend": "is-check-askew==true"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<BEFORE_DESTROY_RET(BEFORE_DESTROY_PARAM)>
|
||||
|
||||
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);
|
||||
|
||||
|
||||
|
|
|
@ -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, // 获取电机板状态失败
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in New Issue