drive the analog devices AD57XX series of DACs using SPI
Diff: dac57xx.h
- Revision:
- 1:59ce04153689
- Parent:
- 0:cbb2d9111355
diff -r cbb2d9111355 -r 59ce04153689 dac57xx.h --- a/dac57xx.h Tue Oct 25 00:02:56 2011 +0000 +++ b/dac57xx.h Wed Oct 26 06:42:45 2011 +0000 @@ -1,206 +1,226 @@ -#pragma once -#include <stdint.h> - - -/** - * a library for driving the Analog Devices Dac 57xx series. - * - * - */ - -class DacAD57XX : public SPI { -public: - /** - * - */ - DacAD57XX(PinName mosi, PinName miso, PinName sclk, PinName cs) : - SPI(mosi, miso, sclk), - mCS(cs) - { - 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 << 8; - result |= (uint32_t)ab; - 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 ); - } - - - void setup() - { - } - - uint32_t getPowerControl() - { - send( RW | POWER_CONTROL, 0, 0 ); - return transferNop(); - } - 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(); - } - - 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; - +#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; + }; \ No newline at end of file