A feature complete driver for the MCP4922 DAC from Microchip.
Dependents: MCP4922_HelloWorld NuMidi401 NuFM401 NuFM402
MCP4922.cpp@1:747ec9c5d80e, 2014-05-15 (annotated)
- Committer:
- neilt6
- Date:
- Thu May 15 23:51:38 2014 +0000
- Revision:
- 1:747ec9c5d80e
- Parent:
- 0:e994c6963c66
Constructor now initializes the internal variables, and performs an initial write to make sure they're in sync
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
neilt6 | 0:e994c6963c66 | 1 | /* MCP4922 Driver Library |
neilt6 | 0:e994c6963c66 | 2 | * Copyright (c) 2014 Neil Thiessen |
neilt6 | 0:e994c6963c66 | 3 | * |
neilt6 | 0:e994c6963c66 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
neilt6 | 0:e994c6963c66 | 5 | * you may not use this file except in compliance with the License. |
neilt6 | 0:e994c6963c66 | 6 | * You may obtain a copy of the License at |
neilt6 | 0:e994c6963c66 | 7 | * |
neilt6 | 0:e994c6963c66 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
neilt6 | 0:e994c6963c66 | 9 | * |
neilt6 | 0:e994c6963c66 | 10 | * Unless required by applicable law or agreed to in writing, software |
neilt6 | 0:e994c6963c66 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
neilt6 | 0:e994c6963c66 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
neilt6 | 0:e994c6963c66 | 13 | * See the License for the specific language governing permissions and |
neilt6 | 0:e994c6963c66 | 14 | * limitations under the License. |
neilt6 | 0:e994c6963c66 | 15 | */ |
neilt6 | 0:e994c6963c66 | 16 | |
neilt6 | 0:e994c6963c66 | 17 | #include "MCP4922.h" |
neilt6 | 0:e994c6963c66 | 18 | |
neilt6 | 0:e994c6963c66 | 19 | MCP4922::MCP4922(PinName mosi, PinName sclk, PinName cs, int hz) : m_SPI(mosi, NC, sclk), m_CS(cs, 1) |
neilt6 | 0:e994c6963c66 | 20 | { |
neilt6 | 1:747ec9c5d80e | 21 | //Initialize the member variables |
neilt6 | 1:747ec9c5d80e | 22 | m_DacValueA = 0; |
neilt6 | 1:747ec9c5d80e | 23 | m_DacValueB = 0; |
neilt6 | 1:747ec9c5d80e | 24 | |
neilt6 | 0:e994c6963c66 | 25 | //Set the SPI format and bus frequency |
neilt6 | 0:e994c6963c66 | 26 | m_SPI.format(16, 0); |
neilt6 | 0:e994c6963c66 | 27 | m_SPI.frequency(hz); |
neilt6 | 1:747ec9c5d80e | 28 | |
neilt6 | 1:747ec9c5d80e | 29 | //Perform an initial write to both DACs so the variables are in sync |
neilt6 | 1:747ec9c5d80e | 30 | writeDac(m_DacValueA | (DAC_A << 15)); |
neilt6 | 1:747ec9c5d80e | 31 | writeDac(m_DacValueB | (DAC_B << 15)); |
neilt6 | 0:e994c6963c66 | 32 | } |
neilt6 | 0:e994c6963c66 | 33 | |
neilt6 | 0:e994c6963c66 | 34 | MCP4922::ReferenceMode MCP4922::referenceMode(DAC dac) |
neilt6 | 0:e994c6963c66 | 35 | { |
neilt6 | 0:e994c6963c66 | 36 | //Return the current reference mode for the specified DAC |
neilt6 | 0:e994c6963c66 | 37 | if (dac == DAC_A) |
neilt6 | 0:e994c6963c66 | 38 | return (ReferenceMode)((m_DacValueA >> 14) & 0x01); |
neilt6 | 0:e994c6963c66 | 39 | else |
neilt6 | 0:e994c6963c66 | 40 | return (ReferenceMode)((m_DacValueB >> 14) & 0x01); |
neilt6 | 0:e994c6963c66 | 41 | } |
neilt6 | 0:e994c6963c66 | 42 | |
neilt6 | 0:e994c6963c66 | 43 | void MCP4922::referenceMode(DAC dac, ReferenceMode mode) |
neilt6 | 0:e994c6963c66 | 44 | { |
neilt6 | 0:e994c6963c66 | 45 | //Update the reference mode for the specified DAC |
neilt6 | 0:e994c6963c66 | 46 | if (dac == DAC_A) { |
neilt6 | 0:e994c6963c66 | 47 | //Mask off the old mode, and set the new one |
neilt6 | 0:e994c6963c66 | 48 | m_DacValueA &= ~(1 << 14); |
neilt6 | 0:e994c6963c66 | 49 | m_DacValueA |= (mode << 14); |
neilt6 | 0:e994c6963c66 | 50 | |
neilt6 | 0:e994c6963c66 | 51 | //Update the DAC A |
neilt6 | 0:e994c6963c66 | 52 | writeDac(m_DacValueA | (dac << 15)); |
neilt6 | 0:e994c6963c66 | 53 | } else { |
neilt6 | 0:e994c6963c66 | 54 | //Mask off the old mode, and set the new one |
neilt6 | 0:e994c6963c66 | 55 | m_DacValueB &= ~(1 << 14); |
neilt6 | 0:e994c6963c66 | 56 | m_DacValueB |= (mode << 14); |
neilt6 | 0:e994c6963c66 | 57 | |
neilt6 | 0:e994c6963c66 | 58 | //Update the DAC B |
neilt6 | 0:e994c6963c66 | 59 | writeDac(m_DacValueB | (dac << 15)); |
neilt6 | 0:e994c6963c66 | 60 | } |
neilt6 | 0:e994c6963c66 | 61 | } |
neilt6 | 0:e994c6963c66 | 62 | |
neilt6 | 0:e994c6963c66 | 63 | MCP4922::GainMode MCP4922::gainMode(DAC dac) |
neilt6 | 0:e994c6963c66 | 64 | { |
neilt6 | 0:e994c6963c66 | 65 | //Return the current gain mode for the specified DAC |
neilt6 | 0:e994c6963c66 | 66 | if (dac == DAC_A) |
neilt6 | 0:e994c6963c66 | 67 | return (GainMode)((m_DacValueA >> 13) & 0x01); |
neilt6 | 0:e994c6963c66 | 68 | else |
neilt6 | 0:e994c6963c66 | 69 | return (GainMode)((m_DacValueB >> 13) & 0x01); |
neilt6 | 0:e994c6963c66 | 70 | } |
neilt6 | 0:e994c6963c66 | 71 | |
neilt6 | 0:e994c6963c66 | 72 | void MCP4922::gainMode(DAC dac, GainMode mode) |
neilt6 | 0:e994c6963c66 | 73 | { |
neilt6 | 0:e994c6963c66 | 74 | //Update the gain mode for the specified DAC |
neilt6 | 0:e994c6963c66 | 75 | if (dac == DAC_A) { |
neilt6 | 0:e994c6963c66 | 76 | //Mask off the old mode, and set the new one |
neilt6 | 0:e994c6963c66 | 77 | m_DacValueA &= ~(1 << 13); |
neilt6 | 0:e994c6963c66 | 78 | m_DacValueA |= (mode << 13); |
neilt6 | 0:e994c6963c66 | 79 | |
neilt6 | 0:e994c6963c66 | 80 | //Update the DAC A |
neilt6 | 0:e994c6963c66 | 81 | writeDac(m_DacValueA | (dac << 15)); |
neilt6 | 0:e994c6963c66 | 82 | } else { |
neilt6 | 0:e994c6963c66 | 83 | //Mask off the old mode, and set the new one |
neilt6 | 0:e994c6963c66 | 84 | m_DacValueB &= ~(1 << 13); |
neilt6 | 0:e994c6963c66 | 85 | m_DacValueB |= (mode << 13); |
neilt6 | 0:e994c6963c66 | 86 | |
neilt6 | 0:e994c6963c66 | 87 | //Update the DAC B |
neilt6 | 0:e994c6963c66 | 88 | writeDac(m_DacValueB | (dac << 15)); |
neilt6 | 0:e994c6963c66 | 89 | } |
neilt6 | 0:e994c6963c66 | 90 | } |
neilt6 | 0:e994c6963c66 | 91 | |
neilt6 | 0:e994c6963c66 | 92 | MCP4922::PowerMode MCP4922::powerMode(DAC dac) |
neilt6 | 0:e994c6963c66 | 93 | { |
neilt6 | 0:e994c6963c66 | 94 | //Return the current power mode for the specified DAC |
neilt6 | 0:e994c6963c66 | 95 | if (dac == DAC_A) |
neilt6 | 0:e994c6963c66 | 96 | return (PowerMode)((m_DacValueA >> 12) & 0x01); |
neilt6 | 0:e994c6963c66 | 97 | else |
neilt6 | 0:e994c6963c66 | 98 | return (PowerMode)((m_DacValueB >> 12) & 0x01); |
neilt6 | 0:e994c6963c66 | 99 | } |
neilt6 | 0:e994c6963c66 | 100 | |
neilt6 | 0:e994c6963c66 | 101 | void MCP4922::powerMode(DAC dac, PowerMode mode) |
neilt6 | 0:e994c6963c66 | 102 | { |
neilt6 | 0:e994c6963c66 | 103 | //Update the power mode for the specified DAC |
neilt6 | 0:e994c6963c66 | 104 | if (dac == DAC_A) { |
neilt6 | 0:e994c6963c66 | 105 | //Mask off the old mode, and set the new one |
neilt6 | 0:e994c6963c66 | 106 | m_DacValueA &= ~(1 << 12); |
neilt6 | 0:e994c6963c66 | 107 | m_DacValueA |= (mode << 12); |
neilt6 | 0:e994c6963c66 | 108 | |
neilt6 | 0:e994c6963c66 | 109 | //Update the DAC A |
neilt6 | 0:e994c6963c66 | 110 | writeDac(m_DacValueA | (dac << 15)); |
neilt6 | 0:e994c6963c66 | 111 | } else { |
neilt6 | 0:e994c6963c66 | 112 | //Mask off the old mode, and set the new one |
neilt6 | 0:e994c6963c66 | 113 | m_DacValueB &= ~(1 << 12); |
neilt6 | 0:e994c6963c66 | 114 | m_DacValueB |= (mode << 12); |
neilt6 | 0:e994c6963c66 | 115 | |
neilt6 | 0:e994c6963c66 | 116 | //Update the DAC B |
neilt6 | 0:e994c6963c66 | 117 | writeDac(m_DacValueB | (dac << 15)); |
neilt6 | 0:e994c6963c66 | 118 | } |
neilt6 | 0:e994c6963c66 | 119 | } |
neilt6 | 0:e994c6963c66 | 120 | |
neilt6 | 0:e994c6963c66 | 121 | float MCP4922::read(DAC dac) |
neilt6 | 0:e994c6963c66 | 122 | { |
neilt6 | 0:e994c6963c66 | 123 | //Return the current value for the specified DAC as a float |
neilt6 | 0:e994c6963c66 | 124 | if (dac == DAC_A) |
neilt6 | 0:e994c6963c66 | 125 | return (m_DacValueA & 0x0FFF) / 4095.0; |
neilt6 | 0:e994c6963c66 | 126 | else |
neilt6 | 0:e994c6963c66 | 127 | return (m_DacValueB & 0x0FFF) / 4095.0; |
neilt6 | 0:e994c6963c66 | 128 | } |
neilt6 | 0:e994c6963c66 | 129 | |
neilt6 | 0:e994c6963c66 | 130 | void MCP4922::write(DAC dac, float value) |
neilt6 | 0:e994c6963c66 | 131 | { |
neilt6 | 0:e994c6963c66 | 132 | //Range limit value |
neilt6 | 0:e994c6963c66 | 133 | if (value < 0.0) |
neilt6 | 0:e994c6963c66 | 134 | value = 0.0; |
neilt6 | 0:e994c6963c66 | 135 | else if (value > 1.0) |
neilt6 | 0:e994c6963c66 | 136 | value = 1.0; |
neilt6 | 0:e994c6963c66 | 137 | |
neilt6 | 0:e994c6963c66 | 138 | //Convert value to an unsigned short, and pass it to write_u16() |
neilt6 | 0:e994c6963c66 | 139 | write_u16(dac, (unsigned short)(value * 4095) << 4); |
neilt6 | 0:e994c6963c66 | 140 | } |
neilt6 | 0:e994c6963c66 | 141 | |
neilt6 | 0:e994c6963c66 | 142 | void MCP4922::write_u16(DAC dac, unsigned short value) |
neilt6 | 0:e994c6963c66 | 143 | { |
neilt6 | 0:e994c6963c66 | 144 | //Update the value for the specified DAC |
neilt6 | 0:e994c6963c66 | 145 | if (dac == DAC_A) { |
neilt6 | 0:e994c6963c66 | 146 | //Mask off the old value, and set the new one |
neilt6 | 0:e994c6963c66 | 147 | m_DacValueA &= 0xF000; |
neilt6 | 0:e994c6963c66 | 148 | m_DacValueA |= value >> 4; |
neilt6 | 0:e994c6963c66 | 149 | |
neilt6 | 0:e994c6963c66 | 150 | //Update the DAC A |
neilt6 | 0:e994c6963c66 | 151 | writeDac(m_DacValueA | (dac << 15)); |
neilt6 | 0:e994c6963c66 | 152 | } else { |
neilt6 | 0:e994c6963c66 | 153 | //Mask off the old value, and set the new one |
neilt6 | 0:e994c6963c66 | 154 | m_DacValueB &= 0xF000; |
neilt6 | 0:e994c6963c66 | 155 | m_DacValueB |= value >> 4; |
neilt6 | 0:e994c6963c66 | 156 | |
neilt6 | 0:e994c6963c66 | 157 | //Update the DAC B |
neilt6 | 0:e994c6963c66 | 158 | writeDac(m_DacValueB | (dac << 15)); |
neilt6 | 0:e994c6963c66 | 159 | } |
neilt6 | 0:e994c6963c66 | 160 | } |
neilt6 | 0:e994c6963c66 | 161 | |
neilt6 | 0:e994c6963c66 | 162 | void MCP4922::writeDac(unsigned short value) |
neilt6 | 0:e994c6963c66 | 163 | { |
neilt6 | 0:e994c6963c66 | 164 | //Pull CS low |
neilt6 | 0:e994c6963c66 | 165 | m_CS = 0; |
neilt6 | 0:e994c6963c66 | 166 | |
neilt6 | 0:e994c6963c66 | 167 | //Perform the 16-bit write |
neilt6 | 0:e994c6963c66 | 168 | m_SPI.write(value); |
neilt6 | 0:e994c6963c66 | 169 | |
neilt6 | 0:e994c6963c66 | 170 | //Pull CS high |
neilt6 | 0:e994c6963c66 | 171 | m_CS = 1; |
neilt6 | 0:e994c6963c66 | 172 | } |