![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Export to MBED Studio for DISCO Board
OPT3101device_Functions.cpp
- Committer:
- tgrosch
- Date:
- 2020-10-25
- Revision:
- 0:62b846b3988a
File content as of revision 0:62b846b3988a:
/*! * \file OPT3101device_Functions.cpp * \author Karthik Rajagopal <krthik@ti.com> * \version 0.9.1 * * \section COPYRIGHT * TEXAS INSTRUMENTS TEXT FILE LICENSE * Copyright (c) 2018 Texas Instruments Incorporated * All rights reserved not granted herein. * Limited License. * Texas Instruments Incorporated grants a world-wide, royalty-free, non-exclusive license under copyrights and patents it now or hereafter owns or controls to make, have made, use, import, offer to sell and sell ("Utilize") this software subject to the terms herein. With respect to the foregoing patent license, such license is granted solely to the extent that any such patent is necessary to Utilize the software alone. The patent license shall not apply to any combinations which include this software, other than combinations with devices manufactured by or for TI ("TI Devices"). No hardware patent is licensed hereunder. * Redistributions must preserve existing copyright notices and reproduce this license (including the above copyright notice and the disclaimer and (if applicable) source code license limitations below) in the documentation and/or other materials provided with the distribution * Redistribution and use in binary form, without modification, are permitted provided that the following conditions are met: * * No reverse engineering, decompilation, or disassembly of this software is permitted with respect to any software provided in binary form. * * any redistribution and use are licensed by TI for use only with TI Devices. * * Nothing shall obligate TI to provide you with source code for the software licensed and provided to you in object code. * If software source code is provided to you, modification and redistribution of the source code are permitted provided that the following conditions are met: * * any redistribution and use of the source code, including any resulting derivative works, are licensed by TI for use only with TI Devices. * * any redistribution and use of any object code compiled from the source code and any resulting derivative works, are licensed by TI for use only with TI Devices. * Neither the name of Texas Instruments Incorporated nor the names of its suppliers may be used to endorse or promote products derived from this software without specific prior written permission. * DISCLAIMER. * THIS SOFTWARE IS PROVIDED BY TI AND TI'S LICENSORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TI AND TI'S LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * \section DESCRIPTION * The file contains methods definitions for classes OPT3101::device OPT3101::frameData OPT3101::calibrationC */ #include "OPT3101device.h" //#include "definitions.h" void OPT3101::device::reset() { /// <b>Algorithm of the method is as follows</b> host.printf("INFO::Resetting Host\r\n"); host.resetDevice(); ///* Invokes the hostController::reset method host.sleep(100); } void OPT3101::device::liveDataView(uint32_t nFrames,uint32_t refreshDelayinms,bool scroll){ uint32_t c0; uint8_t c1; OPT3101::frameData data; host.printf("\r\n"); for(c1=0;c1<3;c1++) host.printf("|Distmm, Phase,Amplud,SigS,AmbS,HDR|--"); host.printf("|Amb,Cntr,Tmain,Tillum | Count/Total |"); host.printf("\r\n"); for(c0=0;c0<nFrames;c0++){ data.capture(&host, this,this->calibration->extTempSensor_connected); this->data[data.ledChannel]=data; for(c1=0;c1<3;c1++){ if(this->data[c1].sigovl || this->data[c1].ambovl) host.printfSetColor(0b100); else host.printfSetColor(0b010); host.printf("|%06u,",(this->data[c1].phase*14989)>>16); host.printf("%06u,",this->data[c1].phase); host.printf("%06u,",this->data[c1].amplitude); host.printf(" %1u,",this->data[c1].sigovl); host.printf(" %1u,",this->data[c1].ambovl); host.printf(" %1u|--",this->data[c1].illumDac); } host.printfSetColor(0xFF); host.printf("|%03d,",data.ambient); host.printf("0x%02x,",data.frameCounter); host.printf(" %+03d,",(int32_t) (((int32_t)data.tmain>>3)-256)); host.printf("%+07.4f|",((double)data.tillum/16-128)); host.printf("%07u",c0); host.printf("/%07u|\r",nFrames); if(scroll) host.printf("\n"); host.sleep(refreshDelayinms); } host.printf("\n"); } void OPT3101::device::resetInitAndViewData(uint32_t nFrames,bool loadCalibration){ this->reset(); host.sleep(5000); this->initialize(); this->measureAndCorrectInternalCrosstalk(&this->calibration->internalCrosstalk[0]); ///* Calls method OPT3101::device::measureAndCorrectInternalCrosstalk with argument OPT3101::calibrationC::internalCrosstalk this->calibration->internalCrosstalk[0].printHeader(); ///* Calls the method OPT3101::crosstalkC::report for debug and data analysis this->calibration->internalCrosstalk[0].print(); ///* Calls the method OPT3101::crosstalkC::report for debug and data analysis host.printf("\r\n"); if(loadCalibration){ this->manuallySetIllumCrosstalkTempCoffs(); this->manuallySetPhaseTempCoffs(); this->manuallySetPhaseAmbientCoffs(); this->loadIllumCrosstalkSet(true); this->loadIllumCrosstalkTempCoffSet(); this->loadPhaseOffsetSet(true); this->loadPhaseOffsetTempCoffSet(); this->loadPhaseAmbientCoffSet(); } this->liveDataView(nFrames, this->configurationFlags_frameTimeInMilliSeconds, false); } bool OPT3101::device::validateI2C() { /// <b>Algorithm of the method is as follows</b> uint32_t data; bool status; //0x8001A0 //data=0xA001802E //data[0]=0x8; //data[1]=001A0 status = 0; host.printf("INFO::Validating I2C Transaction\r\n"); //#ifdef TIMSP430F5529_LAUNCHPAD_CALIBRATION_TOOL status=host.i2c.read(0x2E,&data); if(status){ host.printfSetColor(0b010); host.printf("INFO::I2C Transaction Successful\r\n"); host.printfSetColor(0xFF); } else{ host.printfSetColor(0b100); host.printf("EROR::I2C Transaction Failed. Please check Connection\r\n"); host.printfSetColor(0xFF); } return status; //#endif //#ifndef TIMSP430F5529_LAUNCHPAD_CALIBRATION_TOOL // host.printfSetColor(0b110); // host.printf("WARN::I2C Status checking not implemented\r\n"); // host.printfSetColor(0xFF); // return true; //#endif } bool OPT3101::device::validateDesignID() { /// <b>Algorithm of the method is as follows</b> uint32_t data[2]; bool status; status = 0; host.printf("INFO::Validating OPT3101 Design ID\r\n"); this->reg.iq_read_data_sel=4; data[0]=host.readI2C(0x3b); this->reg.iq_read_data_sel=5; data[1]=host.readI2C(0x3b); if(data[0]==0x100411 && data[1]==0xc01000){ status=true; host.printfSetColor(0b010); host.printf("INFO::Design ID 0x%06lx%06lx Verified\r\n",data[1],data[0]); host.printfSetColor(0xFF); } else{ status=false; host.printfSetColor(0b110); host.printf("WARN::Design ID 0x%06lx%06lx Not Maching\r\n",data[1],data[0]); host.printfSetColor(0xFF); } this->reg.iq_read_data_sel=0; return status; } void OPT3101::device::measureAndCorrectInternalCrosstalk(OPT3101::crosstalkC *internalXtalk){ /// <b>Algorithm of the method is as follows</b> uint8_t regStore[5]; regStore[0]=this->reg.en_adaptive_hdr.read(); regStore[1]=this->reg.hdr_mode.read(); regStore[2]=this->reg.en_sequencer.read(); ///* Critical registers which are modified in this method are read from the h/w and temporarily buffered to local variables. regStore[3]=this->reg.en_processor_values.read(); ///* Temporarily buffered register states are restored to the h/w with register writes while exiting this method. this->reg.tg_en=0; this->reg.en_adaptive_hdr=0; this->reg.hdr_mode=0; this->reg.en_sequencer=0; this->reg.en_processor_values=0; this->reg.tg_en=1; this->reg.use_xtalk_reg_int=0; this->reg.int_xtalk_calib=1; ///* Enables internal crosstalk measure and correct register OPT3101::registers::int_xtalk_calib host.printf("INFO::Performing Internal Cross talk Measurement...\r\n"); host.sleep(this->configurationFlags_xtalkSettlingOneTauInMilliSeconds<<3); ///* Sleeps the host for 8 times the OPT3101::device::configurationFlags_xtalkSettlingOneTauInMilliSeconds so that device settles /* host.sleepDataReadyCounts(this->configurationFlags_xtalkSettlingOneTauInDataReadyCounts<<3); */ ///* Sleep delay can be replaced with wait for 8 times the OPT3101::device::configurationFlags_xtalkSettlingOneTauInDataReadyCounts data ready pulses.User needs to implement based on host configuration this->reg.int_xtalk_calib=0; ///* Disables internal crosstalk measure register OPT3101::registers::int_xtalk_calib to complete internal crosstalk measurement regStore[4]=this->reg.iq_read_data_sel.read(); this->reg.iq_read_data_sel=0; internalXtalk->readCrosstalkRegisters(this); ///* Reads the internal crosstalk registers OPT3101::registers::iphase_xtalk and OPT3101::registers::qphase_xtalk and assigns to internalXtalk input instance pointer of type OPT3101::crosstalkC class this->reg.iq_read_data_sel=regStore[4]; this->reg.tg_en=0; this->reg.en_adaptive_hdr=regStore[0]; this->reg.hdr_mode=regStore[1]; this->reg.en_sequencer=regStore[2]; this->reg.en_processor_values=regStore[3]; ///* Restores the device state to the same state as before entering this method from the buffered local variables this->reg.tg_en=1; host.printf("INFO::Internal Cross talk Measurement Completed\r\n"); } void OPT3101::device::measureIllumCrosstalk(OPT3101::crosstalkC *illumXtalk) { uint8_t regStore[2]; /// <b>Algorithm of the method is as follows</b> regStore[0] = this->reg.use_xtalk_reg_illum.read(); this->reg.use_xtalk_reg_illum = 0; this->reg.illum_xtalk_calib = 1; ///* Enables illum crosstalk measure register OPT3101::registers::illum_xtalk_calib host.sleep(this->configurationFlags_xtalkSettlingOneTauInMilliSeconds << 3); ///* Sleeps the host for 8 times the OPT3101::device::configurationFlags_xtalkSettlingOneTauInMilliSeconds so that device settles // The same can be replated with // host.sleepDataReadyCounts(this->configurationFlags_xtalkSettlingOneTauInDataReadyCounts<<3); // This is for 8 Tau settings ///* Sleep delay can be replaced with wait for 8 times the OPT3101::device::configurationFlags_xtalkSettlingOneTauInDataReadyCounts data ready pulses.User needs to implement based on host configuration this->reg.illum_xtalk_calib = 0; //Wait Time regStore[1] = this->reg.iq_read_data_sel.read(); ///* Reads the internal crosstalk registers OPT3101::registers::iphase_xtalk and OPT3101::registers::qphase_xtalk and assigns to illumXtalk input instance pointer of type OPT3101::crosstalkC class this->reg.iq_read_data_sel = 1; illumXtalk->readCrosstalkRegisters(this); illumXtalk->illumXtalk = true; this->reg.iq_read_data_sel = regStore[1]; this->reg.use_xtalk_reg_illum = regStore[0]; illumXtalk->readTemperatureMain(this); ///* Reads main temp sensor and captures the same to input argument illumXtalk's OPT3101::crosstalkC::tmain illumXtalk->readTemperatureIllum(this); ///* Reads external temp sensor and captures the same to input argument illumXtalk's OPT3101::crosstalkC::tillum } void OPT3101::device::measureIllumCrosstalkSet(bool saveToFile) { uint8_t c0, c1; uint16_t flashLocation; #ifdef OPT3101_USE_STDIOLIB char fileName[FILENAME_LENGTH]; #endif envController.setTargetToInfinity_OR_coverPhotodiode(); ///* Calls the method environmentalController::setTargetToInfinity_OR_coverPhotodiode , which is expected to set the environment so as to be able to measure illumination crosstalk // Loop to iterate over all TX channels for (c0 = 0; c0 < 3; c0++) { ///* Loops though all the valid TX channel and register set configurations if (this->configurationFlags_isTXChannelActive[c0]) { // Checking is TX channel is active for this profile for (c1 = 0; c1 < 2; c1++) { // Loop to iterate over the H/L registers if (this->configurationFlags_isRegisterSetActive[c1]) { // Checking if registers are active for this profile host.printf("INFO:Performing Illum Crosstalk for TX%d HDR %d\r\n",c0,c1); this->measureIllumCrosstalk(&this->calibration->illumCrosstalk[c0][c1], c0, c1 ? 'h' : 'l'); ///* Calls method OPT3101::device::measureIllumCrosstalk with argument OPT3101::calibrationC::illumCrosstalk this->calibration->illumCrosstalk[c0][c1].printHeader(); ///* Calls the method OPT3101::crosstalkC::report for debug and data analysis this->calibration->illumCrosstalk[c0][c1].print(); ///* Calls the method OPT3101::crosstalkC::report for debug and data analysis host.printf("\r\n"); // Provide file name if save to File is implemented eg: illumCrosstalkTX{txChannel}Reg{regSet}_roomTemp if(saveToFile){ #ifdef OPT3101_USE_STDIOLIB sprintf(fileName, "%s/illumCrosstalk_TX%d_%c.txt", filePath, c0, c1 ? 'h' : 'l'); ///* Creates filename illumCrosstalk_TX{channel}_{h/l}.txt in path filePath this->calibration->illumCrosstalk[c0][c1].storeToFile(fileName); ///* Calls method OPT3101::crosstalkC::storeToFile to store the data #endif #ifdef TIMSP430F5529_LAUNCHPAD_CALIBRATION_TOOL flashLocation=(c1+(c0<<1))<<4; //TODO fix this host.flash.write(flashLocation, (uint8_t*)&this->calibration->illumCrosstalk[c0][c1] ,16); host.printf("INFO:Writing Illum Cross talk for TX%d HDR %d to Flash location 0x%04x\r\n",c0,c1,flashLocation); #endif // TIHOST } #ifdef TIMSP430F5529_LAUNCHPAD_CALIBRATION_TOOL if(this->calibration->illumCrosstalk[c0][c1].magnitude()>800) host.printf("WARN:Illumination Cross talk is very high. Check if Photo diode is covered well.. if so increase [force_scale_val] register by 1 count and add it to initialization method\r\n",flashLocation); #endif // TIHOST } } } } host.printf("INFO:Completed Illumination cross talk measurement for all channels\r\n"); } void OPT3101::device::measureIllumCrosstalk( OPT3101::crosstalkC *illumXtalk, uint8_t txChannel, char registerSet,uint8_t shiftIllumPhase) { uint8_t regStore[8]; /// <b>Algorithm of the method is as follows</b> regStore[0] = this->reg.en_sequencer.read(); ///* Critical registers which are modified in this method are read from the h/w and temporarily buffered to local variables. regStore[1] = this->reg.en_processor_values.read(); regStore[2] = this->reg.sel_hdr_mode.read(); regStore[3] = this->reg.sel_tx_ch.read(); regStore[4] = this->reg.en_adaptive_hdr.read(); regStore[5] = this->reg.en_tx_switch.read(); regStore[6] = this->reg.shift_illum_phase.read(); regStore[7] = this->reg.en_temp_xtalk_corr.read(); this->reg.tg_en = 0; this->reg.en_sequencer = 0; this->reg.en_processor_values = 0; if (registerSet == 'h') this->reg.sel_hdr_mode = 1; ///* Register set is chosen based on registerSet input to this method by setting OPT3101::registers::sel_hdr_mode if (registerSet == 'l') this->reg.sel_hdr_mode = 0; this->reg.sel_tx_ch = txChannel; ///* TX channel is chosen based on txChannel input to this method by setting OPT3101::registers::sel_tx_ch this->reg.en_tx_switch = 0; this->reg.en_adaptive_hdr = 0; this->reg.shift_illum_phase = shiftIllumPhase; ///* Sets up the OPT3101::registers::shift_illum_phase based on the input to this method shiftIllumPhase this->reg.tg_en = 1; this->measureIllumCrosstalk(illumXtalk); ///* Measures illum crosstalk from registers OPT3101::registers::iphase_xtalk , and OPT3101::registers::qphase_xtalk and assigns to illumXtalk instance pointer of type OPT3101::crosstalkC class illumXtalk->illumDCdac = this->reg.ILLUM_DC_CURR_DAC.read(); illumXtalk->shiftIllumPhase = shiftIllumPhase; ///* Takes snapshot of device TX register configuration and assign them to illumXtalk instance pointer of type OPT3101::crosstalkC class switch (txChannel) { case 0: if (registerSet == 'h') { illumXtalk->illumDac = this->reg.illum_dac_h_tx0.read(); illumXtalk->illumScale = this->reg.illum_scale_h_tx0.read(); } else if (registerSet == 'l') { illumXtalk->illumDac = this->reg.illum_dac_l_tx0.read(); illumXtalk->illumScale = this->reg.illum_scale_l_tx0.read(); } break; case 1: if (registerSet == 'h') { illumXtalk->illumDac = this->reg.illum_dac_h_tx1.read(); illumXtalk->illumScale = this->reg.illum_scale_h_tx1.read(); } else if (registerSet == 'l') { illumXtalk->illumDac = this->reg.illum_dac_l_tx1.read(); illumXtalk->illumScale = this->reg.illum_scale_l_tx1.read(); } break; case 2: if (registerSet == 'h') { illumXtalk->illumDac = this->reg.illum_dac_h_tx2.read(); illumXtalk->illumScale = this->reg.illum_scale_h_tx2.read(); } else if (registerSet == 'l') { illumXtalk->illumDac = this->reg.illum_dac_l_tx2.read(); illumXtalk->illumScale = this->reg.illum_scale_l_tx2.read(); } break; default: break; } //printf("Illum Cross-talk for Illum current [%d] Magnitude is %4.2f [%d][%d][%d]\n", i, InternalXtalk.magnitude(), InternalXtalk.I, InternalXtalk.Q, InternalXtalk.xtalkScale); this->reg.tg_en = 0; this->reg.en_sequencer = regStore[0]; this->reg.en_processor_values = regStore[1]; this->reg.sel_hdr_mode = regStore[2]; this->reg.sel_tx_ch = regStore[3]; this->reg.en_adaptive_hdr = regStore[4]; this->reg.en_tx_switch = regStore[5]; this->reg.shift_illum_phase = regStore[6]; this->reg.en_temp_xtalk_corr = regStore[7]; ///* Restores the device state to the same state as before entering this method from the buffered local variables this->reg.tg_en = 1; } void OPT3101::device::loadIllumCrosstalk(OPT3101::crosstalkC *illumXtalk, uint8_t txChannel, char registerSet) { uint8_t maxIllumXtalkScale; /// <b>Algorithm of the method is as follows</b> maxIllumXtalkScale = illumXtalk->commonScale; ///* Load the common to all TX channels/register set registers (like for eg OPT3101::registers::illum_xtalk_reg_scale) to the h/w from the method input argument illumXtalk this->reg.illum_xtalk_reg_scale = illumXtalk->commonScale; this->reg.shift_illum_phase = illumXtalk->shiftIllumPhase; //printf("Scale reduction is [%d] [%d] [%d] \n", illumXtalk->I, maxIllumXtalkScale - illumXtalk->xtalkScale, illumXtalk->I >>(maxIllumXtalkScale - illumXtalk->xtalkScale)); switch (txChannel) { ///* Based on txChannel and registerSet argument the the method loads the OPT3101::crosstalkC::I, OPT3101::crosstalkC::Q, OPT3101::crosstalkC::tmain and OPT3101::crosstalkC::tillum to device h/w specified TX channels and register set case 0: ///* for eg: then txChannel=1 and registerSet='l' then the method loads the argument illumXtalk's OPT3101::crosstalkC::I to OPT3101::registers::iphase_xtalk_reg_hdr0_tx1 . Similarly the qphase_reg* registers, OPT3101::registers::tmain_calib_hdr0_tx1 and OPT3101::registers::tillum_calib_hdr0_tx1 are loaded from the input argument illumXtalk's OPT3101::crosstalkC::tmain and OPT3101::crosstalkC::tillum if (registerSet == 'h') { this->reg.iphase_xtalk_reg_hdr1_tx0 = (uint16_t) (illumXtalk->I >> (maxIllumXtalkScale - illumXtalk->xtalkScale)); this->reg.qphase_xtalk_reg_hdr1_tx0 = (uint16_t) (illumXtalk->Q >> (maxIllumXtalkScale - illumXtalk->xtalkScale)); this->reg.tmain_calib_hdr1_tx0 = illumXtalk->tmain; this->reg.tillum_calib_hdr1_tx0 = illumXtalk->tillum; } else if (registerSet == 'l') { this->reg.iphase_xtalk_reg_hdr0_tx0 = (uint16_t)(illumXtalk->I >> (maxIllumXtalkScale - illumXtalk->xtalkScale)); this->reg.qphase_xtalk_reg_hdr0_tx0 = (uint16_t)(illumXtalk->Q >> (maxIllumXtalkScale - illumXtalk->xtalkScale)); this->reg.tmain_calib_hdr0_tx0 = illumXtalk->tmain; this->reg.tillum_calib_hdr0_tx0 = illumXtalk->tillum; } break; case 1: if (registerSet == 'h') { this->reg.iphase_xtalk_reg_hdr1_tx1 = (uint16_t)(illumXtalk->I >> (maxIllumXtalkScale - illumXtalk->xtalkScale)); this->reg.qphase_xtalk_reg_hdr1_tx1 = (uint16_t)(illumXtalk->Q >> (maxIllumXtalkScale - illumXtalk->xtalkScale)); this->reg.tmain_calib_hdr1_tx1 = illumXtalk->tmain; this->reg.tillum_calib_hdr1_tx1 = illumXtalk->tillum; } else if (registerSet == 'l') { this->reg.iphase_xtalk_reg_hdr0_tx1 = (uint16_t)(illumXtalk->I >> (maxIllumXtalkScale - illumXtalk->xtalkScale)); this->reg.qphase_xtalk_reg_hdr0_tx1 = (uint16_t)(illumXtalk->Q >> (maxIllumXtalkScale - illumXtalk->xtalkScale)); this->reg.tmain_calib_hdr0_tx1 = illumXtalk->tmain; this->reg.tillum_calib_hdr0_tx1 = illumXtalk->tillum; } break; case 2: if (registerSet == 'h') { this->reg.iphase_xtalk_reg_hdr1_tx2 = (uint16_t)(illumXtalk->I >> (maxIllumXtalkScale - illumXtalk->xtalkScale)); this->reg.qphase_xtalk_reg_hdr1_tx2 = (uint16_t)(illumXtalk->Q >> (maxIllumXtalkScale - illumXtalk->xtalkScale)); this->reg.tmain_calib_hdr1_tx2 = illumXtalk->tmain; this->reg.tillum_calib_hdr1_tx2 = illumXtalk->tillum; } else if (registerSet == 'l') { this->reg.iphase_xtalk_reg_hdr0_tx2 = (uint16_t)(illumXtalk->I >> (maxIllumXtalkScale - illumXtalk->xtalkScale)); this->reg.qphase_xtalk_reg_hdr0_tx2 = (uint16_t)(illumXtalk->Q >> (maxIllumXtalkScale - illumXtalk->xtalkScale)); this->reg.tmain_calib_hdr0_tx2 = illumXtalk->tmain; this->reg.tillum_calib_hdr0_tx2 = illumXtalk->tillum; } break; default: break; } } void OPT3101::device::loadPhaseOffset(OPT3101::phaseOffsetC *phaseOffset, uint8_t txChannel, char registerSet) { /// <b>Algorithm of the method is as follows</b> //printf("Scale reduction is [%d] [%d] [%d] \n", illumXtalk->I, maxIllumXtalkScale - illumXtalk->xtalkScale, illumXtalk->I >>(maxIllumXtalkScale - illumXtalk->xtalkScale)); this->reg.en_phase_corr = 1; ///* Enables the phase offset correction register OPT3101::registers::en_phase_corr switch (txChannel) { ///* Based on txChannel and registerSet argument the the method loads the OPT3101::phaseOffsetC::phaseOffset, OPT3101::phaseOffsetC::frameData::tmain and OPT3101::phaseOffsetC::frameData::tillum to device h/w specified TX channels and register set case 0: ///* for eg: then txChannel=1 and registerSet='l' then the method loads the argument phaseOffset's OPT3101::phaseOffsetC::phaseOffset to OPT3101::registers::phase_offset_hdr0_tx1 OPT3101::registers::tmain_calib_hdr0_tx1 and OPT3101::registers::tillum_calib_hdr0_tx1 are loaded from the input argument phaseOffset's OPT3101::phaseOffsetC::frameData::tmain and OPT3101::phaseOffsetC::frameData::tillum if (registerSet == 'h') { this->reg.phase_offset_hdr1_tx0 = phaseOffset->phaseOffset; this->reg.tmain_calib_hdr1_tx0 = phaseOffset->data.tmain; this->reg.tillum_calib_hdr1_tx0 = phaseOffset->data.tillum; } else if (registerSet == 'l') { this->reg.phase_offset_hdr0_tx0 = phaseOffset->phaseOffset; this->reg.tmain_calib_hdr0_tx0 = phaseOffset->data.tmain; this->reg.tillum_calib_hdr0_tx0 = phaseOffset->data.tillum; } break; case 1: if (registerSet == 'h') { this->reg.phase_offset_hdr1_tx1 = phaseOffset->phaseOffset; this->reg.tmain_calib_hdr1_tx1 = phaseOffset->data.tmain; this->reg.tillum_calib_hdr1_tx1 = phaseOffset->data.tillum; } else if (registerSet == 'l') { this->reg.phase_offset_hdr0_tx1 = phaseOffset->phaseOffset; this->reg.tmain_calib_hdr0_tx1 = phaseOffset->data.tmain; this->reg.tillum_calib_hdr0_tx1 = phaseOffset->data.tillum; } break; case 2: if (registerSet == 'h') { this->reg.phase_offset_hdr1_tx2 = phaseOffset->phaseOffset; this->reg.tmain_calib_hdr1_tx2 = phaseOffset->data.tmain; this->reg.tillum_calib_hdr1_tx2 = phaseOffset->data.tillum; } else if (registerSet == 'l') { this->reg.phase_offset_hdr0_tx2 = phaseOffset->phaseOffset; this->reg.tmain_calib_hdr0_tx2 = phaseOffset->data.tmain; this->reg.tillum_calib_hdr0_tx2 = phaseOffset->data.tillum; } break; default: break; } } void OPT3101::device::loadIllumCrosstalkTempCoff(OPT3101::crosstalkTempCoffC *illumXtalkTempCoff, uint8_t txChannel, char registerSet) { /// <b>Algorithm of the method is as follows</b> this->reg.scale_temp_coeff_xtalk = illumXtalkTempCoff->commonScale; ///* loads common scale OPT3101::crosstalkTempCoffC::commonScale from input argument illumXtalkTempCoff to device register OPT3101::registers::scale_temp_coeff_xtalk switch (txChannel) { ///* Based on txChannel and registerSet argument the method loads the OPT3101::crosstalkTempCoffC::coffIReg and OPT3101::crosstalkTempCoffC::coffQReg to respective register set and channel registers case 0: ///* for eg: then txChannel=1 and registerSet='l' then the method loads the argument illumXtalkTempCoff's OPT3101::crosstalkTempCoffC::coffIReg to OPT3101::registers::temp_coeff_xtalk_iphase_hdr0_tx1 and similarly for the qphase register as well if (registerSet == 'h') { this->reg.temp_coeff_xtalk_iphase_hdr1_tx0 = illumXtalkTempCoff->coffIReg; this->reg.temp_coeff_xtalk_qphase_hdr1_tx0 = illumXtalkTempCoff->coffQReg; } else if (registerSet == 'l') { this->reg.temp_coeff_xtalk_iphase_hdr0_tx0 = illumXtalkTempCoff->coffIReg; this->reg.temp_coeff_xtalk_qphase_hdr0_tx0 = illumXtalkTempCoff->coffQReg; } break; case 1: if (registerSet == 'h') { this->reg.temp_coeff_xtalk_iphase_hdr1_tx1 = illumXtalkTempCoff->coffIReg; this->reg.temp_coeff_xtalk_qphase_hdr1_tx1 = illumXtalkTempCoff->coffQReg; } else if (registerSet == 'l') { this->reg.temp_coeff_xtalk_iphase_hdr0_tx1 = illumXtalkTempCoff->coffIReg; this->reg.temp_coeff_xtalk_qphase_hdr0_tx1 = illumXtalkTempCoff->coffQReg; } break; case 2: if (registerSet == 'h') { this->reg.temp_coeff_xtalk_iphase_hdr1_tx2 = illumXtalkTempCoff->coffIReg; this->reg.temp_coeff_xtalk_qphase_hdr1_tx2 = illumXtalkTempCoff->coffQReg; } else if (registerSet == 'l') { this->reg.temp_coeff_xtalk_iphase_hdr0_tx2 = illumXtalkTempCoff->coffIReg; this->reg.temp_coeff_xtalk_qphase_hdr0_tx2 = illumXtalkTempCoff->coffQReg; } break; default: break; } } void OPT3101::device::loadPhaseOffsetTempCoff(OPT3101::phaseTempCoffC *phaseTempCoff, uint8_t txChannel, char registerSet) { /// <b>Algorithm of the method is as follows</b> this->reg.en_temp_corr = 1; ///* Enables the phase temp coefficient register OPT3101::registers::en_temp_corr this->reg.scale_phase_temp_coeff = phaseTempCoff->commonScale; ///* Sets the common scale register OPT3101::registers::scale_phase_temp_coeff with value from input argument phaseTempCoff's OPT3101::phaseTempCoffC::commonScale switch (txChannel) { ///* Based on txChannel and registerSet argument the method loads the OPT3101::phaseTempCoffC::coffReg to respective register set and channel registers case 0: ///* for eg: then txChannel=1 and registerSet='l' then the method loads the argument phaseTempCoff's OPT3101::phaseTempCoffC::coffReg to OPT3101::registers::temp_coeff_illum_hdr0_tx1 or OPT3101::registers::temp_coeff_main_hdr0_tx1 depending on if phaseTempCoff's OPT3101::phaseTempCoffC::istMainCoff is True or False if (registerSet == 'h') { if (phaseTempCoff->istMainCoff) this->reg.temp_coeff_main_hdr1_tx0 = phaseTempCoff->coffReg; else this->reg.temp_coeff_illum_hdr1_tx0 = phaseTempCoff->coffReg; } else if (registerSet == 'l') { if (phaseTempCoff->istMainCoff) this->reg.temp_coeff_main_hdr0_tx0 = phaseTempCoff->coffReg; else this->reg.temp_coeff_illum_hdr0_tx0 = phaseTempCoff->coffReg; } break; case 1: if (registerSet == 'h') { if (phaseTempCoff->istMainCoff) this->reg.temp_coeff_main_hdr1_tx1 = phaseTempCoff->coffReg; else this->reg.temp_coeff_illum_hdr1_tx1 = phaseTempCoff->coffReg; } else if (registerSet == 'l') { if (phaseTempCoff->istMainCoff) this->reg.temp_coeff_main_hdr0_tx1 = phaseTempCoff->coffReg; else this->reg.temp_coeff_illum_hdr0_tx1 = phaseTempCoff->coffReg; } break; case 2: if (registerSet == 'h') { if (phaseTempCoff->istMainCoff) this->reg.temp_coeff_main_hdr1_tx2 = phaseTempCoff->coffReg; else this->reg.temp_coeff_illum_hdr1_tx2 = phaseTempCoff->coffReg; } else if (registerSet == 'l') { if (phaseTempCoff->istMainCoff) this->reg.temp_coeff_main_hdr0_tx2 = phaseTempCoff->coffReg; else this->reg.temp_coeff_illum_hdr0_tx2 = phaseTempCoff->coffReg; } break; default: break; } } void OPT3101::device::loadPhaseAmbientCoff(OPT3101::phaseAmbientCoffC *phaseAmbientCoff) { /// <b>Algorithm of the method is as follows</b> this->reg.scale_amb_phase_corr_coeff = phaseAmbientCoff->commonScale; ///* Assigns all the register entries from phaseAmbientCoff OPT3101::phaseAmbientCoffC to h/w registers this->reg.amb_phase_corr_pwl_coeff0 = phaseAmbientCoff->coffReg[0]; ///* for eg: input argument phaseAmbientCoff's OPT3101::phaseAmbientCoffC::coffReg is loaded to OPT3101::registers::amb_phase_corr_pwl_coeff0 and other related registers this->reg.amb_phase_corr_pwl_coeff1 = phaseAmbientCoff->coffReg[1]; this->reg.amb_phase_corr_pwl_coeff2 = phaseAmbientCoff->coffReg[2]; this->reg.amb_phase_corr_pwl_coeff3 = phaseAmbientCoff->coffReg[3]; this->reg.amb_phase_corr_pwl_x0 = phaseAmbientCoff->splitsReg[0]; this->reg.amb_phase_corr_pwl_x1 = phaseAmbientCoff->splitsReg[1]; this->reg.amb_phase_corr_pwl_x2 = phaseAmbientCoff->splitsReg[2]; } OPT3101::frameData::frameData() { /// <b>Algorithm of the method is as follows</b> this->phase = 0; ///* Initializes all members to 0 this->phaseovl = false; this->phaseovlf2 = false; this->ambovl = false; this->illumDac = false; this->ledChannel = 0; this->frameStatus = false; this->dealiasFreq = false; this->frameCounter = 0; this->amplitude = 0; this->sigovl = false; this->dealiasBin = 0; this->ambient = 0; this->temp = 0; this->tmain = 0; this->tillum = 0; } void OPT3101::frameData::capture(hostController *host, OPT3101::device *dev,bool readTillum) { uint8_t c0; uint32_t data32[3]; /// <b>Algorithm of the method is as follows</b> host->sleep((dev->configurationFlags_frameTimeInMilliSeconds)<<1); ///* Sleep host for a specified time depending on device configuration to OPT3101 AFE can update measurements to the registers. for (c0 = 8; c0 < 11; c0++) ///* Performs a direct read of I2C registers 0x08 0x09 and 0x0A directly though hostController::readI2C method data32[c0-8] = (host->readI2C(c0)); this->phase = data32[0] & 0xFFFF; ///* Maps the I2C read values to the class members like OPT3101::frameData::phase, OPT3101::frameData::amplitude etc this->phaseovl = (data32[0] >> 16) & 0x1; this->phase |= (((uint32_t) this->phaseovl) << 16); this->illumDac = (data32[0] >> 17) & 0x01; this->ledChannel = (data32[0] >> 18) & 0x03; this->frameStatus = (data32[0] >> 20) & 0x01; this->dealiasFreq = (data32[0] >> 21) & 0x01; this->ambovl = (data32[0] >> 22) & 0x01; this->frameCounter = (data32[0] >> 23) & 0x01; this->amplitude = data32[1] & 0xFFFF; this->frameCounter |= ((data32[1] >> 16) & 0x03) << 1; this->sigovl = (data32[1] >> 18) & 0x01; this->phaseovlf2 = (data32[1] >> 19) & 0x01; this->dealiasBin = (data32[1] >> 20) & 0x0F; this->frameCounter |= (data32[2] & 0x03) << 3; this->ambient = (data32[2] >> 2) & 0x3FF; this->temp = (data32[2] >> 12) & 0xFFF; this->tmain = this->temp; if (readTillum) this->tillum = dev->reg.tillum.read(); ///* Based on readIllum flag reads the OPT3101::registers::tillum and assigns to OPT3101::frameData::tillum } void OPT3101::frameData::report() { /// <b>Algorithm of the method is as follows</b> host.printf("-----------------------\r\n"); host.printf("Frame data Class Report\r\n"); host.printf("-----------------------\r\n"); ///* Prints all the members and values of members on screen. host.printf("phase=%d\r\n", this->phase); host.printf("phaseovl=%d\r\n", this->phaseovl); host.printf("phaseovlf2=%d\r\n", this->phaseovlf2); host.printf("ambovl=%d\r\n", this->ambovl); host.printf("illumDac=%d\r\n", this->illumDac); host.printf("ledChannel=%d\r\n", this->ledChannel); host.printf("frameStatus=%d\r\n", this->frameStatus); host.printf("dealiasFreq=%d\r\n", this->dealiasFreq); host.printf("frameCounter=%d\r\n", this->frameCounter); host.printf("amplitude=%d\r\n", this->amplitude); host.printf("sigovl=%d\r\n", this->sigovl); host.printf("dealiasBin=%d\r\n", this->dealiasBin); host.printf("ambient=%d\r\n", this->ambient); host.printf("temp=%d\r\n", this->temp); host.printf("tmain=%d\r\n", this->tmain); host.printf("tillum=%d\r\n", this->tillum); host.printf("-----------------------\r\n"); ///* Prints all the members and values of members on screen. } void OPT3101::frameData::printHeader() { /// <b>Algorithm of the method is as follows</b> host.printfSetColor(0b001); host.printf("Phase,"); host.printf("Amplt,"); host.printf("SigOl,"); host.printf("AmbOl,"); host.printf("Amb,"); host.printf("tMain,"); host.printf("tIlum,"); host.printf("tMain(C),"); host.printf(" tIlum(C)\r\n"); host.printfSetColor(0xFF); } void OPT3101::frameData::print() { /// <b>Algorithm of the method is as follows</b> host.printfSetColor(0b001); host.printf("%05u,",this->phase); host.printf("%05u,",this->amplitude); host.printf(" %1u,",this->sigovl); host.printf(" %1u,",this->ambovl); host.printf("%03u,",this->ambient); host.printf(" %04d,",this->tmain); host.printf(" %04d,",this->tillum); host.printf(" %+03d,",(int8_t) ((((int16_t)this->tmain)>>3)-256)); host.printf(" %+07.4f\r\n",((double)(((int16_t)this->tillum)-2048))/16.0); host.printfSetColor(0xFF); } void OPT3101::frameData::populateWithMean(OPT3101::frameData *inputData, uint16_t nFrames) { uint16_t c0; uint16_t shiftBits; uint32_t accum; /// <b>Algorithm of the method is as follows</b> shiftBits = 0; nFrames = nFrames == 0 ? 1 : nFrames; ///* Sets nFrames to 1 when nFrames is 0 if(nFrames>1) while (((nFrames-1) >> ++shiftBits) > 0); ///* Finds the smallest 2^N number higher than the nFrames provided in the argument of this method else // All flags this->phaseovl = 0; this->phaseovlf2 = 0; this->ambovl = 0; this->illumDac = inputData[0].illumDac; this->ledChannel = inputData[0].ledChannel; this->frameStatus = 0; this->dealiasFreq = inputData[0].dealiasFreq; this->sigovl = 0; this->dealiasBin = inputData[0].dealiasBin; this->frameCounter = 0; for (c0 = 0; c0 < nFrames; c0++) { this->phaseovl |= inputData[0].phaseovl; this->phaseovlf2 |= inputData[0].phaseovlf2; this->ambovl |= inputData[0].ambovl; this->sigovl |= inputData[0].sigovl; } // Mean of phase if found accum = 0; ///* Accumulates and measures mean for all the input class instance members and assigns them to the method's class members for (c0 = 0; c0 < nFrames; c0++) accum += inputData[c0].phase; this->phase = accum >> shiftBits; // Mean of amplitude is found accum = 0; for (c0 = 0; c0 < nFrames; c0++) accum += inputData[c0].amplitude; this->amplitude = accum >> shiftBits; // Mean of ambient is found accum = 0; for (c0 = 0; c0 < nFrames; c0++) accum += inputData[c0].ambient; this->ambient = accum >> shiftBits; // Mean of temp is found accum = 0; for (c0 = 0; c0 < nFrames; c0++) accum += inputData[c0].temp; this->temp = accum >> shiftBits; // Mean of tmain is found accum = 0; for (c0 = 0; c0 < nFrames; c0++) accum += inputData[c0].tmain; this->tmain = accum >> shiftBits; // Mean of tillum is found accum = 0; for (c0 = 0; c0 < nFrames; c0++) accum += inputData[c0].tillum; this->tillum = accum >> shiftBits; ///* <b>Warning:</b> When nFrames is a non 2^N number the mean results are expected to be lower than actual measurements } #ifdef OPT3101_USE_STREAMLIB std::ostream & OPT3101::operator<<(std::ostream & os, const OPT3101::frameData * data) { /// <b>Algorithm of the method is as follows</b> os << data->phase << '\n'; ///* Serializes all the members and returns to the stream os << data->phaseovl << '\n'; os << data->phaseovlf2 << '\n'; os << data->ambovl << '\n'; os << data->illumDac << '\n'; os << data->ledChannel << '\n'; os << data->frameStatus << '\n'; os << data->dealiasFreq << '\n'; os << data->frameCounter << '\n'; os << data->amplitude << '\n'; os << data->sigovl << '\n'; os << data->dealiasBin << '\n'; os << data->temp << '\n'; os << data->tmain << '\n'; os << data->tillum << '\n'; return os; } #endif #ifdef OPT3101_USE_STREAMLIB std::istream & OPT3101::operator>>(std::istream & is, OPT3101::frameData * data) { /// <b>Algorithm of the method is as follows</b> is >> data->phase; ///* Serializes all the members and returns to the stream is >> data->phaseovl; is >> data->phaseovlf2; is >> data->ambovl; is >> data->illumDac; is >> data->ledChannel; is >> data->frameStatus; is >> data->dealiasFreq; is >> data->frameCounter; is >> data->amplitude; is >> data->sigovl; is >> data->dealiasBin; is >> data->temp; is >> data->tmain; is >> data->tillum; return is; } #endif #ifdef OPT3101_USE_STDIOLIB void OPT3101::frameData::storeToFile(char * fileName) { #ifdef OPT3101_USE_STREAMLIB /// <b>Algorithm of the method is as follows</b> std::ofstream ofs(fileName); ofs << this; ofs.close(); ///* User needs to implement file storage based on host. #endif } #endif #ifdef OPT3101_USE_STDIOLIB void OPT3101::frameData::loadFromFile(char * fileName) { #ifdef OPT3101_USE_STREAMLIB /// <b>Algorithm of the method is as follows</b> std::ifstream ifs(fileName); ifs >> this; ifs.close(); ///* User needs to implement file load/restore based on host. #endif } #endif void OPT3101::device::measurePhaseOffsetSet(bool saveToFile) { uint8_t c0, c1; uint16_t flashLocation; uint16_t refDistanceInCodes; uint32_t refDistanceInMM; #ifdef OPT3101_USE_STDIOLIB char fileName[FILENAME_LENGTH]; #endif envController.manuallySetReferenceDistances(); // Loop to iterate over all TX channels for (c0 = 0; c0 < 3; c0++) { ///* Loops though all the valid TX channel and register set configurations if (this->configurationFlags_isTXChannelActive[c0]) { // Checking is TX channel is active for this profile for (c1 = 0; c1 < 2; c1++) { // Loop to iterate over the H/L registers if (this->configurationFlags_isRegisterSetActive[c1]) { // Checking if registers are active for this profile refDistanceInMM=envController.refDistancesInMM[c0][c1]; envController.setTargetDistance(refDistanceInMM); ///* Calls environmentalController::setTargetDistance method with the specified distance refDistanceInCodes = (refDistanceInMM * 4477) >> 10; ///* Converts the reference distance specified in codes related to OPT3101::frameData::phase ADC codes host.printf("INFO:Performing Phase Offset for TX%d HDR %d @ ref Distance %dmm\r\n",c0,c1,refDistanceInMM); this->measurePhaseOffset(&this->calibration->phaseOffset[c0][c1], c0, c1 ? 'h' : 'l', refDistanceInCodes); ///* Measures phase offset by calling method OPT3101::device::measurePhaseOffset with specified reference distance and OPT3101::calibrationC::phaseOffset as argument to store the phase offset values this->calibration->phaseOffset[c0][c1].printHeader(); this->calibration->phaseOffset[c0][c1].print(); host.printf("\r\n"); if(saveToFile){ #ifdef OPT3101_USE_STDIOLIB sprintf(fileName, "%s/phaseOffset_TX%d_%c.txt", filePath, c0, c1 ? 'h' : 'l'); ///* Creates filename illumCrosstalk_TX{channel}_{h/l}.txt in path filePath this->calibration->phaseOffset[c0][c1].storeToFile(fileName); ///* Calls method OPT3101::crosstalkC::storeToFile to store the data #endif #ifdef TIMSP430F5529_LAUNCHPAD_CALIBRATION_TOOL flashLocation=96+36*((c0<<1)+c1); // TODO fix this flash host.flash.write(flashLocation, (uint8_t*)&this->calibration->phaseOffset[c0][c1] ,36); host.printf("INFO:Writing Phase Offset for TX%d HDR %d to Flash location 0x%04x\r\n",c0,c1,flashLocation); #endif // TIHOST } } } } } } void OPT3101::device::measurePhaseOffset(OPT3101::phaseOffsetC *phaseOffset,uint16_t refDistanceInCodes) { OPT3101::frameData data[32], meanData; uint16_t nFrames; int32_t phaseOffsetRegister; uint16_t c0; /// <b>Algorithm of the method is as follows</b> nFrames = 1 << (this->configurationFlags_avgFrameCountExponentOfTwo <= 5 ? 5 - this->configurationFlags_avgFrameCountExponentOfTwo : 0); ///* Calculates number of frames to average the data. Based on the OPT3101::device::configurationFlags_avgFrameCountExponentOfTwo number of average is decided. More frames are captured and averaged if device configuration has low average frames and vice versa //data = new OPT3101::frameData[nFrames]; for (c0 = 0; c0<nFrames; c0++) data[c0].capture(&host, this); ///* Captures all calculated number of frames from the h/w using OPT3101::frameData::capture method meanData.populateWithMean(&data[0], nFrames); ///* Measures the mean of the captured frames OPT3101::frameData::populateWithMean method phaseOffsetRegister = (int32_t) (meanData.phase - refDistanceInCodes); ///* Calculates the actual phase offset register value based on the input argument refDistanceInCodes and measured phase OPT3101::frameData::phase (mean over captured frames) phaseOffset->freqCount = this->reg.freq_count_read_reg.read(); ///* Captures snapshot of register value OPT3101::registers::freq_count_read_reg and assigns to input argument phaseOffset's OPT3101::phaseOffsetC::freqCount if (phaseOffset->freqCount > 0) phaseOffsetRegister = (int32_t)((phaseOffsetRegister * 16384) / phaseOffset->freqCount); ///* Scales phase offset value with OPT3101::phaseOffsetC::freqCount value else phaseOffsetRegister = 0; phaseOffset->phaseOffset = (uint16_t)(phaseOffsetRegister & 0xFFFF); ///* Assigns input argument phaseOffset's OPT3101::phaseOffsetC::phaseOffset with scaled register value phaseOffset->data = meanData; ///* Captures the calculated mean OPT3101::frameData to OPT3101::phaseOffsetC::data phaseOffset->referenceDistanceInCodes = refDistanceInCodes; ///* Captures the snapshot of input argument refDistanceInCodes to the input argument phaseOffset's OPT3101::phaseOffsetC::referenceDistanceInCodes } void OPT3101::device::measurePhaseOffset(OPT3101::phaseOffsetC *phaseOffset, uint8_t txChannel, char registerSet, uint16_t refDistanceInCodes,uint8_t shiftIllumPhase) { uint8_t regStore[14]; uint8_t dummy; /// <b>Algorithm of the method is as follows</b> regStore[0] = this->reg.en_sequencer.read(); regStore[1] = this->reg.en_processor_values.read(); regStore[2] = this->reg.sel_hdr_mode.read(); regStore[3] = this->reg.sel_tx_ch.read(); regStore[4] = this->reg.en_adaptive_hdr.read(); regStore[5] = this->reg.en_tx_switch.read(); regStore[6] = this->reg.en_phase_corr.read(); regStore[7] = this->reg.en_nl_corr.read(); regStore[8] = this->reg.en_temp_corr.read(); regStore[9] = this->reg.amb_phase_corr_pwl_coeff0.read(); regStore[10] = this->reg.amb_phase_corr_pwl_coeff1.read(); regStore[11] = this->reg.amb_phase_corr_pwl_coeff2.read(); regStore[12] = this->reg.amb_phase_corr_pwl_coeff3.read(); regStore[13] = this->reg.shift_illum_phase.read(); ///* Critical registers which are modified in this method are read from the h/w and temporarily buffered to local variables. this->reg.tg_en = 0; this->reg.en_sequencer = 0; this->reg.en_processor_values = 0; if (registerSet == 'h') this->reg.sel_hdr_mode = 1; ///* Register set is chosen based on registerSet input to this method by setting OPT3101::registers::sel_hdr_mode if (registerSet == 'l') this->reg.sel_hdr_mode = 0; this->reg.sel_tx_ch = txChannel; ///* TX channel is chosen based on txChannel input to this method by setting OPT3101::registers::sel_tx_ch this->reg.en_tx_switch = 0; this->reg.en_adaptive_hdr = 0; this->reg.en_phase_corr = 0; this->reg.en_nl_corr = 0; this->reg.en_temp_corr = 0; this->reg.amb_phase_corr_pwl_coeff0 = 0; this->reg.amb_phase_corr_pwl_coeff1 = 0; this->reg.amb_phase_corr_pwl_coeff2 = 0; this->reg.amb_phase_corr_pwl_coeff3 = 0; this->reg.shift_illum_phase = shiftIllumPhase; ///* Sets up the OPT3101::registers::shift_illum_phase based on the input to this method shiftIllumPhase this->reg.tg_en = 1; this->measurePhaseOffset(phaseOffset, refDistanceInCodes); ///* Measures phase offset with following steps // Added dummy lines so that Doxygen can recognize these multi-line comments dummy = 0; ///* Calculates number of frames to average the data. Based on the OPT3101::device::configurationFlags_avgFrameCountExponentOfTwo number of average is decided. More frames are captured and averaged if device configuration has low average frames and vice versa dummy = 0; ///* Captures all calculated number of frames from the h/w using OPT3101::frameData::capture method dummy = 0; ///* Measures the mean of the captured frames OPT3101::frameData::populateWithMean method dummy = 0; ///* Calculates the actual phase offset register value based on the input argument refDistanceInCodes and measured phase OPT3101::frameData::phase (mean over captured frames) dummy = 0; ///* Captures snapshot of register value OPT3101::registers::freq_count_read_reg and assigns to input argument phaseOffset's OPT3101::phaseOffsetC::freqCount dummy = 0; ///* Scales phase offset value with OPT3101::phaseOffsetC::freqCount value dummy = 0; ///* Assigns input argument phaseOffset's OPT3101::phaseOffsetC::phaseOffset with scaled register value dummy = 0; ///* Captures the calculated mean OPT3101::frameData to OPT3101::phaseOffsetC::data dummy = 0; ///* Captures the snapshot of input argument refDistanceInCodes to the input argument phaseOffset's OPT3101::phaseOffsetC::referenceDistanceInCodes phaseOffset->shiftIllumPhase = shiftIllumPhase; phaseOffset->illumDCdac = this->reg.ILLUM_DC_CURR_DAC.read(); switch (txChannel) { ///* Captures the snapshot of the illum dac, illum DC and illum scale settings form h/w to the phaseOffset input argument case 0: if (registerSet == 'h') { phaseOffset->illumDac = this->reg.illum_dac_h_tx0.read(); phaseOffset->illumScale = this->reg.illum_scale_h_tx0.read(); } else if (registerSet == 'l') { phaseOffset->illumDac = this->reg.illum_dac_l_tx0.read(); phaseOffset->illumScale = this->reg.illum_scale_l_tx0.read(); } break; case 1: if (registerSet == 'h') { phaseOffset->illumDac = this->reg.illum_dac_h_tx1.read(); phaseOffset->illumScale = this->reg.illum_scale_h_tx1.read(); } else if (registerSet == 'l') { phaseOffset->illumDac = this->reg.illum_dac_l_tx1.read(); phaseOffset->illumScale = this->reg.illum_scale_l_tx1.read(); } break; case 2: if (registerSet == 'h') { phaseOffset->illumDac = this->reg.illum_dac_h_tx2.read(); phaseOffset->illumScale = this->reg.illum_scale_h_tx2.read(); } else if (registerSet == 'l') { phaseOffset->illumDac = this->reg.illum_dac_l_tx2.read(); phaseOffset->illumScale = this->reg.illum_scale_l_tx2.read(); } break; default: break; } this->reg.tg_en = 0; this->reg.en_sequencer = regStore[0]; this->reg.en_processor_values = regStore[1]; this->reg.sel_hdr_mode = regStore[2]; this->reg.sel_tx_ch = regStore[3]; this->reg.en_adaptive_hdr = regStore[4]; this->reg.en_tx_switch = regStore[5]; this->reg.en_phase_corr = regStore[6]; this->reg.en_nl_corr = regStore[7]; this->reg.en_temp_corr = regStore[8]; this->reg.amb_phase_corr_pwl_coeff0 = regStore[9]; this->reg.amb_phase_corr_pwl_coeff1 = regStore[10]; this->reg.amb_phase_corr_pwl_coeff2 = regStore[11]; this->reg.amb_phase_corr_pwl_coeff3 = regStore[12]; this->reg.shift_illum_phase = regStore[13]; ///* Restores the device state to the same state as before entering this method from the buffered local variables this->reg.tg_en = 1; } void OPT3101::device::writeDataToEEPROM(uint8_t location, uint8_t data) { this->reg.i2c_write_data1 = location; this->reg.i2c_write_data2 = data; this->reg.i2c_trig_reg = 1; host.sleep(1); ///* Added delay to initiate an I2C write transaction this->reg.i2c_trig_reg = 0; host.sleep(1); ///* Added delay to initiate an I2C write transaction } uint8_t OPT3101::device::readDataFromEEPROM(uint8_t location) { /* Will be updated in future revision of the SDK this->reg.i2c_write_data1 = location; this->reg.i2c_trig_reg = 1; host.sleep(50); ///* Added delay to initiate an I2C write transaction this->reg.i2c_trig_reg = 0; host.sleep(50); ///* Added delay to initiate an I2C write transaction return ((uint8_t) (this->reg.i2c_read_data.read()&0xFF)); */ return 0x00; } void OPT3101::device::loadIllumCrosstalkSet(bool loadFromFile) { uint8_t c0, c1; uint16_t flashLocation; /// <b>Algorithm of the method is as follows</b> #ifdef OPT3101_USE_STDIOLIB char fileName[FILENAME_LENGTH]; #endif host.printf("INFO::Loading Illumination cross talk Set\r\n"); // Loop to iterate over all TX channels if(loadFromFile){ ///* Checks if input argument loadFromFile is true. If true proceeds to load files in to OPT3101::device::calibration for (c0 = 0; c0 < 3; c0++) { ///* Loops though all the valid TX channel and register set configurations if (this->configurationFlags_isTXChannelActive[c0]) { // Checking is TX channel is active for this profile for (c1 = 0; c1 < 2; c1++) { // Loop to iterate over the H/L registers if (this->configurationFlags_isRegisterSetActive[c1]) { // Checking if registers are active for this profile #ifdef OPT3101_USE_STDIOLIB sprintf(fileName, "%s/illumCrosstalk_TX%d_%c.txt", filePath, c0, c1 ? 'h' : 'l'); this->calibration->illumCrosstalk[c0][c1].loadFromFile(fileName); ///* Calls method OPT3101::crosstalkC::loadFromFile to load data from non-volatile memory to all the OPT3101::device::calibration::illumCrosstalk members #endif #ifdef TIMSP430F5529_LAUNCHPAD_CALIBRATION_TOOL flashLocation=(c1+(c0<<1))<<4; // TODO fix this host.flash.read(flashLocation, (uint8_t*)&this->calibration->illumCrosstalk[c0][c1] ,16); host.printf("INFO:Reading Illum Cross talk from Flash location 0x%04x\r\n",flashLocation); #endif this->calibration->illumCrosstalk[c0][c1].printHeader(); this->calibration->illumCrosstalk[c0][c1].print(); host.printf("\r\n"); } } } } } this->calibration->findCommonCrosstalkScale(&this->calibration->illumCrosstalk[0][0], this->configurationFlags_isTXChannelActive,this->configurationFlags_isTXChannelActive); ///* Finds common crosstalk scale for the illum Crosstalk values captured in OPT3101::device::calibrationC using method OPT3101::calibrationC::findCommonCrosstalkScale // Loop to iterate over all TX channels for (c0 = 0; c0 < 3; c0++) { ///* Loops though all the valid TX channel and register set configurations if (this->configurationFlags_isTXChannelActive[c0]) { // Checking is TX channel is active for this profile for (c1 = 0; c1 < 2; c1++) { // Loop to iterate over the H/L registers if (this->configurationFlags_isRegisterSetActive[c1]) // Checking if registers are active for this profile this->loadIllumCrosstalk(&this->calibration->illumCrosstalk[c0][c1], c0, c1 ? 'h' : 'l'); ///* Loads all the illum crosstalk corresponding to TX and register set configurations to the device from the OPT3101::device::calibrationC::illumCrosstalk member by calling OPT3101::device::loadIllumCrosstalk } } } } void OPT3101::device::loadPhaseOffsetSet(bool loadFromFile) { uint8_t c0, c1; uint16_t flashLocation; #ifdef OPT3101_USE_STDIOLIB char fileName[FILENAME_LENGTH]; #endif host.printf("INFO::Loading Phase Offset Set\r\n"); /// <b>Algorithm of the method is as follows</b> // Loop to iterate over all TX channels if(loadFromFile){ for (c0 = 0; c0 < 3; c0++) { ///* Loops though all the valid TX channel and register set configurations if (this->configurationFlags_isTXChannelActive[c0]) { // Checking is TX channel is active for this profile for (c1 = 0; c1 < 2; c1++) { // Loop to iterate over the H/L registers if (this->configurationFlags_isRegisterSetActive[c1]) { // Checking if registers are active for this profile #ifdef OPT3101_USE_STDIOLIB sprintf(fileName, "%s/phaseOffset_TX%d_%c.txt", filePath, c0, c1 ? 'h' : 'l'); ///* Creates filename illumCrosstalk_TX{channel}_{h/l}.txt in path filePath this->calibration->phaseOffset[c0][c1].loadFromFile(fileName); ///* Calls method OPT3101::crosstalkC::loadFromFile to store the data #endif #ifdef TIMSP430F5529_LAUNCHPAD_CALIBRATION_TOOL flashLocation = 96 + 36 * ((c0 << 1) + c1); // TODo Fix this host.flash.read(flashLocation, (uint8_t*)&this->calibration->phaseOffset[c0][c1], 36); host.printf("INFO:Reading Phase Offset from TX%d HDR %d to Flash location 0x%04x\r\n", c0, c1, flashLocation); #endif // TIHOST this->calibration->phaseOffset[c0][c1].printHeader(); this->calibration->phaseOffset[c0][c1].print(); host.printf("\r\n"); } } } } } for (c0 = 0; c0 < 3; c0++) { ///* Loops though all the valid TX channel and register set configurations if (this->configurationFlags_isTXChannelActive[c0]) { // Checking is TX channel is active for this profile for (c1 = 0; c1 < 2; c1++) { // Loop to iterate over the H/L registers if (this->configurationFlags_isRegisterSetActive[c1]) // Checking if registers are active for this profile this->loadPhaseOffset(&this->calibration->phaseOffset[c0][c1], c0, c1 ? 'h' : 'l'); ///* Loads all the phase offset corresponding to TX and register set configurations to the device from the OPT3101::device::calibrationC::phaseOffset member by calling OPT3101::device::loadPhaseOffset } } } } uint8_t OPT3101::device::determineConfigCount() { return this->calibration->recordLength; } void OPT3101::device::loadIllumCrosstalkTempCoffSet() { uint8_t c0, c1; host.printf("INFO::Loading Illumination crosstalk Temperature Coefficient Set\r\n"); this->loadIllumCrosstalkSet(true); ///* Calls OPT3101::device::loadIllumCrosstalkSet with the same loafFromFile flag specified to this method this->calibration->findCrosstalkTempRegisterValues(&this->calibration->illumCrosstalkTempCoff[0][0], this->configurationFlags_isTXChannelActive,this->configurationFlags_isTXChannelActive, &this->calibration->illumCrosstalk[0][0]); ///* Calls OPT3101::calibrationC::findCrosstalkTempRegisterValues based on the members from OPT3101::calibrationC class OPT3101::calibrationC::illumCrosstalkTempCoff and OPT3101::calibrationC::illumCrosstalk // Loop to iterate over all TX channels for (c0 = 0; c0 < 3; c0++) { ///* Loops though all the valid TX channel and register set configurations if (this->configurationFlags_isTXChannelActive[c0]) { // Checking is TX channel is active for this profile for (c1 = 0; c1 < 2; c1++) { // Loop to iterate over the H/L registers if (this->configurationFlags_isRegisterSetActive[c1]) // Checking if registers are active for this profile this->loadIllumCrosstalkTempCoff(&this->calibration->illumCrosstalkTempCoff[c0][c1], c0, c1 ? 'h' : 'l'); ///* Calls the method OPT3101::device::loadIllumCrosstalkTempCoff to load all the crosstalk temp coff values from the OPT3101::calibrationC::illumCrosstalkTempCoff member } } } this->reg.en_temp_xtalk_corr=1; } void OPT3101::device::loadPhaseOffsetTempCoffSet() { uint8_t c0, c1; host.printf("INFO::Loading Phase Temperature coefficient Set\r\n"); this->calibration->findPhaseTempRegisterValues(&this->calibration->phaseTempCoff[0][0], this->configurationFlags_isTXChannelActive,this->configurationFlags_isTXChannelActive, this->reg.freq_count_read_reg.read()); ///* Calls OPT3101::calibrationC::findPhaseTempRegisterValues based on the members from OPT3101::calibrationC class OPT3101::calibrationC::phaseTempCoff and current device register OPT3101::registers::freq_count_read_reg // Loop to iterate over all TX channels for (c0 = 0; c0 < 3; c0++) { ///* Loops though all the valid TX channel and register set configurations if (this->configurationFlags_isTXChannelActive[c0]) { // Checking is TX channel is active for this profile for (c1 = 0; c1 < 2; c1++) { // Loop to iterate over the H/L registers if (this->configurationFlags_isRegisterSetActive[c1]) // Checking if registers are active for this profile this->loadPhaseOffsetTempCoff(&this->calibration->phaseTempCoff[c0][c1], c0, c1 ? 'h' : 'l'); ///* Calls the method OPT3101::device::loadPhaseOffsetTempCoff to load all the phase temp coff values from the OPT3101::calibrationC::phaseTempCoff member } } } } void OPT3101::device::loadPhaseAmbientCoffSet() { host.printf("INFO::Loading Phase Ambient Coefficient Set\r\n"); this->calibration->phaseAmbientCoff[0].calculateCoff(this->reg.freq_count_read_reg.read()); ///* Calculates the phase ambient coff by calling method OPT3101::phaseAmbientCoffC::calculateCoff also passing argument of device register OPT3101::registers::freq_count_read_reg this->loadPhaseAmbientCoff(&this->calibration->phaseAmbientCoff[0]); ///* Calls method OPT3101::device::loadPhaseAmbientCoff to load ambient coff to device from OPT3101::calibrationC::phaseAmbientCoff member } void OPT3101::calibrationC::findCommonCrosstalkScale(OPT3101::crosstalkC* illumXtalk, bool *txActiveList,bool *registerSetActiveList) { uint8_t maxScale, c0,c1; maxScale = 0; /// <b>Algorithm of the method is as follows</b> for (c0 = 0; c0 < 3; c0++) { for (c1 = 0; c1 < 2; c1++){ if(txActiveList[c0] && registerSetActiveList[c1]) maxScale = illumXtalk[(c0<<1)+c1].xtalkScale > maxScale ? illumXtalk[(c0<<1)+c1].xtalkScale : maxScale; ///* Finds the largest scale what will fit all the input OPT3101::crosstalkC arguments } } for (c0 = 0; c0 < 3; c0++) { for (c1 = 0; c1 < 2; c1++){ if(txActiveList[c0] && registerSetActiveList[c1]) illumXtalk[(c0<<1)+c1].commonScale = maxScale; ///* Assigns the identified maxScale to all the input argument illum Crosstalk pointers OPT3101::crosstalkC } } } OPT3101::calibrationC::calibrationC(bool dummyFlag) { /// <b>Algorithm of the method is as follows</b> ///* Allocates memory for OPT3101::calibrationC::internalCrosstalk size based on system configuration ///* Allocates memory for OPT3101::calibrationC::illumCrosstalk size based on system configuration ///* Allocates memory for OPT3101::calibrationC::phaseOffset size based on system configuration ///* Allocates memory for OPT3101::calibrationC::illumCrosstalkTempCoff size based on system configuration ///* Allocates memory for OPT3101::calibrationC::phaseTempCoff size based on system configuration ///* Allocates memory for OPT3101::calibrationC::phaseAmbientCoff size based on system configuration ///* Sets the member OPT3101::calibrationC::registerAddressListSize based on number of calibration registers requires ///* Allocates memory for OPT3101::calibrationC::registerAddressList based on OPT3101::calibrationC::registerAddressListSize ///* Sets up the flag OPT3101::calibrationC::EEPROM_connected based on configuration ///* Sets up the flag OPT3101::calibrationC::extTempSensor_connected based on configuration }