From 3da3b70ddd3a19a9b6c4aa605fc901486683786c Mon Sep 17 00:00:00 2001 From: Markus Rosenstihl Date: Wed, 1 Feb 2017 18:17:43 +0100 Subject: [PATCH] AD5791 data and clock bits now settable via methods (like latch enable) --- drivers/DAC-AD5791/AD5791.cpp | 241 +++++++++++++--------------------- 1 file changed, 90 insertions(+), 151 deletions(-) diff --git a/drivers/DAC-AD5791/AD5791.cpp b/drivers/DAC-AD5791/AD5791.cpp index 787dd9b..aa2f037 100644 --- a/drivers/DAC-AD5791/AD5791.cpp +++ b/drivers/DAC-AD5791/AD5791.cpp @@ -27,21 +27,35 @@ using std::vector; #define DAC_DATA_BITS 20 #define DAC_CONTROL_BITS 4 -// The channel configuration -#define DATA_BIT 18//18 -#define CLK_BIT 16//16 +// The default channel configuration +#define LE_BIT 17 +#define DATA_BIT 18 +#define CLK_BIT 16 + +// Input shift register addresses + +// Write to DAC register 0001 +#define WRITE_DAC 1 +// Write to the control register 0010 +#define WRITE_CONTROL_REGISTER 2 +// Write to the clearcode register 0011 +#define WRITE_CLEARCODE_REGISTER 3 +// Write to the software control register 0100 +#define WRITE_SOFTWARE_CONTROL_REGISTER 4 -// this bit needs to be set to write the DAC register -#define WRITE_DAC 1<<20 -// software control register +// software control register settings +// Setting this bit to a 1 returns the AD5791 to its power-on state. #define RESET 1 +// Setting this bit to a 1 sets the DAC register to a user defined value (see Table 13) and updates the DAC output. The output +// value depends on the DAC register coding that is being used, either binary or twos complement. #define CLR 2 +// Setting this bit to a 1 updates the DAC register and consequently the DAC output. #define LDAC 4 -// control register +// control register settings // 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 @@ -63,7 +77,9 @@ using std::vector; AD5791::AD5791(int myid) : id(myid) { dac_value = 0; - set_latch_bit(17); + set_latch_bit(LE_BIT); + set_data_bit(DATA_BIT); + set_clock_bit(CLK_BIT); } AD5791::~AD5791() {} @@ -72,10 +88,20 @@ void AD5791::set_dac(signed dw) { dac_value = dw; } -void AD5791::set_latch_bit(int le_bit) +void AD5791::set_latch_bit(int bit) { - latch_bit = le_bit; + latch_bit = bit; } +void AD5791::set_data_bit(int bit) +{ + data_bit = bit; +} +void AD5791::set_clock_bit(int bit) +{ + clock_bit = bit; +} + + // This sets the DAC void AD5791::set_dac(state &experiment) { state_sequent *exp_sequence = dynamic_cast(&experiment); @@ -98,111 +124,67 @@ void AD5791::set_dac(state &experiment) { } } +/** + * push one bit to the DAC, this function returns a state_sequent one can add + * + * @param bit + * @return + */ 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<ttls = bit*(1<push_back(s.copy_new()); - ttl_state->ttls = (1<ttls = (1<push_back(s.copy_new()); - return tx; + return tx; +} + +state_sequent* AD5791::select_input_shift_register(unsigned int register_address){ + state_sequent* tx = new state_sequent(); + int count = DAC_CONTROL_BITS; + while (register_address != 0 and count !=0 ) { + tx->push_back(tx_bit(register_address & 1)); + register_address >>= 1; + count--; + } + return tx; +} + +state_sequent* AD5791::write_serial_register(unsigned int register_value){ + state_sequent* tx = new state_sequent(); + vector dac_word; + // generate the bit pattern, this is MSB last + for (int j = 0; j < DAC_DATA_BITS; j++) { + int bit = register_value & 1; + dac_word.push_back(bit); + register_value >>= 1; + } + // iterate over the dac_word from end to beginning, this is MSB first + // TODO: Run Length Encoding (maybe better on higher level, i.e. full state sequence?) + for (vector::reverse_iterator current_bit = dac_word.rbegin(); + current_bit != dac_word.rend(); + ++current_bit){ + tx->push_back(tx_bit(*current_bit)); + } + 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()); + exp_sequence->insert(where, select_input_shift_register(WRITE_DAC)); + exp_sequence->insert(where, write_serial_register(0)); } 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()); + exp_sequence->insert(where, select_input_shift_register(WRITE_CONTROL_REGISTER)); + exp_sequence->insert(where, write_serial_register(0)); } - - // This loops recursive through the state tree void AD5791::set_dac_recursive(state_sequent &the_sequence, state::iterator &the_state) { @@ -232,8 +214,9 @@ void AD5791::set_dac_recursive(state_sequent &the_sequence, state::iterator &the } // there is no place for me here else { - throw pfg_exception("found another DAC section, ignoring"); delete aout; + throw pfg_exception("found another DAC section, ignoring"); + } // remove the analog out section this_state->erase(pos++); @@ -261,67 +244,23 @@ void AD5791::set_dac_recursive(state_sequent &the_sequence, state::iterator &the 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()); + state_sequent *input = new state_sequent(); + state_sequent *dacword = new state_sequent(); + input = select_input_shift_register(WRITE_DAC); + dacword = write_serial_register(dac_analog_out->dac_value); + register_state->push_back(input); + register_state->push_back(dacword); // shorten the remaining state + this_state->length -= input->length + dacword->length; // 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 input; + delete dacword; delete register_state; delete dac_analog_out; } // state was long enough to work on