/** * \file * \brief Implementation of the Driver for the AD5791 * Digital to Analog Converter Board * * * The board inverts all digital inputs. */ #include "AD5791.h" #include "../../core/states.h" #include #include #include #include #include #include using std::reverse; using std::cout; using std::vector; #ifndef TIMING #define TIMING 9e-8 #endif // The bit depth of the DAC #define DAC_DATA_BITS 20 #define DAC_CONTROL_BITS 4 // The channel configuration #define DATA_BIT 18//18 #define CLK_BIT 16//16 // this bit needs to be set to write the DAC register #define WRITE_DAC 1<<20 // software control register #define RESET 1 #define CLR 2 #define LDAC 4 // control register // Linearity error compensation for varying reference input spans. #define LINCOMP_10V 0*1<<9 + 0*1<<8 + 0*1<<7 + 0*1<<6 #define LINCOMP_12V 1*1<<9 + 0*1<<8 + 0*1<<7 + 1*1<<6 #define LINCOMP_16V 1*1<<9 + 0*1<<8 + 1*1<<7 + 0*1<<6 #define LINCOMP_19V 1*1<<9 + 0*1<<8 + 1*1<<7 + 1*1<<6 #define LINCOMP_20V 1*1<<9 + 1*1<<8 + 0*1<<7 + 0*1<<6 // SDO pin enable/disable control. #define SDODIS 32 // DAC register coding select. #define DAC_CODING_SELECT 16 // DAC tristate control. #define DACTRI 8 // Output ground clamp control. (set by default) #define OPGND 4 // Output amplifier configuration control. (set by default) #define RBUF 2 AD5791::AD5791(int myid) : id(myid) { dac_value = 0; set_latch_bit(17); } AD5791::~AD5791() {} // This sets the dac_value void AD5791::set_dac(signed dw) { dac_value = dw; } void AD5791::set_latch_bit(int le_bit) { latch_bit = le_bit; } // This sets the DAC void AD5791::set_dac(state &experiment) { state_sequent *exp_sequence = dynamic_cast(&experiment); if (exp_sequence == NULL) // is a very state on top level, todo: change interface throw pfg_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_dac_recursive(*exp_sequence, child_state); } std::cout << "first state"<< std::endl; // Set DAC to 0 at start of experiment set_dac_to_zero(exp_sequence, exp_sequence->begin()); // but first initialize DAC init_dac(exp_sequence, exp_sequence->begin()); // And at the end of the experiment set DAC to zero set_dac_to_zero(exp_sequence, exp_sequence->end()); } } state_sequent* AD5791::tx_bit(unsigned int bit) { state_sequent* tx = new state_sequent(); ttlout* ttl_state = new ttlout(); state s(TIMING); s.push_back(ttl_state); ttl_state->ttls = bit*(1<push_back(s.copy_new()); ttl_state->ttls = (1<push_back(s.copy_new()); return tx; } void AD5791::set_dac_to_zero(state_sequent* exp_sequence, state::iterator where) { // 0001 0000 0000 0000 0000 0000 state s(TIMING); ttlout* ttl_state = new ttlout(); ttl_state->id = 0; s.push_front(ttl_state); // test exp_sequence->insert(where, tx_bit(1)); exp_sequence->insert(where, tx_bit(1)); // 0 ttl_state->ttls = 0 + (1 << CLK_BIT); exp_sequence->insert(where, s.copy_new()); ttl_state->ttls = 0; exp_sequence->insert(where, s.copy_new()); // 0 ttl_state->ttls = 0 + (1 << CLK_BIT); exp_sequence->insert(where, s.copy_new()); ttl_state->ttls = 0; exp_sequence->insert(where, s.copy_new()); // 0 ttl_state->ttls = 0 + (1 << CLK_BIT); exp_sequence->insert(where, s.copy_new()); ttl_state->ttls = 0; exp_sequence->insert(where, s.copy_new()); // 1 ttl_state->ttls = (1<insert(where, s.copy_new()); ttl_state->ttls = (1<insert(where, s.copy_new()); // the rest state_sequent *rep_sequence = new state_sequent(); rep_sequence->repeat = DAC_DATA_BITS; ttl_state->ttls = 0 + (1 << CLK_BIT); rep_sequence->push_back(s.copy_new()); ttl_state->ttls = 0; rep_sequence->push_back(s.copy_new()); exp_sequence->insert(where, rep_sequence); //read in the word ttl_state->ttls = 0; exp_sequence->insert(where, s.copy_new()); ttl_state->ttls = (1 << latch_bit); exp_sequence->insert(where, s.copy_new()); } void AD5791::init_dac(state_sequent *exp_sequence, state::iterator where) { state s(TIMING); ttlout *ttl_state = new ttlout(); ttl_state->id = 0; s.push_front(ttl_state); // 0010 0000 0000 0000 0000 0000 // 0 ttl_state->ttls = 0 + (1 << CLK_BIT); exp_sequence->insert(where, s.copy_new()); ttl_state->ttls = 0; exp_sequence->insert(where,s.copy_new()); // 0 ttl_state->ttls = 0 + (1 << CLK_BIT); exp_sequence->insert(where, s.copy_new()); ttl_state->ttls = 0; exp_sequence->insert(where, s.copy_new()); // 1 ttl_state->ttls = (1<insert(where,s.copy_new()); ttl_state->ttls = (1<insert(where,s.copy_new()); // 0 ttl_state->ttls = 0 + (1 << CLK_BIT); exp_sequence->insert(where, s.copy_new()); ttl_state->ttls = 0; exp_sequence->insert(where,s.copy_new()); // the rest state_sequent *rep_sequence = new state_sequent(); rep_sequence->repeat = DAC_DATA_BITS; ttl_state->ttls = 0 + (1 << CLK_BIT); rep_sequence->push_back(s.copy_new()); ttl_state->ttls = 0; rep_sequence->push_back(s.copy_new()); exp_sequence->insert(where, rep_sequence); //read in the word ttl_state->ttls = 0; exp_sequence->insert(where, s.copy_new()); ttl_state->ttls = (1 << latch_bit) + (1<insert(where, s.copy_new()); } // This loops recursive through the state tree void AD5791::set_dac_recursive(state_sequent &the_sequence, state::iterator &the_state) { state_sequent *a_sequence = dynamic_cast(*the_state); // Am I a sequence? Yes? Go one sequence further if (a_sequence != NULL) { for (state_sequent::iterator child_state = a_sequence->begin(); child_state != a_sequence->end(); ++child_state) set_dac_recursive(*a_sequence, child_state); } // I am not a sequence, but a state else { state *this_state = dynamic_cast(*the_state); if (this_state == NULL) throw pfg_exception("state_atom in state_sequent not expected"); analogout *dac_analog_out = NULL; // find an analogout section with suitable id state::iterator pos = this_state->begin(); while (pos != this_state->end()) { // state members loop analogout *aout = dynamic_cast(*pos); // initialize new analogout from state if (aout != NULL) std::cout << aout->id << std::endl; // This is for me, analogout is != NULL (there is an analogout) and has my ID if (aout != NULL && aout->id == id) { if (dac_analog_out == NULL) { // save the information of this aout dac_analog_out = aout; } // there is no place for me here else { throw pfg_exception("found another DAC section, ignoring"); delete aout; } // remove the analog out section this_state->erase(pos++); } else { std::cout << "nope" << std::endl; ++pos; } } // state members loop if (dac_analog_out != NULL) { // state modifications //std::cout<<"found a analog out section, value="<dac_value<length < TIMING * (DAC_CONTROL_BITS + DAC_DATA_BITS) * 2 + 1) throw pfg_exception("AD5791: time is too short to save DAC information"); else { // copy of original state state *register_state = new state(*this_state); ttlout *register_ttls = new ttlout(); register_ttls->id = 0; register_state->length = TIMING; register_state->push_back(register_ttls); if (dac_analog_out->dac_value > (pow(2.0, int(DAC_DATA_BITS - 1)) - 1)) throw pfg_exception("dac_value too high"); if (abs(dac_analog_out->dac_value) > pow(2.0, int(DAC_DATA_BITS - 1))) throw pfg_exception("dac_value too low"); // set dac write register 1<<20 dac_analog_out->dac_value += WRITE_DAC; vector dac_word; // generate the bit pattern, this is MSB last for (int j = 0; j < (DAC_DATA_BITS + DAC_CONTROL_BITS); j++) { int bit = dac_analog_out->dac_value & 1; dac_word.push_back(bit); dac_analog_out->dac_value >>= 1; std::cout << bit; } // reverse the bit pattern (MSB first) reverse(dac_word.begin(), dac_word.end()); // need one clock cycle to read in bit // latch enable (LE) should always be high while doing so // except for the last bit // do run length encoding, grouping same bit values in loops int last_seen_bit = dac_word[0]; int last_seen_bit_count = 1; for (int i = 1; i < (DAC_DATA_BITS + DAC_CONTROL_BITS) + 1; i++) { if (i == (DAC_DATA_BITS + DAC_CONTROL_BITS) || last_seen_bit != dac_word[i]) { // so we have to write the bits // either because the previous were different or we are finished if (last_seen_bit_count > 1) { // insert a loop state_sequent *rep_sequence = new state_sequent(); rep_sequence->repeat = last_seen_bit_count; register_ttls->ttls = (1 << DATA_BIT) * last_seen_bit + (1 << CLK_BIT) + (1 << latch_bit); rep_sequence->push_back(register_state->copy_new()); register_ttls->ttls = (1 << DATA_BIT) * last_seen_bit + (1 << latch_bit); rep_sequence->push_back(register_state->copy_new()); the_sequence.insert(the_state, rep_sequence); } else { // no loop necessary, insert two states register_ttls->ttls = (1 << DATA_BIT) * last_seen_bit + (1 << CLK_BIT) + (1 << latch_bit); the_sequence.insert(the_state, register_state->copy_new()); register_ttls->ttls = (1 << DATA_BIT) * last_seen_bit + (1 << latch_bit); the_sequence.insert(the_state, register_state->copy_new()); } // reset counter and bits if we are not finished if (i < (DAC_DATA_BITS + DAC_CONTROL_BITS)) { last_seen_bit = dac_word[i]; last_seen_bit_count = 1; } } // finished writing else last_seen_bit_count += 1; // same bit value, so continue } // end of bit loop register_ttls->ttls = 0; the_sequence.insert(the_state, register_state->copy_new()); // shorten the remaining state // and add LE high to this state ttlout *ttls = new ttlout(); // 2 clocks per bit + 1 for sync this_state->length -= TIMING * 2 * (DAC_DATA_BITS + DAC_CONTROL_BITS) + 1; ttls->ttls = 1 << latch_bit; this_state->push_front(ttls); // cleanup delete register_state; delete dac_analog_out; } // state was long enough to work on } else { ttlout *le_ttls = new ttlout(); // le_ttls->ttls = 1 << latch_bit; this_state->push_back(le_ttls); } // end of state modifications } // I was a state }