274 lines
8.8 KiB
C++
274 lines
8.8 KiB
C++
/* ***************************************************************************
|
|
|
|
Author: Achim Gädke
|
|
Date: October 2004
|
|
|
|
**************************************************************************** */
|
|
|
|
#include "PTS.h"
|
|
#include <cstdio>
|
|
#include <cmath>
|
|
|
|
#ifdef __CYGWIN__
|
|
# define floorl floor
|
|
#endif
|
|
|
|
PTS::PTS(int myid): id(myid) {
|
|
frequency=0;
|
|
phase=0;
|
|
negative_logic=1;
|
|
phase_step=0.225;
|
|
}
|
|
|
|
PTS::~PTS() {
|
|
|
|
}
|
|
|
|
unsigned int PTS::phase_ttl_values(double p) const {
|
|
// break down to [0;360[
|
|
fprintf(stderr,"PHASE %g\n",phase_step);
|
|
p-=floor(p/360.0)*360.0;
|
|
unsigned int phasesteps=(unsigned int)fabs(round(p/phase_step));
|
|
int bcd_part=phasesteps/100;
|
|
unsigned int ttl_value=bcd_part<<8;
|
|
phasesteps-=bcd_part*100;
|
|
bcd_part=phasesteps/10;
|
|
ttl_value|=bcd_part<<4;
|
|
phasesteps-=bcd_part*10;
|
|
ttl_value|=phasesteps;
|
|
return ttl_value;
|
|
}
|
|
|
|
void PTS::phase_add_ttls(state& the_state, double p) const {
|
|
unsigned int binary_code=phase_ttl_values(p);
|
|
std::vector<ttlout>::const_iterator mask=ttl_masks.begin();
|
|
while (mask!=ttl_masks.end()) {
|
|
/* obeye negative logic */
|
|
if ((binary_code & 1<<11)==0 ^ negative_logic==0) the_state.push_back(mask->copy_new());
|
|
binary_code<<=1;
|
|
binary_code&=0xFFF;
|
|
++mask;
|
|
}
|
|
if (binary_code!=0) fprintf(stderr,"Warning! Insufficient phase precision for %f\n",p);
|
|
}
|
|
|
|
long unsigned int PTS::frequency_ttl_values(double f) const {
|
|
long unsigned int frequency_int=(long unsigned int)fabs(floor(f));
|
|
long unsigned int freq_bcd=0;
|
|
if (sizeof(freq_bcd)<8) {
|
|
fprintf(stderr, "warning! possible overflow (f=%f)\n", f);
|
|
}
|
|
for (long unsigned int divider=100000000; divider>0; divider/=10) {
|
|
int part_freq=frequency_int/divider;
|
|
freq_bcd<<=4;
|
|
freq_bcd|=part_freq;
|
|
frequency_int-=part_freq*divider;
|
|
}
|
|
return freq_bcd;
|
|
}
|
|
|
|
void PTS::set_frequency(double f) {
|
|
frequency=f;
|
|
/* todo switch PMD Module to frequency */
|
|
}
|
|
|
|
void PTS::set_frequency(state& experiment) {
|
|
// find the frequency informations...
|
|
// and exchange the phase informations
|
|
frequency=0;
|
|
phase=0;
|
|
state_sequent* exp_sequence=dynamic_cast<state_sequent*>(&experiment);
|
|
if (exp_sequence==NULL)
|
|
set_frequency_ttls(experiment);
|
|
else {
|
|
state_iterator si(*exp_sequence);
|
|
state* a_state=(state*)si.get_state();
|
|
while (NULL!=a_state) {
|
|
set_frequency_ttls(*a_state);
|
|
a_state=(state*)si.next_state();
|
|
} /* state loop */
|
|
}
|
|
}
|
|
|
|
void PTS::set_frequency_ttls(state& the_state) {
|
|
|
|
// find the frequency informations...
|
|
// and exchange the phase informations
|
|
analogout* pts_aout=NULL;
|
|
/* find a analogout section with suitable id */
|
|
state::iterator i=the_state.begin();
|
|
while(i!=the_state.end()) {
|
|
analogout* aout=dynamic_cast<analogout*>(*i);
|
|
if (aout!=NULL && aout->id==id) {
|
|
if (pts_aout==NULL) {
|
|
/* save the informations */
|
|
pts_aout=aout;
|
|
}
|
|
else {
|
|
fprintf(stderr, "found another pts decade section, ignoring\n");
|
|
delete aout;
|
|
}
|
|
/* remove the analog out section */
|
|
the_state.erase(i++);
|
|
}
|
|
else
|
|
++i;
|
|
} /* state members loop */
|
|
|
|
/* now, add the ttl information*/
|
|
if (pts_aout!=NULL) {
|
|
phase_add_ttls(the_state, pts_aout->phase);
|
|
phase=pts_aout->phase;
|
|
if (pts_aout->frequency!=0) {
|
|
if (frequency==0) {
|
|
set_frequency(pts_aout->frequency);
|
|
}
|
|
/* different frequencies are forbidden */
|
|
else if (frequency!=pts_aout->frequency) {
|
|
fprintf(stderr, "ignoring frequency %g at analogout %d\n",pts_aout->frequency,id);
|
|
}
|
|
}
|
|
delete pts_aout;
|
|
}
|
|
else {
|
|
/* because we use transparent mode, we have to set phase everywhere */
|
|
phase_add_ttls(the_state, phase);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/* **************************************************************************
|
|
|
|
PTS_latched
|
|
|
|
************************************************************************** */
|
|
|
|
void PTS_latched::set_frequency(state& experiment) {
|
|
// find the frequency informations...
|
|
// and exchange the phase informations
|
|
frequency=0;
|
|
phase=0;
|
|
state_sequent* exp_sequence=dynamic_cast<state_sequent*>(&experiment);
|
|
if (exp_sequence==NULL)
|
|
// is a very state on top level, todo: change interface
|
|
throw frequ_exception("cannot work on a single state, sorry (todo: change interface)");
|
|
else {
|
|
for(state_sequent::iterator child_state=exp_sequence->begin(); child_state!=exp_sequence->end(); ++child_state)
|
|
set_frequency_recursive(*exp_sequence, child_state);
|
|
}
|
|
}
|
|
|
|
void PTS_latched::set_frequency_recursive(state_sequent& the_sequence, state::iterator& the_state) {
|
|
|
|
state_sequent* a_sequence=dynamic_cast<state_sequent*>(*the_state);
|
|
if (a_sequence!=NULL) {
|
|
for(state_sequent::iterator child_state=a_sequence->begin(); child_state!=a_sequence->end(); ++child_state)
|
|
set_frequency_recursive(*a_sequence, child_state);
|
|
}
|
|
else {
|
|
// find the frequency informations...
|
|
state* this_state=dynamic_cast<state*>(*the_state);
|
|
if (this_state==NULL) throw frequ_exception("state_atom in state_sequent not expected");
|
|
// and exchange the phase informations
|
|
analogout* pts_aout=NULL;
|
|
/* find a analogout section with suitable id */
|
|
state::iterator i=this_state->begin();
|
|
while(i!=this_state->end()) {
|
|
analogout* aout=dynamic_cast<analogout*>(*i);
|
|
if (aout!=NULL && aout->id==id) {
|
|
if (pts_aout==NULL) {
|
|
/* save the informations */
|
|
pts_aout=aout;
|
|
}
|
|
else {
|
|
fprintf(stderr, "found another pts decade section, ignoring\n");
|
|
delete aout;
|
|
}
|
|
/* remove the analog out section */
|
|
this_state->erase(i++);
|
|
}
|
|
else
|
|
++i;
|
|
} /* state members loop */
|
|
|
|
if (pts_aout!=NULL) {
|
|
if (this_state->length<9e-8*4.0) throw frequ_exception("time is too short to save phase information");
|
|
/* now, insert the ttl information*/
|
|
/* set phase everytime */
|
|
pts_aout->phase-=floor(pts_aout->phase/360.0)*360.0;
|
|
int phase_int=(int)floor(pts_aout->phase/phase_step+0.5);
|
|
/* copy of original state */
|
|
state* register_state=new state(*this_state);
|
|
ttlout* register_ttls=new ttlout();
|
|
register_ttls->id=0;
|
|
register_state->length=9e-8;
|
|
register_state->push_back(register_ttls);
|
|
/* set frequency if necessary */
|
|
if (pts_aout->frequency!=0) {
|
|
if (this_state->length<9e-8*12.0) throw frequ_exception("time is too short to save frequency information");
|
|
// enable remote frequency control
|
|
register_ttls->ttls=0x8010;
|
|
the_sequence.insert(the_state,register_state->copy_new());
|
|
register_ttls->ttls&=0x7fff;
|
|
the_sequence.insert(the_state,register_state->copy_new());
|
|
// in 0.1 Hz units !
|
|
unsigned long int frequency_int=(unsigned long int)floorl(fabs(pts_aout->frequency)*10.0+0.5);
|
|
if (sizeof(frequency_int)<8 && pts_aout->frequency>4e8) {
|
|
fprintf(stderr, "warning! possible overflow (f=%f)\n",pts_aout->frequency);
|
|
}
|
|
/* 100MHz and 10MHz */
|
|
register_ttls->ttls=(frequency_int/1000000000)%10<<8|((frequency_int/100000000)%10)<<4|15<<12;
|
|
the_sequence.insert(the_state,register_state->copy_new());
|
|
register_ttls->ttls&=0x7fff;
|
|
the_sequence.insert(the_state,register_state->copy_new());
|
|
/* 1MHz and 100kHz */
|
|
register_ttls->ttls=(frequency_int/10000000)%10<<8|((frequency_int/1000000)%10)<<4|14<<12;
|
|
the_sequence.insert(the_state,register_state->copy_new());
|
|
register_ttls->ttls&=0x7fff;
|
|
the_sequence.insert(the_state,register_state->copy_new());
|
|
/* 10kHz and 1kHz */
|
|
register_ttls->ttls=(frequency_int/100000)%10<<8|((frequency_int/10000)%10)<<4|13<<12;
|
|
the_sequence.insert(the_state,register_state->copy_new());
|
|
register_ttls->ttls&=0x7fff;
|
|
the_sequence.insert(the_state,register_state->copy_new());
|
|
/* 100Hz and 10Hz */
|
|
register_ttls->ttls=(frequency_int/1000)%10<<8|((frequency_int/100)%10)<<4|12<<12;
|
|
the_sequence.insert(the_state,register_state->copy_new());
|
|
register_ttls->ttls&=0x7fff;
|
|
the_sequence.insert(the_state,register_state->copy_new());
|
|
/* 1Hz and 0.1Hz (not used for all models) */
|
|
//register_state->length=0.5e-6;
|
|
register_ttls->ttls=(frequency_int/10)%10<<8|((frequency_int)%10)<<4|11<<12;
|
|
the_sequence.insert(the_state,register_state->copy_new());
|
|
register_ttls->ttls&=0x7fff;
|
|
the_sequence.insert(the_state,register_state->copy_new());
|
|
//register_state->length=9e-8;
|
|
/* and shorten the remaining state */
|
|
this_state->length-=9e-8*12;
|
|
//this_state->length-=9e-8*11+0.5e-6;
|
|
}
|
|
if (1) {
|
|
/* first entry for phase */
|
|
register_ttls->ttls=((phase_int/100)%16)<<4|9<<12;
|
|
the_sequence.insert(the_state,register_state->copy_new());
|
|
register_ttls->ttls&=0x7fff;
|
|
the_sequence.insert(the_state,register_state->copy_new());
|
|
/* second entry for phase */
|
|
register_ttls->ttls=(phase_int%10)<<8|((phase_int/10)%10)<<4|10<<12;
|
|
the_sequence.insert(the_state,register_state->copy_new());
|
|
register_ttls->ttls&=0x7fff;
|
|
the_sequence.insert(the_state,register_state->copy_new());
|
|
/* and shorten the remaining state */
|
|
this_state->length-=9e-8*4;
|
|
}
|
|
delete register_state;
|
|
delete pts_aout;
|
|
|
|
}
|
|
|
|
|
|
/* end of state modifications */
|
|
}
|
|
}
|