From cb4337b8ec5ba061dcd6bdadc1bca697efc73aee Mon Sep 17 00:00:00 2001 From: Giulio Gaio <giulio.gaio@elettra.eu> Date: Mon, 29 May 2023 09:32:48 +0200 Subject: [PATCH] Reimplemented a more lightweight internal circular buffer --- src/DataVampire.cpp | 1288 ++++++++++++++++++++++++-------------- src/DataVampire.h | 51 +- src/DataVampire.xmi | 2 +- src/DataVampireClass.cpp | 3 +- src/acqthread.cpp | 42 +- 5 files changed, 869 insertions(+), 517 deletions(-) diff --git a/src/DataVampire.cpp b/src/DataVampire.cpp index ac14883..efad341 100644 --- a/src/DataVampire.cpp +++ b/src/DataVampire.cpp @@ -173,8 +173,6 @@ void DataVampire::delete_device() delete mutex; - free_cache_buffer(); - /*----- PROTECTED REGION END -----*/ // DataVampire::delete_device delete[] attr_MinThreshold_read; delete[] attr_MaxThreshold_read; @@ -258,6 +256,9 @@ void DataVampire::init_device() *attr_CacheSize_read = 100; *attr_PostAcqRoi_read = false; *attr_EnableAcquisition_read = true; + *attr_PollingSamples_read = 10; + *attr_PollingPeriod_read = 500; + *attr_EnablePolling_read = false; num_rows_image = 0; num_cols_image = 0; @@ -279,71 +280,101 @@ void DataVampire::init_device() if (pos != std::string::npos) { // if str2 found in str1 new_configuration.erase(pos-1, command_name.length()+1); // erase str2 from str1 } - device_name = new_configuration; + c_device_name = new_configuration; + INFO_STREAM << "Device name: " << c_device_name << endl; INFO_STREAM << "Command name: " << command_name << endl; - INFO_STREAM << "Device name: " << device_name << endl; - device = 0; try { - device = new Tango::DeviceProxy(device_name); + device = 0; + device = new Tango::DeviceProxy(c_device_name); Tango::CommandInfo cmd_info = device->command_query(command_name); cmd_in_type = cmd_info.in_type; cmd_out_type = cmd_info.out_type; - snprintf(*attr_CommandString_read, DATAVAMPIRE_MAX_STR_LEN, "%s", new_configuration.c_str()); + snprintf(*attr_CommandString_read, DATAVAMPIRE_MAX_STR_LEN, "%s/%s", c_device_name.c_str(),command_name.c_str()); set_state(Tango::ON); set_status("Connected to device"); } catch (Tango::DevFailed &e) { - INFO_STREAM << e.errors[0].desc << ", " << device_name << " " << command_name << endl; - INFO_STREAM << e.errors[0].reason << ", " << device_name << " " << command_name << endl; + INFO_STREAM << e.errors[0].desc << ", " << c_device_name << " " << command_name << endl; + INFO_STREAM << e.errors[0].reason << ", " << c_device_name << " " << command_name << endl; set_state(Tango::FAULT); set_status("Failed to execute device command, check CommandString property and restart device"); } catch(...) { set_state(Tango::FAULT); set_status("Failed to execute device command, check CommandString property and restart device"); - INFO_STREAM << "Generic error, failed to execute command_query on device " << device_name << " " << command_name << endl; + INFO_STREAM << "Generic error, failed to execute command_query on device " << c_device_name << " " << command_name << endl; } - /* + std::vector<std::string> results_a; std::string bn_attr(bunchNumberString); string_explode(bn_attr, "/", &results_a); - bn_attr_name = results[results_a.size()-1]; + bn_attr_name = results_a[results_a.size()-1]; pos = bn_attr.find(bn_attr_name); if (pos != std::string::npos) { // if str2 found in str1 bn_attr.erase(pos-1, bn_attr_name.length()+1); // erase str2 from str1 } bn_device_name = bn_attr; - - printf("5\n"); - try { - bn_device = new Tango::DeviceProxy(bn_device_name); + INFO_STREAM << "BN device name: " << bn_device_name << endl; + INFO_STREAM << "BN attr name: " << bn_attr_name << endl; + + if (bn_attr.size() > 0) { + try { + bn_device = new Tango::DeviceProxy(bn_device_name); + INFO_STREAM << bn_device_name << endl; + INFO_STREAM << bn_attr_name << endl; + } + catch(...) { + set_state(Tango::FAULT); + set_status("Failed to connect to BunchNumber device"); + } + } + + for (int i = 0; i < DATAVAMPIRE_MAX_SIZE; i++) { + acq_array[i].sum = 0; + acq_array[i].mean = 0; + acq_array[i].horpos = 0; + acq_array[i].verpos = 0; + acq_array[i].horposstd = 0; + acq_array[i].verposstd = 0; + acq_array[i].validvalues = 0; + acq_array[i].bn = 0; } - catch(...) { - set_state(Tango::FAULT); - set_status("Failed to connect to BunchNumber device"); + array_idx = 0; + + + try { + last_bn = 0; + bn_device->read_attribute(bn_attr_name) >> last_bn; } - */ + catch(...){} + try { + frequency = 0; + Tango::DevLong bunch_number_pre, bunch_number_post; + bn_device->read_attribute(bn_attr_name) >> bunch_number_pre; + sleep(1); + bn_device->read_attribute(bn_attr_name) >> bunch_number_post; + frequency = bunch_number_post - bunch_number_pre; + } + catch(...){} + if (frequency < 25) + frequency = 10; + else + frequency = 50; - - - cache_buffer = 0; - allocate_cache_buffer(); - - /* mutex = new omni_mutex(); acqloop = 0; acqloop = new acqthread(this); acqloop->start_undetached(); - */ + /*----- PROTECTED REGION END -----*/ // DataVampire::init_device } @@ -461,6 +492,8 @@ void DataVampire::always_executed_hook() /* clang-format on */ // code always executed before all requests /* clang-format off */ + + /*----- PROTECTED REGION END -----*/ // DataVampire::always_executed_hook } @@ -616,27 +649,47 @@ void DataVampire::write_CommandString(Tango::WAttribute &attr) /*----- PROTECTED REGION ID(DataVampire::write_CommandString) ENABLED START -----*/ /* clang-format on */ // Add your own code - std::vector<std::string> results; - std::string new_configuration(w_val); - string_explode(new_configuration, "/", &results); - - command_name = results[results.size()-1]; - size_t pos = new_configuration.find(command_name); - if (pos != std::string::npos) { // if str2 found in str1 - new_configuration.erase(pos-1, command_name.length()+1); // erase str2 from str1 - } - device_name = new_configuration; - - if (device) - delete device; - device = new Tango::DeviceProxy(device_name); + try { + mutex->lock(); + std::vector<std::string> results; + std::string new_configuration(w_val); + string_explode(new_configuration, "/", &results); + + command_name = results[results.size()-1]; + size_t pos = new_configuration.find(command_name); + if (pos != std::string::npos) { // if str2 found in str1 + new_configuration.erase(pos-1, command_name.length()+1); // erase str2 from str1 + } + c_device_name = new_configuration; + + if (device) + delete device; + device = new Tango::DeviceProxy(c_device_name); - Tango::CommandInfo cmd_info = device->command_query(command_name); - cmd_in_type = cmd_info.in_type; - cmd_out_type = cmd_info.out_type; + Tango::CommandInfo cmd_info = device->command_query(command_name); + cmd_in_type = cmd_info.in_type; + cmd_out_type = cmd_info.out_type; - snprintf(*attr_CommandString_read, DATAVAMPIRE_MAX_STR_LEN, "%s", new_configuration.c_str()); - store_command_string(w_val); + snprintf(*attr_CommandString_read, DATAVAMPIRE_MAX_STR_LEN, "%s", new_configuration.c_str()); + store_command_string(w_val); + mutex->unlock(); + } + catch (Tango::DevFailed &e) { + mutex->unlock(); + INFO_STREAM << e.errors[0].desc << ", " << c_device_name << " " << command_name << endl; + INFO_STREAM << e.errors[0].reason << ", " << c_device_name << " " << command_name << endl; + Tango::Except::re_throw_exception(e, + (const char *) "Failed to store command string", + (const char *) "Error storing command string", + __FUNCTION__, Tango::ERR); + } + catch(...) { + mutex->unlock(); + Tango::Except::throw_exception( + (const char *) "Failed to store command string", + (const char *) "Generic error", + __FUNCTION__, Tango::ERR); + } /* clang-format off */ /*----- PROTECTED REGION END -----*/ // DataVampire::write_CommandString @@ -675,7 +728,7 @@ void DataVampire::write_PollingPeriod(Tango::WAttribute &attr) Tango::DevLong w_val; attr.get_write_value(w_val); /*----- PROTECTED REGION ID(DataVampire::write_PollingPeriod) ENABLED START -----*/ - + *attr_PollingPeriod_read = w_val; /*----- PROTECTED REGION END -----*/ // DataVampire::write_PollingPeriod } @@ -1125,7 +1178,7 @@ void DataVampire::write_EnablePolling(Tango::WAttribute &attr) Tango::DevBoolean w_val; attr.get_write_value(w_val); /*----- PROTECTED REGION ID(DataVampire::write_EnablePolling) ENABLED START -----*/ - + *attr_EnablePolling_read = w_val; /*----- PROTECTED REGION END -----*/ // DataVampire::write_EnablePolling } @@ -1170,6 +1223,20 @@ void DataVampire::write_RoiParam(Tango::WAttribute &attr) /* clang-format on */ // Add your own code /* clang-format off */ + + if ((w_length == 2) && (w_val[0] > w_val[1])) { + Tango::Except::throw_exception ( + (const char *)"Failed to set ROI param", + (const char *)"Invalid setting", + __FUNCTION__); + } + if ((w_length == 4) && ((w_val[2] < w_val[0]) || (w_val[3] < w_val[1]))) { + Tango::Except::throw_exception ( + (const char *)"Failed to set ROI param", + (const char *)"Invalid setting", + __FUNCTION__); + } + store_roi_param(w_val, w_length); /*----- PROTECTED REGION END -----*/ // DataVampire::write_RoiParam @@ -1189,6 +1256,14 @@ void DataVampire::read_Spectrum(Tango::Attribute &attr) /*----- PROTECTED REGION ID(DataVampire::read_Spectrum) ENABLED START -----*/ /* clang-format on */ // Set the attribute value + + if (roi_dim == 4) { + Tango::Except::throw_exception( + (const char *) "Failed to get spectrum", + (const char *) "Dimension not supported", + __FUNCTION__, Tango::ERR); + } + attr.set_value(attr_Spectrum_read, num_cols_spectrum); /* clang-format off */ /*----- PROTECTED REGION END -----*/ // DataVampire::read_Spectrum @@ -1258,6 +1333,13 @@ void DataVampire::read_Image(Tango::Attribute &attr) /*----- PROTECTED REGION ID(DataVampire::read_Image) ENABLED START -----*/ /* clang-format on */ // Set the attribute value + if (roi_dim == 2) { + Tango::Except::throw_exception( + (const char *) "Failed to get spectrum", + (const char *) "Dimension not supported", + __FUNCTION__, Tango::ERR); + } + attr.set_value(attr_Image_read, num_cols_image, num_rows_image); /* clang-format off */ /*----- PROTECTED REGION END -----*/ // DataVampire::read_Image @@ -1296,15 +1378,43 @@ Tango::DevVarDoubleArray *DataVampire::get_sum(const Tango::DevVarLongArray *arg /* clang-format on */ // Add your own code - acq_buffer_t *rec_data; - recover_data(argin, &rec_data); - - - argout = new Tango::DevVarDoubleArray(); - argout->length(rec_data->num_samples); - - for (int i = 0; i < rec_data->num_samples; i++) - (*argout)[i] = rec_data->sum[i]; + try { + mutex->lock(); + int32_t mode, num_samples, bn_start, bn_end; + + // check and extract input parameters + get_param_in(argin, &mode, &num_samples, &bn_start, &bn_end); + + // if data not preset get data and store it into circular buffers + if (bn_end > last_bn) + store_circ_data(mode, num_samples, last_bn+1, bn_end); + // get start idx of the circular buffer + int32_t start_idx = get_start_index(mode, num_samples, bn_start, bn_end); + argout = new Tango::DevVarDoubleArray(); + argout->length(num_samples); + + for (int32_t i = 0; i < num_samples; i++) { + int32_t idx = (start_idx + i) % DATAVAMPIRE_MAX_SIZE; + // get sum + (*argout)[i] = acq_array[idx].sum; + } + mutex->unlock(); + } + catch (Tango::DevFailed &e) { + mutex->unlock(); + Tango::Except::re_throw_exception(e, + (const char *) "Failed to get data", + (const char *) "Tango exception", + __FUNCTION__, Tango::ERR); + } + catch (...) { + mutex->unlock(); + Tango::Except::throw_exception( + (const char *) "Failed to get data", + (const char *) "Generic exception", + __FUNCTION__, Tango::ERR); + } + mutex->unlock(); /* clang-format off */ /*----- PROTECTED REGION END -----*/ // DataVampire::get_sum @@ -1327,15 +1437,44 @@ Tango::DevVarDoubleArray *DataVampire::get_mean(const Tango::DevVarLongArray *ar /* clang-format on */ // Add your own code - acq_buffer_t *rec_data; - recover_data(argin, &rec_data); + try { + mutex->lock(); + int32_t mode, num_samples, bn_start, bn_end; + // check and extract input parameters + get_param_in(argin, &mode, &num_samples, &bn_start, &bn_end); - - argout = new Tango::DevVarDoubleArray(); - argout->length(rec_data->num_samples); - - for (int i = 0; i < rec_data->num_samples; i++) - (*argout)[i] = rec_data->mean[i]; + // if data not preset get data and store it into circular buffers + if (bn_end > last_bn) + store_circ_data(mode, num_samples, last_bn+1, bn_end); + + // get start idx of the circular buffer + int32_t start_idx = get_start_index(mode, num_samples, bn_start, bn_end); + + argout = new Tango::DevVarDoubleArray(); + argout->length(num_samples); + + for (int32_t i = 0; i < num_samples; i++) { + int32_t idx = (start_idx + i) % DATAVAMPIRE_MAX_SIZE; + // get mean + (*argout)[i] = acq_array[idx].mean; + } + mutex->unlock(); + } + catch (Tango::DevFailed &e) { + mutex->unlock(); + Tango::Except::re_throw_exception(e, + (const char *) "Failed to get data", + (const char *) "Tango exception", + __FUNCTION__, Tango::ERR); + } + catch (...) { + mutex->unlock(); + Tango::Except::throw_exception( + (const char *) "Failed to get data", + (const char *) "Generic exception", + __FUNCTION__, Tango::ERR); + } + mutex->unlock(); /* clang-format off */ /*----- PROTECTED REGION END -----*/ // DataVampire::get_mean @@ -1358,15 +1497,44 @@ Tango::DevVarDoubleArray *DataVampire::get_hor_pos(const Tango::DevVarLongArray /* clang-format on */ // Add your own code - acq_buffer_t *rec_data; - recover_data(argin, &rec_data); + try { + mutex->lock(); + int32_t mode, num_samples, bn_start, bn_end; + // check and extract input parameters + get_param_in(argin, &mode, &num_samples, &bn_start, &bn_end); - - argout = new Tango::DevVarDoubleArray(); - argout->length(rec_data->num_samples); - - for (int i = 0; i < rec_data->num_samples; i++) - (*argout)[i] = rec_data->horpos[i]; + // if data not preset get data and store it into circular buffers + if (bn_end > last_bn) + store_circ_data(mode, num_samples, last_bn+1, bn_end); + + // get start idx of the circular buffer + int32_t start_idx = get_start_index(mode, num_samples, bn_start, bn_end); + + argout = new Tango::DevVarDoubleArray(); + argout->length(num_samples); + + for (int32_t i = 0; i < num_samples; i++) { + int32_t idx = (start_idx + i) % DATAVAMPIRE_MAX_SIZE; + // get horpos + (*argout)[i] = acq_array[idx].horpos; + } + mutex->unlock(); + } + catch (Tango::DevFailed &e) { + mutex->unlock(); + Tango::Except::re_throw_exception(e, + (const char *) "Failed to get data", + (const char *) "Tango exception", + __FUNCTION__, Tango::ERR); + } + catch (...) { + mutex->unlock(); + Tango::Except::throw_exception( + (const char *) "Failed to get data", + (const char *) "Generic exception", + __FUNCTION__, Tango::ERR); + } + mutex->unlock(); /* clang-format off */ /*----- PROTECTED REGION END -----*/ // DataVampire::get_hor_pos @@ -1389,15 +1557,44 @@ Tango::DevVarDoubleArray *DataVampire::get_ver_pos(const Tango::DevVarLongArray /* clang-format on */ // Add your own code - acq_buffer_t *rec_data; - recover_data(argin, &rec_data); + try { + mutex->lock(); + int32_t mode, num_samples, bn_start, bn_end; + // check and extract input parameters + get_param_in(argin, &mode, &num_samples, &bn_start, &bn_end); - - argout = new Tango::DevVarDoubleArray(); - argout->length(rec_data->num_samples); - - for (int i = 0; i < rec_data->num_samples; i++) - (*argout)[i] = rec_data->verpos[i]; + // if data not preset get data and store it into circular buffers + if (bn_end > last_bn) + store_circ_data(mode, num_samples, last_bn+1, bn_end); + + // get start idx of the circular buffer + int32_t start_idx = get_start_index(mode, num_samples, bn_start, bn_end); + + argout = new Tango::DevVarDoubleArray(); + argout->length(num_samples); + + for (int32_t i = 0; i < num_samples; i++) { + int32_t idx = (start_idx + i) % DATAVAMPIRE_MAX_SIZE; + // get ve + (*argout)[i] = acq_array[idx].verpos; + } + mutex->unlock(); + } + catch (Tango::DevFailed &e) { + mutex->unlock(); + Tango::Except::re_throw_exception(e, + (const char *) "Failed to get data", + (const char *) "Tango exception", + __FUNCTION__, Tango::ERR); + } + catch (...) { + mutex->unlock(); + Tango::Except::throw_exception( + (const char *) "Failed to get data", + (const char *) "Generic exception", + __FUNCTION__, Tango::ERR); + } + mutex->unlock(); /* clang-format off */ /*----- PROTECTED REGION END -----*/ // DataVampire::get_ver_pos @@ -1420,15 +1617,44 @@ Tango::DevVarDoubleArray *DataVampire::get_hor_pos_std(const Tango::DevVarLongAr /* clang-format on */ // Add your own code - acq_buffer_t *rec_data; - recover_data(argin, &rec_data); + try { + mutex->lock(); + int32_t mode, num_samples, bn_start, bn_end; + // check and extract input parameters + get_param_in(argin, &mode, &num_samples, &bn_start, &bn_end); - - argout = new Tango::DevVarDoubleArray(); - argout->length(rec_data->num_samples); - - for (int i = 0; i < rec_data->num_samples; i++) - (*argout)[i] = rec_data->horposstd[i]; + // if data not preset get data and store it into circular buffers + if (bn_end > last_bn) + store_circ_data(mode, num_samples, last_bn+1, bn_end); + + // get start idx of the circular buffer + int32_t start_idx = get_start_index(mode, num_samples, bn_start, bn_end); + + argout = new Tango::DevVarDoubleArray(); + argout->length(num_samples); + + for (int32_t i = 0; i < num_samples; i++) { + int32_t idx = (start_idx + i) % DATAVAMPIRE_MAX_SIZE; + // get sum + (*argout)[i] = acq_array[idx].horposstd; + } + mutex->unlock(); + } + catch (Tango::DevFailed &e) { + mutex->unlock(); + Tango::Except::re_throw_exception(e, + (const char *) "Failed to get data", + (const char *) "Tango exception", + __FUNCTION__, Tango::ERR); + } + catch (...) { + mutex->unlock(); + Tango::Except::throw_exception( + (const char *) "Failed to get data", + (const char *) "Generic exception", + __FUNCTION__, Tango::ERR); + } + mutex->unlock(); /* clang-format off */ /*----- PROTECTED REGION END -----*/ // DataVampire::get_hor_pos_std @@ -1451,15 +1677,44 @@ Tango::DevVarDoubleArray *DataVampire::get_ver_pos_std(const Tango::DevVarLongAr /* clang-format on */ // Add your own code - acq_buffer_t *rec_data; - recover_data(argin, &rec_data); + try { + mutex->lock(); + int32_t mode, num_samples, bn_start, bn_end; + // check and extract input parameters + get_param_in(argin, &mode, &num_samples, &bn_start, &bn_end); - - argout = new Tango::DevVarDoubleArray(); - argout->length(rec_data->num_samples); - - for (int i = 0; i < rec_data->num_samples; i++) - (*argout)[i] = rec_data->verposstd[i]; + // if data not preset get data and store it into circular buffers + if (bn_end > last_bn) + store_circ_data(mode, num_samples, last_bn+1, bn_end); + + // get start idx of the circular buffer + int32_t start_idx = get_start_index(mode, num_samples, bn_start, bn_end); + + argout = new Tango::DevVarDoubleArray(); + argout->length(num_samples); + + for (int32_t i = 0; i < num_samples; i++) { + int32_t idx = (start_idx + i) % DATAVAMPIRE_MAX_SIZE; + // get sum + (*argout)[i] = acq_array[idx].verposstd; + } + mutex->unlock(); + } + catch (Tango::DevFailed &e) { + mutex->unlock(); + Tango::Except::re_throw_exception(e, + (const char *) "Failed to get data", + (const char *) "Tango exception", + __FUNCTION__, Tango::ERR); + } + catch (...) { + mutex->unlock(); + Tango::Except::throw_exception( + (const char *) "Failed to get data", + (const char *) "Generic exception", + __FUNCTION__, Tango::ERR); + } + mutex->unlock(); /* clang-format off */ /*----- PROTECTED REGION END -----*/ // DataVampire::get_ver_pos_std @@ -1482,15 +1737,44 @@ Tango::DevVarDoubleArray *DataVampire::get_valid_values(const Tango::DevVarLongA /* clang-format on */ // Add your own code - acq_buffer_t *rec_data; - recover_data(argin, &rec_data); + try { + mutex->lock(); + int32_t mode, num_samples, bn_start, bn_end; + // check and extract input parameters + get_param_in(argin, &mode, &num_samples, &bn_start, &bn_end); - - argout = new Tango::DevVarDoubleArray(); - argout->length(rec_data->num_samples); - - for (int i = 0; i < rec_data->num_samples; i++) - (*argout)[i] = rec_data->validvalues[i]; + // if data not preset get data and store it into circular buffers + if (bn_end > last_bn) + store_circ_data(mode, num_samples, last_bn+1, bn_end); + + // get start idx of the circular buffer + int32_t start_idx = get_start_index(mode, num_samples, bn_start, bn_end); + + argout = new Tango::DevVarDoubleArray(); + argout->length(num_samples); + + for (int32_t i = 0; i < num_samples; i++) { + int32_t idx = (start_idx + i) % DATAVAMPIRE_MAX_SIZE; + // get sum + (*argout)[i] = acq_array[idx].validvalues; + } + mutex->unlock(); + } + catch (Tango::DevFailed &e) { + mutex->unlock(); + Tango::Except::re_throw_exception(e, + (const char *) "Failed to get data", + (const char *) "Tango exception", + __FUNCTION__, Tango::ERR); + } + catch (...) { + mutex->unlock(); + Tango::Except::throw_exception( + (const char *) "Failed to get data", + (const char *) "Generic exception", + __FUNCTION__, Tango::ERR); + } + mutex->unlock(); /* clang-format off */ /*----- PROTECTED REGION END -----*/ // DataVampire::get_valid_values return argout; @@ -1509,7 +1793,11 @@ void DataVampire::set_background() /* clang-format on */ // Add your own code - + for (int i = 0; i < array_idx; i++) { + if ((acq_array[i].bn == 0) || (acq_array[i].sum == 0)) { + printf("%d bn=%d last_bn=%d sum=%f\n",i,acq_array[i].bn,last_bn,acq_array[i].sum); + } + } /* clang-format off */ /*----- PROTECTED REGION END -----*/ // DataVampire::set_background } @@ -1905,6 +2193,7 @@ void DataVampire::store_roi_param(const Tango::DevLong *w_val, int size) /* manual ROI x1,y1,x2,y2 */ try { + mutex->lock(); Tango::DbDatum config("RoiParam"); Tango::DbData db_data_put; std::vector<std::string> val; @@ -1923,14 +2212,24 @@ void DataVampire::store_roi_param(const Tango::DevLong *w_val, int size) config << val; db_data_put.push_back(config); db->put_device_property(get_name(), db_data_put); + } catch (Tango::DevFailed &e) { + mutex->unlock(); delete db; Tango::Except::throw_exception ( (const char *)"Failed to update configuration", (const char *)"Can't write into database", __FUNCTION__); } + catch (...) { + mutex->unlock(); + delete db; + Tango::Except::throw_exception ( + (const char *)"Failed to update configuration", + (const char *)"Unknown error", + __FUNCTION__); + } delete db; for (int i = 0; i < size; i++) { @@ -1941,6 +2240,8 @@ void DataVampire::store_roi_param(const Tango::DevLong *w_val, int size) } roi_dim = size; + + mutex->unlock(); } @@ -1955,6 +2256,8 @@ void DataVampire::store_command_string(Tango::DevString w_val) { std::string new_configuration(w_val); std::string dev_property("CommandString"); + + strncpy(*attr_CommandString_read, new_configuration.c_str(), 256); Tango::Database *db = new Tango::Database(); @@ -1979,139 +2282,26 @@ void DataVampire::store_command_string(Tango::DevString w_val) } delete db; - strncpy(*attr_CommandString_read, new_configuration.c_str(), 256); - - std::vector<std::string> results; - string_explode(new_configuration, "/", &results); - - command_name = results[results.size()-1]; - size_t pos = new_configuration.find(command_name); - if (pos != std::string::npos) { // if str2 found in str1 - new_configuration.erase(pos-1, command_name.length()+1); // erase str2 from str1 - } - device_name = new_configuration; - } - -void DataVampire::extract_input_parameters(const Tango::DevVarLongArray *argin, int *mode, int *num_samples, int *bn_start, int *bn_end, int *roi) +void DataVampire::store_array_2D(Tango::DeviceData *cmd_value, int32_t bn_start, int32_t bn_end) { - if (argin->length() < 2) { + std::vector<double> val; + std::vector<std::string> val_string; + int32_t num_samples = bn_end - bn_start + 1; + int32_t roi[4]; + int32_t auto_bck_samples = *attr_AutoBackgroundSamples_read; + + if (roi_dim != 4) { Tango::Except::throw_exception ( - (const char *)"Failed input parameters size", - (const char *)"Minimum number is 4", - __FUNCTION__); - - } - - *mode = ((*argin)[0] % 10) & 0x1; // 20->0 21->1 - - // return the last number - if (*mode == 0) { - *num_samples = (*argin)[1]; - *bn_start = 0; - *bn_end = 0; - } - else if (*mode == 1) { - *bn_start = (*argin)[1]; - *bn_end = (*argin)[2]; - *num_samples = *bn_end - *bn_start + 1; - } - - for (int i = 0; i < 4; i++) { - roi[i] = attr_RoiParam_read[i]; + (const char *)"Failed to store data", + (const char *)"Invalid ROI dimension", + __FUNCTION__); } - -} - - - - -//+------------------------------------------------------------------ -/** - * method: DataVampire::free_cache_buffer - * Free cache buffer -*/ -//+------------------------------------------------------------------ -void DataVampire::free_cache_buffer(void) -{ - if (cache_buffer != NULL) { - for (int i = 0; i < *attr_CacheSize_read; i++) { - if (cache_buffer[i].databuf) - free(cache_buffer[i].databuf); - if (cache_buffer[i].datavalid) - free(cache_buffer[i].datavalid); - if (cache_buffer[i].sum) - free(cache_buffer[i].sum); - if (cache_buffer[i].mean) - free(cache_buffer[i].mean); - if (cache_buffer[i].horpos) - free(cache_buffer[i].horpos); - if (cache_buffer[i].verpos) - free(cache_buffer[i].verpos); - if (cache_buffer[i].horposstd) - free(cache_buffer[i].horposstd); - if (cache_buffer[i].verposstd) - free(cache_buffer[i].verposstd); - if (cache_buffer[i].validvalues) - free(cache_buffer[i].validvalues); - } - } - free(cache_buffer); - -} - - -//+------------------------------------------------------------------ -/** - * method: DataVampire::allocate_cache_buffer - * Allocate cache buffer -*/ -//+------------------------------------------------------------------ -void DataVampire::allocate_cache_buffer(void) -{ - if (cache_buffer != NULL) { - free_cache_buffer(); - } - - cache_buffer = (acq_buffer_t *) malloc(*attr_CacheSize_read * sizeof(acq_buffer_t)); - - for (int i = 0; i < *attr_CacheSize_read; i++) { - cache_buffer[i].databuf = 0; - cache_buffer[i].datavalid = 0; - cache_buffer[i].sum = 0; - cache_buffer[i].mean = 0; - cache_buffer[i].horpos = 0; - cache_buffer[i].verpos = 0; - cache_buffer[i].horposstd = 0; - cache_buffer[i].verposstd = 0; - cache_buffer[i].validvalues = 0; - clock_gettime(CLOCK_REALTIME, &cache_buffer[i].timerec); - cache_buffer[i].bn_start = 0; - cache_buffer[i].bn_end = 0; - cache_buffer[i].num_samples = 0; - cache_buffer[i].num_rows = 0; - cache_buffer[i].num_cols = 0; - cache_buffer[i].data_size = 0; - } - - cache_idx = 0; - -} - - -//+------------------------------------------------------------------ -/** - * method: DataVampire::store_data - * Allocate cache buffer -*/ -//+------------------------------------------------------------------ -void DataVampire::store_data(Tango::DeviceData *cmd_value, int32_t num_samples, int32_t bn_start, int32_t bn_end, int32_t *roi, struct acq_buffer_t **rec_data) -{ - std::vector<double> val; - std::vector<std::string> val_string; + // minimize risks of anomalies in num_cols/rows calculation + memcpy(roi, attr_RoiParam_read, 4 * sizeof(int32_t)); if (*attr_EnableAcquisition_read == false) { Tango::Except::throw_exception ( @@ -2120,14 +2310,14 @@ void DataVampire::store_data(Tango::DeviceData *cmd_value, int32_t num_samples, __FUNCTION__); } - clock_gettime(CLOCK_REALTIME, &cache_buffer[cache_idx].timerec); cmd_extract_values(cmd_value, val, val_string); int num_rows, num_cols; - if (roi_dim == 2) { - num_cols = roi[1] - roi[0] + 1; - num_rows = 1; + Tango::Except::throw_exception ( + (const char *)"Failed to store data", + (const char *)"Invalid ROI setting", + __FUNCTION__); } else { num_rows = roi[3]-roi[1]+1, @@ -2160,132 +2350,39 @@ void DataVampire::store_data(Tango::DeviceData *cmd_value, int32_t num_samples, } - // reallocate buffer - if (val.size() != cache_buffer[cache_idx].data_size) { - cache_buffer[cache_idx].databuf = (double *)realloc(cache_buffer[cache_idx].databuf, val.size() * sizeof(double)); - cache_buffer[cache_idx].datavalid = (bool *)realloc(cache_buffer[cache_idx].datavalid, val.size() * sizeof(bool)); - cache_buffer[cache_idx].data_size = val.size(); - cache_buffer[cache_idx].sum = (double *)realloc(cache_buffer[cache_idx].sum, num_samples * sizeof(double)); - cache_buffer[cache_idx].mean = (double *)realloc(cache_buffer[cache_idx].mean, num_samples * sizeof(double)); - cache_buffer[cache_idx].horpos = (double *)realloc(cache_buffer[cache_idx].horpos, num_samples * sizeof(double)); - cache_buffer[cache_idx].horposstd = (double *)realloc(cache_buffer[cache_idx].horposstd, num_samples * sizeof(double)); - if (num_rows > 1) { - cache_buffer[cache_idx].verpos = (double *)realloc(cache_buffer[cache_idx].verpos, num_samples * sizeof(double)); - cache_buffer[cache_idx].verposstd = (double *)realloc(cache_buffer[cache_idx].verposstd, num_samples * sizeof(double)); - } - cache_buffer[cache_idx].validvalues = (double *)realloc(cache_buffer[cache_idx].validvalues, num_samples * sizeof(double)); - } - - if (*attr_PostAcqRoi_read == false) { - for (int i = 0; i < cache_buffer[cache_idx].data_size; i++) { - cache_buffer[cache_idx].databuf[i] = val[i]; + vector <bool> data_valid; + if (*attr_PostAcqRoi_read == false) { + for (int i = 0; i < val.size(); i++) { if ((val[i] >= *attr_MinThreshold_read) && (val[i] <= *attr_MaxThreshold_read)) - cache_buffer[cache_idx].datavalid[i] = true; + data_valid.push_back(true); else - cache_buffer[cache_idx].datavalid[i] = false; + data_valid.push_back(false); } - } - // ROI is not supported by command inout so get all the image stream with command inout + // PostROI enabled else { int cnt = 0; - for (int i = 0; i < num_samples; i++) { int offset = wave_size * i; - //printf("num_samples = %d, wave_size = %d offset = %d val.size=%d\n",num_samples, wave_size, offset, val.size()); - double *data = &val[offset]; // ImageWidth must be defined because command_inout does not report the Image width/length values if ((*attr_Width_read > 0) && (roi_dim == 4)) { for (int j = roi[1]; j <= roi[3]; j++) { for (int k = roi[0]; k <= roi[2]; k++) { - cache_buffer[cache_idx].databuf[cnt] = data[j * *attr_Width_read + k]; - //cache_buffer[cache_idx].databuf[cnt] = k; - if ((data[j * *attr_Width_read + k] >= *attr_MinThreshold_read) && - (data[j * *attr_Width_read + k] <= *attr_MaxThreshold_read)) - cache_buffer[cache_idx].datavalid[cnt] = true; + val[cnt] = val[j * *attr_Width_read + k + offset]; + if ((val[cnt] >= *attr_MinThreshold_read) && + (val[cnt] <= *attr_MaxThreshold_read)) + data_valid.push_back(true); else - cache_buffer[cache_idx].datavalid[cnt] = false; - - + data_valid.push_back(false); cnt++; } } } - else if (roi_dim == 2) { - //printf("roi0 = %d roi1 = %d\n",roi[0],roi[1]); - for (int k = roi[0]; k <= roi[1]; k++) { - cache_buffer[cache_idx].databuf[cnt] = data[k]; - - if ((data[k] >= *attr_MinThreshold_read) && (data[k] <= *attr_MaxThreshold_read)) - cache_buffer[cache_idx].datavalid[cnt] = true; - else - cache_buffer[cache_idx].datavalid[cnt] = false; - cnt++; - } - } } - - - + wave_size = (double)cnt / (double)num_samples; } - - if (num_rows > 1) { - for (int i = 0; i < num_rows*num_cols; i++) { - attr_Image_read[i] = cache_buffer[cache_idx].databuf[i]; - } - num_rows_image = num_rows; - num_cols_image = num_cols; - } - - - /* performed in process_1D - else if (num_rows == 1) { - for (int i = 0; i < num_cols; i++) { - attr_Spectrum_read[i] = cache_buffer[cache_idx].databuf[i]; - } - num_cols_spectrum = num_cols; - }*/ - - cache_buffer[cache_idx].bn_start = bn_start; - cache_buffer[cache_idx].bn_end = bn_end; - cache_buffer[cache_idx].num_samples = num_samples; - if (roi_dim == 2) { - cache_buffer[cache_idx].num_rows = 1; - cache_buffer[cache_idx].num_cols = num_cols; - } - else if (roi_dim == 4) { - cache_buffer[cache_idx].num_rows = num_rows; - cache_buffer[cache_idx].num_cols = num_cols; - } - - if (cache_buffer[cache_idx].num_rows == 1) { - process_1D(cache_idx, *attr_AutoBackgroundSamples_read); - } - else if (cache_buffer[cache_idx].num_rows > 1) { - process_2D(cache_idx, *attr_AutoBackgroundSamples_read); - } - - *rec_data = &cache_buffer[cache_idx]; - - cache_idx++; - if (cache_idx >= *attr_CacheSize_read) - cache_idx = 0; - -} - - -void DataVampire::process_2D(int32_t cache_idx, int32_t auto_bck_samples) -{ - - int32_t num_rows = cache_buffer[cache_idx].num_rows; - int32_t num_cols = cache_buffer[cache_idx].num_cols; - - int32_t wave_size = num_rows * num_cols; - int32_t data_size = cache_buffer[cache_idx].data_size; - int32_t num_samples = cache_buffer[cache_idx].num_samples; - double *hor_profile_bck, *ver_profile_bck; uint32_t *hor_profile_bck_cnt, *ver_profile_bck_cnt; @@ -2307,39 +2404,35 @@ void DataVampire::process_2D(int32_t cache_idx, int32_t auto_bck_samples) if (auto_bck_samples) { // calculate horizontal background profile from top and bottom auto_bck_samples rows - for (int j = 0; j < *attr_AutoBackgroundSamples_read; j++) { + for (int j = 0; j < auto_bck_samples; j++) { for (int k = 0; k < num_cols; k++) { int idx = j*num_cols+k+wave_size*i; - if (cache_buffer[cache_idx].datavalid[idx]) { - hor_profile_bck[k] += cache_buffer[cache_idx].databuf[idx]; + if (data_valid[idx]) { + hor_profile_bck[k] += val[idx]; hor_profile_bck_cnt[k]++; } idx = (num_rows-j-1)*num_cols+k+wave_size*i; - if (cache_buffer[cache_idx].datavalid[idx]) { - hor_profile_bck[k] += cache_buffer[cache_idx].databuf[idx]; + if (data_valid[idx]) { + hor_profile_bck[k] += val[idx]; hor_profile_bck_cnt[k]++; } } } // calculate vertical background profile from left and right auto_bck_samples columns - for (int j = 0; j < *attr_AutoBackgroundSamples_read; j++) { + for (int j = 0; j < auto_bck_samples; j++) { // rows - for (int k = 0; k < num_rows; k++) { + for (int k = 0; k < num_rows; k++) { int idx = k*num_cols+j+wave_size*i; - if (cache_buffer[cache_idx].datavalid[idx]) { - ver_profile_bck[k] += cache_buffer[cache_idx].databuf[idx]; - //printf("k=%d ver_bck=%f idx=%d \n",k,cache_buffer[cache_idx].databuf[idx],idx); + if (data_valid[idx]) { + ver_profile_bck[k] += val[idx]; ver_profile_bck_cnt[k]++; } - //int idx2 = (num_rows-k-1)*num_cols-j+wave_size*i; int idx2 = idx + (num_cols - 1) - j; - if (cache_buffer[cache_idx].datavalid[idx2]) { - ver_profile_bck[k] += cache_buffer[cache_idx].databuf[idx2]; - //printf("k=%d ver_bck=%f idx2=%d \n",k,cache_buffer[cache_idx].databuf[idx2],idx2); + if (data_valid[idx2]) { + ver_profile_bck[k] += val[idx2]; ver_profile_bck_cnt[k]++; } - //printf("k=%d ver_bck=%f ver_bck_cnt=%d idx=%d idx2=%d\n",k,ver_profile_bck[k],ver_profile_bck_cnt[k],idx,idx2); } } @@ -2370,7 +2463,7 @@ void DataVampire::process_2D(int32_t cache_idx, int32_t auto_bck_samples) for (int j = 0; j < num_rows; j++) { for (int k = 0; k < num_cols; k++) { int idx = j * num_cols + k + wave_size*i; - cache_buffer[cache_idx].databuf[idx] -= hor_profile_bck[k]; + val[idx] -= hor_profile_bck[k]; } } @@ -2378,7 +2471,7 @@ void DataVampire::process_2D(int32_t cache_idx, int32_t auto_bck_samples) for (int j = 0; j < num_cols; j++) { for (int k = 0; k < num_rows; k++) { int idx = k * num_cols + j + wave_size*i; - cache_buffer[cache_idx].databuf[idx] -= ver_profile_bck[k]; + val[idx] -= ver_profile_bck[k]; } } @@ -2386,8 +2479,8 @@ void DataVampire::process_2D(int32_t cache_idx, int32_t auto_bck_samples) for (int j = 0; j < num_rows; j++) { for (int k = 0; k < num_cols; k++) { int idx = j * num_cols + k + wave_size*i; - if (cache_buffer[cache_idx].databuf[idx] < 0) - cache_buffer[cache_idx].databuf[idx] = 0; + if (val[idx] < 0) + val[idx] = 0; } } @@ -2403,14 +2496,17 @@ void DataVampire::process_2D(int32_t cache_idx, int32_t auto_bck_samples) for(int j = 0; j < num_rows; j++) { for(int k = 0; k < num_cols; k++) { int idx = j * num_cols + k + wave_size*i; - - if (i == 0) - attr_Image_read[idx] = cache_buffer[cache_idx].databuf[idx]; - - if (cache_buffer[cache_idx].datavalid[idx]) { - hor_pos += (cache_buffer[cache_idx].databuf[idx] * (k+1)); - ver_pos += (cache_buffer[cache_idx].databuf[idx] * (j+1)); - total_sum += cache_buffer[cache_idx].databuf[idx]; + + if (i == 0) { + if (data_valid[idx]) + attr_Image_read[idx] = val[idx]; + else + attr_Image_read[idx] = 0; + } + if (data_valid[idx]) { + hor_pos += (val[idx] * (k+1)); + ver_pos += (val[idx] * (j+1)); + total_sum += val[idx]; valid_values++; } } @@ -2431,26 +2527,32 @@ void DataVampire::process_2D(int32_t cache_idx, int32_t auto_bck_samples) std_ver_pos = pow(std_ver_pos / total_sum, 0.5); } - cache_buffer[cache_idx].sum[i] = total_sum; - - cache_buffer[cache_idx].mean[i] = total_sum / (double)valid_values; - cache_buffer[cache_idx].horpos[i] = hor_pos; - cache_buffer[cache_idx].verpos[i] = ver_pos; - cache_buffer[cache_idx].horposstd[i] = std_hor_pos; - cache_buffer[cache_idx].verposstd[i] = std_ver_pos; - cache_buffer[cache_idx].validvalues[i] = valid_values; + acq_array[array_idx].sum = total_sum; + acq_array[array_idx].mean = total_sum / (double)valid_values; + acq_array[array_idx].horpos = hor_pos; + acq_array[array_idx].verpos = ver_pos; + acq_array[array_idx].horposstd = std_hor_pos; + acq_array[array_idx].verposstd = std_ver_pos; + acq_array[array_idx].validvalues = valid_values; + + acq_array[array_idx].bn = bn_start + i; if (i == 0) { - *attr_Sum_read = cache_buffer[cache_idx].sum[i]; - *attr_Mean_read = cache_buffer[cache_idx].mean[i]; - *attr_HorPos_read = cache_buffer[cache_idx].horpos[i]; - *attr_VerPos_read = cache_buffer[cache_idx].verpos[i]; - *attr_HorPosStd_read = cache_buffer[cache_idx].horposstd[i]; - *attr_VerPosStd_read = cache_buffer[cache_idx].verposstd[i]; - *attr_ValidValues_read = cache_buffer[cache_idx].validvalues[i]; + *attr_Sum_read = acq_array[array_idx].sum; + *attr_Mean_read = acq_array[array_idx].mean; + *attr_HorPos_read = acq_array[array_idx].horpos; + *attr_VerPos_read = acq_array[array_idx].verpos; + *attr_HorPosStd_read = acq_array[array_idx].horposstd; + *attr_VerPosStd_read = acq_array[array_idx].verposstd; + *attr_ValidValues_read = acq_array[array_idx].validvalues; } - + last_bn = acq_array[array_idx].bn; + + array_idx++; + if (array_idx >= DATAVAMPIRE_MAX_SIZE) + array_idx = 0; + } free(hor_profile_bck); @@ -2461,17 +2563,87 @@ void DataVampire::process_2D(int32_t cache_idx, int32_t auto_bck_samples) } -void DataVampire::process_1D(int32_t cache_idx, int32_t auto_bck_samples) +void DataVampire::store_array_1D(Tango::DeviceData *cmd_value, int32_t bn_start, int32_t bn_end) { - int32_t wave_size = cache_buffer[cache_idx].num_rows * - cache_buffer[cache_idx].num_cols; - int32_t num_samples = cache_buffer[cache_idx].num_samples; - int32_t data_size = cache_buffer[cache_idx].data_size; + std::vector<double> val; + std::vector<std::string> val_string; + int32_t num_samples = bn_end - bn_start + 1; + int32_t roi[2]; + int32_t auto_bck_samples = *attr_AutoBackgroundSamples_read; + + + if (roi_dim != 2) { + Tango::Except::throw_exception ( + (const char *)"Failed to store data", + (const char *)"Invalid ROI dimension", + __FUNCTION__); + } + + // minimize risks of anomalies in num_cols/rows calculation + memcpy(roi, attr_RoiParam_read, 2 * sizeof(int32_t)); + + if (*attr_EnableAcquisition_read == false) { + Tango::Except::throw_exception ( + (const char *)"Failed to store data", + (const char *)"Acquisition is disabled", + __FUNCTION__); + } + + cmd_extract_values(cmd_value, val, val_string); + + int num_rows, num_cols; + if (roi_dim == 2) { + num_cols = roi[1] - roi[0] + 1; + num_rows = 1; + } + else { + Tango::Except::throw_exception ( + (const char *)"Failed to store data", + (const char *)"Invalid ROI setting", + __FUNCTION__); + } - //printf("GG 1 process_1D cache_idx=%d num_cols=%d\n",cache_idx,cache_buffer[cache_idx].num_cols); + int32_t wave_size = val.size() / num_samples; - // for spectrum display - num_cols_spectrum = cache_buffer[cache_idx].num_cols; + if (((num_cols * num_rows * num_samples) != val.size()) && (*attr_PostAcqRoi_read == false)) { + Tango::Except::throw_exception ( + (const char *)"Failed to store data", + (const char *)"Data size does not match roi setting", + __FUNCTION__); + } + + if (((num_cols * num_rows * num_samples) > val.size()) && (*attr_PostAcqRoi_read == true)) { + Tango::Except::throw_exception ( + (const char *)"Failed to store data", + (const char *)"Data size too large", + __FUNCTION__); + } + + vector <bool> data_valid; + + if (*attr_PostAcqRoi_read == false) { + for (int i = 0; i < val.size(); i++) { + if ((val[i] >= *attr_MinThreshold_read) && (val[i] <= *attr_MaxThreshold_read)) + data_valid.push_back(true); + else + data_valid.push_back(false); + } + } + else { + int cnt = 0; + for (int i = 0; i < num_samples; i++) { + int offset = wave_size * i; + for (int k = roi[0]; k <= roi[1]; k++) { + val[cnt] = val[k+offset]; + if ((val[cnt] >= *attr_MinThreshold_read) && (val[cnt] <= *attr_MaxThreshold_read)) + data_valid.push_back(true); + else + data_valid.push_back(false); + cnt++; + } + } + wave_size = (double)cnt / (double)num_samples; + } for (int i = 0; i < num_samples; i++) { double sum = 0; @@ -2485,17 +2657,19 @@ void DataVampire::process_1D(int32_t cache_idx, int32_t auto_bck_samples) double pos = 0; double std = 0; int cnt_left = 0, cnt_right = 0, cnt = 0; - double valid_values = 0; + int32_t valid_values = 0; + + // calculate backround level as a slope if (auto_bck_samples) { for (int j = 0; j < auto_bck_samples; j++) { - if (cache_buffer[cache_idx].datavalid[i*wave_size+j]) { - double val = cache_buffer[cache_idx].databuf[i*wave_size+j]; - sum_left += val; + if (data_valid[i*wave_size+j]) { + double vald = val[i*wave_size+j]; + sum_left += vald; cnt_left++; } - if (cache_buffer[cache_idx].datavalid[i*wave_size+j]) { - double val = cache_buffer[cache_idx].databuf[i*wave_size+(wave_size-auto_bck_samples)+j]; - sum_right += val; + if (data_valid[i*wave_size+j]) { + double vald = val[i*wave_size+(wave_size-auto_bck_samples)+j]; + sum_right += vald; cnt_right++; } } @@ -2506,7 +2680,7 @@ void DataVampire::process_1D(int32_t cache_idx, int32_t auto_bck_samples) if (cnt_right) sum_right /= (double)cnt_right; else - sum_right = 0; + sum_right = 0; if (auto_bck_samples > 0) { slope = (sum_right - sum_left) / @@ -2518,130 +2692,282 @@ void DataVampire::process_1D(int32_t cache_idx, int32_t auto_bck_samples) else { slope = 0; offset = 0; } - } - - + } + num_cols_spectrum = num_cols; // get sum, mean and position - for (int j = 0; j < cache_buffer[cache_idx].num_cols; j++) { + for (int j = 0; j < num_cols; j++) { //printf("j=%d idx=%d\n",j,i*wave_size+j); - double val = (cache_buffer[cache_idx].databuf[i*wave_size+j] + slope * (double)(cache_buffer[cache_idx].num_cols - j) - offset); + double vald; + + if (sum_left >= sum_right) + vald = (val[i*wave_size+j] + slope * (double)(num_cols - j) - offset); + else + vald = (val[i*wave_size+j] - slope * (double)(j) - offset); + // for spectrum displaying - if (i == 0) - attr_Spectrum_read[j] = val; - - if (cache_buffer[cache_idx].datavalid[i*wave_size+j]) { - sum += val; - pos += val * (double)(j + 1); - cnt++; + if (i == 0) { + if (data_valid[i*wave_size+j]) { + attr_Spectrum_read[j] = vald; + } + else + attr_Spectrum_read[j] = 0; + } + + if (data_valid[i*wave_size+j]) { + sum += vald; + pos += vald * (double)(j + 1); + valid_values++; } } - mean = sum / (double) cnt; + mean = sum / (double) valid_values; pos /= sum; - // get std cnt = 0; - for (int j = 0; j < cache_buffer[cache_idx].num_cols; j++) { - double val = (cache_buffer[cache_idx].databuf[i*wave_size+j] + slope * (double)j - offset); - if (cache_buffer[cache_idx].datavalid[i*wave_size+j]) { + for (int j = 0; j < num_cols; j++) { + double vald = (val[i*wave_size+j] + slope * (double)j - offset); + if (val[i*wave_size+j]) { std += ((double)j - pos) * ((double)j - pos); cnt++; } } if (cnt != 0) std = pow(std / (double) cnt, 0.5); - else + else std = 0; - cache_buffer[cache_idx].sum[i] = sum; - cache_buffer[cache_idx].mean[i] = mean; - cache_buffer[cache_idx].horpos[i] = pos; - cache_buffer[cache_idx].horposstd[i] = std; - cache_buffer[cache_idx].validvalues[i] = cnt; + acq_array[array_idx].sum = sum; + acq_array[array_idx].mean = mean; + acq_array[array_idx].horpos = pos; + acq_array[array_idx].horposstd = std; + acq_array[array_idx].validvalues = valid_values; + + // set bunch number + acq_array[array_idx].bn = bn_start + i; + + if (i == 0) { + *attr_Sum_read = acq_array[array_idx].sum; + *attr_Mean_read = acq_array[array_idx].mean; + *attr_HorPos_read = acq_array[array_idx].horpos; + *attr_HorPosStd_read = acq_array[array_idx].horposstd; + *attr_ValidValues_read = acq_array[array_idx].validvalues; + } + last_bn = acq_array[array_idx].bn; + + array_idx++; + if (array_idx >= DATAVAMPIRE_MAX_SIZE) + array_idx = 0; } + } - //+------------------------------------------------------------------ /** - * method: DataVampire::recover_data - * Recover data + * method: DataVampire::store_circ_data + * Store data into circular buffer */ //+------------------------------------------------------------------ -void DataVampire::recover_data(const Tango::DevVarLongArray *argin, struct acq_buffer_t **rec_data) +void DataVampire::store_circ_data(int32_t mode, int32_t num_samples, int32_t bn_start, int32_t bn_end) { - std::vector<double> cmd_input_value; std::vector<std::string> cmd_input_value_str; std::vector<double> cmd_output_value; std::vector<std::string> cmd_output_value_str; - struct acq_buffer_t *tmp; - - int32_t mode, num_samples, bn_start, bn_end, roi[4]; - - for (unsigned int i = 0; i < argin->length(); i++) { - cmd_input_value.push_back((*argin)[i]); - } + cmd_input_value.push_back(mode); + // get last mode + if (mode == 0) { + cmd_input_value.push_back(num_samples); + // simulate the bunch number for store_array_2D function + bn_start = last_bn + 1; + bn_end = last_bn + num_samples; + // if polling enabled let only the polling thread fill the buffer + if (*attr_EnablePolling_read) { + return; + } + } + // get data from bn_start to bn_end + else if (mode == 1) { + cmd_input_value.push_back(bn_start); + cmd_input_value.push_back(bn_end); + } + else { + INFO_STREAM << "Not supported mode " << mode << endl; + Tango::Except::throw_exception( + (const char *) "Failed to store data", + (const char *) "Not supported mode", + __FUNCTION__, Tango::ERR); + } - if (*attr_PostAcqRoi_read == false) { + // data not present + if (bn_end < bn_start) { + return; + } + + if ((*attr_PostAcqRoi_read) == false) { + // add ROI info to params for (unsigned int i = 0; i < roi_dim; i++) { cmd_input_value.push_back(attr_RoiParam_read[i]); } + } + + /*for (int i = 0; i < cmd_input_value.size(); i++) { + printf("in %d %f\n",i, cmd_input_value[i]); + }*/ + + try { + // prepare input + Tango::DeviceData Din = cmd_insert_values(cmd_in_type, cmd_input_value, cmd_input_value_str); + // get data + Tango::DeviceData Dout = device->command_inout(command_name, Din); + + // store 1D & 2D data + int32_t num_samples = bn_end-bn_start+1; + if (roi_dim == 2) { + store_array_1D(&Dout, bn_start, bn_end); + } + else if (roi_dim == 4) { + store_array_2D(&Dout, bn_start, bn_end); + } + } + catch (Tango::DevFailed &e) { + INFO_STREAM << e.errors[0].desc << ", " << c_device_name << " " << command_name << endl; + INFO_STREAM << e.errors[0].reason << ", " << c_device_name << " " << command_name << endl; + Tango::Except::re_throw_exception(e, + (const char *) "Failed to store data", + (const char *) "Error storing data", + __FUNCTION__, Tango::ERR); + } + catch(...) { + Tango::Except::throw_exception( + (const char *) "Failed to store data", + (const char *) "Generic error", + __FUNCTION__, Tango::ERR); + } + +} + + +//+------------------------------------------------------------------ +/** + * method: DataVampire::get_start_index + * get_start_index + */ +//+------------------------------------------------------------------ +int32_t DataVampire::get_start_index(int32_t mode, int32_t num_samples, int32_t bn_start, int32_t bn_end) +{ + int32_t last_idx, start = -1, end = -1; + bool bn_found = false; + + // last valid sample index stored in circular buffer + last_idx = (array_idx - 1 + DATAVAMPIRE_MAX_SIZE) % DATAVAMPIRE_MAX_SIZE; + + if (mode == 0) { + return ((last_idx - num_samples + 1 + DATAVAMPIRE_MAX_SIZE) % DATAVAMPIRE_MAX_SIZE); + + } + else if (mode == 1) { + // first find the indexes of bn_start and bn_end + for (int i = 0; i < DATAVAMPIRE_MAX_SIZE; i++) { + int32_t idx = ((last_idx-i+DATAVAMPIRE_MAX_SIZE) % DATAVAMPIRE_MAX_SIZE); + if (acq_array[idx].bn == bn_end) { + end = idx; + } + if (acq_array[idx].bn == bn_start) { + start = idx; + } + if ((end != -1) && (start != -1)) { + bn_found = true; break; + } + } + + if (bn_found) { + return start; + } + else { + Tango::Except::throw_exception( + (const char *) "Failed to find buffer indexes", + (const char *) "Can't find start/end bunch numbers", + __FUNCTION__, Tango::ERR); + } + } + else { + Tango::Except::throw_exception( + (const char *) "Failed to find buffer indexes", + (const char *) "Buffer mode not supported", + __FUNCTION__, Tango::ERR); + } + +} + + +//+------------------------------------------------------------------ +/** + * method: DataVampire::get_param_in + * Get input parameters + */ +//+------------------------------------------------------------------ +void DataVampire::get_param_in(const Tango::DevVarLongArray *argin, int32_t *mode, int32_t *num_samples, int32_t *bn_start, int32_t *bn_end) +{ + int32_t arglen = argin->length(); + + *mode = ((*argin)[0] % 10) & 0x1; // 20->0 21->1 + + if (arglen == 2) { + *num_samples = (*argin)[1]; + *bn_start = 0; + *bn_end = 0; + + if (*mode != 0) { + Tango::Except::throw_exception( + (const char *) "Failed to parse input parameter", + (const char *) "Invalid mode (0)", + __FUNCTION__, Tango::ERR); + } + else { + if ((*num_samples < 1) || (*num_samples > DATAVAMPIRE_MAX_SIZE)) { + Tango::Except::throw_exception( + (const char *) "Failed to parse input parameter", + (const char *) "Invalid number of samples", + __FUNCTION__, Tango::ERR); + } + } } + else if (arglen == 3) { + *bn_start = (*argin)[1]; + *bn_end = (*argin)[2]; + *num_samples = *bn_end - *bn_start + 1; - Tango::DeviceData Din = cmd_insert_values(cmd_in_type, cmd_input_value, cmd_input_value_str); - - extract_input_parameters(argin, &mode, &num_samples, &bn_start, &bn_end, roi); - - Tango::DeviceData Dout = device->command_inout(command_name, Din); - - store_data(&Dout, num_samples, bn_start, bn_end, roi, rec_data); - -} - -// //-------------------------------------------------------- -// /** -// * Read attribute VerPosStd related method -// * Description: -// * -// * Data type: Tango::DevDouble -// * Attr type: Scalar -// */ -// //-------------------------------------------------------- -// void DataVampire::read_VerPosStd(Tango::Attribute &attr) -// { -// DEBUG_STREAM << "DataVampire::read_VerPosStd(Tango::Attribute &attr) entering... " << endl; -// /* clang-format on */ -// // Set the attribute value -// attr.set_value(attr_VerPosStd_read); -// /* clang-format off */ -// } - -// //-------------------------------------------------------- -// /** -// * Read attribute VerPosStd related method -// * Description: -// * -// * Data type: Tango::DevDouble -// * Attr type: Scalar -// */ -// //-------------------------------------------------------- -// void DataVampire::read_VerPosStd(Tango::Attribute &attr) -// { -// DEBUG_STREAM << "DataVampire::read_VerPosStd(Tango::Attribute &attr) entering... " << endl; -// /* clang-format on */ -// // Set the attribute value -// attr.set_value(attr_VerPosStd_read); -// /* clang-format off */ -// } + if (*mode != 1) { + Tango::Except::throw_exception( + (const char *) "Failed to parse input parameter", + (const char *) "Invalid mode (1)", + __FUNCTION__, Tango::ERR); + } + else { + if ((*num_samples < 1) || (*num_samples > DATAVAMPIRE_MAX_SIZE)) { + Tango::Except::throw_exception( + (const char *) "Failed to parse input parameter", + (const char *) "Invalid number of samples", + __FUNCTION__, Tango::ERR); + } + } + } + else { + Tango::Except::throw_exception( + (const char *) "Failed to parse input parameter", + (const char *) "Mode not recognized (0/1)", + __FUNCTION__, Tango::ERR); + } + +} /*----- PROTECTED REGION END -----*/ // DataVampire::namespace_ending diff --git a/src/DataVampire.h b/src/DataVampire.h index 838826d..986b13e 100644 --- a/src/DataVampire.h +++ b/src/DataVampire.h @@ -42,6 +42,8 @@ #define DATAVAMPIRE_MAX_STR_LEN 256 +#define DATAVAMPIRE_MAX_SIZE 200000 + class acqthread; @@ -73,37 +75,32 @@ class DataVampire : public TANGO_BASE_CLASS /* clang-format off */ public: - friend class acqthread; - struct acq_buffer_t + struct acq_array_t { - struct timespec timerec; - uint32_t bn_start, bn_end; - uint32_t num_samples; - uint32_t num_rows, num_cols; - uint32_t data_size; - double *databuf; - bool *datavalid; - double *sum; - double *mean; - double *horpos; - double *verpos; - double *horposstd; - double *verposstd; - double *validvalues; + int32_t bn; + double sum; + double mean; + double horpos; + double verpos; + double horposstd; + double verposstd; + double validvalues; }; + int array_idx = 0; + acq_array_t acq_array[DATAVAMPIRE_MAX_SIZE]; Tango::DeviceProxy *device, *bn_device; - std::string device_name, command_name, bn_device_name, bn_attr_name; + std::string c_device_name, command_name, bn_device_name, bn_attr_name; - acq_buffer_t *cache_buffer; - uint32_t cache_idx, roi_dim; + uint32_t roi_dim; long cmd_in_type, cmd_out_type; int32_t num_rows_image, num_cols_image, num_cols_spectrum; + int32_t last_bn; + double frequency; omni_mutex *mutex; - bool abort_flag; acqthread *acqloop; @@ -550,16 +547,12 @@ Tango::DeviceData cmd_insert_values(long cmd_type, std::vector<double> val, std: void string_explode(std::string str, std::string separator, std::vector<std::string>* results); void store_roi_param(const Tango::DevLong *w_val, int size); void store_command_string(Tango::DevString w_val); -void extract_input_parameters(const Tango::DevVarLongArray *argin, int32_t *mode, int32_t *num_samples, int32_t *bn_start, int32_t *bn_end, int32_t *roi); -void free_cache_buffer(void); -void allocate_cache_buffer(void); -void store_data(Tango::DeviceData *cmd_value, int32_t num_samples, int32_t bn_start, int32_t bn_end, int32_t *roi, struct acq_buffer_t **rec_data); -void process_2D(int32_t cache_idx, int32_t auto_bck_samples); -void process_1D(int32_t cache_idx, int32_t auto_bck_samples); void recover_data(const Tango::DevVarLongArray *argin, struct acq_buffer_t **rec_data); - - - +void get_param_in(const Tango::DevVarLongArray *argin, int32_t *mode, int32_t *num_samples, int32_t *bn_start, int32_t *bn_en); +void store_circ_data(int32_t mode, int32_t num_samples, int32_t bn_start, int32_t bn_end); +void store_array_1D(Tango::DeviceData *cmd_value, int32_t bn_start, int32_t bn_end); +void store_array_2D(Tango::DeviceData *cmd_value, int32_t bn_start, int32_t bn_end); +int32_t get_start_index(int32_t mode, int32_t num_samples, int32_t bn_start, int32_t bn_end); diff --git a/src/DataVampire.xmi b/src/DataVampire.xmi index 88be59f..e078e97 100644 --- a/src/DataVampire.xmi +++ b/src/DataVampire.xmi @@ -141,7 +141,7 @@ <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> <properties description="" label="" unit="" standardUnit="" displayUnit="" format="%.5f" maxValue="9.99e10" minValue="-9.99e10" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> </attributes> - <attributes name="CommandString" attType="Scalar" rwType="READ_WRITE" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" memorized="true" memorizedAtInit="true" allocReadMember="true" isDynamic="false"> + <attributes name="CommandString" attType="Scalar" rwType="READ_WRITE" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> <dataType xsi:type="pogoDsl:StringType"/> <changeEvent fire="false" libCheckCriteria="false"/> <archiveEvent fire="false" libCheckCriteria="false"/> diff --git a/src/DataVampireClass.cpp b/src/DataVampireClass.cpp index 070669a..380de52 100644 --- a/src/DataVampireClass.cpp +++ b/src/DataVampireClass.cpp @@ -615,8 +615,7 @@ void DataVampireClass::attribute_factory(vector<Tango::Attr *> &att_list) commandstring->set_default_properties(commandstring_prop); // Not Polled commandstring->set_disp_level(Tango::OPERATOR); - commandstring->set_memorized(); - commandstring->set_memorized_init(true); + // Not Memorized att_list.push_back(commandstring); // Attribute : PollingPeriod diff --git a/src/acqthread.cpp b/src/acqthread.cpp index 186e56a..dd2618d 100644 --- a/src/acqthread.cpp +++ b/src/acqthread.cpp @@ -13,12 +13,46 @@ */ void *acqthread::run_undetached(void *) { - + int margin = 2; + double frequency = 50; + int32_t old_bn = 0; + Tango::DevLong bunch_number; + + try { + if (myobj->bn_device) { + myobj->bn_device->read_attribute(myobj->bn_attr_name) >> bunch_number; + old_bn = bunch_number - frequency + 1; + } + } + catch(...){} while (myobj->abort_flag == false) { - - sleep(1); - + if (*myobj->attr_EnablePolling_read) { + try { + myobj->mutex->lock(); + if (myobj->bn_device) { + myobj->bn_device->read_attribute(myobj->bn_attr_name) >> bunch_number; + int32_t bn_start = myobj->last_bn + 1; + int32_t bn_end = bunch_number - margin; + if ((bn_end - bn_start) > frequency) + bn_start = bn_end - frequency + 1; + myobj->store_circ_data(1, 0, bn_start, bn_end); + } + else { + // last mode, bn_start/bn_end equal to 0 + myobj->store_circ_data(0, *myobj->attr_PollingSamples_read, 0, 0); + } + myobj->mutex->unlock(); + usleep(*myobj->attr_PollingPeriod_read * 1000); + } + // sleep on error + catch(...) { myobj->mutex->unlock();sleep(1);} + + } + // sleep when polling disabled + else { + sleep(1); + } } -- GitLab