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

Dependents:   MCP4822_demo MCP4822_SinewaveV2

Revision:
0:fcd6f2777ddd
diff -r 000000000000 -r fcd6f2777ddd MCP4822A.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MCP4822A.h	Tue Feb 22 17:23:08 2011 +0000
@@ -0,0 +1,253 @@
+/*
+ * MCP4822A - DAC array library.
+ *
+ * Copyright (c) 2011 Steven Beard, UK Astronomy Technology Centre.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "mbed.h"
+
+#ifndef MCP4822_H
+#define MCP4822_H
+
+/* Reference: Microchip Technology (2005), MCP4821/MCP4822 DAC Data Sheet. */
+
+// MCP4822 reference voltage.
+#define MCP4822_VREF     2048    // Reference voltage (mV)
+
+/* Define possible combinations of 16-bit command register bits */
+#define MCP4822_REG_A1   0x3000  // Channel A gain 1
+#define MCP4822_REG_A2   0x1000  // Channel A gain 2
+#define MCP4822_REG_B1   0xB000  // Channel B gain 1
+#define MCP4822_REG_B2   0x9000  // Channel B gain 2
+#define MCP4822_REG_SHDN 0x0000  // Output power down
+
+/*+
+ * Interface to an array of MCP4822 12-bit dual-output DACs daisy chained
+ * on an SPI bus, with each DAC selected using an array of DigitalOut pins.
+ * All the DACs may be latched together using a common nLDAC pin.
+ *
+ *       +-----------------------------------+
+ *       |+------------------------+         |
+ *       ||+-------------+         |         |
+ *       |||            nCS1      nCS2      nCS3
+ *    +--+++-+           |         |         |
+ *    |      |         +-+----+  +-+----+  +-+----+
+ *    | mbed +---SPI---+ DAC1 +--+ DAC2 +--+ DAC3 +--etc...
+ *    |      |         +-+----+  +-+----+  +-+----+
+ *    +---+--+           |         |         |
+ *        |            nLDAC     nLDAC     nLDAC
+ *        +--------------+---------+---------+
+ *-
+ */
+class MCP4822A {
+public:
+    /*+
+     * Constructor: MCP4822A
+     *
+     * Description:
+     *    A class which describes an array of MCP4822 DACs connected in
+     *    a daisy chain with an SPI interface. Each DAC is selected using
+     *    its own separate "not CS" pin and all the DACs may be latched
+     *    together using a single "not LDAC" pin.
+     *
+     * Parameters:
+     *    ndacs, int
+     *        The number of DAC chips included in the array. Must be at
+     *        least 1. (Limited by the number of "not CS" pins available.)
+     *    mosi, PinName
+     *        The SPI data out pin.
+     *    sclk, PinName
+     *        The SPI clock pin.
+     *    ncslist, PinName[]
+     *        An array of "not chip select" ("not CS") pins - one per DAC
+     *        chip. Each pin is held low to make the DAC respond to SPI
+     *        input. The array must contain at least ndacs elements (only
+     *        the first ndacs elements will be used).
+     *    nldac, PinName (optional)
+     *        The "not latch DAC" ("not LDAC") pin. Setting this pin low
+     *        causes each DAC to apply the preset A and B voltages to its
+     *        outputs. The pin is optional. The DAC will apply new voltages
+     *        immediately if the "not LDAC" pin is held permanently to
+     *        ground. This parameter is optional, and if not given will be
+     *        assumed NC (not connected).
+     *-
+     */
+    MCP4822A ( int ndacs, PinName mosi, PinName sclk, PinName ncslist[], PinName nldac=NC );
+
+    /*+
+     * Destructor: MCP4822A
+     *-
+     */
+    ~MCP4822A();
+
+    /*+
+     * frequency: Set the SPI bus clock frequency in Hz.
+     *
+     * Parameters:
+     *    freq, int
+     *        The SPI bus frequency in Hz. Must be within the range
+     *        supported by both the SPI interface and the DAC chips
+     *        (~10 KHz to 20 MHz).
+     *-
+     */
+    void frequency( int freq );
+
+    /*+
+     * writeA1: Write 12-bit data to channel A with gain set to 1.
+     * writeA2: Write 12-bit data to channel A with gain set to 2.
+     * writeB1: Write 12-bit data to channel B with gain set to 1.
+     * writeB2: Write 12-bit data to channel B with gain set to 2.
+     *
+     * These functions will automatically select the chip with the "not CS"
+     * signal. If the "not LDAC" pin is used, it is up to the caller to
+     * enable or disable that signal. For example:
+     *
+     *     latch_disable();
+     *     writeA2( 1500 );
+     *     latch_enable();
+     *
+     * Choose these functions when high performance is most important.
+     *
+     * Parameters:
+     *    dac, int
+     *        The DAC chip to be addressed, corresponding to the elements
+     *        of the ncslist[] array used to create the MCP4822A object.
+     *        Must be in the range 0 to ndacs-1.
+     *    value, int
+     *        The number to be written to the 12 data bits of the A or B
+     *        register of the DAC chip. At a gain setting of 2, this value
+     *        corresponds to a voltage demand in millivolts. Only the first
+     *        12 bits are used, so the value will wrap around after 4095.
+     *        (Note: Strictly this should be an unsigned int, but the SPI
+     *        interface library expects an int.)
+     *-
+     */
+    void writeA1( int dac, int value );
+    void writeA2( int dac, int value );
+    void writeB1( int dac, int value );
+    void writeB2( int dac, int value );
+
+    /*+
+     * write: Write an array of 12-bit register values to multiple DAC channels.
+     *
+     * Choose this function when flexibility and convenience are most important.
+     *
+     * Parameters:
+     *    nchans, int
+     *        The number of channels to be written. There are two channels
+     *        per DAC, so this value must lie between 2 and ndacs x 2.
+     *    values, int[]
+     *        An array of values to be written to the 12 data bits of the DAC
+     *        registers, in the order dac/chan = 0/A, 0/B, 1/A, 1/B, etc...
+     *        The array must contain at least nchans elements (but only the
+     *        first nchans elements will be used for longer arrays).
+     *        At a gain setting of 2, these values corresponds to a voltage
+     *        demand in millivolts. They will wrap back to 0 above 4095.
+     *        (Note: Strictly this should be an unsigned int array, but the SPI
+     *        interface library expects an int.)
+     *    gain, int (optional)
+     *        The required gain setting (1 or 2). If not specified, a default
+     *        of 2 will be assumed.
+     *    latch, int (optional)
+     *        A flag set to 1 if the "not LDAC" signal should be latched after
+     *        setting up the array of voltages. If not specified, a default
+     *        of 1 will be assumed.
+     *-
+     */
+    void write( int nchans, int values[], int gain=2, int latch=1 );
+
+    /*+
+     * voltage2value - convert a voltage into a 12-bit data value.
+     *
+     * Parameters:
+     *    voltage, float
+     *        The voltage to be converted (in volts). The sign is ignored.
+     *    gain, int (optional)
+     *        The gain setting required (1 or 2). If not specified, a default
+     *        of 2 will be assumed.
+     *
+     * Returns:
+     *    value, int.
+     *        The 12-bit data value corresponding to the given
+     *        voltage. 4095 will be returned for out of range
+     *        voltages.
+     *-
+     */
+    int voltage2value( float voltage, int gain=2 );
+
+    /*+
+     * value2voltage - convert a 12-bit data value into a voltage.
+     *
+     * Parameters:
+     *    value, int
+     *        The 12-bit data value to be converted to a voltage.
+     *    gain, int (optional)
+     *        The gain setting required (1 or 2). If not specified, a default
+     *        of 2 will be assumed.
+     *
+     * Returns:
+     *    voltage, float.
+     *        The voltage (in volts) corresponding the the given 12-bit
+     *        data value at the given gain setting.
+     *-
+     */
+    float value2voltage( int value, int gain=2 );
+
+    /*+
+     * latch_enable: enable the latch signal - the DAC(s) will apply
+     *     voltage demands.
+     *
+     * latch_disable: disable the latch signal - the DAC(s) will not
+     *     apply voltage demands.
+     *
+     * These functions only apply for objects constructed with the
+     * optional nldac parameter assigned to a pin.
+     *-
+     */
+    void latch_enable();
+    void latch_disable();
+
+    /*+
+     * shdn: Shut down a DAC. It will sleep until woken by a new command
+     * over the SPI bus.
+     *-
+     */
+    void shdn(int dac);
+    void shdn_all();
+
+private:
+    // Make copy constructor private to prevent the object being copied.
+    // The pins are available to one and only one object.
+    MCP4822A( const MCP4822A& rhs );
+
+    /* Initialise the DAC interface. */
+    void _init();
+
+    int _ndacs;              // The number of DACS in the array
+    int _latched;            // Is the "not LDAC" pin used (1=yes; 0=no)?
+    SPI _spi;                // SPI bus object for communicating with DAC.
+    DigitalOut** _ncs_array; // Array of pointers to DigitalOut objects
+    // connected to "not CS" pins.
+    DigitalOut* _nldac;      // Pointer to DigitalOut object connected
+    // to "not LDAC" pin (if any - NULL if none).
+};
+
+#endif