diff --git a/Ccs/calibrations_SMILE.py b/Ccs/calibrations_SMILE.py
index c9b3189eb954cf5eab0cdffe20ac3537a13e1e74..5ea7b1ab465899bf62224351883d787d14784184 100644
--- a/Ccs/calibrations_SMILE.py
+++ b/Ccs/calibrations_SMILE.py
@@ -15,6 +15,12 @@ T_ZERO = 273.15
 ADC_INPRNG = 7.34783  # V
 ADC_OFFSET = -1.69565  # V
 
+# FEE HK gains/offsets
+FEE_CCD2TsA_gain = 0.013772489
+FEE_CCD2TsA_offset = 542.131358
+FEE_CCD4TsB_gain = 0.013680992
+FEE_CCD4TsB_offset = 525.103894
+
 
 class Dpu:
 
@@ -192,26 +198,6 @@ def t_ccd_deg_to_adu(t):
     return np.where(t <= _ccd_temp_adu_array[0].max(), t_ccd_deg_to_adu_oper(t, warn=False), t_ccd_deg_to_adu_nonoper(t))
 
 
-def t_ccd_fee_adu_to_deg(adu):
-    """
-    For CCD temperature reported in FEE HK
-
-    :param adu:
-    :return:
-    """
-    return adu / 65535 * 4.096 * 338.581 - T_ZERO
-
-
-def t_ccd_fee_deg_to_adu(t):
-    """
-    For CCD temperature reported in FEE HK
-
-    :param t:
-    :return:
-    """
-    return np.rint((t + T_ZERO) / (4.096 * 338.581) * 65535).astype(int)
-
-
 def t_temp1_adu_to_deg(adu):
     return (adu * ADC_INPRNG / (2 ** 14 - 1) + ADC_OFFSET - V_T0.TEMP1) / (V_T0.TEMP1 * K_T.TEMP1)
 
@@ -535,6 +521,75 @@ SIGNAL_IASW_DBS = {
 
 SIGNAL_DBS_IASW = {SIGNAL_IASW_DBS[k]: k for k in SIGNAL_IASW_DBS}
 
+
+def cal_pt1000(temp):
+    return cal_ptx(temp, 1000)
+
+
+def cal_pt2000(temp):
+    return cal_ptx(temp, 2000)
+
+
+def cal_ptx(temp, R0):
+    """
+    Standard DIN EN 60751 PTX transfer curve (-200 - 850°C)
+
+    :param temp: temperature in °C
+    :return: resistance in Ohm
+    """
+    A = 3.9083e-3
+    B = -5.775e-7
+    C = -4.183e-12
+
+    def subzero():
+        return R0 * (1 + A*temp + B*temp**2 + C*(temp - 100)*temp**3)
+
+    def abovezero():
+        return R0 * (1 + A*temp + B*temp**2)
+
+    if (np.array(temp) < -200).any() or (np.array(temp) > 850).any():
+        print("WARNING: Value(s) outside calibrated range (-200 - 850°C)!")
+
+    return np.where(temp > 0, abovezero(), subzero())
+
+
+_ptx = np.arange(-200, 851)
+_pty = cal_pt2000(_ptx)
+_pt2000_curve_inv = sp.interpolate.interp1d(_pty, _ptx, kind='cubic', fill_value='extrapolate')  # inverse PT2000 curve for Ohm to °C conversion
+
+
+def t_ccd_fee_adu_to_deg(adu, ccd):
+    """
+    For CCD temperature reported in FEE HK. Uses PT2000?
+
+    :param adu:
+    :param ccd:
+    :return:
+    """
+    if ccd == 2:
+        return _pt2000_curve_inv(adu * FEE_CCD2TsA_gain + FEE_CCD2TsA_offset)
+    elif ccd == 4:
+        return _pt2000_curve_inv(adu * FEE_CCD4TsB_gain + FEE_CCD4TsB_offset)
+    else:
+        raise ValueError("CCD must be either 2 or 4!")
+
+
+def t_ccd_fee_deg_to_adu(t, ccd):
+    """
+    For CCD temperature reported in FEE HK
+
+    :param t:
+    :param ccd:
+    :return:
+    """
+    if ccd == 2:
+        return np.rint((cal_pt2000(t) - FEE_CCD2TsA_offset) / FEE_CCD2TsA_gain).astype(int)
+    elif ccd == 4:
+        return np.rint((cal_pt2000(t) - FEE_CCD4TsB_offset) / FEE_CCD4TsB_gain).astype(int)
+    else:
+        raise ValueError("CCD must be either 2 or 4!")
+
+
 if __name__ == '__main__':
 
     import matplotlib.pyplot as plt
diff --git a/Ccs/ccs_function_lib.py b/Ccs/ccs_function_lib.py
index 8df849f32db3caf676fd4becdf756b324dfdf322..cbfb7d20157b0c9896f5ac3bbf37d6abaa67c2d9 100644
--- a/Ccs/ccs_function_lib.py
+++ b/Ccs/ccs_function_lib.py
@@ -3810,6 +3810,87 @@ def srectosrecmod(input_srec, output_srec, imageaddr=0x40180000, linesperpack=61
     source_to_srec('srec_binary_source.TC', output_srec, memaddr=imageaddr)
 
 
+def srec_to_s6(fname, memid, memaddr, segid, tcname=None, linesperpack=50, max_pkt_size=MAX_PKT_LEN, image_crc=True):
+    # get service 6,2 info from MIB
+    apid, memid_ref, fmt, endspares = _get_upload_service_info(tcname)
+    pkt_overhead = TC_HEADER_LEN + struct.calcsize(fmt) + SEG_HEADER_LEN + SEG_SPARE_LEN + SEG_CRC_LEN + len(
+        endspares) + PEC_LEN
+    payload_len = max_pkt_size - pkt_overhead
+
+    memid = get_mem_id(memid, memid_ref)
+
+    pckts = []
+
+    f = open(fname, 'r').readlines()[1:]
+    lines = [p[12:-3] for p in f]
+    data_size = len(''.join(lines)) // 2
+    startaddr = int(f[0][4:12], 16)
+
+    upload_bytes = b''
+    linecount = 0
+    bcnt = 0
+    pcnt = 0
+    ptot = None
+
+    while linecount < len(f) - 1:
+
+        t1 = time.time()
+
+        linepacklist = []
+        for n in range(linesperpack):
+            if linecount >= (len(lines) - 1):
+                break
+
+            if (len(''.join(linepacklist)) + len(lines[linecount])) // 2 > payload_len:  # ensure max_pkt_size
+                break
+
+            linepacklist.append(lines[linecount])
+            linelength = len(lines[linecount]) // 2
+            if int(f[linecount + 1][4:12], 16) != (int(f[linecount][4:12], 16) + linelength):
+                linecount += 1
+                newstartaddr = int(f[linecount][4:12], 16)
+                break
+            else:
+                linecount += 1
+                newstartaddr = int(f[linecount][4:12], 16)
+
+        linepack = bytes.fromhex(''.join(linepacklist))
+        dlen = len(linepack)
+        bcnt += dlen
+        # segment header, see IWF DBS HW SW ICD
+        data = struct.pack(SEG_HEADER_FMT, segid, startaddr, dlen // 4) + linepack + bytes(SEG_SPARE_LEN)
+        data = data + crc(data).to_bytes(SEG_CRC_LEN, 'big')
+
+        # create PUS packet
+        packetdata = struct.pack(fmt, memid, memaddr, len(data)) + data + endspares
+        seq_cnt = counters.setdefault(apid, 0)
+        puspckt = Tcpack(data=packetdata, st=6, sst=2, apid=apid, sc=seq_cnt, ack=0b1001)
+
+        if len(puspckt) > MAX_PKT_LEN:
+            logger.warning('Packet length ({}) exceeding MAX_PKT_LEN of {} bytes!'.format(len(puspckt), MAX_PKT_LEN))
+
+        pckts.append(puspckt)
+
+        # collect all uploaded segments for CRC at the end
+        upload_bytes += data
+        pcnt += 1
+
+        startaddr = newstartaddr
+        memaddr += len(data)
+        counters[apid] += 1
+
+    packetdata = struct.pack(fmt, memid, memaddr, 12) + bytes(12) + endspares
+    puspckt = Tcpack(data=packetdata, st=6, sst=2, apid=apid, sc=counters[apid], ack=0b1001)
+    counters[apid] += 1
+    pckts.append(puspckt)
+
+    if image_crc:
+        # return total length of uploaded data (without termination segment) and CRC over entire image, including segment headers
+        return pckts, len(upload_bytes), crc(upload_bytes)
+
+    return pckts
+
+
 def upload_srec(fname, memid, memaddr, segid, pool_name='LIVE', tcname=None, linesperpack=50, sleep=0.125,
                 max_pkt_size=MAX_PKT_LEN, progress=True, image_crc=True):
     """
diff --git a/Ccs/scripts/upload_IASW.py b/Ccs/scripts/upload_IASW.py
index 0372759f7bfc36a19f733db1f2b93a80b2845190..d770f79d753f9d42c755fca8fda72b5246c49af9 100644
--- a/Ccs/scripts/upload_IASW.py
+++ b/Ccs/scripts/upload_IASW.py
@@ -1,17 +1,18 @@
 # Template for uploading the IASW binary to DPU via SREC file
 
 # convert the IASW binary to SREC format
-binary = '/path/to/binary'  # IASW binary
-srecfile = '/path/to/srec'  # SREC filename
+binary = '/home/marko/space/CCS/aux/flightos'  # IASW binary
+srecfile = '/home/marko/space/CCS/aux/flightos.srec'  # SREC filename
 start_addr = 0x60040000  # start address of IASW in RAM
 
-cfl.source_to_srec(binary, srecfile, start_addr, skip_bytes=0)
+cfl.source_to_srec(binary, srecfile, start_addr, skip_bytes=65536)
 
 # upload the SREC content to DPU
 memid = 'MEM_WR_MRAM'  # memory ID, 'DPU_MRAM' or 'MEM_WR_MRAM', depending on whether DBS or IASW S6 is used
 mem_addr = 0x40000000  # address where the data is uploaded to
 segid = 0x200B0101  # ID for data segments, see DBS UM
 
+#pkts, size, chksm = cfl.srec_to_s6(srecfile, memid, mem_addr, segid, max_pkt_size=504)
 cfl.upload_srec(srecfile, memid, mem_addr, segid, pool_name='LIVE', max_pkt_size=504, progress=True)  # optionally, provide the name of the TC that shall be used for upload, e.g., tcname='DBS_TC_LOAD_MEMORY'
 
 #! CCS.BREAKPOINT