Skip to content
158 changes: 148 additions & 10 deletions camerad/archon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,108 @@ namespace Archon {
}
/**************** Archon::Interface::interface ******************************/

/***** Archon::Interface::do_power ******************************************/
/**
* @brief set/get the power state
* @param[in] state_in input string contains requested power state
* @param[out] retstring return string contains the current power state
* @return ERROR or NO_ERROR
*
*/
long Interface::do_power(std::string state_in, std::string &retstring) {
std::string function = "Archon::Interface::do_power";
std::stringstream message;
long error = ERROR;

if ( !this->archon.isconnected() ) { // nothing to do if no connection open to controller
this->camera.log_error( function, "connection not open to controller" );
return( ERROR );
}

// set the Archon power state as requested
//
if ( !state_in.empty() ) { // received something
std::transform( state_in.begin(), state_in.end(), state_in.begin(), ::toupper ); // make uppercase
if ( state_in == "ON" ) {
error = this->archon_cmd( POWERON ); // send POWERON command to Archon
if ( error == NO_ERROR ) std::this_thread::sleep_for( std::chrono::seconds(2) ); // wait 2s to ensure power is stable
}
else
if ( state_in == "OFF" ) {
error = this->archon_cmd( POWEROFF ); // send POWEROFF command to Archon
if ( error == NO_ERROR ) std::this_thread::sleep_for( std::chrono::milliseconds(200) ); // wait 200ms to ensure power is off
}
else {
message.str(""); message << "unrecognized argument " << state_in << ": expected {on|off}";
this->camera.log_error( function, message.str() );
return( ERROR );
}
if ( error != NO_ERROR ) {
message.str(""); message << "setting Archon power " << state_in;
this->camera.log_error( function, message.str() );
return( ERROR );
}
}

// Read the Archon power state directly from Archon
//
std::string power;
error = get_status_key( "POWER", power );

if ( error != NO_ERROR ) return( ERROR );

int status=-1;

try { status = std::stoi( power ); }
catch (std::invalid_argument &) {
this->camera.log_error( function, "unable to convert power status message to integer" );
return(ERROR);
}
catch (std::out_of_range &) {
this->camera.log_error( function, "power status out of range" );
return(ERROR);
}

// set the power status (or not) depending on the value extracted from the STATUS message
//
switch( status ) {
case -1: // no POWER token found in status message
this->camera.log_error( function, "unable to find power in Archon status message" );
return( ERROR );
case 0: // usually an internal error
this->camera.power_status = "UNKNOWN";
break;
case 1: // no configuration applied
this->camera.power_status = "NOT_CONFIGURED";
break;
case 2: // power is off
this->camera.power_status = "OFF";
break;
case 3: // some modules powered, some not
this->camera.power_status = "INTERMEDIATE";
break;
case 4: // power is on
this->camera.power_status = "ON";
break;
case 5: // system is in standby
this->camera.power_status = "STANDBY";
break;
default: // should be impossible
message.str(""); message << "unknown power status: " << status;
this->camera.log_error( function, message.str() );
return( ERROR );
}

message.str(""); message << "POWER:" << this->camera.power_status;
this->camera.async.enqueue( message.str() );

retstring = this->camera.power_status;

return(NO_ERROR);
}
/***** Archon::Interface::do_power ******************************************/



/***** Archon::Interface::configure_controller ******************************/
/**
Expand Down Expand Up @@ -3532,6 +3634,46 @@ namespace Archon {
/**************** Archon::Interface::add_filename_key ***********************/


/***** Archon::Interface::get_status_key ************************************/
/**
* @brief get value for the indicated key from the Archon "STATUS" string
* @param[in] key key to extract from STATUS
* @param[out] value value of key
* @return ERROR or NO_ERROR
*
*/
long Interface::get_status_key( std::string key, std::string &value ) {
std::string function = "Archon::Interface::get_status_key";
std::stringstream message;
std::string reply;

long error = this->archon_cmd( STATUS, reply ); // first the whole reply in one string

if ( error != NO_ERROR ) return error;

std::vector<std::string> lines, tokens;
Tokenize( reply, lines, " " ); // then each line in a separate token "lines"

for ( auto line : lines ) {
Tokenize( line, tokens, "=" ); // break each line into tokens to get KEY=value
if ( tokens.size() != 2 ) continue; // need 2 tokens
try {
if ( tokens.at(0) == key ) { // looking for the KEY
value = tokens.at(1); // found the KEY= status here
break; // done looking
} else continue;
}
catch (std::out_of_range &) { // should be impossible
this->camera.log_error( function, "token out of range" );
return(ERROR);
}
}

return( NO_ERROR );
}
/***** Archon::Interface::get_status_key ************************************/


/**************** Archon::Interface::expose *********************************/
/**
* @fn expose
Expand Down Expand Up @@ -3906,9 +4048,9 @@ namespace Archon {
* @return ERROR or NO_ERROR
*
* NOTE: this assumes LVDS is module 10
* This function does the following:
* 1) Pulse low on MainResetB
* 2) sets output to Pad B and HIGHOHM
* This function sets output to Pad B and HIGHOHM
* The register reset of H2RGMainReset is already done
* if you power on and then setp Start 1
*
*/
long Interface::hsetup() {
Expand All @@ -3917,17 +4059,13 @@ namespace Archon {
std::string reg;
long error = NO_ERROR;

// H2RG manual says to pull this value low for 100 ns
// however, currently it is pulled low for ~1000 usec
this->set_parameter("H2RGMainReset", 1);
usleep(1500); // to be sure we are done with the reset
this->set_parameter("H2RGMainReset", 0);
usleep(1000); // to be sure we are done with the reset

// Enable output to Pad B and HIGHOHM
error = this->inreg("10 1 16402"); // 0100 000000010010
std::this_thread::sleep_for(std::chrono::seconds(1));
if (error == NO_ERROR) error = this->inreg("10 0 1"); // send to detector
std::this_thread::sleep_for(std::chrono::seconds(1));
if (error == NO_ERROR) error = this->inreg("10 0 0"); // reset to 0
std::this_thread::sleep_for(std::chrono::seconds(1));

if (error != NO_ERROR) {
message.str(""); message << "enabling output to Pad B and HIGHOHM";
Expand Down
5 changes: 5 additions & 0 deletions camerad/archon.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,11 @@ namespace Archon {

void add_filename_key();

long get_status_key( std::string key, std::string &value ); /// get value for indicated key from STATUS string

long power( std::string state_in, std::string &retstring ); /// wrapper for do_power
long do_power( std::string state_in, std::string &retstring ); /// set/get Archon power state

long expose(std::string nseq_in);

long hexpose(std::string nseq_in);
Expand Down
2 changes: 2 additions & 0 deletions camerad/camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ namespace Camera {
std::map<int, int> readout_time;
//!< readout time in msec for given controller device number, read from .cfg file

std::string power_status; //!< archon power status

void log_error(std::string function, std::string message);

std::string get_longerror();
Expand Down
6 changes: 6 additions & 0 deletions camerad/camerad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -787,6 +787,12 @@ void doit(Network::TcpSocket sock) {
ret = server.interface(retstring);
sock.Write(retstring);
sock.Write(" ");
} else if (cmd =="power") {
ret = server.power( args, retstring );
if (!retstring.empty()) {
sock.Write(retstring);
sock.Write(" ");
}
} else if (cmd == "test") {
ret = server.test(args, retstring);
if (!retstring.empty()) {
Expand Down
19 changes: 19 additions & 0 deletions camerad/generic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,23 @@ namespace Archon {
}

/**************** Archon::Interface::region_of_interest *****************/


/***** Archon::Interface::power *****************************************/
/**
* @brief wrapper for Archon::Interface::do_power()
* @param[in] state_in requested power state
* @param[out] restring return string holds power state
* @return ERROR or NO_ERROR
*
*/
long Interface::power( std::string state_in, std::string &retstring ) {
std::string function = "Archon::Instrument::power";
std::stringstream message;

// use Archon::Interface::do_power() to set/get the power
//
return( this->do_power( state_in, retstring ) );
}
/***** Archon::Interface::power *****************************************/
}