303 lines
7.7 KiB
C++
303 lines
7.7 KiB
C++
#include "MCP4461.h"
|
|
|
|
/*
|
|
Library to control the MCP4461 Digital Potentiometer over I2C.
|
|
http://ww1.microchip.com/downloads/en/DeviceDoc/22265a.pdf
|
|
This library does not fully implement the functionality of
|
|
the MCP4461 just the basics of changing the wiper values.
|
|
Note this is currently configured to use the second I2C bus
|
|
on the Due: Wire1
|
|
The master joins the bus with the default address of 0
|
|
|
|
No warranty given or implied, use at your own risk.
|
|
Tony@think3dprint3d.com
|
|
GPL v3
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <Wire.h>
|
|
|
|
//ensure you call begin() before any other functions but note
|
|
//begin can only be called once for all MCP* objects as it initialises
|
|
//the local master through the Wire library
|
|
//if the MCP4461 does not have a default address, call set address before
|
|
//trying to communicate
|
|
MCP4461::MCP4461() {
|
|
_mcp4461_address = DEFAULT_ADDRESS;
|
|
}
|
|
|
|
//initialise the I2C interface as master ie local address is 0
|
|
void MCP4461::begin() {
|
|
Wire1.begin();
|
|
}
|
|
|
|
//set the MCP4461 address
|
|
void MCP4461::setMCP4461Address(uint8_t mcp4461_addr) {
|
|
_mcp4461_address = mcp4461_addr;
|
|
}
|
|
|
|
void MCP4461::setVolatileWiper(uint8_t wiper, uint16_t wiper_value){
|
|
uint16_t value = wiper_value;
|
|
if (value > 0xFF) value = 0x100;
|
|
uint8_t d_byte = (uint8_t)value;
|
|
uint8_t c_byte;
|
|
if (value > 0xFF)c_byte = 0x1; //the 8th data bit is 1
|
|
else c_byte =0;
|
|
switch (wiper) {
|
|
case 0:
|
|
c_byte |= MCP4461_VW0;
|
|
break;
|
|
case 1:
|
|
c_byte |= MCP4461_VW1;
|
|
break;
|
|
case 2:
|
|
c_byte |= MCP4461_VW2;
|
|
break;
|
|
case 3:
|
|
c_byte |= MCP4461_VW3;
|
|
break;
|
|
default:
|
|
break; //not a valid wiper
|
|
}
|
|
c_byte |= MCP4461_WRITE;
|
|
//send command byte
|
|
Wire1.beginTransmission(_mcp4461_address);
|
|
Wire1.write(c_byte);
|
|
Wire1.write(d_byte);
|
|
Wire1.endTransmission(); //do not release bus
|
|
}
|
|
|
|
void MCP4461::setNonVolatileWiper(uint8_t wiper, uint16_t wiper_value){
|
|
uint16_t value = wiper_value;
|
|
if (value > 0xFF) value = 0x100;
|
|
uint8_t d_byte = (uint8_t)value;
|
|
uint8_t c_byte;
|
|
if (value > 0xFF)c_byte = 0x1; //the 8th data bit is 1
|
|
else c_byte =0;
|
|
switch (wiper) {
|
|
case 0:
|
|
c_byte |= MCP4461_NVW0;
|
|
break;
|
|
case 1:
|
|
c_byte |= MCP4461_NVW1;
|
|
break;
|
|
case 2:
|
|
c_byte |= MCP4461_NVW2;
|
|
break;
|
|
case 3:
|
|
c_byte |= MCP4461_NVW3;
|
|
break;
|
|
default:
|
|
break; //not a valid wiper
|
|
}
|
|
c_byte |= MCP4461_WRITE;
|
|
//send command byte
|
|
Wire1.beginTransmission(_mcp4461_address);
|
|
Wire1.write(c_byte);
|
|
Wire1.write(d_byte);
|
|
Wire1.endTransmission(); //do not release bus
|
|
delay(20); //allow the write to complete (this is wasteful - better to check if the write has completed)
|
|
}
|
|
|
|
//set all the wipers in one transmission, more verbose but quicker than multiple calls to
|
|
//setVolatileWiper(uint8_t wiper, uint16_t wiper_value)
|
|
void MCP4461::setVolatileWipers(uint16_t wiper_value){
|
|
uint16_t value = wiper_value;
|
|
if (value > 0xFF) value = 0x100;
|
|
uint8_t d_byte = (uint8_t)value;
|
|
uint8_t c_byte;
|
|
if (value > 0xFF)c_byte = 0x1; //the 8th data bit is 1
|
|
else c_byte =0;
|
|
Wire1.beginTransmission(_mcp4461_address);
|
|
c_byte |= MCP4461_WRITE;
|
|
c_byte |= MCP4461_VW0;
|
|
Wire1.write(c_byte);
|
|
Wire1.write(d_byte);
|
|
if (value > 0xFF) c_byte = 0x1;
|
|
else c_byte =0;
|
|
c_byte |= MCP4461_WRITE;
|
|
c_byte |= MCP4461_VW1;
|
|
Wire1.write(c_byte);
|
|
Wire1.write(d_byte);
|
|
if (value > 0xFF) c_byte = 0x1;
|
|
else c_byte =0;
|
|
c_byte |= MCP4461_WRITE;
|
|
c_byte |= MCP4461_VW2;
|
|
Wire1.write(c_byte);
|
|
Wire1.write(d_byte);
|
|
if (value > 0xFF) c_byte = 0x1;
|
|
else c_byte =0;
|
|
c_byte |= MCP4461_WRITE;
|
|
c_byte |= MCP4461_VW3;
|
|
Wire1.write(c_byte);
|
|
Wire1.write(d_byte);
|
|
Wire1.endTransmission();
|
|
}
|
|
|
|
//set all the wipers in one transmission, more verbose but quicker than multiple calls to
|
|
//setNonVolatileWiper(uint8_t wiper, uint16_t wiper_value)
|
|
void MCP4461::setNonVolatileWipers(uint16_t wiper_value){
|
|
uint16_t value = wiper_value;
|
|
if (value > 0xFF) value = 0x100;
|
|
uint8_t d_byte = (uint8_t)value;
|
|
uint8_t c_byte;
|
|
if (value > 0xFF)c_byte = 0x1; //the 8th data bit is 1
|
|
else c_byte =0;
|
|
Wire1.beginTransmission(_mcp4461_address);
|
|
c_byte |= MCP4461_WRITE;
|
|
c_byte |= MCP4461_NVW0;
|
|
Wire1.write(c_byte);
|
|
Wire1.write(d_byte);
|
|
delay(20); //allow the write to complete (this is wasteful - better to check if the write has completed)
|
|
if (value > 0xFF) c_byte = 0x1;
|
|
else c_byte =0;
|
|
c_byte |= MCP4461_WRITE;
|
|
c_byte |= MCP4461_NVW1;
|
|
Wire1.write(c_byte);
|
|
Wire1.write(d_byte);
|
|
delay(20);
|
|
if (value > 0xFF) c_byte = 0x1;
|
|
else c_byte =0;
|
|
c_byte |= MCP4461_WRITE;
|
|
c_byte |= MCP4461_NVW2;
|
|
Wire1.write(c_byte);
|
|
Wire1.write(d_byte);
|
|
delay(20);
|
|
if (value > 0xFF) c_byte = 0x1;
|
|
else c_byte =0;
|
|
c_byte |= MCP4461_WRITE;
|
|
c_byte |= MCP4461_NVW3;
|
|
Wire1.write(c_byte);
|
|
Wire1.write(d_byte);
|
|
Wire1.endTransmission();
|
|
delay(20);
|
|
}
|
|
|
|
//return the value for a specific wiper
|
|
uint16_t MCP4461::getNonVolatileWiper(uint8_t wiper){
|
|
uint16_t ret = 0;
|
|
uint16_t c_byte =0;
|
|
switch (wiper) {
|
|
case 0:
|
|
c_byte |= MCP4461_NVW0;
|
|
break;
|
|
case 1:
|
|
c_byte |= MCP4461_NVW1;
|
|
break;
|
|
case 2:
|
|
c_byte |= MCP4461_NVW2;
|
|
break;
|
|
case 3:
|
|
c_byte |= MCP4461_NVW3;
|
|
break;
|
|
default:
|
|
return 0; //not a valid wiper
|
|
}
|
|
c_byte |= MCP4461_READ;
|
|
//send command byte
|
|
Wire1.beginTransmission(_mcp4461_address);
|
|
Wire1.write(c_byte);
|
|
Wire1.endTransmission(false); //do not release bus
|
|
Wire1.requestFrom((uint8_t)_mcp4461_address,(uint8_t)2);
|
|
//read the register
|
|
int i = 0;
|
|
while(Wire1.available())
|
|
{
|
|
ret |= Wire1.read();
|
|
if (i==0) ret = ret<<8;
|
|
i++;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
//return the volatile value for a specific wiper
|
|
uint16_t MCP4461::getVolatileWiper(uint8_t wiper){
|
|
uint16_t ret = 0;
|
|
uint16_t c_byte =0;
|
|
switch (wiper) {
|
|
case 0:
|
|
c_byte |= MCP4461_VW0;
|
|
break;
|
|
case 1:
|
|
c_byte |= MCP4461_VW1;
|
|
break;
|
|
case 2:
|
|
c_byte |= MCP4461_VW2;
|
|
break;
|
|
case 3:
|
|
c_byte |= MCP4461_VW3;
|
|
break;
|
|
default:
|
|
return 0; //not a valid wiper
|
|
}
|
|
c_byte |= MCP4461_READ;
|
|
//send command byte
|
|
Wire1.beginTransmission(_mcp4461_address);
|
|
Wire1.write(c_byte);
|
|
Wire1.endTransmission(false); //do not release bus
|
|
Wire1.requestFrom((uint8_t)_mcp4461_address,(uint8_t)2);
|
|
//read the register
|
|
int i = 0;
|
|
while(Wire1.available())
|
|
{
|
|
ret |= Wire1.read();
|
|
if (i==0) ret = ret<<8;
|
|
i++;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
//return the status register
|
|
uint16_t MCP4461::getStatus(){
|
|
uint16_t ret = 0;
|
|
uint16_t c_byte =0;
|
|
c_byte |= MCP4461_STATUS;
|
|
c_byte |= MCP4461_READ;
|
|
//send command byte
|
|
Wire1.beginTransmission(_mcp4461_address);
|
|
Wire1.write(c_byte);
|
|
Wire1.endTransmission(false); //do not release bus
|
|
Wire1.requestFrom((uint8_t)_mcp4461_address, (uint8_t)2);
|
|
//read the register
|
|
int i = 0;
|
|
while(Wire1.available())
|
|
{
|
|
ret |= Wire1.read();
|
|
if (i==0) ret = ret<<8;
|
|
i++;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
//toggle a specific pot channel on and off
|
|
/* //NOT YET IMPLEMENTED
|
|
void MCP4461::toggleWiper(uint8_t wiper){
|
|
uint16_t tcon = 0;
|
|
uint16_t c_byte =0;
|
|
//read the specific TCONX register to get the current stae of the
|
|
//pot connections
|
|
if (wiper <=1) {
|
|
c_byte |= MCP4461_TCON0;
|
|
c_byte |= MCP4461_READ;
|
|
}
|
|
else {
|
|
c_byte |= MCP4461_TCON1;
|
|
c_byte |= MCP4461_READ;
|
|
}
|
|
//send command byte
|
|
Wire1.beginTransmission(_mcp4461_address);
|
|
Wire1.write(c_byte);
|
|
Wire1.endTransmission(false); //do not release bus
|
|
Wire1.requestFrom((uint8_t)_mcp4461_address,(uint8_t)2);
|
|
//read the register
|
|
int i = 0;
|
|
while(Wire1.available())
|
|
{
|
|
tcon |= Wire1.read();
|
|
if (i==0) tcon = tcon<<8;
|
|
i++;
|
|
}
|
|
SerialUSB.print(" TCON ");
|
|
SerialUSB.print(tcon,BIN);
|
|
} */
|