From a2a326f0d2c51e6f60db407638209bd8e8aad7c7 Mon Sep 17 00:00:00 2001 From: DreamSourceLab Date: Wed, 16 May 2018 17:04:11 +0800 Subject: [PATCH] Add file save/load and export support for DAQ mode Fix file save/load and export issue --- DSView/pv/data/analogsnapshot.cpp | 45 ++++++-- DSView/pv/data/analogsnapshot.h | 12 ++- DSView/pv/data/dsosnapshot.cpp | 22 ++++ DSView/pv/data/dsosnapshot.h | 6 ++ DSView/pv/data/logicsnapshot.h | 7 +- DSView/pv/data/snapshot.cpp | 7 ++ DSView/pv/data/snapshot.h | 6 ++ DSView/pv/dialogs/storeprogress.cpp | 2 +- DSView/pv/storesession.cpp | 159 ++++++++++++++++++++++------ libsigrok4DSL/hardware/DSL/dscope.c | 1 - libsigrok4DSL/hardware/DSL/dsl.c | 2 +- libsigrok4DSL/hardware/demo/demo.c | 3 +- libsigrok4DSL/hwdriver.c | 4 +- libsigrok4DSL/libsigrok-internal.h | 2 - libsigrok4DSL/libsigrok.h | 2 +- libsigrok4DSL/output/csv.c | 82 +++++++++----- libsigrok4DSL/proto.h | 2 + libsigrok4DSL/session_driver.c | 67 ++++++++++-- libsigrok4DSL/session_file.c | 25 +++++ 19 files changed, 363 insertions(+), 93 deletions(-) diff --git a/DSView/pv/data/analogsnapshot.cpp b/DSView/pv/data/analogsnapshot.cpp index 415329f8..088d4907 100644 --- a/DSView/pv/data/analogsnapshot.cpp +++ b/DSView/pv/data/analogsnapshot.cpp @@ -46,11 +46,10 @@ const float AnalogSnapshot::LogEnvelopeScaleFactor = const uint64_t AnalogSnapshot::EnvelopeDataUnit = 64*1024; // bytes AnalogSnapshot::AnalogSnapshot() : - Snapshot(sizeof(uint16_t), 1, 1), - _unit_bytes(1), - _unit_pitch(0) + Snapshot(sizeof(uint16_t), 1, 1) { memset(_envelope_levels, 0, sizeof(_envelope_levels)); + _unit_pitch = 0; } AnalogSnapshot::~AnalogSnapshot() @@ -150,7 +149,9 @@ void AnalogSnapshot::first_payload(const sr_datafeed_analog &analog, uint64_t to for (const GSList *l = channels; l; l = l->next) { sr_channel *const probe = (sr_channel*)l->data; assert(probe); - if (probe->type == SR_CHANNEL_ANALOG && probe->enabled) { + // TODO: data of disabled channels should not be captured. + //if (probe->type == SR_CHANNEL_ANALOG && probe->enabled) { + if (probe->type == SR_CHANNEL_ANALOG) { _ch_index.push_back(probe->index); } } @@ -369,15 +370,41 @@ int AnalogSnapshot::get_ch_order(int sig_index) return order; } -uint8_t AnalogSnapshot::get_unit_bytes() const -{ - return _unit_bytes; -} - int AnalogSnapshot::get_scale_factor() const { return EnvelopeScaleFactor; } +bool AnalogSnapshot::has_data(int index) +{ + for (auto& iter:_ch_index) { + if (iter == index) + return true; + } + return false; +} + +int AnalogSnapshot::get_block_num() +{ + const uint64_t size = _sample_count * get_unit_bytes() * get_channel_num(); + return (size >> LeafBlockPower) + + ((size & LeafMask) != 0); +} + +uint64_t AnalogSnapshot::get_block_size(int block_index) +{ + assert(block_index < get_block_num()); + + if (block_index < get_block_num() - 1) { + return LeafBlockSamples; + } else { + const uint64_t size = _sample_count * get_unit_bytes() * get_channel_num(); + if (size % LeafBlockSamples == 0) + return LeafBlockSamples; + else + return size % LeafBlockSamples; + } +} + } // namespace data } // namespace pv diff --git a/DSView/pv/data/analogsnapshot.h b/DSView/pv/data/analogsnapshot.h index a4811a08..25d1c0d6 100644 --- a/DSView/pv/data/analogsnapshot.h +++ b/DSView/pv/data/analogsnapshot.h @@ -77,6 +77,10 @@ private: static const float LogEnvelopeScaleFactor; static const uint64_t EnvelopeDataUnit; + static const uint64_t LeafBlockPower = 21; + static const uint64_t LeafBlockSamples = 1 << LeafBlockPower; + static const uint64_t LeafMask = ~(~0ULL << LeafBlockPower); + public: AnalogSnapshot(); @@ -97,10 +101,12 @@ public: int get_ch_order(int sig_index); - uint8_t get_unit_bytes() const; - int get_scale_factor() const; + bool has_data(int index); + int get_block_num(); + uint64_t get_block_size(int block_index); + private: void append_data(void *data, uint64_t samples, uint16_t pitch); void free_envelop(); @@ -111,8 +117,6 @@ private: private: struct Envelope _envelope_levels[DS_MAX_ANALOG_PROBES_NUM][ScaleStepCount]; - uint8_t _unit_bytes; - uint16_t _unit_pitch; friend class AnalogSnapshotTest::Basic; }; diff --git a/DSView/pv/data/dsosnapshot.cpp b/DSView/pv/data/dsosnapshot.cpp index 05227cb3..f90b8e71 100644 --- a/DSView/pv/data/dsosnapshot.cpp +++ b/DSView/pv/data/dsosnapshot.cpp @@ -415,5 +415,27 @@ bool DsoSnapshot::has_data(int index) return false; } +int DsoSnapshot::get_block_num() +{ + const uint64_t size = _sample_count * get_unit_bytes() * get_channel_num(); + return (size >> LeafBlockPower) + + ((size & LeafMask) != 0); +} + +uint64_t DsoSnapshot::get_block_size(int block_index) +{ + assert(block_index < get_block_num()); + + if (block_index < get_block_num() - 1) { + return LeafBlockSamples; + } else { + const uint64_t size = _sample_count * get_unit_bytes() * get_channel_num(); + if (size % LeafBlockSamples == 0) + return LeafBlockSamples; + else + return size % LeafBlockSamples; + } +} + } // namespace data } // namespace pv diff --git a/DSView/pv/data/dsosnapshot.h b/DSView/pv/data/dsosnapshot.h index 5e33eca7..7b56c47a 100644 --- a/DSView/pv/data/dsosnapshot.h +++ b/DSView/pv/data/dsosnapshot.h @@ -68,6 +68,10 @@ private: static const float LogEnvelopeScaleFactor; static const uint64_t EnvelopeDataUnit; + static const uint64_t LeafBlockPower = 21; + static const uint64_t LeafBlockSamples = 1 << LeafBlockPower; + static const uint64_t LeafMask = ~(~0ULL << LeafBlockPower); + static const int VrmsScaleFactor; public: @@ -94,6 +98,8 @@ public: double cal_vmean(int index) const; bool has_data(int index); + int get_block_num(); + uint64_t get_block_size(int block_index); private: void append_data(void *data, uint64_t samples, bool instant); diff --git a/DSView/pv/data/logicsnapshot.h b/DSView/pv/data/logicsnapshot.h index 496fd27c..bfbf0b78 100644 --- a/DSView/pv/data/logicsnapshot.h +++ b/DSView/pv/data/logicsnapshot.h @@ -55,12 +55,13 @@ private: static const uint64_t RootScale = 1 << RootScalePower; static const uint64_t LeafBlockSpace = (Scale + Scale*Scale + Scale*Scale*Scale + Scale*Scale*Scale*Scale) / 8; - static const uint64_t LeafBlockSamples = 1 << ScaleLevel*ScalePower; + static const uint64_t LeafBlockPower = ScaleLevel*ScalePower; + static const uint64_t LeafBlockSamples = 1 << LeafBlockPower; static const uint64_t RootNodeSamples = LeafBlockSamples*RootScale; - static const uint64_t RootMask = ~(~0ULL << RootScalePower) << ScaleLevel*ScalePower; - static const uint64_t LeafMask = ~(~0ULL << ScaleLevel*ScalePower); + static const uint64_t RootMask = ~(~0ULL << RootScalePower) << LeafBlockPower; + static const uint64_t LeafMask = ~(~0ULL << LeafBlockPower); static const uint64_t LevelMask[ScaleLevel]; static const uint64_t LevelOffset[ScaleLevel]; diff --git a/DSView/pv/data/snapshot.cpp b/DSView/pv/data/snapshot.cpp index 46683579..50a094d0 100644 --- a/DSView/pv/data/snapshot.cpp +++ b/DSView/pv/data/snapshot.cpp @@ -46,6 +46,8 @@ Snapshot::Snapshot(int unit_size, uint64_t total_sample_count, unsigned int chan _last_ended(true) { assert(_unit_size > 0); + _unit_bytes = 1; + _unit_pitch = 0; } Snapshot::~Snapshot() @@ -123,6 +125,11 @@ int Snapshot::unit_size() const return _unit_size; } +uint8_t Snapshot::get_unit_bytes() const +{ + return _unit_bytes; +} + unsigned int Snapshot::get_channel_num() const { return _channel_num; diff --git a/DSView/pv/data/snapshot.h b/DSView/pv/data/snapshot.h index 07d788f7..5ea70a9a 100644 --- a/DSView/pv/data/snapshot.h +++ b/DSView/pv/data/snapshot.h @@ -45,6 +45,7 @@ public: const void * get_data() const; int unit_size() const; + uint8_t get_unit_bytes() const; bool memory_failed() const; bool empty() const; @@ -55,6 +56,9 @@ public: unsigned int get_channel_num() const; virtual void capture_ended(); + virtual bool has_data(int index) = 0; + virtual int get_block_num() = 0; + virtual uint64_t get_block_size(int block_index) = 0; protected: virtual void free_data(); @@ -72,6 +76,8 @@ protected: uint64_t _total_sample_count; uint64_t _ring_sample_count; int _unit_size; + uint8_t _unit_bytes; + uint16_t _unit_pitch; bool _memory_failed; bool _last_ended; }; diff --git a/DSView/pv/dialogs/storeprogress.cpp b/DSView/pv/dialogs/storeprogress.cpp index a03beb1a..fc01b217 100644 --- a/DSView/pv/dialogs/storeprogress.cpp +++ b/DSView/pv/dialogs/storeprogress.cpp @@ -39,7 +39,7 @@ StoreProgress::StoreProgress(SigSession &session, QWidget *parent) : _progress.setValue(0); _progress.setMaximum(100); - QVBoxLayout* add_layout = new QVBoxLayout(this); + QVBoxLayout* add_layout = new QVBoxLayout(); add_layout->addWidget(&_info, 0, Qt::AlignCenter); add_layout->addWidget(&_progress); add_layout->addWidget(&_button_box); diff --git a/DSView/pv/storesession.cpp b/DSView/pv/storesession.cpp index 8518fd58..998e8101 100644 --- a/DSView/pv/storesession.cpp +++ b/DSView/pv/storesession.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -101,7 +102,8 @@ QList StoreSession::getSuportedExportFormats(){ while(*supportedModules){ if(*supportedModules == NULL) break; - if (_session.get_device()->dev_inst()->mode == DSO && strcmp((*supportedModules)->id, "csv")) + if (_session.get_device()->dev_inst()->mode != LOGIC && + strcmp((*supportedModules)->id, "csv")) break; QString format((*supportedModules)->desc); format.append(" (*."); @@ -233,10 +235,38 @@ void StoreSession::save_proc(shared_ptr snapshot) break; } if (ch_type != -1) { - uint64_t size = snapshot->get_sample_count() * snapshot->get_channel_num(); - uint8_t *buf = (uint8_t *)snapshot->get_data(); - sr_session_append(_file_name.toLocal8Bit().data(), buf, size, - 0, 0, ch_type, 1); + const int num = snapshot->get_block_num(); + _unit_count = snapshot->get_sample_count() * + snapshot->get_unit_bytes() * + snapshot->get_channel_num(); + uint8_t *buf = (uint8_t *)snapshot->get_data() + + (snapshot->get_ring_start() * snapshot->get_unit_bytes() * snapshot->get_channel_num()); + const uint8_t *buf_start = (uint8_t *)snapshot->get_data(); + const uint8_t *buf_end = buf_start + _unit_count; + + for (int i = 0; !boost::this_thread::interruption_requested() && i < num; i++) { + const uint64_t size = snapshot->get_block_size(i); + if ((buf + size) > buf_end) { + uint8_t *tmp = (uint8_t *)malloc(size); + if (tmp == NULL) { + _has_error = true; + _error = tr("Malloc failed."); + return; + } + memcpy(tmp, buf, buf_end-buf); + memcpy(tmp+(buf_end-buf), buf_start, buf+size-buf_end); + sr_session_append(_file_name.toLocal8Bit().data(), tmp, size, + i, 0, ch_type, File_Version); + buf += (size - _unit_count); + free(tmp); + } else { + sr_session_append(_file_name.toLocal8Bit().data(), buf, size, + i, 0, ch_type, File_Version); + buf += size; + } + _units_stored += size; + progress_updated(); + } } } @@ -276,10 +306,11 @@ QString StoreSession::meta_gen(boost::shared_ptr snapshot) } fprintf(meta, "[version]\n"); - if (sdi->mode == DSO) - fprintf(meta, "version = %d\n", 1); // should be updated in next version - else - fprintf(meta, "version = %d\n", File_Version); +// if (sdi->mode != LOGIC) +// fprintf(meta, "version = %d\n", 1); // should be updated in next version +// else +// fprintf(meta, "version = %d\n", File_Version); + fprintf(meta, "version = %d\n", File_Version); /* metadata */ @@ -293,8 +324,10 @@ QString StoreSession::meta_gen(boost::shared_ptr snapshot) fprintf(meta, "capturefile = data\n"); fprintf(meta, "total samples = %" PRIu64 "\n", snapshot->get_sample_count()); - if (sdi->mode == DSO) - fprintf(meta, "total probes = %d\n", g_slist_length(sdi->channels)); + if (sdi->mode != LOGIC) { + fprintf(meta, "total probes = %d\n", snapshot->get_channel_num()); + fprintf(meta, "total blocks = %d\n", snapshot->get_block_num()); + } shared_ptr logic_snapshot; if (logic_snapshot = dynamic_pointer_cast(snapshot)) { @@ -326,37 +359,51 @@ QString StoreSession::meta_gen(boost::shared_ptr snapshot) } } else if (sdi->mode == LOGIC) { fprintf(meta, "trigger time = %lld\n", _session.get_trigger_time().toMSecsSinceEpoch()); + } else if (sdi->mode == ANALOG) { + shared_ptr analog_snapshot; + if (analog_snapshot = dynamic_pointer_cast(snapshot)) { + uint8_t tmp_u8 = analog_snapshot->get_unit_bytes(); + fprintf(meta, "bits = %d\n", tmp_u8*8); + } } fprintf(meta, "trigger pos = %" PRIu64 "\n", _session.get_trigger_pos()); - probecnt = 1; + probecnt = 0; for (l = sdi->channels; l; l = l->next) { probe = (struct sr_channel *)l->data; - if (probe->enabled || sdi->mode == DSO) { + if (snapshot->has_data(probe->index)) { if (probe->name) - fprintf(meta, "probe%d = %s\n", probe->index, probe->name); + fprintf(meta, "probe%d = %s\n", probecnt, probe->name); if (probe->trigger) - fprintf(meta, " trigger%d = %s\n", probe->index, probe->trigger); + fprintf(meta, " trigger%d = %s\n", probecnt, probe->trigger); if (sdi->mode == DSO) { - fprintf(meta, " enable%d = %d\n", probe->index, probe->enabled); - fprintf(meta, " coupling%d = %d\n", probe->index, probe->coupling); - fprintf(meta, " vDiv%d = %" PRIu64 "\n", probe->index, probe->vdiv); - fprintf(meta, " vFactor%d = %d\n", probe->index, probe->vfactor); - fprintf(meta, " vPos%d = %lf\n", probe->index, probe->vpos); - fprintf(meta, " vTrig%d = %d\n", probe->index, probe->trig_value); + fprintf(meta, " enable%d = %d\n", probecnt, probe->enabled); + fprintf(meta, " coupling%d = %d\n", probecnt, probe->coupling); + fprintf(meta, " vDiv%d = %" PRIu64 "\n", probecnt, probe->vdiv); + fprintf(meta, " vFactor%d = %d\n", probecnt, probe->vfactor); + fprintf(meta, " vPos%d = %lf\n", probecnt, probe->vpos); + fprintf(meta, " vTrig%d = %d\n", probecnt, probe->trig_value); if (sr_status_get(sdi, &status, false, 0, 0) == SR_OK) { if (probe->index == 0) { - fprintf(meta, " period%d = %" PRIu64 "\n", probe->index, status.ch0_period); - fprintf(meta, " pcnt%d = %" PRIu32 "\n", probe->index, status.ch0_pcnt); - fprintf(meta, " max%d = %d\n", probe->index, status.ch0_max); - fprintf(meta, " min%d = %d\n", probe->index, status.ch0_min); + fprintf(meta, " period%d = %" PRIu64 "\n", probecnt, status.ch0_period); + fprintf(meta, " pcnt%d = %" PRIu32 "\n", probecnt, status.ch0_pcnt); + fprintf(meta, " max%d = %d\n", probecnt, status.ch0_max); + fprintf(meta, " min%d = %d\n", probecnt, status.ch0_min); } else { - fprintf(meta, " period%d = %" PRIu64 "\n", probe->index, status.ch1_period); - fprintf(meta, " pcnt%d = %" PRIu32 "\n", probe->index, status.ch1_pcnt); - fprintf(meta, " max%d = %d\n", probe->index, status.ch1_max); - fprintf(meta, " min%d = %d\n", probe->index, status.ch1_min); + fprintf(meta, " period%d = %" PRIu64 "\n", probecnt, status.ch1_period); + fprintf(meta, " pcnt%d = %" PRIu32 "\n", probecnt, status.ch1_pcnt); + fprintf(meta, " max%d = %d\n", probecnt, status.ch1_max); + fprintf(meta, " min%d = %d\n", probecnt, status.ch1_min); } } + } else if (sdi->mode == ANALOG) { + fprintf(meta, " enable%d = %d\n", probecnt, probe->enabled); + fprintf(meta, " coupling%d = %d\n", probecnt, probe->coupling); + fprintf(meta, " vDiv%d = %" PRIu64 "\n", probecnt, probe->vdiv); + fprintf(meta, " vPos%d = %lf\n", probecnt, probe->vpos); + fprintf(meta, " mapUnit%d = %s\n", probecnt, probe->map_unit); + fprintf(meta, " mapMax%d = %lf\n", probecnt, probe->map_max); + fprintf(meta, " mapMin%d = %lf\n", probecnt, probe->map_min); } probecnt++; } @@ -450,6 +497,8 @@ void StoreSession::export_proc(shared_ptr snapshot) channel_type = SR_CHANNEL_LOGIC; } else if (dso_snapshot = boost::dynamic_pointer_cast(snapshot)) { channel_type = SR_CHANNEL_DSO; + } else if (analog_snapshot = boost::dynamic_pointer_cast(snapshot)) { + channel_type = SR_CHANNEL_ANALOG; } else { _has_error = true; _error = tr("data type don't support."); @@ -482,6 +531,31 @@ void StoreSession::export_proc(shared_ptr snapshot) out.setCodec("UTF-8"); out.setGenerateByteOrderMark(true); + // Meta + GString *data_out; + struct sr_datafeed_packet p; + struct sr_datafeed_meta meta; + struct sr_config *src; + src = sr_config_new(SR_CONF_SAMPLERATE, + g_variant_new_uint64(_session.cur_samplerate())); + meta.config = g_slist_append(NULL, src); + src = sr_config_new(SR_CONF_LIMIT_SAMPLES, + g_variant_new_uint64(snapshot->get_sample_count())); + meta.config = g_slist_append(meta.config, src); + p.type = SR_DF_META; + p.status = SR_PKT_OK; + p.payload = &meta; + _outModule->receive(&output, &p, &data_out); + if(data_out){ + out << QString::fromUtf8((char*) data_out->str); + g_string_free(data_out,TRUE); + } + for (GSList *l = meta.config; l; l = l->next) { + src = (struct sr_config *)l->data; + sr_config_free(src); + } + g_slist_free(meta.config); + if (channel_type == SR_CHANNEL_LOGIC) { _unit_count = logic_snapshot->get_sample_count(); int blk_num = logic_snapshot->get_block_num(); @@ -506,11 +580,9 @@ void StoreSession::export_proc(shared_ptr snapshot) } uint16_t unitsize = ceil(buf_vec.size() / 8.0); - GString *data_out; unsigned int usize = 8192; unsigned int size = usize; struct sr_datafeed_logic lp; - struct sr_datafeed_packet p; for(uint64_t i = 0; !boost::this_thread::interruption_requested() && i < buf_sample_num; i+=usize){ if(buf_sample_num - i < usize) @@ -551,11 +623,9 @@ void StoreSession::export_proc(shared_ptr snapshot) } else if (channel_type == SR_CHANNEL_DSO) { _unit_count = snapshot->get_sample_count(); unsigned char* datat = (unsigned char*)snapshot->get_data(); - GString *data_out; unsigned int usize = 8192; unsigned int size = usize; struct sr_datafeed_dso dp; - struct sr_datafeed_packet p; for(uint64_t i = 0; !boost::this_thread::interruption_requested() && i < _unit_count; i+=usize){ if(_unit_count - i < usize) size = _unit_count - i; @@ -570,6 +640,29 @@ void StoreSession::export_proc(shared_ptr snapshot) g_string_free(data_out,TRUE); } + _units_stored += size; + progress_updated(); + } + } else if (channel_type == SR_CHANNEL_ANALOG) { + _unit_count = snapshot->get_sample_count(); + unsigned char* datat = (unsigned char*)snapshot->get_data(); + unsigned int usize = 8192; + unsigned int size = usize; + struct sr_datafeed_analog ap; + for(uint64_t i = 0; !boost::this_thread::interruption_requested() && i < _unit_count; i+=usize){ + if(_unit_count - i < usize) + size = _unit_count - i; + ap.data = &datat[i*snapshot->get_channel_num()]; + ap.num_samples = size; + p.type = SR_DF_ANALOG; + p.status = SR_PKT_OK; + p.payload = ≈ + _outModule->receive(&output, &p, &data_out); + if(data_out){ + out << (char*) data_out->str; + g_string_free(data_out,TRUE); + } + _units_stored += size; progress_updated(); } diff --git a/libsigrok4DSL/hardware/DSL/dscope.c b/libsigrok4DSL/hardware/DSL/dscope.c index 319a25bb..ac2cd127 100644 --- a/libsigrok4DSL/hardware/DSL/dscope.c +++ b/libsigrok4DSL/hardware/DSL/dscope.c @@ -123,7 +123,6 @@ static const char *probeMapUnits[] = { "g", "m", "m/s", - "Custom", }; static const uint64_t samplerates[] = { diff --git a/libsigrok4DSL/hardware/DSL/dsl.c b/libsigrok4DSL/hardware/DSL/dsl.c index 85638499..985b25f2 100755 --- a/libsigrok4DSL/hardware/DSL/dsl.c +++ b/libsigrok4DSL/hardware/DSL/dsl.c @@ -1342,7 +1342,7 @@ static void receive_transfer(struct libusb_transfer *transfer) analog.mq = SR_MQ_VOLTAGE; analog.unit = SR_UNIT_VOLT; analog.mqflags = SR_MQFLAG_AC; - analog.data = (float *)cur_buf; + analog.data = cur_buf; } if ((devc->limit_samples && devc->num_bytes < devc->actual_bytes) || diff --git a/libsigrok4DSL/hardware/demo/demo.c b/libsigrok4DSL/hardware/demo/demo.c index 9bb507ab..18c7a9b7 100644 --- a/libsigrok4DSL/hardware/demo/demo.c +++ b/libsigrok4DSL/hardware/demo/demo.c @@ -187,7 +187,6 @@ static const char *probeMapUnits[] = { "g", "m", "m/s", - "Custom", }; static const int const_dc = 1.95 / 10 * 255; @@ -1162,7 +1161,7 @@ static int receive_data(int fd, int revents, const struct sr_dev_inst *sdi) analog.mq = SR_MQ_VOLTAGE; analog.unit = SR_UNIT_VOLT; analog.mqflags = SR_MQFLAG_AC; - analog.data = (float *)devc->buf; + analog.data = devc->buf; } if (sdi->mode == DSO && !devc->instant) { diff --git a/libsigrok4DSL/hwdriver.c b/libsigrok4DSL/hwdriver.c index 68f7ea28..faf5ab5e 100644 --- a/libsigrok4DSL/hwdriver.c +++ b/libsigrok4DSL/hwdriver.c @@ -252,7 +252,7 @@ SR_PRIV void sr_hw_cleanup_all(void) } /** A floating reference can be passed in for data. */ -SR_PRIV struct sr_config *sr_config_new(int key, GVariant *data) +SR_API struct sr_config *sr_config_new(int key, GVariant *data) { struct sr_config *src; @@ -264,7 +264,7 @@ SR_PRIV struct sr_config *sr_config_new(int key, GVariant *data) return src; } -SR_PRIV void sr_config_free(struct sr_config *src) +SR_API void sr_config_free(struct sr_config *src) { if (!src || !src->data) { diff --git a/libsigrok4DSL/libsigrok-internal.h b/libsigrok4DSL/libsigrok-internal.h index a201548c..de86db20 100644 --- a/libsigrok4DSL/libsigrok-internal.h +++ b/libsigrok4DSL/libsigrok-internal.h @@ -109,8 +109,6 @@ SR_PRIV void sr_serial_dev_inst_free(struct sr_serial_dev_inst *serial); /*--- hwdriver.c ------------------------------------------------------------*/ SR_PRIV void sr_hw_cleanup_all(void); -SR_PRIV struct sr_config *sr_config_new(int key, GVariant *data); -SR_PRIV void sr_config_free(struct sr_config *src); SR_PRIV int sr_source_remove(int fd); SR_PRIV int sr_source_add(int fd, int events, int timeout, sr_receive_data_callback_t cb, void *cb_data); diff --git a/libsigrok4DSL/libsigrok.h b/libsigrok4DSL/libsigrok.h index eab601e5..c0921e9f 100644 --- a/libsigrok4DSL/libsigrok.h +++ b/libsigrok4DSL/libsigrok.h @@ -379,7 +379,7 @@ struct sr_datafeed_analog { uint64_t mqflags; /** The analog value(s). The data is interleaved according to * the probes list. */ - float *data; + void *data; }; /** Input (file) format struct. */ diff --git a/libsigrok4DSL/output/csv.c b/libsigrok4DSL/output/csv.c index bb48873e..0090c9c9 100644 --- a/libsigrok4DSL/output/csv.c +++ b/libsigrok4DSL/output/csv.c @@ -30,11 +30,14 @@ struct context { unsigned int num_enabled_channels; uint64_t samplerate; + uint64_t limit_samples; char separator; gboolean header_done; int *channel_index; float *channel_vdiv; double *channel_vpos; + double *channel_mmin; + double *channel_mmax; uint64_t timebase; uint64_t mask; uint64_t pre_data; @@ -84,6 +87,8 @@ static int init(struct sr_output *o, GHashTable *options) 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); + ctx->channel_mmax = g_malloc(sizeof(double) * ctx->num_enabled_channels); + ctx->channel_mmin = 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) { @@ -97,6 +102,8 @@ static int init(struct sr_output *o, GHashTable *options) ctx->mask |= (1 << i); 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; + ctx->channel_mmax[i] = ch->map_max; + ctx->channel_mmin[i] = ch->map_min; i++; } @@ -107,7 +114,6 @@ static GString *gen_header(const struct sr_output *o) { struct context *ctx; struct sr_channel *ch; - GVariant *gvar; GString *header; GSList *l; time_t t; @@ -129,27 +135,28 @@ static GString *gen_header(const struct sr_output *o) g_string_append_printf(header, "; Channels (%d/%d)\n", ctx->num_enabled_channels, num_channels); - if (ctx->samplerate == 0) { - if (sr_config_get(o->sdi->driver, o->sdi, NULL, NULL, SR_CONF_SAMPLERATE, - &gvar) == SR_OK) { - ctx->samplerate = g_variant_get_uint64(gvar); - g_variant_unref(gvar); - } - } - if (ctx->samplerate != 0) { - char *samplerate_s = sr_samplerate_string(ctx->samplerate); - g_string_append_printf(header, "; Sample rate: %s\n", samplerate_s); - g_free(samplerate_s); - } +// if (ctx->samplerate == 0) { +// if (sr_config_get(o->sdi->driver, o->sdi, NULL, NULL, SR_CONF_SAMPLERATE, +// &gvar) == SR_OK) { +// ctx->samplerate = g_variant_get_uint64(gvar); +// g_variant_unref(gvar); +// } +// } + char *samplerate_s = sr_samplerate_string(ctx->samplerate); + g_string_append_printf(header, "; Sample rate: %s\n", samplerate_s); + g_free(samplerate_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 (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); +// } + char *depth_s = sr_samplecount_string(ctx->limit_samples); + 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),"); @@ -162,6 +169,8 @@ static GString *gen_header(const struct sr_output *o) 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 if (ctx->type == SR_CHANNEL_ANALOG) { + g_string_append_printf(header, " %s (Unit: %s),", ch->name, ch->map_unit); } else { g_string_append_printf(header, " %s,", ch->name); } @@ -180,6 +189,7 @@ 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_datafeed_analog *analog; const struct sr_config *src; GSList *l; struct context *ctx; @@ -198,9 +208,10 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p meta = packet->payload; for (l = meta->config; l; l = l->next) { src = l->data; - if (src->key != SR_CONF_SAMPLERATE) - continue; - ctx->samplerate = g_variant_get_uint64(src->data); + if (src->key == SR_CONF_SAMPLERATE) + ctx->samplerate = g_variant_get_uint64(src->data); + else if (src->key == SR_CONF_LIMIT_SAMPLES) + ctx->limit_samples = g_variant_get_uint64(src->data); } break; case SR_DF_LOGIC: @@ -251,6 +262,29 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p g_string_append_printf(*out, "\n"); } break; + case SR_DF_ANALOG: + analog = 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 < (uint64_t)analog->num_samples; i++) { + for (j = 0; j < ctx->num_enabled_channels; j++) { + idx = ctx->channel_index[j]; + p = analog->data + i * ctx->num_enabled_channels + idx * ((ctx->num_enabled_channels > 1) ? 1 : 0); + g_string_append_printf(*out, "%0.2f", + ctx->channel_mmin[j] + (255.0 - *p) / 255.0 * (ctx->channel_mmax[j] - ctx->channel_mmin[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; diff --git a/libsigrok4DSL/proto.h b/libsigrok4DSL/proto.h index f1a406a0..3107da7a 100644 --- a/libsigrok4DSL/proto.h +++ b/libsigrok4DSL/proto.h @@ -80,6 +80,8 @@ SR_API int sr_config_list(const struct sr_dev_driver *driver, SR_API const struct sr_config_info *sr_config_info_get(int key); SR_API const struct sr_config_info *sr_config_info_name_get(const char *optname); SR_API int sr_status_get(const struct sr_dev_inst *sdi, struct sr_status *status, gboolean prg, int begin, int end); +SR_API struct sr_config *sr_config_new(int key, GVariant *data); +SR_API void sr_config_free(struct sr_config *src); /*--- session.c -------------------------------------------------------------*/ diff --git a/libsigrok4DSL/session_driver.c b/libsigrok4DSL/session_driver.c index 7eabd173..8019d8ff 100644 --- a/libsigrok4DSL/session_driver.c +++ b/libsigrok4DSL/session_driver.c @@ -88,6 +88,22 @@ static const int hwoptions[] = { SR_CONF_MAX_HEIGHT, }; +static const int32_t probeOptions[] = { + SR_CONF_PROBE_MAP_UNIT, + SR_CONF_PROBE_MAP_MIN, + SR_CONF_PROBE_MAP_MAX, +}; + +static const char *probeMapUnits[] = { + "V", + "A", + "°C", + "°F", + "g", + "m", + "m/s", +}; + static int trans_data(struct sr_dev_inst *sdi) { // translate for old format @@ -151,6 +167,7 @@ static int receive_data(int fd, int revents, const struct sr_dev_inst *cb_sdi) /* already done with this instance */ continue; + assert(vdev->unit_bits > 0); assert(vdev->cur_channel >= 0); if (vdev->cur_channel < vdev->num_probes) { if (vdev->version == 1) { @@ -167,7 +184,7 @@ static int receive_data(int fd, int revents, const struct sr_dev_inst *cb_sdi) (probe->type == SR_CHANNEL_DSO) ? "O" : (probe->type == SR_CHANNEL_ANALOG) ? "A" : "U"; snprintf(file_name, 31, "%s-%d/%d", type_name, - probe->index, vdev->cur_block); + sdi->mode == LOGIC ? probe->index : 0, vdev->cur_block); if (!(vdev->capfile = zip_fopen(vdev->archive, file_name, 0))) { sr_err("Failed to open capture file '%s' in " "session file '%s'.", file_name, vdev->sessionfile); @@ -191,7 +208,7 @@ static int receive_data(int fd, int revents, const struct sr_dev_inst *cb_sdi) if (sdi->mode == DSO) { packet.type = SR_DF_DSO; packet.payload = &dso; - dso.num_samples = ret / vdev->enabled_probes; + dso.num_samples = ret / vdev->num_probes; dso.data = vdev->buf; dso.probes = sdi->channels; dso.mq = SR_MQ_VOLTAGE; @@ -201,7 +218,7 @@ static int receive_data(int fd, int revents, const struct sr_dev_inst *cb_sdi) packet.type = SR_DF_ANALOG; packet.payload = &analog; analog.probes = sdi->channels; - analog.num_samples = ret / vdev->num_probes; + analog.num_samples = ret / vdev->num_probes / ((vdev->unit_bits + 7) / 8); analog.unit_bits = vdev->unit_bits; analog.mq = SR_MQ_VOLTAGE; analog.unit = SR_UNIT_VOLT; @@ -299,12 +316,7 @@ static int dev_open(struct sr_dev_inst *sdi) vdev->cur_channel = 0; vdev->file_opened = FALSE; vdev->num_blocks = 0; - if (sdi->mode == DSO) - vdev->unit_bits = 8; - else if (sdi->mode == ANALOG) - vdev->unit_bits = 16; - else - vdev->unit_bits = 1; + vdev->unit_bits = 1; vdev->max_height = 0; dev_insts = g_slist_append(dev_insts, sdi); @@ -401,6 +413,21 @@ static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi, } else return SR_ERR; break; + case SR_CONF_PROBE_MAP_UNIT: + if (!sdi || !ch) + return SR_ERR; + *data = g_variant_new_string(ch->map_unit); + break; + case SR_CONF_PROBE_MAP_MIN: + if (!sdi || !ch) + return SR_ERR; + *data = g_variant_new_double(ch->map_min); + break; + case SR_CONF_PROBE_MAP_MAX: + if (!sdi || !ch) + return SR_ERR; + *data = g_variant_new_double(ch->map_max); + break; case SR_CONF_TRIGGER_VALUE: if (sdi && ch) { *data = g_variant_new_byte(ch->trig_value); @@ -534,6 +561,15 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi, case SR_CONF_PROBE_VPOS: ch->vpos = g_variant_get_double(data); break; + case SR_CONF_PROBE_MAP_UNIT: + ch->map_unit = g_variant_get_string(data, NULL); + break; + case SR_CONF_PROBE_MAP_MIN: + ch->map_min = g_variant_get_double(data); + break; + case SR_CONF_PROBE_MAP_MAX: + ch->map_max = g_variant_get_double(data); + break; case SR_CONF_TRIGGER_VALUE: ch->trig_value = g_variant_get_byte(data); break; @@ -623,6 +659,14 @@ static int config_list(int key, GVariant **data, case SR_CONF_MAX_HEIGHT: *data = g_variant_new_strv(maxHeights, ARRAY_SIZE(maxHeights)); break; + + case SR_CONF_PROBE_CONFIGS: + *data = g_variant_new_from_data(G_VARIANT_TYPE("ai"), + probeOptions, ARRAY_SIZE(probeOptions)*sizeof(int32_t), TRUE, NULL, NULL); + break; + case SR_CONF_PROBE_MAP_UNIT: + *data = g_variant_new_strv(probeMapUnits, ARRAY_SIZE(probeMapUnits)); + break; default: return SR_ERR_ARG; } @@ -687,7 +731,10 @@ static int dev_acquisition_start(struct sr_dev_inst *sdi, vdev->file_opened = TRUE; vdev->cur_channel = vdev->num_probes - 1; } else { - vdev->cur_channel = 0; + if (sdi->mode == LOGIC) + vdev->cur_channel = 0; + else + vdev->cur_channel = vdev->num_probes - 1; } for (l = sdi->channels; l; l = l->next) { diff --git a/libsigrok4DSL/session_file.c b/libsigrok4DSL/session_file.c index ecfa36c6..5b14cc0c 100644 --- a/libsigrok4DSL/session_file.c +++ b/libsigrok4DSL/session_file.c @@ -267,6 +267,8 @@ SR_API int sr_session_load(const char *filename) probenum = strtoul(keys[j]+7, NULL, 10); sr_dev_trigger_set(sdi, probenum, val); } else if (!strncmp(keys[j], "enable", 6)) { + if (mode != LOGIC) + continue; probenum = strtoul(keys[j]+6, NULL, 10); tmp_u64 = strtoull(val, NULL, 10); if (probenum < g_slist_length(sdi->channels)) { @@ -346,6 +348,29 @@ SR_API int sr_session_load(const char *filename) sdi->driver->config_set(SR_CONF_STATUS_MIN, g_variant_new_uint64(tmp_u64), sdi, probe, NULL); } + } else if (!strncmp(keys[j], "mapUnit", 7)) { + probenum = strtoul(keys[j]+7, NULL, 10); + if (probenum < g_slist_length(sdi->channels)) { + probe = g_slist_nth(sdi->channels, probenum)->data; + sdi->driver->config_set(SR_CONF_PROBE_MAP_UNIT, + g_variant_new_string(val), sdi, probe, NULL); + } + } else if (!strncmp(keys[j], "mapMax", 6)) { + probenum = strtoul(keys[j]+6, NULL, 10); + tmp_double = strtod(val, NULL); + if (probenum < g_slist_length(sdi->channels)) { + probe = g_slist_nth(sdi->channels, probenum)->data; + sdi->driver->config_set(SR_CONF_PROBE_MAP_MAX, + g_variant_new_double(tmp_double), sdi, probe, NULL); + } + } else if (!strncmp(keys[j], "mapMin", 6)) { + probenum = strtoul(keys[j]+6, NULL, 10); + tmp_double = strtod(val, NULL); + if (probenum < g_slist_length(sdi->channels)) { + probe = g_slist_nth(sdi->channels, probenum)->data; + sdi->driver->config_set(SR_CONF_PROBE_MAP_MIN, + g_variant_new_double(tmp_double), sdi, probe, NULL); + } } } g_strfreev(keys);