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