OB1203 basic mbed driver

Dependents:   OB1203_IDT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers OB1203.cpp Source File

OB1203.cpp

00001 #include "OB1203.h"
00002 #include "mbed.h"
00003 
00004 extern Serial pc;
00005 
00006 //  //
00007 OB1203::OB1203(I2C *i2c_obj) 
00008 {
00009     i2c = i2c_obj;
00010 }
00011 
00012 
00013 void OB1203::reset()
00014 {
00015     /*POR reset*/
00016     writeRegister(OB1203_ADDR,REG_MAIN_CTRL_0,SW_RESET);
00017     wait_ms(POR_TIME_MS);
00018 }
00019 
00020 
00021 void OB1203::writeRegister(int addr, char reg, char val) {
00022  /*writes 1 byte to a single register*/
00023     char writeData[2];
00024     writeData[0] = reg;
00025     writeData[1] = val;
00026     i2c->write(addr,writeData, 2);
00027 }
00028 
00029 
00030 void OB1203::writeBlock(int addr, char startReg, char *data, char numBytes) {
00031 /*writes data from an array beginning at the startReg*/
00032 //    pc.printf("entering writeBlock with data %02x %02x\r\n",data[0],data[1]);
00033     char writeData[numBytes+1];
00034     writeData[0]=startReg;
00035     for(int n=1;n<numBytes+1;n++) {
00036         writeData[n]=data[n-1];
00037     }
00038     i2c->write(addr,writeData,numBytes+1);
00039 }
00040 
00041 
00042 void OB1203::readBlock(int addr, char startReg, char *data, int numBytes) 
00043 {
00044     char writeData[1];
00045     writeData[0] = startReg;
00046     i2c->write(addr,writeData,1,true);
00047     i2c->read(addr,data,numBytes);
00048 //    wait_us(800);
00049 //    for(int n=0;n<numBytes;n++)
00050 //    {
00051 //        i2c->read(addr,data+n,1,1);
00052 //        wait_us(20);
00053 //    }
00054 }
00055 
00056 uint16_t OB1203::get_status()
00057 {
00058     char writeData[1]; //declare array of size 1
00059     writeData[0] = REG_STATUS_0; 
00060     char data[2]; //declare array of size 1
00061     i2c->write(OB1203_ADDR,writeData,1,true);
00062     i2c->read(OB1203_ADDR,data,2);
00063     return (data[0]<<8 | data[1]);
00064 }
00065 
00066 bool OB1203::dataIsNew()
00067 {
00068     int status_reg_vals;
00069     status_reg_vals = get_status();
00070     return ((status_reg_vals & 0x0100)>>8) || (status_reg_vals & 0x0091);
00071 }
00072 
00073 bool OB1203::lsIsNew()
00074 {
00075     int status_reg_vals;
00076     status_reg_vals = get_status();
00077     return ((status_reg_vals & 0x0100)>>8);
00078 }
00079 
00080 bool OB1203::psIsNew()
00081 {
00082     int status_reg_vals;
00083     status_reg_vals = get_status();
00084     return (status_reg_vals & 0x0001);
00085 }
00086 
00087 bool OB1203::tempIsNew()
00088 {
00089     int status_reg_vals;
00090     status_reg_vals = get_status();
00091     return (status_reg_vals & 0x0080);
00092 }
00093 
00094 bool OB1203::bioIsNew()
00095 {
00096     int status_reg_vals;
00097     status_reg_vals = get_status();
00098     return (status_reg_vals & 0x0010);
00099 }
00100 
00101 void OB1203::setOscTrim()
00102 {
00103     char writeData[1];
00104     writeData[0] = osc_trim;
00105 //    pc.printf("writing %02x to REG %02x\r\n",osc_trim,REG_OSC_TRIM);
00106     writeBlock(OB1203_ADDR,REG_OSC_TRIM,writeData,1);
00107 }
00108 
00109 void OB1203::setMainConfig()
00110 {
00111     char writeData[2];
00112     writeData[0] = ls_sai | ls_mode | ls_en; //MAIN_CTRL_0
00113     writeData[1] = temp_en | ps_sai_en | ppg_ps_mode | ppg_ps_en; //MAIN_CTRL_1
00114 //    pc.printf("main config 1 to write %02x\r\n",writeData[1]);
00115     writeBlock(OB1203_ADDR,REG_MAIN_CTRL_0,writeData,2); 
00116 }
00117 
00118 
00119 void OB1203::setIntConfig()
00120 {
00121     char writeData[3];
00122     writeData[0] =  ls_int_sel | ls_var_mode | ls_int_en;
00123     writeData[1] = afull_int_en | ppg_int_en | ps_logic_mode | ps_int_en;
00124     writeData[2] = ls_persist | ps_persist;
00125     writeBlock(OB1203_ADDR,REG_INT_CFG_0,writeData,3); //default  
00126 }
00127 
00128 
00129 void OB1203::setLSthresh()
00130 {
00131     char writeData[6];
00132     writeData[0] = (char) (ls_thres_hi & 0x000000FF);
00133     writeData[1] = (char) ((ls_thres_hi & 0x0000FF00)>>8);
00134     writeData[2] = (char) ((ls_thres_hi & 0x00FF0000)>>16);
00135     writeData[3] = (char) (ls_thres_lo & 0x000000FF);
00136     writeData[4] = (char) ((ls_thres_lo & 0x0000FF00)>>8);
00137     writeData[5] = (char) ((ls_thres_lo & 0x00FF0000)>>16);
00138     writeBlock(OB1203_ADDR,REG_LS_THRES_HI,writeData,6); //default  
00139 }
00140 
00141 
00142 void OB1203::setPSthresh()
00143 {
00144     char writeData[4];
00145     writeData[0] = (char) (ps_thres_hi & 0x000FF);
00146     writeData[1] = (char) ((ps_thres_hi & 0xFF00)>>8);
00147     writeData[2] = (char) (ps_thres_lo & 0x000FF);
00148     writeData[3] = (char) ((ps_thres_lo & 0xFF00)>>8);
00149     writeBlock(OB1203_ADDR,REG_PS_THRES_HI,writeData,4); //default  
00150 }
00151 
00152 
00153 void OB1203::setPScurrent()
00154 {
00155     char writeData[2];
00156     writeData[0] = (char) (ps_current & 0x00FF);
00157     writeData[1] = (char) ((ps_current & 0xFF00)>>8);
00158     writeBlock(OB1203_ADDR,REG_PS_LED_CURR,writeData,2);
00159 }
00160 
00161 
00162 void OB1203::setPPGcurrent()
00163 {
00164     char writeData[4];
00165     if(led_flip == LED_FLIP_OFF) {
00166         writeData[0] = (char) (ir_current & 0x00FF);
00167         writeData[1] = (char) ((ir_current & 0xFF00)>>8);
00168         writeData[2] = (char) (r_current & 0x00FF);
00169         writeData[3] = (char) ((r_current & 0xFF00)>>8);
00170     } else {
00171         writeData[2] = (char) (ir_current & 0x00FF);
00172         writeData[3] = (char) ((ir_current & 0xFF00)>>8);
00173         writeData[0] = (char) (r_current & 0x00FF);
00174         writeData[1] = (char) ((r_current & 0xFF00)>>8);
00175     }
00176     writeBlock(OB1203_ADDR,REG_PPG_IRLED_CURR,writeData,4);
00177 }
00178 
00179 
00180 void OB1203::setPPG_PSgain_cfg()
00181 {
00182     char writeData[2];
00183     writeData[0] = ppg_ps_gain | ppg_LED_settling | ppg_ALC_track;
00184     writeData[1] = ppg_pow_save | led_flip | sig_out | diff | alc;
00185     writeBlock(OB1203_ADDR,REG_PPG_PS_GAIN,writeData,2);
00186 }
00187 
00188 void OB1203::setPPGana_can()
00189 {
00190     char writeData[1];
00191     writeData[0] = ch1_can_ana | ch2_can_ana;
00192     writeBlock(OB1203_ADDR,REG_PPG_CAN_ANA,writeData,1);
00193 }
00194 
00195 void OB1203::setPPGavg_and_rate()
00196 {
00197     char writeData[2];
00198     writeData[0] = ppg_avg | 0x0A; //use standard LED max settings
00199     writeData[1] = ppg_pwidth | ppg_freq | ppg_rate;
00200     writeBlock(OB1203_ADDR,REG_PPG_AVG,writeData,2);
00201 }
00202 
00203 void OB1203::setBioTrim()
00204 {
00205     char writeData[1];
00206     writeData[0] = bio_trim;
00207     writeBlock(OB1203_ADDR, REG_BIO_TRIM,writeData,1);
00208 }
00209 
00210 void OB1203::setLEDTrim()
00211 {
00212     char writeData[1];
00213     writeData[0] = led_trim;
00214     writeBlock(OB1203_ADDR, REG_LED_TRIM,writeData,1);
00215 }
00216 
00217 void OB1203::setDigTrim()
00218 {
00219     char writeData[2];
00220     writeData[0] = led1_trim;
00221     writeData[1] = led2_trim;
00222     writeBlock(OB1203_ADDR, REG_DIG_LED1_TRIM,writeData,2);
00223 }
00224 
00225 void OB1203::setDigitalCan()
00226 {
00227     char writeData[2];
00228     writeData[0] = (char)(ps_digital_can & 0x00FF);
00229     writeData[1] = (char)((ps_digital_can & 0xFF00)>>8);
00230     writeBlock(OB1203_ADDR,REG_PS_CAN_DIG,writeData,2);
00231 }
00232 
00233 
00234 void OB1203::setFifoConfig()
00235 {
00236     char writeData[1];
00237     writeData[0] = fifo_rollover_en | fifo_afull_advance_warning;
00238     writeBlock(OB1203_ADDR,REG_FIFO_CFG,writeData,1);    
00239 }
00240 
00241 
00242 void OB1203::resetFIFO()
00243 {
00244     char writeData[2];
00245     writeData[0]=0;
00246     writeData[1]=0;
00247     writeBlock(OB1203_ADDR,REG_FIFO_WR_PTR,writeData,2);//set write and read pointer to zero--next sample is newest
00248     writeRegister(OB1203_ADDR,REG_MAIN_CTRL_1, (temp_en | ps_sai_en | ppg_ps_mode | 0) ); //turn PPG off MAIN_CTRL_1;
00249     writeRegister(OB1203_ADDR,REG_MAIN_CTRL_1, (temp_en | ps_sai_en | ppg_ps_mode | ppg_ps_en) ); //MAIN_CTRL_1;
00250 }
00251 
00252 
00253 void OB1203::init_rgb()
00254 {
00255     /*Configures ALS/RGB mode. PS and BIO off.
00256     Use: set class variables using header declarations. Then call this function.*/
00257     char writeData[2];
00258     writeBlock(OB1203_ADDR,REG_LS_RES_RATE,writeData,2);
00259     writeData[0] = ls_res | ls_rate; //LS_RES_RATE
00260     writeData[1] = ls_gain; //LS_GAIN
00261     writeBlock(OB1203_ADDR,REG_LS_RES_RATE,writeData,2);  
00262     setLSthresh(); 
00263     setIntConfig();
00264     ppg_ps_en = PPG_PS_OFF;
00265     ls_en = LS_ON;
00266     setMainConfig();
00267 }
00268 
00269 
00270 void OB1203::init_ps()
00271 {
00272     /*Configures PS mode but not thresholds or interrupts. RGB/ALS and BIO off.
00273     Use: set class variables using header declarations. Then call this function.*/
00274     char writeData[2];  
00275     //PS settings
00276     setPScurrent();
00277     writeData[0] = ps_can_ana | ps_pulses | 0x02; //PS_CAN_PULSES -->set hidden max current registers to allow higher LED powers
00278     writeData[1] = ps_pwidth | ps_rate; //PS_PWIDTH_RATE
00279     writeBlock(OB1203_ADDR,REG_PS_CAN_PULSES,writeData,2);
00280     //Digital crosstalk cancellation
00281     setDigitalCan(); //PS_CAN_DIG
00282     //set PS moving average and hysteresis
00283     writeData[0] = ps_avg_en | ps_hys_level; //PS_MOV_AVG_HYS
00284     writeBlock(OB1203_ADDR,REG_PS_MOV_AVG_HYS,writeData,1);
00285     //set PS interrupt thresholds
00286     setPSthresh();
00287     //interrupt configuration
00288     ls_int_en = LS_INT_OFF;
00289     setIntConfig();
00290     setPPG_PSgain_cfg();
00291     setPScurrent(); 
00292     //config PS
00293     ls_en = LS_OFF;
00294     ppg_ps_en = 1;
00295     ppg_ps_mode = PS_MODE;
00296     //setLEDTrim();
00297     setMainConfig();
00298 }
00299 
00300 
00301 void OB1203::init_ps_rgb()
00302 {
00303     reset();
00304     char writeData[2];
00305     writeData[0] = ls_res | ls_rate; //LS_RES_RATE
00306     writeData[1] = ls_gain; //LS_GAIN
00307     writeBlock(OB1203_ADDR,REG_LS_RES_RATE,writeData,2);
00308     writeData[0] = ps_can_ana | ps_pulses | 0x02; //PS_CAN_PULSES -->set hidden max current registers to allow higher LED powers
00309     writeData[1] = ps_pwidth | ps_rate; //PS_PWIDTH_RATE
00310     writeBlock(OB1203_ADDR,REG_PS_CAN_PULSES,writeData,2);
00311     setDigitalCan(); //PS_CAN_DIG
00312     //set PS moving average and hysteresis
00313     writeData[0] = ps_avg_en | ps_hys_level; //PS_MOV_AVG_HYS
00314     writeBlock(OB1203_ADDR,REG_PS_MOV_AVG_HYS,writeData,1);
00315     setIntConfig();
00316     setPSthresh();
00317     setPScurrent();   
00318     setLSthresh();
00319     ls_en = LS_ON;
00320     ppg_ps_en = PPG_PS_ON;
00321     ppg_ps_mode = PS_MODE;
00322     //setLEDTrim();
00323     setMainConfig();
00324 }
00325 
00326 
00327 void OB1203::init_hr()
00328 {
00329     reset();
00330     ps_int_en = PS_INT_OFF;
00331     ls_en = LS_OFF;
00332     setIntConfig(); 
00333     char readData[1];
00334     //readBlock(OB1203_ADDR,REG_PS_INT_CFG_1,readData,1);
00335 //    pc.printf("int config 1 = %02X\r\n",readData[0]);
00336     setPPG_PSgain_cfg();
00337     setPPGcurrent();
00338     setPPGana_can();
00339     setPPGavg_and_rate();
00340     setFifoConfig(); 
00341     ppg_ps_mode = HR_MODE;
00342     //setBioTrim();
00343     //setLEDTrim();
00344     setDigTrim();
00345     setMainConfig();    
00346 }
00347 
00348 void OB1203::init_spo2()
00349 {
00350     reset();
00351     ps_int_en = PS_INT_OFF;
00352     ls_en = LS_OFF;
00353     setIntConfig(); 
00354     char readData[1];
00355     readBlock(OB1203_ADDR,REG_PS_INT_CFG_1,readData,1);
00356 //    pc.printf("int config 1 = %02X\r\n",readData[0]);
00357     setPPG_PSgain_cfg();
00358     setPPGcurrent();
00359     setPPGana_can();
00360     setPPGavg_and_rate();
00361     setFifoConfig(); 
00362     ppg_ps_mode = SPO2_MODE;
00363     //setLEDTrim();
00364     setDigTrim();
00365     //setBioTrim();
00366     setMainConfig();    
00367 }
00368 
00369 uint32_t OB1203::bytes2uint32(char *data, int start_byte) 
00370 {
00371     //coverts a string of 3 bytes with LSB first into unsigned long MSB last
00372     return ((uint32_t)data[start_byte+2])<<16 | ((uint32_t)data[start_byte+1])<<8 | ((uint32_t)data[start_byte]) ;
00373 }
00374 
00375 uint32_t OB1203::twoandhalfBytes2uint32(char *data, int start_byte) 
00376 {
00377     //coverts a string of 3 bytes with LSB first into unsigned long MSB last
00378     return (uint32_t)( ((data[start_byte+2] & 0x0F)<<16) | (uint32_t(data[start_byte+1])<<8) | uint32_t(data[start_byte]) ) ;
00379 }
00380 
00381 char OB1203::get_ls_data(uint32_t *data)
00382 {  
00383     char byte_data[21];
00384     readBlock(OB1203_ADDR,REG_STATUS_0,byte_data,21);  
00385     #ifdef DEBUG
00386         pc.printf("%02x %02x  %02x %02x  %02x %02x %02x  %02x %02x %02x  %02x %02x %02x  %02x %02x  %02x %02x %02x %02x %02x $02x\r\n",
00387         byte_data[0],byte_data[1],byte_data[2],byte_data[3],
00388         byte_data[4],byte_data[5],byte_data[6],byte_data[7],
00389         byte_data[8],byte_data[9],byte_data[10],byte_data[11],
00390         byte_data[12],byte_data[13],byte_data[14],byte_data[15],
00391         byte_data[16],byte_data[17],byte_data[18]),
00392         byte_data[19],byte_data[20];
00393     #endif
00394      
00395 
00396     //byte_data[0] is ps (not populated)
00397     data[1] = twoandhalfBytes2uint32(byte_data,4); //w
00398     data[2] = twoandhalfBytes2uint32(byte_data,7); //g
00399     data[3] = twoandhalfBytes2uint32(byte_data,10); //b
00400     data[4] = twoandhalfBytes2uint32(byte_data,13); //r
00401     data[5] = twoandhalfBytes2uint32(byte_data,16); //c
00402     data[6] =  (uint32_t)((byte_data[20] & 0x0F)<<8) | (uint32_t)byte_data[19] ; //temp data
00403     return ( (byte_data[0] & LS_NEW_DATA) == 0x01 ? 1 : 0); //return 1 if new data or 0 if old data
00404 }
00405 
00406 char OB1203::get_ps_data(uint32_t *data)
00407 {  
00408     char byte_data[4];
00409     readBlock(OB1203_ADDR,REG_STATUS_0,byte_data,4);  
00410     #ifdef DEBUG
00411         pc.printf( "%02x %02x %02x %02x\r\n", byte_data[0], byte_data[1], byte_data[2], byte_data[3] );
00412     #endif
00413 
00414     data[0] = ((uint32_t)byte_data[3])<<8 | ((uint32_t)byte_data[2]); //ps data
00415     return ( (byte_data[1] & PS_NEW_DATA) == 0x01 ? 1 : 0); //return 1 if new data or 0 if old data
00416 }
00417 
00418 char OB1203::get_ps_ls_data(uint32_t *data)
00419 {  
00420     char byte_data[21];
00421     readBlock(OB1203_ADDR,REG_STATUS_0,byte_data,21);  
00422     #ifdef DEBUG
00423         pc.printf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x $02x\r\n",
00424         byte_data[0],byte_data[1],byte_data[2],byte_data[3],byte_data[4],
00425         byte_data[5],byte_data[6],byte_data[7],byte_data[8],byte_data[9],
00426         byte_data[10],byte_data[11],byte_data[12],byte_data[13],byte_data[14],
00427         byte_data[15],byte_data[16],byte_data[17],byte_data[18] ),
00428         byte_data[19],byte_data[20];
00429     #endif
00430      
00431     data[0] = ((uint32_t)byte_data[3])<<8 | ((uint32_t)byte_data[2]); //ps
00432     data[1] = twoandhalfBytes2uint32(byte_data,4); //w
00433     data[2] = twoandhalfBytes2uint32(byte_data,7); //g
00434     data[3] = twoandhalfBytes2uint32(byte_data,10); //b
00435     data[4] = twoandhalfBytes2uint32(byte_data,13); //r
00436     data[5] = twoandhalfBytes2uint32(byte_data,16); //c
00437     data[6] =  (uint32_t)((byte_data[20] & 0x0F)<<8) | (uint32_t)byte_data[19] ; //temp data
00438     return ( (byte_data[0] & LS_NEW_DATA) == 0x01 ? 1 : 0); //return 1 if new data or 0 if old data
00439 }
00440 
00441 
00442 void OB1203::getFifoInfo(char *fifo_info)
00443 {
00444     readBlock(OB1203_ADDR,REG_FIFO_WR_PTR,fifo_info,3);
00445     writePointer = fifo_info[0];
00446     readPointer = fifo_info[1];
00447     fifoOverflow = fifo_info[2];
00448 }
00449 
00450 
00451 void OB1203::getNumFifoSamplesAvailable(char *fifo_info, char *sample_info)
00452 {
00453     /*sample_info [3] = {numSamplesHR, numSamplesSpO2, overflow*/
00454     
00455     getFifoInfo(fifo_info);
00456     uint8_t writePointer = fifo_info[0];
00457     uint8_t readPointer = fifo_info [1];
00458     uint8_t numSamples = writePointer;
00459     if (writePointer<readPointer)
00460     {
00461         numSamples += 32; 
00462     }
00463     numSamples -= readPointer;
00464     sample_info[0] = numSamples; //num HR samples
00465     sample_info[1] = (numSamples>>1); //num SpO2 samples
00466     sample_info[2] = fifo_info[2];
00467 }
00468 
00469 
00470 void OB1203::getFifoSamples(uint8_t numSamples, char *fifoData)
00471 {
00472     readBlock(OB1203_ADDR,REG_FIFO_DATA,fifoData,3*numSamples);
00473 }
00474 
00475 
00476 void OB1203::parseFifoSamples(char numSamples, char *fifoData, uint32_t *assembledData)
00477 {
00478     for (int n=0; n<numSamples; n++)
00479     {
00480         assembledData[n] = bytes2uint32(fifoData,3*n);
00481     }
00482 }
00483 
00484 
00485 char OB1203::get_part_ID(char *data)
00486 {
00487     readBlock(OB1203_ADDR,REG_PART_ID,data,1);
00488     return data[0];
00489 }
00490 
00491 
00492 void OB1203::do_agc(uint32_t data, bool ch)
00493 {
00494     const uint32_t tol1 = TOL1;
00495     const uint32_t tol2 = TOL2;
00496     const uint16_t in_range_persist = IN_RANGE_PERSIST;
00497     static uint16_t in_range[2] = {0,0};
00498     uint16_t maxCurrent[2];
00499     if(led_flip == LED_FLIP_OFF) {
00500         maxCurrent[0] = IR_MAX_CURRENT;
00501         maxCurrent[1] = R_MAX_CURRENT;
00502     } else {
00503         maxCurrent[0] = R_MAX_CURRENT;
00504         maxCurrent[1] = IR_MAX_CURRENT;
00505     }
00506     const uint16_t step = STEP;
00507     const uint32_t targetCounts[2] = {IR_TARGET_COUNTS, R_TARGET_COUNTS};
00508      //ch = 0 for IR, 1 for R (channel)
00509      if( data > targetCounts[ch] + (in_range[ch]>in_range_persist ? tol2: tol1) )
00510     {       
00511         if(data>targetCounts[ch] + tol2)
00512             in_range[ch]=0;
00513         
00514        
00515         if( (ch ? r_current : ir_current)>step)
00516         {
00517             (ch ? r_current : ir_current) -= step;
00518             update = 1;
00519         }
00520     }
00521     else if( data < targetCounts[ch] - (in_range[ch]>in_range_persist ? tol2 : tol1) )
00522     {
00523         if(data<targetCounts[ch] - tol2)
00524             in_range[ch]=0;
00525         if( (ch ? r_current : ir_current) +step<maxCurrent[ch]) //no need to go to full current
00526         {
00527             (ch ? r_current : ir_current) += step;
00528             update = 1;
00529         }
00530     }
00531     else
00532     {
00533         if( (data > (targetCounts[ch]-tol1) ) && (data < (targetCounts[ch]+tol1)) )
00534             in_range[ch]++;
00535     }
00536 }