2015-11-25 16:43:12 +00:00
|
|
|
|
/**
|
|
|
|
|
* \file
|
|
|
|
|
* \brief Implementation of the Driver for the AD5791
|
|
|
|
|
* Digital to Analog Converter Board
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* The board inverts all digital inputs.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "AD5791.h"
|
2016-12-19 14:03:14 +00:00
|
|
|
|
#include "../../core/states.h"
|
2015-11-25 16:43:12 +00:00
|
|
|
|
#include <cstdio>
|
|
|
|
|
#include <cmath>
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <list>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
|
|
using std::reverse;
|
|
|
|
|
using std::cout;
|
|
|
|
|
using std::vector;
|
|
|
|
|
#ifndef TIMING
|
|
|
|
|
#define TIMING 9e-8
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// The bit depth of the DAC
|
2016-12-19 14:03:14 +00:00
|
|
|
|
#define DAC_DATA_BITS 20
|
|
|
|
|
#define DAC_CONTROL_BITS 4
|
2015-11-25 16:43:12 +00:00
|
|
|
|
|
2017-02-01 17:17:43 +00:00
|
|
|
|
// The default channel configuration
|
|
|
|
|
#define LE_BIT 17
|
|
|
|
|
#define DATA_BIT 18
|
|
|
|
|
#define CLK_BIT 16
|
2015-11-25 16:43:12 +00:00
|
|
|
|
|
2017-02-01 17:17:43 +00:00
|
|
|
|
// Input shift register addresses
|
2016-12-19 14:03:14 +00:00
|
|
|
|
|
2017-02-01 17:17:43 +00:00
|
|
|
|
// 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
|
2016-12-19 14:03:14 +00:00
|
|
|
|
|
|
|
|
|
|
2017-02-01 17:17:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// software control register settings
|
|
|
|
|
// Setting this bit to a 1 returns the AD5791 to its power-on state.
|
2016-12-19 14:03:14 +00:00
|
|
|
|
#define RESET 1
|
2017-02-01 17:17:43 +00:00
|
|
|
|
// 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.
|
2016-12-19 14:03:14 +00:00
|
|
|
|
#define CLR 2
|
2017-02-01 17:17:43 +00:00
|
|
|
|
// Setting this bit to a 1 updates the DAC register and consequently the DAC output.
|
2016-12-19 14:03:14 +00:00
|
|
|
|
#define LDAC 4
|
|
|
|
|
|
2017-02-01 17:17:43 +00:00
|
|
|
|
// control register settings
|
2016-12-19 14:03:14 +00:00
|
|
|
|
// 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;
|
2017-02-01 17:17:43 +00:00
|
|
|
|
set_latch_bit(LE_BIT);
|
|
|
|
|
set_data_bit(DATA_BIT);
|
|
|
|
|
set_clock_bit(CLK_BIT);
|
2015-11-25 16:43:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AD5791::~AD5791() {}
|
|
|
|
|
// This sets the dac_value
|
|
|
|
|
void AD5791::set_dac(signed dw) {
|
2016-12-19 14:03:14 +00:00
|
|
|
|
dac_value = dw;
|
2015-11-25 16:43:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-02-01 17:17:43 +00:00
|
|
|
|
void AD5791::set_latch_bit(int bit)
|
|
|
|
|
{
|
|
|
|
|
latch_bit = bit;
|
|
|
|
|
}
|
|
|
|
|
void AD5791::set_data_bit(int bit)
|
2017-01-19 11:48:08 +00:00
|
|
|
|
{
|
2017-02-01 17:17:43 +00:00
|
|
|
|
data_bit = bit;
|
2015-11-25 16:43:12 +00:00
|
|
|
|
}
|
2017-02-01 17:17:43 +00:00
|
|
|
|
void AD5791::set_clock_bit(int bit)
|
|
|
|
|
{
|
|
|
|
|
clock_bit = bit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-11-25 16:43:12 +00:00
|
|
|
|
// This sets the DAC
|
2016-12-19 14:03:14 +00:00
|
|
|
|
void AD5791::set_dac(state &experiment) {
|
|
|
|
|
state_sequent *exp_sequence = dynamic_cast<state_sequent *>(&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();
|
2017-01-19 11:48:08 +00:00
|
|
|
|
child_state != exp_sequence->end(); ++child_state) {
|
2016-12-19 14:03:14 +00:00
|
|
|
|
set_dac_recursive(*exp_sequence, child_state);
|
2017-01-19 11:48:08 +00:00
|
|
|
|
}
|
|
|
|
|
std::cout << "first state"<< std::endl;
|
2016-12-19 14:03:14 +00:00
|
|
|
|
|
|
|
|
|
// 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());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-01 17:17:43 +00:00
|
|
|
|
/**
|
|
|
|
|
* push one bit to the DAC, this function returns a state_sequent one can add
|
|
|
|
|
*
|
|
|
|
|
* @param bit
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
2017-01-19 11:48:08 +00:00
|
|
|
|
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);
|
|
|
|
|
|
2017-02-01 17:17:43 +00:00
|
|
|
|
ttl_state->ttls = bit*(1<<data_bit) + (1 << clock_bit);
|
2017-01-19 11:48:08 +00:00
|
|
|
|
tx->push_back(s.copy_new());
|
2017-02-01 17:17:43 +00:00
|
|
|
|
ttl_state->ttls = (1<<data_bit);
|
2017-01-19 11:48:08 +00:00
|
|
|
|
tx->push_back(s.copy_new());
|
2017-02-01 17:17:43 +00:00
|
|
|
|
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<int> 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<int>::reverse_iterator current_bit = dac_word.rbegin();
|
|
|
|
|
current_bit != dac_word.rend();
|
|
|
|
|
++current_bit){
|
|
|
|
|
tx->push_back(tx_bit(*current_bit));
|
|
|
|
|
}
|
|
|
|
|
return tx;
|
2017-01-19 11:48:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AD5791::set_dac_to_zero(state_sequent* exp_sequence, state::iterator where) {
|
2016-12-19 14:03:14 +00:00
|
|
|
|
// 0001 0000 0000 0000 0000 0000
|
2017-02-01 17:17:43 +00:00
|
|
|
|
exp_sequence->insert(where, select_input_shift_register(WRITE_DAC));
|
|
|
|
|
exp_sequence->insert(where, write_serial_register(0));
|
2015-11-25 16:43:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-19 14:03:14 +00:00
|
|
|
|
void AD5791::init_dac(state_sequent *exp_sequence, state::iterator where) {
|
2017-02-01 17:17:43 +00:00
|
|
|
|
exp_sequence->insert(where, select_input_shift_register(WRITE_CONTROL_REGISTER));
|
|
|
|
|
exp_sequence->insert(where, write_serial_register(0));
|
2015-11-25 16:43:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-19 14:03:14 +00:00
|
|
|
|
|
2015-11-25 16:43:12 +00:00
|
|
|
|
// This loops recursive through the state tree
|
2016-12-19 14:03:14 +00:00
|
|
|
|
void AD5791::set_dac_recursive(state_sequent &the_sequence, state::iterator &the_state) {
|
|
|
|
|
|
|
|
|
|
state_sequent *a_sequence = dynamic_cast<state_sequent *>(*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<state *>(*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
|
2017-01-19 11:48:08 +00:00
|
|
|
|
analogout *aout = dynamic_cast<analogout *>(*pos); // initialize new analogout from state
|
|
|
|
|
if (aout != NULL)
|
|
|
|
|
std::cout << aout->id << std::endl;
|
2016-12-19 14:03:14 +00:00
|
|
|
|
// 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 {
|
|
|
|
|
delete aout;
|
2017-02-01 17:17:43 +00:00
|
|
|
|
throw pfg_exception("found another DAC section, ignoring");
|
|
|
|
|
|
2016-12-19 14:03:14 +00:00
|
|
|
|
}
|
|
|
|
|
// remove the analog out section
|
|
|
|
|
this_state->erase(pos++);
|
|
|
|
|
} else {
|
2017-01-19 11:48:08 +00:00
|
|
|
|
std::cout << "nope" << std::endl;
|
2016-12-19 14:03:14 +00:00
|
|
|
|
++pos;
|
|
|
|
|
}
|
|
|
|
|
} // state members loop
|
|
|
|
|
|
|
|
|
|
if (dac_analog_out != NULL) { // state modifications
|
2017-01-19 11:48:08 +00:00
|
|
|
|
|
2016-12-19 14:03:14 +00:00
|
|
|
|
//std::cout<<"found a analog out section, value="<<dac_analog_out->dac_value<<std::endl;
|
|
|
|
|
// check the length of the state
|
|
|
|
|
if (this_state->length < TIMING * (DAC_CONTROL_BITS + DAC_DATA_BITS) * 2 + 1)
|
2017-01-19 11:48:08 +00:00
|
|
|
|
throw pfg_exception("AD5791: time is too short to save DAC information");
|
2016-12-19 14:03:14 +00:00
|
|
|
|
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");
|
|
|
|
|
|
2017-02-01 17:17:43 +00:00
|
|
|
|
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);
|
2016-12-19 14:03:14 +00:00
|
|
|
|
|
|
|
|
|
// shorten the remaining state
|
2017-02-01 17:17:43 +00:00
|
|
|
|
this_state->length -= input->length + dacword->length;
|
2016-12-19 14:03:14 +00:00
|
|
|
|
// and add LE high to this state
|
|
|
|
|
ttlout *ttls = new ttlout();
|
|
|
|
|
ttls->ttls = 1 << latch_bit;
|
|
|
|
|
this_state->push_front(ttls);
|
2015-11-25 16:43:12 +00:00
|
|
|
|
|
2016-12-19 14:03:14 +00:00
|
|
|
|
// cleanup
|
2017-02-01 17:17:43 +00:00
|
|
|
|
delete input;
|
|
|
|
|
delete dacword;
|
2016-12-19 14:03:14 +00:00
|
|
|
|
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
|
2015-11-25 16:43:12 +00:00
|
|
|
|
}
|