OB1203 basic mbed driver
Diff: OB1203.cpp
- Revision:
- 0:2da1f69b38fd
- Child:
- 1:99ca9c464503
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OB1203.cpp Wed Apr 25 05:26:34 2018 +0000 @@ -0,0 +1,366 @@ +#include "OB1203.h" +#include "mbed.h" + +extern Serial pc; + +OB1203::OB1203(I2C *i2c_obj) +{ + i2c = i2c_obj; +} + + +void OB1203::reset() +{ + /*POR reset*/ + writeRegister(OB1203_ADDR,REG_MAIN_CTRL_0,SW_RESET); + wait_ms(POR_TIME_MS); +} + + +void OB1203::writeRegister(int addr, char reg, char val) { + /*writes 1 byte to a single register*/ + char writeData[2]; + writeData[0] = reg; + writeData[1] = val; + i2c->write(addr,writeData, 2); +} + + +void OB1203::writeBlock(int addr, char startReg, char *data, char numBytes) { +/*writes data from an array beginning at the startReg*/ + pc.printf("entering writeBlock with data %02x %02x\r\n",data[0],data[1]); + char writeData[numBytes+1]; + writeData[0]=startReg; + for(int n=1;n<numBytes+1;n++) { + writeData[n]=data[n-1]; + } + i2c->write(addr,writeData,numBytes+1); +} + + +void OB1203::readBlock(int addr, char startReg, char *data, int numBytes) +{ + char writeData[1]; + writeData[0] = startReg; + i2c->write(addr,writeData,1,true); + i2c->read(addr,data,numBytes); +} + + +int OB1203::get_status() +{ + char writeData[1]; //declare array of size 1 + writeData[0] = REG_STATUS_0; + char data[1]; //declare array of size 1 + i2c->write(OB1203_ADDR,writeData,1,true); + i2c->read(OB1203_ADDR,data,2); + return (data[0]<<8 | data[1]); +} + + +void OB1203::setMainConfig() +{ + char writeData[2]; + writeData[0] = ls_sai | ls_mode | ls_en; //MAIN_CTRL_0 + writeData[1] = ps_sai_en | ppg_ps_mode | ppg_ps_en; //MAIN_CTRL_1 + writeBlock(OB1203_ADDR,REG_MAIN_CTRL_0,writeData,2); +} + + +void OB1203::setIntConfig() +{ + char writeData[3]; + writeData[0] = ls_int_sel | ls_var_mode | ls_int_en; + writeData[1] = afull_int_en | ppg_int_en | ps_logic_mode | ps_int_en; + writeData[2] = ls_persist | ps_persist; + writeBlock(OB1203_ADDR,REG_INT_CFG_0,writeData,3); //default +} + + +void OB1203::setLSthresh() +{ + char writeData[6]; + writeData[0] = (char) (ls_thres_hi & 0x000000FF); + writeData[1] = (char) ((ls_thres_hi & 0x0000FF00)>>8); + writeData[2] = (char) (ls_thres_hi & 0x00FF0000)>>16; + writeData[3] = (char) (ls_thres_lo & 0x000000FF); + writeData[4] = (char) ((ls_thres_lo & 0x0000FF00)>>8); + writeData[5] = (char) (ls_thres_lo & 0x00FF0000)>>16; + writeBlock(OB1203_ADDR,REG_LS_THRES_HI,writeData,6); //default +} + + +void OB1203::setPSthresh() +{ + char writeData[4]; + writeData[0] = (char) (ps_thres_hi & 0x000FF); + writeData[1] = (char) ((ps_thres_hi & 0xFF00)>>8); + writeData[0] = (char) (ps_thres_lo & 0x000FF); + writeData[1] = (char) ((ps_thres_lo & 0xFF00)>>8); + writeBlock(OB1203_ADDR,REG_PS_THRES_HI,writeData,4); //default +} + + +void OB1203::setPScurrent() +{ + char writeData[2]; + writeData[0] = (char) (ps_current & 0x00FF); + writeData[1] = (char) ((ps_current & 0xFF00)>>8); + writeBlock(OB1203_ADDR,REG_PS_LED_CURR,writeData,2); +} + + +void OB1203::setPPGcurrent() +{ + char writeData[4]; + writeData[0] = (char) (ir_current & 0x00FF); + writeData[1] = (char) ((ir_current & 0xFF00)>>8); + writeData[2] = (char) (r_current & 0x00FF); + writeData[3] = (char) ((r_current & 0xFF00)>>8); + writeBlock(OB1203_ADDR,REG_PPG_IRLED_CURR,writeData,4); +} + + +void OB1203::setPPG_PSgain_cfg() +{ + char writeData[2]; + writeData[0] = ppg_ps_gain; + writeData[1] = ppg_pow_save | led_flip; + writeBlock(OB1203_ADDR,REG_PPG_PS_GAIN,writeData,2); +} + +void OB1203::setPPGana_can() +{ + char writeData[1]; + writeData[0] = ch1_can_ana | ch2_can_ana; + writeBlock(OB1203_ADDR,REG_PPG_CAN_ANA,writeData,1); +} + +void OB1203::setPPGavg_and_rate() +{ + char writeData[2]; + writeData[0] = ppg_avg; + writeData[1] = ppg_pwidth | ppg_freq | ppg_rate; + writeBlock(OB1203_ADDR,REG_PPG_AVG,writeData,2); +} + + +void OB1203::setDigitalCan() +{ + char writeData[2]; + writeData[0] = (char)(ps_digital_can & 0x00FF); + writeData[1] = (char)((ps_digital_can & 0xFF00)>>8); + writeBlock(OB1203_ADDR,REG_PS_CAN_DIG,writeData,2); +} + + +void OB1203::setFifoConfig() +{ + char writeData[1]; + writeData[0] = fifo_rollover_en | fifo_afull_samples_left; + writeBlock(OB1203_ADDR,REG_FIFO_CFG,writeData,1); +} + + +void OB1203::init_rgb() +{ + /*Configures ALS/RGB mode. PS and BIO off. + Use: set class variables using header declarations. Then call this function.*/ + char writeData[2]; + writeBlock(OB1203_ADDR,REG_LS_RES_RATE,writeData,2); + writeData[0] = ls_res | ls_rate; //LS_RES_RATE + writeData[1] = ls_gain; //LS_GAIN + writeBlock(OB1203_ADDR,REG_LS_RES_RATE,writeData,2); + setLSthresh(); + setIntConfig(); + ppg_ps_en = PPG_PS_OFF; + ls_en = LS_ON; + setMainConfig(); +} + + +void OB1203::init_ps() +{ + /*Configures PS mode but not thresholds or interrupts. RGB/ALS and BIO off. + Use: set class variables using header declarations. Then call this function.*/ + char writeData[2]; + //PS settings + setPScurrent(); + writeData[0] = ps_can_ana | ps_pulses; //PS_CAN_PULSES + writeData[1] = ps_pwidth | ps_rate; //PS_PWIDTH_RATE + writeBlock(OB1203_ADDR,REG_PS_CAN_PULSES,writeData,2); + //Digital crosstalk cancellation + setDigitalCan(); //PS_CAN_DIG + //set PS moving average and hysteresis + writeData[0] = ps_avg_en | ps_hys_level; //PS_MOV_AVG_HYS + writeBlock(OB1203_ADDR,REG_PS_MOV_AVG_HYS,writeData,1); + //set PS interrupt thresholds + setPSthresh(); + //interrupt configuration + ls_int_en = LS_INT_OFF; + setIntConfig(); + setPPG_PSgain_cfg(); + setPScurrent(); + //config PS + ls_en = LS_OFF; + ppg_ps_en = 1; + ppg_ps_mode = PS_MODE; + setMainConfig(); +} + + +void OB1203::init_ps_rgb() +{ + char writeData[2]; + writeBlock(OB1203_ADDR,REG_LS_RES_RATE,writeData,2); + writeData[0] = ls_res | ls_rate; //LS_RES_RATE + writeData[1] = ls_gain; //LS_GAIN + writeBlock(OB1203_ADDR,REG_LS_RES_RATE,writeData,2); + writeData[0] = ps_can_ana | ps_pulses; //PS_CAN_PULSES + writeData[1] = ps_pwidth | ps_rate; //PS_PWIDTH_RATE + writeBlock(OB1203_ADDR,REG_PS_CAN_PULSES,writeData,2); + setDigitalCan(); //PS_CAN_DIG + //set PS moving average and hysteresis + writeData[0] = ps_avg_en | ps_hys_level; //PS_MOV_AVG_HYS + writeBlock(OB1203_ADDR,REG_PS_MOV_AVG_HYS,writeData,1); + setIntConfig(); + setPSthresh(); + setPScurrent(); + setLSthresh(); + ls_en = LS_ON; + ppg_ps_en = PPG_PS_ON; + ppg_ps_mode = PS_MODE; + setMainConfig(); +} + + +void OB1203::init_hr() +{ + setIntConfig(); + setPPG_PSgain_cfg(); + setPPGcurrent(); + setPPGana_can(); + setPPGavg_and_rate(); + setFifoConfig(); + ppg_ps_mode = HR_MODE; + setMainConfig(); +} + +void OB1203::init_spo2() +{ + setIntConfig(); + setPPG_PSgain_cfg(); + setPPGcurrent(); + setPPGana_can(); + setPPGavg_and_rate(); + setFifoConfig(); + ppg_ps_mode = SPO2_MODE; + setMainConfig(); +} + +uint32_t OB1203::bytes2uint32(char *data, int start_byte) +{ + //coverts a string of 3 bytes with LSB first into unsigned long + return uint32_t(data[start_byte+2])<<16 | int32_t(data[start_byte+1])<<8 | int32_t(data[start_byte]) ; +} + + +char OB1203::get_ls_data(uint32_t *data) +{ + char byte_data[19]; + readBlock(OB1203_ADDR,REG_STATUS_0,byte_data,19); + #ifdef DEBUG + pc.printf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\r\n", + byte_data[0],byte_data[1],byte_data[2],byte_data[3], + byte_data[4],byte_data[5],byte_data[6],byte_data[7], + byte_data[8],byte_data[9],byte_data[10],byte_data[11], + byte_data[12],byte_data[13],byte_data[14],byte_data[15], + byte_data[16],byte_data[17],byte_data[18]); + #endif + + //byte_data[0] is status + data[1] = bytes2uint32(byte_data,4); //w + data[2] = bytes2uint32(byte_data,7); //g + data[3] = bytes2uint32(byte_data,10); //b + data[4] = bytes2uint32(byte_data,13); //r + data[5] = bytes2uint32(byte_data,16); //c + + return ( (byte_data[0] & LS_NEW_DATA) == 0x01 ? 1 : 0); //return 1 if new data or 0 if old data +} + +char OB1203::get_ps_data(uint32_t *data) +{ + char byte_data[4]; + readBlock(OB1203_ADDR,REG_STATUS_0,byte_data,19); + #ifdef DEBUG + pc.printf( "%02x %02x %02x %02x\r\n", byte_data[0], byte_data[1], byte_data[2], byte_data[3] ); + #endif + + //byte_data[0] is status + data[0] = ((uint32_t)byte_data[3])<<8 | ((uint32_t)byte_data[2]); + return ( (byte_data[1] & PS_NEW_DATA) == 0x01 ? 1 : 0); //return 1 if new data or 0 if old data +} + +char OB1203::get_ps_ls_data(uint32_t *data) +{ + char byte_data[19]; + readBlock(OB1203_ADDR,REG_STATUS_0,byte_data,19); + #ifdef DEBUG + pc.printf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\r\n", + byte_data[0],byte_data[1],byte_data[2],byte_data[3],byte_data[4], + byte_data[5],byte_data[6],byte_data[7],byte_data[8],byte_data[9], + byte_data[10],byte_data[11],byte_data[12],byte_data[13],byte_data[14], + byte_data[15],byte_data[16],byte_data[17],byte_data[18] ); + #endif + + //byte_data[0] is status + data[0] = ((uint32_t)byte_data[3])<<8 | ((uint32_t)byte_data[2]); + data[1] = bytes2uint32(byte_data,4); //w + data[2] = bytes2uint32(byte_data,7); //g + data[3] = bytes2uint32(byte_data,10); //b + data[4] = bytes2uint32(byte_data,13); //r + data[5] = bytes2uint32(byte_data,16); //c + return ( (byte_data[0] & LS_NEW_DATA) == 0x01 ? 1 : 0); //return 1 if new data or 0 if old data +} + + +void OB1203::getFifoInfo(char *fifo_info) +{ + readBlock(OB1203_ADDR,REG_FIFO_WR_PTR,fifo_info,3); + writePointer = fifo_info[0]; + readPointer = fifo_info[1]; + fifoOverflow = fifo_info[2]; +} + + +uint8_t OB1203::getNumFifoSamplesAvailable() +{ + uint8_t numSamples = writePointer; + if (writePointer<readPointer) + { + numSamples += 31-readPointer; + } + return numSamples; +} + + +void OB1203::getFifoSamples(uint8_t numSamples, char *fifoData) +{ + readBlock(OB1203_ADDR,REG_FIFO_DATA,fifoData,numSamples); +} + + +void OB1203::parseFifoSamples(char numSamples, char *fifoData, uint32_t *assembledData) +{ + for (int n=0; n<numSamples; n++) + { + assembledData[n] = bytes2uint32(fifoData,3*n); + } +} + + +char OB1203::get_part_ID(char *data) +{ + readBlock(OB1203_ADDR,REG_PART_ID,data,1); + return data[0]; +} \ No newline at end of file