Simplified access to a Microchip Digital Potentiometer (MCP41xxx/MCP42xxx) devices
Dependents: MCP41xxxApp MCP320xApp MCP41xxxApp
Diff: MCP4xxxx_SPI.cpp
- Revision:
- 6:ded0d8a6729c
- Parent:
- 5:4f6133144e7e
- Child:
- 7:12a0d89aa72f
--- a/MCP4xxxx_SPI.cpp Fri Apr 05 13:36:29 2013 +0000 +++ b/MCP4xxxx_SPI.cpp Thu Jun 06 07:59:16 2013 +0000 @@ -1,4 +1,4 @@ -/* mbed simplified access to Microchip MCP42xxx/MCP41xxx Digital Potentiometer devices (SPI) +/* mbed simplified access to Microchip 24LCxx Serial EEPROM devices (SPI) * Copyright (c) 2013 ygarcia, MIT License * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software @@ -23,19 +23,18 @@ unsigned char CMCP4xxxx_SPI::SPIModuleRefCounter = 0; - 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 unsigned int p_frequency) : _internalId("") { + 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 Mcp4xxxFamilly p_familly, const unsigned int p_frequency) : _internalId("") { DEBUG_ENTER("CMCP4xxxx_SPI") - CMCP4xxxx_SPI::SPIModuleRefCounter += 1; - if (CMCP4xxxx_SPI::SPIModuleRefCounter > 1) { - //FIXME Check that SPI settings are identical. Otherwise it should failed - return; + if (CMCP4xxxx_SPI::SPIModuleRefCounter != 0) { + error("CMCP4xxxx_SPI: Wrong params"); } _spiInstance = new SPI(p_mosi, p_miso, p_sclk); _spiInstance->frequency(p_frequency); // Set the frequency of the SPI interface _spiInstance->format(16, 0); // See http://mbed.org/users/mbed_official/code/mbed/docs/0954ebd79f59//classmbed_1_1SPI.html - DEBUG("CMCP4xxxx_SPI: refCounter=%d", CMCP4xxxx_SPI::SPIModuleRefCounter) + CMCP4xxxx_SPI::SPIModuleRefCounter += 1; + DEBUG_ENTER("CMCP4xxxx_SPI: refCounter=%d", CMCP4xxxx_SPI::SPIModuleRefCounter) if (p_cs != NC) { DEBUG("CMCP4xxxx_SPI: /CS managed"); @@ -63,7 +62,12 @@ DEBUG("CMCP4xxxx_SPI: /SHDN not managed"); _shdn = NULL; // Not used } - + + _familly = p_familly; + SetFamilly(p_familly); + + _incStep = 0x80; // Set to middle step + DEBUG_LEAVE("CMCP4xxxx_SPI") } @@ -79,7 +83,7 @@ } // Release _reset if required if (_cs != NULL) { - _cs->write(1); + _cs->write(0); delete _cs; } // Release _reset if required @@ -96,28 +100,100 @@ DEBUG_LEAVE("~CMCP4xxxx_SPI") } - unsigned short CMCP4xxxx_SPI::Write(const Commands p_command, const unsigned char p_value) { - DEBUG_ENTER("CMCP4xxxx_SPI::Write: 0x%02x - 0x%02x", (unsigned char)p_command, p_value) + unsigned short CMCP4xxxx_SPI::WriteRegister(const Addresses p_address, const unsigned char p_value) { + DEBUG_ENTER("CMCP4xxxx_SPI::WriteRegister: 0x%02x - 0x%02x - 0x%02x", (unsigned char)p_address, p_value, (unsigned char)_familly) // Sanity check - if ((p_command != WriteToPot1) && (p_command != WriteToPot2) && (p_command != WriteToBoth)) { + if (p_address == CMCP4xxxx_SPI::Status) { + // Wrong parameters + return (unsigned short) -1; + } + + unsigned short command = ((p_address & 0x0f) << 4 | 0x00/*TODO Use 'define' for Write command*/) << 8; + command |= p_value; + + DEBUG("CMCP4xxxx_SPI::WriteRegister: Send command: 0x%04x", command) + if (_cs != NULL) { + _cs->write(0); + } + unsigned short result = _spiInstance->write(command); + DEBUG("CMCP4xxxx_SPI::WriteRegister: returned value=%d", result) + if (_cs != NULL) { + _cs->write(1); + } + + DEBUG_LEAVE("CMCP4xxxx_SPI::WriteRegister: %d", result & 0x00ff) + return result & 0x00ff; + } + + unsigned short CMCP4xxxx_SPI::ReadRegister(const Addresses p_address) { + DEBUG_ENTER("CMCP4xxxx_SPI::ReadRegister: 0x%02x - 0x%02x", (unsigned char)p_address, (unsigned char)_familly) + + unsigned short command = ((p_address & 0x0f) << 4 | (0x03/*TODO Use 'define' for Read command*/ << 2)) << 8; + + DEBUG("CMCP4xxxx_SPI::ReadRegister: Send command: 0x%04x", command) + if (_cs != NULL) { + _cs->write(0); + } + unsigned short result = _spiInstance->write(command); + DEBUG("CMCP4xxxx_SPI::ReadRegister: full result=0x%04x", result) + if (_cs != NULL) { + _cs->write(1); + } + + DEBUG_LEAVE("CMCP4xxxx_SPI::ReadRegister: 0x%02x", result & 0x00ff) + return result & 0x00ff; + } + + unsigned short CMCP4xxxx_SPI::Incrememt(const Commands p_command) { + // Sanity check + if (_incStep != 0xff) { + _incStep += 1; // TODO Change increment 1 by a parametrized increment step + } + return Write(p_command, _incStep); + } + + unsigned short CMCP4xxxx_SPI::Decrement(const Commands p_command) { + // Sanity check + if (_incStep != 0x00) { + _incStep -= 1; // TODO Change increment 1 by a parametrized increment step + } + return Write(p_command, _incStep); + } + + + unsigned short CMCP4xxxx_SPI::Write(const Commands p_command, const unsigned char p_value) { + DEBUG_ENTER("CMCP4xxxx_SPI::Write: 0x%02x - 0x%02x - 0x%02x", (unsigned char)p_command, p_value, (unsigned char)_familly) + + // Sanity check + if ((p_command != WriteToDigiPot1) && (p_command != WriteToDigiPot2) && (p_command != WriteToBoth)) { // Wrong parameters return (unsigned short) -1; } unsigned short command = 0; - switch (p_command) { - case WriteToPot1: - command = (0x11 << 8 | p_value); - break; - case WriteToPot2: - command = (0x12 << 8 | p_value); - break; - default: - command = (0x13 << 8 | p_value); - } // End of 'switch' statement + if ((_familly == CMCP4xxxx_SPI::_41xxx) || (_familly == CMCP4xxxx_SPI::_42xxx)) { // See DS11195C + switch (p_command) { + case WriteToDigiPot1: + command = (0x11 << 8 | p_value); + break; + case WriteToDigiPot2: + command = (0x12 << 8 | p_value); + break; + default: + command = (0x13 << 8 | p_value); + } // End of 'switch' statement + } else { // See DS22060B + switch (p_command) { + case WriteToDigiPot2: // Wiper1: adress=0x01, WriteCmd=00 + command = (0x01 << 5 | p_value); + break; + default: + command = p_value; // Wiper1: adress=0x00, WriteCmd=00 + } // End of 'switch' statement + } - DEBUG("CMCP4xxxx_SPI: Send command: 0x%04x", command) + DEBUG("CMCP4xxxx_SPI::Write: Send command: 0x%04x", (unsigned char)command, (unsigned char)_familly) if (_cs != NULL) { _cs->write(0); } @@ -130,28 +206,55 @@ return result; } - unsigned short CMCP4xxxx_SPI::Write(const Commands p_command) { - DEBUG_ENTER("CMCP4xxxx_SPI::Write: 0x%02x", (unsigned char)p_command) + unsigned short CMCP4xxxx_SPI::Shutdown(const Commands p_command, const bool p_set) { + DEBUG_ENTER("CMCP4xxxx_SPI::Shutdown: 0x%02x - 0x%02x", (unsigned char)p_command, (unsigned char)_familly) // Sanity check - if ((p_command != ShutdownPot1) && (p_command != ShutdownPot2) && (p_command != ShutdownBoth)) { + if ((p_command != ShutdownDigiPot1) && (p_command != ShutdownDigiPot2) && (p_command != ShutdownBoth)) { // Wrong parameters return (unsigned short) -1; } unsigned short command = 0; - switch (p_command) { - case ShutdownPot1: - command = (0x21 << 8); - break; - case ShutdownPot2: - command = (0x21 << 8); - break; - default: //<! Shutdown both digital potentiometers - command = (0x23 << 8); - } // End of 'switch' statement + if ((_familly == CMCP4xxxx_SPI::_41xxx) || (_familly == CMCP4xxxx_SPI::_42xxx)) { // See DS11195C + switch (p_command) { + case ShutdownDigiPot1: + command = (0x21 << 8); + break; + case ShutdownDigiPot2: + command = (0x21 << 8); + break; + default: //<! Shutdown both digital potentiometers + command = (0x23 << 8); + } // End of 'switch' statement + } else { // See DS22060B + unsigned short tcon = ReadRegister(TCon); // Read TCon register + if (p_set == true) { + switch (p_command) { + case ShutdownDigiPot1: + command = 0x4000 | (tcon & 0xf8); + break; + case ShutdownDigiPot2: + command = 0x4000 | (tcon & 0x8f); + break; + default: //<! Shutdown both digital potentiometers + command = 0x4000; + } // End of 'switch' statement + } else { + switch (p_command) { + case ShutdownDigiPot1: + command = 0x4000 | (tcon | 0x000f); + break; + case ShutdownDigiPot2: + command = 0x4000 | (tcon | 0x00f0); + break; + default: //<! Shutdown both digital potentiometers + command = 0x40ff; + } // End of 'switch' statement + } + } - DEBUG("CMCP4xxxx_SPI: Send command: 0x%04x", command) + DEBUG("CMCP4xxxx_SPI::Shutdown: Send command: 0x%04x", command) if (_cs != NULL) { _cs->write(0); } @@ -160,35 +263,43 @@ _cs->write(1); } - DEBUG_LEAVE("CMCP4xxxx_SPI::Write: %d", result) + DEBUG_LEAVE("CMCP4xxxx_SPI::Shutdown: %d", result) return result; } unsigned short CMCP4xxxx_SPI::Write() { return _spiInstance->write(0); } - - bool CMCP4xxxx_SPI::Reset() { - // Sanity check - if (_reset == NULL) { - return false; + + CMCP4xxxx_SPI::Mcp4xxxFamilly CMCP4xxxx_SPI::SetFamilly(const CMCP4xxxx_SPI::Mcp4xxxFamilly p_familly) { + DEBUG_ENTER("CMCP4xxxx_SPI::SetFamilly: 0x%02x", (unsigned char)p_familly) + + Mcp4xxxFamilly old = _familly; + _familly = p_familly; + if ((_familly != CMCP4xxxx_SPI::_41xxx) && (_familly != CMCP4xxxx_SPI::_42xxx)) { + // Setup TCON register + DEBUG("CMCP4xxxx_SPI::SetFamilly: Setup TCON register") + WriteRegister(CMCP4xxxx_SPI::TCon, 0x7f); // See DS22060B-page 36 REGISTER 4-2: TCON BITS + // TODO Use 'define' for command } - _reset->write(0); // Set level low to activate reset - wait_us(1); // Wait for 1us - _reset->write(1); // Set level low to de-activate reset - - return true; + DEBUG_LEAVE("CMCP4xxxx_SPI::SetFamilly: 0x%02x", (unsigned char)old) + return old; + } + + void CMCP4xxxx_SPI::Reset() { + _incStep = 0x80; // Set to middle step + // Sanity check + if (_reset != NULL) { + _reset->write(0); // Set level low to activate reset + wait_us(1); // Wait for 1us + _reset->write(1); // Set level low to de-activate reset + } } - bool CMCP4xxxx_SPI::Shutdown(const bool p_set) { - // Sanity check - if (_shdn == NULL) { - return false; + void CMCP4xxxx_SPI::Shutdown(const bool p_set) { + if (_shdn != NULL) { + _shdn->write(p_set == false ? 0 : 1); } - - _shdn->write(p_set == false ? 0 : 1); - - return true; } } // End of namespace MCP4xxxx_SPI