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