511 lines
18 KiB
C++
511 lines
18 KiB
C++
/* **************************************************************************
|
|
|
|
Author: Achim Gaedke
|
|
Created: June 2004
|
|
|
|
****************************************************************************/
|
|
#include "SpinCore-PulseBlasterDDSIII.h"
|
|
#include <cmath>
|
|
#include <typeinfo>
|
|
#include <iterator>
|
|
#include "core/core.h"
|
|
#include "core/states.h"
|
|
|
|
/*********************************************************************
|
|
|
|
PulseBlasterDDSIIICommand
|
|
|
|
*********************************************************************/
|
|
|
|
PulseBlasterDDSIIICommand::PulseBlasterDDSIIICommand() {
|
|
instruction=SpinCorePulseBlaster::CONTINUE;
|
|
length=0;
|
|
rx_phase_reg=0;
|
|
rx_enable=SpinCorePulseBlasterDDSIII::ANALOG_OFF;
|
|
tx_phase_reg=0;
|
|
tx_enable=SpinCorePulseBlasterDDSIII::ANALOG_OFF;
|
|
freq_reg=0;
|
|
ttls=0;
|
|
program=NULL;
|
|
}
|
|
|
|
PulseBlasterDDSIIICommand::PulseBlasterDDSIIICommand(const PulseBlasterDDSIIICommand& orig): PulseBlasterCommand(orig) {
|
|
rx_phase_reg=orig.rx_phase_reg;
|
|
rx_enable=orig.rx_enable;
|
|
tx_phase_reg=orig.tx_phase_reg;
|
|
tx_enable=orig.tx_enable;
|
|
freq_reg=orig.freq_reg;
|
|
}
|
|
|
|
|
|
PulseBlasterDDSIIICommand::PulseBlasterDDSIIICommand(PulseBlasterDDSIIIProgram& p,
|
|
double _frequency,
|
|
double _rx_phase, SpinCorePulseBlasterDDSIII::analog_state _rx_enable,
|
|
double _tx_phase, SpinCorePulseBlasterDDSIII::analog_state _tx_enable,
|
|
int _ttls, double _length)
|
|
:PulseBlasterCommand(p,_ttls,_length) {
|
|
rx_phase_reg=0;
|
|
tx_phase_reg=0;
|
|
freq_reg=0;
|
|
// allocate frequency and phases only if necessary
|
|
if (_rx_enable==SpinCorePulseBlasterDDSIII::ANALOG_ON || _tx_enable==SpinCorePulseBlasterDDSIII::ANALOG_ON) {
|
|
freq_reg=p.get_frequency_regno(_frequency);
|
|
// todo: be sure, whether tx_phase is really needed for DAC_OUT_0
|
|
// and so on...
|
|
//if (_rx_enable==SpinCorePulseBlasterDDSIII::ANALOG_ON)
|
|
rx_phase_reg=p.get_rx_phase_regno(_rx_phase);
|
|
//if (_tx_enable==SpinCorePulseBlasterDDSIII::ANALOG_ON)
|
|
tx_phase_reg=p.get_tx_phase_regno(_tx_phase);
|
|
}
|
|
rx_enable=_rx_enable;
|
|
tx_enable=_tx_enable;
|
|
}
|
|
|
|
|
|
int PulseBlasterDDSIIICommand::write_to_file(FILE* out, size_t indent) const {
|
|
|
|
if (program==NULL) throw pulse_exception("PulseBlasterDDSIII: Command not associated with Program");
|
|
fprintf(out,"%s<instruction frequency=\"%d\" rxphase=\"%d\" rxenable=\"%d\" txphase=\"%d\" txenable=\"%d\" ttls=\"%d\" ",
|
|
std::string(indent,' ').c_str(),freq_reg,rx_phase_reg,rx_enable,tx_phase_reg,tx_enable,ttls);
|
|
switch(instruction) {
|
|
case SpinCorePulseBlaster::LOOP:
|
|
fprintf(out,"inst=\"LOOP\" instdata=\"%d\"",loop_count);
|
|
break;
|
|
case SpinCorePulseBlaster::LONG_DELAY:
|
|
fprintf(out,"inst=\"LONG_DELAY\" instdata=\"%d\"",loop_count);
|
|
break;
|
|
case SpinCorePulseBlaster::BRANCH:
|
|
fprintf(out,"inst=\"BRANCH\" instdata=\"%" SIZETPRINTFLETTER "\"",std::distance(program->begin(),jump));
|
|
break;
|
|
case SpinCorePulseBlaster::END_LOOP:
|
|
fprintf(out,"inst=\"END_LOOP\" instdata=\"%" SIZETPRINTFLETTER "\"",std::distance(program->begin(),jump));
|
|
break;
|
|
case SpinCorePulseBlaster::JSR:
|
|
fprintf(out,"inst=\"JSR\" instdata=\"%" SIZETPRINTFLETTER "\"",std::distance(program->begin(),jump));
|
|
break;
|
|
case SpinCorePulseBlaster::CONTINUE:
|
|
fprintf(out,"inst=\"CONTINUE\"");
|
|
break;
|
|
case SpinCorePulseBlaster::STOP:
|
|
fprintf(out,"inst=\"STOP\"");
|
|
break;
|
|
case SpinCorePulseBlaster::RTS:
|
|
fprintf(out,"inst=\"RTS\"");
|
|
break;
|
|
case SpinCorePulseBlaster::WAIT:
|
|
fprintf(out,"inst=\"WAIT\"");
|
|
break;
|
|
default:
|
|
fprintf(out,"inst=\"%d\" instdata=\"UNKNOWN\"",instruction);
|
|
}
|
|
fprintf(out," length=\"%g\"/>\n",1.0/program->internal_clock_freq*length);
|
|
return 1;
|
|
}
|
|
|
|
/*********************************************************************
|
|
|
|
PulseBlasterDDSIIIProgram
|
|
|
|
*********************************************************************/
|
|
|
|
|
|
PulseBlasterDDSIIIProgram::PulseBlasterDDSIIIProgram() {
|
|
internal_clock_freq=100.0e6; // Hz
|
|
phase_accuracy=360.0/pow(2,12); // degree, manual page 8
|
|
freq_accuracy=internal_clock_freq/pow(2,28); // Hz, manual page 8
|
|
minimum_interval=9; // in clock cycles
|
|
}
|
|
|
|
PulseBlasterDDSIIIProgram::PulseBlasterDDSIIIProgram(const SpinCorePulseBlasterDDSIII& pbddsiii) {
|
|
internal_clock_freq=pbddsiii.clock; // Hz
|
|
minimum_interval=pbddsiii.shortest_pulse; // in clock cycles
|
|
phase_accuracy=360.0/pow(2,12); // degree, manual page 8
|
|
freq_accuracy=internal_clock_freq/pow(2,28); // Hz, manual page 8
|
|
}
|
|
|
|
PulseBlasterDDSIIIProgram::PulseBlasterDDSIIIProgram(const PulseBlasterDDSIIIProgram& orig): PulseBlasterProgram(orig) {
|
|
freq_accuracy=orig.freq_accuracy;
|
|
phase_accuracy=orig.phase_accuracy;
|
|
frequency_registers=orig.frequency_registers;
|
|
rx_phase_registers=orig.rx_phase_registers;
|
|
|
|
clear();
|
|
const_iterator orig_i;
|
|
for (orig_i=orig.begin(); orig_i!=orig.end(); ++orig_i) {
|
|
const PulseBlasterDDSIIICommand* the_command=dynamic_cast<const PulseBlasterDDSIIICommand*>(*orig_i);
|
|
if (the_command==NULL) {
|
|
throw SpinCorePulseBlaster_error("wrong command class or NULL pointer found in program");
|
|
}
|
|
PulseBlasterDDSIIICommand* new_one=new PulseBlasterDDSIIICommand(*the_command);
|
|
new_one->program=this;
|
|
push_back(new_one);
|
|
}
|
|
// set correct references...
|
|
orig_i=orig.begin();
|
|
for(iterator i=begin();i!=end();++i) {
|
|
(**i).program=this;
|
|
if ((**i).instruction==SpinCorePulseBlaster::END_LOOP || (**i).instruction==SpinCorePulseBlaster::BRANCH || (**i).instruction==SpinCorePulseBlaster::JSR) {
|
|
(**i).jump=i;
|
|
advance((**i).jump,distance(orig.begin(),(**orig_i).jump)-distance(orig.begin(),orig_i));
|
|
}
|
|
++orig_i;
|
|
}
|
|
}
|
|
|
|
int PulseBlasterDDSIIIProgram::write_to_file(FILE* out, size_t indent) const {
|
|
std::string indent_string(indent,' ');
|
|
fprintf(out,"%s<PulseBlasterDDSIIIProgram>\n",indent_string.c_str());
|
|
|
|
if (!frequency_registers.empty()) {
|
|
fprintf(out,"%s <frequencies>",indent_string.c_str());
|
|
for (size_t i=0; i<frequency_registers.size(); i++)
|
|
fprintf(out," %g",frequency_registers[i]);
|
|
fprintf(out," </frequencies>\n");
|
|
}
|
|
|
|
if (!rx_phase_registers.empty()) {
|
|
fprintf(out,"%s <rxphases>",indent_string.c_str());
|
|
for (size_t i=0;i<rx_phase_registers.size();i++)
|
|
fprintf(out," %g",rx_phase_registers[i]);
|
|
fprintf(out," </rxphases>\n");
|
|
}
|
|
|
|
if (!tx_phase_registers.empty()) {
|
|
fprintf(out,"%s <txphases>",indent_string.c_str());
|
|
for (size_t i=0;i<tx_phase_registers.size();i++)
|
|
fprintf(out," %g",tx_phase_registers[i]);
|
|
fprintf(out," </txphases>\n");
|
|
}
|
|
|
|
for(const_iterator i=begin();i!=end();++i) {
|
|
(**i).write_to_file(out,indent+2);
|
|
}
|
|
fprintf(out,"%s</PulseBlasterDDSIIIProgram>\n",indent_string.c_str());
|
|
return 1;
|
|
}
|
|
|
|
int PulseBlasterDDSIIIProgram::get_frequency_regno(double f) {
|
|
size_t i=0;
|
|
while (i<frequency_registers.size() && fabs(frequency_registers[i]-f)>freq_accuracy) ++i;
|
|
if (i==frequency_registers.size())
|
|
frequency_registers.push_back(f);
|
|
return i;
|
|
}
|
|
|
|
int PulseBlasterDDSIIIProgram::get_rx_phase_regno(double p) {
|
|
size_t i=0;
|
|
while (i<rx_phase_registers.size() && fabs(rx_phase_registers[i]-p)>phase_accuracy) ++i;
|
|
if (i==rx_phase_registers.size())
|
|
rx_phase_registers.push_back(p);
|
|
return i;
|
|
|
|
}
|
|
|
|
int PulseBlasterDDSIIIProgram::get_tx_phase_regno(double p) {
|
|
size_t i=0;
|
|
while (i<tx_phase_registers.size() && fabs(tx_phase_registers[i]-p)>phase_accuracy) ++i;
|
|
if (i==tx_phase_registers.size())
|
|
tx_phase_registers.push_back(p);
|
|
return i;
|
|
}
|
|
|
|
PulseBlasterCommand* PulseBlasterDDSIIIProgram::create_command(const state& the_state) {
|
|
if (typeid(the_state)!=typeid(state))
|
|
throw pulse_exception("tried to make a state from a sequence");
|
|
|
|
// todo: state's defaults
|
|
|
|
/*
|
|
There are three analog outputs on this card, but only two phase registers and two gates:
|
|
|
|
id=0, DAC_OUT0: influenced by rx1_specified, tx_phase, rx_enable
|
|
id=1, DAC_OUT1: influenced by rx2_specified, rx_phase, rx_enable
|
|
id=2, DAC_OUT2: influenced by tx_specified, tx_phase, tx_enable
|
|
|
|
all channels have the same frequency
|
|
|
|
*/
|
|
|
|
double length=the_state.length;
|
|
double state_frequency=0;
|
|
unsigned long ttls=0;
|
|
double rx_phase=0;
|
|
SpinCorePulseBlasterDDSIII::analog_state rx_enable=SpinCorePulseBlasterDDSIII::ANALOG_OFF;
|
|
double tx_phase=0;
|
|
SpinCorePulseBlasterDDSIII::analog_state tx_enable=SpinCorePulseBlasterDDSIII::ANALOG_OFF;
|
|
int id0_specified=0;
|
|
int id1_specified=0;
|
|
int id2_specified=0;
|
|
|
|
for (state::const_iterator i=the_state.begin(); i!=the_state.end(); ++i) {
|
|
// collect states information
|
|
const ttlout* to=dynamic_cast<const ttlout*>(*i);
|
|
if (to!=NULL && to->id==0) {
|
|
ttls|=to->ttls.to_ulong();
|
|
continue;
|
|
}
|
|
// add frequency information
|
|
const analogout* ao=dynamic_cast<const analogout*>(*i);
|
|
if (ao!=NULL && ao->id>=0 && ao->id<=2) {
|
|
if ((rx_enable!=SpinCorePulseBlasterDDSIII::ANALOG_OFF ||
|
|
tx_enable!=SpinCorePulseBlasterDDSIII::ANALOG_OFF) &&
|
|
fabs(state_frequency-ao->frequency)>freq_accuracy)
|
|
throw pulse_exception("only one frequency for analog outputs possible");
|
|
state_frequency=ao->frequency;
|
|
double phase=ao->phase;
|
|
if (phase < 0 || phase >= 360.0) {
|
|
phase=fmod(phase, 360.0);
|
|
if (phase<0) {phase+=360.0;}
|
|
}
|
|
assert(phase>=0 && phase<360.0);
|
|
switch(ao->id) {
|
|
case 0:
|
|
if (id0_specified) throw pulse_exception("rx channel (DAC_OUT_0) channel already set");
|
|
//if (rx_enable!=SpinCorePulseBlasterDDSIII::ANALOG_OFF) throw pulse_exception("rx channel already set");
|
|
// rx is identified with channel 0
|
|
if (id2_specified && fabs(phase-tx_phase)>phase_accuracy) fprintf(stderr, "WARNING from PulseBlaster DDSIII: redefining phase of TX (DAC_OUT_2) channel\n");
|
|
tx_phase=phase;
|
|
rx_enable=SpinCorePulseBlasterDDSIII::ANALOG_ON;
|
|
id0_specified=1;
|
|
break;
|
|
case 1:
|
|
if (id1_specified) throw pulse_exception("rx channel (DAC_OUT_1) channel already set");
|
|
// tx is identified with channel 1
|
|
rx_phase=phase;
|
|
rx_enable=SpinCorePulseBlasterDDSIII::ANALOG_ON;
|
|
id1_specified=1;
|
|
break;
|
|
case 2:
|
|
if (id2_specified || tx_enable==SpinCorePulseBlasterDDSIII::ANALOG_ON) throw pulse_exception("tx channel (DAC_OUT_2) already set");
|
|
// tx is identified with channel 1
|
|
if (id0_specified && fabs(phase-tx_phase)>phase_accuracy) fprintf(stderr, "WARNING from PulseBlaster DDSIII: redefining phase of RX (DAC_OUT_0) channel\n");
|
|
tx_phase=phase;
|
|
tx_enable=SpinCorePulseBlasterDDSIII::ANALOG_ON;
|
|
id2_specified=1;
|
|
break;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
#if SP_DEBUG
|
|
fprintf(stderr, "rx phase=%f, tx phase=%f\n",rx_phase, tx_phase);
|
|
#endif
|
|
if (!id0_specified && rx_enable==SpinCorePulseBlasterDDSIII::ANALOG_ON)
|
|
fprintf(stderr, "WARNING from PulseBlaster DDSIII: RF Output enabled on DAC_OUT_0\n");
|
|
if (!id1_specified && rx_enable==SpinCorePulseBlasterDDSIII::ANALOG_ON)
|
|
fprintf(stderr, "WARNING from PulseBlaster DDSIII: RF Output enabled on DAC_OUT_1\n");
|
|
|
|
return new PulseBlasterDDSIIICommand(*this,state_frequency,rx_phase,rx_enable,tx_phase,tx_enable,ttls,length);
|
|
}
|
|
|
|
PulseBlasterCommand* PulseBlasterDDSIIIProgram::create_command(const PulseBlasterCommand* orig) {
|
|
PulseBlasterDDSIIICommand* new_command=NULL;
|
|
if (orig==NULL) {
|
|
new_command=new PulseBlasterDDSIIICommand();
|
|
new_command->program=this;
|
|
new_command->length=minimum_interval;
|
|
}
|
|
else {
|
|
const PulseBlasterDDSIIICommand* commandDDSIII=dynamic_cast<const PulseBlasterDDSIIICommand*>(orig);
|
|
if (commandDDSIII==NULL) throw pulse_exception("wrong PulseBlasterCommand class in PulseBlasterDDSIIIProgram method");
|
|
new_command=new PulseBlasterDDSIIICommand(*commandDDSIII);
|
|
}
|
|
return new_command;
|
|
}
|
|
|
|
|
|
/*********************************************************************
|
|
|
|
SpinCorePulseBlasterDDSIII
|
|
|
|
*********************************************************************/
|
|
|
|
SpinCorePulseBlasterDDSIII::SpinCorePulseBlasterDDSIII(int the_id, double the_clock, unsigned int _sync_mask): SpinCorePulseBlaster(10,the_clock) {
|
|
sync_mask=_sync_mask;
|
|
ttl_device_id=the_id;
|
|
freq_regno=16;
|
|
phase_regno=16;
|
|
}
|
|
|
|
void SpinCorePulseBlasterDDSIII::set_registers(int device, unsigned int register_size, double multiplier, const std::vector<double>& values) {
|
|
if (values.size()>register_size)
|
|
throw SpinCorePulseBlaster_error("to many data for registers");
|
|
unsigned char* data=(unsigned char*)malloc(4*register_size);
|
|
if (data==NULL) {
|
|
throw SpinCorePulseBlaster_error("could not allocate memory for register data");
|
|
}
|
|
|
|
for (unsigned int reg=0; reg<register_size; ++reg) {
|
|
if (values.size()>reg) {
|
|
double temp=values[reg]*multiplier;
|
|
if (temp<0 || temp>pow(2,32))
|
|
throw SpinCorePulseBlaster_error("invalid data value");
|
|
unsigned int val=(unsigned int)temp;
|
|
data[reg*4]=(val&0xff000000)>>24;
|
|
data[reg*4+1]=(val&0xff0000)>>16;
|
|
data[reg*4+2]=(val&0xff00)>>8;
|
|
data[reg*4+3]=val&0xff;
|
|
}
|
|
else {
|
|
data[reg*4]=0;
|
|
data[reg*4+1]=0;
|
|
data[reg*4+2]=0;
|
|
data[reg*4+3]=0;
|
|
}
|
|
}
|
|
write_register(0,0); // dev reset
|
|
write_register(2,4); // bytes per word
|
|
write_register(3,device); // dev to program
|
|
write_register(4,0); //reset address counter
|
|
write_data(data,4*register_size);
|
|
free(data);
|
|
}
|
|
|
|
void SpinCorePulseBlasterDDSIII::set_phase_registers(std::vector<double> rx_phases, std::vector<double> tx_phases) {
|
|
if (tx_phases.empty())
|
|
set_registers(2,phase_regno,1.0,std::vector<double>(1,0.0));
|
|
else
|
|
set_registers(2,phase_regno,pow(2,32)/360.0,tx_phases);
|
|
if (rx_phases.empty())
|
|
set_registers(3,phase_regno,1.0,std::vector<double>(1,0.0));
|
|
else
|
|
set_registers(3,phase_regno,pow(2,32)/360.0,rx_phases);
|
|
}
|
|
|
|
void SpinCorePulseBlasterDDSIII::set_frequency_registers(const std::vector<double>& values) {
|
|
if (values.empty())
|
|
set_registers(1,freq_regno,pow(2,32)/clock,std::vector<double>(1,1e6));
|
|
else
|
|
set_registers(1,freq_regno,pow(2,32)/clock,values);
|
|
}
|
|
|
|
void SpinCorePulseBlasterDDSIII::write_command(unsigned char* data, const PulseBlasterCommand& command) {
|
|
//void PulseBlasterDDSIII::append_command(std::string& data, int freqreg, int phasereg_tx, int output_tx, int phasereg_rx, int output_rx, int flags, opcode inst, int inst_data, double length)
|
|
const PulseBlasterDDSIIICommand* commandDDSIII=dynamic_cast<const PulseBlasterDDSIIICommand*>(&command);
|
|
if (commandDDSIII==NULL)
|
|
throw SpinCorePulseBlaster_error("found wrong command class in PulseBlasterProgram");
|
|
|
|
if (command.program==NULL) throw SpinCorePulseBlaster_error("Command not associated with Program");
|
|
int inst_data=0;
|
|
switch(command.instruction) {
|
|
case SpinCorePulseBlaster::CONTINUE:
|
|
case SpinCorePulseBlaster::STOP:
|
|
case SpinCorePulseBlaster::WAIT:
|
|
case SpinCorePulseBlaster::RTS:
|
|
// no parameter
|
|
break;
|
|
case SpinCorePulseBlaster::LOOP:
|
|
inst_data=command.loop_count-1;
|
|
break;
|
|
case SpinCorePulseBlaster::LONG_DELAY:
|
|
inst_data=command.loop_count-2;
|
|
break;
|
|
case SpinCorePulseBlaster::BRANCH:
|
|
case SpinCorePulseBlaster::END_LOOP:
|
|
case SpinCorePulseBlaster::JSR:
|
|
inst_data=std::distance(command.program->begin(),command.jump);
|
|
break;
|
|
default:
|
|
throw SpinCorePulseBlaster_error("instruction code not known");
|
|
}
|
|
unsigned int delay=(unsigned int)command.length-3;
|
|
|
|
// Output, Control Word 1st Byte
|
|
data[0]=(commandDDSIII->freq_reg&0x0f)<<4|(commandDDSIII->tx_phase_reg&0x0f);
|
|
// Output, Control Word 2nd Byte
|
|
data[1]=((commandDDSIII->rx_phase_reg&0x0f)<<4)|((command.ttls&0x300)>>8);
|
|
if (commandDDSIII->rx_enable==ANALOG_OFF) data[1]|=0x04;
|
|
if (commandDDSIII->tx_enable==ANALOG_OFF) data[1]|=0x08;
|
|
// Output, Control Word 3rd Byte
|
|
data[2]=command.ttls&0xff;
|
|
// Data Field 1st Byte
|
|
data[3]=(inst_data&0x0ff000)>>12;
|
|
// Data Field 2nd Byte
|
|
data[4]=(inst_data&0xff0)>>4;
|
|
// Data Field 3rd Byte and opcode
|
|
data[5]=(inst_data&0xf)<<4|(command.instruction&0xf);
|
|
// Delay Count 1st Byte
|
|
data[6]=(delay&0xff000000)>>24;
|
|
// Delay Count 2nd Byte
|
|
data[7]=(delay&0xff0000)>>16;
|
|
// Delay Count 3rd Byte
|
|
data[8]=(delay&0xff00)>>8;
|
|
// Delay Count 4th Byte
|
|
data[9]=(delay&0xff);
|
|
/* *** BUG-FIX (ToDo: clean solution) ***
|
|
there is a nasty error in pulseblaster, affecting all states with 4th byte
|
|
equal 0xff and delay >255. In this case reduce state for 10ns.
|
|
*/
|
|
if (data[9]==0xff && delay>0xff)
|
|
data[9]=0xfe;
|
|
}
|
|
|
|
int SpinCorePulseBlasterDDSIII::write_to_device(const PulseBlasterDDSIIIProgram& p) {
|
|
set_frequency_registers(p.frequency_registers);
|
|
set_phase_registers(p.rx_phase_registers,p.tx_phase_registers);
|
|
|
|
std::string program;
|
|
//Begin pulse program
|
|
for (PulseBlasterDDSIIIProgram::const_iterator c=p.begin(); c!=p.end();++c) {
|
|
char command[10];
|
|
write_command((unsigned char*)command,**c);
|
|
program.append(command, (size_t)10);
|
|
}
|
|
|
|
set_program(program);
|
|
|
|
// End of programming registers and pulse program
|
|
set_initialized();
|
|
return 1;
|
|
}
|
|
|
|
PulseBlasterProgram* SpinCorePulseBlasterDDSIII::create_program(state& exp) {
|
|
PulseBlasterDDSIIIProgram* prog=new PulseBlasterDDSIIIProgram();
|
|
// some initialisiation...
|
|
prog->append_sequence(exp);
|
|
// some reset code ...
|
|
return prog;
|
|
}
|
|
|
|
void SpinCorePulseBlasterDDSIII::run_pulse_program(const PulseBlasterProgram& p) {
|
|
const PulseBlasterDDSIIIProgram* prog=dynamic_cast<const PulseBlasterDDSIIIProgram*>(&p);
|
|
if (prog==NULL)
|
|
throw SpinCorePulseBlaster_error("found wrong program class in SpinCorePulseBlasterDDSIII method");
|
|
write_to_device(*prog);
|
|
start();
|
|
}
|
|
|
|
void SpinCorePulseBlasterDDSIII::wait_till_end() {
|
|
|
|
double waittime=duration-time_running.elapsed();
|
|
double timeout=(waittime>10)?(waittime*0.01):0.05;
|
|
#if SP_DEBUG
|
|
fprintf(stderr,"waiting while DDSIII pulseprogram running (%f s of %f s)...", waittime, duration);
|
|
#endif
|
|
while (waittime>-timeout && core::term_signal==0) {
|
|
if (waittime<1e-2)
|
|
waittime=1e-2;
|
|
else
|
|
waittime*=0.9;
|
|
#if SP_DEBUG
|
|
fprintf(stderr,"sleeping for %g seconds...",waittime);
|
|
fflush(stderr);
|
|
#endif
|
|
timespec nanosleep_time;
|
|
nanosleep_time.tv_sec=(time_t)floor(waittime);
|
|
nanosleep_time.tv_nsec=(long)ceil((waittime-nanosleep_time.tv_sec)*1e9);
|
|
nanosleep(&nanosleep_time,NULL);
|
|
waittime=duration-time_running.elapsed();
|
|
}
|
|
if (core::term_signal!=0) {
|
|
//reset pulseblaster
|
|
stop();
|
|
reset_flags(0);
|
|
}
|
|
#if SP_DEBUG
|
|
fprintf(stderr,"done\n");
|
|
#endif
|
|
}
|
|
|
|
|