Yann Garcia / MCP4xxxx_SPI

Dependents:   MCP41xxxApp MCP320xApp MCP41xxxApp

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MCP4xxxx_SPI.cpp Source File

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