control for DAC AD5384 for the SOLID SM1 Slow Control

Dependents:   SPItest sscm

Committer:
wbeaumont
Date:
Thu Jan 29 11:03:56 2015 +0000
Revision:
5:477603ce54a0
Parent:
4:bc9ab300ab26
i n calculation corrected gain+1  to gain+2

Who changed what in which revision?

UserRevisionLine numberNew contents of line
wbeaumont 0:33bb5081488a 1 #include "AD5384.h"
wbeaumont 0:33bb5081488a 2 #include "mbed.h"
wbeaumont 0:33bb5081488a 3
wbeaumont 0:33bb5081488a 4 #define nrch 40 // nr channels
wbeaumont 0:33bb5081488a 5 #define p2_14 16384
wbeaumont 0:33bb5081488a 6 #define p2_13 8192
wbeaumont 0:33bb5081488a 7
wbeaumont 3:7ca85ed310e0 8 #define CS_ACTIVE 1
wbeaumont 3:7ca85ed310e0 9 #define CS_DEACTIVE 0
wbeaumont 3:7ca85ed310e0 10
wbeaumont 3:7ca85ed310e0 11 #define RST_ACTIVE 1
wbeaumont 3:7ca85ed310e0 12 #define RST_DEACTIVE 0
wbeaumont 3:7ca85ed310e0 13
wbeaumont 0:33bb5081488a 14
wbeaumont 0:33bb5081488a 15 // spi mode has to be set for each transmission as spi bus can be shared
wbeaumont 0:33bb5081488a 16
wbeaumont 1:d2d6341d3e97 17 /*****
wbeaumont 1:d2d6341d3e97 18 * version history
wbeaumont 1:d2d6341d3e97 19 * v1.10 initial release version
wbeaumont 1:d2d6341d3e97 20 * v1.11 added init 1 and init 2 function an ctrlreg defs
wbeaumont 1:d2d6341d3e97 21 * v1.12
wbeaumont 2:fc250e37a028 22 * v1.13 corrected channel mask from 0x1F to 0x3F
wbeaumont 3:7ca85ed310e0 23 * v1.20 added hw_rst , added hwrst to init1 not in init2
wbeaumont 4:bc9ab300ab26 24 * v1.24 added update shadow registers
wbeaumont 4:bc9ab300ab26 25 * v1.26 corrected mask for reading register value
wbeaumont 4:bc9ab300ab26 26 * v1.30 added get voltage
wbeaumont 5:477603ce54a0 27 *V1.31 corrected gain+1 to gain+2 in calculate_dac_setting
wbeaumont 1:d2d6341d3e97 28 */
wbeaumont 1:d2d6341d3e97 29
wbeaumont 5:477603ce54a0 30 #define AD5384_SRC_VERSION "1.31"
wbeaumont 0:33bb5081488a 31
wbeaumont 0:33bb5081488a 32 #define M_DATA_R 0x3
wbeaumont 0:33bb5081488a 33 #define M_OFFS_R 0x2
wbeaumont 0:33bb5081488a 34 #define M_GAIN_R 0x1
wbeaumont 0:33bb5081488a 35 #define M_SPEC_R 0x0
wbeaumont 0:33bb5081488a 36
wbeaumont 0:33bb5081488a 37 #define NOP_INST 0x0
wbeaumont 0:33bb5081488a 38
wbeaumont 1:d2d6341d3e97 39
wbeaumont 1:d2d6341d3e97 40 // control register bits
wbeaumont 1:d2d6341d3e97 41 #define CTRL_REG_ADDR 0x0C
wbeaumont 1:d2d6341d3e97 42 #define OUT_PWD_STAT_HIMP 0x2000
wbeaumont 1:d2d6341d3e97 43 //0b10 0000 0000 0000
wbeaumont 1:d2d6341d3e97 44 #define OUT_PWD_STAT_100K 0x1FFF
wbeaumont 1:d2d6341d3e97 45 //0b01 1111 1111 1111
wbeaumont 1:d2d6341d3e97 46 #define INT_REF_2500 0X1000
wbeaumont 1:d2d6341d3e97 47 //0b01000000000000
wbeaumont 1:d2d6341d3e97 48 #define INT_REF_1250 0x2FFF
wbeaumont 1:d2d6341d3e97 49 //0b10111111111111
wbeaumont 1:d2d6341d3e97 50 #define I_BOOST_ON 0x0800
wbeaumont 1:d2d6341d3e97 51 //0b00100000000000
wbeaumont 1:d2d6341d3e97 52 #define I_BOOST_OFF 0x37FF
wbeaumont 1:d2d6341d3e97 53 //0b11011111111111
wbeaumont 1:d2d6341d3e97 54 #define REF_SRC_INT 0x0400
wbeaumont 1:d2d6341d3e97 55 //0b00010000000000
wbeaumont 1:d2d6341d3e97 56 #define REF_SRC_EXT 0x3BFF
wbeaumont 1:d2d6341d3e97 57 //0b11 1011 1111 1111
wbeaumont 1:d2d6341d3e97 58 #define MONITOR_MODE_EN 0x0200
wbeaumont 1:d2d6341d3e97 59 //0b00001000000000
wbeaumont 1:d2d6341d3e97 60 #define MONITOR_MODE_DIS 0x3DFF
wbeaumont 1:d2d6341d3e97 61 //0b11 1101 1111 1111
wbeaumont 1:d2d6341d3e97 62 #define TEMP_MONITOR_EN 0x0100
wbeaumont 1:d2d6341d3e97 63 //0b00000100000000
wbeaumont 1:d2d6341d3e97 64 #define TEMP_MONITOR_DIS 0x3EFF
wbeaumont 1:d2d6341d3e97 65 //0b11 1110 1111 1111
wbeaumont 1:d2d6341d3e97 66 #define TOGGLE_DISABLE 0x3F83
wbeaumont 1:d2d6341d3e97 67 //0b11 1111 1000 0011
wbeaumont 1:d2d6341d3e97 68
wbeaumont 1:d2d6341d3e97 69
wbeaumont 1:d2d6341d3e97 70
wbeaumont 1:d2d6341d3e97 71
wbeaumont 3:7ca85ed310e0 72 AD5384::AD5384(SWSPI *spiinterface ,DigitalOut* chipselect, DigitalOut* reset):getVersion( VERSION_AD5384_HDR,AD5384_SRC_VERSION, __TIME__, __DATE__) {
wbeaumont 0:33bb5081488a 73 vref=2.5;
wbeaumont 0:33bb5081488a 74 spi=spiinterface;
wbeaumont 0:33bb5081488a 75 cs=chipselect;
wbeaumont 3:7ca85ed310e0 76 rst=reset;
wbeaumont 4:bc9ab300ab26 77 for ( int nc=0 ; nc < nrch; nc++){
wbeaumont 4:bc9ab300ab26 78 gain[nc]=0x3FFE; //power up values
wbeaumont 0:33bb5081488a 79 offset[nc]=0x2000;
wbeaumont 4:bc9ab300ab26 80 dacr[nc]=0x0000;
wbeaumont 0:33bb5081488a 81 }
wbeaumont 0:33bb5081488a 82 };
wbeaumont 0:33bb5081488a 83
wbeaumont 4:bc9ab300ab26 84
wbeaumont 4:bc9ab300ab26 85 void AD5384::update_gain_shadow(u8 ch ) {
wbeaumont 4:bc9ab300ab26 86 if( ch) gain[ch-1] = get_gain(ch-1);
wbeaumont 4:bc9ab300ab26 87 else
wbeaumont 4:bc9ab300ab26 88 for (u8 chc=0;chc < 40;chc++) {
wbeaumont 4:bc9ab300ab26 89 gain[chc] = get_gain(chc);
wbeaumont 4:bc9ab300ab26 90 }
wbeaumont 4:bc9ab300ab26 91
wbeaumont 4:bc9ab300ab26 92 }
wbeaumont 4:bc9ab300ab26 93 void AD5384::update_offset_shadow(u8 ch ) {
wbeaumont 4:bc9ab300ab26 94 if( ch) offset[ch-1] = get_offset(ch-1);
wbeaumont 4:bc9ab300ab26 95 else
wbeaumont 4:bc9ab300ab26 96 for (u8 chc=0;chc < 40;chc++) {
wbeaumont 4:bc9ab300ab26 97 offset[chc] = get_offset(chc);
wbeaumont 4:bc9ab300ab26 98 }
wbeaumont 4:bc9ab300ab26 99 }
wbeaumont 4:bc9ab300ab26 100
wbeaumont 4:bc9ab300ab26 101 void AD5384::update_dac_shadow(u8 ch ) {
wbeaumont 4:bc9ab300ab26 102 if( ch) dacr[ch-1] = get_dac(ch-1);
wbeaumont 4:bc9ab300ab26 103 else
wbeaumont 4:bc9ab300ab26 104 for (u8 chc=0;chc < 40;chc++) {
wbeaumont 4:bc9ab300ab26 105 dacr[chc] = get_dac(chc);
wbeaumont 4:bc9ab300ab26 106 }
wbeaumont 4:bc9ab300ab26 107 }
wbeaumont 4:bc9ab300ab26 108
wbeaumont 4:bc9ab300ab26 109
wbeaumont 4:bc9ab300ab26 110 u16 AD5384::calculate_dac_setting(u8 nr, float vout ) {
wbeaumont 0:33bb5081488a 111 //Vout = 2 * Vref * x2 / 2^n => x2 = Vout * 2^14 /(2 * Vref)
wbeaumont 0:33bb5081488a 112 // x2 is loaded to the DAC string
wbeaumont 4:bc9ab300ab26 113 // x1 is the 14 bit DAC wordt written to the DAC input register
wbeaumont 4:bc9ab300ab26 114 float x2= vout * (float)p2_14 /(2 *vref);
wbeaumont 0:33bb5081488a 115 // x2 = [(gain+2)/2^n * x1] + offset-2^13
wbeaumont 0:33bb5081488a 116 // x1 = 2^14/(gain+2) * [ x2 - offset+2^13 ]
wbeaumont 5:477603ce54a0 117 u16 x1 = (float)p2_14/((float)gain[nr]+2) *( x2- offset[nr]+p2_13);
wbeaumont 1:d2d6341d3e97 118 x1= 0x3FFF & x1;
wbeaumont 4:bc9ab300ab26 119 dacr[nr]=x1 ;
wbeaumont 0:33bb5081488a 120 return x1;
wbeaumont 0:33bb5081488a 121 };
wbeaumont 0:33bb5081488a 122
wbeaumont 0:33bb5081488a 123
wbeaumont 0:33bb5081488a 124 u32 AD5384::format_word(u8 mode,u8 ch,u8 rw,u16 data) {
wbeaumont 2:fc250e37a028 125 // MSB set to 0 , toggle mode not supported
wbeaumont 0:33bb5081488a 126 u32 shift = (u32) rw&1;
wbeaumont 0:33bb5081488a 127 u32 word= shift << 22;
wbeaumont 0:33bb5081488a 128
wbeaumont 2:fc250e37a028 129 shift= (u32)(ch &0x3F);
wbeaumont 0:33bb5081488a 130 shift = shift << 16;
wbeaumont 0:33bb5081488a 131 word = word | shift;
wbeaumont 0:33bb5081488a 132
wbeaumont 0:33bb5081488a 133 shift= (u32)(mode & 0x3);
wbeaumont 0:33bb5081488a 134 shift = shift << 14;
wbeaumont 0:33bb5081488a 135 word = word | shift;
wbeaumont 0:33bb5081488a 136
wbeaumont 0:33bb5081488a 137 word = word | (data & 0x3FFF);
wbeaumont 0:33bb5081488a 138
wbeaumont 0:33bb5081488a 139 return word;
wbeaumont 0:33bb5081488a 140 }
wbeaumont 0:33bb5081488a 141
wbeaumont 0:33bb5081488a 142 void AD5384::set_spi_mode(){
wbeaumont 0:33bb5081488a 143 spi->format(24,1);
wbeaumont 0:33bb5081488a 144 spi->frequency(10000000);
wbeaumont 0:33bb5081488a 145 }
wbeaumont 0:33bb5081488a 146
wbeaumont 0:33bb5081488a 147 u16 AD5384::set_volt(u8 ch, float vout ){
wbeaumont 0:33bb5081488a 148 volt[ch]=vout;
wbeaumont 0:33bb5081488a 149 u16 dacin=calculate_dac_setting(ch, vout );
wbeaumont 0:33bb5081488a 150 set_spi_mode();
wbeaumont 0:33bb5081488a 151 u32 data=format_word(M_DATA_R,ch,0,dacin);
wbeaumont 3:7ca85ed310e0 152 cs->write(CS_ACTIVE);
wbeaumont 0:33bb5081488a 153 spi->write(data);
wbeaumont 3:7ca85ed310e0 154 cs->write(CS_DEACTIVE);
wbeaumont 4:bc9ab300ab26 155 dacr[ch]=dacin;
wbeaumont 0:33bb5081488a 156 return dacin;
wbeaumont 0:33bb5081488a 157 }
wbeaumont 0:33bb5081488a 158
wbeaumont 4:bc9ab300ab26 159
wbeaumont 4:bc9ab300ab26 160 float AD5384::get_volt(u8 nr, bool readallreg ) {
wbeaumont 4:bc9ab300ab26 161 u16 lgain;
wbeaumont 4:bc9ab300ab26 162 u16 loffset;
wbeaumont 4:bc9ab300ab26 163 u16 ldac=get_ch_out_reg(nr);
wbeaumont 4:bc9ab300ab26 164 dacr[nr]=ldac;
wbeaumont 4:bc9ab300ab26 165 if( readallreg) {
wbeaumont 4:bc9ab300ab26 166 lgain= get_gain(nr); gain[nr]=lgain;
wbeaumont 4:bc9ab300ab26 167 loffset=get_offset(nr); offset[nr]=loffset;
wbeaumont 4:bc9ab300ab26 168 }
wbeaumont 4:bc9ab300ab26 169 else { lgain=gain[nr]; loffset=offset[nr];}
wbeaumont 4:bc9ab300ab26 170 //Vout = 2 * Vref * x2 / 2^n x2= [x1*(m+2)]/2^n ]+ (c-2^(n-1))
wbeaumont 4:bc9ab300ab26 171 float x2= ((float)(lgain+2)/(float)p2_14)*(float) ldac + loffset- p2_13;
wbeaumont 4:bc9ab300ab26 172 float vout = 2 *vref * x2 / p2_14;
wbeaumont 4:bc9ab300ab26 173 return vout;
wbeaumont 4:bc9ab300ab26 174 }
wbeaumont 4:bc9ab300ab26 175
wbeaumont 4:bc9ab300ab26 176
wbeaumont 4:bc9ab300ab26 177
wbeaumont 1:d2d6341d3e97 178 void AD5384::init1(){
wbeaumont 1:d2d6341d3e97 179 u16 ctrlreg=0;
wbeaumont 3:7ca85ed310e0 180 hw_rst();
wbeaumont 1:d2d6341d3e97 181 ctrlreg = (INT_REF_2500 | REF_SRC_INT ) & TOGGLE_DISABLE;
wbeaumont 1:d2d6341d3e97 182 set_reg(M_SPEC_R,CTRL_REG_ADDR,ctrlreg);
wbeaumont 4:bc9ab300ab26 183 wait_us(100);
wbeaumont 4:bc9ab300ab26 184 // update_dac_shadow(0);
wbeaumont 4:bc9ab300ab26 185 // update_gain_shadow(0);
wbeaumont 4:bc9ab300ab26 186 // update_offset_shadow(0);
wbeaumont 1:d2d6341d3e97 187 }
wbeaumont 1:d2d6341d3e97 188
wbeaumont 1:d2d6341d3e97 189 void AD5384::init2(){
wbeaumont 1:d2d6341d3e97 190 u16 ctrlreg=0;
wbeaumont 1:d2d6341d3e97 191 // implecite INT_REF_1250
wbeaumont 1:d2d6341d3e97 192 ctrlreg = REF_SRC_INT & TOGGLE_DISABLE;
wbeaumont 1:d2d6341d3e97 193 set_reg(M_SPEC_R,CTRL_REG_ADDR,ctrlreg);
wbeaumont 1:d2d6341d3e97 194
wbeaumont 1:d2d6341d3e97 195 }
wbeaumont 1:d2d6341d3e97 196
wbeaumont 0:33bb5081488a 197
wbeaumont 0:33bb5081488a 198
wbeaumont 0:33bb5081488a 199 u32 AD5384::soft_clr(){
wbeaumont 0:33bb5081488a 200 return set_reg(M_SPEC_R,0x02,0x2000);
wbeaumont 0:33bb5081488a 201 }
wbeaumont 0:33bb5081488a 202
wbeaumont 0:33bb5081488a 203
wbeaumont 0:33bb5081488a 204 u32 AD5384::soft_rst(){
wbeaumont 0:33bb5081488a 205 return set_reg(M_SPEC_R,0x0F,0x211F);
wbeaumont 0:33bb5081488a 206 }
wbeaumont 0:33bb5081488a 207
wbeaumont 0:33bb5081488a 208
wbeaumont 0:33bb5081488a 209 u32 AD5384::clear_code(){
wbeaumont 0:33bb5081488a 210 return set_reg(M_SPEC_R,0x01,0x2000);
wbeaumont 0:33bb5081488a 211 }
wbeaumont 0:33bb5081488a 212
wbeaumont 4:bc9ab300ab26 213 u16 AD5384::set_gain(u8 ch, u16 gainin ){
wbeaumont 4:bc9ab300ab26 214 set_reg(M_GAIN_R,ch,gainin);
wbeaumont 4:bc9ab300ab26 215 gain[ch]=gainin;
wbeaumont 4:bc9ab300ab26 216 return gainin;
wbeaumont 0:33bb5081488a 217 }
wbeaumont 0:33bb5081488a 218
wbeaumont 4:bc9ab300ab26 219 u16 AD5384::set_offset(u8 ch, u16 gainin ){
wbeaumont 4:bc9ab300ab26 220 set_reg(M_OFFS_R,ch,gainin);
wbeaumont 4:bc9ab300ab26 221 offset[ch]=gainin;
wbeaumont 4:bc9ab300ab26 222 return gainin;
wbeaumont 0:33bb5081488a 223 }
wbeaumont 0:33bb5081488a 224
wbeaumont 0:33bb5081488a 225
wbeaumont 0:33bb5081488a 226 u16 AD5384::set_dac(u8 ch, u16 dac ){
wbeaumont 0:33bb5081488a 227 set_reg(M_DATA_R,ch,dac);
wbeaumont 4:bc9ab300ab26 228 dacr[ch]=dac;
wbeaumont 0:33bb5081488a 229 return dac;
wbeaumont 0:33bb5081488a 230 }
wbeaumont 0:33bb5081488a 231
wbeaumont 1:d2d6341d3e97 232
wbeaumont 1:d2d6341d3e97 233
wbeaumont 1:d2d6341d3e97 234
wbeaumont 0:33bb5081488a 235
wbeaumont 0:33bb5081488a 236 u32 AD5384::set_reg(u8 mode,u8 ch, u16 value ){
wbeaumont 0:33bb5081488a 237 set_spi_mode();
wbeaumont 0:33bb5081488a 238 value=value & 0x3FFF;
wbeaumont 0:33bb5081488a 239 u32 data=format_word(mode,ch,0,value);
wbeaumont 3:7ca85ed310e0 240 cs->write(CS_ACTIVE);
wbeaumont 0:33bb5081488a 241 spi->write(data);
wbeaumont 3:7ca85ed310e0 242 cs->write(CS_DEACTIVE);
wbeaumont 0:33bb5081488a 243 return data;
wbeaumont 0:33bb5081488a 244 }
wbeaumont 0:33bb5081488a 245
wbeaumont 0:33bb5081488a 246 u16 AD5384::get_reg(u8 mode, u8 ch ){
wbeaumont 0:33bb5081488a 247 set_spi_mode();
wbeaumont 0:33bb5081488a 248 u32 data=format_word(mode,ch,1,0);
wbeaumont 3:7ca85ed310e0 249 cs->write(CS_ACTIVE);
wbeaumont 0:33bb5081488a 250 spi->write(data);
wbeaumont 3:7ca85ed310e0 251 cs->write(CS_DEACTIVE);
wbeaumont 0:33bb5081488a 252 wait( .00001);
wbeaumont 3:7ca85ed310e0 253 cs->write(CS_ACTIVE);
wbeaumont 0:33bb5081488a 254 data=spi->write(NOP_INST);
wbeaumont 3:7ca85ed310e0 255 cs->write(CS_DEACTIVE);
wbeaumont 4:bc9ab300ab26 256 return (u16) data &0x3FFF;
wbeaumont 0:33bb5081488a 257 }
wbeaumont 0:33bb5081488a 258
wbeaumont 0:33bb5081488a 259 u16 AD5384::get_gain(u8 ch ){
wbeaumont 0:33bb5081488a 260 return get_reg(M_GAIN_R,ch);
wbeaumont 0:33bb5081488a 261
wbeaumont 0:33bb5081488a 262 }
wbeaumont 0:33bb5081488a 263
wbeaumont 0:33bb5081488a 264 u16 AD5384::get_dac(u8 ch){
wbeaumont 0:33bb5081488a 265 return get_reg(M_DATA_R,ch);
wbeaumont 0:33bb5081488a 266
wbeaumont 0:33bb5081488a 267 }
wbeaumont 0:33bb5081488a 268
wbeaumont 0:33bb5081488a 269
wbeaumont 0:33bb5081488a 270
wbeaumont 0:33bb5081488a 271
wbeaumont 0:33bb5081488a 272 u16 AD5384::get_offset(u8 ch ){
wbeaumont 0:33bb5081488a 273 return get_reg(M_OFFS_R,ch);
wbeaumont 0:33bb5081488a 274
wbeaumont 0:33bb5081488a 275 }
wbeaumont 0:33bb5081488a 276
wbeaumont 0:33bb5081488a 277 u32 AD5384::get_ctrl(){
wbeaumont 1:d2d6341d3e97 278
wbeaumont 0:33bb5081488a 279 return get_reg(M_SPEC_R, 0x0C);
wbeaumont 0:33bb5081488a 280 }
wbeaumont 0:33bb5081488a 281
wbeaumont 0:33bb5081488a 282
wbeaumont 0:33bb5081488a 283
wbeaumont 0:33bb5081488a 284
wbeaumont 0:33bb5081488a 285 u16 AD5384::get_ch_out_reg(u8 ch) {
wbeaumont 0:33bb5081488a 286 u32 data=format_word(M_DATA_R,ch,1,0);
wbeaumont 3:7ca85ed310e0 287 cs->write(CS_ACTIVE);
wbeaumont 0:33bb5081488a 288 spi->write(data);
wbeaumont 3:7ca85ed310e0 289 cs->write(CS_DEACTIVE);
wbeaumont 0:33bb5081488a 290 wait( .00001);
wbeaumont 3:7ca85ed310e0 291 cs->write(CS_ACTIVE);
wbeaumont 0:33bb5081488a 292 data=spi->write(NOP_INST);
wbeaumont 3:7ca85ed310e0 293 cs->write(CS_DEACTIVE);
wbeaumont 4:bc9ab300ab26 294 return (u16) data & 0x3FFF;
wbeaumont 1:d2d6341d3e97 295 }
wbeaumont 1:d2d6341d3e97 296
wbeaumont 3:7ca85ed310e0 297
wbeaumont 3:7ca85ed310e0 298 void AD5384::hw_rst(){
wbeaumont 3:7ca85ed310e0 299 rst->write( RST_ACTIVE); // edge sensitive
wbeaumont 3:7ca85ed310e0 300 wait_us(30);
wbeaumont 3:7ca85ed310e0 301 rst->write( RST_DEACTIVE);
wbeaumont 3:7ca85ed310e0 302 wait_us(300); // 270 us according data sheet
wbeaumont 3:7ca85ed310e0 303
wbeaumont 3:7ca85ed310e0 304 }
wbeaumont 3:7ca85ed310e0 305