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