Commit 7af972ae authored by Achim Morschhauser's avatar Achim Morschhauser
Browse files

ADC calibrate #7 save cal working

parent 9a7f6786
......@@ -31,8 +31,14 @@ private:
/** ADC calibration constant */
struct adc_cal {
std::string offset;
std::string scale;
std::string offset;
bool operator==(const adc_cal& a) const {
return (scale == a.scale && offset == a.offset);
}
};
/** Map containing the ADC calibration key-value pairs */
......@@ -99,6 +105,8 @@ public:
/** Set the internal ADC calibration file */
int set_adc_calibrate(std::string filename);
/** Get the internal ADC calibration file */
std::string get_adc_calibrate();
};
......
......@@ -163,6 +163,9 @@ int init();
/** Prepare continuous data acquisition **/
int init_run(double freq);
/** Automatically calibrate the ObsDAQ with given config*/
int auto_calibrate(int channel, int repeat, std::string config);
};
#endif /* _DRIVER_OBS_OBSDAQ_H */
// C++ headers
#include <string> // String
#include <iostream> // String streams
#include <iostream> // I/O
#include <sstream> // String streams
#include <fstream> // File operations
#include <unordered_map>
......@@ -164,13 +165,13 @@ int Obs_Calibration_Vector::add_adc_calibrate(std::string config,
cal.scale = scale;
// Check if already exists
if (map_ADC.count(config)>0) {
map_ADC[config]=cal;
} else {
std::cerr << "Calibration for " << config << " overwritten.";
std::cerr << "Calibration for " << config << " overwritten."
<< std::endl;
}
map_ADC[config]=cal;
return(0);
}
......@@ -188,13 +189,20 @@ int Obs_Calibration_Vector::add_adc_calibrate(std::string config,
* file. Comment out duplicates instead of overwriting.
*/
std::ifstream file_buf(filename);
std::ifstream file_in(filename);
std::ofstream file_out;
std::string line, config, comment;
std::stringstream buf_in;
size_t pos_c;
struct adc_cal cal;
struct adc_cal cal, cal_buf;
// Copy the file to stringstream
if (file_in) {
buf_in << file_in.rdbuf();
file_in.close();
}
// Copy the hash map
// The copy will be used to track what has been written to file
......@@ -204,22 +212,30 @@ int Obs_Calibration_Vector::add_adc_calibrate(std::string config,
file_out.open(filename,std::ios::out | std::ios::trunc);
// Read from buffered file
while ( getline (file_buf,line) ) {
while ( getline (buf_in,line) ) {
// Parse from line
if (parse_adc_calibration(line,config,cal,comment) < 0){
// Comment line
if (parse_adc_calibration(line,config,cal_buf,comment) < 0){
file_out << line << std::endl;
} else {
// Configuration exists and is overwritten
// Configuration exists
if (map_ADC_cpy.count(config)>0) {
file_out << "#" << line << std::endl;
cal=map_ADC_cpy[config];
map_ADC_cpy.erase(config);
// Existing config is the same
if (cal==cal_buf){
file_out << line << std::endl;
// Existing config is different
} else {
file_out << "#" << line << std::endl;
file_out << config << "," << cal.offset << "," <<
cal.scale << ";" << comment << std::endl;
}
// Configuration doesn't exist
} else {
......@@ -230,6 +246,13 @@ int Obs_Calibration_Vector::add_adc_calibrate(std::string config,
}
// Write all remaining configurations
for (auto& i : map_ADC_cpy){
file_out << i.first << "," << i.second.scale << ","
<< i.second.offset << ";" << std::endl;
}
file_out.close();
......@@ -318,10 +341,10 @@ int Obs_Calibration_Vector::add_adc_calibrate(std::string config,
// Find calibration string
line=line.substr(pos_c+1);
pos_c=line.find(',');
cal.offset = line.substr(0,pos_c);
cal.scale = line.substr(0,pos_c);
line=line.substr(pos_c+1);
pos_c=line.find(';');
cal.scale = line.substr(0,pos_c);
cal.offset = line.substr(0,pos_c);
return(0);
}
......@@ -343,3 +366,9 @@ int Obs_Calibration_Vector::add_adc_calibrate(std::string config,
return(0);
}
std::string Obs_Calibration_Vector::get_adc_calibrate() {
return(file_ADC);
}
\ No newline at end of file
......@@ -29,6 +29,7 @@
#include <buffer_obs.hpp> // Buffer for data
#include <data_obs_vector.hpp> // Vector data structure
#include <driver_obs_obsdaq.hpp> // Generic observatory driver
#include <Obs_Calibration_Vector.hpp> // Calibration routines
/*******************************************************************************
*******************************************************************************
......@@ -414,7 +415,8 @@ int driver_obs_obsdaq::stop() {
* Individual calibration steps are averaged.
*
***************************************************************************/
int driver_obs_obsdaq::auto_calibrate(int channel, int repeat){
int driver_obs_obsdaq::auto_calibrate(int channel, int repeat,
std::string config){
/////////////////////////////////////////////////////////////////////////
//
......@@ -428,6 +430,8 @@ int driver_obs_obsdaq::auto_calibrate(int channel, int repeat){
// The calibration constants
double offset=0, scale=0;
// Calibration constants as string
std::string offset_str, scale_str;
/////////////////////////////////////////////////////////////////////////
//
......@@ -465,31 +469,31 @@ int driver_obs_obsdaq::auto_calibrate(int channel, int repeat){
while (checked_send(cmd,"R0",2,5)<0){
}
// Read the offset value
// Read the full-scale value
sprintf(cmd,"$%1dRO",channel);
sprintf(cmd,"$%1dRF",channel);
send(cmd);
//TODO Repeat loop instead of just omitting
if (receive(recv,sizeof(recv),5)==0) {
// Parse the offset value and add to average
// Parse the full-scale value and add to average
n32 = (uint32_t) strtoul(&recv[3], NULL, 16);
num=0x800000L;
offset += (double) (n32 ^ num) - (double) num;
scale += (double) (n32 ^ num) - (double) num;
}
// Necessary to avoid time outs
// Necessary to avoid timeouts
usleep(1e6);
// Read the full-scale value
// Read the offset value
sprintf(cmd,"$%1dRF",channel);
sprintf(cmd,"$%1dRO",channel);
send(cmd);
//TODO Repeat loop instead of just omitting
if (receive(recv,sizeof(recv),5)==0) {
// Parse the full-scale value and add to average
// Parse the offset value and add to average
n32 = (uint32_t) strtoul(&recv[3], NULL, 16);
num=0x800000L;
scale += (double) (n32 ^ num) - (double) num;
offset += (double) (n32 ^ num) - (double) num;
}
}
......@@ -499,21 +503,32 @@ int driver_obs_obsdaq::auto_calibrate(int channel, int repeat){
// OBSDAQ.
//
// Offset
// Full-scale
n32 = ((int32_t) (scale/repeat) + (int32_t) 0x800000L)
^ (int32_t) 0x800000L ;
sprintf(cmd,"$%1dWF%06X",channel,n32);
send(cmd);
scale_str=offset_str.substr(4,6);
waitanswer(1);
std::cerr << "Set offset: " << scale/repeat << " " << cmd << std::endl;
std::cerr << "Set scale: " << scale/repeat << " " << cmd << std::endl;
// Full-scale
// Offset
n32 = ((int32_t) (offset/repeat) + (int32_t) 0x800000L)
^ (int32_t) 0x800000L;
sprintf(cmd,"$%1dWO%06X",channel,n32);
send(cmd);
offset_str=std::string(cmd).substr(4,6);
waitanswer(1);
std::cerr << "Set scale: " << scale/repeat << " " << cmd << std::endl;
std::cerr << "Set offset: " << offset/repeat << " " << cmd << std::endl;
/////////////////////////////////////////////////////////////////////////
//
// Store the new calibration values
//
/////////////////////////////////////////////////////////////////////////
cal->add_adc_calibrate(config,offset_str,scale_str);
return(0);
......@@ -1103,6 +1118,7 @@ int driver_obs_obsdaq::init_run(double freq){
// Iterate over all three channels
for (int i=0; i<3; i++){
// Get current 24-bit configuration (Manual 12.4.9)
flush();
sprintf(cmd,"$%1dRS",i);
send(cmd);
receive(recv,sizeof(recv),5);
......@@ -1119,7 +1135,7 @@ int driver_obs_obsdaq::init_run(double freq){
if (driver_obs::cal->get_adc_calibrate
(config, adc_offset, adc_scale)<0){
// Automatic Calibration
auto_calibrate(i,1);
auto_calibrate(i,1,config);
auto_cal=1;
} else {
// Set the pre-determined calibration constant
......@@ -1134,7 +1150,11 @@ int driver_obs_obsdaq::init_run(double freq){
}
// Save calibration constants
if (auto_cal) driver_obs::cal->save_adc_calibrate();
if (auto_cal) {
driver_obs::cal->save_adc_calibrate();
std::cerr << "New calibration constants written to "
<< cal->get_adc_calibrate() << std::endl;
}
/////////////////////////////////////////////////////////////////////////
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment