32 using std::dynamic_pointer_cast;
33 using std::make_shared;
35 using std::unique_lock;
40 #define MATH_ERR_NONE 0 41 #define MATH_ERR_EMPTY_EXPR 1 42 #define MATH_ERR_EXPRESSION 2 43 #define MATH_ERR_INVALID_SIGNAL 3 44 #define MATH_ERR_ENABLE 4 66 const string_t exprtk_sig_name =
string_t(parameters[0]);
67 const scalar_t exprtk_sample_num =
scalar_t(parameters[1]);
69 const std::string str_sig_name =
to_str(exprtk_sig_name);
70 const double sample_num = exprtk_sample_num();
96 use_custom_sample_rate_(false),
97 use_custom_sample_count_(false),
100 exprtk_unknown_symbol_table_(nullptr),
101 exprtk_symbol_table_(nullptr),
102 exprtk_expression_(nullptr),
103 exprtk_parser_(nullptr),
107 set_name(QString(tr(
"Math%1")).arg(sig_idx));
110 set_data(std::make_shared<data::Analog>());
112 connect(&
session_, SIGNAL(capture_state_changed(
int)),
137 if (settings.contains(
"expression"))
138 expression_ = settings.value(
"expression").toString();
140 if (settings.contains(
"custom_sample_rate"))
143 if (settings.contains(
"custom_sample_count"))
146 if (settings.contains(
"use_custom_sample_rate"))
149 if (settings.contains(
"use_custom_sample_count"))
170 qDebug().nospace() <<
name() <<
": " << msg <<
"(Expression: '" +
expression_ +
"')";
189 const shared_ptr<SignalBase>& sb = input_signal.second.sb;
191 shared_ptr<Analog> a = sb->analog_data();
192 auto analog_segments = a->analog_segments();
194 if (analog_segments.size() == 0) {
199 const uint32_t highest_segment_id = (analog_segments.size() - 1);
200 if (segment_id > highest_segment_id)
203 const shared_ptr<AnalogSegment> segment = analog_segments.at(segment_id);
204 result =
min(result, (int64_t)segment->get_sample_count());
215 bool output_complete =
true;
219 const shared_ptr<SignalBase>& sb = input_signal.second.sb;
221 shared_ptr<Analog> a = sb->analog_data();
222 auto analog_segments = a->analog_segments();
224 if (analog_segments.size() == 0) {
225 output_complete =
false;
229 const uint32_t highest_segment_id = (analog_segments.size() - 1);
230 if (segment_id > highest_segment_id) {
231 output_complete =
false;
235 const shared_ptr<AnalogSegment> segment = analog_segments.at(segment_id);
236 if (!segment->is_complete()) {
237 output_complete =
false;
241 if (output_sample_count < segment->get_sample_count())
242 output_complete =
false;
248 output_complete =
false;
252 analog_data()->analog_segments().at(segment_id)->set_complete();
295 qDebug().nospace() <<
name() <<
": Error cleared";
313 if (sb->analog_data())
314 disconnect(sb->analog_data().get(),
nullptr,
this, SLOT(
on_data_received()));
324 exprtk_symbol_table_->
add_function(
"sample", *fnc_sample_);
337 QString error_details;
340 for (
size_t i = 0; i < error_count; i++) {
345 QString error_detail = tr(
"%1 at line %2, column %3: %4");
346 if ((error_count > 1) && (i < (error_count - 1)))
347 error_detail +=
"\n";
349 error_details += error_detail \
351 .arg(error.line_no) \
352 .arg(error.column_no) \
353 .arg(error.diagnostic.c_str());
358 vector<string> unknowns;
360 for (
string& unknown : unknowns) {
362 const shared_ptr<SignalBase> signal = (sig_data) ? (sig_data->
sb) :
nullptr;
363 if (!signal || (!signal->analog_data())) {
365 .arg(QString::fromStdString(unknown)));
371 QString disabled_signals;
374 tr(
"No data will be generated as %1 must be enabled").arg(disabled_signals));
387 const int64_t sample_count)
391 shared_ptr<Analog> analog = dynamic_pointer_cast<
Analog>(
data_);
392 shared_ptr<AnalogSegment> segment = analog->
analog_segments().at(segment_id);
397 const double sample_rate =
data_->get_samplerate();
401 float *sample_data =
new float[sample_count];
403 for (int64_t i = 0; i < sample_count; i++) {
412 sample_data[i] =
value;
423 segment->append_interleaved_samples(sample_data, count, 1);
425 delete[] sample_data;
439 if (
data_->get_samplerate() == 1) {
448 uint32_t segment_id = 0;
452 shared_ptr<AnalogSegment> output_segment =
453 make_shared<AnalogSegment>(*analog.get(), segment_id, analog->get_samplerate());
454 analog->push_segment(output_segment);
459 const uint64_t output_sample_count = output_segment->get_sample_count();
461 const uint64_t samples_to_process =
462 (input_sample_count > output_sample_count) ?
463 (input_sample_count - output_sample_count) : 0;
466 if (samples_to_process > 0) {
467 uint64_t processed_samples = 0;
469 const uint64_t start_sample = output_sample_count + processed_samples;
470 uint64_t sample_count =
474 processed_samples += sample_count;
477 samples_added(segment_id, start_sample, start_sample + processed_samples);
478 }
while (!
gen_interrupt_ && (processed_samples < samples_to_process));
488 make_shared<AnalogSegment>(*analog.get(), segment_id, analog->get_samplerate());
489 analog->push_segment(output_segment);
504 const QString sig_name = QString::fromStdString(name);
505 if (sig_name == this->
name())
513 return &(element->second);
517 for (
const shared_ptr<SignalBase>& sb : signalbases)
518 if (sb->name() == sig_name) {
519 if (!sb->analog_data())
524 connect(sb->analog_data().get(), SIGNAL(segment_completed()),
537 .arg(QString::fromStdString(name)));
550 assert(sig_data->
sb);
551 const shared_ptr<pv::data::Analog> analog = sig_data->
sb->analog_data();
554 assert(segment_id < analog->analog_segments().size());
556 const shared_ptr<AnalogSegment> segment = analog->analog_segments().at(segment_id);
560 if (sample_num < segment->get_sample_count())
561 sig_data->
sample_value = segment->get_sample(sample_num);
573 bool all_enabled =
true;
575 disabled_signals.clear();
578 const shared_ptr<SignalBase>& sb = input_signal.second.sb;
580 if (!sb->enabled()) {
582 disabled_signals += disabled_signals.isEmpty() ?
583 sb->name() :
", " + sb->name();
607 QString disabled_signals;
611 tr(
"No data will be generated as %1 must be enabled").arg(disabled_signals));
bool update_error(type &error, const std::string &expression)
void register_symbol_table(symbol_table< T > &st)
#define MATH_ERR_INVALID_SIGNAL
exprtk::symbol_table< double > * exprtk_unknown_symbol_table_
exprtk::parser< double > * exprtk_parser_
const vector< shared_ptr< data::SignalBase > > signalbases() const
bool use_custom_sample_count_
double exprtk_current_sample_
igeneric_function(const std::string ¶m_seq="", const return_type rtr_type=e_rtrn_scalar)
void error_message_changed(QString msg)
signal_data * signal_from_name(const std::string &name)
void set_data(shared_ptr< pv::data::SignalData > data)
bool compile(const std::string &expression_string, expression< T > &expr)
std::string to_str(int i)
std::shared_ptr< pv::data::Segment > SharedPtrToSegment
void on_enabled_changed()
uint32_t get_next_signal_index(data::SignalBase::ChannelType type)
shared_ptr< pv::data::SignalData > data_
void set_error(uint8_t type, QString msg)
const shared_ptr< SignalBase > sb
void on_capture_state_changed(int state)
double exprtk_current_time_
T value(details::expression_node< T > *n)
std::size_t get_variable_list(Sequence< std::pair< std::string, T >, Allocator > &vlist) const
uint64_t custom_sample_count_
std::size_t error_count() const
condition_variable gen_input_cond_
void set_expression(QString expression)
exprtk::symbol_table< double > * exprtk_symbol_table_
void update_completeness(uint32_t segment_id, uint64_t output_sample_count)
#define MATH_ERR_EMPTY_EXPR
virtual void restore_settings(QSettings &settings)
Virtual channel generated by math operations.
parser_error::type get_error(const std::size_t &index) const
virtual void save_settings(QSettings &settings) const
T max(const T v0, const T v1)
atomic< bool > gen_interrupt_
exprtk::igeneric_function< T >::parameter_list_t parameter_list_t
bool all_input_signals_enabled(QString &disabled_signals) const
uint32_t get_highest_segment_id() const
double get_samplerate() const
map< std::string, signal_data > input_signals_
virtual void set_name(QString name)
uint64_t generation_chunk_size_
bool add_variable(const std::string &variable_name, T &t, const bool is_constant=false)
virtual void save_settings(QSettings &settings) const
QString get_expression() const
void enabled_changed(const bool &value)
T min(const T v0, const T v1)
capture_state get_capture_state() const
const deque< shared_ptr< AnalogSegment > > & analog_segments() const
uint64_t get_segment_sample_count(uint32_t segment_id) const
exprtk::expression< double > * exprtk_expression_
bool add_constant(const std::string &constant_name, const T &value)
bool use_custom_sample_rate_
fnc_sample< double > * fnc_sample_
T operator()(parameter_list_t parameters)
uint64_t generate_samples(uint32_t segment_id, const uint64_t start_sample, const int64_t sample_count)
bool add_function(const std::string &function_name, function_t &function)
void update_signal_sample(signal_data *sig_data, uint32_t segment_id, uint64_t sample_num)
virtual void begin_generation()
#define MATH_ERR_EXPRESSION
shared_ptr< pv::data::Analog > analog_data() const
virtual void restore_settings(QSettings &settings)
MathSignal(pv::Session &session)
void enable_unknown_symbol_resolver(unknown_symbol_resolver *usr=reinterpret_cast< unknown_symbol_resolver * >(0))
static const QColor AnalogSignalColors[8]
uint64_t custom_sample_rate_
virtual void set_color(QColor color)
generic_type::string_view string_t
fnc_sample(MathSignal &owner)
T & variable_ref(const std::string &symbol_name)
static const int64_t ChunkLength
exprtk::igeneric_function< T >::generic_type generic_type
generic_type::scalar_view scalar_t
void samples_added(uint64_t segment_id, uint64_t start_sample, uint64_t end_sample)
std::string to_str(error_mode mode)
uint64_t get_working_sample_count(uint32_t segment_id) const