A feature complete driver for the MCP4922 DAC from Microchip.
Dependents: MCP4922_HelloWorld NuMidi401 NuFM401 NuFM402
MCP4922.cpp@0:e994c6963c66, 2014-05-15 (annotated)
- Committer:
- neilt6
- Date:
- Thu May 15 17:33:40 2014 +0000
- Revision:
- 0:e994c6963c66
- Child:
- 1:747ec9c5d80e
Initial commit
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 | 0:e994c6963c66 | 21 | //Set the SPI format and bus frequency |
neilt6 | 0:e994c6963c66 | 22 | m_SPI.format(16, 0); |
neilt6 | 0:e994c6963c66 | 23 | m_SPI.frequency(hz); |
neilt6 | 0:e994c6963c66 | 24 | } |
neilt6 | 0:e994c6963c66 | 25 | |
neilt6 | 0:e994c6963c66 | 26 | MCP4922::ReferenceMode MCP4922::referenceMode(DAC dac) |
neilt6 | 0:e994c6963c66 | 27 | { |
neilt6 | 0:e994c6963c66 | 28 | //Return the current reference mode for the specified DAC |
neilt6 | 0:e994c6963c66 | 29 | if (dac == DAC_A) |
neilt6 | 0:e994c6963c66 | 30 | return (ReferenceMode)((m_DacValueA >> 14) & 0x01); |
neilt6 | 0:e994c6963c66 | 31 | else |
neilt6 | 0:e994c6963c66 | 32 | return (ReferenceMode)((m_DacValueB >> 14) & 0x01); |
neilt6 | 0:e994c6963c66 | 33 | } |
neilt6 | 0:e994c6963c66 | 34 | |
neilt6 | 0:e994c6963c66 | 35 | void MCP4922::referenceMode(DAC dac, ReferenceMode mode) |
neilt6 | 0:e994c6963c66 | 36 | { |
neilt6 | 0:e994c6963c66 | 37 | //Update the reference mode for the specified DAC |
neilt6 | 0:e994c6963c66 | 38 | if (dac == DAC_A) { |
neilt6 | 0:e994c6963c66 | 39 | //Mask off the old mode, and set the new one |
neilt6 | 0:e994c6963c66 | 40 | m_DacValueA &= ~(1 << 14); |
neilt6 | 0:e994c6963c66 | 41 | m_DacValueA |= (mode << 14); |
neilt6 | 0:e994c6963c66 | 42 | |
neilt6 | 0:e994c6963c66 | 43 | //Update the DAC A |
neilt6 | 0:e994c6963c66 | 44 | writeDac(m_DacValueA | (dac << 15)); |
neilt6 | 0:e994c6963c66 | 45 | } else { |
neilt6 | 0:e994c6963c66 | 46 | //Mask off the old mode, and set the new one |
neilt6 | 0:e994c6963c66 | 47 | m_DacValueB &= ~(1 << 14); |
neilt6 | 0:e994c6963c66 | 48 | m_DacValueB |= (mode << 14); |
neilt6 | 0:e994c6963c66 | 49 | |
neilt6 | 0:e994c6963c66 | 50 | //Update the DAC B |
neilt6 | 0:e994c6963c66 | 51 | writeDac(m_DacValueB | (dac << 15)); |
neilt6 | 0:e994c6963c66 | 52 | } |
neilt6 | 0:e994c6963c66 | 53 | } |
neilt6 | 0:e994c6963c66 | 54 | |
neilt6 | 0:e994c6963c66 | 55 | MCP4922::GainMode MCP4922::gainMode(DAC dac) |
neilt6 | 0:e994c6963c66 | 56 | { |
neilt6 | 0:e994c6963c66 | 57 | //Return the current gain mode for the specified DAC |
neilt6 | 0:e994c6963c66 | 58 | if (dac == DAC_A) |
neilt6 | 0:e994c6963c66 | 59 | return (GainMode)((m_DacValueA >> 13) & 0x01); |
neilt6 | 0:e994c6963c66 | 60 | else |
neilt6 | 0:e994c6963c66 | 61 | return (GainMode)((m_DacValueB >> 13) & 0x01); |
neilt6 | 0:e994c6963c66 | 62 | } |
neilt6 | 0:e994c6963c66 | 63 | |
neilt6 | 0:e994c6963c66 | 64 | void MCP4922::gainMode(DAC dac, GainMode mode) |
neilt6 | 0:e994c6963c66 | 65 | { |
neilt6 | 0:e994c6963c66 | 66 | //Update the gain mode for the specified DAC |
neilt6 | 0:e994c6963c66 | 67 | if (dac == DAC_A) { |
neilt6 | 0:e994c6963c66 | 68 | //Mask off the old mode, and set the new one |
neilt6 | 0:e994c6963c66 | 69 | m_DacValueA &= ~(1 << 13); |
neilt6 | 0:e994c6963c66 | 70 | m_DacValueA |= (mode << 13); |
neilt6 | 0:e994c6963c66 | 71 | |
neilt6 | 0:e994c6963c66 | 72 | //Update the DAC A |
neilt6 | 0:e994c6963c66 | 73 | writeDac(m_DacValueA | (dac << 15)); |
neilt6 | 0:e994c6963c66 | 74 | } else { |
neilt6 | 0:e994c6963c66 | 75 | //Mask off the old mode, and set the new one |
neilt6 | 0:e994c6963c66 | 76 | m_DacValueB &= ~(1 << 13); |
neilt6 | 0:e994c6963c66 | 77 | m_DacValueB |= (mode << 13); |
neilt6 | 0:e994c6963c66 | 78 | |
neilt6 | 0:e994c6963c66 | 79 | //Update the DAC B |
neilt6 | 0:e994c6963c66 | 80 | writeDac(m_DacValueB | (dac << 15)); |
neilt6 | 0:e994c6963c66 | 81 | } |
neilt6 | 0:e994c6963c66 | 82 | } |
neilt6 | 0:e994c6963c66 | 83 | |
neilt6 | 0:e994c6963c66 | 84 | MCP4922::PowerMode MCP4922::powerMode(DAC dac) |
neilt6 | 0:e994c6963c66 | 85 | { |
neilt6 | 0:e994c6963c66 | 86 | //Return the current power mode for the specified DAC |
neilt6 | 0:e994c6963c66 | 87 | if (dac == DAC_A) |
neilt6 | 0:e994c6963c66 | 88 | return (PowerMode)((m_DacValueA >> 12) & 0x01); |
neilt6 | 0:e994c6963c66 | 89 | else |
neilt6 | 0:e994c6963c66 | 90 | return (PowerMode)((m_DacValueB >> 12) & 0x01); |
neilt6 | 0:e994c6963c66 | 91 | } |
neilt6 | 0:e994c6963c66 | 92 | |
neilt6 | 0:e994c6963c66 | 93 | void MCP4922::powerMode(DAC dac, PowerMode mode) |
neilt6 | 0:e994c6963c66 | 94 | { |
neilt6 | 0:e994c6963c66 | 95 | //Update the power mode for the specified DAC |
neilt6 | 0:e994c6963c66 | 96 | if (dac == DAC_A) { |
neilt6 | 0:e994c6963c66 | 97 | //Mask off the old mode, and set the new one |
neilt6 | 0:e994c6963c66 | 98 | m_DacValueA &= ~(1 << 12); |
neilt6 | 0:e994c6963c66 | 99 | m_DacValueA |= (mode << 12); |
neilt6 | 0:e994c6963c66 | 100 | |
neilt6 | 0:e994c6963c66 | 101 | //Update the DAC A |
neilt6 | 0:e994c6963c66 | 102 | writeDac(m_DacValueA | (dac << 15)); |
neilt6 | 0:e994c6963c66 | 103 | } else { |
neilt6 | 0:e994c6963c66 | 104 | //Mask off the old mode, and set the new one |
neilt6 | 0:e994c6963c66 | 105 | m_DacValueB &= ~(1 << 12); |
neilt6 | 0:e994c6963c66 | 106 | m_DacValueB |= (mode << 12); |
neilt6 | 0:e994c6963c66 | 107 | |
neilt6 | 0:e994c6963c66 | 108 | //Update the DAC B |
neilt6 | 0:e994c6963c66 | 109 | writeDac(m_DacValueB | (dac << 15)); |
neilt6 | 0:e994c6963c66 | 110 | } |
neilt6 | 0:e994c6963c66 | 111 | } |
neilt6 | 0:e994c6963c66 | 112 | |
neilt6 | 0:e994c6963c66 | 113 | float MCP4922::read(DAC dac) |
neilt6 | 0:e994c6963c66 | 114 | { |
neilt6 | 0:e994c6963c66 | 115 | //Return the current value for the specified DAC as a float |
neilt6 | 0:e994c6963c66 | 116 | if (dac == DAC_A) |
neilt6 | 0:e994c6963c66 | 117 | return (m_DacValueA & 0x0FFF) / 4095.0; |
neilt6 | 0:e994c6963c66 | 118 | else |
neilt6 | 0:e994c6963c66 | 119 | return (m_DacValueB & 0x0FFF) / 4095.0; |
neilt6 | 0:e994c6963c66 | 120 | } |
neilt6 | 0:e994c6963c66 | 121 | |
neilt6 | 0:e994c6963c66 | 122 | void MCP4922::write(DAC dac, float value) |
neilt6 | 0:e994c6963c66 | 123 | { |
neilt6 | 0:e994c6963c66 | 124 | //Range limit value |
neilt6 | 0:e994c6963c66 | 125 | if (value < 0.0) |
neilt6 | 0:e994c6963c66 | 126 | value = 0.0; |
neilt6 | 0:e994c6963c66 | 127 | else if (value > 1.0) |
neilt6 | 0:e994c6963c66 | 128 | value = 1.0; |
neilt6 | 0:e994c6963c66 | 129 | |
neilt6 | 0:e994c6963c66 | 130 | //Convert value to an unsigned short, and pass it to write_u16() |
neilt6 | 0:e994c6963c66 | 131 | write_u16(dac, (unsigned short)(value * 4095) << 4); |
neilt6 | 0:e994c6963c66 | 132 | } |
neilt6 | 0:e994c6963c66 | 133 | |
neilt6 | 0:e994c6963c66 | 134 | void MCP4922::write_u16(DAC dac, unsigned short value) |
neilt6 | 0:e994c6963c66 | 135 | { |
neilt6 | 0:e994c6963c66 | 136 | //Update the value for the specified DAC |
neilt6 | 0:e994c6963c66 | 137 | if (dac == DAC_A) { |
neilt6 | 0:e994c6963c66 | 138 | //Mask off the old value, and set the new one |
neilt6 | 0:e994c6963c66 | 139 | m_DacValueA &= 0xF000; |
neilt6 | 0:e994c6963c66 | 140 | m_DacValueA |= value >> 4; |
neilt6 | 0:e994c6963c66 | 141 | |
neilt6 | 0:e994c6963c66 | 142 | //Update the DAC A |
neilt6 | 0:e994c6963c66 | 143 | writeDac(m_DacValueA | (dac << 15)); |
neilt6 | 0:e994c6963c66 | 144 | } else { |
neilt6 | 0:e994c6963c66 | 145 | //Mask off the old value, and set the new one |
neilt6 | 0:e994c6963c66 | 146 | m_DacValueB &= 0xF000; |
neilt6 | 0:e994c6963c66 | 147 | m_DacValueB |= value >> 4; |
neilt6 | 0:e994c6963c66 | 148 | |
neilt6 | 0:e994c6963c66 | 149 | //Update the DAC B |
neilt6 | 0:e994c6963c66 | 150 | writeDac(m_DacValueB | (dac << 15)); |
neilt6 | 0:e994c6963c66 | 151 | } |
neilt6 | 0:e994c6963c66 | 152 | } |
neilt6 | 0:e994c6963c66 | 153 | |
neilt6 | 0:e994c6963c66 | 154 | void MCP4922::writeDac(unsigned short value) |
neilt6 | 0:e994c6963c66 | 155 | { |
neilt6 | 0:e994c6963c66 | 156 | //Pull CS low |
neilt6 | 0:e994c6963c66 | 157 | m_CS = 0; |
neilt6 | 0:e994c6963c66 | 158 | |
neilt6 | 0:e994c6963c66 | 159 | //Perform the 16-bit write |
neilt6 | 0:e994c6963c66 | 160 | m_SPI.write(value); |
neilt6 | 0:e994c6963c66 | 161 | |
neilt6 | 0:e994c6963c66 | 162 | //Pull CS high |
neilt6 | 0:e994c6963c66 | 163 | m_CS = 1; |
neilt6 | 0:e994c6963c66 | 164 | } |