class to readout the VEML7700 light sensor via i2c

Dependents:   veml7700_tst

Revision:
0:e71d3ecdd257
Child:
1:d6eb62dc0a1e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/veml7700.cpp	Tue Sep 10 11:11:19 2019 +0000
@@ -0,0 +1,303 @@
+#include "veml7700.h"
+//nclude <stdio.h>
+/** 
+ * veml7700.cpp  
+ * implementation of the veml7700 class , see veml7700.h
+ *
+ * version history  
+ * version 0.20  : initial value not tested with the sensor 
+ * version 0.21  : just change the name from VEML770 VEML7700 
+                   corrected address
+ * version 0.30  : start with error reporting 
+ * version 0.34  : correction  
+ * version 0.46  :  corrections for correct working , more methods added 
+ * This file make part of the PeriperalDevice package see repository  
+ * https://github.com/wimbeaumont/PeripheralDevices
+ *
+ * (C) Wim Beaumont Universiteit Antwerpen 2015  2019 
+ * License see
+ * https://github.com/wimbeaumont/PeripheralDevices/blob/master/LICENSE
+ *
+ **/
+
+#define VERSION_VEML7700_SRC "0.49"
+
+namespace VEML7700_CONST {
+// the VEML7700 support only 1 I2C address 
+const int i2caddr = 0x20;
+
+// registers 
+
+const u8 ALS_CONF_0  =0x0 ;
+const u8 ALS_WH  =0x1 ;
+const u8 ALS_WL  =0x2 ;
+const u8 POW_SET  =0x3 ; 
+const u8 ALS  =0x4 ;
+const u8 WHITE  =0x5 ;
+const u8 ALS_INT  =0x6 ;
+
+
+// bit masks R0 and values 
+const u16 ALS_SD_SIZE   =0x1 ; //shutdown  =1 
+const u16 ALS_SD_LSB   =0x0 ; 
+const u16 ALS_INT_EN_SIZE   =0x1 ; //enable  =1 
+const u16 ALS_INT_EN_LSB   =0x1 ; 
+const u16 ALS_PERS_SIZE   =0x2 ; 
+const u16 ALS_PERS_LSB   =4 ; 
+const u16 ALS_GAIN_SIZE   =0x2 ; 
+const u16 ALS_GAIN_LSB   = 11;
+const u16 ALS_IT_SIZE   =0x4; 
+const u16 ALS_IT_LSB   =6; 
+const u16 RESERVED_BIT_MSK_ALS_CONF_0 =  0xE40C; // these bits should be 0  so use inverse with AND 
+
+const int NrGains =4;
+
+// make array of struct for the next 2 ? 
+u16 GainSets[NrGains] = { 0x2, 0x3 , 0x0 , 0x1 };
+float gains[NrGains] = {.125, .25 , 1, 2  };
+
+const int NrIntT =6;
+u16 IntTSets[NrIntT]={ 0b1100,0b1000,0b0000,0b0001,0b0010,0b0011 };
+int IntTs[NrIntT] = { 25 ,50,100,200,400, 800 };
+   
+
+// R1 and R2 are 16 words  value 
+// bit mask R3 and values 
+const u16 RESERVED_BIT_MSK_POW_SET =  0xFFF8; // these bits should be 0  so use inverse with AND 
+const u16 PSM_EN_SIZE  =0x1 ; 
+const u16 PSM_EN_LSB   =0x0 ; 
+const u16 PSM_SIZE     =0x6 ; 
+const u16 PSM_LSB      =0x1 ; 
+
+// R4 and R5 are 16 words  value 
+// bit mask R6 and values   status 
+
+const u16 INT_TH_HIGH_MSK   =0x4000 ; 
+const u16 INT_TH_LOW_MSK   =0x8000 ; 
+}
+
+using namespace VEML7700_CONST; 
+
+
+
+VEML7700::VEML7700(I2CInterface*  i2c , bool init   )
+  :getVersion( VERSION_VEML7700_HDR,VERSION_VEML7700_SRC, __TIME__, __DATE__),
+   i2cdev(i2c) {
+    i2cdev=i2c;
+    gain_nr=0;
+    IntTnr =0;
+    if( init) {
+        set_default_als_config();
+        set_default_powermode();
+        // don't care about the threshold settings are interrupt  not used by default
+    }
+    
+} 
+
+int VEML7700::get_status(void) {
+        return i2cdev-> getLastComError() ;
+    
+}
+
+
+void VEML7700::setHighWarningLevel( int lvl){ 
+    u16 llvl=(u16) lvl & 0xFF;
+    write_cmd(ALS_WH, llvl);
+}
+
+void VEML7700::setLowWarningLevel( int lvl){
+    u16 llvl=(u16) lvl & 0xFF;
+    write_cmd(ALS_WL, llvl);
+}
+
+bool VEML7700::HighThresoldExeed(void) {
+     return (INT_TH_HIGH_MSK  & read_cmd(ALS_INT )) ? true:false; 
+}
+
+bool VEML7700::LowThresoldExeed(void){
+     return (INT_TH_LOW_MSK  & read_cmd(ALS_INT )) ? true:false; 
+}
+
+
+void VEML7700::set_bits_reg  ( u8 reg , u16 value, u16 lsb ,u16 bsize ) {
+    u16  regvalue =read_cmd(reg );  
+    regvalue = set_bits(regvalue,  value, lsb, bsize) ;
+    if (reg == ALS_CONF_0) {regvalue &= ~RESERVED_BIT_MSK_ALS_CONF_0; } 
+    if (reg == POW_SET) {regvalue &= ~RESERVED_BIT_MSK_POW_SET; } 
+    write_cmd( reg, regvalue ) ;
+} 
+
+u16 VEML7700::set_bits(u16 regvalue, u16 value,  u16 lsb ,u16 bsize ) {
+    u16 mask = 1; 
+    mask = mask << bsize ; mask = mask -1; // so bsize=3 give now mask 0  0111
+    mask = mask << lsb; // put the bits in the correct place 
+    regvalue  &= ~mask; // set bits to 0
+    value = value << lsb; // set the value bits in the correct place. 
+    value &= mask ; //only set these bits 
+    return  value | regvalue;
+}   
+
+void VEML7700::shutdown( bool enable) {
+    u16 ie= enable  ? 0 :1 ;
+    set_bits_reg(  ALS_CONF_0,ie, ALS_SD_LSB,ALS_SD_SIZE );
+}
+    
+void VEML7700::set_int_enable( bool int_enable) {
+    u16 ie= int_enable  ? 0 :1 ;
+    set_bits_reg(  ALS_CONF_0,ie, ALS_INT_EN_LSB,ALS_INT_EN_SIZE );
+}
+
+void VEML7700::set_gain_bits( u16 gbits ) {
+    set_bits_reg ( ALS_CONF_0 , gbits , ALS_GAIN_LSB,ALS_GAIN_SIZE );
+}
+
+void VEML7700::set_IntT_bits( u16 InTgbits ) {
+    set_bits_reg ( ALS_CONF_0 , InTgbits , ALS_IT_LSB,ALS_IT_SIZE );
+}
+
+    
+void VEML7700::set_default_als_config ( bool shutdown , bool int_enable ,u16 pres, u16 integrationtime, u16 gain ) {
+    u16 setvalue = shutdown? 1:0;  //set shutdown 
+    u16 uinterrupt= int_enable ?1:0;
+    setvalue=set_bits( setvalue , uinterrupt ,  ALS_INT_EN_LSB,ALS_INT_EN_SIZE);
+    setvalue=set_bits( setvalue , pres , ALS_PERS_LSB,ALS_PERS_SIZE);
+    setvalue=set_bits( setvalue , integrationtime , ALS_IT_LSB,ALS_IT_SIZE);
+    setvalue=set_bits( setvalue , gain  , ALS_GAIN_LSB,ALS_GAIN_SIZE);
+    setvalue &= ~RESERVED_BIT_MSK_ALS_CONF_0;
+    write_cmd(  ALS_CONF_0, setvalue ) ;// it will et all the bits so no need to read first 
+}
+
+void VEML7700::set_power_saving_enable( bool ps_enable) {
+    u16 pse=ps_enable ? 0 :1  ;
+    set_bits_reg( POW_SET ,pse, PSM_EN_LSB, PSM_EN_SIZE );
+}
+
+void VEML7700::set_power_saving_mode( u16 psmode)       {
+    set_bits_reg( POW_SET ,psmode, PSM_LSB, PSM_SIZE );
+}
+
+void VEML7700::set_default_powermode ( bool ps_enable , u16 psmode) {
+    u16 setvalue = ps_enable ? 0:1;
+    setvalue = set_bits( setvalue, psmode,PSM_LSB, PSM_SIZE );
+    setvalue &= ~ ~RESERVED_BIT_MSK_POW_SET;
+    write_cmd(  POW_SET , setvalue ) ;
+}   
+
+// error handling via DevErrorReporter 
+u16 VEML7700::read_cmd ( u8 reg) {
+/* seems this doesn work  returns always zero    
+    printf("call read_cmd ");
+    char readvalue[2]; // max 2 values read 
+    // first set the reg pointer . not sure if this works
+    readvalue[0] = (char) reg;
+     int err= i2cdev->write (i2caddr,readvalue, 1,false) ; // Write reg to an I2C slave. 3 words with stop
+     if (err) { printf("VELM7700 %d i2c err %d  in %d \n\r",err, __LINE__); }
+     //now read 
+    err = i2cdev->read( i2caddr, readvalue , 2, false) ;// read from the i2c dev with stop
+    if (err) {printf("VELM7700 %d i2c err %d  in %d \n\r",err, __LINE__); }
+    printf(" %x %x \n\r", (int) readvalue[0], (int) readvalue[1]);
+    u16 rv= readvalue[1]; rv=rv<<8;
+     rv|= readvalue[0];
+    return rv; 
+*/ 
+    char readvalue[2];
+    i2cdev-> read_reg( i2caddr , readvalue , 2, (int) reg, 1);
+     u16 rv= readvalue[1]; rv=rv<<8;
+     rv|= readvalue[0];
+    return rv; 
+    
+}
+
+
+
+// error handling via DevErrorReporter     
+void VEML7700::write_cmd( u8 reg , u16 value    ){
+    char writevalue[3]; // max 3 values to write 
+    writevalue[0] = (char) reg;
+    writevalue[1] = (char)( value & 0xFF); //Write LSByte first see data I2C interface 
+    value =value >>8;
+    writevalue[2] = (char)( value & 0xFF); //MSByte 
+    i2cdev->write(i2caddr,writevalue, 3,false) ; // Write to an I2C slave. 3 words with stop    
+}
+
+
+u16 VEML7700::get_IntT_in_set_bit( int time_ms) {
+        for ( IntTnr= 0;IntTnr <NrIntT  ;IntTnr++){
+            if( time_ms < IntTs[IntTnr] ) break;
+         }
+         if( IntTnr == NrIntT ) { IntTnr--;}
+         return    IntTSets[IntTnr];
+}
+
+void VEML7700::set_integrationtime( int time_ms ) {
+    u16 gb=get_IntT_in_set_bit(  time_ms);
+    set_IntT_bits( gb);
+}
+
+
+void VEML7700::set_gain( float gain ) {
+    u16 gb= get_gain_in_set_bit (  gain );
+    set_gain_bits( gb);
+}
+
+
+u16 VEML7700::get_gain_in_set_bit (float  gainsel ) {
+    for ( gain_nr = 0; gain_nr < NrGains; gain_nr++ ){
+        if ( gainsel <= gains[gain_nr] ) { break;}
+    }
+    if( gain_nr ==  NrGains) { gain_nr--;};
+    return GainSets[gain_nr];
+}
+
+
+u16 VEML7700::get_als_bits(void){
+    return read_cmd(ALS );
+}
+
+u16 VEML7700::get_white_ch_bits(void){
+    return read_cmd(WHITE );
+}
+// below are not necessay but useful fpr debugging 
+u16 VEML7700::get_bits(u16 regvalue,   u16 lsb ,u16 bsize ) {
+    u16 mask = 1; 
+    mask = mask << bsize ; mask = mask -1; // so bsize=3 give now mask 0  0111
+    mask = mask << lsb; // put the bits in the correct place 
+    regvalue &= mask ; //truncate if to big    
+    mask = 1; 
+    mask = mask << bsize ; mask = mask -1; // so bsize=3 give now mask 0  0111
+    regvalue = regvalue >> lsb; // set the value bits in the correct place. 
+    return   regvalue & mask;
+}   
+
+float VEML7700::decodeGainBits( u16 gb) {
+    int g_nr ; float rv=0;
+    for ( g_nr = 0; g_nr < NrGains; g_nr++ ){
+        if ( gb == GainSets[g_nr] ) { break;}                
+    }
+    if( g_nr  < NrGains) { rv = gains[gain_nr];};
+    // else not valid gain setting , return 0 
+    return rv;
+}
+
+int VEML7700::decodeIntTbits( u16 ib ) {
+        int In_nr, rv=0;
+        for ( In_nr= 0;In_nr < NrIntT  ;In_nr++){
+            if( ib == IntTSets[In_nr] ){ break;}            
+         }
+         if ( In_nr <  NrIntT) { rv =IntTs[In_nr]; };
+            //else  not valid Integration bit code  return 0 
+         return rv ;
+}
+
+void VEML7700::decode_Reg0(  bool& sd ,bool& ie, u16& pers_protect,int& IntT, float& gain  ) {
+    u16 reg= read_cmd(ALS_CONF_0);
+    u16 res= get_bits(reg, ALS_SD_LSB , ALS_SD_SIZE ) ;
+    sd = reg ? false : true;
+    res= get_bits(reg,ALS_INT_EN_LSB , ALS_INT_EN_SIZE ) ;
+    ie = reg ? false : true;
+    pers_protect= get_bits(reg,ALS_PERS_LSB , ALS_PERS_SIZE ) ;
+    res= get_bits(reg,ALS_IT_LSB , ALS_IT_SIZE ) ;
+    IntT=decodeIntTbits(res);
+    res= get_bits(reg,ALS_GAIN_LSB , ALS_GAIN_SIZE ) ; 
+    gain=decodeGainBits(res);
+}