Merge branch 'add_dso_export' into develop

Add data export(csv only) support @ DSO mode
This commit is contained in:
DreamSourceLab 2015-04-24 16:18:33 +08:00
commit 716c3fffb8
9 changed files with 204 additions and 54 deletions

View File

@ -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."),

View File

@ -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++){

View File

@ -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) {

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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