damaris-backends/drivers/PTS-Synthesizer/PTS.cpp
2021-06-24 21:51:45 +02:00

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 */
}
}