General usable MCP4728 quad DAC implementation only limited function has to be used together with the DevInterface lib
Dependents: mbedSerialInterface_talkback2 MCP4728test mbedSerialInterface_sequencer
mcp4728.cpp
- Committer:
- wbeaumont
- Date:
- 2016-07-06
- Revision:
- 5:164362cf5836
- Parent:
- 3:2a2eafba8a1d
File content as of revision 5:164362cf5836:
#include "mcp4728.h" #include "mbed.h" #define VERSION_MCP4728_SRC "0.49" #define VREFVOLTAGE 2.048 #define CMDFAST 0 //#define CMDWRITEI2CADDR 3 // handled in a different class #define CMDWRITEVREF 4 #define CMDWRITEGAIN 6 #define CMDWRITEPWDDOWN 5 #define WRITEFCTMULTI 8 // write to multiple DAC ch given by ch selectio bits //#define WRITEFCTSEQ 2 // write to DAC AND eeprom, from ch given in ch selection bits to D //#define WRITEFCTSINGLE 3 // write to a singe DAC AND eeprom ch given in ch selection bits MCP4728::MCP4728(I2CInterface* i2cinterface, int device_address_bits , float Vddin ): getVersion( VERSION_MCP4728_HDR,VERSION_MCP4728_SRC, __TIME__, __DATE__),_i2c_interface(i2cinterface) { _adrbytes= device_address_bits & 7; // Assemble the full I2C device address. _device_address = 0xC0; // Prime the full device address with the device code. _device_address |= (device_address_bits<<1); // next has to be read back from the device but Vdd=Vddin; for ( int ch=0;ch<4;ch++) { ChCfg[ch].pwr=Normal; ChCfg[ch].vref=InternRef; ChCfg[ch].gain=GainX2; } } int MCP4728::getDACvalue(int& value, int ch){ ch = ch & 7; value =chstat[ch].dacvalue; return lastupdateresult; } int MCP4728::getVoltage(float &voltage, int ch){ int value ; int result = getDACvalue( value , ch ); voltage = dig2volt( (short int) value, chstat[ch].gain, chstat[ch].vref); return result; }; int MCP4728::setVoltage (float voltage, int ch){ short int value = volt2dig( voltage, ChCfg[ch].gain, ChCfg[ch].vref); return setDACvalue( (int) value, ch); }; float MCP4728::dig2volt( short int value, GainMode gain, VrefMode vref ){ float vout =(float)value / 4096; if ( vref == ExternRef ) { vout = Vdd * vout; } else { vout = VREFVOLTAGE * vout; if ( gain == GainX2 ) vout = vout*2; } return vout; } short int MCP4728::volt2dig( float voltage, GainMode gain, VrefMode vref ){ float tmp; tmp= 4096 * voltage; if ( vref == ExternRef ) { tmp= tmp/Vdd ; } else { if ( gain == GainX2 ) tmp=tmp/2; tmp = tmp / VREFVOLTAGE; } return (short int) ( tmp +.5 ); } int MCP4728::update(bool checkall ) { int result; // Read the raw data from the device. result = _i2c_interface->read(_device_address, rbdata, sizeof(rbdata)/sizeof(*rbdata), false); // Parse the raw data, extracting our fields. Refer to MCP4728 ref manual, section 6.2 if (result == 0){ int bytecnt=0; char chancheck=0; char addrcheck=0; for ( int cc =0 ; cc < 4 ; cc++) { bytecnt= cc*6; // 6 byte per channel chstat[cc].busy= (rbdata[bytecnt] & 0x80)? false:true; chstat[cc].por= (rbdata[bytecnt] & 0x40)? false:true; if (checkall) { chancheck=(rbdata[bytecnt] & 0x30) ; chancheck=chancheck >>4; chancheck=chancheck & 3; if ( cc != chancheck ) { result= chancheck ; result = result <<4 ; result=0xC |result | cc;} addrcheck= (rbdata[bytecnt] & 0x07) ; if ( _adrbytes != addrcheck) { result= 0x08 | addrcheck ; result = result <<4 ; result=0x8 | result | cc;} } bytecnt++; // point to the second addr chstat[cc].vref = (enum VrefMode) ((rbdata[bytecnt] & 0x80)>>7); chstat[cc].pwr = (enum PowerMode) ((rbdata[bytecnt] & 0x06)>>5); chstat[cc].gain = (enum GainMode) ((rbdata[bytecnt] & 0x10)>>4); chstat[cc].dacvalue = (rbdata[bytecnt++] & 0xF );// point to the third addr chstat[cc].dacvalue = chstat[cc].dacvalue << 8 ; chstat[cc].dacvalue = chstat[cc].dacvalue | rbdata[bytecnt++] ;// point to the forth addr // eprom bytes chstat[cc].busy= (rbdata[bytecnt] & 0x80)? false:true; chstat[cc].por= (rbdata[bytecnt] & 0x40)? false:true; if (checkall) { chancheck=(rbdata[bytecnt] & 0x30) ; chancheck=chancheck >>4; chancheck=chancheck & 3; if ( cc != chancheck ) { result= chancheck ; result = result <<4 ; result=0xC |result | cc;} addrcheck= (rbdata[bytecnt] & 0x07) ; if ( _adrbytes != addrcheck) { result= 0x08 | addrcheck ; result = result <<4 ; result=0x8 | result | cc;} } bytecnt++; // point to the second addr chstat[cc].promvref = (enum VrefMode) ((rbdata[bytecnt] & 0x80)>>7); chstat[cc].prompwr = (enum PowerMode) ((rbdata[bytecnt] & 0x06)>>5); chstat[cc].promgain = (enum GainMode) ((rbdata[bytecnt] & 0x10)>>4); chstat[cc].promvalue = (rbdata[bytecnt++] & 0xF ); chstat[cc].promvalue = chstat[cc].promvalue << 8 ; chstat[cc].promvalue = chstat[cc].promvalue | rbdata[bytecnt] ; } } lastupdateresult=result; return result; } int MCP4728::setDACvalue( int value, int ch){ char data[3], tmp ; data[0] = WRITEFCTMULTI << 3 ; // select write multi ch no eeprom ch =ch & 3; tmp =(char) ch << 1; // select the channel data[0] = data[0] | tmp ; data[0] = data[0] & 0xFE ; // update now , assuming !LDAC =0 data[2] = 0xFF & (char)value; // lower byte value=value >>8; data[1] = 0x0F & (char)value; data[1] = data[1] | (char)( ChCfg[ch].gain <<4); //set gain data[1] = data[1] | (char)( ChCfg[ch].pwr <<5); // set pwr mode data[1] = data[1] | (char)( ChCfg[ch].vref <<7); // set pwr mode //data[0]= 0x52; // 0b0101 0010 ch 1 !UDAC=0 //data[1]= 0x17; // 0b0000 0111 ref=Vdd, pwd =0 normal ; gain =1 d11=0 ,111, return _i2c_interface->write(_device_address, data, sizeof(data)/sizeof(*data), false); } // kept c compatible // no text interpretation of gain ,ref and power mod int MCP4728::StatusString(int ch,bool updatereq , bool eprom, char *str , int length){ if (length < 200 ) return -200; int result=0; if ( updatereq ) result= update (false); if ( result ) return result ; ch=ch&3 ; int dataidx= ch* 6 + 3* (int) eprom; if ( eprom ) { result= sprintf( str, "d1:%02X d2:%02X d3:%02X EEP Ch: %1d pwr: %1d Ref: %1d gain: %1d, value %04d", (int)rbdata[dataidx++],(int)rbdata[dataidx++],(int)rbdata[dataidx], ch,(int) chstat[ch].prompwr, (int) chstat[ch].promvref , (int) chstat[ch].promgain, (int) chstat[ch].promvalue ); }else { result= sprintf( str, "d1:%02X d2:%02X d3:%02X DAC Ch: %01d pwr: %04d Ref: %04d gain: %04d, value %04d", (int)rbdata[dataidx],(int)rbdata[dataidx+1],(int)rbdata[dataidx+2], ch,(int) chstat[ch].pwr, (int) chstat[ch].vref , (int) chstat[ch].gain, (int) chstat[ch].dacvalue ); } return result; }