toiy
Dependencies: mbed
MCP4922.cpp@0:daa660f72f9f, 2017-11-23 (annotated)
- Committer:
- jnjtnutty
- Date:
- Thu Nov 23 12:09:10 2017 +0000
- Revision:
- 0:daa660f72f9f
toiy
Who changed what in which revision?
User | Revision | Line number | New 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 |