From 0b8039cc0a6e329f7071191379d1662a355cca42 Mon Sep 17 00:00:00 2001
From: Diego Lopez Gutierrez <dlopezgu@bu.edu>
Date: Mon, 6 Mar 2023 12:21:59 -0500
Subject: [PATCH 1/7] Enable current source for ADC7 and set current to 14 uA,
 taking into account new thermistor NTCG063JF103FTB

---
 tamalero/LPGBT.py | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/tamalero/LPGBT.py b/tamalero/LPGBT.py
index 0fab62a..069c3b2 100644
--- a/tamalero/LPGBT.py
+++ b/tamalero/LPGBT.py
@@ -127,6 +127,8 @@ class LPGBT(RegParser):
                 self.cal_gain = 1.85
                 self.cal_offset = 512
 
+        self.set_current_adc7()
+
     def read_base_config(self):
         #
         print("{:80}{:10}{:10}".format("Register", "value", "default"))
@@ -626,7 +628,20 @@ class LPGBT(RegParser):
 
         self.cal_gain = gain
         self.cal_offset = offset
+
+    def set_current_adc7(self, verbose=False):
+        self.wr_reg("LPGBT.RWF.VOLTAGE_DAC.CURDACENABLE", 0x1)
+        if verbose:
+            print("Set current DAC...", self.rd_reg("LPGBT.RWF.VOLTAGE_DAC.CURDACENABLE"))
         
+        self.wr_reg("LPGBT.RWF.CUR_DAC.CURDACCHNENABLE", 0x40) # Set pin ADC7 to current source; 0x40 = 64 = 01000000
+        if verbose:
+            print("Set current source to pin ADC7...", bin(self.rd_reg("LPGBT.RWF.CUR_DAC.CURDACCHNENABLE")))
+        
+        self.wr_reg("LPGBT.RWF.CUR_DAC.CURDACSELECT", 0xE) # Set current to 14 uA; max V = 0.977, min V = 0.080 for T in -20-40C range
+        if verbose:
+            print("Set current source value to...", int(self.rd_reg("LPGBT.RWF.CUR_DAC.CURDACSELECT")), "uA")
+
     def set_dac(self, v_out):
         if v_out > 1.00:
             print ("Can't set the DAC to a value larger than 1.0 V!")
-- 
GitLab


From bb7856ac68d85616b4d7954b5a91d047bc6c3c83 Mon Sep 17 00:00:00 2001
From: Diego Lopez Gutierrez <dlopezgu@bu.edu>
Date: Thu, 9 Mar 2023 15:46:11 -0500
Subject: [PATCH 2/7] Generalize current_adc function to apply to any ADC
 input, add get_temp_direct to tamalero.utils to properly calculate temp of
 RT1

---
 tamalero/LPGBT.py        | 33 +++++++++++++++++++++++++++------
 tamalero/ReadoutBoard.py |  5 +++--
 tamalero/utils.py        | 27 +++++++++++++++++++++++++++
 3 files changed, 57 insertions(+), 8 deletions(-)

diff --git a/tamalero/LPGBT.py b/tamalero/LPGBT.py
index 069c3b2..f3766d4 100644
--- a/tamalero/LPGBT.py
+++ b/tamalero/LPGBT.py
@@ -127,7 +127,7 @@ class LPGBT(RegParser):
                 self.cal_gain = 1.85
                 self.cal_offset = 512
 
-        self.set_current_adc7()
+        self.set_current_adc(7)
 
     def read_base_config(self):
         #
@@ -629,18 +629,39 @@ class LPGBT(RegParser):
         self.cal_gain = gain
         self.cal_offset = offset
 
-    def set_current_adc7(self, verbose=False):
+    def set_current_adc(self, channel, verbose=True):
+        assert channel in range(8), f"Can only choose from ADC0 to ADC7; ADC{channel} was given instead"
+        
         self.wr_reg("LPGBT.RWF.VOLTAGE_DAC.CURDACENABLE", 0x1)
         if verbose:
             print("Set current DAC...", self.rd_reg("LPGBT.RWF.VOLTAGE_DAC.CURDACENABLE"))
         
-        self.wr_reg("LPGBT.RWF.CUR_DAC.CURDACCHNENABLE", 0x40) # Set pin ADC7 to current source; 0x40 = 64 = 01000000
+        if channel == 0:
+            adc_chn = self.LPGBT_CONST.CURDAC_CHN0_bm
+        elif channel == 1:
+            adc_chn = self.LPGBT_CONST.CURDAC_CHN1_bm
+        elif channel == 2:
+            adc_chn = self.LPGBT_CONST.CURDAC_CHN2_bm
+        elif channel == 3:
+            adc_chn = self.LPGBT_CONST.CURDAC_CHN3_bm
+        elif channel == 4:
+            adc_chn = self.LPGBT_CONST.CURDAC_CHN4_bm
+        elif channel == 5:
+            adc_chn = self.LPGBT_CONST.CURDAC_CHN5_bm
+        elif channel == 6:
+            adc_chn = self.LPGBT_CONST.CURDAC_CHN6_bm
+        elif channel == 7:
+            adc_chn = self.LPGBT_CONST.CURDAC_CHN7_bm
+
+        self.wr_reg("LPGBT.RWF.CUR_DAC.CURDACCHNENABLE", adc_chn) # Set pin ADC channel to current source
         if verbose:
             print("Set current source to pin ADC7...", bin(self.rd_reg("LPGBT.RWF.CUR_DAC.CURDACCHNENABLE")))
-        
-        self.wr_reg("LPGBT.RWF.CUR_DAC.CURDACSELECT", 0xE) # Set current to 14 uA; max V = 0.977, min V = 0.080 for T in -20-40C range
+       
+        curr_dac = 14 # Desired current of 14 uA; max V = 0.977, min V = 0.080 for T in -20-40C range
+        curr_dac_select = round(curr_dac*256/900) # CURDACSELECT is in units of 900/256 uA per bit
+        self.wr_reg("LPGBT.RWF.CUR_DAC.CURDACSELECT", curr_dac_select)
         if verbose:
-            print("Set current source value to...", int(self.rd_reg("LPGBT.RWF.CUR_DAC.CURDACSELECT")), "uA")
+            print("Set current source value to...", curr_dac_select*900/256, "uA")
 
     def set_dac(self, v_out):
         if v_out > 1.00:
diff --git a/tamalero/ReadoutBoard.py b/tamalero/ReadoutBoard.py
index cd2e370..f2dacaa 100644
--- a/tamalero/ReadoutBoard.py
+++ b/tamalero/ReadoutBoard.py
@@ -1,7 +1,7 @@
 import os
 from tamalero.LPGBT import LPGBT
 from tamalero.SCA import SCA
-from tamalero.utils import get_temp, chunk
+from tamalero.utils import get_temp, chunk, get_temp_direct
 from tamalero.VTRX import VTRX
 
 from time import sleep
@@ -365,7 +365,8 @@ class ReadoutBoard:
             elif self.ver == 2:
                 # https://www.digikey.com/en/products/detail/tdk-corporation/NTCG063JF103FTB/5872743
                 # Parameters need updating?
-                t1 = get_temp(adc_7, v_ref, 10000, 25, 10000, 3900)  # this comes from the lpGBT ADC
+                curr_dac = self.DAQ_LPGBT.rd_reg("LPGBT.RWF.CUR_DAC.CURDACSELECT")*900/256
+                t1 = get_temp_direct(adc_7, curr_dac, 25, 10000, 3380)  # this comes from the lpGBT ADC
                 t2 = get_temp(adc_in29, v_ref, 10000, 25, 10000, 3380)  # this comes from the SCA ADC
 
             if verbose>0:
diff --git a/tamalero/utils.py b/tamalero/utils.py
index 64a9169..473f860 100644
--- a/tamalero/utils.py
+++ b/tamalero/utils.py
@@ -37,6 +37,33 @@ def get_temp(v_out, v_ref, r_ref, t_1, r_1, b, celcius=True):
         return -999
     return t_2-delta_t
 
+def get_temp_direct(v_out, curr_dac, t_1, r_1, b, celcius=True):
+    """
+    Calculate the temperature of a thermistor, given the voltage measured on it.
+
+    Arguments:
+    v_out (float) -- voltage measured on the thermistor
+    curr_dac (float) -- current source value set on the DAC (in uA)
+    t_1 (float) -- reference temperature of thermistor
+    r_1 (float) -- resistance of NTC at reference temperature
+    b (float) -- B coefficient, with B = (ln(r_1)-ln(r_t)) / (1/t_1 - 1/t_out)
+
+    Keyword arguments:
+    celcius (bool) -- give and return the temperature in degree celcius. Kelvin scale used otherwise.
+    """
+
+    delta_t = 273.15 if celcius else 0
+    try:
+        r_t = v_out / (curr_dac / 10**6)
+        print(f"r_t: {r_t}")
+        print(f"v_out: {v_out}")
+        print(f"curr_dac: {curr_dac / 10**6}")
+        print(f"b: {b}")
+        t_2 = b/((b/(t_1+delta_t)) - math.log(r_1) + math.log(r_t))
+    except ZeroDivisionError:
+        print ("Temperature calculation failed!")
+        return -999
+    return t_2-delta_t
 
 def read_mapping(f_in, selection='adc', flavor='small'):
     flavors = {'small':0, 'medium':1, 'large': 2}
-- 
GitLab


From 4da1bf5baa611efb294921d3edc480cb7232631a Mon Sep 17 00:00:00 2001
From: Diego Lopez Gutierrez <dlopezgu@bu.edu>
Date: Tue, 14 Mar 2023 15:02:27 -0400
Subject: [PATCH 3/7] Include VTRX thermistor, improve accuracy of get_temp
 function, add VTRX read to ReadoutBoard

---
 tamalero/LPGBT.py        | 52 ++++++++++++++++++++++++++++---
 tamalero/ReadoutBoard.py |  7 +++--
 tamalero/utils.py        | 67 ++++++++++++++++++++++++++++++----------
 3 files changed, 104 insertions(+), 22 deletions(-)

diff --git a/tamalero/LPGBT.py b/tamalero/LPGBT.py
index f3766d4..3552709 100644
--- a/tamalero/LPGBT.py
+++ b/tamalero/LPGBT.py
@@ -128,6 +128,7 @@ class LPGBT(RegParser):
                 self.cal_offset = 512
 
         self.set_current_adc(7)
+        self.set_current_adc(0)
 
     def read_base_config(self):
         #
@@ -653,9 +654,14 @@ class LPGBT(RegParser):
         elif channel == 7:
             adc_chn = self.LPGBT_CONST.CURDAC_CHN7_bm
 
-        self.wr_reg("LPGBT.RWF.CUR_DAC.CURDACCHNENABLE", adc_chn) # Set pin ADC channel to current source
+        currently_set = self.rd_reg("LPGBT.RWF.CUR_DAC.CURDACCHNENABLE")
+        print(f"LPGBT.RWF.CUR_DAC.CURDACCHNENABLE currently set: {bin(currently_set)}")
+        print(f"Want to set {bin(adc_chn)}")
+        print(f"LPGBT.RWF.CUR_DAC.CURDACCHNENABLE new set: {bin(adc_chn | currently_set)}")
+
+        self.wr_reg("LPGBT.RWF.CUR_DAC.CURDACCHNENABLE", adc_chn | currently_set) # Set pin ADC channel to current source
         if verbose:
-            print("Set current source to pin ADC7...", bin(self.rd_reg("LPGBT.RWF.CUR_DAC.CURDACCHNENABLE")))
+            print(f"Set current source to pin ADC{channel}...", bin(self.rd_reg("LPGBT.RWF.CUR_DAC.CURDACCHNENABLE")))
        
         curr_dac = 14 # Desired current of 14 uA; max V = 0.977, min V = 0.080 for T in -20-40C range
         curr_dac_select = round(curr_dac*256/900) # CURDACSELECT is in units of 900/256 uA per bit
@@ -954,13 +960,21 @@ class LPGBT(RegParser):
                         print ("Write not successfull!")
                     break
 
-    def I2C_read(self, reg=0x0, master=2, slave_addr=0x70, nbytes=1, adr_nbytes=2, freq=2, verbose=False):
+    def I2C_read(self, reg=0x0, master=2, slave_addr=0x70, nbytes=1, adr_nbytes=2, freq=2, verbose=True):
         #https://gitlab.cern.ch/lpgbt/pigbt/-/blob/master/backend/apiapp/lpgbtLib/lowLevelDrivers/MASTERI2C.py#L83
+        
+        # debugging
+        #print("### LPGBT.I2C_read ###")
+        #print(f"reg: {reg}, \tmaster: {master}, \tslave_addr: {slave_addr}, \tnbytes: {nbytes}, \tadr_nbytes: {adr_nbytes}, \tfreq: {freq}, \tver: {self.ver}")
+
         i2cm      = master
 	
         i2cm1cmd = self.get_node('LPGBT.RW.I2C.I2CM1CMD').real_address
         i2cm0cmd = self.get_node('LPGBT.RW.I2C.I2CM0CMD').real_address
 
+        # debugging
+        #print(f"i2cm1cmd: {i2cm1cmd}, \ti2cm0cmd: {i2cm0cmd}")
+
         if self.ver == 0:
             i2cm1status = self.LPGBT_CONST.I2CM1STATUS
             i2cm0status = self.LPGBT_CONST.I2CM0STATUS
@@ -975,28 +989,49 @@ class LPGBT(RegParser):
         OFFSET_WR = i2cm*(i2cm1cmd - i2cm0cmd) #using the offset trick to switch between masters easily
         OFFSET_RD = i2cm*(i2cm1status - i2cm0status)
 
+        # debugging
+        #print(f"i2cm1status: {i2cm1status}, \ti2cm0status: {i2cm0status}, \ti2cm0data0: {i2cm0data0}, \ti2cm0cmd: {i2cm0cmd}, \ti2cm0address: {i2cm0address}, \tOFFSET_WR: {OFFSET_WR}, \tOFFSET_RD: {OFFSET_RD}")
+
         ################################################################################
         # Write the register address
         ################################################################################
 
         # https://lpgbt.web.cern.ch/lpgbt/v0/i2cMasters.html#i2c-write-cr-0x0
         self.wr_adr(i2cm0data0+OFFSET_WR, adr_nbytes<<self.LPGBT_CONST.I2CM_CR_NBYTES_of | (freq<<self.LPGBT_CONST.I2CM_CR_FREQ_of))
+        # debugging
+        #print(f"Address: {i2cm0data0+OFFSET_WR}, \tValue: {adr_nbytes<<self.LPGBT_CONST.I2CM_CR_NBYTES_of | (freq<<self.LPGBT_CONST.I2CM_CR_FREQ_of)}")
         self.wr_adr(i2cm0cmd+OFFSET_WR, self.LPGBT_CONST.I2CM_WRITE_CRA) #write to config register
+        # debugging
+        #print(f"Address: {i2cm0cmd+OFFSET_WR}, \tValue: {self.LPGBT_CONST.I2CM_WRITE_CRA}")
     
         # https://lpgbt.web.cern.ch/lpgbt/v0/i2cMasters.html#i2c-w-multi-4byte0-0x8
         for i in range (adr_nbytes):
             self.wr_adr(self.get_node("LPGBT.RW.I2C.I2CM0DATA%d"%i).real_address + OFFSET_WR, (reg >> (8*i)) & 0xff )
+            # debugging
+            #print(f"Address: {self.get_node('LPGBT.RW.I2C.I2CM0DATA%d'%i).real_address + OFFSET_WR}, \tValue: {(reg >> (8*i)) & 0xff}, \ti: {i}")
         # self.wr_adr(self.LPGBT_CONST.I2CM0DATA1 + OFFSET_WR , regh)
         self.wr_adr(i2cm0cmd+OFFSET_WR, self.LPGBT_CONST.I2CM_W_MULTI_4BYTE0) # prepare a multi-write
+        # debugging
+        #print(f"Address: {i2cm0cmd+OFFSET_WR}, \tValue: {self.LPGBT_CONST.I2CM_W_MULTI_4BYTE0}")
     
         # https://lpgbt.web.cern.ch/lpgbt/v0/i2cMasters.html#i2c-write-multi-0xc
         self.wr_adr(i2cm0address+OFFSET_WR, slave_addr)
+        # debugging
+        #print(f"Address: {i2cm0address+OFFSET_WR}, \tValue: {slave_addr}")
         self.wr_adr(i2cm0cmd+OFFSET_WR, self.LPGBT_CONST.I2CM_WRITE_MULTI)# execute multi-write
+        # debugging
+        #print(f"Address: {i2cm0cmd+OFFSET_WR}, \tValue: {self.LPGBT_CONST.I2CM_WRITE_MULTI}")
 
         status = self.rd_adr(i2cm0status+OFFSET_RD)
+        
+        # debugging
+        #print(f"status: {status}, LPGBT_CONST.I2CM_SR_SUCC_bm: {self.LPGBT_CONST.I2CM_SR_SUCC_bm}, Address: {i2cm0status+OFFSET_RD}")
+
         retries = 0
         while (status != self.LPGBT_CONST.I2CM_SR_SUCC_bm):
             status = self.rd_adr(i2cm0status+OFFSET_RD)
+            # debugging
+            #print(f"Updating status: {status}, retries: {retries}")
             retries += 1
             if retries > 50:
                 if verbose:
@@ -1016,12 +1051,16 @@ class LPGBT(RegParser):
         self.wr_adr(i2cm0cmd+OFFSET_WR, self.LPGBT_CONST.I2CM_READ_MULTI)# execute read
         
         status = self.rd_adr(i2cm0status+OFFSET_RD)
+
+        # debugging
+        #print(f"status: {status}")
+
         retries = 0
         while (status != self.LPGBT_CONST.I2CM_SR_SUCC_bm):
             status = self.rd_adr(i2cm0status+OFFSET_RD)
             retries += 1
             if retries > 50:
-                if not quiet:
+                if verbose:
                     print ("Read not successfull!")
                 return None
 
@@ -1032,8 +1071,13 @@ class LPGBT(RegParser):
         else:
             i2cm0read15 = self.get_node("LPGBT.RO.I2CREAD.I2CM0READ.I2CM0READ15").real_address
 
+        # debugging
+        #print(f"i2cm0read15: {i2cm0read15}")
+
         for i in range(0, nbytes):
             tmp_adr = abs(i-i2cm0read15)+OFFSET_RD
+            # debugging
+            #print(f"tmp_adr: {tmp_adr}, \ttmp_adr_val: {self.rd_adr(tmp_adr).value()}")
             read_values.append(self.rd_adr(tmp_adr).value())
 
         #read_value = self.rd_adr(self.LPGBT_CONST.I2CM0READ15+OFFSET_RD) # get the read value. this is just the first byte
diff --git a/tamalero/ReadoutBoard.py b/tamalero/ReadoutBoard.py
index f2dacaa..f57066b 100644
--- a/tamalero/ReadoutBoard.py
+++ b/tamalero/ReadoutBoard.py
@@ -353,6 +353,7 @@ class ReadoutBoard:
         # high level function to read all the temperature sensors
         
         adc_7    = self.DAQ_LPGBT.read_adc(7)/(2**10-1)
+        adc_0    = self.DAQ_LPGBT.read_adc(0)/(2**10-1)
         adc_in29 = self.SCA.read_adc(29)/(2**12-1)
         v_ref    = self.DAQ_LPGBT.read_dac()
         t_SCA    = self.SCA.read_temp()  # internal temp from SCA
@@ -366,16 +367,18 @@ class ReadoutBoard:
                 # https://www.digikey.com/en/products/detail/tdk-corporation/NTCG063JF103FTB/5872743
                 # Parameters need updating?
                 curr_dac = self.DAQ_LPGBT.rd_reg("LPGBT.RWF.CUR_DAC.CURDACSELECT")*900/256
-                t1 = get_temp_direct(adc_7, curr_dac, 25, 10000, 3380)  # this comes from the lpGBT ADC
+                t1 = get_temp_direct(adc_7, curr_dac, thermistor="NTCG063JF103FTB")  # this comes from the lpGBT ADC
                 t2 = get_temp(adc_in29, v_ref, 10000, 25, 10000, 3380)  # this comes from the SCA ADC
+                t_VTRX = get_temp_direct(adc_0, curr_dac, thermistor="NCP03XM102E05RL")  # this comes from the lpGBT ADC (VTRX TH)
 
             if verbose>0:
                 print ("\nV_ref is set to: %.3f V"%v_ref)
                 print ("\nTemperature on RB RT1 is: %.3f C"%t1)
                 print ("Temperature on RB RT2 is: %.3f C"%t2)
                 print ("Temperature on RB SCA is: %.3f C"%t_SCA)
+                print ("Temperature on RB VTRX is: %.3f C"%t_VTRX)
         else:
             print ("V_ref found to be 0. Exiting.")
             return {'t_SCA': t_SCA}
 
-        return {'t1': t1, 't2': t2, 't_SCA': t_SCA}
+        return {'t1': t1, 't2': t2, 't_SCA': t_SCA, 't_VTRX': t_VTRX}
diff --git a/tamalero/utils.py b/tamalero/utils.py
index 473f860..490f742 100644
--- a/tamalero/utils.py
+++ b/tamalero/utils.py
@@ -37,33 +37,68 @@ def get_temp(v_out, v_ref, r_ref, t_1, r_1, b, celcius=True):
         return -999
     return t_2-delta_t
 
-def get_temp_direct(v_out, curr_dac, t_1, r_1, b, celcius=True):
+def get_temp_direct(v_out, curr_dac, thermistor="NTCG063JF103FTB", celcius=True):
     """
     Calculate the temperature of a thermistor, given the voltage measured on it.
 
     Arguments:
     v_out (float) -- voltage measured on the thermistor
     curr_dac (float) -- current source value set on the DAC (in uA)
-    t_1 (float) -- reference temperature of thermistor
-    r_1 (float) -- resistance of NTC at reference temperature
-    b (float) -- B coefficient, with B = (ln(r_1)-ln(r_t)) / (1/t_1 - 1/t_out)
+    thermistor (str="NTCG063JF103FTB") -- thermistor used for temperature calculation
 
     Keyword arguments:
     celcius (bool) -- give and return the temperature in degree celcius. Kelvin scale used otherwise.
     """
 
-    delta_t = 273.15 if celcius else 0
-    try:
-        r_t = v_out / (curr_dac / 10**6)
-        print(f"r_t: {r_t}")
-        print(f"v_out: {v_out}")
-        print(f"curr_dac: {curr_dac / 10**6}")
-        print(f"b: {b}")
-        t_2 = b/((b/(t_1+delta_t)) - math.log(r_1) + math.log(r_t))
-    except ZeroDivisionError:
-        print ("Temperature calculation failed!")
-        return -999
-    return t_2-delta_t
+    find_temp = temp_res_fit(thermistor=thermistor)
+
+    r_t = v_out / (curr_dac / 10**6)
+    t = find_temp(np.log10(r_t))
+
+    delta_t = 0 if celcius else 273.15
+    
+    print(f"Thermistor: {thermistor}")
+    print(f"Voltage: {v_out} \t Current: {curr_dac} uA")
+    print(f"Resistance: {r_t}")
+    print(f"Temperature: {t}")
+
+    return t+delta_t
+
+def temp_res_fit(thermistor="NTCG063JF103FTB", power=2):
+
+    T_ref = 25
+    if thermistor=="NTCG063JF103FTB":
+        B_list = [3194, 3270, 3382, 3422]
+        T_list = [-25, 0, 50, 75]
+        R_ref = 10e3
+    elif thermistor=="NTCG063UH103HTBX":
+        B_list = [3770, 3822, 3900, 3926]
+        T_list = [-25, 0, 50, 75]
+        R_ref = 10e3
+    elif thermistor=="NCP03XM102E05RL":
+        B_list = [3500, 3539, 3545, 3560]
+        T_list = [50, 80, 85, 100]
+        R_ref = 1e3
+    else:
+        raise ValueError(f"Only thermistors NTCG063JF103FTB, NTCG063UH103HTBX or NCP03XM102E05RL are currently allowed, but {thermistor} was passed.")
+
+    R_list = []
+
+    for B, T in zip(B_list, T_list):
+        R = R_ref * math.exp(-B * ((1/298.15) - (1/(T+273.15))))
+        R_list.append(R)
+
+    if thermistor=="NTCG063JF103FTB" or thermistor=="NTCG063UH103HTBX":
+        T_list.insert(2, T_ref)     # Reference temperature of thermistor
+        R_list.insert(2, R_ref)     # Reference resistance of NTC at reference temperature
+    elif thermistor=="NCP03XM102E05RL":
+        T_list = [T_ref] + T_list
+        R_list = [R_ref] + R_list
+    
+    poly_coeffs = np.polyfit(np.log10(R_list), T_list, power)
+    fit = np.poly1d(poly_coeffs)
+
+    return fit
 
 def read_mapping(f_in, selection='adc', flavor='small'):
     flavors = {'small':0, 'medium':1, 'large': 2}
-- 
GitLab


From 6c4ca1cf91b4731f466b95bade19f2b528492e8f Mon Sep 17 00:00:00 2001
From: Diego Lopez Gutierrez <dlopezgu@bu.edu>
Date: Thu, 23 Mar 2023 12:41:33 -0400
Subject: [PATCH 4/7] Add current_adcs.yaml file that contains the lpGBT adcs
 to set for current source

---
 configs/current_adcs.yaml | 3 +++
 tamalero/LPGBT.py         | 5 +++--
 2 files changed, 6 insertions(+), 2 deletions(-)
 create mode 100644 configs/current_adcs.yaml

diff --git a/configs/current_adcs.yaml b/configs/current_adcs.yaml
new file mode 100644
index 0000000..e773384
--- /dev/null
+++ b/configs/current_adcs.yaml
@@ -0,0 +1,3 @@
+lpGBT:
+   - 0
+   - 7
diff --git a/tamalero/LPGBT.py b/tamalero/LPGBT.py
index 3552709..5231ae8 100644
--- a/tamalero/LPGBT.py
+++ b/tamalero/LPGBT.py
@@ -127,8 +127,9 @@ class LPGBT(RegParser):
                 self.cal_gain = 1.85
                 self.cal_offset = 512
 
-        self.set_current_adc(7)
-        self.set_current_adc(0)
+        self.current_adcs = load_yaml(os.path.expandvars('$TAMALERO_BASE/configs/current_adcs.yaml'))['lpGBT']
+        for adc in self.current_adcs:
+            self.set_current_adc(adc)
 
     def read_base_config(self):
         #
-- 
GitLab


From 8bde0558ed3e938d15a51b6be2a3c2f834cbeb42 Mon Sep 17 00:00:00 2001
From: Diego Lopez Gutierrez <dlopezgu@bu.edu>
Date: Thu, 23 Mar 2023 15:53:23 -0400
Subject: [PATCH 5/7] Set current source to 100uA to get proper temperatures in
 VTRX and RT1

---
 tamalero/LPGBT.py        | 6 +++---
 tamalero/ReadoutBoard.py | 1 -
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/tamalero/LPGBT.py b/tamalero/LPGBT.py
index 5231ae8..7fdafd3 100644
--- a/tamalero/LPGBT.py
+++ b/tamalero/LPGBT.py
@@ -664,12 +664,12 @@ class LPGBT(RegParser):
         if verbose:
             print(f"Set current source to pin ADC{channel}...", bin(self.rd_reg("LPGBT.RWF.CUR_DAC.CURDACCHNENABLE")))
        
-        curr_dac = 14 # Desired current of 14 uA; max V = 0.977, min V = 0.080 for T in -20-40C range
-        curr_dac_select = round(curr_dac*256/900) # CURDACSELECT is in units of 900/256 uA per bit
+        curr_dac = 100 # Desired current of 100 uA
+        curr_dac_select = min(round(curr_dac*256/900), 255) # CURDACSELECT is in units of 900/256 uA per bit, with max of 255
         self.wr_reg("LPGBT.RWF.CUR_DAC.CURDACSELECT", curr_dac_select)
         if verbose:
             print("Set current source value to...", curr_dac_select*900/256, "uA")
-
+    
     def set_dac(self, v_out):
         if v_out > 1.00:
             print ("Can't set the DAC to a value larger than 1.0 V!")
diff --git a/tamalero/ReadoutBoard.py b/tamalero/ReadoutBoard.py
index f57066b..1dd4074 100644
--- a/tamalero/ReadoutBoard.py
+++ b/tamalero/ReadoutBoard.py
@@ -365,7 +365,6 @@ class ReadoutBoard:
                 t2 = get_temp(adc_in29, v_ref, 10000, 25, 10000, 3900)  # this comes from the SCA ADC
             elif self.ver == 2:
                 # https://www.digikey.com/en/products/detail/tdk-corporation/NTCG063JF103FTB/5872743
-                # Parameters need updating?
                 curr_dac = self.DAQ_LPGBT.rd_reg("LPGBT.RWF.CUR_DAC.CURDACSELECT")*900/256
                 t1 = get_temp_direct(adc_7, curr_dac, thermistor="NTCG063JF103FTB")  # this comes from the lpGBT ADC
                 t2 = get_temp(adc_in29, v_ref, 10000, 25, 10000, 3380)  # this comes from the SCA ADC
-- 
GitLab


From 5f6bee8de102352f79c80540911bca9270428e00 Mon Sep 17 00:00:00 2001
From: Andrew Peck <andrew.peck@cern.ch>
Date: Tue, 11 Apr 2023 13:40:43 -0400
Subject: [PATCH 6/7] fix thermistor readings + cleanup

- use different currents for the two thermistors to keep readings close to
the center of the lpgbt analog input
- to provide separate methods for reading the different thermistors
- provide wrappers around setting and reading the current sources
---
 tamalero/LPGBT.py        | 53 ++++++++++++++++++------
 tamalero/ReadoutBoard.py | 88 ++++++++++++++++++++++++++++------------
 tamalero/utils.py        | 13 +++---
 test_tamalero.py         |  2 +-
 4 files changed, 112 insertions(+), 44 deletions(-)

diff --git a/tamalero/LPGBT.py b/tamalero/LPGBT.py
index 7fdafd3..3203ea8 100644
--- a/tamalero/LPGBT.py
+++ b/tamalero/LPGBT.py
@@ -550,7 +550,25 @@ class LPGBT(RegParser):
         else:
             print(tabulate(table, headers=["Register","Pin", "Reading", "Voltage", "Comment"],  tablefmt="simple_outline"))
 
-    def read_adc(self, channel, convert=False):
+    def set_current_dac(self, units):
+        self.wr_reg("LPGBT.RWF.CUR_DAC.CURDACSELECT", units)
+
+    def get_current_dac(self):
+        return self.rd_reg("LPGBT.RWF.CUR_DAC.CURDACSELECT")
+
+    def set_current_dac_uA(self, uA):
+        # CURDACSELECT is in units of 900/256 uA per bit, with max of 255
+        conv = 256.0/900
+        val = min(round(uA*conv), 255)
+        self.set_current_dac(val)
+        return val/conv
+
+    def get_current_dac_uA(self):
+        # CURDACSELECT is in units of 900/256 uA per bit, with max of 255
+        return self.rd_reg("LPGBT.RWF.CUR_DAC.CURDACSELECT") * 900/256.0
+
+
+    def read_adc(self, channel, calibrate=True, convert=False):
         # ADCInPSelect[3:0]  |  Input
         # ------------------ |----------------------------------------
         # 4'd0               |  ADC0 (external pin)
@@ -587,13 +605,19 @@ class LPGBT(RegParser):
         self.wr_reg("LPGBT.RW.ADC.ADCCONVERT", 0x0)
         self.wr_reg("LPGBT.RW.ADC.ADCENABLE", 0x1)
 
+        if calibrate:
+            val = val*self.cal_gain/1.85 + (512 - self.cal_offset) # calibrate
+
         if convert:
+            conversion = None
             for k in self.adc_mapping.keys():
                 if int(self.adc_mapping[k]['pin']) == channel:
                     conversion = self.adc_mapping[k]['conv']
                     break
-            val = val*self.cal_gain/1.85 + (512 - self.cal_offset) # calibrate
-            val = val / (2**10 - 1) * conversion # convert
+            if conversion is not None:
+                val = val * conversion / (2**10 - 1)
+            else:
+                raise Exception(f"ADC conversion not found when reading ADC {channel}")
         return val
 
     def calibrate_adc(self, recalibrate=False):
@@ -631,7 +655,7 @@ class LPGBT(RegParser):
         self.cal_gain = gain
         self.cal_offset = offset
 
-    def set_current_adc(self, channel, verbose=True):
+    def set_current_adc(self, channel, verbose=False):
         assert channel in range(8), f"Can only choose from ADC0 to ADC7; ADC{channel} was given instead"
         
         self.wr_reg("LPGBT.RWF.VOLTAGE_DAC.CURDACENABLE", 0x1)
@@ -654,21 +678,24 @@ class LPGBT(RegParser):
             adc_chn = self.LPGBT_CONST.CURDAC_CHN6_bm
         elif channel == 7:
             adc_chn = self.LPGBT_CONST.CURDAC_CHN7_bm
+        else:
+            raise Exception("Invalid lpGBT ADC channel selected")
 
         currently_set = self.rd_reg("LPGBT.RWF.CUR_DAC.CURDACCHNENABLE")
-        print(f"LPGBT.RWF.CUR_DAC.CURDACCHNENABLE currently set: {bin(currently_set)}")
-        print(f"Want to set {bin(adc_chn)}")
-        print(f"LPGBT.RWF.CUR_DAC.CURDACCHNENABLE new set: {bin(adc_chn | currently_set)}")
+
+        if verbose:
+            print(f"LPGBT.RWF.CUR_DAC.CURDACCHNENABLE currently set: {bin(currently_set)}")
+            print(f"Want to set {bin(adc_chn)}")
+            print(f"LPGBT.RWF.CUR_DAC.CURDACCHNENABLE new set: {bin(adc_chn | currently_set)}")
 
         self.wr_reg("LPGBT.RWF.CUR_DAC.CURDACCHNENABLE", adc_chn | currently_set) # Set pin ADC channel to current source
         if verbose:
             print(f"Set current source to pin ADC{channel}...", bin(self.rd_reg("LPGBT.RWF.CUR_DAC.CURDACCHNENABLE")))
-       
-        curr_dac = 100 # Desired current of 100 uA
-        curr_dac_select = min(round(curr_dac*256/900), 255) # CURDACSELECT is in units of 900/256 uA per bit, with max of 255
-        self.wr_reg("LPGBT.RWF.CUR_DAC.CURDACSELECT", curr_dac_select)
+
+        current = 100 # Desired current of 100 uA
+        self.set_current_dac_uA(current)
         if verbose:
-            print("Set current source value to...", curr_dac_select*900/256, "uA")
+            print(f"Set current source value to {current} uA")
     
     def set_dac(self, v_out):
         if v_out > 1.00:
@@ -696,6 +723,8 @@ class LPGBT(RegParser):
         elif self.ver == 1:
             lo_bits = self.rd_reg("LPGBT.RWF.VOLTAGE_DAC.VOLDACVALUE_0TO7")
             hi_bits = self.rd_reg("LPGBT.RWF.VOLTAGE_DAC.VOLDACVALUE_8TO11")
+        else:
+            raise Exception("Invalid lpgbt version detected.")
         value = lo_bits | (hi_bits << 8)
         return value/4096*v_ref
 
diff --git a/tamalero/ReadoutBoard.py b/tamalero/ReadoutBoard.py
index 1dd4074..1868a9f 100644
--- a/tamalero/ReadoutBoard.py
+++ b/tamalero/ReadoutBoard.py
@@ -349,35 +349,73 @@ class ReadoutBoard:
                     else:
                         raise RuntimeError(f"{link} link does not have a stable connection after {max_retries} retries")
 
-    def read_temp(self, verbose=0):
-        # high level function to read all the temperature sensors
-        
-        adc_7    = self.DAQ_LPGBT.read_adc(7)/(2**10-1)
-        adc_0    = self.DAQ_LPGBT.read_adc(0)/(2**10-1)
-        adc_in29 = self.SCA.read_adc(29)/(2**12-1)
-        v_ref    = self.DAQ_LPGBT.read_dac()
-        t_SCA    = self.SCA.read_temp()  # internal temp from SCA
+    def read_vtrx_temp(self):
+
+        # vtrx thermistors
+        current_vtrx    = self.DAQ_LPGBT.set_current_dac_uA(600)
+        rt_vtrx_voltage = self.DAQ_LPGBT.read_adc(0)/(2**10-1)
+
+        if self.ver == 1:
+            return -1.0
+        elif self.ver == 2:
+            return get_temp_direct(rt_vtrx_voltage, current_vtrx, thermistor="NCP03XM102E05RL")  # this comes from the lpGBT ADC (VTRX TH)
+        else:
+            raise Exception("Unknown lpgbt version")
+
+    def read_rb_thermistor(self, rt):
+
+        # read voltage reference; some temperature readings depend on it
+        v_ref = self.DAQ_LPGBT.read_dac()
+        if v_ref==0 and ((rt==1 and self.ver==1) or rt==2):
+            raise Exception("Read temperature called with VREF configured as 0V. VREF must be configured to read the temperatures.")
+
+        if rt==1:
+
+            if self.ver == 1:
+                # This uses the DAC output for current so just read the voltage
+                rt1_voltage = self.DAQ_LPGBT.read_adc(7)/(2**10-1) # FIXME: 7 should not be hardcoded
+                return get_temp(rt1_voltage, v_ref, 10000, 25, 10000, 3900)  # this comes from the lpGBT ADC
+            elif self.ver == 2:
+                # Set the DAC current then read the voltage
+                current_rt1 = self.DAQ_LPGBT.set_current_dac_uA(50)
+                rt1_voltage = self.DAQ_LPGBT.read_adc(7)/(2**10-1) # FIXME: 7 should not be hardcoded
+                return get_temp_direct(rt1_voltage, current_rt1, thermistor="NTCG063JF103FTB")  # this comes from the lpGBT ADC
+            else:
+                raise Exception("Unknown lpgbt version")
+
+        elif rt==2:
+
+            rt2_voltage = self.SCA.read_adc(29)/(2**12-1) # FIXME: 29 should not be hardcoded
 
-        if v_ref>0:
             if self.ver == 1:
                 # https://www.digikey.com/en/products/detail/tdk-corporation/NTCG063UH103HTBX/8565486
-                t1 = get_temp(adc_7, v_ref, 10000, 25, 10000, 3900)  # this comes from the lpGBT ADC
-                t2 = get_temp(adc_in29, v_ref, 10000, 25, 10000, 3900)  # this comes from the SCA ADC
+                return get_temp(rt2_voltage, v_ref, 10000, 25, 10000, 3900)  # this comes from the SCA ADC
             elif self.ver == 2:
                 # https://www.digikey.com/en/products/detail/tdk-corporation/NTCG063JF103FTB/5872743
-                curr_dac = self.DAQ_LPGBT.rd_reg("LPGBT.RWF.CUR_DAC.CURDACSELECT")*900/256
-                t1 = get_temp_direct(adc_7, curr_dac, thermistor="NTCG063JF103FTB")  # this comes from the lpGBT ADC
-                t2 = get_temp(adc_in29, v_ref, 10000, 25, 10000, 3380)  # this comes from the SCA ADC
-                t_VTRX = get_temp_direct(adc_0, curr_dac, thermistor="NCP03XM102E05RL")  # this comes from the lpGBT ADC (VTRX TH)
-
-            if verbose>0:
-                print ("\nV_ref is set to: %.3f V"%v_ref)
-                print ("\nTemperature on RB RT1 is: %.3f C"%t1)
-                print ("Temperature on RB RT2 is: %.3f C"%t2)
-                print ("Temperature on RB SCA is: %.3f C"%t_SCA)
-                print ("Temperature on RB VTRX is: %.3f C"%t_VTRX)
+                return get_temp(rt2_voltage, v_ref, 10000, 25, 10000, 3380)  # this comes from the SCA ADC
+            else:
+                raise Exception("Unknown lpgbt version")
+
         else:
-            print ("V_ref found to be 0. Exiting.")
-            return {'t_SCA': t_SCA}
 
-        return {'t1': t1, 't2': t2, 't_SCA': t_SCA, 't_VTRX': t_VTRX}
+            raise Exception(f"Attempt to read unknown thermistor {rt=}")
+
+    def read_temp(self, verbose=False):
+
+        """
+        read all the temperature sensors
+        """
+
+        # internal temp from SCA
+        t_sca = self.SCA.read_temp()
+        t_vtrx = self.read_vtrx_temp()
+        t_rt1 = self.read_rb_thermistor(1)
+        t_rt2 = self.read_rb_thermistor(2)
+
+        if verbose:
+            print ("\nTemperature on RB RT1 is: %.1f C" % t_rt1)
+            print ("Temperature on RB RT2 is: %.1f C" % t_rt2)
+            print ("Temperature on RB SCA is: %.1f C" % t_sca)
+            print ("Temperature on RB VTRX is: %.1f C" % t_vtrx)
+
+        return {'t1': t_rt1, 't2': t_rt2, 't_SCA': t_sca, 't_VTRX': t_vtrx}
diff --git a/tamalero/utils.py b/tamalero/utils.py
index 490f742..e781d71 100644
--- a/tamalero/utils.py
+++ b/tamalero/utils.py
@@ -37,7 +37,7 @@ def get_temp(v_out, v_ref, r_ref, t_1, r_1, b, celcius=True):
         return -999
     return t_2-delta_t
 
-def get_temp_direct(v_out, curr_dac, thermistor="NTCG063JF103FTB", celcius=True):
+def get_temp_direct(v_out, curr_dac, thermistor="NTCG063JF103FTB", celcius=True, verbose=False):
     """
     Calculate the temperature of a thermistor, given the voltage measured on it.
 
@@ -56,11 +56,12 @@ def get_temp_direct(v_out, curr_dac, thermistor="NTCG063JF103FTB", celcius=True)
     t = find_temp(np.log10(r_t))
 
     delta_t = 0 if celcius else 273.15
-    
-    print(f"Thermistor: {thermistor}")
-    print(f"Voltage: {v_out} \t Current: {curr_dac} uA")
-    print(f"Resistance: {r_t}")
-    print(f"Temperature: {t}")
+
+    if verbose:
+        print(f"Thermistor: {thermistor}")
+        print(f"Voltage: {v_out} \t Current: {curr_dac} uA")
+        print(f"Resistance: {r_t}")
+        print(f"Temperature: {t}")
 
     return t+delta_t
 
diff --git a/test_tamalero.py b/test_tamalero.py
index 0c34aef..85d9bc8 100644
--- a/test_tamalero.py
+++ b/test_tamalero.py
@@ -189,7 +189,7 @@ if __name__ == '__main__':
         rb_0.DAQ_LPGBT.read_adcs(check=True)
 
         # High level reading of temperatures
-        temp = rb_0.read_temp(verbose=1)
+        temp = rb_0.read_temp(verbose=True)
 
     #-------------------------------------------------------------------------------
     # I2C Test
-- 
GitLab


From 33293d26e399e50de4365e09efd4512d7e57173b Mon Sep 17 00:00:00 2001
From: Andrew Peck <andrew.peck@cern.ch>
Date: Tue, 11 Apr 2023 13:47:59 -0400
Subject: [PATCH 7/7] fix: disable calibration by default

the calibration settings are not enabled automtically or at the right
stage of running which is causing adc reads to fail
---
 tamalero/LPGBT.py        | 2 +-
 tamalero/ReadoutBoard.py | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tamalero/LPGBT.py b/tamalero/LPGBT.py
index 3203ea8..ff8f4f3 100644
--- a/tamalero/LPGBT.py
+++ b/tamalero/LPGBT.py
@@ -568,7 +568,7 @@ class LPGBT(RegParser):
         return self.rd_reg("LPGBT.RWF.CUR_DAC.CURDACSELECT") * 900/256.0
 
 
-    def read_adc(self, channel, calibrate=True, convert=False):
+    def read_adc(self, channel, calibrate=False, convert=False):
         # ADCInPSelect[3:0]  |  Input
         # ------------------ |----------------------------------------
         # 4'd0               |  ADC0 (external pin)
diff --git a/tamalero/ReadoutBoard.py b/tamalero/ReadoutBoard.py
index 1868a9f..d1a1334 100644
--- a/tamalero/ReadoutBoard.py
+++ b/tamalero/ReadoutBoard.py
@@ -353,7 +353,7 @@ class ReadoutBoard:
 
         # vtrx thermistors
         current_vtrx    = self.DAQ_LPGBT.set_current_dac_uA(600)
-        rt_vtrx_voltage = self.DAQ_LPGBT.read_adc(0)/(2**10-1)
+        rt_vtrx_voltage = self.DAQ_LPGBT.read_adc(0)/(2**10-1) # FIXME: 0 should not be hardcoded
 
         if self.ver == 1:
             return -1.0
-- 
GitLab