Source code for pyspex.lib.tlm_utils

#
# This file is part of pyspex
#
# https://github.com/rmvanhees/pyspex.git
#
# Copyright (c) 2019-2023 SRON - Netherlands Institute for Space Research
#    All Rights Reserved
#
# License:  BSD-3-Clause
"""Contains helper functions for the class `SPXtlm`."""
from __future__ import annotations

__all__ = ['UNITS_DICT', 'convert_hk']

from enum import Enum

import numpy as np
from numpy import ma

# This dictionary is only valid when raw counts are converted to physical units
UNITS_DICT = {'ADC1_GAIN': 'Volt',
              'ADC1_OFFSET': 'Volt',
              'ADC1_REF': 'Volt',
              'ADC1_T': 'K',
              'ADC1_VCC': 'Volt',
              'ADC2_GAIN': 'Volt',
              'ADC2_OFFSET': 'Volt',
              'ADC2_REF': 'Volt',
              'ADC2_T': 'K',
              'ADC2_VCC': 'Volt',
              'DEM_I': 'mA',
              'DEM_T': 'K',
              'DEM_V': 'Volt',
              'HTR1_DUTYCYCL': '%',
              'HTR1_I': 'mA',
              'HTR2_DUTYCYCL': '%',
              'HTR2_I': 'mA',
              'HTR3_DUTYCYCL': '%',
              'HTR3_I': 'mA',
              'HTR4_DUTYCYCL': '%',
              'HTR4_I': 'mA',
              'HTRGRP1_V': 'Volt',
              'HTRGRP2_V': 'Volt',
              'ICU_1P2V_I': 'mA',
              'ICU_1P2V_V': 'Volt',
              'ICU_3P3V_I': 'mA',
              'ICU_3P3V_V': 'Volt',
              'ICU_4P0V_I': 'mA',
              'ICU_4P0V_V': 'Volt',
              'ICU_4V_T': 'K',
              'ICU_5P0V_I': 'mA',
              'ICU_5P0V_V': 'Volt',
              'ICU_5V_T': 'K',
              'ICU_DIGV_T': 'K',
              'ICU_HG1_T': 'K',
              'ICU_HG2_T': 'K',
              'ICU_MCU_T': 'K',
              'ICU_MID_T': 'K',
              'LED1_ANODE_V': 'Volt',
              'LED1_CATH_V': 'Volt',
              'LED1_I': 'mA',
              'LED2_ANODE_V': 'Volt',
              'LED2_CATH_V': 'Volt',
              'LED2_I': 'mA',
              'TS1_DEM_N_T': 'K',
              'TS2_HOUSING_N_T': 'K',
              'TS3_RADIATOR_N_T': 'K',
              'TS4_DEM_R_T': 'K',
              'TS5_HOUSING_R_T': 'K',
              'TS6_RADIATOR_R_T': 'K'}


# - helper functions ------------------------
def exp_spex_det_t(raw_data: np.ndarray) -> np.ndarray:
    """Convert Detector Temperature Sensor to [K]."""
    res = np.empty(raw_data.size, dtype=float)
    mask = raw_data < 400
    res[mask] = 1.224 * raw_data[mask] - 17.05
    res[~mask] = 0.6426 * raw_data[~mask] - 145.57
    return res


def exp_spex_thermistor(raw_data: np.ndarray) -> np.ndarray:
    """Convert readouts of the Temperature Sensors to [K].

    Notes
    -----
    - TS1 DEM Nominal temperature
    - TS2 Housing Nominal Temperature
    - TS3 Radiator Nominal Temperature
    - TS4 DEM Redundant Temperature
    - TS5 Housing Redundant Temperature
    - TS6 Radiator Redundant Temperature*
    """
    coefficients = (294.34, 272589.0, 1.5173e-15, 5.73666e-19, 5.11328e-20)
    buff = ma.masked_array(raw_data / 256, mask=raw_data == 0)
    buff = (coefficients[0]
            + coefficients[1] / buff
            - coefficients[2] * buff ** 4
            + (coefficients[3] - coefficients[4] * ma.log(buff)) * buff ** 5)
    buff[raw_data == 0] = np.nan
    return buff.data


def poly_spex_icuhk_internaltemp(raw_data: np.ndarray) -> np.ndarray:
    """Convert readouts of temperature sensors on ICU power supplies to [K].

    Notes
    -----
    - ICU V5 supply temperature
    - ICU V4 supply temperature
    - ICU HtrG1 supply temperature
    - ICU HtrG2 supply temperature
    - ICU MidBoard temperature
    - ICU MCU-RAM temperature
    - ICU 1V2, 3V3 supply temperature
    """
    coefficients = (273.15, 0.0625)
    return coefficients[0] + coefficients[1] * raw_data


def poly_spex_icuhk_internaltemp2(raw_data: np.ndarray) -> np.ndarray:
    """Convert readings of ICU bus voltages to Voltages.

    Notes
    -----
    - ICU 4.0 Volt bus voltage
    - ICU 3.3 Volt bus voltage
    - ICU 1.2 Volt bus voltage
    - DEM power supply
    """
    coefficients = (0, 0.001)
    return coefficients[0] + coefficients[1] * raw_data


def poly_spex_htr_v(raw_data: np.ndarray) -> np.ndarray:
    """Convert Heater Bus voltages to Volt."""
    coefficients = (0, 0.003)
    return coefficients[0] + coefficients[1] * raw_data


def poly_spex_dutycycle(raw_data: np.ndarray) -> np.ndarray:
    """Convert Heater Controller Duty Cycle output to percent."""
    coefficients = (0, 0.1)
    return coefficients[0] + coefficients[1] * raw_data


def poly_spex_led_anode_v(raw_data: np.ndarray) -> np.ndarray:
    """Convert LED Anode voltage to Volt."""
    coefficients = (0, 0.000000623703003)
    return coefficients[0] + coefficients[1] * raw_data


def poly_spex_led_cath_v(raw_data: np.ndarray) -> np.ndarray:
    """Convert LED Cathode voltage to Volt."""
    coefficients = (0, 0.000000415802001953)
    return coefficients[0] + coefficients[1] * raw_data


def poly_spex_led_i(raw_data: np.ndarray) -> np.ndarray:
    """Convert LED current to milli-Ampere."""
    coefficients = (0, 0.0000030307446495961334745762711864407)
    return coefficients[0] + coefficients[1] * raw_data


def poly_spex_adc_vcc(raw_data: np.ndarray) -> np.ndarray:
    """Convert ADC Analog VCC reading to Volt."""
    coefficients = (0, 0.00000127156575520833333)
    return coefficients[0] + coefficients[1] * raw_data


def poly_spex_adc_gain(raw_data: np.ndarray) -> np.ndarray:
    """Convert ADC Analog VCC reading to Volt."""
    coefficients = (0, 0.000000127156575520833333)
    return coefficients[0] + coefficients[1] * raw_data


def poly_spex_adc_t(raw_data: np.ndarray) -> np.ndarray:
    """Convert ADC1 Temperature reading to [K]."""
    coefficients = (-0.25, 0.0007385466842651367)
    return coefficients[0] + coefficients[1] * raw_data


def poly_spex_adc_offset(raw_data: np.ndarray) -> np.ndarray:
    """Convert ADC offset (?) to Voltage."""
    coefficients = (0, 0.000415802001953)
    return coefficients[0] + coefficients[1] * raw_data


def poly_spex_dem_i(raw_data: np.ndarray) -> np.ndarray:
    """Convert DEM Supply current to milli-Ampere."""
    coefficients = (0, 0.2417)
    return coefficients[0] + coefficients[1] * raw_data


class Enable(Enum):
    """Possible values of the DEM SpaceWire link status."""

    INACTIVE = 0
    ACTIVE = 1


class EnaDis(Enum):
    """Possible values of the LED commanded enable state."""

    OFF = 0
    ON = 1


class IcuMode(Enum):
    """Possible values of the ICU mode."""

    IDLE = 0
    OPER = 1


class IsEna(Enum):
    """Possible values of the Power Sense."""

    DISABLED = 0
    ENABLED = 1


class OcdReg(Enum):
    """Possible values of the OCD state."""

    PWR_OK = 0
    OC2V1 = 1
    OC3V3 = 2
    OC2V1_AND_3V3 = 3


class TimeMsg(Enum):
    """Received status of external PPS or Time message."""

    MISSING = 0
    RECEIVED = 1


class WriteProt(Enum):
    """Status of Flash Write protection (both banks)."""

    BANK0_DISABLED = 0
    BANK0_ENABLED = 1
    BANK1_DISABLED = 16
    BANK1_ENABLED = 17


# - exported functions ----------------------
[docs] def convert_hk(key: str, raw_data: np.ndarray) -> np.ndarray: """Convert a DemHK or NomHK parameter to physical units.""" conv_dict = {'DEM_T': exp_spex_det_t, 'TS1_DEM_N_T': exp_spex_thermistor, 'TS2_HOUSING_N_T': exp_spex_thermistor, 'TS3_RADIATOR_N_T': exp_spex_thermistor, 'TS4_DEM_R_T': exp_spex_thermistor, 'TS5_HOUSING_R_T': exp_spex_thermistor, 'TS6_RADIATOR_R_T': exp_spex_thermistor, 'ADC1_GAIN': poly_spex_adc_gain, 'ADC2_GAIN': poly_spex_adc_gain, 'ADC1_OFFSET': poly_spex_adc_offset, 'ADC2_OFFSET': poly_spex_adc_offset, 'ADC1_T': poly_spex_adc_t, 'ADC2_T': poly_spex_adc_t, 'ADC1_REF': poly_spex_adc_vcc, 'ADC1_VCC': poly_spex_adc_vcc, 'ADC2_REF': poly_spex_adc_vcc, 'ADC2_VCC': poly_spex_adc_vcc, 'DEM_I': poly_spex_dem_i, 'HTR1_DUTYCYCL': poly_spex_dutycycle, 'HTR2_DUTYCYCL': poly_spex_dutycycle, 'HTR3_DUTYCYCL': poly_spex_dutycycle, 'HTR4_DUTYCYCL': poly_spex_dutycycle, 'HTRGRP1_V': poly_spex_htr_v, 'HTRGRP2_V': poly_spex_htr_v, 'ICU_4V_T': poly_spex_icuhk_internaltemp, 'ICU_5V_T': poly_spex_icuhk_internaltemp, 'ICU_DIGV_T': poly_spex_icuhk_internaltemp, 'ICU_HG1_T': poly_spex_icuhk_internaltemp, 'ICU_HG2_T': poly_spex_icuhk_internaltemp, 'ICU_MCU_T': poly_spex_icuhk_internaltemp, 'ICU_MID_T': poly_spex_icuhk_internaltemp, 'DEM_V': poly_spex_icuhk_internaltemp2, 'ICU_1P2V_V': poly_spex_icuhk_internaltemp2, 'ICU_3P3V_V': poly_spex_icuhk_internaltemp2, 'ICU_4P0V_V': poly_spex_icuhk_internaltemp2, 'ICU_5P0V_V': poly_spex_icuhk_internaltemp2, 'LED1_ANODE_V': poly_spex_led_anode_v, 'LED2_ANODE_V': poly_spex_led_anode_v, 'LED1_CATH_V': poly_spex_led_cath_v, 'LED2_CATH_V': poly_spex_led_cath_v, 'LED1_I': poly_spex_led_i, 'LED2_I': poly_spex_led_i} func = conv_dict.get(key, None) if func is not None: return func(raw_data) return raw_data