Kevin Braun / MLX9062x

Dependents:   KL25Z_MLX90620

Revision:
1:fd536ebc7eaf
Parent:
0:8c2ddd9801ca
Child:
2:82782c73251e
--- a/MLX90620.cpp	Tue Jun 14 19:17:47 2016 +0000
+++ b/MLX90620.cpp	Thu Jul 21 23:09:24 2016 +0000
@@ -4,62 +4,46 @@
 #include "mbed.h"
 #include "MLX90620.h"
 
-//these bufferes must reside in main.cpp
-//extern char* MLXEEbuf;                         //256 uint8_ts, holds contents of EEPROM
-//extern char* MLXRamBuf;                        //128 uint8_ts, 0x0 - 0x3f 'uint16_t', holds contents of RAM array
-//extern char* MLXRamCmmd;                       //  8 uint8_ts, MLX90620 i2c command i/o buffer
-/*
-uint16_t Config = 0;                  //MLX90620 configuration register
-uint16_t OscTrim = 0;                 //MLX90620 oscillator trim register
-uint16_t PtatD = 0;                   //MLX90620 PTAT data register
-int16_t VCP = 0;                              //VCP / TGC
-int16_t Vth25X = 0;
-float TaXX = 0.0;
-
-//For To
-int8_t AcpX = 0;
-int8_t BcpX = 0;
-float Kt1fX = 0.0;
-float Kt2fX = 0.0;
-int8_t TGCX = 0;
-uint8_t BiScaleX = 0;
-uint16_t theta0X = 0;
-uint8_t theta0ScaleX = 0;
-uint8_t deltaThetaScaleX = 0;
-uint16_t elipsonX = 0;
-int8_t AiPixelX = 0;                   //eeprom address range 0x00 - 0x3f
-int8_t BiPixelX = 0;                   //eeprom address range 0x40 - 0x7f
-uint8_t dThetaPixelX = 0;                      //eeprom address range 0x80 - 0xbf
-int16_t VirPixelX = 0;
-double TempPxlX = 0;
-*/
+//for debugging purposes (uncomment)
+//#define MLXTEST_621b         1
 
 //--------------------------------------------------------------------------------------------------------------------------------------//
-// Constructor
+// Original Constructor
 
-MLX90620::MLX90620(PinName sda, PinName scl, const char* name) : _i2c(sda, scl){
+MLX9062x::MLX9062x(PinName sda, PinName scl, const char* name) : _i2c(sda, scl){
     _i2c.frequency(400000);                             //set up i2c speed
     _i2c.stop();                                        //initialize with a stop
+    mlxDev = mlx90620;                                  //default device is MLX90620
 }
 
 //--------------------------------------------------------------------------------------------------------------------------------------//
-//copy contents of EEPROM inside the MLX90620 into a local buffer.  Data is used for lookup tables and parameters
+// Additional Constructor for selecting the MLX device
+
+MLX9062x::MLX9062x(PinName sda, PinName scl, MLXdevice MLXtype, const char* name) : _i2c(sda, scl){
+    _i2c.frequency(400000);                             //set up i2c speed
+    _i2c.stop();                                        //initialize with a stop
+    mlxDev = MLXtype;                                   //user select device 620 or 621
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//copy contents of EEPROM inside the MLX9062x into a local buffer.  Data is used for lookup tables and parameters
 
 #define MLX_EEP_EASY_LOAD        1
 
-int MLX90620::LoadEEPROM(mlx_struct& Pntr) {
+int MLX9062x::LoadEEPROM(mlx_struct& Pntr) {
+    Pntr.mlx621IDhi = 0;
+    Pntr.mlx621IDlo = 0;
+    Pntr.mlxDevice = mlxDev;                                    //make strurcture device same as local device
     
     //clear out buffer first
-    for(int i = 0; i < 256; i++) {                      //option to clear out EEPROM buffer first
-        Pntr.MLXEEbuf[i] = 0;
-    }
+    for(int i = 0; i < 256; i++) Pntr.MLXEEbuf[i] = 0;  //clear out entire EEMPROM buffer
     
     //load the entire EEPROM
     Pntr.MLXEEbuf[0] = 0;                                       //start at address 0 of EEPROM
     if(!_i2c.write(MLX_EEPADDR, Pntr.MLXEEbuf, 1, true)) {      //send command, 0 returned is ok
 
 #ifdef MLX_EEP_EASY_LOAD
-        _i2c.read((MLX_EEPADDR + 1), Pntr.MLXEEbuf, 256);             //**** this command does not work with the KL25Z anv v63 of mbed.lbr !!!!  //load contents of EEPROM
+        _i2c.read((MLX_EEPADDR + 1), Pntr.MLXEEbuf, 256);//**** this command does not work with the KL25Z and v63 of mbed.lbr !!!!
 #else
         _i2c.start();
         _i2c.write(MLX_EEPADDR + 1);
@@ -73,57 +57,73 @@
         _i2c.stop();                                    //don't read EEP if write is broken
         return(1);                                      //return with error
     }
+    if(Pntr.mlxDevice == mlx90621) {
+        Pntr.mlx621IDhi = (Pntr.MLXEEbuf[MLX621_EE_ID_BASE + 7] << 24) | (Pntr.MLXEEbuf[MLX621_EE_ID_BASE + 6] << 16) | 
+                          (Pntr.MLXEEbuf[MLX621_EE_ID_BASE + 5] <<  8) |  Pntr.MLXEEbuf[MLX621_EE_ID_BASE + 4];
+        Pntr.mlx621IDlo = (Pntr.MLXEEbuf[MLX621_EE_ID_BASE + 3] << 24) | (Pntr.MLXEEbuf[MLX621_EE_ID_BASE + 2] << 16) | 
+                          (Pntr.MLXEEbuf[MLX621_EE_ID_BASE + 1] <<  8) |  Pntr.MLXEEbuf[MLX621_EE_ID_BASE + 0];
+    }
     return(0);                                          //return with ok
 }
 
 //--------------------------------------------------------------------------------------------------------------------------------------//
-//copy oscillator offset from MLXEEbuf to MLX90620 (MS byte = 0)
+//copy oscillator offset from MLXEEbuf to MLX9062x (MS byte on 620 always = 0)
 
-int MLX90620::SetOscTrimReg(mlx_struct& Pntr) { 
+int MLX9062x::SetOscTrimReg(mlx_struct& Pntr) {
     Pntr.MLXRamCmmd[0] = 4;                                     //command
-    Pntr.MLXRamCmmd[1] = Pntr.MLXEEbuf[MLX_EETRIM] - 0xaa;              //LS byte check
-    Pntr.MLXRamCmmd[2] = Pntr.MLXEEbuf[MLX_EETRIM];                     //oscillator trim value
+    Pntr.MLXRamCmmd[1] = Pntr.MLXEEbuf[MLX620_EETRIM] - 0xaa;   //LS byte check
+    Pntr.MLXRamCmmd[2] = Pntr.MLXEEbuf[MLX620_EETRIM];          //oscillator trim value
     Pntr.MLXRamCmmd[3] = 0x100 - 0xaa;                          //MS byte check
     Pntr.MLXRamCmmd[4] = 0;                                     //MS byte = 0
     int r = _i2c.write(MLX_RAMADDR, Pntr.MLXRamCmmd, 5, false); //send command
-    return(r);                                          //return ok or error
+    //printf("OscTrim-W: %02x %02x %02x %02x %02x\r\n", Pntr.MLXRamCmmd[0], Pntr.MLXRamCmmd[1], Pntr.MLXRamCmmd[2], Pntr.MLXRamCmmd[3], Pntr.MLXRamCmmd[4]);
+    return(r);                                                  //return ok or error
 }
 
 //--------------------------------------------------------------------------------------------------------------------------------------//
-//get oscillator offset register from MLX90620
+//get oscillator offset register from MLX9062x
 
-uint16_t MLX90620::GetOscTrimReg(mlx_struct& Pntr) { 
+uint16_t MLX9062x::GetOscTrimReg(mlx_struct& Pntr) { 
     Pntr.MLXRamCmmd[0] = 2;                                     //command
     Pntr.MLXRamCmmd[1] = MLX_TRIM;                              //address of register
     Pntr.MLXRamCmmd[2] = 0;                                     //address step
     Pntr.MLXRamCmmd[3] = 1;                                     //# of reads
     _i2c.write(MLX_RAMADDR, Pntr.MLXRamCmmd, 4, true);          //send command  
-    _i2c.read(MLX_RAMADDR, Pntr.MLXRamCmmd, 2);                 //get 16 bit register
-    Pntr.OscTrim = (Pntr.MLXRamCmmd[1] << 8) + Pntr.MLXRamCmmd[0];           //store register
-    return(Pntr.OscTrim);                                    //return value
+    _i2c.read(MLX_RAMADDR, Pntr.MLXRamCmmd, 2, false);          //get 16 bit register
+    Pntr.OscTrim = (Pntr.MLXRamCmmd[1] << 8) + Pntr.MLXRamCmmd[0]; //store register
+    //printf("OscTrim-R: %02x %02x\r\n", Pntr.MLXRamCmmd[0], Pntr.MLXRamCmmd[1]);
+    return(Pntr.OscTrim);                                       //return value
 }
 
 //--------------------------------------------------------------------------------------------------------------------------------------//
 //initialize the configuration register
 //******* NOTE: Step measurement mode was removed from new data sheet dated   Sept 19 2012
 
-int MLX90620::SetConfigReg(mlx_struct& Pntr) {   
-    Pntr.MLXRamCmmd[0] = 3;                                     //command
-    //old mode
-    //MLXRamCmmd[1] = 0x14c - 0x55;                          //LS byte check
-    //MLXRamCmmd[2] = 0x4c;                                  //LS config value, step meas mode, 4Hz array  *******
-    Pntr.MLXRamCmmd[1] = 0x10c - 0x55;                          //LS byte check
-    Pntr.MLXRamCmmd[2] = 0x0c;                                  //LS config value, normal mode, 4Hz array  *******
-    Pntr.MLXRamCmmd[3] = 0x5c - 0x55;                           //MS byte check
-    Pntr.MLXRamCmmd[4] = 0x5c;                                  //MS config value, 8Hz Ta, 400k i2c
+int MLX9062x::SetConfigReg(mlx_struct& Pntr) {  
+    Pntr.MLXRamCmmd[0] = 3;                                     //command 
+    if(Pntr.mlxDevice == mlx90621) {
+        Pntr.MLXRamCmmd[2] = Pntr.MLXEEbuf[MLX621_CONFIG_LO];   //LS byte
+        Pntr.MLXRamCmmd[4] = Pntr.MLXEEbuf[MLX621_CONFIG_HI];   //MS byte
+        //here you can manipulate the Config Register contents from the default EEPROM values of 0x463e
+        Pntr.MLXRamCmmd[2] = (Pntr.MLXRamCmmd[2] & ~MLX621_CONF_ADC_MASK) | MLX621_CONF_ADC18;
+        Pntr.MLXRamCmmd[4] = Pntr.MLXRamCmmd[4] | (MLX621_CONF_MD_1 >> 8);
+        Pntr.MLXRamCmmd[1] = Pntr.MLXRamCmmd[2] - 0x55;         //LS byte check
+        Pntr.MLXRamCmmd[3] = Pntr.MLXRamCmmd[4] - 0x55;         //MS byte check
+    } else {
+        Pntr.MLXRamCmmd[1] = 0x10c - 0x55;                      //LS byte check
+        Pntr.MLXRamCmmd[2] = 0x0c;                              //LS config value, normal mode, 4Hz array  *******
+        Pntr.MLXRamCmmd[3] = 0x5c - 0x55;                       //MS byte check
+        Pntr.MLXRamCmmd[4] = 0x5c;                              //MS config value, 8Hz Ta, 400k i2c
+    }
     int r = _i2c.write(MLX_RAMADDR, Pntr.MLXRamCmmd, 5, false);
+    //printf("Command-W: %02x %02x %02x %02x %02x\r\n", Pntr.MLXRamCmmd[0], Pntr.MLXRamCmmd[1], Pntr.MLXRamCmmd[2], Pntr.MLXRamCmmd[3], Pntr.MLXRamCmmd[4]);
     return(r);
 }
 
 //--------------------------------------------------------------------------------------------------------------------------------------//
-//get configuration register from MLX90620
+//get configuration register from MLX9062x
 
-uint16_t MLX90620::GetConfigReg(mlx_struct& Pntr) { 
+uint16_t MLX9062x::GetConfigReg(mlx_struct& Pntr) { 
     Pntr.MLXRamCmmd[0] = 2;                                     //command
     Pntr.MLXRamCmmd[1] = MLX_CONFIG;                            //address of register
     Pntr.MLXRamCmmd[2] = 0;                                     //address step
@@ -135,52 +135,78 @@
 }
 
 //--------------------------------------------------------------------------------------------------------------------------------------//
-//get PTAT register from MLX90620
+//get PTAT register from MLX9062x
 
-uint16_t MLX90620::GetPTATReg(mlx_struct& Pntr) { 
+uint16_t MLX9062x::GetPTATReg(mlx_struct& Pntr) { 
     Pntr.MLXRamCmmd[0] = 2;                                     //command
-    Pntr.MLXRamCmmd[1] = MLX_PTATSENS;                          //address of register
+    Pntr.MLXRamCmmd[1] = MLX620_PTATSENS;                       //address of register
+    if(Pntr.mlxDevice == mlx90621) Pntr.MLXRamCmmd[1] = MLX621_PTATSENS;
     Pntr.MLXRamCmmd[2] = 0;                                     //address step
     Pntr.MLXRamCmmd[3] = 1;                                     //# of reads
     _i2c.write(MLX_RAMADDR, Pntr.MLXRamCmmd, 4, true); 
     _i2c.read(MLX_RAMADDR, Pntr.MLXRamCmmd, 2);
     Pntr.PtatD = (Pntr.MLXRamCmmd[1] << 8) + Pntr.MLXRamCmmd[0];
+#ifdef MLXTEST_621b
+    if(Pntr.mlxDevice == mlx90620) {
+        Pntr.PtatD = 0x1ac0;
+    } else {
+        if(ConfigReg54 == 0) {
+            Pntr.PtatD = 0x0cfb;
+        } else
+        if(ConfigReg54 == 1) {
+            Pntr.PtatD = 0x19f7;
+        } else
+        if(ConfigReg54 == 2) {
+            Pntr.PtatD = 0x33ef;
+        } else
+        if(ConfigReg54 == 3) {
+            Pntr.PtatD = 0x67de;
+        } else {
+            Pntr.PtatD = 0;
+        }
+    }
+#endif
     return(Pntr.PtatD);
 }
 
 //--------------------------------------------------------------------------------------------------------------------------------------//
-//get VCP / TGC register from MLX90620
+//get VCP / TGC register from MLX9062x
 
-int16_t MLX90620::GetTGCReg(mlx_struct& Pntr) { 
+int16_t MLX9062x::GetTGCReg(mlx_struct& Pntr) { 
     Pntr.MLXRamCmmd[0] = 2;                                     //command
-    Pntr.MLXRamCmmd[1] = MLX_TGCSENS;                           //address of register
+    Pntr.MLXRamCmmd[1] = MLX620_TGCSENS;                        //address of register
+    if(Pntr.mlxDevice == mlx90621) Pntr.MLXRamCmmd[1] = MLX621_TGCSENS;
     Pntr.MLXRamCmmd[2] = 0;                                     //address step
     Pntr.MLXRamCmmd[3] = 1;                                     //# of reads
     _i2c.write(MLX_RAMADDR, Pntr.MLXRamCmmd, 4, true);
     _i2c.read(MLX_RAMADDR, Pntr.MLXRamCmmd, 2); 
-    VCP = (Pntr.MLXRamCmmd[1] << 8) + Pntr.MLXRamCmmd[0];
+    int16_t VCP = (Pntr.MLXRamCmmd[1] << 8) + Pntr.MLXRamCmmd[0];
+#ifdef MLXTEST_621b
+    VCP = 0xffdc;
+#endif
+    Pntr.VCP = VCP;
     return(VCP);
 }
 
 //--------------------------------------------------------------------------------------------------------------------------------------//
-//get RAM dump from MLX90620
-bool firstDump = false;
+//get RAM dump from MLX9062x
 
-void MLX90620::LoadMLXRam(mlx_struct& Pntr) { 
+void MLX9062x::LoadMLXRam(mlx_struct& Pntr) { 
     Pntr.MLXRamCmmd[0] = 2;                                     //command
     Pntr.MLXRamCmmd[1] = 0;                                     //start address
     Pntr.MLXRamCmmd[2] = 1;                                     //address step
     Pntr.MLXRamCmmd[3] = 0x40;                                  //# of reads
     _i2c.write(MLX_RAMADDR, Pntr.MLXRamCmmd, 4, true);
     _i2c.read(MLX_RAMADDR, Pntr.MLXRamBuf, 0x80); 
-    Pntr.PtatD = MLX90620::GetPTATReg(Pntr);
-    VCP = MLX90620::GetTGCReg(Pntr);
+    Pntr.PtatD = MLX9062x::GetPTATReg(Pntr);
+    Pntr.VCP = MLX9062x::GetTGCReg(Pntr);
 }
 
 //--------------------------------------------------------------------------------------------------------------------------------------//
-//start measurement MLX90620
+//start measurement MLX9062x
 
-int MLX90620::StartMeasurement(mlx_struct& Pntr) {   
+int MLX9062x::StartMeasurement(mlx_struct& Pntr) {  
+    if(Pntr.mlxDevice == mlx90621)  return(0);                          //there is no start_meas in the 90621  
     Pntr.MLXRamCmmd[0] = 1;                                     //command
     Pntr.MLXRamCmmd[1] = 8;                                     //address of config register
     int r = _i2c.write(MLX_RAMADDR, Pntr.MLXRamCmmd, 2, false);
@@ -188,88 +214,447 @@
 }
 
 //--------------------------------------------------------------------------------------------------------------------------------------//
-// Initial Calculations for Ta and To
+// Only a test to set up values in EEPROM and RAM buffers to debug math.
+//Note: must be performed after reading the EEPROM and RAM data
 
-float MLX90620::GetDieTemp(mlx_struct& Pntr) {
-    Pntr.PtatD = MLX90620::GetPTATReg(Pntr);
-    float TaX = (-Kt1fX + sqrt(pow(Kt1fX, 2.0f) - 4.0f * Kt2fX * ((float)(Vth25X - Pntr.PtatD))))/(2.0f * Kt2fX) + 25.0f;
-    return(TaX);
+void MLX9062x::DSSetup(mlx_struct& Pntr, int Pixel) {
+#ifdef MLXTEST_621b
+#warning "MLX90620 test mode B"
+    if(Pntr.mlxDevice == mlx90620) {
+        Pntr.MLXEEbuf[0xda] = 0x78;
+        Pntr.MLXEEbuf[0xdb] = 0x1a;
+        Pntr.MLXEEbuf[0xdc] = 0x33;
+        Pntr.MLXEEbuf[0xdd] = 0x5b;
+        Pntr.MLXEEbuf[0xde] = 0xcc;
+        Pntr.MLXEEbuf[0xdf] = 0xed;
+    } else {
+        //7.3.2 for Ta Calculations
+        Pntr.MLXEEbuf[0xda] = 0x20;
+        Pntr.MLXEEbuf[0xdb] = 0x64;
+        Pntr.MLXEEbuf[0xdc] = 0x89;
+        Pntr.MLXEEbuf[0xdd] = 0x55;
+        Pntr.MLXEEbuf[0xde] = 0x7e;
+        Pntr.MLXEEbuf[0xdf] = 0x5e;
+        Pntr.MLXEEbuf[0xd2] = 0x8b;
+        
+        //7.3.4 for To Calculations (pixel 11)
+        Pntr.MLXEEbuf[0x00 + Pixel] = 0x21;
+        Pntr.MLXEEbuf[0x40 + Pixel] = 0xbc;
+        Pntr.MLXEEbuf[0x80 + Pixel] = 0xcd;
+        
+        Pntr.MLXEEbuf[0xc0] = 0x99;
+        Pntr.MLXEEbuf[0xc4] = 0x9e;
+        
+        Pntr.MLXEEbuf[0xd0] = 0x8a;
+        Pntr.MLXEEbuf[0xd1] = 0xff;
+    
+        Pntr.MLXEEbuf[0xd3] = 0x9d;
+        Pntr.MLXEEbuf[0xd4] = 0xff;
+        Pntr.MLXEEbuf[0xd5] = 0xa2;
+        Pntr.MLXEEbuf[0xd6] = 0xa8;
+        Pntr.MLXEEbuf[0xd7] = 0x0f;
+        Pntr.MLXEEbuf[0xd8] = 0x18;
+        Pntr.MLXEEbuf[0xd9] = 0x07;
+        
+        Pntr.MLXEEbuf[0xe0] = 0xae;
+        Pntr.MLXEEbuf[0xe1] = 0x4e;
+        Pntr.MLXEEbuf[0xe2] = 0x26;
+        Pntr.MLXEEbuf[0xe3] = 0x1f;
+        Pntr.MLXEEbuf[0xe4] = 0x00;
+        Pntr.MLXEEbuf[0xe5] = 0x80;
+        Pntr.MLXEEbuf[0xe6] = 0x0c;
+        Pntr.MLXEEbuf[0xe7] = 0x02;
+        
+        VirPix = 0x01b7;
+    }
+#endif
 }
 
 //--------------------------------------------------------------------------------------------------------------------------------------//
 // Initial Calculations for Ta and To
 
-void MLX90620::CalcTa_To(mlx_struct& Pntr) {
-    //Calculate Ta first
-    Vth25X =      (Pntr.MLXEEbuf[MLX_TAINDEX +  1] << 8) + Pntr.MLXEEbuf[MLX_TAINDEX +  0];
-    int16_t Kt1 = (Pntr.MLXEEbuf[MLX_TAINDEX +  3] << 8) + Pntr.MLXEEbuf[MLX_TAINDEX +  2];
-    int16_t Kt2 = (Pntr.MLXEEbuf[MLX_TAINDEX +  5] << 8) + Pntr.MLXEEbuf[MLX_TAINDEX +  4];
-    Kt1fX = Kt1 / 1024.0;
-    Kt2fX = Kt2 / 1048576.0;
-    TaXX = MLX90620::GetDieTemp(Pntr);
+//#define MLXTEST_621         1
+
+double MLX9062x::GetDieTemp(mlx_struct& Pntr) {
+    Pntr.PtatD = MLX9062x::GetPTATReg(Pntr);
+
+    //Note: There seems to be a scaling error in the following routine
+    //MLX621_CONF_ADC18 = +26.891C
+    //MLX621_CONF_ADC17 = +25.934C
+    //MLX621_CONF_ADC16 = +25.467C
+    //MLX621_CONF_ADC15 = +25.187C
+
+    double TaX = (-Kt1_f + sqrt(pow(Kt1_f, 2.0) - 4.0 * Kt2_f * (((Vth25 - (double)Pntr.PtatD)/ScaleCR54))))/(2.0 * Kt2_f) + 25.0;
+    Pntr.DieTemp = TaX;
+    return(TaX);
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+// Display internal PIXEL registers for debugging math
+
+void MLX9062x::DumpPixRegs(mlx_struct& Pntr, int Pixel) {
+#ifdef MLXTEST_621b
+    if(Pntr.mlxDevice == mlx90620) {
+    /*
+        printf("\r\n\r\npixel = %d\r\n", Pixel);
+        printf("Acp   = %d\r\nBcp   = %d\r\nBiS   = %d\r\n", AcpX, BcpX, BiScaleX);
+        printf("Vcp   = %d\r\neps   = %d\r\nTGC   = %d\r\n", VCP, elipsonX, TGCX);
+        printf("Vcp_off_comp             = %f\r\n", Vcp_off_comp);
+        printf("VirPix_off_comp        = %f\r\n", VirPix_off_comp);
+        printf("VirPix                 = %d\r\n", VirPix);
+        printf("AiPix                  = %d\r\n", AiPix);
+        printf("BiPix                  = %d\r\n", BiPix);
+        printf("BiScale                  = %d\r\n", BiScaleX);
+        printf("2^BiScale                = %f\r\n", (powf(2.0,BiScaleX)));
+        printf("1 << BiScale             = %d\r\n", (1 << BiScaleX));
+        printf("Ta-25.0                  = %f\r\n", (Ta - 25.0f));
+        printf("BiPix/2^BiScale          = %f\r\n", (BiPix / powf(2.0,BiScaleX)));
+        printf("AiP+BiP/2^BiScale)*(Ta-25= %f\r\n", (AiPix + BiPix / powf(2.0,BiScaleX) * (Ta - 25.0f)));
+        printf("VirPix_off_comp again  = %f\r\n", (VirPix - (AiPix + BiPix / powf(2.0,BiScaleX) * (Ta - 25.0f))));
+        printf("VirPix_off_comp2 step  = %f\r\n", VirPix_off_comp2);
+        printf("VirPix_tgc_comp        = %f\r\n", VirPix_tgc_comp);
+        printf("elipsonf                 = %f\r\n", elipsonf);
+        printf("VirPix_comp            = %f\r\n", VirPix_comp);
+        printf("theta28                  = %f  << double print problem\r\n", (theta28 * 100000000.0));  //<<< can't print a double
+        printf("TempPxl                  = %f\r\n",  TempPxl);
+*/
+    
+    } else {
+        printf("Pixel,%2d\r\n", Pixel);
+    
+        //DSSetup(Pntr, Pixel);
+        printf("VirPix,%d,%x\r\n", VirPix, VirPix);
+        printf("VCP,%d\r\n", Pntr.VCP);
+        printf("Ta,%.3f\r\n\r\n", Ta);
+        
+        printf("Acommon_mod,%d\r\n", Acommon);
+        printf("AiPix,%d\r\n", AiPix);
+        printf("Ai_ij_f,%.16f\r\n", Ai_ij); 
+        printf("BiPix_mod,%d\r\n", BiPix);
+        printf("Bi_ij_f,%.16f\r\n", Bi_ij);
+        printf("VirOffComp,%.16f\r\n", VirOffComp);
+        printf("ACP_ee_mod,%d\r\n", ACP_ee); 
+        int8_t bCPx = Pntr.MLXEEbuf[MLX621_BCP];
+        if(bCPx > 127) bCPx -= 256;
+        printf("bCP_ee_mod,%d\r\n", bCPx);
+        printf("bCP,%.16f\r\n", bCP);
+        printf("VcpCPOffComp,%.16f\r\n", VcpCPOffComp);
+        printf("TempTCG_mod,%d\r\n\r\n", TempTCG);
+        
+        printf("Tgc621 mod,%.16f\r\n", Tgc621);
+        printf("Emiss mod,%d\r\n", Emiss); 
+        printf("VirTGCComp,%.16f\r\n", VirTGCComp);
+        printf("VirComp,%.16f\r\n", VirComp);
     
-    //Calculate To
-    AcpX =              Pntr.MLXEEbuf[MLX_TOINDEX +  0];
-    BcpX =              Pntr.MLXEEbuf[MLX_TOINDEX +  1];
-//    uint16_t thetaCPX = (EEbuf[MLX_TOINDEX + 3] << 8) + MLXEEbuf[MLX_TOINDEX + 2];
-    TGCX =              Pntr.MLXEEbuf[MLX_TOINDEX +  4];
-    BiScaleX =          Pntr.MLXEEbuf[MLX_TOINDEX +  5];
-    theta0X =          (Pntr.MLXEEbuf[MLX_TOINDEX + 13] << 8) + Pntr.MLXEEbuf[MLX_TOINDEX + 12];
-    theta0ScaleX =      Pntr.MLXEEbuf[MLX_TOINDEX + 14];
-    deltaThetaScaleX =  Pntr.MLXEEbuf[MLX_TOINDEX + 15];
-    elipsonX =         (Pntr.MLXEEbuf[MLX_TOINDEX + 17] << 8) + Pntr.MLXEEbuf[MLX_TOINDEX + 16];
-/*
-        printf("Vth(25) = %6d 0x%x\nTa1     = %6d 0x%x\nTa2     = %6d 0x%x\n", Vth25X, Vth25X, Kt1, Kt1, Kt2, Kt2);
-        printf("Kt1fX   = %f\nKt2fX   = %f\nTaXX    = %f\n\n", Kt1fX, Kt2fX, TaXX);
-        printf("Acp     = %6d 0x%x\nBcp     = %6d 0x%x\nThCP    = %6d 0x%x\n", AcpX, AcpX, BcpX, BcpX, thetaCPX, thetaCPX); 
-        printf("TGC     = %6d 0x%x\nBiS     = %6d 0x%x\nTh0     = %6d 0x%x\n", TGCX, TGCX, BiScaleX, BiScaleX, theta0X, theta0X);   
-        printf("T0s     = %6d 0x%x\nDts     = %6d 0x%x\nelip    = %6d 0x%x\n\n", theta0ScaleX, theta0ScaleX, deltaThetaScaleX, deltaThetaScaleX, elipsonX, elipsonX);   
+        printf("KsTa,%d\r\n", KsTa);
+        printf("KsTaF,%.16f\r\n", KsTaF);
+        printf("ThPix,%.16f\r\n", ThPix);
+        printf("ThetaCP,%.16f\r\n", ThetaCP);
+        printf("ThetaCompPix,%.16f\r\n", ThetaCompPix);
+        
+        printf("Ks4_ee,%d\r\n", Ks4_ee);
+        printf("Ks4_scale,%d,%x\r\n", Pntr.MLXEEbuf[MLX621_KS_SCALE], Pntr.MLXEEbuf[MLX621_KS_SCALE]);
+        printf("Ks4,%.16f\r\n", Ks4);
+        printf("TaK4,%.2f\r\n", TaK4);
+        printf("Sx,%.16f\r\n", Sx);
+    /*
+        
+        printf("BiPix,%d,%x\r\n", Pntr.MLXEEbuf[Pixel + 0x40], Pntr.MLXEEbuf[Pixel + 0x40]);
+        printf("d_Th_Pix,%d,%x\r\n", d_Th_Pix, d_Th_Pix);
+        
+        //printf("VirOff_(Ta - 25.0f),%.16f\r\n", (Ta - 25.0f));
+        //printf("VirOff_Bi_ij * (Ta - 25.0f),%.16f\r\n", Bi_ij * (Ta - 25.0f));
+        //printf("VirOff_(Ai_ij + Bi_ij * (Ta - 25.0f)),%.16f\r\n", (Ai_ij + Bi_ij * (Ta - 25.0f)));
+        
+        printf("VircpTgcComp,%.16f\r\n", VircpTgcComp);
+        printf("VirTGCComp,%.16f\r\n", VirTGCComp);
+        printf("DELTA_TH_SCALE,%d,%.0f\r\n", Pntr.MLXEEbuf[MLX621_DELTA_TH_SCALE], (double) powf(2.0,Pntr.MLXEEbuf[MLX621_DELTA_TH_SCALE]));
+        printf("THETA0_SCALE,%d,%.0f\r\n", Pntr.MLXEEbuf[MLX621_THETA0_SCALE], (double) powf(2.0,Pntr.MLXEEbuf[MLX621_THETA0_SCALE]));
+        //printf("Alpha_ij_raw,%d,%04x\r\n", (Pntr.MLXEEbuf[MLX621_THETA0_HI] << 8) + Pntr.MLXEEbuf[MLX621_THETA0_LO], (Pntr.MLXEEbuf[MLX621_THETA0_HI] << 8) + Pntr.MLXEEbuf[MLX621_THETA0_LO]);
+        //printf("Alpha_ij_f,%.16f\r\n", Alpha_ij);
+        //printf("VirNorm,%.16f\r\n", VirNorm);
+        printf("VirComp,%.16f\r\n", VirComp);
+        printf("TempPxl,%.16f\r\n", TempPxl);
+            
+        //printf("TempPxl_a,%.16f\r\n", powf((Ta + 273.15), 4.0));
+        //printf("TempPxl_b,%.16f\r\n", log10((VirComp + powf((Ta + 273.15), 4.0)) / 4.0));
+        //printf("TempPxl_c,%.16f\r\n", exp((log10((VirComp + powf((Ta + 273.15), 4.0)) / 4.0))));
+        //printf("TempPxl_d,%.16f\r\n", powf((Ta + 273.15), 1.0));
+        //printf("TempPxl_e,%.16f\r\n", Ta + 273.15);
+        //printf("TempPxl_f,%.16f\r\n", Ta + 273.15);
+        printf("Th_0  ,%.16f\r\n", (double)Th_0 / pow(2.0,(double)Th_0_sc));
+        //printf("d_Th_Pix,%d,%x\r\n", d_Th_Pix, d_Th_Pix);
+        //printf("d_Th_Pix_raw,%d,%3.20f\r\n", Pntr.MLXEEbuf[Pixel + 0x80], (double)Pntr.MLXEEbuf[Pixel + 0x80]);
+        //printf("ThDeltaZ,%3.20f\r\n", (double)d_Th_Pix); // !!!!! coverting 205 to 34!!
+        //d_Th_Pix = Pntr.MLXEEbuf[Pixel + 0x80];
+        //printf("ThDelta1,%.16f\r\n", (double)d_Th_Pix); 
+        //printf("ThDelta2,%.16f\r\n", (double)Th_0 / pow(2.0,(double)Th_0_sc));
+        //printf("ThDelta3,%.16f\r\n", (double)d_Th_Pix / pow(2.0,(double)d_Th_sc));
+        //printf("ThDelta4,%.16f\r\n", (double)Th_0 / pow(2.0,(double)Th_0_sc) + (double)d_Th_Pix / pow(2.0,(double)d_Th_sc));
+        //printf("ThDelta5,%.16f\r\n", (double)d_Th_Pix / pow(2.0,(double)d_Th_sc));
+            
+        //ThPix = (((double)Th_0 / pow(2.0,(double)Th_0_sc) + ((double)d_Th_Pix / pow(2.0,(double)d_Th_sc)))) / ScaleCR54;
+            
+        printf("ThPix,%.16f\r\n", ThPix);
+        printf("ThetaCP,%.16f\r\n", ThetaCP);
+        printf("ThetaCompPix,%.16f\r\n", ThetaCompPix);
+        //printf("SxGuts1,%.32f\r\n", pow(ThetaCompPix, 3.0));
+        //printf("SxGuts2,%.32f\r\n", pow(ThetaCompPix, 3.0) * VirComp);
+        //printf("SxGuts3,%.32f\r\n", pow(ThetaCompPix, 4.0));
+        //printf("SxGuts4,%.32f\r\n", pow(ThetaCompPix, 4.0) * TaK4);
+        //printf("SxGuts5,%.32f\r\n", pow(ThetaCompPix, 3.0) * VirComp + (pow(ThetaCompPix, 4.0) * TaK4));
+        printf("SxGuts,%.32f\r\n", SxGuts);
+        printf("Sx,%.16f\r\n", Sx);
 */
+        printf("TempPxl,%.16f\r\n", TempPxl);
+        printf("\r\n");
+    }
+#endif
+}
+
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+// Display internal registers for debugging math
+ 
+void MLX9062x::DumpRawRegs(mlx_struct& Pntr) {
+#ifdef MLXTEST_621b
+    if(Pntr.mlxDevice == mlx90620) {
+        printf("\r\n\r\nMLX90620 Ta_T0 regs:\r\n");
+        //printf("ConfigReg54     = %d\r\n", ConfigReg54);
+        //printf("ScaleCR54        = %d\r\n", ScaleCR54);
+        //printf("Ktbits          = %02x\r\n",Pntr.MLXEEbuf[MLX621_KT12_SCALE]);
+        printf("Kt1,%d,%x\r\n", Kt1, Kt1);
+        //printf("Kt1_0xd2        = %d\r\n", 1 << ((Pntr.MLXEEbuf[MLX621_KT12_SCALE] & MLX621_KT1SCALE_BITS) >> 4));
+        printf("Kt2,%d,%x\r\n", Kt2, Kt2);
+        //printf("Kt2_0xd2        = %d  %x\r\n", 1 << (Pntr.MLXEEbuf[MLX621_KT12_SCALE] & MLX621_KT2SCALE_BITS), 1 << (Pntr.MLXEEbuf[MLX621_KT12_SCALE] & MLX621_KT2SCALE_BITS));
+        //printf("Kt2_0xd2 2      = %d  %x\r\n", 1 << 10 << (Pntr.MLXEEbuf[MLX621_KT12_SCALE] & MLX621_KT2SCALE_BITS), 1 << 10 << (Pntr.MLXEEbuf[MLX621_KT12_SCALE] & MLX621_KT2SCALE_BITS));
+        printf("Vth25,%d,%x\r\n", Vth25, Vth25);
+        printf("Kt1_f,%f\r\n", Kt1_f);
+        printf("Kt2_f,%f\r\n", Kt2_f);
+        printf("Pntr.PtatD,%d,%x\r\n", Pntr.PtatD, Pntr.PtatD);
+        printf("Ta,%f\r\n", Ta);
+        //printf("Tak4            = %f\r\n", Tak4);
+            
+        //printf("MLX621_KS4_EE   = %d\r\n", Pntr.MLXEEbuf[MLX621_KS4_EE]);
+        //printf("MLX621_KS_SCALE = %d\r\n", Pntr.MLXEEbuf[MLX621_KS_SCALE]);
+        //printf("ks4             = %d\r\n", ks4);
+        //printf("Acommon      = %d\r\n", Acommon);
+        //printf("deltaAi621      = %d\r\n", deltaAi621);
+        //printf("deltaAiScale621 = %d\r\n", deltaAiScale621);
+        //printf("Ai_ij           = %d\r\n", Ai_ij);
+            
+        //printf("BiScale621      = %d\r\n", BiScale621);
+        //printf("Bi_ijEEP        = %d **\r\n", Bi_ijEEP);
+        //printf("Bi_ij           = %d\r\n", Bi_ij);
+            
+        //printf("ACP_ee       = %d **\r\n", ACP_ee);
+        //printf("aCP         = %d\r\n", aCP);  //was 8 bit, now 16 
+         
+        //printf("Vth(25) = %6d 0x%x\nTa1     = %6d 0x%x\nTa2     = %6d 0x%x\n", Vth25, Vth25, Kt1, Kt1, Kt2, Kt2);
+        //printf("Kt1_f   = %f\nKt2_f   = %f\nTa    = %f\n\n", Kt1_f, Kt2_f, Ta);
+        //printf("Acp     = %6d 0x%x\nBcp     = %6d 0x%x\nThCP    = %6d 0x%x\n", AcpX, AcpX, BcpX, BcpX, thetaCPX, thetaCPX); 
+        //printf("TGC     = %6d 0x%x\nBiS     = %6d 0x%x\nTh0     = %6d 0x%x\n", TGCX, TGCX, BiScaleX, BiScaleX, theta0X, theta0X);   
+        //printf("T0s     = %6d 0x%x\nDts     = %6d 0x%x\nelip    = %6d 0x%x\n\n", theta0ScaleX, theta0ScaleX, deltaThetaScaleX, deltaThetaScaleX, elipsonX, elipsonX); 
+    } else {
+        printf("\r\n\r\nMLX90621 Ta_T0 regs:\r\n");
+        printf("ConfigReg54,%d,%02x\r\n", (Pntr.Config & MLX621_RESOLUTION) >> 4, (Pntr.Config & MLX621_RESOLUTION) >> 4);
+        printf("Pntr.PtatD,%d,%x\r\n", Pntr.PtatD, Pntr.PtatD);
+        printf("Vth25 mod,%d,%x\r\n", Vth25, Vth25);
+        printf("Kt1_f,%.16f\r\n", Kt1_f);
+        printf("Kt2_f,%.16f\r\n", Kt2_f);
+        printf("Ta,%.16f\r\n\r\n", Ta);
+    
+        printf("ScaleCR54,%d,%x\r\n", 1 << (3 - ((Pntr.Config & MLX621_RESOLUTION) >> 4)), 1 << (3 - ((Pntr.Config & MLX621_RESOLUTION) >> 4))); 
+        printf("Ktbits,%02x\r\n",Pntr.MLXEEbuf[MLX621_KT12_SCALE]);
+        printf("Kt1,%d,%x\r\n", (int16_t)(Pntr.MLXEEbuf[MLX621_KT1_HI] << 8) | Pntr.MLXEEbuf[MLX621_KT1_LO], (Pntr.MLXEEbuf[MLX621_KT1_HI] << 8) | Pntr.MLXEEbuf[MLX621_KT1_LO]); 
+        printf("Kt1_0xd2,%d\r\n", 1 << ((Pntr.MLXEEbuf[MLX621_KT12_SCALE] & MLX621_KT1SCALE_BITS) >> 4));      
+        printf("Kt1 mod,%d,%x\r\n", Kt1, Kt1); 
+        printf("Kt2,%d,%x\r\n", (int16_t)((Pntr.MLXEEbuf[MLX621_KT2_HI] << 8) | Pntr.MLXEEbuf[MLX621_KT2_LO]), ((Pntr.MLXEEbuf[MLX621_KT2_HI] << 8) | Pntr.MLXEEbuf[MLX621_KT2_LO])); 
+        printf("Kt2_0xd2,%d,%x\r\n", 1 << (Pntr.MLXEEbuf[MLX621_KT12_SCALE] & MLX621_KT2SCALE_BITS), 1 << (Pntr.MLXEEbuf[MLX621_KT12_SCALE] & MLX621_KT2SCALE_BITS));
+        printf("Kt2_0xd2_2,%d,%x\r\n", 1 << 10 << (Pntr.MLXEEbuf[MLX621_KT12_SCALE] & MLX621_KT2SCALE_BITS), 1 << 10 << (Pntr.MLXEEbuf[MLX621_KT12_SCALE] & MLX621_KT2SCALE_BITS));
+        printf("Kt2 mod,%d,%x\r\n", Kt2, Kt2);
+        printf("Vth25,%d,%x\r\n", (int16_t)(((Pntr.MLXEEbuf[MLX621_VTH25_HI] << 8) | Pntr.MLXEEbuf[MLX621_VTH25_LO])), (((Pntr.MLXEEbuf[MLX621_VTH25_HI] << 8) | Pntr.MLXEEbuf[MLX621_VTH25_LO]))); 
+        printf("Kt1_f^2,%12f\r\n", pow(Kt1_f, 2.0));
+        printf("Vth25-PtatD,%12f\r\n", (Vth25 - (double)Pntr.PtatD));
+        printf("4*Kt2_f,%12f\r\n", 4.0 * Kt2_f);
+        printf("4*Kt2_f*(Vth25 - Pntr.PtatD),%12f\r\n", 4.0 * Kt2_f * (Vth25 - (double)Pntr.PtatD));
+        printf("TopBeforesqrt,%12f\r\n", -pow(Kt1_f, 2.0) - 4.0 * Kt2_f * (Vth25 - (double)Pntr.PtatD));
+        printf("\r\n");
+        
+        printf("Acommon,%d,%x\r\n", (int16_t)(Pntr.MLXEEbuf[MLX621_A_COMMON_HI] << 8) + Pntr.MLXEEbuf[MLX621_A_COMMON_LO], (Pntr.MLXEEbuf[MLX621_A_COMMON_HI] << 8) + Pntr.MLXEEbuf[MLX621_A_COMMON_LO]); 
+        printf("Acommon mod,%d,%x\r\n", Acommon, Acommon); 
+        printf("Emiss,%d,%x\r\n", (uint16_t)((Pntr.MLXEEbuf[MLX621_A_EMMIS_HI] << 8) + Pntr.MLXEEbuf[MLX621_A_EMMIS_LO]), ((Pntr.MLXEEbuf[MLX621_A_EMMIS_HI] << 8) + Pntr.MLXEEbuf[MLX621_A_EMMIS_LO])); 
+        printf("Emiss mod,%d,%x\r\n", Emiss, Emiss); 
+        printf("ACP_ee,%d,%x\r\n", (int16_t)(Pntr.MLXEEbuf[MLX621_ACP_HI] << 8) + Pntr.MLXEEbuf[MLX621_ACP_LO], (Pntr.MLXEEbuf[MLX621_ACP_HI] << 8) + Pntr.MLXEEbuf[MLX621_ACP_LO]); 
+        printf("ACP_ee mod,%d,%x\r\n", ACP_ee, ACP_ee); 
+        printf("AlphaCP,%d,%x\r\n", (int16_t)((Pntr.MLXEEbuf[MLX621_ALPHACP_HI] << 8) + Pntr.MLXEEbuf[MLX621_ALPHACP_LO]), ((Pntr.MLXEEbuf[MLX621_ALPHACP_HI] << 8) + Pntr.MLXEEbuf[MLX621_ALPHACP_LO])); 
+        printf("AlphaCP mod,%d,%x\r\n", AlphaCP, AlphaCP); 
+        printf("aCP,%.16f\r\n", aCP);
+        printf("AiScale621,%d,%x\r\n", (int16_t)(Pntr.MLXEEbuf[MLX621_DELTA_ABI_SCALE] & MLX621_DAISCALE_BITS) >> 4, (Pntr.MLXEEbuf[MLX621_DELTA_ABI_SCALE] & MLX621_DAISCALE_BITS) >> 4);
+        printf("BiScale621,%d,%x\r\n", (int16_t)(Pntr.MLXEEbuf[MLX621_DELTA_ABI_SCALE] & MLX621_DBISCALE_BITS), (Pntr.MLXEEbuf[MLX621_DELTA_ABI_SCALE] & MLX621_DBISCALE_BITS));
+        printf("bCP,%d,%x\r\n", (int8_t)Pntr.MLXEEbuf[MLX621_BCP], Pntr.MLXEEbuf[MLX621_BCP]);
+        printf("bCP mod,%.16f\r\n", bCP);
+            
+        printf("TempTCG,%d,%x\r\n", (int8_t)Pntr.MLXEEbuf[MLX621_TGC], Pntr.MLXEEbuf[MLX621_TGC]);
+        printf("TempTCG mod,%d,%x\r\n", TempTCG, TempTCG);
+        printf("Tgc621 mod,%.16f\r\n", Tgc621);
+        //printf("TGCReg,%d,%x\r\n", (int16_t)TGCReg, TGCReg);
+        printf("VCP,%d,%x\r\n", (int16_t)Pntr.VCP, Pntr.VCP);
+        printf("VcpCPOffComp,%.16f\r\n", VcpCPOffComp);
+        printf("KsTa,%d,%x\r\n", (int16_t)KsTa, KsTa);
+        printf("KsTaF,%.16f\r\n", KsTaF);
+        printf("Ks4_ee,%d,%x\r\n", (int16_t)Ks4_ee, Ks4_ee);
+        printf("Ks4_scale,%d,%x\r\n", Pntr.MLXEEbuf[MLX621_KS_SCALE], Pntr.MLXEEbuf[MLX621_KS_SCALE]);
+        printf("Ks4,%.16f\r\n", Ks4);
+        printf("TaK4,%.16f\r\n", TaK4);
+        printf("Th_0,%d,%x\r\n", (int16_t)Th_0, Th_0);
+        printf("Th_0_sc,%d,%x\r\n", (int16_t)Th_0_sc, Th_0_sc);
+        printf("d_Th_sc,%d,%x\r\n", (int16_t)d_Th_sc, d_Th_sc);
+        printf("\r\n");
+    }
+#endif
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+// Initial Calculations for Ta and To
+
+void MLX9062x::CalcTa_To(mlx_struct& Pntr) {
+#ifdef MLXTEST_621b
+    DSSetup(Pntr, 11);
+#endif
+    if(Pntr.mlxDevice == mlx90620) {
+        //Calculate Ta first
+        Vth25 = (Pntr.MLXEEbuf[MLX_TAINDEX +  1] << 8) + Pntr.MLXEEbuf[MLX_TAINDEX +  0];
+        Kt1 = (Pntr.MLXEEbuf[MLX_TAINDEX +  3] << 8) + Pntr.MLXEEbuf[MLX_TAINDEX +  2];
+        Kt2 = (Pntr.MLXEEbuf[MLX_TAINDEX +  5] << 8) + Pntr.MLXEEbuf[MLX_TAINDEX +  4];
+        if(Vth25  > 32767) Vth25  -= 65536;  
+        if(Kt1 > 32767) Kt1 -= 65536; 
+        if(Kt2 > 32767) Kt2 -= 65536;
+        
+        Kt1_f = (double)Kt1 / 1024.0f;
+        Kt2_f = (double)Kt2 / 1048576.0f;
+        ScaleCR54 = 1;
+        Ta = MLX9062x::GetDieTemp(Pntr);
+        
+        //Calculate To
+        AcpX =              Pntr.MLXEEbuf[MLX621_A_COMMON_LO]; //[MLX_TOINDEX +  0];
+        BcpX =              Pntr.MLXEEbuf[MLX621_A_COMMON_HI]; //[MLX_TOINDEX +  1];
+        //uint16_t thetaCPX = (EEbuf[MLX_TOINDEX + 3] << 8) + MLXEEbuf[MLX_TOINDEX + 2];
+        TGCX =              Pntr.MLXEEbuf[MLX_TGCX_REG]; //[MLX_TOINDEX +  4];
+        BiScaleX =          Pntr.MLXEEbuf[MLX621_DELTA_ABI_SCALE]; //[MLX_TOINDEX +  5];
+        theta0X =          (Pntr.MLXEEbuf[MLX_THETA0_REG_HI] << 8) + Pntr.MLXEEbuf[MLX_THETA0_REG_LO]; //[MLX_TOINDEX + 13] << 8) + Pntr.MLXEEbuf[MLX_TOINDEX + 12];
+        theta0ScaleX =      Pntr.MLXEEbuf[MLX_THETA0_SCALE_REG];  //[MLX_TOINDEX + 14];
+        deltaThetaScaleX =  Pntr.MLXEEbuf[MLX_DELTA_TH_SCALE_REG];  //[MLX_TOINDEX + 15];
+        elipsonX =         (Pntr.MLXEEbuf[MLX_EPSILON_REG_HI] << 8) + Pntr.MLXEEbuf[MLX_EPSILON_REG_LO];  //[MLX_TOINDEX + 17] << 8) + Pntr.MLXEEbuf[MLX_TOINDEX + 16];  
+    } else {
+        ConfigReg54 = (Pntr.Config & MLX621_RESOLUTION) >> 4;
+        ScaleCR54 = 1 << (3 - ((Pntr.Config & MLX621_RESOLUTION) >> 4));  //1 << (3 - ConfigReg54);
+        Kt1 = (int16_t)((Pntr.MLXEEbuf[MLX621_KT1_HI] << 8) | Pntr.MLXEEbuf[MLX621_KT1_LO]);
+        Kt2 = (int16_t)((Pntr.MLXEEbuf[MLX621_KT2_HI] << 8) | Pntr.MLXEEbuf[MLX621_KT2_LO]);
+        Vth25 = (int16_t)(((Pntr.MLXEEbuf[MLX621_VTH25_HI] << 8) | Pntr.MLXEEbuf[MLX621_VTH25_LO]));
+           
+#ifdef MLXTEST_621
+#warning "MLX90620 test mode"
+        //for testing only
+        ConfigReg54 = 0;
+        ScaleCR54 =  1 << (3 - ConfigReg54);
+        Vth25  = 0x6420;
+        Kt1    = 0x5589;
+        Kt2    = 0x5e7e;
+#endif
+
+        if(Kt1 > 32767) Kt1 -= 65536; 
+        if(Kt2 > 32767) Kt2 -= 65536;
+        if(Vth25  > 32767) Vth25  -= 65536;  
+        Vth25 /= ScaleCR54;
+        Kt1_f = (double)Kt1 / ((1 << ((Pntr.MLXEEbuf[MLX621_KT12_SCALE] & MLX621_KT1SCALE_BITS) >> 4)) * ScaleCR54);
+        Kt2_f = (double)Kt2 / ((1 << 10 << (Pntr.MLXEEbuf[MLX621_KT12_SCALE] & MLX621_KT2SCALE_BITS)) * ScaleCR54);        
+        Ta = MLX9062x::GetDieTemp(Pntr);
+        //double Tak4 = pow(Ta + 273.15, 4.0);
+        
+        Acommon = (int16_t)(Pntr.MLXEEbuf[MLX621_A_COMMON_HI] << 8) + Pntr.MLXEEbuf[MLX621_A_COMMON_LO];
+        Emiss = (uint16_t)((Pntr.MLXEEbuf[MLX621_A_EMMIS_HI] << 8) + Pntr.MLXEEbuf[MLX621_A_EMMIS_LO]) / 32768;
+        ACP_ee = (int16_t)(Pntr.MLXEEbuf[MLX621_ACP_HI] << 8) + Pntr.MLXEEbuf[MLX621_ACP_LO];
+        AlphaCP = (int16_t)((Pntr.MLXEEbuf[MLX621_ALPHACP_HI] << 8) + Pntr.MLXEEbuf[MLX621_ALPHACP_LO]) / ScaleCR54;
+        
+        if(Acommon > 32767) Acommon -= 65536; 
+        //if(Emiss > 32767) Emiss -= 65536; 
+        if(ACP_ee > 32767) ACP_ee -= 65536;
+        aCP = (float)(ACP_ee / ScaleCR54);  
+        AiScale621 = (int16_t)(Pntr.MLXEEbuf[MLX621_DELTA_ABI_SCALE] & MLX621_DAISCALE_BITS) >> 4;
+        BiScale621 = (int16_t)(Pntr.MLXEEbuf[MLX621_DELTA_ABI_SCALE] & MLX621_DBISCALE_BITS);
+        bCP = (float)Pntr.MLXEEbuf[MLX621_BCP];
+        if(bCP > 127.0f) bCP -= 256.0f;
+        bCP /= (pow(2.0f, (float)BiScale621) * (float)ScaleCR54);
+        TempTCG = Pntr.MLXEEbuf[MLX621_TGC];
+        if(TempTCG > 127) TempTCG -= 256;
+        Tgc621 = (float)TempTCG / 32.0f;
+        TGCReg = GetTGCReg(Pntr);
+        if(Pntr.VCP > 32767) Pntr.VCP -= 65536;
+        VcpCPOffComp = (double)Pntr.VCP - ((double)aCP + bCP * (Ta - 25.0));
+        KsTa = (Pntr.MLXEEbuf[MLX621_KSTA_HI] << 8) + Pntr.MLXEEbuf[MLX621_KSTA_LO];
+        if(KsTa > 32767) KsTa -= 65536;
+        KsTaF = (double)KsTa / pow(2.0, 20);
+        Ks4_ee =  Pntr.MLXEEbuf[MLX621_KS4_EE];
+        if(Ks4_ee > 127) Ks4_ee -= 256;
+        Ks4 = (double)Ks4_ee / pow(2.0, (double)((Pntr.MLXEEbuf[MLX621_KS_SCALE] & 15) + 8.0));
+        TaK4 = pow((Ta + 273.15), 4.0);
+        Th_0 = (Pntr.MLXEEbuf[MLX621_THETA0_HI] << 8) + Pntr.MLXEEbuf[MLX621_THETA0_LO];
+        Th_0_sc = Pntr.MLXEEbuf[MLX621_THETA0_SCALE];
+        d_Th_sc = Pntr.MLXEEbuf[MLX621_DELTA_TH_SCALE];
+    }
+    DumpRawRegs(Pntr);
 }
 
 //--------------------------------------------------------------------------------------------------------------------------------------//
 // Pixel Temperature Calculation
 
-double MLX90620::CalcPixel(mlx_struct& Pntr, int Pixel) {
-    AiPixelX = Pntr.MLXEEbuf[Pixel];                                        //eeprom address range 0x00 - 0x3f
-    BiPixelX = Pntr.MLXEEbuf[Pixel + 0x40];                                 //eeprom address range 0x40 - 0x7f
-    dThetaPixelX = Pntr.MLXEEbuf[Pixel + 0x80];                             //eeprom address range 0x08 - 0xbf
-    VirPixelX = (Pntr.MLXRamBuf[Pixel * 2 + 1] << 8) + Pntr.MLXRamBuf[Pixel * 2];   //ram address range 0x000 - 0x08f, 16b
-    float Vcp_off_comp = VCP - (AcpX + BcpX / powf(2.0f,BiScaleX) * (TaXX - 25.0f));
-    float VirPixel_off_comp = VirPixelX - (AiPixelX + BiPixelX / powf(2.0f,BiScaleX) * (TaXX - 25.0f));
-    float VirPixel_off_comp2 = (float(AiPixelX) + float(BiPixelX) / float(1 << BiScaleX) * (TaXX - 25.0f));
-    VirPixel_off_comp2 = VirPixelX - VirPixel_off_comp2;
-    float VirPixel_tgc_comp = VirPixel_off_comp - TGCX / 32.0 * Vcp_off_comp;
-    float elipsonf = elipsonX / 32768.0;
-    float VirPixel_comp = VirPixel_tgc_comp / elipsonf;
-    double theta28 = theta0X / powf(2.0, theta0ScaleX) + dThetaPixelX / powf(2.0, deltaThetaScaleX);
-    double TempPxl = powf((VirPixel_comp / theta28 + powf((TaXX + 273.15f), 4.0f)), (1.0f / 4.0f)) - 273.15f;
-/*
-        printf("\r\n\r\npixel = %d\r\n", Pixel);
-        printf("Acp   = %d\r\nBcp   = %d\r\nBiS   = %d\r\n", AcpX, BcpX, BiScaleX);
-        printf("Vcp   = %d\r\neps   = %d\r\nTGC   = %d\r\n", VCP, elipsonX, TGCX);
-        printf("Vcp_off_comp             = %f\r\n", Vcp_off_comp);
-        printf("VirPixel_off_comp        = %f\r\n", VirPixel_off_comp);
-        printf("VirPixel                 = %d\r\n", VirPixelX);
-        printf("AiPixel                  = %d\r\n", AiPixelX);
-        printf("BiPixel                  = %d\r\n", BiPixelX);
-        printf("BiScale                  = %d\r\n", BiScaleX);
-        printf("2^BiScale                = %f\r\n", (powf(2.0,BiScaleX)));
-        printf("1 << BiScale             = %d\r\n", (1 << BiScaleX));
-        printf("Ta-25.0                  = %f\r\n", (TaXX - 25.0f));
-        printf("BiPix/2^BiScale          = %f\r\n", (BiPixelX / powf(2.0,BiScaleX)));
-        printf("AiP+BiP/2^BiScale)*(Ta-25= %f\r\n", (AiPixelX + BiPixelX / powf(2.0,BiScaleX) * (TaXX - 25.0f)));
-        printf("VirPixel_off_comp again  = %f\r\n", (VirPixelX - (AiPixelX + BiPixelX / powf(2.0,BiScaleX) * (TaXX - 25.0f))));
-        printf("VirPixel_off_comp2 step  = %f\r\n", VirPixel_off_comp2);
-        printf("VirPixel_tgc_comp        = %f\r\n", VirPixel_tgc_comp);
-        printf("elipsonf                 = %f\r\n", elipsonf);
-        printf("VirPixel_comp            = %f\r\n", VirPixel_comp);
-        printf("theta28                  = %f  << double print problem\r\n", (theta28 * 100000000.0));  //<<< can't print a double
-        printf("TempPxl                  = %f\r\n",  TempPxl);
-*/
+double MLX9062x::CalcPixel(mlx_struct& Pntr, int Pixel) {
+    if(Pntr.mlxDevice == mlx90620) {
+        AiPix = Pntr.MLXEEbuf[Pixel];                                        //eeprom address range 0x00 - 0x3f
+        BiPix = Pntr.MLXEEbuf[Pixel + 0x40];                                 //eeprom address range 0x40 - 0x7f
+        d_Th_Pix = Pntr.MLXEEbuf[Pixel + 0x80];                             //eeprom address range 0x08 - 0xbf
+        VirPix = (Pntr.MLXRamBuf[Pixel * 2 + 1] << 8) + Pntr.MLXRamBuf[Pixel * 2];   //ram address range 0x000 - 0x08f, 16b
+        float Vcp_off_comp = Pntr.VCP - (AcpX + BcpX / powf(2.0f,BiScaleX) * (Ta - 25.0f));
+        float VirPix_off_comp = VirPix - (AiPix + BiPix / powf(2.0f,BiScaleX) * (Ta - 25.0f));
+        float VirPix_off_comp2 = (float(AiPix) + float(BiPix) / float(1 << BiScaleX) * (Ta - 25.0f));
+        VirPix_off_comp2 = VirPix - VirPix_off_comp2;
+        float VirPix_tgc_comp = VirPix_off_comp - TGCX / 32.0 * Vcp_off_comp;
+        float elipsonf = elipsonX / 32768.0;
+        float VirPix_comp = VirPix_tgc_comp / elipsonf;
+        double theta28 = theta0X / powf(2.0, theta0ScaleX) + d_Th_Pix / powf(2.0, deltaThetaScaleX);
+        TempPxl = powf((VirPix_comp / theta28 + powf((Ta + 273.15f), 4.0f)), (1.0f / 4.0f)) - 273.15f;
+    } else {
+        AiPix = Pntr.MLXEEbuf[Pixel];                                       //eeprom address range 0x00 - 0x3f
+        BiPix = Pntr.MLXEEbuf[Pixel + 0x40];                                //eeprom address range 0x40 - 0x7f
+        d_Th_Pix = Pntr.MLXEEbuf[Pixel + 0x80];                             //eeprom address range 0x08 - 0xbf
+        VirPix = (Pntr.MLXRamBuf[Pixel * 2 + 1] << 8) + Pntr.MLXRamBuf[Pixel * 2];   //ram address range 0x000 - 0x08f, 16b
+#ifdef MLXTEST_621b
+        VirPix = 0x01b7;
+#endif 
+        if(VirPix > 32767) VirPix -= 65536;       
+        if(BiPix > 127) BiPix -= 256; 
+        Ai_ij = (float)(Acommon + AiPix * pow(2.0, AiScale621)) / (float)ScaleCR54;
+        Bi_ij = (float)BiPix / (float)((1 << BiScale621) * ScaleCR54);
+        
+        VirOffComp = (float)VirPix - (Ai_ij + Bi_ij * (Ta - 25.0f));
+        VirTGCComp = VirOffComp - Tgc621 * VcpCPOffComp;
+        VirComp = VirTGCComp / Emiss;
+        
+        ThPix = (((double)Th_0 / pow(2.0,(double)Th_0_sc) + ((double)d_Th_Pix / pow(2.0,(double)d_Th_sc)))) / ScaleCR54;
+        ThetaCP = (double)AlphaCP / (pow(2.0, (double)Th_0_sc) * ScaleCR54);
+        ThetaCompPix = (1.0 + KsTaF * (Ta - 25.0)) * (ThPix - Tgc621 * ThetaCP);
+        SxGuts = pow(ThetaCompPix, 3.0) * VirComp + (pow(ThetaCompPix, 4.0) * TaK4);
+        Sx = sqrt(SxGuts); 
+        Sx = Ks4 * sqrt(Sx); 
+
+        TempPxl = ThetaCompPix * (1.0 - (Ks4 * 273.15)) + Sx;
+        TempPxl = (VirComp / TempPxl) + TaK4;
+        TempPxl = sqrt(TempPxl);
+        TempPxl = sqrt(TempPxl) - 273.15;
+    }
+    DumpPixRegs(Pntr, Pixel);
     return(TempPxl);
 }
 
 
-
-