2
0
forked from Ivasoft/DSView

able to set range for data saving, and fix a bug of store module

This commit is contained in:
dreamsourcelabTAI
2024-01-12 15:39:19 +08:00
parent bb22f36b66
commit 1c6f061673
16 changed files with 346 additions and 31 deletions

View File

@@ -1502,5 +1502,14 @@ void LogicSnapshot::free_head_blocks(int count)
_lst_free_block_index = count;
}
int LogicSnapshot::get_block_with_sample(uint64_t index, uint64_t *out_offset)
{
assert(out_offset);
int block = index / LeafBlockSamples;
*out_offset = index % LeafBlockSamples;
return block;
}
} // namespace data
} // namespace pv

View File

@@ -150,6 +150,8 @@ public:
return _loop_offset;
}
static int get_block_with_sample(uint64_t index, uint64_t *out_offset);
private:
bool get_sample_unlock(uint64_t index, int sig_index);
bool get_sample_self(uint64_t index, int sig_index);

View File

@@ -28,10 +28,14 @@
#include <QTextEdit>
#include <QPushButton>
#include <QRadioButton>
#include <QComboBox>
#include <QFormLayout>
#include "../ui/msgbox.h"
#include "../config/appconfig.h"
#include "../interface/icallbacks.h"
#include "../log.h"
#include "../view/view.h"
#include "../view/cursor.h"
#include "../ui/langresource.h"
@@ -54,6 +58,10 @@ StoreProgress::StoreProgress(SigSession *session, QWidget *parent) :
_isExport = false;
_done = false;
_isBusy = false;
_start_cursor = NULL;
_end_cursor = NULL;
_view = NULL;
_is_normal_end = false;
QGridLayout *grid = new QGridLayout();
_grid = grid;
@@ -104,8 +112,8 @@ StoreProgress::~StoreProgress()
_store_session.wait();
}
void StoreProgress::on_change_file()
{
void StoreProgress::on_change_file()
{
QString file = "";
if (_isExport)
file = _store_session.MakeExportFile(true);
@@ -121,7 +129,7 @@ StoreProgress::~StoreProgress()
_ckCompress->setVisible(bFlag);
}
}
}
}
void StoreProgress::reject()
{
@@ -164,6 +172,47 @@ void StoreProgress::accept()
}
}
// Get data range
if (_store_session.IsLogicDataType() && _view != NULL)
{
uint64_t start_index = 0;
uint64_t end_index = 0;
auto &cursor_list = _view->get_cursorList();
int dex1 = _start_cursor->currentIndex();
int dex2 = _end_cursor->currentIndex();
if (dex1 > 0)
{
auto c = _view->get_cursor_by_index(dex1-1);
assert(c);
start_index = c->get_index();
}
if (dex2 > 0){
auto c = _view->get_cursor_by_index(dex2-1);
assert(c);
end_index = c->get_index();
}
if (dex1 > 0 && dex2 > 0)
{
if (dex1 == dex2){
QString mStr = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_DATA_RANGE_ERROR), "Data range error");
MsgBox::Show(mStr);
return;
}
else if (start_index > end_index){
uint64_t tmp = start_index;
start_index = end_index;
end_index = tmp;
}
}
_store_session.SetDataRange(start_index, end_index);
}
//start done
if (_isExport){
if (_store_session.export_start()){
@@ -178,8 +227,8 @@ void StoreProgress::accept()
show_error();
}
}
else{
if (_store_session.save_start()){
else{
if (_store_session.save_start()){
_isBusy = true;
_store_session.session()->set_saving(true);
QTimer::singleShot(100, this, SLOT(timeout()));
@@ -214,6 +263,32 @@ void StoreProgress::save_run(ISessionDataGetter *getter)
QString file = _store_session.MakeSaveFile(false);
_fileLab->setText(file);
_store_session._sessionDataGetter = getter;
if (_store_session.IsLogicDataType() && _view != NULL)
{
QFormLayout *lay = new QFormLayout();
lay->setContentsMargins(5, 0, 0, 0);
_start_cursor = new QComboBox();
_end_cursor = new QComboBox();
_start_cursor->addItem("-");
_end_cursor->addItem("-");
auto &cursor_list = _view->get_cursorList();
for (int i=0; i<cursor_list.size(); i++){
//tr
QString cursor_name = L_S(STR_PAGE_DLG, S_ID(IDS_DLG_CURSOR), "Cursor") +
QString::number(i+1);
_start_cursor->addItem(cursor_name);
_end_cursor->addItem(cursor_name);
}
lay->addRow(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_START_CURSOR), "Start") , _start_cursor);
lay->addRow(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_END_CURSOR), "End"), _end_cursor);
_grid->addLayout(lay, 2, 0, 1, 2);
}
show();
}
@@ -221,7 +296,7 @@ void StoreProgress::export_run()
{
if (_store_session.IsLogicDataType())
{
QGridLayout *lay = new QGridLayout();
QFormLayout *lay = new QFormLayout();
lay->setContentsMargins(5, 0, 0, 0);
bool isOrg = AppConfig::Instance().appOptions.originalData;
@@ -233,8 +308,31 @@ void StoreProgress::export_run()
_ckCompress->setText(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_COMPRESSED_DATA), "Compressed data"));
_ckCompress->setChecked(!isOrg);
lay->addWidget(_ckOrigin);
lay->addWidget(_ckCompress);
_start_cursor = new QComboBox();
_end_cursor = new QComboBox();
_start_cursor->addItem("-");
_end_cursor->addItem("-");
auto &cursor_list = _view->get_cursorList();
for (int i=0; i<cursor_list.size(); i++){
//tr
QString cursor_name = L_S(STR_PAGE_DLG, S_ID(IDS_DLG_CURSOR), "Cursor") +
QString::number(i+1);
_start_cursor->addItem(cursor_name);
_end_cursor->addItem(cursor_name);
}
lay->addRow(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_START_CURSOR), "Start") , _start_cursor);
lay->addRow(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_END_CURSOR), "End"), _end_cursor);
QWidget *space = new QWidget();
space->setFixedHeight(5);
lay->addRow(space);
lay->addRow("",_ckOrigin);
lay->addRow("", _ckCompress);
_grid->addLayout(lay, 2, 0, 1, 2);
connect(_ckOrigin, SIGNAL(clicked(bool)), this, SLOT(on_ck_origin(bool)));
@@ -246,11 +344,11 @@ void StoreProgress::export_run()
QString file = _store_session.MakeExportFile(false);
_fileLab->setText(file);
if (_ckOrigin != NULL){
bool bFlag = file.endsWith(".csv");
_ckOrigin->setVisible(bFlag);
_ckCompress->setVisible(bFlag);
}
if (_ckOrigin != NULL){
bool bFlag = file.endsWith(".csv");
_ckOrigin->setVisible(bFlag);
_ckCompress->setVisible(bFlag);
}
show();
}
@@ -265,26 +363,38 @@ void StoreProgress::show_error()
void StoreProgress::closeEvent(QCloseEvent* e)
{
_store_session.cancel();
if (!_is_normal_end){
_store_session.cancel();
}
_store_session.session()->set_saving(false);
DSDialog::closeEvent(e);
save_done();
_store_session.session()->broadcast_msg(DSV_MSG_SAVE_COMPLETE);
}
void StoreProgress::on_progress_updated()
{
const std::pair<uint64_t, uint64_t> p = _store_session.progress();
assert(p.first <= p.second);
int percent = p.first * 1.0 / p.second * 100;
_progress.setValue(percent);
uint64_t writed = 0;
uint64_t total = 0;
_store_session.get_progress(&writed, &total);
if (writed < total){
int percent = writed * 1.0 / total * 100.0;
_progress.setValue(percent);
}
else{
_progress.setValue(100);
}
const QString err = _store_session.error();
if (!err.isEmpty()) {
show_error();
}
if (p.first == p.second) {
_done = true;
if (writed >= total){
_is_normal_end = true;
_done = true; // Set end flag.
}
}

View File

@@ -33,6 +33,13 @@ class QRadioButton;
class QGridLayout;
class QPushButton;
class QWidget;
class QComboBox;
namespace pv {
namespace view {
class View;
}
}
namespace pv {
@@ -50,6 +57,9 @@ public:
virtual ~StoreProgress();
inline void SetView(view::View *view){
_view = view;
}
protected:
void reject();
@@ -85,6 +95,11 @@ private:
QGridLayout *_grid;
QWidget *_space;
bool _isBusy;
QComboBox *_start_cursor;
QComboBox *_end_cursor;
view::View *_view;
bool _is_normal_end;
};
} // dialogs

View File

@@ -626,6 +626,7 @@ namespace pv
_session->set_saving(true);
StoreProgress *dlg = new StoreProgress(_session, this);
dlg->SetView(_view);
dlg->save_run(this);
}
@@ -639,6 +640,7 @@ namespace pv
}
StoreProgress *dlg = new StoreProgress(_session, this);
dlg->SetView(_view);
dlg->export_run();
}

View File

@@ -75,6 +75,8 @@ StoreSession::StoreSession(SigSession *session) :
_canceled(false)
{
_sessionDataGetter = NULL;
_start_index = 0;
_end_index = 0;
}
StoreSession::~StoreSession()
@@ -87,9 +89,13 @@ SigSession* StoreSession::session()
return _session;
}
std::pair<uint64_t, uint64_t> StoreSession::progress()
{
return std::make_pair(_units_stored, _unit_count);
void StoreSession::get_progress(uint64_t *writed, uint64_t *total)
{
assert(writed);
assert(total);
*writed = _units_stored;
*total = _unit_count;
}
const QString& StoreSession::error()
@@ -226,6 +232,40 @@ void StoreSession::save_logic(pv::data::LogicSnapshot *logic_snapshot)
_unit_count = logic_snapshot->get_ring_sample_count() / 8 * to_save_probes;
num = logic_snapshot->get_block_num();
uint64_t start_index = _start_index;
uint64_t end_index = _end_index;
uint64_t start_offset = 0;
uint64_t end_offset = 0;
int start_block = 0;
int end_block = 0;
if (start_index > logic_snapshot->get_ring_sample_count()){
dsv_err("ERROR:the start curosr is invalid!");
_units_stored = -1;
progress_updated();
return;
}
if (end_index > logic_snapshot->get_ring_sample_count()){
end_index = 0;
}
if (start_index > 0){
start_block = LogicSnapshot::get_block_with_sample(start_index, &start_offset);
}
if (end_index > 0){
end_block = LogicSnapshot::get_block_with_sample(end_index, &end_offset);
}
if (start_index > 0 && end_index > 0){
_unit_count = (end_index - start_index) / 8 * to_save_probes;
}
else if (start_index > 0){
_unit_count = (logic_snapshot->get_ring_sample_count() - start_index) / 8 * to_save_probes;
}
else if (end_index > 0){
_unit_count = end_index / 8 * to_save_probes;
}
for(auto s : _session->get_signals())
{
int ch_type = s->get_type();
@@ -234,7 +274,15 @@ void StoreSession::save_logic(pv::data::LogicSnapshot *logic_snapshot)
if (!s->enabled() || !logic_snapshot->has_data(ch_index))
continue;
for (int i = 0; !_canceled && i < num; i++) {
for (int i = 0; !_canceled && i < num; i++)
{
if (i < start_block){
continue;
}
if (i > end_block && end_block > 0){
break;
}
uint8_t *buf = logic_snapshot->get_block_buf(i, ch_index, sample);
uint64_t size = logic_snapshot->get_block_size(i);
bool need_malloc = (buf == NULL);
@@ -250,7 +298,7 @@ void StoreSession::save_logic(pv::data::LogicSnapshot *logic_snapshot)
}
}
MakeChunkName(chunk_name, i, ch_index, ch_type, HEADER_FORMAT_VERSION);
MakeChunkName(chunk_name, i - start_block, ch_index, ch_type, HEADER_FORMAT_VERSION);
ret = m_zipDoc.AddFromBuffer(chunk_name, (const char*)buf, size) ? SR_OK : -1;
if (ret != SR_OK) {
@@ -266,7 +314,9 @@ void StoreSession::save_logic(pv::data::LogicSnapshot *logic_snapshot)
}
_units_stored += size;
if (_units_stored > _unit_count){
if (_units_stored > _unit_count
&& start_index == 0
&& end_index == 0){
dsv_err("Read block data error!");
assert(false);
}
@@ -494,8 +544,38 @@ bool StoreSession::meta_gen(data::Snapshot *snapshot, std::string &str)
if (probe->enabled && logic_snapshot->has_data(probe->index))
to_save_probes++;
}
int block_count = logic_snapshot->get_block_num();
uint64_t start_index = _start_index;
uint64_t end_index = _end_index;
uint64_t start_offset = 0;
uint64_t end_offset = 0;
int start_block = 0;
int end_block = 0;
if (end_index > logic_snapshot->get_ring_sample_count()){
end_index = 0;
}
if (start_index > 0){
start_block = LogicSnapshot::get_block_with_sample(start_index, &start_offset);
}
if (end_index > 0){
end_block = LogicSnapshot::get_block_with_sample(end_index, &end_offset);
}
if (start_index > 0 && end_index > 0){
block_count = end_block - start_block + 1;
}
else if (start_index > 0){
block_count = block_count - start_block;
}
else if (end_index > 0){
block_count = end_block + 1;
}
sprintf(meta, "total probes = %d\n", to_save_probes); str += meta;
sprintf(meta, "total blocks = %d\n", logic_snapshot->get_block_num()); str += meta;
sprintf(meta, "total blocks = %d\n", block_count); str += meta;
}
s = sr_samplerate_string(_session->cur_snap_samplerate());
@@ -775,6 +855,11 @@ void StoreSession::export_proc(data::Snapshot *snapshot)
output.module = (sr_output_module*) _outModule;
output.sdi = _session->get_device()->inst();
output.param = NULL;
output.start_sample_index = 0;
if (channel_type == SR_CHANNEL_LOGIC){
output.start_sample_index = _start_index;
}
if(_outModule->init){
if(_outModule->init(&output, params) != SR_OK){
@@ -854,11 +939,50 @@ void StoreSession::export_proc(data::Snapshot *snapshot)
std::vector<uint8_t *> buf_vec;
std::vector<bool> buf_sample;
uint64_t start_index = _start_index;
uint64_t end_index = _end_index;
uint64_t start_offset = 0;
uint64_t end_offset = 0;
int start_block = 0;
int end_block = 0;
if (start_index > logic_snapshot->get_ring_sample_count()){
dsv_err("ERROR:the start curosr is invalid!");
_units_stored = -1;
progress_updated();
return;
}
if (end_index > logic_snapshot->get_ring_sample_count()){
end_index = 0;
}
if (start_index > 0){
start_block = LogicSnapshot::get_block_with_sample(start_index, &start_offset);
}
if (end_index > 0){
end_block = LogicSnapshot::get_block_with_sample(end_index, &end_offset);
}
if (start_index > 0 && end_index > 0){
_unit_count = (end_index - start_index);
}
else if (start_index > 0){
_unit_count = (logic_snapshot->get_ring_sample_count() - start_index);
}
else if (end_index > 0){
_unit_count = end_index;
}
for (int blk = 0; !_canceled && blk < blk_num; blk++) {
uint64_t buf_sample_num = logic_snapshot->get_block_size(blk) * 8;
buf_vec.clear();
buf_sample.clear();
if (blk < start_block)
continue;
if (blk > end_block && end_block > 0)
break;
for(auto s : _session->get_signals()) {
int ch_type = s->get_type();
if (ch_type == SR_CHANNEL_LOGIC) {

View File

@@ -59,7 +59,7 @@ public:
SigSession* session();
std::pair<uint64_t, uint64_t> progress();
void get_progress(uint64_t *writed, uint64_t *total);
const QString& error();
@@ -91,7 +91,11 @@ public:
{ return _file_name;}
bool IsLogicDataType();
inline void SetDataRange(uint64_t start_index, uint64_t end_index){
_start_index = start_index;
_end_index = end_index;
}
private:
QList<QString> getSuportedExportFormats();
@@ -119,6 +123,8 @@ private:
QString _error;
volatile bool _canceled;
ZipMaker m_zipDoc;
uint64_t _start_index;
uint64_t _end_index;
};
} // pv

View File

@@ -1408,5 +1408,19 @@ bool View::header_is_draging()
return _header->mouse_is_down();
}
Cursor* View::get_cursor_by_index(int index)
{
int dex = 0;
auto &cursors = get_cursorList();
for (auto c : cursors){
if (dex == index){
return c;
}
dex++;
}
return NULL;
}
} // namespace view
} // namespace pv

View File

@@ -229,6 +229,8 @@ public:
return _trig_cursor;
}
Cursor* get_cursor_by_index(int index);
inline Cursor* get_search_cursor(){
return _search_cursor;
}

View File

@@ -722,5 +722,13 @@
{
"id": "IDS_DLG_DATA_OUT_OFF_RANGE",
"text": "数据超出量程"
}
},
{
"id": "IDS_DLG_START_CURSOR",
"text": "开始"
},
{
"id": "IDS_DLG_END_CURSOR",
"text": "结束"
}
]

View File

@@ -377,5 +377,9 @@
{
"id": "IDS_MSG_DEVICE_USB_IO_ERROR",
"text": "Error: USB读写错误!"
},
{
"id": "IDS_MSG_DATA_RANGE_ERROR",
"text": "数据范围设置错误!"
}
]

View File

@@ -722,5 +722,13 @@
{
"id": "IDS_DLG_DATA_OUT_OFF_RANGE",
"text": "Data out off range"
},
{
"id": "IDS_DLG_START_CURSOR",
"text": "Start"
},
{
"id": "IDS_DLG_END_CURSOR",
"text": "End"
}
]

View File

@@ -378,5 +378,9 @@
{
"id": "IDS_MSG_DEVICE_USB_IO_ERROR",
"text": "Error: USB IO error!"
},
{
"id": "IDS_MSG_DATA_RANGE_ERROR",
"text": "Data range is error!"
}
]

View File

@@ -530,6 +530,8 @@ struct sr_output {
* there, and only flush it when it reaches a certain size.
*/
void *priv;
uint64_t start_sample_index;
};
/** Generic option struct used by various subsystems. */

View File

@@ -88,6 +88,10 @@ static int init(struct sr_output *o, GHashTable *options)
ctx->type = g_variant_get_int16(g_hash_table_lookup(options, "type"));
ch_num = 0;
if (o->start_sample_index > 0){
ctx->index = o->start_sample_index;
}
/* Get the number of channels, and the unitsize. */
for (l = o->sdi->channels; l; l = l->next) {
ch = l->data;

View File

@@ -636,6 +636,7 @@ static int receive_data_logic_dso_v2(int fd, int revents, const struct sr_dev_in
if ((pack_buffer->block_data_len - pack_buffer->block_read_len) % 8 != 0)
{
sr_err("The block data is not align with 8 byte.");
bToEnd = 1;
break;
}
}