control for DAC AD5384 for the SOLID SM1 Slow Control
AD5384.cpp
- Committer:
- wbeaumont
- Date:
- 2015-01-29
- Revision:
- 5:477603ce54a0
- Parent:
- 4:bc9ab300ab26
File content as of revision 5:477603ce54a0:
#include "AD5384.h" #include "mbed.h" #define nrch 40 // nr channels #define p2_14 16384 #define p2_13 8192 #define CS_ACTIVE 1 #define CS_DEACTIVE 0 #define RST_ACTIVE 1 #define RST_DEACTIVE 0 // spi mode has to be set for each transmission as spi bus can be shared /***** * version history * v1.10 initial release version * v1.11 added init 1 and init 2 function an ctrlreg defs * v1.12 * v1.13 corrected channel mask from 0x1F to 0x3F * v1.20 added hw_rst , added hwrst to init1 not in init2 * v1.24 added update shadow registers * v1.26 corrected mask for reading register value * v1.30 added get voltage *V1.31 corrected gain+1 to gain+2 in calculate_dac_setting */ #define AD5384_SRC_VERSION "1.31" #define M_DATA_R 0x3 #define M_OFFS_R 0x2 #define M_GAIN_R 0x1 #define M_SPEC_R 0x0 #define NOP_INST 0x0 // control register bits #define CTRL_REG_ADDR 0x0C #define OUT_PWD_STAT_HIMP 0x2000 //0b10 0000 0000 0000 #define OUT_PWD_STAT_100K 0x1FFF //0b01 1111 1111 1111 #define INT_REF_2500 0X1000 //0b01000000000000 #define INT_REF_1250 0x2FFF //0b10111111111111 #define I_BOOST_ON 0x0800 //0b00100000000000 #define I_BOOST_OFF 0x37FF //0b11011111111111 #define REF_SRC_INT 0x0400 //0b00010000000000 #define REF_SRC_EXT 0x3BFF //0b11 1011 1111 1111 #define MONITOR_MODE_EN 0x0200 //0b00001000000000 #define MONITOR_MODE_DIS 0x3DFF //0b11 1101 1111 1111 #define TEMP_MONITOR_EN 0x0100 //0b00000100000000 #define TEMP_MONITOR_DIS 0x3EFF //0b11 1110 1111 1111 #define TOGGLE_DISABLE 0x3F83 //0b11 1111 1000 0011 AD5384::AD5384(SWSPI *spiinterface ,DigitalOut* chipselect, DigitalOut* reset):getVersion( VERSION_AD5384_HDR,AD5384_SRC_VERSION, __TIME__, __DATE__) { vref=2.5; spi=spiinterface; cs=chipselect; rst=reset; for ( int nc=0 ; nc < nrch; nc++){ gain[nc]=0x3FFE; //power up values offset[nc]=0x2000; dacr[nc]=0x0000; } }; void AD5384::update_gain_shadow(u8 ch ) { if( ch) gain[ch-1] = get_gain(ch-1); else for (u8 chc=0;chc < 40;chc++) { gain[chc] = get_gain(chc); } } void AD5384::update_offset_shadow(u8 ch ) { if( ch) offset[ch-1] = get_offset(ch-1); else for (u8 chc=0;chc < 40;chc++) { offset[chc] = get_offset(chc); } } void AD5384::update_dac_shadow(u8 ch ) { if( ch) dacr[ch-1] = get_dac(ch-1); else for (u8 chc=0;chc < 40;chc++) { dacr[chc] = get_dac(chc); } } u16 AD5384::calculate_dac_setting(u8 nr, float vout ) { //Vout = 2 * Vref * x2 / 2^n => x2 = Vout * 2^14 /(2 * Vref) // x2 is loaded to the DAC string // x1 is the 14 bit DAC wordt written to the DAC input register float x2= vout * (float)p2_14 /(2 *vref); // x2 = [(gain+2)/2^n * x1] + offset-2^13 // x1 = 2^14/(gain+2) * [ x2 - offset+2^13 ] u16 x1 = (float)p2_14/((float)gain[nr]+2) *( x2- offset[nr]+p2_13); x1= 0x3FFF & x1; dacr[nr]=x1 ; return x1; }; u32 AD5384::format_word(u8 mode,u8 ch,u8 rw,u16 data) { // MSB set to 0 , toggle mode not supported u32 shift = (u32) rw&1; u32 word= shift << 22; shift= (u32)(ch &0x3F); shift = shift << 16; word = word | shift; shift= (u32)(mode & 0x3); shift = shift << 14; word = word | shift; word = word | (data & 0x3FFF); return word; } void AD5384::set_spi_mode(){ spi->format(24,1); spi->frequency(10000000); } u16 AD5384::set_volt(u8 ch, float vout ){ volt[ch]=vout; u16 dacin=calculate_dac_setting(ch, vout ); set_spi_mode(); u32 data=format_word(M_DATA_R,ch,0,dacin); cs->write(CS_ACTIVE); spi->write(data); cs->write(CS_DEACTIVE); dacr[ch]=dacin; return dacin; } float AD5384::get_volt(u8 nr, bool readallreg ) { u16 lgain; u16 loffset; u16 ldac=get_ch_out_reg(nr); dacr[nr]=ldac; if( readallreg) { lgain= get_gain(nr); gain[nr]=lgain; loffset=get_offset(nr); offset[nr]=loffset; } else { lgain=gain[nr]; loffset=offset[nr];} //Vout = 2 * Vref * x2 / 2^n x2= [x1*(m+2)]/2^n ]+ (c-2^(n-1)) float x2= ((float)(lgain+2)/(float)p2_14)*(float) ldac + loffset- p2_13; float vout = 2 *vref * x2 / p2_14; return vout; } void AD5384::init1(){ u16 ctrlreg=0; hw_rst(); ctrlreg = (INT_REF_2500 | REF_SRC_INT ) & TOGGLE_DISABLE; set_reg(M_SPEC_R,CTRL_REG_ADDR,ctrlreg); wait_us(100); // update_dac_shadow(0); // update_gain_shadow(0); // update_offset_shadow(0); } void AD5384::init2(){ u16 ctrlreg=0; // implecite INT_REF_1250 ctrlreg = REF_SRC_INT & TOGGLE_DISABLE; set_reg(M_SPEC_R,CTRL_REG_ADDR,ctrlreg); } u32 AD5384::soft_clr(){ return set_reg(M_SPEC_R,0x02,0x2000); } u32 AD5384::soft_rst(){ return set_reg(M_SPEC_R,0x0F,0x211F); } u32 AD5384::clear_code(){ return set_reg(M_SPEC_R,0x01,0x2000); } u16 AD5384::set_gain(u8 ch, u16 gainin ){ set_reg(M_GAIN_R,ch,gainin); gain[ch]=gainin; return gainin; } u16 AD5384::set_offset(u8 ch, u16 gainin ){ set_reg(M_OFFS_R,ch,gainin); offset[ch]=gainin; return gainin; } u16 AD5384::set_dac(u8 ch, u16 dac ){ set_reg(M_DATA_R,ch,dac); dacr[ch]=dac; return dac; } u32 AD5384::set_reg(u8 mode,u8 ch, u16 value ){ set_spi_mode(); value=value & 0x3FFF; u32 data=format_word(mode,ch,0,value); cs->write(CS_ACTIVE); spi->write(data); cs->write(CS_DEACTIVE); return data; } u16 AD5384::get_reg(u8 mode, u8 ch ){ set_spi_mode(); u32 data=format_word(mode,ch,1,0); cs->write(CS_ACTIVE); spi->write(data); cs->write(CS_DEACTIVE); wait( .00001); cs->write(CS_ACTIVE); data=spi->write(NOP_INST); cs->write(CS_DEACTIVE); return (u16) data &0x3FFF; } u16 AD5384::get_gain(u8 ch ){ return get_reg(M_GAIN_R,ch); } u16 AD5384::get_dac(u8 ch){ return get_reg(M_DATA_R,ch); } u16 AD5384::get_offset(u8 ch ){ return get_reg(M_OFFS_R,ch); } u32 AD5384::get_ctrl(){ return get_reg(M_SPEC_R, 0x0C); } u16 AD5384::get_ch_out_reg(u8 ch) { u32 data=format_word(M_DATA_R,ch,1,0); cs->write(CS_ACTIVE); spi->write(data); cs->write(CS_DEACTIVE); wait( .00001); cs->write(CS_ACTIVE); data=spi->write(NOP_INST); cs->write(CS_DEACTIVE); return (u16) data & 0x3FFF; } void AD5384::hw_rst(){ rst->write( RST_ACTIVE); // edge sensitive wait_us(30); rst->write( RST_DEACTIVE); wait_us(300); // 270 us according data sheet }