Write to a daisy chained array of MCP4822 DAC chips, with latching.

Dependents:   MCP4822_demo MCP4822_SinewaveV2

Committer:
ukatcsmb
Date:
Tue Feb 22 17:23:08 2011 +0000
Revision:
0:fcd6f2777ddd
First published

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ukatcsmb 0:fcd6f2777ddd 1 /*
ukatcsmb 0:fcd6f2777ddd 2 * MCP4822A - DAC array library.
ukatcsmb 0:fcd6f2777ddd 3 *
ukatcsmb 0:fcd6f2777ddd 4 * Copyright (c) 2011 Steven Beard, UK Astronomy Technology Centre.
ukatcsmb 0:fcd6f2777ddd 5 *
ukatcsmb 0:fcd6f2777ddd 6 * Permission is hereby granted, free of charge, to any person obtaining a copy
ukatcsmb 0:fcd6f2777ddd 7 * of this software and associated documentation files (the "Software"), to deal
ukatcsmb 0:fcd6f2777ddd 8 * in the Software without restriction, including without limitation the rights
ukatcsmb 0:fcd6f2777ddd 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
ukatcsmb 0:fcd6f2777ddd 10 * copies of the Software, and to permit persons to whom the Software is
ukatcsmb 0:fcd6f2777ddd 11 * furnished to do so, subject to the following conditions:
ukatcsmb 0:fcd6f2777ddd 12 *
ukatcsmb 0:fcd6f2777ddd 13 * The above copyright notice and this permission notice shall be included in
ukatcsmb 0:fcd6f2777ddd 14 * all copies or substantial portions of the Software.
ukatcsmb 0:fcd6f2777ddd 15 *
ukatcsmb 0:fcd6f2777ddd 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
ukatcsmb 0:fcd6f2777ddd 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
ukatcsmb 0:fcd6f2777ddd 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
ukatcsmb 0:fcd6f2777ddd 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
ukatcsmb 0:fcd6f2777ddd 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
ukatcsmb 0:fcd6f2777ddd 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
ukatcsmb 0:fcd6f2777ddd 22 * THE SOFTWARE.
ukatcsmb 0:fcd6f2777ddd 23 */
ukatcsmb 0:fcd6f2777ddd 24
ukatcsmb 0:fcd6f2777ddd 25 #include "mbed.h"
ukatcsmb 0:fcd6f2777ddd 26
ukatcsmb 0:fcd6f2777ddd 27 #ifndef MCP4822_H
ukatcsmb 0:fcd6f2777ddd 28 #define MCP4822_H
ukatcsmb 0:fcd6f2777ddd 29
ukatcsmb 0:fcd6f2777ddd 30 /* Reference: Microchip Technology (2005), MCP4821/MCP4822 DAC Data Sheet. */
ukatcsmb 0:fcd6f2777ddd 31
ukatcsmb 0:fcd6f2777ddd 32 // MCP4822 reference voltage.
ukatcsmb 0:fcd6f2777ddd 33 #define MCP4822_VREF 2048 // Reference voltage (mV)
ukatcsmb 0:fcd6f2777ddd 34
ukatcsmb 0:fcd6f2777ddd 35 /* Define possible combinations of 16-bit command register bits */
ukatcsmb 0:fcd6f2777ddd 36 #define MCP4822_REG_A1 0x3000 // Channel A gain 1
ukatcsmb 0:fcd6f2777ddd 37 #define MCP4822_REG_A2 0x1000 // Channel A gain 2
ukatcsmb 0:fcd6f2777ddd 38 #define MCP4822_REG_B1 0xB000 // Channel B gain 1
ukatcsmb 0:fcd6f2777ddd 39 #define MCP4822_REG_B2 0x9000 // Channel B gain 2
ukatcsmb 0:fcd6f2777ddd 40 #define MCP4822_REG_SHDN 0x0000 // Output power down
ukatcsmb 0:fcd6f2777ddd 41
ukatcsmb 0:fcd6f2777ddd 42 /*+
ukatcsmb 0:fcd6f2777ddd 43 * Interface to an array of MCP4822 12-bit dual-output DACs daisy chained
ukatcsmb 0:fcd6f2777ddd 44 * on an SPI bus, with each DAC selected using an array of DigitalOut pins.
ukatcsmb 0:fcd6f2777ddd 45 * All the DACs may be latched together using a common nLDAC pin.
ukatcsmb 0:fcd6f2777ddd 46 *
ukatcsmb 0:fcd6f2777ddd 47 * +-----------------------------------+
ukatcsmb 0:fcd6f2777ddd 48 * |+------------------------+ |
ukatcsmb 0:fcd6f2777ddd 49 * ||+-------------+ | |
ukatcsmb 0:fcd6f2777ddd 50 * ||| nCS1 nCS2 nCS3
ukatcsmb 0:fcd6f2777ddd 51 * +--+++-+ | | |
ukatcsmb 0:fcd6f2777ddd 52 * | | +-+----+ +-+----+ +-+----+
ukatcsmb 0:fcd6f2777ddd 53 * | mbed +---SPI---+ DAC1 +--+ DAC2 +--+ DAC3 +--etc...
ukatcsmb 0:fcd6f2777ddd 54 * | | +-+----+ +-+----+ +-+----+
ukatcsmb 0:fcd6f2777ddd 55 * +---+--+ | | |
ukatcsmb 0:fcd6f2777ddd 56 * | nLDAC nLDAC nLDAC
ukatcsmb 0:fcd6f2777ddd 57 * +--------------+---------+---------+
ukatcsmb 0:fcd6f2777ddd 58 *-
ukatcsmb 0:fcd6f2777ddd 59 */
ukatcsmb 0:fcd6f2777ddd 60 class MCP4822A {
ukatcsmb 0:fcd6f2777ddd 61 public:
ukatcsmb 0:fcd6f2777ddd 62 /*+
ukatcsmb 0:fcd6f2777ddd 63 * Constructor: MCP4822A
ukatcsmb 0:fcd6f2777ddd 64 *
ukatcsmb 0:fcd6f2777ddd 65 * Description:
ukatcsmb 0:fcd6f2777ddd 66 * A class which describes an array of MCP4822 DACs connected in
ukatcsmb 0:fcd6f2777ddd 67 * a daisy chain with an SPI interface. Each DAC is selected using
ukatcsmb 0:fcd6f2777ddd 68 * its own separate "not CS" pin and all the DACs may be latched
ukatcsmb 0:fcd6f2777ddd 69 * together using a single "not LDAC" pin.
ukatcsmb 0:fcd6f2777ddd 70 *
ukatcsmb 0:fcd6f2777ddd 71 * Parameters:
ukatcsmb 0:fcd6f2777ddd 72 * ndacs, int
ukatcsmb 0:fcd6f2777ddd 73 * The number of DAC chips included in the array. Must be at
ukatcsmb 0:fcd6f2777ddd 74 * least 1. (Limited by the number of "not CS" pins available.)
ukatcsmb 0:fcd6f2777ddd 75 * mosi, PinName
ukatcsmb 0:fcd6f2777ddd 76 * The SPI data out pin.
ukatcsmb 0:fcd6f2777ddd 77 * sclk, PinName
ukatcsmb 0:fcd6f2777ddd 78 * The SPI clock pin.
ukatcsmb 0:fcd6f2777ddd 79 * ncslist, PinName[]
ukatcsmb 0:fcd6f2777ddd 80 * An array of "not chip select" ("not CS") pins - one per DAC
ukatcsmb 0:fcd6f2777ddd 81 * chip. Each pin is held low to make the DAC respond to SPI
ukatcsmb 0:fcd6f2777ddd 82 * input. The array must contain at least ndacs elements (only
ukatcsmb 0:fcd6f2777ddd 83 * the first ndacs elements will be used).
ukatcsmb 0:fcd6f2777ddd 84 * nldac, PinName (optional)
ukatcsmb 0:fcd6f2777ddd 85 * The "not latch DAC" ("not LDAC") pin. Setting this pin low
ukatcsmb 0:fcd6f2777ddd 86 * causes each DAC to apply the preset A and B voltages to its
ukatcsmb 0:fcd6f2777ddd 87 * outputs. The pin is optional. The DAC will apply new voltages
ukatcsmb 0:fcd6f2777ddd 88 * immediately if the "not LDAC" pin is held permanently to
ukatcsmb 0:fcd6f2777ddd 89 * ground. This parameter is optional, and if not given will be
ukatcsmb 0:fcd6f2777ddd 90 * assumed NC (not connected).
ukatcsmb 0:fcd6f2777ddd 91 *-
ukatcsmb 0:fcd6f2777ddd 92 */
ukatcsmb 0:fcd6f2777ddd 93 MCP4822A ( int ndacs, PinName mosi, PinName sclk, PinName ncslist[], PinName nldac=NC );
ukatcsmb 0:fcd6f2777ddd 94
ukatcsmb 0:fcd6f2777ddd 95 /*+
ukatcsmb 0:fcd6f2777ddd 96 * Destructor: MCP4822A
ukatcsmb 0:fcd6f2777ddd 97 *-
ukatcsmb 0:fcd6f2777ddd 98 */
ukatcsmb 0:fcd6f2777ddd 99 ~MCP4822A();
ukatcsmb 0:fcd6f2777ddd 100
ukatcsmb 0:fcd6f2777ddd 101 /*+
ukatcsmb 0:fcd6f2777ddd 102 * frequency: Set the SPI bus clock frequency in Hz.
ukatcsmb 0:fcd6f2777ddd 103 *
ukatcsmb 0:fcd6f2777ddd 104 * Parameters:
ukatcsmb 0:fcd6f2777ddd 105 * freq, int
ukatcsmb 0:fcd6f2777ddd 106 * The SPI bus frequency in Hz. Must be within the range
ukatcsmb 0:fcd6f2777ddd 107 * supported by both the SPI interface and the DAC chips
ukatcsmb 0:fcd6f2777ddd 108 * (~10 KHz to 20 MHz).
ukatcsmb 0:fcd6f2777ddd 109 *-
ukatcsmb 0:fcd6f2777ddd 110 */
ukatcsmb 0:fcd6f2777ddd 111 void frequency( int freq );
ukatcsmb 0:fcd6f2777ddd 112
ukatcsmb 0:fcd6f2777ddd 113 /*+
ukatcsmb 0:fcd6f2777ddd 114 * writeA1: Write 12-bit data to channel A with gain set to 1.
ukatcsmb 0:fcd6f2777ddd 115 * writeA2: Write 12-bit data to channel A with gain set to 2.
ukatcsmb 0:fcd6f2777ddd 116 * writeB1: Write 12-bit data to channel B with gain set to 1.
ukatcsmb 0:fcd6f2777ddd 117 * writeB2: Write 12-bit data to channel B with gain set to 2.
ukatcsmb 0:fcd6f2777ddd 118 *
ukatcsmb 0:fcd6f2777ddd 119 * These functions will automatically select the chip with the "not CS"
ukatcsmb 0:fcd6f2777ddd 120 * signal. If the "not LDAC" pin is used, it is up to the caller to
ukatcsmb 0:fcd6f2777ddd 121 * enable or disable that signal. For example:
ukatcsmb 0:fcd6f2777ddd 122 *
ukatcsmb 0:fcd6f2777ddd 123 * latch_disable();
ukatcsmb 0:fcd6f2777ddd 124 * writeA2( 1500 );
ukatcsmb 0:fcd6f2777ddd 125 * latch_enable();
ukatcsmb 0:fcd6f2777ddd 126 *
ukatcsmb 0:fcd6f2777ddd 127 * Choose these functions when high performance is most important.
ukatcsmb 0:fcd6f2777ddd 128 *
ukatcsmb 0:fcd6f2777ddd 129 * Parameters:
ukatcsmb 0:fcd6f2777ddd 130 * dac, int
ukatcsmb 0:fcd6f2777ddd 131 * The DAC chip to be addressed, corresponding to the elements
ukatcsmb 0:fcd6f2777ddd 132 * of the ncslist[] array used to create the MCP4822A object.
ukatcsmb 0:fcd6f2777ddd 133 * Must be in the range 0 to ndacs-1.
ukatcsmb 0:fcd6f2777ddd 134 * value, int
ukatcsmb 0:fcd6f2777ddd 135 * The number to be written to the 12 data bits of the A or B
ukatcsmb 0:fcd6f2777ddd 136 * register of the DAC chip. At a gain setting of 2, this value
ukatcsmb 0:fcd6f2777ddd 137 * corresponds to a voltage demand in millivolts. Only the first
ukatcsmb 0:fcd6f2777ddd 138 * 12 bits are used, so the value will wrap around after 4095.
ukatcsmb 0:fcd6f2777ddd 139 * (Note: Strictly this should be an unsigned int, but the SPI
ukatcsmb 0:fcd6f2777ddd 140 * interface library expects an int.)
ukatcsmb 0:fcd6f2777ddd 141 *-
ukatcsmb 0:fcd6f2777ddd 142 */
ukatcsmb 0:fcd6f2777ddd 143 void writeA1( int dac, int value );
ukatcsmb 0:fcd6f2777ddd 144 void writeA2( int dac, int value );
ukatcsmb 0:fcd6f2777ddd 145 void writeB1( int dac, int value );
ukatcsmb 0:fcd6f2777ddd 146 void writeB2( int dac, int value );
ukatcsmb 0:fcd6f2777ddd 147
ukatcsmb 0:fcd6f2777ddd 148 /*+
ukatcsmb 0:fcd6f2777ddd 149 * write: Write an array of 12-bit register values to multiple DAC channels.
ukatcsmb 0:fcd6f2777ddd 150 *
ukatcsmb 0:fcd6f2777ddd 151 * Choose this function when flexibility and convenience are most important.
ukatcsmb 0:fcd6f2777ddd 152 *
ukatcsmb 0:fcd6f2777ddd 153 * Parameters:
ukatcsmb 0:fcd6f2777ddd 154 * nchans, int
ukatcsmb 0:fcd6f2777ddd 155 * The number of channels to be written. There are two channels
ukatcsmb 0:fcd6f2777ddd 156 * per DAC, so this value must lie between 2 and ndacs x 2.
ukatcsmb 0:fcd6f2777ddd 157 * values, int[]
ukatcsmb 0:fcd6f2777ddd 158 * An array of values to be written to the 12 data bits of the DAC
ukatcsmb 0:fcd6f2777ddd 159 * registers, in the order dac/chan = 0/A, 0/B, 1/A, 1/B, etc...
ukatcsmb 0:fcd6f2777ddd 160 * The array must contain at least nchans elements (but only the
ukatcsmb 0:fcd6f2777ddd 161 * first nchans elements will be used for longer arrays).
ukatcsmb 0:fcd6f2777ddd 162 * At a gain setting of 2, these values corresponds to a voltage
ukatcsmb 0:fcd6f2777ddd 163 * demand in millivolts. They will wrap back to 0 above 4095.
ukatcsmb 0:fcd6f2777ddd 164 * (Note: Strictly this should be an unsigned int array, but the SPI
ukatcsmb 0:fcd6f2777ddd 165 * interface library expects an int.)
ukatcsmb 0:fcd6f2777ddd 166 * gain, int (optional)
ukatcsmb 0:fcd6f2777ddd 167 * The required gain setting (1 or 2). If not specified, a default
ukatcsmb 0:fcd6f2777ddd 168 * of 2 will be assumed.
ukatcsmb 0:fcd6f2777ddd 169 * latch, int (optional)
ukatcsmb 0:fcd6f2777ddd 170 * A flag set to 1 if the "not LDAC" signal should be latched after
ukatcsmb 0:fcd6f2777ddd 171 * setting up the array of voltages. If not specified, a default
ukatcsmb 0:fcd6f2777ddd 172 * of 1 will be assumed.
ukatcsmb 0:fcd6f2777ddd 173 *-
ukatcsmb 0:fcd6f2777ddd 174 */
ukatcsmb 0:fcd6f2777ddd 175 void write( int nchans, int values[], int gain=2, int latch=1 );
ukatcsmb 0:fcd6f2777ddd 176
ukatcsmb 0:fcd6f2777ddd 177 /*+
ukatcsmb 0:fcd6f2777ddd 178 * voltage2value - convert a voltage into a 12-bit data value.
ukatcsmb 0:fcd6f2777ddd 179 *
ukatcsmb 0:fcd6f2777ddd 180 * Parameters:
ukatcsmb 0:fcd6f2777ddd 181 * voltage, float
ukatcsmb 0:fcd6f2777ddd 182 * The voltage to be converted (in volts). The sign is ignored.
ukatcsmb 0:fcd6f2777ddd 183 * gain, int (optional)
ukatcsmb 0:fcd6f2777ddd 184 * The gain setting required (1 or 2). If not specified, a default
ukatcsmb 0:fcd6f2777ddd 185 * of 2 will be assumed.
ukatcsmb 0:fcd6f2777ddd 186 *
ukatcsmb 0:fcd6f2777ddd 187 * Returns:
ukatcsmb 0:fcd6f2777ddd 188 * value, int.
ukatcsmb 0:fcd6f2777ddd 189 * The 12-bit data value corresponding to the given
ukatcsmb 0:fcd6f2777ddd 190 * voltage. 4095 will be returned for out of range
ukatcsmb 0:fcd6f2777ddd 191 * voltages.
ukatcsmb 0:fcd6f2777ddd 192 *-
ukatcsmb 0:fcd6f2777ddd 193 */
ukatcsmb 0:fcd6f2777ddd 194 int voltage2value( float voltage, int gain=2 );
ukatcsmb 0:fcd6f2777ddd 195
ukatcsmb 0:fcd6f2777ddd 196 /*+
ukatcsmb 0:fcd6f2777ddd 197 * value2voltage - convert a 12-bit data value into a voltage.
ukatcsmb 0:fcd6f2777ddd 198 *
ukatcsmb 0:fcd6f2777ddd 199 * Parameters:
ukatcsmb 0:fcd6f2777ddd 200 * value, int
ukatcsmb 0:fcd6f2777ddd 201 * The 12-bit data value to be converted to a voltage.
ukatcsmb 0:fcd6f2777ddd 202 * gain, int (optional)
ukatcsmb 0:fcd6f2777ddd 203 * The gain setting required (1 or 2). If not specified, a default
ukatcsmb 0:fcd6f2777ddd 204 * of 2 will be assumed.
ukatcsmb 0:fcd6f2777ddd 205 *
ukatcsmb 0:fcd6f2777ddd 206 * Returns:
ukatcsmb 0:fcd6f2777ddd 207 * voltage, float.
ukatcsmb 0:fcd6f2777ddd 208 * The voltage (in volts) corresponding the the given 12-bit
ukatcsmb 0:fcd6f2777ddd 209 * data value at the given gain setting.
ukatcsmb 0:fcd6f2777ddd 210 *-
ukatcsmb 0:fcd6f2777ddd 211 */
ukatcsmb 0:fcd6f2777ddd 212 float value2voltage( int value, int gain=2 );
ukatcsmb 0:fcd6f2777ddd 213
ukatcsmb 0:fcd6f2777ddd 214 /*+
ukatcsmb 0:fcd6f2777ddd 215 * latch_enable: enable the latch signal - the DAC(s) will apply
ukatcsmb 0:fcd6f2777ddd 216 * voltage demands.
ukatcsmb 0:fcd6f2777ddd 217 *
ukatcsmb 0:fcd6f2777ddd 218 * latch_disable: disable the latch signal - the DAC(s) will not
ukatcsmb 0:fcd6f2777ddd 219 * apply voltage demands.
ukatcsmb 0:fcd6f2777ddd 220 *
ukatcsmb 0:fcd6f2777ddd 221 * These functions only apply for objects constructed with the
ukatcsmb 0:fcd6f2777ddd 222 * optional nldac parameter assigned to a pin.
ukatcsmb 0:fcd6f2777ddd 223 *-
ukatcsmb 0:fcd6f2777ddd 224 */
ukatcsmb 0:fcd6f2777ddd 225 void latch_enable();
ukatcsmb 0:fcd6f2777ddd 226 void latch_disable();
ukatcsmb 0:fcd6f2777ddd 227
ukatcsmb 0:fcd6f2777ddd 228 /*+
ukatcsmb 0:fcd6f2777ddd 229 * shdn: Shut down a DAC. It will sleep until woken by a new command
ukatcsmb 0:fcd6f2777ddd 230 * over the SPI bus.
ukatcsmb 0:fcd6f2777ddd 231 *-
ukatcsmb 0:fcd6f2777ddd 232 */
ukatcsmb 0:fcd6f2777ddd 233 void shdn(int dac);
ukatcsmb 0:fcd6f2777ddd 234 void shdn_all();
ukatcsmb 0:fcd6f2777ddd 235
ukatcsmb 0:fcd6f2777ddd 236 private:
ukatcsmb 0:fcd6f2777ddd 237 // Make copy constructor private to prevent the object being copied.
ukatcsmb 0:fcd6f2777ddd 238 // The pins are available to one and only one object.
ukatcsmb 0:fcd6f2777ddd 239 MCP4822A( const MCP4822A& rhs );
ukatcsmb 0:fcd6f2777ddd 240
ukatcsmb 0:fcd6f2777ddd 241 /* Initialise the DAC interface. */
ukatcsmb 0:fcd6f2777ddd 242 void _init();
ukatcsmb 0:fcd6f2777ddd 243
ukatcsmb 0:fcd6f2777ddd 244 int _ndacs; // The number of DACS in the array
ukatcsmb 0:fcd6f2777ddd 245 int _latched; // Is the "not LDAC" pin used (1=yes; 0=no)?
ukatcsmb 0:fcd6f2777ddd 246 SPI _spi; // SPI bus object for communicating with DAC.
ukatcsmb 0:fcd6f2777ddd 247 DigitalOut** _ncs_array; // Array of pointers to DigitalOut objects
ukatcsmb 0:fcd6f2777ddd 248 // connected to "not CS" pins.
ukatcsmb 0:fcd6f2777ddd 249 DigitalOut* _nldac; // Pointer to DigitalOut object connected
ukatcsmb 0:fcd6f2777ddd 250 // to "not LDAC" pin (if any - NULL if none).
ukatcsmb 0:fcd6f2777ddd 251 };
ukatcsmb 0:fcd6f2777ddd 252
ukatcsmb 0:fcd6f2777ddd 253 #endif