toiy

Dependencies:   mbed

Committer:
jnjtnutty
Date:
Thu Nov 23 12:09:10 2017 +0000
Revision:
0:daa660f72f9f
toiy

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jnjtnutty 0:daa660f72f9f 1 /*
jnjtnutty 0:daa660f72f9f 2 * MCP4922 - DAC library.
jnjtnutty 0:daa660f72f9f 3 */
jnjtnutty 0:daa660f72f9f 4
jnjtnutty 0:daa660f72f9f 5 #include "mbed.h"
jnjtnutty 0:daa660f72f9f 6 #include "MCP4922.h"
jnjtnutty 0:daa660f72f9f 7
jnjtnutty 0:daa660f72f9f 8 using namespace mbed;
jnjtnutty 0:daa660f72f9f 9
jnjtnutty 0:daa660f72f9f 10 int dac =0;
jnjtnutty 0:daa660f72f9f 11
jnjtnutty 0:daa660f72f9f 12 MCP4922::MCP4922(PinName mosi, PinName sclk, PinName cs) : _spi(mosi, NC, sclk) {
jnjtnutty 0:daa660f72f9f 13
jnjtnutty 0:daa660f72f9f 14 int i;
jnjtnutty 0:daa660f72f9f 15 _ndacs = 1;
jnjtnutty 0:daa660f72f9f 16 _ncs_array = new DigitalOut*[ _ndacs ];
jnjtnutty 0:daa660f72f9f 17 for (i=0; i<_ndacs; i++) {
jnjtnutty 0:daa660f72f9f 18 _ncs_array[i] = new DigitalOut(cs);
jnjtnutty 0:daa660f72f9f 19 }
jnjtnutty 0:daa660f72f9f 20
jnjtnutty 0:daa660f72f9f 21 // Initialise the DAC SPI interface.
jnjtnutty 0:daa660f72f9f 22 _init();
jnjtnutty 0:daa660f72f9f 23 }
jnjtnutty 0:daa660f72f9f 24
jnjtnutty 0:daa660f72f9f 25 // Destructor
jnjtnutty 0:daa660f72f9f 26 MCP4922::~MCP4922() {
jnjtnutty 0:daa660f72f9f 27
jnjtnutty 0:daa660f72f9f 28 // Before destroying the object, shut down all the chips.
jnjtnutty 0:daa660f72f9f 29 //shdn_all();
jnjtnutty 0:daa660f72f9f 30
jnjtnutty 0:daa660f72f9f 31 // Delete all the NCS DigitalOut objects and the array pointing to
jnjtnutty 0:daa660f72f9f 32 // them.
jnjtnutty 0:daa660f72f9f 33 int i;
jnjtnutty 0:daa660f72f9f 34 for (i=0; i<_ndacs; i++) {
jnjtnutty 0:daa660f72f9f 35 delete _ncs_array[i];
jnjtnutty 0:daa660f72f9f 36 }
jnjtnutty 0:daa660f72f9f 37 delete [] _ncs_array;
jnjtnutty 0:daa660f72f9f 38
jnjtnutty 0:daa660f72f9f 39 // Delete the LDAC DigitalOut object if it exists.
jnjtnutty 0:daa660f72f9f 40 if (_latched ) delete _nldac;
jnjtnutty 0:daa660f72f9f 41 }
jnjtnutty 0:daa660f72f9f 42
jnjtnutty 0:daa660f72f9f 43 // Initialise SPI interface.
jnjtnutty 0:daa660f72f9f 44 void MCP4922::_init() {
jnjtnutty 0:daa660f72f9f 45
jnjtnutty 0:daa660f72f9f 46 // Set up the SPI for 16-bit values (12-bit + 4 command bits) and mode 0.
jnjtnutty 0:daa660f72f9f 47 _spi.format(16, 0);
jnjtnutty 0:daa660f72f9f 48
jnjtnutty 0:daa660f72f9f 49 // Start with all the CS and LDAC signals high (disabled)
jnjtnutty 0:daa660f72f9f 50 int i;
jnjtnutty 0:daa660f72f9f 51 for (i=0; i<_ndacs; i++) {
jnjtnutty 0:daa660f72f9f 52 _ncs_array[i]->write(1);
jnjtnutty 0:daa660f72f9f 53 }
jnjtnutty 0:daa660f72f9f 54
jnjtnutty 0:daa660f72f9f 55 if (_latched ) _nldac->write(1);
jnjtnutty 0:daa660f72f9f 56 return;
jnjtnutty 0:daa660f72f9f 57 }
jnjtnutty 0:daa660f72f9f 58
jnjtnutty 0:daa660f72f9f 59 // Set SPI clock frequency.
jnjtnutty 0:daa660f72f9f 60 void MCP4922::frequency( int freq ) {
jnjtnutty 0:daa660f72f9f 61
jnjtnutty 0:daa660f72f9f 62 // Set the SPI interface clock frequency in Hz.
jnjtnutty 0:daa660f72f9f 63 _spi.frequency( freq );
jnjtnutty 0:daa660f72f9f 64 return;
jnjtnutty 0:daa660f72f9f 65 }
jnjtnutty 0:daa660f72f9f 66
jnjtnutty 0:daa660f72f9f 67 /*
jnjtnutty 0:daa660f72f9f 68 * Note: There is a lot of code in common between the following 4 functions.
jnjtnutty 0:daa660f72f9f 69 * The code is kept in line to keep it efficient. Could the functions have
jnjtnutty 0:daa660f72f9f 70 * been written as templates?
jnjtnutty 0:daa660f72f9f 71 */
jnjtnutty 0:daa660f72f9f 72 // Write to DAC channel A with gain 1.
jnjtnutty 0:daa660f72f9f 73 void MCP4922::writeA(int value) {
jnjtnutty 0:daa660f72f9f 74
jnjtnutty 0:daa660f72f9f 75 // Set up the command register with the appropriate value.
jnjtnutty 0:daa660f72f9f 76 // For efficiency, the caller is assumed to have checked dac.
jnjtnutty 0:daa660f72f9f 77 int reg;
jnjtnutty 0:daa660f72f9f 78 //int dac = 0;
jnjtnutty 0:daa660f72f9f 79 reg = (value & 0x0FFF) | MCP4922_REG_A1;
jnjtnutty 0:daa660f72f9f 80
jnjtnutty 0:daa660f72f9f 81 // Select the DAC chip, write to its command register and
jnjtnutty 0:daa660f72f9f 82 // then unselect the DAC chip.
jnjtnutty 0:daa660f72f9f 83 _ncs_array[dac]->write(0);
jnjtnutty 0:daa660f72f9f 84 _spi.write(reg);
jnjtnutty 0:daa660f72f9f 85 _ncs_array[dac]->write(1);
jnjtnutty 0:daa660f72f9f 86 return;
jnjtnutty 0:daa660f72f9f 87 }
jnjtnutty 0:daa660f72f9f 88
jnjtnutty 0:daa660f72f9f 89 // Write to DAC channel B with gain 1.
jnjtnutty 0:daa660f72f9f 90 void MCP4922::writeB(int value) {
jnjtnutty 0:daa660f72f9f 91
jnjtnutty 0:daa660f72f9f 92 // Set up the command register with the appropriate value.
jnjtnutty 0:daa660f72f9f 93 // For efficiency, the caller is assumed to have checked dac.
jnjtnutty 0:daa660f72f9f 94 int reg;
jnjtnutty 0:daa660f72f9f 95 reg = (value & 0x0FFF) | MCP4922_REG_B1;
jnjtnutty 0:daa660f72f9f 96
jnjtnutty 0:daa660f72f9f 97 // Select the DAC chip, write to its command register and then
jnjtnutty 0:daa660f72f9f 98 // unselect the DAC chip.
jnjtnutty 0:daa660f72f9f 99 _ncs_array[dac]->write(0);
jnjtnutty 0:daa660f72f9f 100 _spi.write(reg);
jnjtnutty 0:daa660f72f9f 101 _ncs_array[dac]->write(1);
jnjtnutty 0:daa660f72f9f 102 return;
jnjtnutty 0:daa660f72f9f 103 }
jnjtnutty 0:daa660f72f9f 104
jnjtnutty 0:daa660f72f9f 105 // Write an array of values to the DACs.
jnjtnutty 0:daa660f72f9f 106 void MCP4922::write(int nchans, int values[], int gain, int latch) {
jnjtnutty 0:daa660f72f9f 107
jnjtnutty 0:daa660f72f9f 108 // nchans must be at least 1 but less than or equal to ndacs x 2.
jnjtnutty 0:daa660f72f9f 109 if (nchans < 1) nchans = 1;
jnjtnutty 0:daa660f72f9f 110 const int maxchans = _ndacs * 2;
jnjtnutty 0:daa660f72f9f 111 if (nchans > maxchans) nchans = maxchans;
jnjtnutty 0:daa660f72f9f 112
jnjtnutty 0:daa660f72f9f 113 if (latch && _latched)
jnjtnutty 0:daa660f72f9f 114 latch_disable();
jnjtnutty 0:daa660f72f9f 115
jnjtnutty 0:daa660f72f9f 116 int i;
jnjtnutty 0:daa660f72f9f 117
jnjtnutty 0:daa660f72f9f 118 for (i=0; i<nchans;) {
jnjtnutty 0:daa660f72f9f 119 dac = i/2;
jnjtnutty 0:daa660f72f9f 120 writeA(values[i]);
jnjtnutty 0:daa660f72f9f 121 i++;
jnjtnutty 0:daa660f72f9f 122 if (i < nchans) {
jnjtnutty 0:daa660f72f9f 123 writeB(values[i]);
jnjtnutty 0:daa660f72f9f 124 i++;
jnjtnutty 0:daa660f72f9f 125 } else break;
jnjtnutty 0:daa660f72f9f 126 }
jnjtnutty 0:daa660f72f9f 127
jnjtnutty 0:daa660f72f9f 128 // Automatically latch the new voltages if the latch flag is 1.
jnjtnutty 0:daa660f72f9f 129 if (latch && _latched)
jnjtnutty 0:daa660f72f9f 130 latch_enable();
jnjtnutty 0:daa660f72f9f 131 return;
jnjtnutty 0:daa660f72f9f 132 }
jnjtnutty 0:daa660f72f9f 133
jnjtnutty 0:daa660f72f9f 134 // Set latch signal to "enable".
jnjtnutty 0:daa660f72f9f 135 void MCP4922::latch_enable() {
jnjtnutty 0:daa660f72f9f 136
jnjtnutty 0:daa660f72f9f 137 // Latch all chips. There should be a delay of at least T_LS=40
jnjtnutty 0:daa660f72f9f 138 // nanoseconds between the last CS rising edge and the LDAC falling
jnjtnutty 0:daa660f72f9f 139 // edge. The software function calls seem to be sufficient to
jnjtnutty 0:daa660f72f9f 140 // introduce that delay. A delay may be inserted here if this
jnjtnutty 0:daa660f72f9f 141 // software is ported to a faster processor.
jnjtnutty 0:daa660f72f9f 142 if (_latched) _nldac->write(0);
jnjtnutty 0:daa660f72f9f 143 // The LDAC pulse width must be at least T_LD=100 nanoseconds long.
jnjtnutty 0:daa660f72f9f 144 // A delay can be inserted here if necessary, but so far this has
jnjtnutty 0:daa660f72f9f 145 // not been needed (see above).
jnjtnutty 0:daa660f72f9f 146 return;
jnjtnutty 0:daa660f72f9f 147 }
jnjtnutty 0:daa660f72f9f 148
jnjtnutty 0:daa660f72f9f 149 // Set latch signal to "disable".
jnjtnutty 0:daa660f72f9f 150 void MCP4922::latch_disable() {
jnjtnutty 0:daa660f72f9f 151
jnjtnutty 0:daa660f72f9f 152 // Disable latch for all chips.
jnjtnutty 0:daa660f72f9f 153 if (_latched) _nldac->write(1);
jnjtnutty 0:daa660f72f9f 154 return;
jnjtnutty 0:daa660f72f9f 155 }
jnjtnutty 0:daa660f72f9f 156