General usable MCP4728 quad DAC implementation only limited function has to be used together with the DevInterface lib

Dependents:   mbedSerialInterface_talkback2 MCP4728test mbedSerialInterface_sequencer

Committer:
wbeaumont
Date:
Fri Jan 08 11:58:33 2016 +0000
Revision:
1:cd7c70a46739
Parent:
0:7a0ebc527fb9
Child:
3:2a2eafba8a1d
Read, write to the DAC,  setVoltage, readVoltage  to different channels checked.  No detail checks done for config settings is done,  only one write method implemented, no eprom write checks.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
wbeaumont 0:7a0ebc527fb9 1 #include "mcp4728.h"
wbeaumont 0:7a0ebc527fb9 2 #include "mbed.h"
wbeaumont 0:7a0ebc527fb9 3
wbeaumont 0:7a0ebc527fb9 4
wbeaumont 1:cd7c70a46739 5 #define VERSION_MCP4728_SRC "0.48"
wbeaumont 0:7a0ebc527fb9 6
wbeaumont 1:cd7c70a46739 7 #define VREFVOLTAGE 2.048
wbeaumont 0:7a0ebc527fb9 8 #define CMDFAST 0
wbeaumont 1:cd7c70a46739 9
wbeaumont 0:7a0ebc527fb9 10 //#define CMDWRITEI2CADDR 3 // handled in a different class
wbeaumont 0:7a0ebc527fb9 11 #define CMDWRITEVREF 4
wbeaumont 0:7a0ebc527fb9 12 #define CMDWRITEGAIN 6
wbeaumont 0:7a0ebc527fb9 13 #define CMDWRITEPWDDOWN 5
wbeaumont 0:7a0ebc527fb9 14
wbeaumont 1:cd7c70a46739 15 #define WRITEFCTMULTI 8 // write to multiple DAC ch given by ch selectio bits
wbeaumont 1:cd7c70a46739 16 //#define WRITEFCTSEQ 2 // write to DAC AND eeprom, from ch given in ch selection bits to D
wbeaumont 1:cd7c70a46739 17 //#define WRITEFCTSINGLE 3 // write to a singe DAC AND eeprom ch given in ch selection bits
wbeaumont 0:7a0ebc527fb9 18
wbeaumont 1:cd7c70a46739 19 MCP4728::MCP4728(I2CInterface* i2cinterface, int device_address_bits , float Vddin ):
wbeaumont 1:cd7c70a46739 20 getVersion( VERSION_MCP4728_HDR,VERSION_MCP4728_SRC, __TIME__, __DATE__),_i2c_interface(i2cinterface)
wbeaumont 0:7a0ebc527fb9 21 {
wbeaumont 1:cd7c70a46739 22 _adrbytes= device_address_bits & 7;
wbeaumont 0:7a0ebc527fb9 23 // Assemble the full I2C device address.
wbeaumont 0:7a0ebc527fb9 24 _device_address = 0xC0; // Prime the full device address with the device code.
wbeaumont 0:7a0ebc527fb9 25 _device_address |= (device_address_bits<<1);
wbeaumont 0:7a0ebc527fb9 26 // next has to be read back from the device but
wbeaumont 1:cd7c70a46739 27 Vdd=Vddin;
wbeaumont 0:7a0ebc527fb9 28 for ( int ch=0;ch<4;ch++) {
wbeaumont 0:7a0ebc527fb9 29 ChCfg[ch].pwr=Normal;
wbeaumont 0:7a0ebc527fb9 30 ChCfg[ch].vref=InternRef;
wbeaumont 0:7a0ebc527fb9 31 ChCfg[ch].gain=GainX2;
wbeaumont 0:7a0ebc527fb9 32 }
wbeaumont 0:7a0ebc527fb9 33 }
wbeaumont 0:7a0ebc527fb9 34
wbeaumont 0:7a0ebc527fb9 35 int MCP4728::getDACvalue(int& value, int ch){
wbeaumont 1:cd7c70a46739 36 ch = ch & 7;
wbeaumont 1:cd7c70a46739 37 value =chstat[ch].dacvalue;
wbeaumont 1:cd7c70a46739 38 return lastreadresult;
wbeaumont 0:7a0ebc527fb9 39 }
wbeaumont 1:cd7c70a46739 40 int MCP4728::getVoltage(float &voltage, int ch){
wbeaumont 1:cd7c70a46739 41 int value ;
wbeaumont 1:cd7c70a46739 42 int result = getDACvalue( value , ch );
wbeaumont 1:cd7c70a46739 43 voltage = dig2volt( (short int) value, chstat[ch].gain, chstat[ch].vref);
wbeaumont 1:cd7c70a46739 44 return result;
wbeaumont 1:cd7c70a46739 45 };
wbeaumont 0:7a0ebc527fb9 46
wbeaumont 1:cd7c70a46739 47 int MCP4728::setVoltage (float voltage, int ch){
wbeaumont 1:cd7c70a46739 48 short int value = volt2dig( voltage, chstat[ch].gain, chstat[ch].vref);
wbeaumont 1:cd7c70a46739 49 return setDACvalue( (int) value, ch);
wbeaumont 1:cd7c70a46739 50
wbeaumont 1:cd7c70a46739 51 };
wbeaumont 1:cd7c70a46739 52
wbeaumont 1:cd7c70a46739 53
wbeaumont 1:cd7c70a46739 54
wbeaumont 1:cd7c70a46739 55 float MCP4728::dig2volt( short int value, GainMode gain, VrefMode vref ){
wbeaumont 1:cd7c70a46739 56 float vout =(float)value / 4096;
wbeaumont 1:cd7c70a46739 57 if ( vref == ExternRef ) {
wbeaumont 1:cd7c70a46739 58 vout = Vdd * vout;
wbeaumont 1:cd7c70a46739 59 }
wbeaumont 1:cd7c70a46739 60 else {
wbeaumont 1:cd7c70a46739 61 vout = VREFVOLTAGE * vout;
wbeaumont 1:cd7c70a46739 62 if ( gain == GainX2 ) vout = vout*2;
wbeaumont 1:cd7c70a46739 63 }
wbeaumont 1:cd7c70a46739 64 return vout;
wbeaumont 1:cd7c70a46739 65 }
wbeaumont 1:cd7c70a46739 66 short int MCP4728::volt2dig( float voltage, GainMode gain, VrefMode vref ){
wbeaumont 1:cd7c70a46739 67 float tmp;
wbeaumont 1:cd7c70a46739 68 tmp= 4096 * voltage;
wbeaumont 1:cd7c70a46739 69 if ( vref == ExternRef ) {
wbeaumont 1:cd7c70a46739 70 tmp= tmp/Vdd ;
wbeaumont 1:cd7c70a46739 71 }
wbeaumont 1:cd7c70a46739 72 else {
wbeaumont 1:cd7c70a46739 73 if ( gain == GainX2 ) tmp=tmp/2;
wbeaumont 1:cd7c70a46739 74 tmp = tmp / VREFVOLTAGE;
wbeaumont 1:cd7c70a46739 75 }
wbeaumont 1:cd7c70a46739 76 return (short int) ( tmp +.5 );
wbeaumont 1:cd7c70a46739 77 }
wbeaumont 1:cd7c70a46739 78
wbeaumont 1:cd7c70a46739 79
wbeaumont 1:cd7c70a46739 80 int MCP4728::update(bool checkall ) {
wbeaumont 1:cd7c70a46739 81 int result;
wbeaumont 0:7a0ebc527fb9 82
wbeaumont 0:7a0ebc527fb9 83 // Read the raw data from the device.
wbeaumont 1:cd7c70a46739 84 result = _i2c_interface->read(_device_address, rbdata, sizeof(rbdata)/sizeof(*rbdata), false);
wbeaumont 0:7a0ebc527fb9 85
wbeaumont 0:7a0ebc527fb9 86 // Parse the raw data, extracting our fields. Refer to MCP4728 ref manual, section 6.2
wbeaumont 1:cd7c70a46739 87 if (result == 0){
wbeaumont 1:cd7c70a46739 88 int bytecnt=0;
wbeaumont 1:cd7c70a46739 89 char chancheck=0;
wbeaumont 1:cd7c70a46739 90 char addrcheck=0;
wbeaumont 1:cd7c70a46739 91 for ( int cc =0 ; cc < 4 ; cc++) {
wbeaumont 1:cd7c70a46739 92 bytecnt= cc*6; // 6 byte per channel
wbeaumont 1:cd7c70a46739 93 chstat[cc].bussy= (rbdata[bytecnt] & 0x80)? false:true;
wbeaumont 1:cd7c70a46739 94 chstat[cc].por= (rbdata[bytecnt] & 0x40)? false:true;
wbeaumont 1:cd7c70a46739 95 if (checkall) {
wbeaumont 1:cd7c70a46739 96 chancheck=(rbdata[bytecnt] & 0x30) ;
wbeaumont 1:cd7c70a46739 97 chancheck=chancheck >>4; chancheck=chancheck & 3;
wbeaumont 1:cd7c70a46739 98 if ( cc != chancheck ) { result= chancheck ; result = result <<4 ; result=0xC |result | cc;}
wbeaumont 1:cd7c70a46739 99 addrcheck= (rbdata[bytecnt] & 0x07) ;
wbeaumont 1:cd7c70a46739 100 if ( _adrbytes != addrcheck) { result= 0x08 | addrcheck ; result = result <<4 ; result=0x8 | result | cc;}
wbeaumont 1:cd7c70a46739 101 }
wbeaumont 1:cd7c70a46739 102 bytecnt++; // point to the second addr
wbeaumont 1:cd7c70a46739 103 chstat[cc].vref = (enum VrefMode) ((rbdata[bytecnt] & 0x80)>>7);
wbeaumont 1:cd7c70a46739 104 chstat[cc].pwr = (enum PowerMode) ((rbdata[bytecnt] & 0x06)>>5);
wbeaumont 1:cd7c70a46739 105 chstat[cc].gain = (enum GainMode) ((rbdata[bytecnt] & 0x10)>>4);
wbeaumont 1:cd7c70a46739 106 chstat[cc].dacvalue = (rbdata[bytecnt++] & 0xF );// point to the third addr
wbeaumont 1:cd7c70a46739 107 chstat[cc].dacvalue = chstat[cc].dacvalue << 8 ;
wbeaumont 1:cd7c70a46739 108 chstat[cc].dacvalue = chstat[cc].dacvalue | rbdata[bytecnt++] ;// point to the forth addr
wbeaumont 1:cd7c70a46739 109 // eprom bytes
wbeaumont 1:cd7c70a46739 110 chstat[cc].bussy= (rbdata[bytecnt] & 0x80)? false:true;
wbeaumont 1:cd7c70a46739 111 chstat[cc].por= (rbdata[bytecnt] & 0x40)? false:true;
wbeaumont 1:cd7c70a46739 112 if (checkall) {
wbeaumont 1:cd7c70a46739 113 chancheck=(rbdata[bytecnt] & 0x30) ;
wbeaumont 1:cd7c70a46739 114 chancheck=chancheck >>4; chancheck=chancheck & 3;
wbeaumont 1:cd7c70a46739 115 if ( cc != chancheck ) { result= chancheck ; result = result <<4 ; result=0xC |result | cc;}
wbeaumont 1:cd7c70a46739 116 addrcheck= (rbdata[bytecnt] & 0x07) ;
wbeaumont 1:cd7c70a46739 117 if ( _adrbytes != addrcheck) { result= 0x08 | addrcheck ; result = result <<4 ; result=0x8 | result | cc;}
wbeaumont 1:cd7c70a46739 118 }
wbeaumont 1:cd7c70a46739 119 bytecnt++; // point to the second addr
wbeaumont 1:cd7c70a46739 120 chstat[cc].promvref = (enum VrefMode) ((rbdata[bytecnt] & 0x80)>>7);
wbeaumont 1:cd7c70a46739 121 chstat[cc].prompwr = (enum PowerMode) ((rbdata[bytecnt] & 0x06)>>5);
wbeaumont 1:cd7c70a46739 122 chstat[cc].promgain = (enum GainMode) ((rbdata[bytecnt] & 0x10)>>4);
wbeaumont 0:7a0ebc527fb9 123
wbeaumont 1:cd7c70a46739 124 chstat[cc].promvalue = (rbdata[bytecnt++] & 0xF );
wbeaumont 1:cd7c70a46739 125 chstat[cc].promvalue = chstat[cc].promvalue << 8 ;
wbeaumont 1:cd7c70a46739 126 chstat[cc].promvalue = chstat[cc].promvalue | rbdata[bytecnt] ;
wbeaumont 1:cd7c70a46739 127 }
wbeaumont 1:cd7c70a46739 128 }
wbeaumont 1:cd7c70a46739 129 lastreadresult=result;
wbeaumont 0:7a0ebc527fb9 130 return result;
wbeaumont 0:7a0ebc527fb9 131 }
wbeaumont 0:7a0ebc527fb9 132
wbeaumont 0:7a0ebc527fb9 133
wbeaumont 0:7a0ebc527fb9 134 int MCP4728::setDACvalue( int value, int ch){
wbeaumont 0:7a0ebc527fb9 135 char data[3], tmp ;
wbeaumont 1:cd7c70a46739 136
wbeaumont 1:cd7c70a46739 137 data[0] = WRITEFCTMULTI << 3 ; // select write multi ch no eeprom
wbeaumont 0:7a0ebc527fb9 138 ch =ch & 3;
wbeaumont 1:cd7c70a46739 139 tmp =(char) ch << 1; // select the channel
wbeaumont 0:7a0ebc527fb9 140 data[0] = data[0] | tmp ;
wbeaumont 1:cd7c70a46739 141 data[0] = data[0] & 0xFE ; // update now , assuming !LDAC =0
wbeaumont 1:cd7c70a46739 142
wbeaumont 1:cd7c70a46739 143 data[2] = 0xFF & (char)value; // lower byte
wbeaumont 1:cd7c70a46739 144 value=value >>8;
wbeaumont 0:7a0ebc527fb9 145 data[1] = 0x0F & (char)value;
wbeaumont 0:7a0ebc527fb9 146 data[1] = data[1] | (char)( ChCfg[ch].gain <<4); //set gain
wbeaumont 0:7a0ebc527fb9 147 data[1] = data[1] | (char)( ChCfg[ch].pwr <<5); // set pwr mode
wbeaumont 0:7a0ebc527fb9 148 data[1] = data[1] | (char)( ChCfg[ch].vref <<7); // set pwr mode
wbeaumont 1:cd7c70a46739 149
wbeaumont 1:cd7c70a46739 150 //data[0]= 0x52; // 0b0101 0010 ch 1 !UDAC=0
wbeaumont 1:cd7c70a46739 151 //data[1]= 0x17; // 0b0000 0111 ref=Vdd, pwd =0 normal ; gain =1 d11=0 ,111,
wbeaumont 0:7a0ebc527fb9 152 return _i2c_interface->write(_device_address, data, sizeof(data)/sizeof(*data), false);
wbeaumont 0:7a0ebc527fb9 153
wbeaumont 0:7a0ebc527fb9 154
wbeaumont 0:7a0ebc527fb9 155 }
wbeaumont 0:7a0ebc527fb9 156
wbeaumont 1:cd7c70a46739 157 // kept c compatible
wbeaumont 1:cd7c70a46739 158 // no text interpretation of gain ,ref and power mod
wbeaumont 1:cd7c70a46739 159 int MCP4728::StatusString(int ch,bool updatereq , bool eprom, char *str , int length){
wbeaumont 1:cd7c70a46739 160 if (length < 200 ) return -200;
wbeaumont 1:cd7c70a46739 161 int result=0;
wbeaumont 1:cd7c70a46739 162 if ( updatereq ) result= update (false);
wbeaumont 1:cd7c70a46739 163 if ( result ) return result ;
wbeaumont 1:cd7c70a46739 164 ch=ch&3 ;
wbeaumont 0:7a0ebc527fb9 165
wbeaumont 1:cd7c70a46739 166 int dataidx= ch* 6 + 3* (int) eprom;
wbeaumont 1:cd7c70a46739 167 if ( eprom ) {
wbeaumont 0:7a0ebc527fb9 168
wbeaumont 1:cd7c70a46739 169
wbeaumont 1:cd7c70a46739 170 result= sprintf( str, "d1:%02X d2:%02X d3:%02X EEP Ch: %1d pwr: %1d Ref: %1d gain: %1d, value %04d",
wbeaumont 1:cd7c70a46739 171 (int)rbdata[dataidx++],(int)rbdata[dataidx++],(int)rbdata[dataidx],
wbeaumont 1:cd7c70a46739 172 ch,(int) chstat[ch].prompwr, (int) chstat[ch].promvref , (int) chstat[ch].promgain, (int) chstat[ch].promvalue );
wbeaumont 0:7a0ebc527fb9 173
wbeaumont 1:cd7c70a46739 174 }else {
wbeaumont 1:cd7c70a46739 175 result= sprintf( str, "d1:%02X d2:%02X d3:%02X DAC Ch: %01d pwr: %04d Ref: %04d gain: %04d, value %04d",
wbeaumont 1:cd7c70a46739 176 (int)rbdata[dataidx],(int)rbdata[dataidx+1],(int)rbdata[dataidx+2],
wbeaumont 1:cd7c70a46739 177 ch,(int) chstat[ch].pwr, (int) chstat[ch].vref , (int) chstat[ch].gain, (int) chstat[ch].dacvalue );
wbeaumont 1:cd7c70a46739 178 }
wbeaumont 1:cd7c70a46739 179 return result;
wbeaumont 0:7a0ebc527fb9 180 }