drive the analog devices AD57XX series of DACs using SPI
dac57xx.h
- Committer:
- daan
- Date:
- 2011-10-26
- Revision:
- 1:59ce04153689
- Parent:
- 0:cbb2d9111355
File content as of revision 1:59ce04153689:
#pragma once #include <stdint.h> /** * a library for driving the Analog Devices Dac 57X4 series and more. * Tested on the AD5724 and AD5754. The AD5734 should also work. * http://www.analog.com/en/digital-to-analog-converters/da-converters/ad5724/products/product.html * the AD5722 AFD5732 and AD5752 should also work with minimal effort. * * note: this is the first commit. not all functionalities have been tested with the mbed. */ class DacAD57XX : public SPI { public: /** * */ DacAD57XX(PinName mosi, PinName miso, PinName sclk, PinName cs) : SPI(mosi, miso, sclk), mCS(cs) { // TODO(dps): make the frequency in an argument? frequency(1000000); // 8 bits a frame // mode 2: ClockPolarity 1 ClockPhase 1 format(8, 2); disableChipSelect(); }; enum registers { RW = 128, REG2 = 32, REG1 = 16, REG0 = 8, A2 = 4, A1 = 2, A0 = 1, PUA = 1, PUB = 2, PUC = 4, PUD = 8 }; enum control { OUTPUT_RANGE_SELECT = REG0, CONTROL = REG0 | REG1, CONTROL_SET = CONTROL | A0, POWER_CONTROL = REG1 }; // enum resolution {AD5724R, AD5734R, AD5754R}; enum outputRanges { UNIPOLAR_5V = 0, UNIPOLAR_10V = 1, BIPOLAR_5V = 3, BIPOLAR_10V = 4 }; enum channels { ADDRESS_A = 0, ADDRESS_B = A0, ADDRESS_C = A1, ADDRESS_D = A0+A1, ADDRESS_ALL = A2 }; /** * start communicating with the dac */ inline void enableChipSelect() { mCS = 0; // zero to select } /** * End communicating with the dac */ inline void disableChipSelect() { mCS = 1; } /** * Send 3 bytes to the dac. Discard returned values. */ inline void send(uint8_t a, uint8_t b, uint8_t c) { enableChipSelect(); write(a); write(b); write(c); disableChipSelect(); } /** * Send 3 bytes, Receive 3 bytes. To receive from the previous command * use transferNop() * @return: a 32bit unsigned int with the received 3 bytes. */ // do range check your input. inline uint32_t transfer(uint8_t a, uint8_t b, uint8_t c) { enableChipSelect(); // TODO(dps): refactor to shorter code. uint8_t aa = (uint8_t)write(a); uint8_t ab = (uint8_t)write(b); uint8_t ac = (uint8_t)write(c); uint32_t result = (uint32_t)aa; result = result << 8; result |= (uint32_t)ab; result = result << 8; result |= ac; disableChipSelect(); return result; /* uint32_t r = ((uint8_t)(write(a))) << 16; r |= ((uint8_t)(write(b))) << 8; r |= (uint8_t)(write(c)); disableChipSelect(); return r; */ } /** * Send a NOP to receive the output of the previous command. * @return: a 32bit unsigned int with the received 3 bytes. */ inline uint32_t transferNop() { return transfer( 0x18, 0, 0 ); } /** * Nothing to be done here yet. TODO(dps): move some items from the constructor? */ void setup() { } /** * returns the power control register. */ uint32_t getPowerControl() { send( RW | POWER_CONTROL, 0, 0 ); return transferNop(); } /** * returns the control register. */ uint32_t getControl() { send( RW | CONTROL_SET, 0, 0 ); return transferNop(); } /** * Set the output range for the addresses. * example : setOutputRange( ADDRESS_ALL, BIPOLAR_5V ); * */ void setOutputRange(int address, int range) { uint8_t a = OUTPUT_RANGE_SELECT | address; uint8_t b = 0; uint8_t c = range; // range & 0x7; send(a,b,c); } /** * Query the output range of the given address. * The address is stored in the lower bytes. * (result & 0x3) == BIPOLAR_5V */ uint32_t getOutputRange(int address) { uint8_t a = RW | OUTPUT_RANGE_SELECT | address; send(a,0,0); return transferNop(); } /** * * Set power control. * */ void setPowerControl(int channels) { /* AD5722R http://www.analog.com/static/imported-files/data_sheets/AD5722R_5732R_5752R.pdf |R/W |Zero|Reg2|Reg1|Reg0 | A2| A1| A0| | DB15-DB11|10 | 9| 8| | 7| 6| 5| 4| 3| 2| 1| 0| |0 |0 |0 |1 |0 |0 |0 |0 | | ---------|X |OCb|X | |OCa|0 |TSD|PUref|X |PUb|X |PUa| */ uint8_t a = POWER_CONTROL; uint8_t b = 0; uint8_t c = channels & 15; send(a,b,c); } void setControl() { uint8_t a = CONTROL_SET; uint8_t b = 0; uint8_t c = 8+4; // TSD termal shutdown + clamp enable send(a,b,c); } /** * Send a value to the dac. */ void setValue(int address, uint16_t value) { send(address,(uint8_t)(value >> 8) & 0xFF,(uint8_t)(value) & 0xFF); } private: DigitalOut mCS; };