From 91f687eb264640cf212a12dac1cd94fec5f6fc91 Mon Sep 17 00:00:00 2001 From: Maximilian Rehkopf Date: Sat, 18 Jan 2025 20:13:42 +0100 Subject: [PATCH] feat: add external clock frequency configuration and handling --- DSView/pv/deviceagent.cpp | 25 ++++++++++- DSView/pv/deviceagent.h | 13 +++++- DSView/pv/prop/binding/deviceoptions.cpp | 4 ++ DSView/pv/toolbars/samplingbar.cpp | 7 ++- DSView/pv/toolbars/samplingbar.h | 2 + DSView/res/DSLogic0.def.dsc | 1 + libsigrok4DSL/hardware/DSL/dsl.c | 16 ++++--- libsigrok4DSL/hardware/DSL/dsl.h | 54 ++++++++++++------------ libsigrok4DSL/hardware/DSL/dslogic.c | 12 ++++++ libsigrok4DSL/hwdriver.c | 1 + libsigrok4DSL/libsigrok.h | 3 ++ 11 files changed, 102 insertions(+), 36 deletions(-) diff --git a/DSView/pv/deviceagent.cpp b/DSView/pv/deviceagent.cpp index 62ebf10eb..6db0e58b5 100644 --- a/DSView/pv/deviceagent.cpp +++ b/DSView/pv/deviceagent.cpp @@ -126,8 +126,15 @@ uint64_t DeviceAgent::get_sample_rate() uint64_t v; GVariant* gvar = NULL; - ds_get_actived_device_config(NULL, NULL, SR_CONF_SAMPLERATE, &gvar); + int key; + if(is_external_clock()) { + key = SR_CONF_EXT_SAMPLERATE; + } else { + key = SR_CONF_SAMPLERATE; + } + + ds_get_actived_device_config(NULL, NULL, key, &gvar); if (gvar != NULL) { v = g_variant_get_uint64(gvar); g_variant_unref(gvar); @@ -139,6 +146,22 @@ uint64_t DeviceAgent::get_sample_rate() return v; } +bool DeviceAgent::is_external_clock() +{ + assert(_dev_handle); + + bool ct = false; + GVariant* gvar = NULL; + + ds_get_actived_device_config(NULL, NULL, SR_CONF_CLOCK_TYPE, &gvar); + if (gvar != NULL) { + ct = g_variant_get_boolean(gvar); + g_variant_unref(gvar); + } + + return ct; +} + uint64_t DeviceAgent::get_time_base() { assert(_dev_handle); diff --git a/DSView/pv/deviceagent.h b/DSView/pv/deviceagent.h index ae9132d16..86ccbbfa9 100644 --- a/DSView/pv/deviceagent.h +++ b/DSView/pv/deviceagent.h @@ -113,7 +113,18 @@ class DeviceAgent */ uint64_t get_sample_rate(); - /** + /** + * @brief Checks if the device is using an external clock source + * + * This function determines whether the device is currently configured to use + * an external clock source for timing/sampling instead of its internal clock. + * + * @return true If the device is using an external clock source + * @return false If the device is using its internal clock source + */ + bool is_external_clock(); + + /** * @brief Gets the time base from the driver. * * @return The returned time base from the driver, or 0 if the diff --git a/DSView/pv/prop/binding/deviceoptions.cpp b/DSView/pv/prop/binding/deviceoptions.cpp index 643566021..3ad6812d4 100644 --- a/DSView/pv/prop/binding/deviceoptions.cpp +++ b/DSView/pv/prop/binding/deviceoptions.cpp @@ -118,6 +118,10 @@ DeviceOptions::DeviceOptions() bind_bool(name, label, key); break; + case SR_CONF_EXT_SAMPLERATE: + bind_int(name, label, key, "", pair(10000, 1000000000)); + break; + case SR_CONF_TIMEBASE: bind_enum(name, label, key, gvar_list, print_timebase); break; diff --git a/DSView/pv/toolbars/samplingbar.cpp b/DSView/pv/toolbars/samplingbar.cpp index d82a3b5b4..de32c7533 100644 --- a/DSView/pv/toolbars/samplingbar.cpp +++ b/DSView/pv/toolbars/samplingbar.cpp @@ -106,7 +106,8 @@ namespace pv addWidget(&_sample_count); //tr - addWidget(new QLabel(" @ ")); + _sample_at = new QLabel(" @ "); + addWidget(_sample_at); addWidget(&_sample_rate); _action_single = new QAction(this); @@ -427,6 +428,8 @@ namespace pv _sample_rate.setMinimumWidth(_sample_rate.sizeHint().width() + 15); _sample_rate.view()->setMinimumWidth(_sample_rate.sizeHint().width() + 30); + _sample_at->setText(_device_agent->is_external_clock() ? " @ ext." : " @ "); + _updating_sample_rate = false; g_variant_unref(gvar_dict); @@ -1055,7 +1058,7 @@ namespace pv _run_stop_action->setVisible(true); _instant_action->setVisible(true); } - + retranslateUi(); reStyle(); update(); diff --git a/DSView/pv/toolbars/samplingbar.h b/DSView/pv/toolbars/samplingbar.h index fde21696b..4e7169078 100644 --- a/DSView/pv/toolbars/samplingbar.h +++ b/DSView/pv/toolbars/samplingbar.h @@ -31,6 +31,7 @@ #include #include #include +#include #include "../ui/dscombobox.h" #include "../interface/icallbacks.h" #include "../ui/xtoolbutton.h" @@ -151,6 +152,7 @@ namespace pv DsComboBox _device_selector; XToolButton _configure_button; DsComboBox _sample_count; + QLabel *_sample_at; DsComboBox _sample_rate; XToolButton _run_stop_button; XToolButton _instant_button; diff --git a/DSView/res/DSLogic0.def.dsc b/DSView/res/DSLogic0.def.dsc index 85e990412..9fa2f032a 100644 --- a/DSView/res/DSLogic0.def.dsc +++ b/DSView/res/DSLogic0.def.dsc @@ -21,6 +21,7 @@ "Trigger source": 0, "Using Clock Negedge": 0, "Using External Clock": 0, + "Ext. Clock Frequency [Hz]": 1000000, "Version": 3, "channel": [ { diff --git a/libsigrok4DSL/hardware/DSL/dsl.c b/libsigrok4DSL/hardware/DSL/dsl.c index d80e59b0e..a91e173df 100644 --- a/libsigrok4DSL/hardware/DSL/dsl.c +++ b/libsigrok4DSL/hardware/DSL/dsl.c @@ -1778,13 +1778,17 @@ SR_PRIV int dsl_config_list(int key, GVariant **data, const struct sr_dev_inst * switch (key) { case SR_CONF_SAMPLERATE: + GVariant *list; + g_variant_builder_init(&gvb, G_VARIANT_TYPE("at")); + if(devc->clock_type) { + g_variant_builder_add(&gvb, "t", devc->ext_samplerate); + } + for(int i = devc->samplerates_min_index; i <= devc->samplerates_max_index; i++) { + g_variant_builder_add(&gvb, "t", devc->profile->dev_caps.samplerates[i]); + } + list = g_variant_builder_end(&gvb); g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}")); -// gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates, -// ARRAY_SIZE(samplerates), sizeof(uint64_t)); - gvar = g_variant_new_from_data(G_VARIANT_TYPE("at"), - devc->profile->dev_caps.samplerates + devc->samplerates_min_index, - (devc->samplerates_max_index - devc->samplerates_min_index + 1) * sizeof(uint64_t), TRUE, NULL, NULL); - g_variant_builder_add(&gvb, "{sv}", "samplerates", gvar); + g_variant_builder_add(&gvb, "{sv}", "samplerates", list); *data = g_variant_builder_end(&gvb); break; diff --git a/libsigrok4DSL/hardware/DSL/dsl.h b/libsigrok4DSL/hardware/DSL/dsl.h index b06dab646..0bc1231cc 100644 --- a/libsigrok4DSL/hardware/DSL/dsl.h +++ b/libsigrok4DSL/hardware/DSL/dsl.h @@ -368,63 +368,63 @@ struct DSL_channels { static const struct DSL_channels channel_modes[] = { // LA Stream - {DSL_STREAM20x16, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 16, 1, SR_KHZ(50), SR_MHZ(20), + {DSL_STREAM20x16, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 16, 1, SR_KHZ(10), SR_MHZ(20), SR_KHZ(10), SR_MHZ(100), 1, "Use 16 Channels (Max 20MHz)"}, - {DSL_STREAM25x12, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 12, 1, SR_KHZ(50), SR_MHZ(25), + {DSL_STREAM25x12, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 12, 1, SR_KHZ(10), SR_MHZ(25), SR_KHZ(10), SR_MHZ(100), 1, "Use 12 Channels (Max 25MHz)"}, - {DSL_STREAM50x6, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 6, 1, SR_KHZ(50), SR_MHZ(50), + {DSL_STREAM50x6, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 6, 1, SR_KHZ(10), SR_MHZ(50), SR_KHZ(10), SR_MHZ(100), 1, "Use 6 Channels (Max 50MHz)"}, - {DSL_STREAM100x3, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 3, 1, SR_KHZ(50), SR_MHZ(100), + {DSL_STREAM100x3, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 3, 1, SR_KHZ(10), SR_MHZ(100), SR_KHZ(10), SR_MHZ(100), 1, "Use 3 Channels (Max 100MHz)"}, - {DSL_STREAM20x16_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 16, 1, SR_KHZ(100), SR_MHZ(20), + {DSL_STREAM20x16_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 16, 1, SR_KHZ(10), SR_MHZ(20), SR_KHZ(10), SR_MHZ(500), 5, "Use 16 Channels (Max 20MHz)"}, - {DSL_STREAM25x12_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 12, 1, SR_KHZ(100), SR_MHZ(25), + {DSL_STREAM25x12_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 12, 1, SR_KHZ(10), SR_MHZ(25), SR_KHZ(10), SR_MHZ(500), 5, "Use 12 Channels (Max 25MHz)"}, - {DSL_STREAM50x6_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 6, 1, SR_KHZ(100), SR_MHZ(50), + {DSL_STREAM50x6_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 6, 1, SR_KHZ(10), SR_MHZ(50), SR_KHZ(10), SR_MHZ(500), 5, "Use 6 Channels (Max 50MHz)"}, - {DSL_STREAM100x3_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 3, 1, SR_KHZ(100), SR_MHZ(100), + {DSL_STREAM100x3_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 3, 1, SR_KHZ(10), SR_MHZ(100), SR_KHZ(10), SR_MHZ(500), 5, "Use 3 Channels (Max 100MHz)"}, - {DSL_STREAM10x32_32_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 32, 1, SR_KHZ(100), SR_MHZ(10), + {DSL_STREAM10x32_32_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 32, 1, SR_KHZ(10), SR_MHZ(10), SR_KHZ(10), SR_MHZ(500), 5, "Use 32 Channels (Max 10MHz)"}, - {DSL_STREAM20x16_32_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 16, 1, SR_KHZ(100), SR_MHZ(20), + {DSL_STREAM20x16_32_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 16, 1, SR_KHZ(10), SR_MHZ(20), SR_KHZ(10), SR_MHZ(500), 5, "Use 16 Channels (Max 20MHz)"}, - {DSL_STREAM25x12_32_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 12, 1, SR_KHZ(100), SR_MHZ(25), + {DSL_STREAM25x12_32_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 12, 1, SR_KHZ(10), SR_MHZ(25), SR_KHZ(10), SR_MHZ(500), 5, "Use 12 Channels (Max 25MHz)"}, - {DSL_STREAM50x6_32_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 6, 1, SR_KHZ(100), SR_MHZ(50), + {DSL_STREAM50x6_32_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 6, 1, SR_KHZ(10), SR_MHZ(50), SR_KHZ(10), SR_MHZ(500), 5, "Use 6 Channels (Max 50MHz)"}, - {DSL_STREAM100x3_32_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 3, 1, SR_KHZ(100), SR_MHZ(100), + {DSL_STREAM100x3_32_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 3, 1, SR_KHZ(10), SR_MHZ(100), SR_KHZ(10), SR_MHZ(500), 5, "Use 3 Channels (Max 100MHz)"}, - {DSL_STREAM50x32, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 32, 1, SR_MHZ(1), SR_MHZ(50), + {DSL_STREAM50x32, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 32, 1, SR_KHZ(10), SR_MHZ(50), SR_KHZ(10), SR_MHZ(500), 5, "Use 32 Channels (Max 50MHz)"}, - {DSL_STREAM100x30, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 30, 1, SR_MHZ(1), SR_MHZ(100), + {DSL_STREAM100x30, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 30, 1, SR_KHZ(10), SR_MHZ(100), SR_KHZ(10), SR_MHZ(500), 5, "Use 30 Channels (Max 100MHz)"}, - {DSL_STREAM250x12, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 12, 1, SR_MHZ(1), SR_MHZ(250), + {DSL_STREAM250x12, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 12, 1, SR_KHZ(10), SR_MHZ(250), SR_KHZ(10), SR_MHZ(500), 5, "Use 12 Channels (Max 250MHz)"}, - {DSL_STREAM125x16_16, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 16, 1, SR_MHZ(1), SR_MHZ(125), + {DSL_STREAM125x16_16, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 16, 1, SR_KHZ(10), SR_MHZ(125), SR_KHZ(10), SR_MHZ(500), 5, "Use 16 Channels (Max 125MHz)"}, - {DSL_STREAM250x12_16, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 12, 1, SR_MHZ(1), SR_MHZ(250), + {DSL_STREAM250x12_16, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 12, 1, SR_KHZ(10), SR_MHZ(250), SR_KHZ(10), SR_MHZ(500), 5, "Use 12 Channels (Max 250MHz)"}, - {DSL_STREAM500x6, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 6, 1, SR_MHZ(1), SR_MHZ(500), + {DSL_STREAM500x6, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 6, 1, SR_KHZ(10), SR_MHZ(500), SR_KHZ(10), SR_MHZ(500), 5, "Use 6 Channels (Max 500MHz)"}, - {DSL_STREAM1000x3, LOGIC, SR_CHANNEL_LOGIC, TRUE, 8, 3, 1, SR_MHZ(1), SR_GHZ(1), + {DSL_STREAM1000x3, LOGIC, SR_CHANNEL_LOGIC, TRUE, 8, 3, 1, SR_KHZ(10), SR_GHZ(1), SR_KHZ(10), SR_MHZ(500), 5, "Use 3 Channels (Max 1GHz)"}, // LA Buffer - {DSL_BUFFER100x16, LOGIC, SR_CHANNEL_LOGIC, FALSE, 16, 16, 1, SR_KHZ(50), SR_MHZ(100), + {DSL_BUFFER100x16, LOGIC, SR_CHANNEL_LOGIC, FALSE, 16, 16, 1, SR_KHZ(10), SR_MHZ(100), SR_KHZ(10), SR_MHZ(100), 1, "Use Channels 0~15 (Max 100MHz)"}, - {DSL_BUFFER200x8, LOGIC, SR_CHANNEL_LOGIC, FALSE, 8, 8, 1, SR_KHZ(50), SR_MHZ(200), + {DSL_BUFFER200x8, LOGIC, SR_CHANNEL_LOGIC, FALSE, 8, 8, 1, SR_KHZ(10), SR_MHZ(200), SR_KHZ(10), SR_MHZ(100), 1, "Use Channels 0~7 (Max 200MHz)"}, - {DSL_BUFFER400x4, LOGIC, SR_CHANNEL_LOGIC, FALSE, 4, 4, 1, SR_KHZ(50), SR_MHZ(400), + {DSL_BUFFER400x4, LOGIC, SR_CHANNEL_LOGIC, FALSE, 4, 4, 1, SR_KHZ(10), SR_MHZ(400), SR_KHZ(10), SR_MHZ(100), 1, "Use Channels 0~3 (Max 400MHz)"}, - {DSL_BUFFER250x32, LOGIC, SR_CHANNEL_LOGIC, FALSE, 32, 32, 1, SR_MHZ(1), SR_MHZ(250), + {DSL_BUFFER250x32, LOGIC, SR_CHANNEL_LOGIC, FALSE, 32, 32, 1, SR_KHZ(10), SR_MHZ(250), SR_KHZ(10), SR_MHZ(500), 5, "Use Channels 0~31 (Max 250MHz)"}, - {DSL_BUFFER500x16, LOGIC, SR_CHANNEL_LOGIC, FALSE, 16, 16, 1, SR_MHZ(1), SR_MHZ(500), + {DSL_BUFFER500x16, LOGIC, SR_CHANNEL_LOGIC, FALSE, 16, 16, 1, SR_KHZ(10), SR_MHZ(500), SR_KHZ(10), SR_MHZ(500), 5, "Use Channels 0~15 (Max 500MHz)"}, - {DSL_BUFFER1000x8, LOGIC, SR_CHANNEL_LOGIC, FALSE, 8, 8, 1, SR_MHZ(1), SR_GHZ(1), + {DSL_BUFFER1000x8, LOGIC, SR_CHANNEL_LOGIC, FALSE, 8, 8, 1, SR_KHZ(10), SR_GHZ(1), SR_KHZ(10), SR_MHZ(500), 5, "Use Channels 0~7 (Max 1GHz)"}, // DAQ @@ -1237,6 +1237,8 @@ struct DSL_context { int empty_poll_count; int is_loop; + + uint64_t ext_samplerate; }; /* diff --git a/libsigrok4DSL/hardware/DSL/dslogic.c b/libsigrok4DSL/hardware/DSL/dslogic.c index 777341ad6..0b7f6104a 100644 --- a/libsigrok4DSL/hardware/DSL/dslogic.c +++ b/libsigrok4DSL/hardware/DSL/dslogic.c @@ -142,6 +142,7 @@ static const int32_t hwoptions[] = { SR_CONF_RLE_SUPPORT, SR_CONF_CLOCK_TYPE, SR_CONF_CLOCK_EDGE, + SR_CONF_EXT_SAMPLERATE, }; static const int32_t hwoptions_pro[] = { @@ -153,6 +154,7 @@ static const int32_t hwoptions_pro[] = { SR_CONF_RLE_SUPPORT, SR_CONF_CLOCK_TYPE, SR_CONF_CLOCK_EDGE, + SR_CONF_EXT_SAMPLERATE, }; static const int32_t sessions[] = { @@ -172,6 +174,7 @@ static const int32_t sessions[] = { SR_CONF_HORIZ_TRIGGERPOS, SR_CONF_TRIGGER_HOLDOFF, SR_CONF_TRIGGER_MARGIN, + SR_CONF_EXT_SAMPLERATE, }; static const int32_t sessions_pro[] = { @@ -192,6 +195,7 @@ static const int32_t sessions_pro[] = { SR_CONF_HORIZ_TRIGGERPOS, SR_CONF_TRIGGER_HOLDOFF, SR_CONF_TRIGGER_MARGIN, + SR_CONF_EXT_SAMPLERATE, }; SR_PRIV struct sr_dev_driver DSLogic_driver_info; @@ -251,6 +255,7 @@ static struct DSL_context *DSLogic_dev_new(const struct DSL_profile *prof) devc->trigger_margin = 8; devc->trigger_channel = 0; + devc->ext_samplerate = 1000000; dsl_adjust_samplerate(devc); return devc; @@ -729,6 +734,9 @@ static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi, case SR_CONF_TOTAL_CH_NUM: *data = g_variant_new_int16(devc->profile->dev_caps.total_ch_num); break; + case SR_CONF_EXT_SAMPLERATE: + *data = g_variant_new_uint64(devc->ext_samplerate); + break; default: return SR_ERR_NA; } @@ -1173,6 +1181,10 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi, devc->is_loop = g_variant_get_boolean(data); sr_info("Set device loop mode:%d", devc->is_loop); } + else if (id == SR_CONF_EXT_SAMPLERATE) { + devc->ext_samplerate = g_variant_get_uint64(data); + sr_info("Set device ext samplerate: %d", devc->ext_samplerate); + } else { ret = SR_ERR_NA; } diff --git a/libsigrok4DSL/hwdriver.c b/libsigrok4DSL/hwdriver.c index 73e9c52ba..510824ecc 100644 --- a/libsigrok4DSL/hwdriver.c +++ b/libsigrok4DSL/hwdriver.c @@ -51,6 +51,7 @@ static struct sr_config_info sr_config_info_data[] = { {SR_CONF_LIMIT_SAMPLES, SR_T_UINT64,"Sample count"}, {SR_CONF_ACTUAL_SAMPLES, SR_T_UINT64,"Sample count-actual"}, {SR_CONF_CLOCK_TYPE, SR_T_BOOL,"Using External Clock"}, + {SR_CONF_EXT_SAMPLERATE, SR_T_UINT64, "Ext. Clock Frequency [Hz]"}, {SR_CONF_CLOCK_EDGE, SR_T_BOOL, "Using Clock Negedge"}, {SR_CONF_CAPTURE_RATIO, SR_T_UINT64,"Pre-trigger capture ratio"}, {SR_CONF_PATTERN_MODE, SR_T_CHAR,"Operation Mode"}, diff --git a/libsigrok4DSL/libsigrok.h b/libsigrok4DSL/libsigrok.h index 28d8a0caf..fbfa3b190 100644 --- a/libsigrok4DSL/libsigrok.h +++ b/libsigrok4DSL/libsigrok.h @@ -1094,6 +1094,9 @@ enum sr_config_option_id * starts or stops the internal logging. */ SR_CONF_DATALOG = 50007, + /** Manually entered sample rate as supplement for external clock mode */ + SR_CONF_EXT_SAMPLERATE = 50008, + SR_CONF_LOOP_MODE = 60001, };