Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: MCP41xxxApp MCP320xApp MCP41xxxApp
MCP4xxxx_SPI.cpp
00001 /* mbed simplified access to Microchip 24LCxx Serial EEPROM devices (SPI) 00002 * Copyright (c) 2013 ygarcia, MIT License 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00005 * and associated documentation files (the "Software"), to deal in the Software without restriction, 00006 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 00007 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 00008 * furnished to do so, subject to the following conditions: 00009 * 00010 * The above copyright notice and this permission notice shall be included in all copies or 00011 * substantial portions of the Software. 00012 * 00013 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00014 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00015 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00016 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00017 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00018 */ 00019 00020 #include "MCP4xxxx_SPI.h" 00021 00022 namespace MCP4xxxx_SPI { 00023 00024 unsigned char CMCP4xxxx_SPI::SPIModuleRefCounter = 0; 00025 00026 CMCP4xxxx_SPI::CMCP4xxxx_SPI(const PinName p_mosi, const PinName p_miso, const PinName p_sclk, const PinName p_cs, const PinName p_reset, const PinName p_shdn, const Mcp4xxxFamily p_family, const unsigned int p_frequency) : _internalId("") { 00027 DEBUG_ENTER("CMCP4xxxx_SPI") 00028 00029 if (CMCP4xxxx_SPI::SPIModuleRefCounter != 0) { 00030 error("CMCP4xxxx_SPI: Wrong params"); 00031 } 00032 00033 _spiInstance = new SPI(p_mosi, p_miso, p_sclk); 00034 _spiInstance->frequency(p_frequency); // Set the frequency of the SPI interface 00035 _spiInstance->format(16, 0); // See http://mbed.org/users/mbed_official/code/mbed/docs/0954ebd79f59//classmbed_1_1SPI.html 00036 CMCP4xxxx_SPI::SPIModuleRefCounter += 1; 00037 DEBUG_ENTER("CMCP4xxxx_SPI: refCounter=%d", CMCP4xxxx_SPI::SPIModuleRefCounter) 00038 00039 if (p_cs != NC) { 00040 DEBUG("CMCP4xxxx_SPI: /CS managed"); 00041 _cs = new DigitalOut(p_cs); 00042 _cs->write(1); // Disable chip 00043 } else { 00044 DEBUG("CMCP4xxxx_SPI: /CS not managed"); 00045 _cs = NULL; // Not used 00046 } 00047 00048 if (p_reset != NC) { 00049 DEBUG("CMCP4xxxx_SPI: /RESET managed"); 00050 _reset = new DigitalOut(p_reset); 00051 _reset->write(1); // Disable reset 00052 } else { 00053 DEBUG("CMCP4xxxx_SPI: /RESET not managed"); 00054 _reset = NULL; // Not used 00055 } 00056 00057 if (p_shdn != NC) { 00058 DEBUG("CMCP4xxxx_SPI: /SHDN managed"); 00059 _shdn = new DigitalOut(p_shdn); 00060 _shdn->write(1); // Disable shutdown 00061 } else { 00062 DEBUG("CMCP4xxxx_SPI: /SHDN not managed"); 00063 _shdn = NULL; // Not used 00064 } 00065 00066 _family = p_family; 00067 SetFamilly(p_family); 00068 00069 _incStep = 0x80; // Set to middle step 00070 00071 DEBUG_LEAVE("CMCP4xxxx_SPI") 00072 } 00073 00074 CMCP4xxxx_SPI::~CMCP4xxxx_SPI() { 00075 DEBUG_ENTER("~CMCP4xxxx_SPI") 00076 00077 // Release I2C instance 00078 DEBUG_ENTER("~CMCP4xxxx_SPI: refCounter=%d", CMCP4xxxx_SPI::SPIModuleRefCounter) 00079 CMCP4xxxx_SPI::SPIModuleRefCounter -= 1; 00080 if (CMCP4xxxx_SPI::SPIModuleRefCounter == 0) { 00081 delete _spiInstance; 00082 _spiInstance = NULL; 00083 } 00084 // Release _reset if required 00085 if (_cs != NULL) { 00086 _cs->write(0); 00087 delete _cs; 00088 } 00089 // Release _reset if required 00090 if (_reset != NULL) { 00091 _reset->write(0); 00092 delete _reset; 00093 } 00094 // Release _shdn if required 00095 if (_shdn != NULL) { 00096 _shdn->write(0); 00097 delete _shdn; 00098 } 00099 00100 DEBUG_LEAVE("~CMCP4xxxx_SPI") 00101 } 00102 00103 unsigned short CMCP4xxxx_SPI::WriteRegister(const Addresses p_address, const unsigned char p_value) { 00104 DEBUG_ENTER("CMCP4xxxx_SPI::WriteRegister: 0x%02x - 0x%02x - 0x%02x", (unsigned char)p_address, p_value, (unsigned char)_family) 00105 00106 // Sanity check 00107 if (p_address == CMCP4xxxx_SPI::Status) { 00108 // Wrong parameters 00109 return (unsigned short) -1; 00110 } 00111 00112 unsigned short command = ((p_address & 0x0f) << 4 | 0x00/*TODO Use 'define' for Write command*/) << 8; 00113 command |= p_value; 00114 00115 DEBUG("CMCP4xxxx_SPI::WriteRegister: Send command: 0x%04x", command) 00116 if (_cs != NULL) { 00117 _cs->write(0); 00118 } 00119 unsigned short result = _spiInstance->write(command); 00120 if (_cs != NULL) { 00121 _cs->write(1); 00122 } 00123 00124 DEBUG_LEAVE("CMCP4xxxx_SPI::WriteRegister: %d", result & 0x00ff) 00125 return result & 0x00ff; 00126 } 00127 00128 unsigned short CMCP4xxxx_SPI::ReadRegister(const Addresses p_address) { 00129 DEBUG_ENTER("CMCP4xxxx_SPI::ReadRegister: 0x%02x", (unsigned char)p_address) 00130 00131 unsigned short command = ((p_address & 0x0f) << 4 | (0x03/*TODO Use 'define' for Read command*/ << 2)) << 8; 00132 00133 DEBUG("CMCP4xxxx_SPI::ReadRegister: Send command: 0x%04x", command) 00134 if (_cs != NULL) { 00135 _cs->write(0); 00136 } 00137 unsigned short result = _spiInstance->write(command); 00138 DEBUG("CMCP4xxxx_SPI::ReadRegister: full result=0x%04x", result) 00139 if (_cs != NULL) { 00140 _cs->write(1); 00141 } 00142 00143 DEBUG_LEAVE("CMCP4xxxx_SPI::ReadRegister: 0x%02x", result & 0x00ff) 00144 return result & 0x00ff; 00145 } 00146 00147 unsigned short CMCP4xxxx_SPI::Increment(const Commands p_command) { 00148 // Sanity check 00149 if (_incStep != 0xff) { 00150 _incStep += 1; // TODO Change increment 1 by a parametrized increment step 00151 } 00152 return Write(p_command, _incStep); 00153 } 00154 00155 unsigned short CMCP4xxxx_SPI::Decrement(const Commands p_command) { 00156 // Sanity check 00157 if (_incStep != 0x00) { 00158 _incStep -= 1; // TODO Change increment 1 by a parametrized increment step 00159 } 00160 return Write(p_command, _incStep); 00161 } 00162 00163 00164 unsigned short CMCP4xxxx_SPI::Write(const Commands p_command, const unsigned char p_value) { 00165 DEBUG_ENTER("CMCP4xxxx_SPI::Write: 0x%02x - 0x%02x - 0x%02x", (unsigned char)p_command, p_value, (unsigned char)_family) 00166 00167 // Sanity check 00168 if ((p_command != WriteToDigiPot1) && (p_command != WriteToDigiPot2) && (p_command != WriteToBoth)) { 00169 // Wrong parameters 00170 return (unsigned short) -1; 00171 } 00172 00173 unsigned short command = 0; 00174 if ((_family == CMCP4xxxx_SPI::_41xxx) || (_family == CMCP4xxxx_SPI::_42xxx)) { // See DS11195C 00175 switch (p_command) { 00176 case WriteToDigiPot1: 00177 command = (0x11 << 8 | p_value); 00178 break; 00179 case WriteToDigiPot2: 00180 command = (0x12 << 8 | p_value); 00181 break; 00182 default: 00183 command = (0x13 << 8 | p_value); 00184 } // End of 'switch' statement 00185 } else { // See DS22060B 00186 switch (p_command) { 00187 case WriteToDigiPot2: // Wiper1: adress=0x01, WriteCmd=00 00188 command = (0x01 << 5 | p_value); 00189 break; 00190 default: 00191 command = p_value; // Wiper1: adress=0x00, WriteCmd=00 00192 } // End of 'switch' statement 00193 } 00194 00195 DEBUG("CMCP4xxxx_SPI::Write: Send command: 0x%04x", (unsigned char)command) 00196 if (_cs != NULL) { 00197 _cs->write(0); 00198 } 00199 unsigned short result = _spiInstance->write(command); 00200 if (_cs != NULL) { 00201 _cs->write(1); 00202 } 00203 00204 DEBUG_LEAVE("CMCP4xxxx_SPI::Write: %d", result) 00205 return result; 00206 } 00207 00208 unsigned short CMCP4xxxx_SPI::Shutdown(const Commands p_command, const bool p_set) { 00209 DEBUG_ENTER("CMCP4xxxx_SPI::Shutdown: 0x%02x - 0x%02x", (unsigned char)p_command, (unsigned char)_family) 00210 00211 // Sanity check 00212 if ((p_command != ShutdownDigiPot1) && (p_command != ShutdownDigiPot2) && (p_command != ShutdownBoth)) { 00213 // Wrong parameters 00214 return (unsigned short) -1; 00215 } 00216 00217 unsigned short command = 0; 00218 if ((_family == CMCP4xxxx_SPI::_41xxx) || (_family == CMCP4xxxx_SPI::_42xxx)) { // See DS11195C 00219 switch (p_command) { 00220 case ShutdownDigiPot1: 00221 command = (0x21 << 8); 00222 break; 00223 case ShutdownDigiPot2: 00224 command = (0x21 << 8); 00225 break; 00226 default: //<! Shutdown both digital potentiometers 00227 command = (0x23 << 8); 00228 } // End of 'switch' statement 00229 } else { // See DS22060B 00230 unsigned short tcon = ReadRegister(TCon); // Read TCon register 00231 if (p_set == true) { 00232 switch (p_command) { 00233 case ShutdownDigiPot1: 00234 command = 0x4000 | (tcon & 0xf8); 00235 break; 00236 case ShutdownDigiPot2: 00237 command = 0x4000 | (tcon & 0x8f); 00238 break; 00239 default: //<! Shutdown both digital potentiometers 00240 command = 0x4000; 00241 } // End of 'switch' statement 00242 } else { 00243 switch (p_command) { 00244 case ShutdownDigiPot1: 00245 command = 0x4000 | (tcon | 0x000f); 00246 break; 00247 case ShutdownDigiPot2: 00248 command = 0x4000 | (tcon | 0x00f0); 00249 break; 00250 default: //<! Shutdown both digital potentiometers 00251 command = 0x40ff; 00252 } // End of 'switch' statement 00253 } 00254 } 00255 00256 DEBUG("CMCP4xxxx_SPI::Shutdown: Send command: 0x%04x", command) 00257 if (_cs != NULL) { 00258 _cs->write(0); 00259 } 00260 unsigned short result = _spiInstance->write(command); 00261 if (_cs != NULL) { 00262 _cs->write(1); 00263 } 00264 00265 DEBUG_LEAVE("CMCP4xxxx_SPI::Shutdown: %d", result) 00266 return result; 00267 } 00268 00269 //unsigned short CMCP4xxxx_SPI::Write() { 00270 // return _spiInstance->write(0); 00271 //} 00272 00273 CMCP4xxxx_SPI::Mcp4xxxFamily CMCP4xxxx_SPI::SetFamilly(const CMCP4xxxx_SPI::Mcp4xxxFamily p_family) { 00274 DEBUG_ENTER("CMCP4xxxx_SPI::SetFamilly: 0x%02x", (unsigned char)p_family) 00275 00276 Mcp4xxxFamily old = _family; 00277 _family = p_family; 00278 if ((_family != CMCP4xxxx_SPI::_41xxx) && (_family != CMCP4xxxx_SPI::_42xxx)) { 00279 // Setup TCON register 00280 DEBUG("CMCP4xxxx_SPI::SetFamilly: Setup TCON register") 00281 WriteRegister(CMCP4xxxx_SPI::TCon, 0xff); // See DS22060B-page 36 REGISTER 4-2: TCON BITS 00282 // TODO Use 'define' for command 00283 } 00284 00285 DEBUG_LEAVE("CMCP4xxxx_SPI::SetFamilly: 0x%02x", (unsigned char)old) 00286 return old; 00287 } 00288 00289 void CMCP4xxxx_SPI::Reset() { 00290 _incStep = 0x80; // Set to middle step 00291 // Sanity check 00292 if (_reset != NULL) { 00293 _reset->write(0); // Set level low to activate reset 00294 wait_us(1); // Wait for 1us 00295 _reset->write(1); // Set level low to de-activate reset 00296 } 00297 } 00298 00299 void CMCP4xxxx_SPI::Shutdown(const bool p_set) { 00300 if (_shdn != NULL) { 00301 _shdn->write(p_set == false ? 0 : 1); 00302 } 00303 } 00304 00305 } // End of namespace MCP4xxxx_SPI
Generated on Tue Jul 12 2022 18:38:23 by
1.7.2