mirror of
https://github.com/DreamSourceLab/DSView.git
synced 2025-01-13 13:32:53 +08:00
Merge branch 'add_dso_export' into develop
Add data export(csv only) support @ DSO mode
This commit is contained in:
commit
716c3fffb8
@ -188,6 +188,8 @@ QList<QString> SigSession::getSuportedExportFormats(){
|
||||
while(*supportedModules){
|
||||
if(*supportedModules == NULL)
|
||||
break;
|
||||
if (_dev_inst->dev_inst()->mode == DSO && strcmp((*supportedModules)->id, "csv"))
|
||||
break;
|
||||
QString format((*supportedModules)->desc);
|
||||
format.append(" (*.");
|
||||
format.append((*supportedModules)->id);
|
||||
@ -203,12 +205,27 @@ void SigSession::cancelSaveFile(){
|
||||
}
|
||||
|
||||
void SigSession::export_file(const std::string &name, QWidget* parent, const std::string &ext){
|
||||
const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots =
|
||||
_logic_data->get_snapshots();
|
||||
if(snapshots.empty())
|
||||
boost::shared_ptr<pv::data::Snapshot> snapshot;
|
||||
int channel_type;
|
||||
|
||||
if (_dev_inst->dev_inst()->mode == LOGIC) {
|
||||
const deque< boost::shared_ptr<pv::data::LogicSnapshot> > &snapshots =
|
||||
_logic_data->get_snapshots();
|
||||
if(snapshots.empty())
|
||||
return;
|
||||
snapshot = snapshots.front();
|
||||
channel_type = SR_CHANNEL_LOGIC;
|
||||
} else if (_dev_inst->dev_inst()->mode == DSO) {
|
||||
const deque< boost::shared_ptr<pv::data::DsoSnapshot> > &snapshots =
|
||||
_dso_data->get_snapshots();
|
||||
if(snapshots.empty())
|
||||
return;
|
||||
snapshot = snapshots.front();
|
||||
channel_type = SR_CHANNEL_DSO;
|
||||
} else {
|
||||
return;
|
||||
const boost::shared_ptr<pv::data::LogicSnapshot> & snapshot =
|
||||
snapshots.front();
|
||||
}
|
||||
|
||||
const struct sr_output_module** supportedModules = sr_output_list();
|
||||
const struct sr_output_module* outModule = NULL;
|
||||
while(*supportedModules){
|
||||
@ -222,10 +239,23 @@ void SigSession::export_file(const std::string &name, QWidget* parent, const std
|
||||
}
|
||||
if(outModule == NULL)
|
||||
return;
|
||||
struct sr_output output;
|
||||
|
||||
|
||||
GHashTable *params = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
GVariant* filenameGVariant = g_variant_new_string(name.c_str());
|
||||
g_hash_table_insert(params, (char*)"filename", filenameGVariant);
|
||||
GVariant* typeGVariant = g_variant_new_int16(channel_type);
|
||||
g_hash_table_insert(params, (char*)"type", typeGVariant);
|
||||
BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _signals) {
|
||||
boost::shared_ptr<view::DsoSignal> dsoSig;
|
||||
if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(s)) {
|
||||
GVariant* timebaseGVariant = g_variant_new_uint64(dsoSig->get_hDialValue());
|
||||
g_hash_table_insert(params, (char*)"timebase", timebaseGVariant);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct sr_output output;
|
||||
output.module = (sr_output_module*) outModule;
|
||||
output.sdi = _dev_inst->dev_inst();
|
||||
output.param = NULL;
|
||||
@ -234,33 +264,64 @@ void SigSession::export_file(const std::string &name, QWidget* parent, const std
|
||||
QFile file(name.c_str());
|
||||
file.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
QTextStream out(&file);
|
||||
QFuture<void> future = QtConcurrent::run([&]{
|
||||
saveFileThreadRunning = true;
|
||||
unsigned char* datat = (unsigned char*)snapshot->get_data();
|
||||
unsigned int numsamples = snapshot->get_sample_count()*snapshot->unit_size();
|
||||
GString *data_out;
|
||||
int usize = 8192;
|
||||
int size = usize;
|
||||
struct sr_datafeed_logic lp;
|
||||
struct sr_datafeed_packet p;
|
||||
for(uint64_t i = 0; i < numsamples; i+=usize){
|
||||
if(numsamples - i < usize)
|
||||
size = numsamples - i;
|
||||
lp.data = &datat[i];
|
||||
lp.length = size;
|
||||
lp.unitsize = snapshot->unit_size();
|
||||
p.type = SR_DF_LOGIC;
|
||||
p.payload = &lp;
|
||||
outModule->receive(&output, &p, &data_out);
|
||||
if(data_out){
|
||||
out << (char*) data_out->str;
|
||||
g_string_free(data_out,TRUE);
|
||||
QFuture<void> future;
|
||||
if (_dev_inst->dev_inst()->mode == LOGIC) {
|
||||
future = QtConcurrent::run([&]{
|
||||
saveFileThreadRunning = true;
|
||||
unsigned char* datat = (unsigned char*)snapshot->get_data();
|
||||
unsigned int numsamples = snapshot->get_sample_count()*snapshot->unit_size();
|
||||
GString *data_out;
|
||||
int usize = 8192;
|
||||
int size = usize;
|
||||
struct sr_datafeed_logic lp;
|
||||
struct sr_datafeed_packet p;
|
||||
for(uint64_t i = 0; i < numsamples; i+=usize){
|
||||
if(numsamples - i < usize)
|
||||
size = numsamples - i;
|
||||
lp.data = &datat[i];
|
||||
lp.length = size;
|
||||
lp.unitsize = snapshot->unit_size();
|
||||
p.type = SR_DF_LOGIC;
|
||||
p.payload = &lp;
|
||||
outModule->receive(&output, &p, &data_out);
|
||||
if(data_out){
|
||||
out << (char*) data_out->str;
|
||||
g_string_free(data_out,TRUE);
|
||||
}
|
||||
emit progressSaveFileValueChanged(i*100/numsamples);
|
||||
if(!saveFileThreadRunning)
|
||||
break;
|
||||
}
|
||||
emit progressSaveFileValueChanged(i*100/numsamples);
|
||||
if(!saveFileThreadRunning)
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
} else if (_dev_inst->dev_inst()->mode == DSO) {
|
||||
future = QtConcurrent::run([&]{
|
||||
saveFileThreadRunning = true;
|
||||
unsigned char* datat = (unsigned char*)snapshot->get_data();
|
||||
unsigned int numsamples = snapshot->get_sample_count();
|
||||
GString *data_out;
|
||||
int usize = 8192;
|
||||
int size = usize;
|
||||
struct sr_datafeed_dso dp;
|
||||
struct sr_datafeed_packet p;
|
||||
for(uint64_t i = 0; i < numsamples; i+=usize){
|
||||
if(numsamples - i < usize)
|
||||
size = numsamples - i;
|
||||
dp.data = &datat[i*snapshot->get_channel_num()];
|
||||
dp.num_samples = size;
|
||||
p.type = SR_DF_DSO;
|
||||
p.payload = &dp;
|
||||
outModule->receive(&output, &p, &data_out);
|
||||
if(data_out){
|
||||
out << (char*) data_out->str;
|
||||
g_string_free(data_out,TRUE);
|
||||
}
|
||||
emit progressSaveFileValueChanged(i*100/numsamples);
|
||||
if(!saveFileThreadRunning)
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
QFutureWatcher<void> watcher;
|
||||
Qt::WindowFlags flags = Qt::CustomizeWindowHint;
|
||||
QProgressDialog dlg(QString::fromUtf8("Exporting data... It can take a while."),
|
||||
|
@ -127,14 +127,7 @@ void FileBar::on_actionExport_triggered(){
|
||||
msg.setStandardButtons(QMessageBox::Ok);
|
||||
msg.setIcon(QMessageBox::Warning);
|
||||
msg.exec();
|
||||
} else if (_session.get_device()->dev_inst()->mode != LOGIC) {
|
||||
QMessageBox msg(this);
|
||||
msg.setText("Export Data");
|
||||
msg.setInformativeText("DSLogic currently only support exporting logic data to file!");
|
||||
msg.setStandardButtons(QMessageBox::Ok);
|
||||
msg.setIcon(QMessageBox::Warning);
|
||||
msg.exec();
|
||||
}else {
|
||||
} else {
|
||||
QList<QString> supportedFormats = _session.getSuportedExportFormats();
|
||||
QString filter;
|
||||
for(int i = 0; i < supportedFormats.count();i++){
|
||||
|
@ -503,6 +503,8 @@ void Viewport::set_receive_len(quint64 length)
|
||||
|
||||
void Viewport::measure()
|
||||
{
|
||||
if (_view.session().get_capture_state() == SigSession::Running)
|
||||
return;
|
||||
const uint64_t sample_rate = _view.session().get_device()->get_sample_rate();
|
||||
const vector< boost::shared_ptr<Signal> > sigs(_view.session().get_signals());
|
||||
BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) {
|
||||
|
@ -601,6 +601,7 @@ static int set_probes(struct sr_dev_inst *sdi, int num_probes)
|
||||
return SR_ERR;
|
||||
if (sdi->mode == DSO) {
|
||||
probe->vdiv = 1000;
|
||||
probe->vfactor = 1;
|
||||
probe->vpos = 0;
|
||||
probe->coupling = SR_DC_COUPLING;
|
||||
probe->trig_value = 0x80;
|
||||
|
@ -642,6 +642,7 @@ static int set_probes(struct sr_dev_inst *sdi, int num_probes)
|
||||
return SR_ERR;
|
||||
if (sdi->mode == DSO) {
|
||||
probe->vdiv = 1000;
|
||||
probe->vfactor = 1;
|
||||
probe->coupling = SR_DC_COUPLING;
|
||||
probe->trig_value = 0x80;
|
||||
}
|
||||
|
@ -323,7 +323,7 @@ struct sr_datafeed_dso {
|
||||
uint64_t mqflags;
|
||||
/** The analog value(s). The data is interleaved according to
|
||||
* the probes list. */
|
||||
float *data;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct sr_datafeed_analog {
|
||||
@ -559,6 +559,7 @@ struct sr_channel {
|
||||
char *name;
|
||||
char *trigger;
|
||||
uint64_t vdiv;
|
||||
uint16_t vfactor;
|
||||
double vpos;
|
||||
uint8_t coupling;
|
||||
uint8_t trig_value;
|
||||
|
@ -33,9 +33,13 @@ struct context {
|
||||
char separator;
|
||||
gboolean header_done;
|
||||
int *channel_index;
|
||||
float *channel_vdiv;
|
||||
double *channel_vpos;
|
||||
uint64_t timebase;
|
||||
uint64_t mask;
|
||||
uint64_t pre_data;
|
||||
uint64_t index;
|
||||
int type;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -57,8 +61,6 @@ static int init(struct sr_output *o, GHashTable *options)
|
||||
GSList *l;
|
||||
int i;
|
||||
|
||||
(void)options;
|
||||
|
||||
if (!o || !o->sdi)
|
||||
return SR_ERR_ARG;
|
||||
|
||||
@ -67,27 +69,34 @@ static int init(struct sr_output *o, GHashTable *options)
|
||||
ctx->separator = ',';
|
||||
ctx->mask = 0;
|
||||
ctx->index = 0;
|
||||
ctx->type = g_variant_get_int16(g_hash_table_lookup(options, "type"));
|
||||
ctx->timebase = g_variant_get_uint64(g_hash_table_lookup(options, "timebase"));
|
||||
|
||||
/* Get the number of channels, and the unitsize. */
|
||||
for (l = o->sdi->channels; l; l = l->next) {
|
||||
ch = l->data;
|
||||
if (ch->type != SR_CHANNEL_LOGIC)
|
||||
if (ch->type != ctx->type)
|
||||
continue;
|
||||
if (!ch->enabled)
|
||||
continue;
|
||||
ctx->num_enabled_channels++;
|
||||
}
|
||||
ctx->channel_index = g_malloc(sizeof(int) * ctx->num_enabled_channels);
|
||||
ctx->channel_vdiv = g_malloc(sizeof(float) * ctx->num_enabled_channels);
|
||||
ctx->channel_vpos = g_malloc(sizeof(double) * ctx->num_enabled_channels);
|
||||
|
||||
/* Once more to map the enabled channels. */
|
||||
for (i = 0, l = o->sdi->channels; l; l = l->next) {
|
||||
ch = l->data;
|
||||
if (ch->type != SR_CHANNEL_LOGIC)
|
||||
if (ch->type != ctx->type)
|
||||
continue;
|
||||
if (!ch->enabled)
|
||||
continue;
|
||||
ctx->channel_index[i++] = ch->index;
|
||||
ctx->channel_index[i] = ch->index;
|
||||
ctx->mask |= (1 << ch->index);
|
||||
ctx->channel_vdiv[i] = ch->vdiv * ch->vfactor >= 500 ? ch->vdiv * ch->vfactor / 100.0f : ch->vdiv * ch->vfactor * 10.0f;
|
||||
ctx->channel_vpos[i] = ch->vdiv * ch->vfactor >= 500 ? ch->vpos / 1000 : ch->vpos;
|
||||
i++;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
@ -102,7 +111,6 @@ static GString *gen_header(const struct sr_output *o)
|
||||
GSList *l;
|
||||
time_t t;
|
||||
int num_channels, i;
|
||||
char *samplerate_s;
|
||||
|
||||
ctx = o->priv;
|
||||
header = g_string_sized_new(512);
|
||||
@ -113,7 +121,10 @@ static GString *gen_header(const struct sr_output *o)
|
||||
PACKAGE_STRING, ctime(&t));
|
||||
|
||||
/* Columns / channels */
|
||||
num_channels = g_slist_length(o->sdi->channels);
|
||||
if (ctx->type == SR_CHANNEL_LOGIC)
|
||||
num_channels = g_slist_length(o->sdi->channels);
|
||||
else
|
||||
num_channels = ctx->num_enabled_channels;
|
||||
g_string_append_printf(header, "; Channels (%d/%d)\n",
|
||||
ctx->num_enabled_channels, num_channels);
|
||||
|
||||
@ -125,19 +136,34 @@ static GString *gen_header(const struct sr_output *o)
|
||||
}
|
||||
}
|
||||
if (ctx->samplerate != 0) {
|
||||
samplerate_s = sr_samplerate_string(ctx->samplerate);
|
||||
g_string_append_printf(header, "; Samplerate: %s\n", samplerate_s);
|
||||
char *samplerate_s = sr_samplerate_string(ctx->samplerate);
|
||||
g_string_append_printf(header, "; Sample rate: %s\n", samplerate_s);
|
||||
g_free(samplerate_s);
|
||||
}
|
||||
|
||||
g_string_append_printf(header, "Time(s),");
|
||||
if (sr_config_get(o->sdi->driver, o->sdi, NULL, NULL, SR_CONF_LIMIT_SAMPLES,
|
||||
&gvar) == SR_OK) {
|
||||
uint64_t depth = g_variant_get_uint64(gvar);
|
||||
g_variant_unref(gvar);
|
||||
char *depth_s = sr_samplecount_string(depth);
|
||||
g_string_append_printf(header, "; Sample count: %s\n", depth_s);
|
||||
g_free(depth_s);
|
||||
}
|
||||
|
||||
if (ctx->type == SR_CHANNEL_LOGIC)
|
||||
g_string_append_printf(header, "Time(s),");
|
||||
for (i = 0, l = o->sdi->channels; l; l = l->next, i++) {
|
||||
ch = l->data;
|
||||
if (ch->type != SR_CHANNEL_LOGIC)
|
||||
if (ch->type != ctx->type)
|
||||
continue;
|
||||
if (!ch->enabled)
|
||||
continue;
|
||||
g_string_append_printf(header, " %s,", ch->name);
|
||||
if (ctx->type == SR_CHANNEL_DSO) {
|
||||
char *unit_s = (ch->vdiv * ch->vfactor) >= 500 ? "V" : "mV";
|
||||
g_string_append_printf(header, " %s (Unit: %s),", ch->name, unit_s);
|
||||
} else {
|
||||
g_string_append_printf(header, " %s,", ch->name);
|
||||
}
|
||||
}
|
||||
if (o->sdi->channels)
|
||||
/* Drop last separator. */
|
||||
@ -152,12 +178,13 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p
|
||||
{
|
||||
const struct sr_datafeed_meta *meta;
|
||||
const struct sr_datafeed_logic *logic;
|
||||
const struct sr_datafeed_dso *dso;
|
||||
const struct sr_config *src;
|
||||
GSList *l;
|
||||
struct context *ctx;
|
||||
int idx;
|
||||
uint64_t i, j;
|
||||
gchar *p, c;
|
||||
unsigned char *p, c;
|
||||
|
||||
*out = NULL;
|
||||
if (!o || !o->sdi)
|
||||
@ -200,6 +227,28 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p
|
||||
ctx->pre_data = (*(uint64_t *)(logic->data + i) & ctx->mask);
|
||||
}
|
||||
break;
|
||||
case SR_DF_DSO:
|
||||
dso = packet->payload;
|
||||
if (!ctx->header_done) {
|
||||
*out = gen_header(o);
|
||||
ctx->header_done = TRUE;
|
||||
} else {
|
||||
*out = g_string_sized_new(512);
|
||||
}
|
||||
|
||||
for (i = 0; i < dso->num_samples; i++) {
|
||||
for (j = 0; j < ctx->num_enabled_channels; j++) {
|
||||
idx = ctx->channel_index[j];
|
||||
p = dso->data + i * ctx->num_enabled_channels + idx * ((ctx->num_enabled_channels > 1) ? 1 : 0);
|
||||
g_string_append_printf(*out, "%0.2f", (128 - *p) * ctx->channel_vdiv[j] / 255 - ctx->channel_vpos[j]);
|
||||
g_string_append_c(*out, ctx->separator);
|
||||
}
|
||||
|
||||
/* Drop last separator. */
|
||||
g_string_truncate(*out, (*out)->len - 1);
|
||||
g_string_append_printf(*out, "\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
|
@ -141,6 +141,7 @@ SR_API char *sr_iec_string_u64(uint64_t x, const char *unit);
|
||||
SR_API char *sr_samplerate_string(uint64_t samplerate);
|
||||
SR_API char *sr_samplecount_string(uint64_t samplecount);
|
||||
SR_API char *sr_period_string(uint64_t frequency);
|
||||
SR_API char *sr_time_string(uint64_t time);
|
||||
SR_API char *sr_voltage_string(uint64_t v_p, uint64_t v_q);
|
||||
SR_API char **sr_parse_triggerstring(const struct sr_dev_inst *sdi,
|
||||
const char *triggerstring);
|
||||
|
@ -211,6 +211,47 @@ SR_API char *sr_period_string(uint64_t frequency)
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a numeric time(ns) value to the "natural" string representation
|
||||
* of its period.
|
||||
*
|
||||
* E.g. a value of 3000000 would be converted to "3 ms", 20000 to "20 us".
|
||||
*
|
||||
* @param time The time in ns.
|
||||
*
|
||||
* @return A g_try_malloc()ed string representation of the time value,
|
||||
* or NULL upon errors. The caller is responsible to g_free() the
|
||||
* memory.
|
||||
*/
|
||||
SR_API char *sr_time_string(uint64_t time)
|
||||
{
|
||||
char *o;
|
||||
int r;
|
||||
|
||||
/* Allocate enough for a uint64_t as string + " ms". */
|
||||
if (!(o = g_try_malloc0(30 + 1))) {
|
||||
sr_err("%s: o malloc failed", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (time >= 1000000000)
|
||||
r = snprintf(o, 30, "%" PRIu64 " s", time / 1000000000);
|
||||
else if (time >= 1000000)
|
||||
r = snprintf(o, 30, "%" PRIu64 " ms", time / 1000000);
|
||||
else if (time >= 1000)
|
||||
r = snprintf(o, 30, "%" PRIu64 " us", time / 1000);
|
||||
else
|
||||
r = snprintf(o, 30, "%" PRIu64 " ns", time);
|
||||
|
||||
if (r < 0) {
|
||||
/* Something went wrong... */
|
||||
g_free(o);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a numeric voltage value to the "natural" string representation
|
||||
* of its voltage value. The voltage is specified as a rational number's
|
||||
|
Loading…
x
Reference in New Issue
Block a user