code to access the AT30TSE75x temperature and E-prom device

Dependents:   AT30TSE752TST AT30TSE752TST2

Revision:
2:91836ad02096
Parent:
1:c0db18a0c56b
Child:
3:5944e2454e42
--- a/AT30TSE75x.cpp	Tue Jan 17 13:43:08 2017 +0000
+++ b/AT30TSE75x.cpp	Wed Jan 18 17:52:08 2017 +0000
@@ -10,7 +10,9 @@
 */
 
 
-#define VERSION_AT30TSE75x_SRC  "0.86"  
+#define VERSION_AT30TSE75x_SRC  "0.90"  
+
+#define RegisterLocDownEnable 0 // set this to one to enable permanent NV register locking , never tested with 1 
 
 #define AT30TSE75X_ADD_TEMP    0x48 /*Temperature Sensor: 0b1001xxx */
 #define AT30TSE75X_ADD_EEPROM  0x50 /*EEPROM: 0b1010xxx */
@@ -27,6 +29,8 @@
 
 #define AT30TSE_TEMPERATURE_REG_SIZE    2
 
+#define CopyNV2VolReg 0xB8
+#define CopyVolV2NVReg 0x48
 
 #define TReg 0x0  // 16 bits 
 #define ConfigReg 0x1  // 16 bits 
@@ -36,6 +40,30 @@
 #define TLowRegNV 0x12  // 16 bits 
 #define THighRegNV 0x13  // 16 bits 
 
+  /*  for no all fixed values           ..5432 1098 7654 3210
+        15 normal : 1     ONSHOT        0b1xxx xxxx xxxx xxxx
+        14:13  12 bit :11 RESOLUTION    0b1RRx xxxx xxxx xxxx
+        12:11  1 fault:00 FaultTQ       0b111F Fxxx xxxx xxxx
+        10     0 act low  AlertPol      0b1110 0Axx xxxx xxxx
+        9      0 cmp mode               0b1110 00Cx xxxx xxxx
+        8      0 temp act  SHUTDOWNM    0b1110 000S xxxx xxxx
+        7:1      dont care 0b1110 0000 0000 000x
+        0        read only 0b1110 0000 0000 0000 
+        =>  0xE0 
+    */
+
+// config 
+#define ONSHOT_BM       0x8000
+#define RESOLUTION_BM   0x6000
+#define FaultTQ_BM      0x1800
+#define ALERTPOL_BM     0x0400
+#define AlarmMode_BM    0x0200
+#define SHUTDOWN_BM     0x0100
+#define NVREGBUSY_BM    0x0001
+#define REGLOCKDOWN_BM  0x0004
+#define REGLOCK_BM      0x0002
+
+
 AT30TSE75x::AT30TSE75x (I2CInterface* i2cinterface,  int device_address_bits,int eepromsize):
     getVersion( VERSION_AT30TSE75x_HDR,VERSION_AT30TSE75x_SRC, __TIME__, __DATE__),_i2c(i2cinterface) {
     Taddr= ((device_address_bits & 0x7) |  AT30TSE75X_ADD_TEMP ) & 0x7F; Taddr=Taddr<<1;    
@@ -43,25 +71,33 @@
     
     Esize=1;
     if( eepromsize ==4 ) Esize=2; if( eepromsize ==8) Esize=3; 
-    resolution=AT30TSE_CONFIG_RES_12_bit;
+    
+    read_config(initstatus);
+    read_config(initstatus,1);
+    
 }   
 
 
-
-
-float AT30TSE75x::get_temperature(int *error) {
-   
+uint16_t  AT30TSE75x::set_temperature(float temperature ) {
+    uint16_t td;
+    uint16_t  sign= 0x8000;
+    if ( temperature  < 0)   temperature = -temperature;
+    else sign=0;
+    // this function is only used to calculate limits so we don't care
+    // about resolution settings, all is 12 bits
+    temperature=temperature *16;
+    td=(int)temperature;
+    td= td<<4;
+    if (sign){ td = ~td; td=td+1;}
+    td=td|sign;
+    return td;    
+        
+}
     
-    float temperature;
-    uint16_t data;
-    int locerr=-200;
-    buffer[0] = 0;
-    buffer[1] = 0;
-    
-    locerr=_i2c->read(Taddr,(char *)buffer,AT30TSE_TEMPERATURE_REG_SIZE,false);
-    if ( error )   *error=locerr;  // pointer !=0 
- 
-    data = (buffer[0] << 8) | buffer[1];
+
+float  AT30TSE75x::convert_temperature( uint16_t datain) {
+    uint16_t data=datain;
+    float temperature;    
     int8_t sign = 1;
  
     /* Check if negative and clear sign bit. */
@@ -71,7 +107,7 @@
     }
  
     /* Convert to temperature. */
-    switch (resolution) {
+    switch (Creg.resolution) {
     case AT30TSE_CONFIG_RES_9_bit:
         data = (data >> 7);
         (temperature) = data * sign * 0.5;
@@ -96,48 +132,280 @@
         break;
     }
     return temperature;
+
+}
+float AT30TSE75x::get_temperature(int &error) {
+   
+    
+    uint16_t data;
+    int locerr=-200;
+    buffer[0] = 0;
+    buffer[1] = 0;
+    
+    locerr=_i2c->read(Taddr,(char *)buffer,AT30TSE_TEMPERATURE_REG_SIZE,false);
+    data = (buffer[0] << 8) | buffer[1];
+    
+    error=locerr;  // pointer !=0 
+    return convert_temperature(  data);
 }     
 
 
-int AT30TSE75x::read_config( int Nonvolatille,int *error ) {
+void AT30TSE75x::set_TlowLimitRegister(int &error ,  float temperture, int Nonvolatile) {
+    uint8_t reg = TLowReg ;
+    if ( Nonvolatile) reg = TLowRegNV;
+    set_LimitRegister(error ,reg ,  temperture,  Nonvolatile);
+}
+ 
+void AT30TSE75x::set_THighLimitRegister(int &error ,  float temperture, int Nonvolatile) {
+    uint8_t reg = THighReg ;
+    if ( Nonvolatile) reg = THighRegNV;
+    set_LimitRegister(error ,reg ,  temperture,  Nonvolatile);
+}    
+void AT30TSE75x::set_LimitRegister(int &error ,uint8_t reg  ,float temperature, int Nonvolatile) {
+    int locerr;
+    if( Nonvolatile &&  CregNV.RegisterLockDown ) { error=43; return ;}
+    if(  CregNV.RegisterLock) { error=44; return; }
+    buffer[0]= reg;
+    uint16_t td=set_temperature(temperature);
+    uint16_t td_low= td & 0x0F;
+    buffer[2] = (uint8_t) td_low;
+    td = td >> 8; td= td & 0x0F;
+    buffer[1] = (uint8_t) td;
+    locerr=_i2c->write(Taddr,(char *)buffer,3,false);
+    buffer[0]=  TReg;
+     locerr= locerr<<2;
+    locerr|=_i2c->write(Taddr,(char *)buffer,1,false); // make sure temp read reg is active again 
+    error= locerr;
+}
+
+float AT30TSE75x::get_THighLimitRegister(int &error ,  float temperture, int Nonvolatile) {
+    uint8_t reg = THighReg ;
+    if ( Nonvolatile) reg = THighRegNV;
+    return get_LimitRegister(error ,reg ,  Nonvolatile);
+}
+ 
+float AT30TSE75x::get_TLowLimitRegister(int &error ,  float temperture, int Nonvolatile) {
+    uint8_t reg = TLowReg ;
+    if ( Nonvolatile) reg = TLowRegNV;
+    return get_LimitRegister(error ,reg ,  Nonvolatile);
+}
+    
+float  AT30TSE75x::get_LimitRegister(int &error ,uint8_t reg  , int Nonvolatile) {
+    int locerr;
+    
+    buffer[0]= reg;
+    locerr=_i2c->write(Taddr,(char *)buffer,1,false); // set reg addres to read
+    error = locerr<<2;
+    locerr =  _i2c->read(Taddr,(char *)buffer,AT30TSE_TEMPERATURE_REG_SIZE,false);
+    uint16_t data = (buffer[0] << 8) | buffer[1];
+    buffer[0]=  TReg;
+    locerr= locerr<<2;
+    locerr|=_i2c->write(Taddr,(char *)buffer,1,false); // make sure temp read reg is active again 
+    error= locerr;
+    return convert_temperature(  data);
+}
+    
+void AT30TSE75x::CopyNonVolatile2VolatileRegisters( int &error) {
+    if ( CregNV.RegisterLock ) { error=43; return ;}
+    if ( CregNV.RegisterLockDown ) { error=44; return ;}
+    CopyRegisters( error,CopyNV2VolReg);    
+}
+
+void AT30TSE75x::CopyVolatile2NoneVolatileRegisters( int &error) { 
+    if ( CregNV.RegisterLock ) { error=43; return ;}
+    CopyRegisters( error, CopyVolV2NVReg);
+}    
+
+void AT30TSE75x::CopyRegisters( int &error , uint8_t reg) {  
+    int locerr;
+    bool busy=true;
+    int lc=3;
+    while ( busy && lc--) { 
+        (void) read_config(locerr,0);
+        if ( locerr ) { error =locerr ; return;}
+        busy =Creg.NVregBusy;
+        if(busy) wait_ms(100);
+    }
+    if ( busy ) { error =22; return ;}
+    
+    buffer[0]= reg;
+    locerr=_i2c->write(Taddr,(char *)buffer,1,false);
+    // not sure if this is needed  
+    buffer[0]=  TReg;
+    locerr= locerr<<2;
+    locerr|=_i2c->write(Taddr,(char *)buffer,1,false); // make sure temp read reg is active again 
+    error= locerr;
+}   
+
+
+uint16_t AT30TSE75x::read_config(int &error, int Nonvolatile ) {
     uint16_t data;
+    uint16_t td;
     int locerr;
-    buffer[0]=  ConfigReg; // set pointer to config reg nv 
+    if ( Nonvolatile) buffer[0]=  ConfigRegNV; else buffer[0]=  ConfigReg;
      locerr=_i2c->write(Taddr,(char *)buffer,1,false);
      locerr= locerr<<2;
     locerr|=_i2c->read(Taddr,(char *)buffer,AT30TSE_TEMPERATURE_REG_SIZE,false);
      locerr= locerr<<2;
     data = (buffer[0] << 8) | buffer[1];
     buffer[0]=  TReg;
-    locerr|=_i2c->write(Taddr,(char *)buffer,1,false);
-    if ( error )   *error=locerr;  // pointer !=0 
+    locerr|=_i2c->write(Taddr,(char *)buffer,1,false); // set back to read Treg
+    error=locerr;  
+    if ( locerr == 0) {
+        struct configreg *lcreg;
+        if(  Nonvolatile) lcreg =&CregNV; else lcreg =&Creg;     
+        lcreg->oneshot =bool  ( data  & ONSHOT_BM); // should be 0 when reading
+        td = data &  RESOLUTION_BM ; td = td >> 13; lcreg->resolution =td;
+        td = data & FaultTQ_BM ; td = td >> 11;  lcreg->faultTolQueue=td;  
+        lcreg->alertpol =bool  ( data  & ALERTPOL_BM);
+        lcreg->alarmMode =bool  ( data  & AlarmMode_BM);
+        lcreg->shutdownMode =bool  ( data  & SHUTDOWN_BM);
+        lcreg->RegisterLockDown =bool  ( data  & REGLOCKDOWN_BM);
+        lcreg->RegisterLock =bool  ( data  & REGLOCK_BM);
+        lcreg->NVregBusy =bool  ( data  & NVREGBUSY_BM);
+    }
     return (int)data;
 }    
 
 
-int AT30TSE75x::set_config( int Nonvolatille ) {
-    int locerr;
-    buffer[0]=  ConfigReg; // set pointer to config reg nv 
-   
-      
+int AT30TSE75x::get_NonevolatileBussy(int &error){
+       uint16_t data= read_config(error, 0 ) ;
+       return (int) Creg.NVregBusy;
+    }
     
-    /*  for no all fixed values 
-        15 normal : 1      0b1xxx xxxx xxxx xxxx
-        14:13  12 bit :11  0b111x xxxx xxxx xxxx
-        12:11  1 fault:00  0b1110 0xxx xxxx xxxx
-        10     0 act low   0b1110 00xx xxxx xxxx
-        9      0 cmp mode  0b1110 000x xxxx xxxx
-        8      0 temp act  0b1110 0000 xxxx xxxx
-        7:1      dont care 0b1110 0000 0000 000x
-        0        read only 0b1110 0000 0000 0000 
-        =>  0xE0 
-    */
-    buffer[1]=0xE0; buffer[2]=0x00;
+void AT30TSE75x::set_resolution(int resolution , int &error,  int Nonvolatile,bool write, bool update ){
+    int locerr;
+    if( resolution ==12 ) resolution =   AT30TSE_CONFIG_RES_12_bit;
+    if( resolution ==11 ) resolution =   AT30TSE_CONFIG_RES_11_bit;
+    if( resolution ==10 ) resolution =   AT30TSE_CONFIG_RES_10_bit;
+    if( resolution ==9 ) resolution =   AT30TSE_CONFIG_RES_9_bit;
+    if ( resolution >=0 && resolution <=3 ) {
+        if ( update ) read_config(locerr, Nonvolatile ) ;
+        error=locerr<<2;
+        if(  Nonvolatile) CregNV.resolution=resolution; else Creg.resolution=resolution;
+        if(write ) set_config(locerr,  Nonvolatile ) ;
+        error |= locerr;
+    }
+    error=36; // invalid resolution    
+ }   
+
+void AT30TSE75x::set_FaultTollerantQueue(int ftq, int &error, int Nonvolatile, bool write, bool update ){
+   int locerr;
+   if ( ftq >=0 && ftq <=3 ) {
+        if ( update ) read_config(locerr, Nonvolatile ) ;
+        error=locerr<<2;
+        if(  Nonvolatile) CregNV.faultTolQueue=ftq; else Creg.faultTolQueue=ftq;
+        if(write ) set_config(locerr,  Nonvolatile ) ;
+        error |= locerr;
+    }
+    error=36; // invalid value
+}   
+
+
+void AT30TSE75x::set_AlertPinPolarity(int pol, int &error,  int Nonvolatile,bool write, bool update ){
+        int locerr;
+        bool mode=(bool) pol;
+        if ( update ) read_config(locerr, Nonvolatile ) ;
+        error=locerr<<2;
+        if(  Nonvolatile) CregNV.alertpol=mode; else Creg.alertpol=mode;
+        if(write ) set_config(locerr,  Nonvolatile ) ;
+        error |= locerr;
+}
+
+void AT30TSE75x::set_AlarmThermostateMode(int modein, int &error,  int Nonvolatile,bool write, bool update ){
+        int locerr;
+        bool mode=(bool) modein;
+        if ( update ) read_config(locerr, Nonvolatile ) ;
+        error=locerr<<2;
+        if(  Nonvolatile) CregNV.alarmMode=mode; else Creg.alarmMode=mode;
+        if(write ) set_config(locerr,  Nonvolatile ) ;
+        error |= locerr;
+}
+
+
+void AT30TSE75x::set_ShutdownMode(int modein, int &error,  int Nonvolatile,bool write, bool update ){
+        int locerr;
+        bool mode=(bool) modein;
+        if ( update ) read_config(locerr, Nonvolatile ) ;
+        error=locerr<<2;
+        if(  Nonvolatile) CregNV.shutdownMode=mode; else Creg.shutdownMode=mode;
+        if(write ) set_config(locerr,  Nonvolatile ) ;
+        error |= locerr;
+}
+void AT30TSE75x::set_FaultTollerantQueue(char nrfaults, int &error, int Nonvolatile, bool write, bool update ){
+    int ftq=7;
+    if ( nrfaults == '1') ftq=0;
+    if ( nrfaults == '2') ftq=1;
+    if ( nrfaults == '4') ftq=2;
+    if ( nrfaults == '6') ftq=3;
+    set_FaultTollerantQueue( ftq,error, Nonvolatile,  write,  update);
+}
+
+void AT30TSE75x::activate_oneshot(int &error  ){
+    int locerr;
+    buffer[0]=  ConfigReg;
+    locerr=_i2c->write(Taddr,(char *)buffer,1,false);
+    locerr= locerr<<2;
+    locerr|=_i2c->read(Taddr,(char *)buffer,AT30TSE_TEMPERATURE_REG_SIZE,false);
+    locerr= locerr<<2;
+    buffer[0]=  ConfigReg;
+    buffer[1] = 0x80  ; //set once shot MSByte 
+    buffer[2] = 0 ; // volataille  
     locerr=_i2c->write(Taddr,(char *)buffer,3,false);
     buffer[0]=  TReg;
-     locerr= locerr<<2;
+    locerr= locerr<<2;
     locerr|=_i2c->write(Taddr,(char *)buffer,1,false); // make sure temp read reg is active again 
-    return locerr;
+    error=locerr;
+}    
+
+void AT30TSE75x::set_RegisterLock (int &error, int lock   ){
+     int locerr;
+     (void)read_config(locerr,1 );
+     error= locerr<<2;
+     CregNV.RegisterLock    =lock;
+     set_config(locerr,1 );
+     error |= locerr;
+}    
+    
+void AT30TSE75x::set_RegisterLockdown (int &error, int lockpermanent  ){
+    int locerr;
+    if( RegisterLocDownEnable) {
+         if ( error != 123) {error=36; return;}
+         (void)read_config(locerr,1 );
+          error= locerr<<2;
+          CregNV. RegisterLockDown   = lockpermanent;
+          set_config(locerr,1 );
+         error |= locerr;
+    }
+    else { error =36 ;}
+}    
+    
+
+
+void AT30TSE75x::set_config( int &error, int Nonvolatile ) {
+    int locerr;
+    struct configreg *lcreg=&Creg;
+    if ( Creg.RegisterLockDown && Nonvolatile  ) { locerr = 43; return; }
+    if ( Creg.RegisterLock  ) { locerr = 44; return; }
+    if ( Nonvolatile) buffer[0]=  ConfigRegNV; else buffer[0]=  ConfigReg; 
+    if(  Nonvolatile) lcreg =&CregNV; else lcreg =&Creg; 
+    uint16_t ld=0, td;
+    if ( lcreg->oneshot) ld= ONSHOT_BM;  // no effect for NV reg
+    td= (lcreg->resolution) <<13; ld= ld | td;
+    td= (lcreg->faultTolQueue) <<11; ld= ld | td;
+    if ( lcreg->alertpol) ld=ld |ALERTPOL_BM;
+    if ( lcreg-> alarmMode) ld=ld |AlarmMode_BM; 
+    if ( lcreg-> shutdownMode) ld=ld |SHUTDOWN_BM; 
+    if ( lcreg->  RegisterLockDown) ld=ld |(REGLOCKDOWN_BM & RegisterLocDownEnable); 
+    if ( lcreg->  RegisterLock) ld=ld |(REGLOCK_BM ); 
+    if(  Nonvolatile )  ld=ld; else ld= 0xFF00 & ld;
+    buffer[2]=ld & 0xFF; ld = ld>>8;
+    buffer[1]=ld & 0xFF;    
+    locerr=_i2c->write(Taddr,(char *)buffer,3,false);
+    buffer[0]=  TReg;
+    locerr= locerr<<2;
+    locerr|=_i2c->write(Taddr,(char *)buffer,1,false); // make sure temp read reg is active again 
+    error= locerr;
 }