
Added the libraries to the repository Preliminary changes to fix slow startup when no network cable is connected
303 lines
7.8 KiB
C++
303 lines
7.8 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);
|
||
} */
|