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@1:cd7c70a46739, 2016-01-08 (annotated)
- 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?
User | Revision | Line number | New 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 | } |