#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_IMTQDEFINITIONS_H_
#define MISSION_DEVICES_DEVICEDEFINITIONS_IMTQDEFINITIONS_H_

#include <fsfw/datapoollocal/StaticLocalDataSet.h>

namespace IMTQ {

	static const DeviceCommandId_t NONE = 0x0;
	static const DeviceCommandId_t GET_ENG_HK_DATA = 0x1;
	static const DeviceCommandId_t START_ACTUATION_DIPOLE = 0x2;
	static const DeviceCommandId_t GET_COMMANDED_DIPOLE = 0x3;
	/** Generates new measurement of the magnetic field */
	static const DeviceCommandId_t START_MTM_MEASUREMENT = 0x4;
	/** Requests the calibrated magnetometer measurement */
	static const DeviceCommandId_t GET_CAL_MTM_MEASUREMENT = 0x5;
	/** Requests the raw values measured by the built-in MTM XEN1210 */
	static const DeviceCommandId_t GET_RAW_MTM_MEASUREMENT = 0x6;
	static const DeviceCommandId_t POS_X_SELF_TEST = 0x7;
	static const DeviceCommandId_t NEG_X_SELF_TEST = 0x8;
	static const DeviceCommandId_t POS_Y_SELF_TEST = 0x9;
	static const DeviceCommandId_t NEG_Y_SELF_TEST = 0xA;
	static const DeviceCommandId_t POS_Z_SELF_TEST = 0xB;
	static const DeviceCommandId_t NEG_Z_SELF_TEST = 0xC;
	static const DeviceCommandId_t GET_SELF_TEST_RESULT = 0xD;

	static const uint8_t GET_TEMP_REPLY_SIZE = 2;
	static const uint8_t CFGR_CMD_SIZE = 3;
	static const uint8_t POINTER_REG_SIZE = 1;

	static const uint32_t ENG_HK_DATA_SET_ID = 1;
	static const uint32_t CAL_MTM_SET = 2;
	static const uint32_t RAW_MTM_SET = 3;
	static const uint32_t POS_X_TEST_DATASET = 4;
	static const uint32_t NEG_X_TEST_DATASET = 5;
	static const uint32_t POS_Y_TEST_DATASET = 6;
	static const uint32_t NEG_Y_TEST_DATASET = 7;
	static const uint32_t POS_Z_TEST_DATASET = 8;
	static const uint32_t NEG_Z_TEST_DATASET = 9;

	static const uint8_t SIZE_ENG_HK_COMMAND = 1;
	static const uint8_t SIZE_STATUS_REPLY = 2;
	static const uint8_t SIZE_ENG_HK_DATA_REPLY = 24;
	static const uint8_t SIZE_GET_COMMANDED_DIPOLE_REPLY = 8;
	static const uint8_t SIZE_GET_CAL_MTM_MEASUREMENT = 15;
	static const uint8_t SIZE_GET_RAW_MTM_MEASUREMENT = 15;
	static const uint16_t SIZE_SELF_TEST_RESULTS = 120;

	static const uint16_t MAX_REPLY_SIZE = SIZE_SELF_TEST_RESULTS;
	static const uint8_t MAX_COMMAND_SIZE = 9;

	/** Define entries in IMTQ specific dataset */
	static const uint8_t ENG_HK_SET_POOL_ENTRIES = 11;
	static const uint8_t CAL_MTM_POOL_ENTRIES = 4;
	static const uint8_t SELF_TEST_DATASET_ENTRIES = 104;

	/** Error codes for interpreting the self test error byte */
	static const uint8_t I2C_FAILURE_MASK = 0x1;
	static const uint8_t SPI_FAILURE_MASK = 0x2; // MTM connectivity
	static const uint8_t ADC_FAILURE_MASK = 0x4; // Current/Temp measurement
	static const uint8_t PWM_FAILURE_MASK = 0x8; // Coil actuation
	static const uint8_t TC_FAILURE_MASK = 0x10; // System failure
	static const uint8_t MTM_RANGE_FAILURE_MASK = 0x20; // MTM values outside of expected range
	static const uint8_t COIL_CURRENT_FAILURE_MASK = 0x40; // Coil currents outside of expected range
	static const uint8_t INVALID_ERROR_BYTE = 0x80; // This is an invalid error byte and should be never replied by the IMTQ

	static const uint8_t MAIN_STEP_OFFSET = 43;

	/**
	 * Command code definitions. Each command or reply of an IMTQ request will begin with one of
	 * the following command codes.
	 */
	namespace CC {
	    static const uint8_t START_MTM_MEASUREMENT = 0x4;
	    static const uint8_t START_ACTUATION_DIPOLE = 0x6;
	    static const uint8_t SELF_TEST_CMD = 0x8;
	    static const uint8_t SOFTWARE_RESET = 0xAA;
	    static const uint8_t GET_ENG_HK_DATA = 0x4A;
	    static const uint8_t GET_COMMANDED_DIPOLE = 0x46;
	    static const uint8_t GET_RAW_MTM_MEASUREMENT = 0x42;
	    static const uint8_t GET_CAL_MTM_MEASUREMENT = 0x43;
	    static const uint8_t GET_SELF_TEST_RESULT = 0x47;
	};

	namespace SELF_TEST_AXIS {
	    static const uint8_t ALL = 0x0;
	    static const uint8_t X_POSITIVE = 0x1;
	    static const uint8_t X_NEGATIVE = 0x2;
	    static const uint8_t Y_POSITIVE = 0x3;
	    static const uint8_t Y_NEGATIVE = 0x4;
	    static const uint8_t Z_POSITIVE = 0x5;
	    static const uint8_t Z_NEGATIVE = 0x6;
	}

	namespace SELF_TEST_STEPS {
	    static const uint8_t INIT = 0x0;
	    static const uint8_t X_POSITIVE = 0x1;
	    static const uint8_t X_NEGATIVE = 0x2;
	    static const uint8_t Y_POSITIVE = 0x3;
	    static const uint8_t Y_NEGATIVE = 0x4;
	    static const uint8_t Z_POSITIVE = 0x5;
	    static const uint8_t Z_NEGATIVE = 0x6;
	    static const uint8_t FINA = 0x7;
	}

	enum IMTQPoolIds: lp_id_t {
		DIGITAL_VOLTAGE_MV,
		ANALOG_VOLTAGE_MV,
		DIGITAL_CURRENT,
		ANALOG_CURRENT,
		COIL_X_CURRENT,
		COIL_Y_CURRENT,
		COIL_Z_CURRENT,
		COIL_X_TEMPERATURE,
		COIL_Y_TEMPERATURE,
		COIL_Z_TEMPERATURE,
		MCU_TEMPERATURE,
		MTM_CAL_X,
		MTM_CAL_Y,
		MTM_CAL_Z,
		ACTUATION_CAL_STATUS,
		MTM_RAW_X,
		MTM_RAW_Y,
		MTM_RAW_Z,
		ACTUATION_RAW_STATUS,

		INIT_POS_X_ERR,
		INIT_POS_X_RAW_MAG_X,
		INIT_POS_X_RAW_MAG_Y,
		INIT_POS_X_RAW_MAG_Z,
		INIT_POS_X_CAL_MAG_X,
		INIT_POS_X_CAL_MAG_Y,
		INIT_POS_X_CAL_MAG_Z,
		INIT_POS_X_COIL_X_CURRENT,
		INIT_POS_X_COIL_Y_CURRENT,
		INIT_POS_X_COIL_Z_CURRENT,
		INIT_POS_X_COIL_X_TEMPERATURE,
		INIT_POS_X_COIL_Y_TEMPERATURE,
		INIT_POS_X_COIL_Z_TEMPERATURE,

		INIT_NEG_X_ERR,
		INIT_NEG_X_RAW_MAG_X,
		INIT_NEG_X_RAW_MAG_Y,
		INIT_NEG_X_RAW_MAG_Z,
		INIT_NEG_X_CAL_MAG_X,
		INIT_NEG_X_CAL_MAG_Y,
		INIT_NEG_X_CAL_MAG_Z,
		INIT_NEG_X_COIL_X_CURRENT,
		INIT_NEG_X_COIL_Y_CURRENT,
		INIT_NEG_X_COIL_Z_CURRENT,
		INIT_NEG_X_COIL_X_TEMPERATURE,
		INIT_NEG_X_COIL_Y_TEMPERATURE,
		INIT_NEG_X_COIL_Z_TEMPERATURE,

		INIT_POS_Y_ERR,
		INIT_POS_Y_RAW_MAG_X,
		INIT_POS_Y_RAW_MAG_Y,
		INIT_POS_Y_RAW_MAG_Z,
		INIT_POS_Y_CAL_MAG_X,
		INIT_POS_Y_CAL_MAG_Y,
		INIT_POS_Y_CAL_MAG_Z,
		INIT_POS_Y_COIL_X_CURRENT,
		INIT_POS_Y_COIL_Y_CURRENT,
		INIT_POS_Y_COIL_Z_CURRENT,
		INIT_POS_Y_COIL_X_TEMPERATURE,
		INIT_POS_Y_COIL_Y_TEMPERATURE,
		INIT_POS_Y_COIL_Z_TEMPERATURE,

		INIT_NEG_Y_ERR,
		INIT_NEG_Y_RAW_MAG_X,
		INIT_NEG_Y_RAW_MAG_Y,
		INIT_NEG_Y_RAW_MAG_Z,
		INIT_NEG_Y_CAL_MAG_X,
		INIT_NEG_Y_CAL_MAG_Y,
		INIT_NEG_Y_CAL_MAG_Z,
		INIT_NEG_Y_COIL_X_CURRENT,
		INIT_NEG_Y_COIL_Y_CURRENT,
		INIT_NEG_Y_COIL_Z_CURRENT,
		INIT_NEG_Y_COIL_X_TEMPERATURE,
		INIT_NEG_Y_COIL_Y_TEMPERATURE,
		INIT_NEG_Y_COIL_Z_TEMPERATURE,

		INIT_POS_Z_ERR,
		INIT_POS_Z_RAW_MAG_X,
		INIT_POS_Z_RAW_MAG_Y,
		INIT_POS_Z_RAW_MAG_Z,
		INIT_POS_Z_CAL_MAG_X,
		INIT_POS_Z_CAL_MAG_Y,
		INIT_POS_Z_CAL_MAG_Z,
		INIT_POS_Z_COIL_X_CURRENT,
		INIT_POS_Z_COIL_Y_CURRENT,
		INIT_POS_Z_COIL_Z_CURRENT,
		INIT_POS_Z_COIL_X_TEMPERATURE,
		INIT_POS_Z_COIL_Y_TEMPERATURE,
		INIT_POS_Z_COIL_Z_TEMPERATURE,

		INIT_NEG_Z_ERR,
		INIT_NEG_Z_RAW_MAG_X,
		INIT_NEG_Z_RAW_MAG_Y,
		INIT_NEG_Z_RAW_MAG_Z,
		INIT_NEG_Z_CAL_MAG_X,
		INIT_NEG_Z_CAL_MAG_Y,
		INIT_NEG_Z_CAL_MAG_Z,
		INIT_NEG_Z_COIL_X_CURRENT,
		INIT_NEG_Z_COIL_Y_CURRENT,
		INIT_NEG_Z_COIL_Z_CURRENT,
		INIT_NEG_Z_COIL_X_TEMPERATURE,
		INIT_NEG_Z_COIL_Y_TEMPERATURE,
		INIT_NEG_Z_COIL_Z_TEMPERATURE,

		POS_X_ERR,
		POS_X_RAW_MAG_X,
		POS_X_RAW_MAG_Y,
		POS_X_RAW_MAG_Z,
		POS_X_CAL_MAG_X,
		POS_X_CAL_MAG_Y,
		POS_X_CAL_MAG_Z,
		POS_X_COIL_X_CURRENT,
		POS_X_COIL_Y_CURRENT,
		POS_X_COIL_Z_CURRENT,
		POS_X_COIL_X_TEMPERATURE,
		POS_X_COIL_Y_TEMPERATURE,
		POS_X_COIL_Z_TEMPERATURE,

		NEG_X_ERR,
		NEG_X_RAW_MAG_X,
		NEG_X_RAW_MAG_Y,
		NEG_X_RAW_MAG_Z,
		NEG_X_CAL_MAG_X,
		NEG_X_CAL_MAG_Y,
		NEG_X_CAL_MAG_Z,
		NEG_X_COIL_X_CURRENT,
		NEG_X_COIL_Y_CURRENT,
		NEG_X_COIL_Z_CURRENT,
		NEG_X_COIL_X_TEMPERATURE,
		NEG_X_COIL_Y_TEMPERATURE,
		NEG_X_COIL_Z_TEMPERATURE,

		POS_Y_ERR,
		POS_Y_RAW_MAG_X,
		POS_Y_RAW_MAG_Y,
		POS_Y_RAW_MAG_Z,
		POS_Y_CAL_MAG_X,
		POS_Y_CAL_MAG_Y,
		POS_Y_CAL_MAG_Z,
		POS_Y_COIL_X_CURRENT,
		POS_Y_COIL_Y_CURRENT,
		POS_Y_COIL_Z_CURRENT,
		POS_Y_COIL_X_TEMPERATURE,
		POS_Y_COIL_Y_TEMPERATURE,
		POS_Y_COIL_Z_TEMPERATURE,

		NEG_Y_ERR,
		NEG_Y_RAW_MAG_X,
		NEG_Y_RAW_MAG_Y,
		NEG_Y_RAW_MAG_Z,
		NEG_Y_CAL_MAG_X,
		NEG_Y_CAL_MAG_Y,
		NEG_Y_CAL_MAG_Z,
		NEG_Y_COIL_X_CURRENT,
		NEG_Y_COIL_Y_CURRENT,
		NEG_Y_COIL_Z_CURRENT,
		NEG_Y_COIL_X_TEMPERATURE,
		NEG_Y_COIL_Y_TEMPERATURE,
		NEG_Y_COIL_Z_TEMPERATURE,

		POS_Z_ERR,
		POS_Z_RAW_MAG_X,
		POS_Z_RAW_MAG_Y,
		POS_Z_RAW_MAG_Z,
		POS_Z_CAL_MAG_X,
		POS_Z_CAL_MAG_Y,
		POS_Z_CAL_MAG_Z,
		POS_Z_COIL_X_CURRENT,
		POS_Z_COIL_Y_CURRENT,
		POS_Z_COIL_Z_CURRENT,
		POS_Z_COIL_X_TEMPERATURE,
		POS_Z_COIL_Y_TEMPERATURE,
		POS_Z_COIL_Z_TEMPERATURE,

		NEG_Z_ERR,
		NEG_Z_RAW_MAG_X,
		NEG_Z_RAW_MAG_Y,
		NEG_Z_RAW_MAG_Z,
		NEG_Z_CAL_MAG_X,
		NEG_Z_CAL_MAG_Y,
		NEG_Z_CAL_MAG_Z,
		NEG_Z_COIL_X_CURRENT,
		NEG_Z_COIL_Y_CURRENT,
		NEG_Z_COIL_Z_CURRENT,
		NEG_Z_COIL_X_TEMPERATURE,
		NEG_Z_COIL_Y_TEMPERATURE,
		NEG_Z_COIL_Z_TEMPERATURE,

		FINA_POS_X_ERR,
        FINA_POS_X_RAW_MAG_X,
        FINA_POS_X_RAW_MAG_Y,
        FINA_POS_X_RAW_MAG_Z,
        FINA_POS_X_CAL_MAG_X,
        FINA_POS_X_CAL_MAG_Y,
        FINA_POS_X_CAL_MAG_Z,
        FINA_POS_X_COIL_X_CURRENT,
        FINA_POS_X_COIL_Y_CURRENT,
        FINA_POS_X_COIL_Z_CURRENT,
        FINA_POS_X_COIL_X_TEMPERATURE,
        FINA_POS_X_COIL_Y_TEMPERATURE,
        FINA_POS_X_COIL_Z_TEMPERATURE,

        FINA_NEG_X_ERR,
        FINA_NEG_X_RAW_MAG_X,
        FINA_NEG_X_RAW_MAG_Y,
        FINA_NEG_X_RAW_MAG_Z,
        FINA_NEG_X_CAL_MAG_X,
        FINA_NEG_X_CAL_MAG_Y,
        FINA_NEG_X_CAL_MAG_Z,
        FINA_NEG_X_COIL_X_CURRENT,
        FINA_NEG_X_COIL_Y_CURRENT,
        FINA_NEG_X_COIL_Z_CURRENT,
        FINA_NEG_X_COIL_X_TEMPERATURE,
        FINA_NEG_X_COIL_Y_TEMPERATURE,
        FINA_NEG_X_COIL_Z_TEMPERATURE,

        FINA_POS_Y_ERR,
        FINA_POS_Y_RAW_MAG_X,
        FINA_POS_Y_RAW_MAG_Y,
        FINA_POS_Y_RAW_MAG_Z,
        FINA_POS_Y_CAL_MAG_X,
        FINA_POS_Y_CAL_MAG_Y,
        FINA_POS_Y_CAL_MAG_Z,
        FINA_POS_Y_COIL_X_CURRENT,
        FINA_POS_Y_COIL_Y_CURRENT,
        FINA_POS_Y_COIL_Z_CURRENT,
        FINA_POS_Y_COIL_X_TEMPERATURE,
        FINA_POS_Y_COIL_Y_TEMPERATURE,
        FINA_POS_Y_COIL_Z_TEMPERATURE,

        FINA_NEG_Y_ERR,
        FINA_NEG_Y_RAW_MAG_X,
        FINA_NEG_Y_RAW_MAG_Y,
        FINA_NEG_Y_RAW_MAG_Z,
        FINA_NEG_Y_CAL_MAG_X,
        FINA_NEG_Y_CAL_MAG_Y,
        FINA_NEG_Y_CAL_MAG_Z,
        FINA_NEG_Y_COIL_X_CURRENT,
        FINA_NEG_Y_COIL_Y_CURRENT,
        FINA_NEG_Y_COIL_Z_CURRENT,
        FINA_NEG_Y_COIL_X_TEMPERATURE,
        FINA_NEG_Y_COIL_Y_TEMPERATURE,
        FINA_NEG_Y_COIL_Z_TEMPERATURE,

        FINA_POS_Z_ERR,
        FINA_POS_Z_RAW_MAG_X,
        FINA_POS_Z_RAW_MAG_Y,
        FINA_POS_Z_RAW_MAG_Z,
        FINA_POS_Z_CAL_MAG_X,
        FINA_POS_Z_CAL_MAG_Y,
        FINA_POS_Z_CAL_MAG_Z,
        FINA_POS_Z_COIL_X_CURRENT,
        FINA_POS_Z_COIL_Y_CURRENT,
        FINA_POS_Z_COIL_Z_CURRENT,
        FINA_POS_Z_COIL_X_TEMPERATURE,
        FINA_POS_Z_COIL_Y_TEMPERATURE,
        FINA_POS_Z_COIL_Z_TEMPERATURE,

        FINA_NEG_Z_ERR,
        FINA_NEG_Z_RAW_MAG_X,
        FINA_NEG_Z_RAW_MAG_Y,
        FINA_NEG_Z_RAW_MAG_Z,
        FINA_NEG_Z_CAL_MAG_X,
        FINA_NEG_Z_CAL_MAG_Y,
        FINA_NEG_Z_CAL_MAG_Z,
        FINA_NEG_Z_COIL_X_CURRENT,
        FINA_NEG_Z_COIL_Y_CURRENT,
        FINA_NEG_Z_COIL_Z_CURRENT,
        FINA_NEG_Z_COIL_X_TEMPERATURE,
        FINA_NEG_Z_COIL_Y_TEMPERATURE,
        FINA_NEG_Z_COIL_Z_TEMPERATURE,
	};

class EngHkDataset: public StaticLocalDataSet<ENG_HK_SET_POOL_ENTRIES> {
public:

    EngHkDataset(HasLocalDataPoolIF* owner) :
            StaticLocalDataSet(owner, ENG_HK_DATA_SET_ID) {
    }

    EngHkDataset(object_id_t objectId) :
            StaticLocalDataSet(sid_t(objectId, ENG_HK_DATA_SET_ID)) {
    }

    lp_var_t<uint16_t> digitalVoltageMv = lp_var_t<uint16_t>(sid.objectId, DIGITAL_VOLTAGE_MV,
            this);
    lp_var_t<uint16_t> analogVoltageMv = lp_var_t<uint16_t>(sid.objectId, ANALOG_VOLTAGE_MV, this);
    lp_var_t<float> digitalCurrentmA = lp_var_t<float>(sid.objectId, DIGITAL_CURRENT, this);
    lp_var_t<float> analogCurrentmA = lp_var_t<float>(sid.objectId, ANALOG_CURRENT, this);
    lp_var_t<float> coilXCurrentmA = lp_var_t<float>(sid.objectId, COIL_X_CURRENT, this);
    lp_var_t<float> coilYCurrentmA = lp_var_t<float>(sid.objectId, COIL_Y_CURRENT, this);
    lp_var_t<float> coilZCurrentmA = lp_var_t<float>(sid.objectId, COIL_Z_CURRENT, this);
    /** All temperatures in [�C] */
    lp_var_t<uint16_t> coilXTemperature = lp_var_t<uint16_t>(sid.objectId, COIL_X_TEMPERATURE,
            this);
    lp_var_t<uint16_t> coilYTemperature = lp_var_t<uint16_t>(sid.objectId, COIL_Y_TEMPERATURE,
            this);
    lp_var_t<uint16_t> coilZTemperature = lp_var_t<uint16_t>(sid.objectId, COIL_Z_TEMPERATURE,
            this);
    lp_var_t<uint16_t> mcuTemperature = lp_var_t<uint16_t>(sid.objectId, MCU_TEMPERATURE, this);
};

/**
 * @brief   This dataset holds the last calibrated MTM measurement.
 */
class CalibratedMtmMeasurementSet: public StaticLocalDataSet<CAL_MTM_POOL_ENTRIES> {
public:

    CalibratedMtmMeasurementSet(HasLocalDataPoolIF* owner) :
            StaticLocalDataSet(owner, CAL_MTM_SET) {
    }

    CalibratedMtmMeasurementSet(object_id_t objectId) :
            StaticLocalDataSet(sid_t(objectId, CAL_MTM_SET)) {
    }

    /** The unit of all measurements is nT */
    lp_var_t<int32_t> mtmXnT = lp_var_t<int32_t>(sid.objectId, MTM_CAL_X, this);
    lp_var_t<int32_t> mtmYnT = lp_var_t<int32_t>(sid.objectId, MTM_CAL_Y, this);
    lp_var_t<int32_t> mtmZnT = lp_var_t<int32_t>(sid.objectId, MTM_CAL_Z, this);
    /** 1 if coils were actuating during measurement otherwise 0 */
    lp_var_t<uint8_t> coilActuationStatus = lp_var_t<uint8_t>(sid.objectId, ACTUATION_CAL_STATUS,
            this);
};

/**
 * @brief   This dataset holds the raw MTM measurements.
 */
class RawMtmMeasurementSet: public StaticLocalDataSet<CAL_MTM_POOL_ENTRIES> {
public:

    RawMtmMeasurementSet(HasLocalDataPoolIF* owner) :
            StaticLocalDataSet(owner, RAW_MTM_SET) {
    }

    RawMtmMeasurementSet(object_id_t objectId) :
            StaticLocalDataSet(sid_t(objectId, RAW_MTM_SET)) {
    }

    /** The unit of all measurements is nT */
    lp_var_t<float> mtmXnT = lp_var_t<float>(sid.objectId, MTM_RAW_X, this);
    lp_var_t<float> mtmYnT = lp_var_t<float>(sid.objectId, MTM_RAW_Y, this);
    lp_var_t<float> mtmZnT = lp_var_t<float>(sid.objectId, MTM_RAW_Z, this);
    /** 1 if coils were actuating during measurement otherwise 0 */
    lp_var_t<uint8_t> coilActuationStatus = lp_var_t<uint8_t>(sid.objectId, ACTUATION_RAW_STATUS,
            this);
};


/**
 * @brief   This class can be used to ease the generation of an action message commanding the
 *          IMTQHandler to configure the magnettorquer with the desired dipoles.
 *
 * @details Deserialize the packet, write the deserialized data to the ipc store and store the
 *          the ipc store address in the action message.
 */
class CommandDipolePacket : public SerialLinkedListAdapter<SerializeIF> {
public:

    CommandDipolePacket() {
        setLinks();
    }

private:

    /**
     * @brief   Constructor
     *
     * @param xDipole   The dipole of the x coil in 10 ^ -4 * Am^2
     * @param yDipole   The dipole of the y coil in 10 ^ -4 * Am^2
     * @param zDipole   The dipole of the z coil in 10 ^ -4 * Am^2
     * @param duration  The duration in milliseconds the dipole will be generated by the coils.
     *                  When set to 0, the dipole will be generated until a new dipole actuation
     *                  command is sent.
     */
    CommandDipolePacket(uint16_t xDipole, uint16_t yDipole, uint16_t zDipole, uint16_t duration) :
            xDipole(xDipole), yDipole(yDipole), zDipole(zDipole), duration(duration) {
    }
    void setLinks() {
        setStart(&xDipole);
        xDipole.setNext(&yDipole);
        yDipole.setNext(&zDipole);
        zDipole.setNext(&duration);
    }
    SerializeElement<uint16_t> xDipole;
    SerializeElement<uint16_t> yDipole;
    SerializeElement<uint16_t> zDipole;
    SerializeElement<uint16_t> duration;
};

/**
 * @brief   This dataset can be used to store the self test results of the +X self test.
 *
 * @details Units of measurements:
 *          Raw magnetic field: [nT]
 *          Calibrated magnetic field: [nT]
 *          Coil currents: [mA]
 *          Temperature: [�C]
 *          The +X self test generates a positive dipole in X direction and measures the magnetic
 *          field with the built-in MTM. The procedure of the test is as follows:
 *          1. All coils off (INIT step)
 *          2. +X actuation
 *          3. All coils off (FINA step)
 */
class PosXSelfTestSet: public StaticLocalDataSet<SELF_TEST_DATASET_ENTRIES> {
public:

    PosXSelfTestSet(HasLocalDataPoolIF* owner) :
            StaticLocalDataSet(owner, IMTQ::POS_X_TEST_DATASET) {
    }

    PosXSelfTestSet(object_id_t objectId) :
            StaticLocalDataSet(sid_t(objectId, IMTQ::POS_X_TEST_DATASET)) {
    }

    /** INIT block */
    lp_var_t<uint8_t> initErr = lp_var_t<uint8_t>(sid.objectId, INIT_POS_X_ERR, this);
    lp_var_t<float> initRawMagX = lp_var_t<float>(sid.objectId, INIT_POS_X_RAW_MAG_X, this);
    lp_var_t<float> initRawMagY = lp_var_t<float>(sid.objectId, INIT_POS_X_RAW_MAG_Y, this);
    lp_var_t<float> initRawMagZ = lp_var_t<float>(sid.objectId, INIT_POS_X_RAW_MAG_Z, this);
    lp_var_t<float> initCalMagX = lp_var_t<float>(sid.objectId, INIT_POS_X_CAL_MAG_X, this);
    lp_var_t<float> initCalMagY = lp_var_t<float>(sid.objectId, INIT_POS_X_CAL_MAG_Y, this);
    lp_var_t<float> initCalMagZ = lp_var_t<float>(sid.objectId, INIT_POS_X_CAL_MAG_Z, this);
    lp_var_t<float> initCoilXCurrent = lp_var_t<float>(sid.objectId, INIT_POS_X_COIL_X_CURRENT,
            this);
    lp_var_t<float> initCoilYCurrent = lp_var_t<float>(sid.objectId, INIT_POS_X_COIL_Y_CURRENT,
            this);
    lp_var_t<float> initCoilZCurrent = lp_var_t<float>(sid.objectId, INIT_POS_X_COIL_Z_CURRENT,
            this);
    lp_var_t<uint16_t> initCoilXTemperature = lp_var_t<uint16_t>(sid.objectId,
            INIT_POS_X_COIL_X_TEMPERATURE, this);
    lp_var_t<uint16_t> initCoilYTemperature = lp_var_t<uint16_t>(sid.objectId,
            INIT_POS_X_COIL_Y_TEMPERATURE, this);
    lp_var_t<uint16_t> initCoilZTemperature = lp_var_t<uint16_t>(sid.objectId,
            INIT_POS_X_COIL_Z_TEMPERATURE, this);

    /** +X block */
    lp_var_t<uint8_t> err = lp_var_t<uint8_t>(sid.objectId, POS_X_ERR, this);
    lp_var_t<float> rawMagX = lp_var_t<float>(sid.objectId, POS_X_RAW_MAG_X, this);
    lp_var_t<float> rawMagY = lp_var_t<float>(sid.objectId, POS_X_RAW_MAG_Y, this);
    lp_var_t<float> rawMagZ = lp_var_t<float>(sid.objectId, POS_X_RAW_MAG_Z, this);
    lp_var_t<float> calMagX = lp_var_t<float>(sid.objectId, POS_X_CAL_MAG_X, this);
    lp_var_t<float> calMagY = lp_var_t<float>(sid.objectId, POS_X_CAL_MAG_Y, this);
    lp_var_t<float> calMagZ = lp_var_t<float>(sid.objectId, POS_X_CAL_MAG_Z, this);
    lp_var_t<float> coilXCurrent = lp_var_t<float>(sid.objectId, POS_X_COIL_X_CURRENT,
            this);
    lp_var_t<float> coilYCurrent = lp_var_t<float>(sid.objectId, POS_X_COIL_Y_CURRENT,
            this);
    lp_var_t<float> coilZCurrent = lp_var_t<float>(sid.objectId, POS_X_COIL_Z_CURRENT,
            this);
    lp_var_t<uint16_t> coilXTemperature = lp_var_t<uint16_t>(sid.objectId,
            POS_X_COIL_X_TEMPERATURE, this);
    lp_var_t<uint16_t> coilYTemperature = lp_var_t<uint16_t>(sid.objectId,
            POS_X_COIL_Y_TEMPERATURE, this);
    lp_var_t<uint16_t> coilZTemperature = lp_var_t<uint16_t>(sid.objectId,
            POS_X_COIL_Z_TEMPERATURE, this);

    /** FINA block */
    lp_var_t<uint8_t> finaErr = lp_var_t<uint8_t>(sid.objectId, FINA_POS_X_ERR, this);
    lp_var_t<float> finaRawMagX = lp_var_t<float>(sid.objectId, FINA_POS_X_RAW_MAG_X, this);
    lp_var_t<float> finaRawMagY = lp_var_t<float>(sid.objectId, FINA_POS_X_RAW_MAG_Y, this);
    lp_var_t<float> finaRawMagZ = lp_var_t<float>(sid.objectId, FINA_POS_X_RAW_MAG_Z, this);
    lp_var_t<float> finaCalMagX = lp_var_t<float>(sid.objectId, FINA_POS_X_CAL_MAG_X, this);
    lp_var_t<float> finaCalMagY = lp_var_t<float>(sid.objectId, FINA_POS_X_CAL_MAG_Y, this);
    lp_var_t<float> finaCalMagZ = lp_var_t<float>(sid.objectId, FINA_POS_X_CAL_MAG_Z, this);
    lp_var_t<float> finaCoilXCurrent = lp_var_t<float>(sid.objectId, FINA_POS_X_COIL_X_CURRENT,
            this);
    lp_var_t<float> finaCoilYCurrent = lp_var_t<float>(sid.objectId, FINA_POS_X_COIL_Y_CURRENT,
            this);
    lp_var_t<float> finaCoilZCurrent = lp_var_t<float>(sid.objectId, FINA_POS_X_COIL_Z_CURRENT,
            this);
    lp_var_t<uint16_t> finaCoilXTemperature = lp_var_t<uint16_t>(sid.objectId,
            FINA_POS_X_COIL_X_TEMPERATURE, this);
    lp_var_t<uint16_t> finaCoilYTemperature = lp_var_t<uint16_t>(sid.objectId,
            FINA_POS_X_COIL_Y_TEMPERATURE, this);
    lp_var_t<uint16_t> finaCoilZTemperature = lp_var_t<uint16_t>(sid.objectId,
            FINA_POS_X_COIL_Z_TEMPERATURE, this);
};

/**
 * @brief   This dataset can be used to store the self test results of the -X self test.
 *
 * @details Units of measurements:
 *          Raw magnetic field: [nT]
 *          Calibrated magnetic field: [nT]
 *          Coil currents: [mA]
 *          Temperature: [�C]
 *          The -X self test generates a negative dipole in X direction and measures the magnetic
 *          field with the built-in MTM. The procedure of the test is as follows:
 *          1. All coils off (INIT step)
 *          2. -X actuation
 *          3. All coils off (FINA step)
 */
class NegXSelfTestSet: public StaticLocalDataSet<SELF_TEST_DATASET_ENTRIES> {
public:

    NegXSelfTestSet(HasLocalDataPoolIF* owner) :
            StaticLocalDataSet(owner, IMTQ::NEG_X_TEST_DATASET) {
    }

    NegXSelfTestSet(object_id_t objectId) :
            StaticLocalDataSet(sid_t(objectId, IMTQ::NEG_X_TEST_DATASET)) {
    }

    /** INIT block */
    lp_var_t<uint8_t> initErr = lp_var_t<uint8_t>(sid.objectId, INIT_NEG_X_ERR, this);
    lp_var_t<float> initRawMagX = lp_var_t<float>(sid.objectId, INIT_NEG_X_RAW_MAG_X, this);
    lp_var_t<float> initRawMagY = lp_var_t<float>(sid.objectId, INIT_NEG_X_RAW_MAG_Y, this);
    lp_var_t<float> initRawMagZ = lp_var_t<float>(sid.objectId, INIT_NEG_X_RAW_MAG_Z, this);
    lp_var_t<float> initCalMagX = lp_var_t<float>(sid.objectId, INIT_NEG_X_CAL_MAG_X, this);
    lp_var_t<float> initCalMagY = lp_var_t<float>(sid.objectId, INIT_NEG_X_CAL_MAG_Y, this);
    lp_var_t<float> initCalMagZ = lp_var_t<float>(sid.objectId, INIT_NEG_X_CAL_MAG_Z, this);
    lp_var_t<float> initCoilXCurrent = lp_var_t<float>(sid.objectId, INIT_NEG_X_COIL_X_CURRENT,
            this);
    lp_var_t<float> initCoilYCurrent = lp_var_t<float>(sid.objectId, INIT_NEG_X_COIL_Y_CURRENT,
            this);
    lp_var_t<float> initCoilZCurrent = lp_var_t<float>(sid.objectId, INIT_NEG_X_COIL_Z_CURRENT,
            this);
    lp_var_t<uint16_t> initCoilXTemperature = lp_var_t<uint16_t>(sid.objectId,
            INIT_NEG_X_COIL_X_TEMPERATURE, this);
    lp_var_t<uint16_t> initCoilYTemperature = lp_var_t<uint16_t>(sid.objectId,
            INIT_NEG_X_COIL_Y_TEMPERATURE, this);
    lp_var_t<uint16_t> initCoilZTemperature = lp_var_t<uint16_t>(sid.objectId,
            INIT_NEG_X_COIL_Z_TEMPERATURE, this);

    /** -X block */
    lp_var_t<uint8_t> err = lp_var_t<uint8_t>(sid.objectId, NEG_X_ERR, this);
    lp_var_t<float> rawMagX = lp_var_t<float>(sid.objectId, NEG_X_RAW_MAG_X, this);
    lp_var_t<float> rawMagY = lp_var_t<float>(sid.objectId, NEG_X_RAW_MAG_Y, this);
    lp_var_t<float> rawMagZ = lp_var_t<float>(sid.objectId, NEG_X_RAW_MAG_Z, this);
    lp_var_t<float> calMagX = lp_var_t<float>(sid.objectId, NEG_X_CAL_MAG_X, this);
    lp_var_t<float> calMagY = lp_var_t<float>(sid.objectId, NEG_X_CAL_MAG_Y, this);
    lp_var_t<float> calMagZ = lp_var_t<float>(sid.objectId, NEG_X_CAL_MAG_Z, this);
    lp_var_t<float> coilXCurrent = lp_var_t<float>(sid.objectId, NEG_X_COIL_X_CURRENT,
            this);
    lp_var_t<float> coilYCurrent = lp_var_t<float>(sid.objectId, NEG_X_COIL_Y_CURRENT,
            this);
    lp_var_t<float> coilZCurrent = lp_var_t<float>(sid.objectId, NEG_X_COIL_Z_CURRENT,
            this);
    lp_var_t<uint16_t> coilXTemperature = lp_var_t<uint16_t>(sid.objectId,
            NEG_X_COIL_X_TEMPERATURE, this);
    lp_var_t<uint16_t> coilYTemperature = lp_var_t<uint16_t>(sid.objectId,
            NEG_X_COIL_Y_TEMPERATURE, this);
    lp_var_t<uint16_t> coilZTemperature = lp_var_t<uint16_t>(sid.objectId,
            NEG_X_COIL_Z_TEMPERATURE, this);

    /** FINA block */
    lp_var_t<uint8_t> finaErr = lp_var_t<uint8_t>(sid.objectId, FINA_NEG_X_ERR, this);
    lp_var_t<float> finaRawMagX = lp_var_t<float>(sid.objectId, FINA_NEG_X_RAW_MAG_X, this);
    lp_var_t<float> finaRawMagY = lp_var_t<float>(sid.objectId, FINA_NEG_X_RAW_MAG_Y, this);
    lp_var_t<float> finaRawMagZ = lp_var_t<float>(sid.objectId, FINA_NEG_X_RAW_MAG_Z, this);
    lp_var_t<float> finaCalMagX = lp_var_t<float>(sid.objectId, FINA_NEG_X_CAL_MAG_X, this);
    lp_var_t<float> finaCalMagY = lp_var_t<float>(sid.objectId, FINA_NEG_X_CAL_MAG_Y, this);
    lp_var_t<float> finaCalMagZ = lp_var_t<float>(sid.objectId, FINA_NEG_X_CAL_MAG_Z, this);
    lp_var_t<float> finaCoilXCurrent = lp_var_t<float>(sid.objectId, FINA_NEG_X_COIL_X_CURRENT,
            this);
    lp_var_t<float> finaCoilYCurrent = lp_var_t<float>(sid.objectId, FINA_NEG_X_COIL_Y_CURRENT,
            this);
    lp_var_t<float> finaCoilZCurrent = lp_var_t<float>(sid.objectId, FINA_NEG_X_COIL_Z_CURRENT,
            this);
    lp_var_t<uint16_t> finaCoilXTemperature = lp_var_t<uint16_t>(sid.objectId,
            FINA_NEG_X_COIL_X_TEMPERATURE, this);
    lp_var_t<uint16_t> finaCoilYTemperature = lp_var_t<uint16_t>(sid.objectId,
            FINA_NEG_X_COIL_Y_TEMPERATURE, this);
    lp_var_t<uint16_t> finaCoilZTemperature = lp_var_t<uint16_t>(sid.objectId,
            FINA_NEG_X_COIL_Z_TEMPERATURE, this);
};


/**
 * @brief   This dataset can be used to store the self test results of the +Y self test.
 *
 * @details Units of measurements:
 *          Raw magnetic field: [nT]
 *          Calibrated magnetic field: [nT]
 *          Coil currents: [mA]
 *          Temperature: [�C]
 *          The +Y self test generates a positive dipole in y direction and measures the magnetic
 *          field with the built-in MTM. The procedure of the test is as follows:
 *          1. All coils off (INIT step)
 *          2. +Y actuation
 *          3. All coils off (FINA step)
 */
class PosYSelfTestSet: public StaticLocalDataSet<SELF_TEST_DATASET_ENTRIES> {
public:

    PosYSelfTestSet(HasLocalDataPoolIF* owner) :
            StaticLocalDataSet(owner, IMTQ::POS_Y_TEST_DATASET) {
    }

    PosYSelfTestSet(object_id_t objectId) :
            StaticLocalDataSet(sid_t(objectId, IMTQ::POS_Y_TEST_DATASET)) {
    }

    /** INIT block */
    lp_var_t<uint8_t> initErr = lp_var_t<uint8_t>(sid.objectId, INIT_POS_Y_ERR, this);
    lp_var_t<float> initRawMagX = lp_var_t<float>(sid.objectId, INIT_POS_Y_RAW_MAG_X, this);
    lp_var_t<float> initRawMagY = lp_var_t<float>(sid.objectId, INIT_POS_Y_RAW_MAG_Y, this);
    lp_var_t<float> initRawMagZ = lp_var_t<float>(sid.objectId, INIT_POS_Y_RAW_MAG_Z, this);
    lp_var_t<float> initCalMagX = lp_var_t<float>(sid.objectId, INIT_POS_Y_CAL_MAG_X, this);
    lp_var_t<float> initCalMagY = lp_var_t<float>(sid.objectId, INIT_POS_Y_CAL_MAG_Y, this);
    lp_var_t<float> initCalMagZ = lp_var_t<float>(sid.objectId, INIT_POS_Y_CAL_MAG_Z, this);
    lp_var_t<float> initCoilXCurrent = lp_var_t<float>(sid.objectId, INIT_POS_Y_COIL_X_CURRENT,
            this);
    lp_var_t<float> initCoilYCurrent = lp_var_t<float>(sid.objectId, INIT_POS_Y_COIL_Y_CURRENT,
            this);
    lp_var_t<float> initCoilZCurrent = lp_var_t<float>(sid.objectId, INIT_POS_Y_COIL_Z_CURRENT,
            this);
    lp_var_t<uint16_t> initCoilXTemperature = lp_var_t<uint16_t>(sid.objectId,
            INIT_POS_Y_COIL_X_TEMPERATURE, this);
    lp_var_t<uint16_t> initCoilYTemperature = lp_var_t<uint16_t>(sid.objectId,
            INIT_POS_Y_COIL_Y_TEMPERATURE, this);
    lp_var_t<uint16_t> initCoilZTemperature = lp_var_t<uint16_t>(sid.objectId,
            INIT_POS_Y_COIL_Z_TEMPERATURE, this);

    /** +Y block */
    lp_var_t<uint8_t> err = lp_var_t<uint8_t>(sid.objectId, POS_Y_ERR, this);
    lp_var_t<float> rawMagX = lp_var_t<float>(sid.objectId, POS_Y_RAW_MAG_X, this);
    lp_var_t<float> rawMagY = lp_var_t<float>(sid.objectId, POS_Y_RAW_MAG_Y, this);
    lp_var_t<float> rawMagZ = lp_var_t<float>(sid.objectId, POS_Y_RAW_MAG_Z, this);
    lp_var_t<float> calMagX = lp_var_t<float>(sid.objectId, POS_Y_CAL_MAG_X, this);
    lp_var_t<float> calMagY = lp_var_t<float>(sid.objectId, POS_Y_CAL_MAG_Y, this);
    lp_var_t<float> calMagZ = lp_var_t<float>(sid.objectId, POS_Y_CAL_MAG_Z, this);
    lp_var_t<float> coilXCurrent = lp_var_t<float>(sid.objectId, POS_Y_COIL_X_CURRENT,
            this);
    lp_var_t<float> coilYCurrent = lp_var_t<float>(sid.objectId, POS_Y_COIL_Y_CURRENT,
            this);
    lp_var_t<float> coilZCurrent = lp_var_t<float>(sid.objectId, POS_Y_COIL_Z_CURRENT,
            this);
    lp_var_t<uint16_t> coilXTemperature = lp_var_t<uint16_t>(sid.objectId,
            POS_Y_COIL_X_TEMPERATURE, this);
    lp_var_t<uint16_t> coilYTemperature = lp_var_t<uint16_t>(sid.objectId,
            POS_Y_COIL_Y_TEMPERATURE, this);
    lp_var_t<uint16_t> coilZTemperature = lp_var_t<uint16_t>(sid.objectId,
            POS_Y_COIL_Z_TEMPERATURE, this);

    /** FINA block */
    lp_var_t<uint8_t> finaErr = lp_var_t<uint8_t>(sid.objectId, FINA_POS_Y_ERR, this);
    lp_var_t<float> finaRawMagX = lp_var_t<float>(sid.objectId, FINA_POS_Y_RAW_MAG_X, this);
    lp_var_t<float> finaRawMagY = lp_var_t<float>(sid.objectId, FINA_POS_Y_RAW_MAG_Y, this);
    lp_var_t<float> finaRawMagZ = lp_var_t<float>(sid.objectId, FINA_POS_Y_RAW_MAG_Z, this);
    lp_var_t<float> finaCalMagX = lp_var_t<float>(sid.objectId, FINA_POS_Y_CAL_MAG_X, this);
    lp_var_t<float> finaCalMagY = lp_var_t<float>(sid.objectId, FINA_POS_Y_CAL_MAG_Y, this);
    lp_var_t<float> finaCalMagZ = lp_var_t<float>(sid.objectId, FINA_POS_Y_CAL_MAG_Z, this);
    lp_var_t<float> finaCoilXCurrent = lp_var_t<float>(sid.objectId, FINA_POS_Y_COIL_X_CURRENT,
            this);
    lp_var_t<float> finaCoilYCurrent = lp_var_t<float>(sid.objectId, FINA_POS_Y_COIL_Y_CURRENT,
            this);
    lp_var_t<float> finaCoilZCurrent = lp_var_t<float>(sid.objectId, FINA_POS_Y_COIL_Z_CURRENT,
            this);
    lp_var_t<uint16_t> finaCoilXTemperature = lp_var_t<uint16_t>(sid.objectId,
            FINA_POS_Y_COIL_X_TEMPERATURE, this);
    lp_var_t<uint16_t> finaCoilYTemperature = lp_var_t<uint16_t>(sid.objectId,
            FINA_POS_Y_COIL_Y_TEMPERATURE, this);
    lp_var_t<uint16_t> finaCoilZTemperature = lp_var_t<uint16_t>(sid.objectId,
            FINA_POS_Y_COIL_Z_TEMPERATURE, this);
};

/**
 * @brief   This dataset can be used to store the self test results of the -Y self test.
 *
 * @details Units of measurements:
 *          Raw magnetic field: [nT]
 *          Calibrated magnetic field: [nT]
 *          Coil currents: [mA]
 *          Temperature: [�C]
 *          The -Y self test generates a negative dipole in y direction and measures the magnetic
 *          field with the built-in MTM. The procedure of the test is as follows:
 *          1. All coils off (INIT step)
 *          2. -Y actuation
 *          3. All coils off (FINA step)
 */
class NegYSelfTestSet: public StaticLocalDataSet<SELF_TEST_DATASET_ENTRIES> {
public:

    NegYSelfTestSet(HasLocalDataPoolIF* owner) :
            StaticLocalDataSet(owner, IMTQ::NEG_Y_TEST_DATASET) {
    }

    NegYSelfTestSet(object_id_t objectId) :
            StaticLocalDataSet(sid_t(objectId, IMTQ::NEG_Y_TEST_DATASET)) {
    }

    /** INIT block */
    lp_var_t<uint8_t> initErr = lp_var_t<uint8_t>(sid.objectId, INIT_NEG_Y_ERR, this);
    lp_var_t<float> initRawMagX = lp_var_t<float>(sid.objectId, INIT_NEG_Y_RAW_MAG_X, this);
    lp_var_t<float> initRawMagY = lp_var_t<float>(sid.objectId, INIT_NEG_Y_RAW_MAG_Y, this);
    lp_var_t<float> initRawMagZ = lp_var_t<float>(sid.objectId, INIT_NEG_Y_RAW_MAG_Z, this);
    lp_var_t<float> initCalMagX = lp_var_t<float>(sid.objectId, INIT_NEG_Y_CAL_MAG_X, this);
    lp_var_t<float> initCalMagY = lp_var_t<float>(sid.objectId, INIT_NEG_Y_CAL_MAG_Y, this);
    lp_var_t<float> initCalMagZ = lp_var_t<float>(sid.objectId, INIT_NEG_Y_CAL_MAG_Z, this);
    lp_var_t<float> initCoilXCurrent = lp_var_t<float>(sid.objectId, INIT_NEG_Y_COIL_X_CURRENT,
            this);
    lp_var_t<float> initCoilYCurrent = lp_var_t<float>(sid.objectId, INIT_NEG_Y_COIL_Y_CURRENT,
            this);
    lp_var_t<float> initCoilZCurrent = lp_var_t<float>(sid.objectId, INIT_NEG_Y_COIL_Z_CURRENT,
            this);
    lp_var_t<uint16_t> initCoilXTemperature = lp_var_t<uint16_t>(sid.objectId,
            INIT_NEG_Y_COIL_X_TEMPERATURE, this);
    lp_var_t<uint16_t> initCoilYTemperature = lp_var_t<uint16_t>(sid.objectId,
            INIT_NEG_Y_COIL_Y_TEMPERATURE, this);
    lp_var_t<uint16_t> initCoilZTemperature = lp_var_t<uint16_t>(sid.objectId,
            INIT_NEG_Y_COIL_Z_TEMPERATURE, this);

    /** -Y block */
    lp_var_t<uint8_t> err = lp_var_t<uint8_t>(sid.objectId, NEG_Y_ERR, this);
    lp_var_t<float> rawMagX = lp_var_t<float>(sid.objectId, NEG_Y_RAW_MAG_X, this);
    lp_var_t<float> rawMagY = lp_var_t<float>(sid.objectId, NEG_Y_RAW_MAG_Y, this);
    lp_var_t<float> rawMagZ = lp_var_t<float>(sid.objectId, NEG_Y_RAW_MAG_Z, this);
    lp_var_t<float> calMagX = lp_var_t<float>(sid.objectId, NEG_Y_CAL_MAG_X, this);
    lp_var_t<float> calMagY = lp_var_t<float>(sid.objectId, NEG_Y_CAL_MAG_Y, this);
    lp_var_t<float> calMagZ = lp_var_t<float>(sid.objectId, NEG_Y_CAL_MAG_Z, this);
    lp_var_t<float> coilXCurrent = lp_var_t<float>(sid.objectId, NEG_Y_COIL_X_CURRENT,
            this);
    lp_var_t<float> coilYCurrent = lp_var_t<float>(sid.objectId, NEG_Y_COIL_Y_CURRENT,
            this);
    lp_var_t<float> coilZCurrent = lp_var_t<float>(sid.objectId, NEG_Y_COIL_Z_CURRENT,
            this);
    lp_var_t<uint16_t> coilXTemperature = lp_var_t<uint16_t>(sid.objectId,
            NEG_Y_COIL_X_TEMPERATURE, this);
    lp_var_t<uint16_t> coilYTemperature = lp_var_t<uint16_t>(sid.objectId,
            NEG_Y_COIL_Y_TEMPERATURE, this);
    lp_var_t<uint16_t> coilZTemperature = lp_var_t<uint16_t>(sid.objectId,
            NEG_Y_COIL_Z_TEMPERATURE, this);

    /** FINA block */
    lp_var_t<uint8_t> finaErr = lp_var_t<uint8_t>(sid.objectId, FINA_NEG_Y_ERR, this);
    lp_var_t<float> finaRawMagX = lp_var_t<float>(sid.objectId, FINA_NEG_Y_RAW_MAG_X, this);
    lp_var_t<float> finaRawMagY = lp_var_t<float>(sid.objectId, FINA_NEG_Y_RAW_MAG_Y, this);
    lp_var_t<float> finaRawMagZ = lp_var_t<float>(sid.objectId, FINA_NEG_Y_RAW_MAG_Z, this);
    lp_var_t<float> finaCalMagX = lp_var_t<float>(sid.objectId, FINA_NEG_Y_CAL_MAG_X, this);
    lp_var_t<float> finaCalMagY = lp_var_t<float>(sid.objectId, FINA_NEG_Y_CAL_MAG_Y, this);
    lp_var_t<float> finaCalMagZ = lp_var_t<float>(sid.objectId, FINA_NEG_Y_CAL_MAG_Z, this);
    lp_var_t<float> finaCoilXCurrent = lp_var_t<float>(sid.objectId, FINA_NEG_Y_COIL_X_CURRENT,
            this);
    lp_var_t<float> finaCoilYCurrent = lp_var_t<float>(sid.objectId, FINA_NEG_Y_COIL_Y_CURRENT,
            this);
    lp_var_t<float> finaCoilZCurrent = lp_var_t<float>(sid.objectId, FINA_NEG_Y_COIL_Z_CURRENT,
            this);
    lp_var_t<uint16_t> finaCoilXTemperature = lp_var_t<uint16_t>(sid.objectId,
            FINA_NEG_Y_COIL_X_TEMPERATURE, this);
    lp_var_t<uint16_t> finaCoilYTemperature = lp_var_t<uint16_t>(sid.objectId,
            FINA_NEG_Y_COIL_Y_TEMPERATURE, this);
    lp_var_t<uint16_t> finaCoilZTemperature = lp_var_t<uint16_t>(sid.objectId,
            FINA_NEG_Y_COIL_Z_TEMPERATURE, this);
};

/**
 * @brief   This dataset can be used to store the self test results of the +Z self test.
 *
 * @details Units of measurements:
 *          Raw magnetic field: [nT]
 *          Calibrated magnetic field: [nT]
 *          Coil currents: [mA]
 *          Temperature: [�C]
 *          The +Z self test generates a positive dipole in z direction and measures the magnetic
 *          field with the built-in MTM. The procedure of the test is as follows:
 *          1. All coils off (INIT step)
 *          2. +Z actuation
 *          3. All coils off (FINA step)
 */
class PosZSelfTestSet: public StaticLocalDataSet<SELF_TEST_DATASET_ENTRIES> {
public:

    PosZSelfTestSet(HasLocalDataPoolIF* owner) :
            StaticLocalDataSet(owner, IMTQ::POS_Z_TEST_DATASET) {
    }

    PosZSelfTestSet(object_id_t objectId) :
            StaticLocalDataSet(sid_t(objectId, IMTQ::POS_Z_TEST_DATASET)) {
    }

    /** INIT block */
    lp_var_t<uint8_t> initErr = lp_var_t<uint8_t>(sid.objectId, INIT_POS_Z_ERR, this);
    lp_var_t<float> initRawMagX = lp_var_t<float>(sid.objectId, INIT_POS_Z_RAW_MAG_X, this);
    lp_var_t<float> initRawMagY = lp_var_t<float>(sid.objectId, INIT_POS_Z_RAW_MAG_Y, this);
    lp_var_t<float> initRawMagZ = lp_var_t<float>(sid.objectId, INIT_POS_Z_RAW_MAG_Z, this);
    lp_var_t<float> initCalMagX = lp_var_t<float>(sid.objectId, INIT_POS_Z_CAL_MAG_X, this);
    lp_var_t<float> initCalMagY = lp_var_t<float>(sid.objectId, INIT_POS_Z_CAL_MAG_Y, this);
    lp_var_t<float> initCalMagZ = lp_var_t<float>(sid.objectId, INIT_POS_Z_CAL_MAG_Z, this);
    lp_var_t<float> initCoilXCurrent = lp_var_t<float>(sid.objectId, INIT_POS_Z_COIL_X_CURRENT,
            this);
    lp_var_t<float> initCoilYCurrent = lp_var_t<float>(sid.objectId, INIT_POS_Z_COIL_Y_CURRENT,
            this);
    lp_var_t<float> initCoilZCurrent = lp_var_t<float>(sid.objectId, INIT_POS_Z_COIL_Z_CURRENT,
            this);
    lp_var_t<uint16_t> initCoilXTemperature = lp_var_t<uint16_t>(sid.objectId,
            INIT_POS_Z_COIL_X_TEMPERATURE, this);
    lp_var_t<uint16_t> initCoilYTemperature = lp_var_t<uint16_t>(sid.objectId,
            INIT_POS_Z_COIL_Y_TEMPERATURE, this);
    lp_var_t<uint16_t> initCoilZTemperature = lp_var_t<uint16_t>(sid.objectId,
            INIT_POS_Z_COIL_Z_TEMPERATURE, this);

    /** +Z block */
    lp_var_t<uint8_t> err = lp_var_t<uint8_t>(sid.objectId, POS_Z_ERR, this);
    lp_var_t<float> rawMagX = lp_var_t<float>(sid.objectId, POS_Z_RAW_MAG_X, this);
    lp_var_t<float> rawMagY = lp_var_t<float>(sid.objectId, POS_Z_RAW_MAG_Y, this);
    lp_var_t<float> rawMagZ = lp_var_t<float>(sid.objectId, POS_Z_RAW_MAG_Z, this);
    lp_var_t<float> calMagX = lp_var_t<float>(sid.objectId, POS_Z_CAL_MAG_X, this);
    lp_var_t<float> calMagY = lp_var_t<float>(sid.objectId, POS_Z_CAL_MAG_Y, this);
    lp_var_t<float> calMagZ = lp_var_t<float>(sid.objectId, POS_Z_CAL_MAG_Z, this);
    lp_var_t<float> coilXCurrent = lp_var_t<float>(sid.objectId, POS_Z_COIL_X_CURRENT,
            this);
    lp_var_t<float> coilYCurrent = lp_var_t<float>(sid.objectId, POS_Z_COIL_Y_CURRENT,
            this);
    lp_var_t<float> coilZCurrent = lp_var_t<float>(sid.objectId, POS_Z_COIL_Z_CURRENT,
            this);
    lp_var_t<uint16_t> coilXTemperature = lp_var_t<uint16_t>(sid.objectId,
            POS_Z_COIL_X_TEMPERATURE, this);
    lp_var_t<uint16_t> coilYTemperature = lp_var_t<uint16_t>(sid.objectId,
            POS_Z_COIL_Y_TEMPERATURE, this);
    lp_var_t<uint16_t> coilZTemperature = lp_var_t<uint16_t>(sid.objectId,
            POS_Z_COIL_Z_TEMPERATURE, this);

    /** FINA block */
    lp_var_t<uint8_t> finaErr = lp_var_t<uint8_t>(sid.objectId, FINA_POS_Z_ERR, this);
    lp_var_t<float> finaRawMagX = lp_var_t<float>(sid.objectId, FINA_POS_Z_RAW_MAG_X, this);
    lp_var_t<float> finaRawMagY = lp_var_t<float>(sid.objectId, FINA_POS_Z_RAW_MAG_Y, this);
    lp_var_t<float> finaRawMagZ = lp_var_t<float>(sid.objectId, FINA_POS_Z_RAW_MAG_Z, this);
    lp_var_t<float> finaCalMagX = lp_var_t<float>(sid.objectId, FINA_POS_Z_CAL_MAG_X, this);
    lp_var_t<float> finaCalMagY = lp_var_t<float>(sid.objectId, FINA_POS_Z_CAL_MAG_Y, this);
    lp_var_t<float> finaCalMagZ = lp_var_t<float>(sid.objectId, FINA_POS_Z_CAL_MAG_Z, this);
    lp_var_t<float> finaCoilXCurrent = lp_var_t<float>(sid.objectId, FINA_POS_Z_COIL_X_CURRENT,
            this);
    lp_var_t<float> finaCoilYCurrent = lp_var_t<float>(sid.objectId, FINA_POS_Z_COIL_Y_CURRENT,
            this);
    lp_var_t<float> finaCoilZCurrent = lp_var_t<float>(sid.objectId, FINA_POS_Z_COIL_Z_CURRENT,
            this);
    lp_var_t<uint16_t> finaCoilXTemperature = lp_var_t<uint16_t>(sid.objectId,
            FINA_POS_Z_COIL_X_TEMPERATURE, this);
    lp_var_t<uint16_t> finaCoilYTemperature = lp_var_t<uint16_t>(sid.objectId,
            FINA_POS_Z_COIL_Y_TEMPERATURE, this);
    lp_var_t<uint16_t> finaCoilZTemperature = lp_var_t<uint16_t>(sid.objectId,
            FINA_POS_Z_COIL_Z_TEMPERATURE, this);
};

/**
 * @brief   This dataset can be used to store the self test results of the -Z self test.
 *
 * @details Units of measurements:
 *          Raw magnetic field: [nT]
 *          Calibrated magnetic field: [nT]
 *          Coil currents: [mA]
 *          Temperature: [�C]
 *          The -Z self test generates a negative dipole in z direction and measures the magnetic
 *          field with the built-in MTM. The procedure of the test is as follows:
 *          1. All coils off (INIT step)
 *          2. -Z actuation
 *          3. All coils off (FINA step)
 */
class NegZSelfTestSet: public StaticLocalDataSet<SELF_TEST_DATASET_ENTRIES> {
public:

    NegZSelfTestSet(HasLocalDataPoolIF* owner) :
            StaticLocalDataSet(owner, IMTQ::NEG_Z_TEST_DATASET) {
    }

    NegZSelfTestSet(object_id_t objectId) :
            StaticLocalDataSet(sid_t(objectId, IMTQ::NEG_Z_TEST_DATASET)) {
    }

    /** INIT block */
    lp_var_t<uint8_t> initErr = lp_var_t<uint8_t>(sid.objectId, INIT_NEG_Z_ERR, this);
    lp_var_t<float> initRawMagX = lp_var_t<float>(sid.objectId, INIT_NEG_Z_RAW_MAG_X, this);
    lp_var_t<float> initRawMagY = lp_var_t<float>(sid.objectId, INIT_NEG_Z_RAW_MAG_Y, this);
    lp_var_t<float> initRawMagZ = lp_var_t<float>(sid.objectId, INIT_NEG_Z_RAW_MAG_Z, this);
    lp_var_t<float> initCalMagX = lp_var_t<float>(sid.objectId, INIT_NEG_Z_CAL_MAG_X, this);
    lp_var_t<float> initCalMagY = lp_var_t<float>(sid.objectId, INIT_NEG_Z_CAL_MAG_Y, this);
    lp_var_t<float> initCalMagZ = lp_var_t<float>(sid.objectId, INIT_NEG_Z_CAL_MAG_Z, this);
    lp_var_t<float> initCoilXCurrent = lp_var_t<float>(sid.objectId, INIT_NEG_Z_COIL_X_CURRENT,
            this);
    lp_var_t<float> initCoilYCurrent = lp_var_t<float>(sid.objectId, INIT_NEG_Z_COIL_Y_CURRENT,
            this);
    lp_var_t<float> initCoilZCurrent = lp_var_t<float>(sid.objectId, INIT_NEG_Z_COIL_Z_CURRENT,
            this);
    lp_var_t<uint16_t> initCoilXTemperature = lp_var_t<uint16_t>(sid.objectId,
            INIT_NEG_Z_COIL_X_TEMPERATURE, this);
    lp_var_t<uint16_t> initCoilYTemperature = lp_var_t<uint16_t>(sid.objectId,
            INIT_NEG_Z_COIL_Y_TEMPERATURE, this);
    lp_var_t<uint16_t> initCoilZTemperature = lp_var_t<uint16_t>(sid.objectId,
            INIT_NEG_Z_COIL_Z_TEMPERATURE, this);

    /** +Z block */
    lp_var_t<uint8_t> err = lp_var_t<uint8_t>(sid.objectId, NEG_Z_ERR, this);
    lp_var_t<float> rawMagX = lp_var_t<float>(sid.objectId, NEG_Z_RAW_MAG_X, this);
    lp_var_t<float> rawMagY = lp_var_t<float>(sid.objectId, NEG_Z_RAW_MAG_Y, this);
    lp_var_t<float> rawMagZ = lp_var_t<float>(sid.objectId, NEG_Z_RAW_MAG_Z, this);
    lp_var_t<float> calMagX = lp_var_t<float>(sid.objectId, NEG_Z_CAL_MAG_X, this);
    lp_var_t<float> calMagY = lp_var_t<float>(sid.objectId, NEG_Z_CAL_MAG_Y, this);
    lp_var_t<float> calMagZ = lp_var_t<float>(sid.objectId, NEG_Z_CAL_MAG_Z, this);
    lp_var_t<float> coilXCurrent = lp_var_t<float>(sid.objectId, NEG_Z_COIL_X_CURRENT,
            this);
    lp_var_t<float> coilYCurrent = lp_var_t<float>(sid.objectId, NEG_Z_COIL_Y_CURRENT,
            this);
    lp_var_t<float> coilZCurrent = lp_var_t<float>(sid.objectId, NEG_Z_COIL_Z_CURRENT,
            this);
    lp_var_t<uint16_t> coilXTemperature = lp_var_t<uint16_t>(sid.objectId,
            NEG_Z_COIL_X_TEMPERATURE, this);
    lp_var_t<uint16_t> coilYTemperature = lp_var_t<uint16_t>(sid.objectId,
            NEG_Z_COIL_Y_TEMPERATURE, this);
    lp_var_t<uint16_t> coilZTemperature = lp_var_t<uint16_t>(sid.objectId,
            NEG_Z_COIL_Z_TEMPERATURE, this);

    /** FINA block */
    lp_var_t<uint8_t> finaErr = lp_var_t<uint8_t>(sid.objectId, FINA_NEG_Z_ERR, this);
    lp_var_t<float> finaRawMagX = lp_var_t<float>(sid.objectId, FINA_NEG_Z_RAW_MAG_X, this);
    lp_var_t<float> finaRawMagY = lp_var_t<float>(sid.objectId, FINA_NEG_Z_RAW_MAG_Y, this);
    lp_var_t<float> finaRawMagZ = lp_var_t<float>(sid.objectId, FINA_NEG_Z_RAW_MAG_Z, this);
    lp_var_t<float> finaCalMagX = lp_var_t<float>(sid.objectId, FINA_NEG_Z_CAL_MAG_X, this);
    lp_var_t<float> finaCalMagY = lp_var_t<float>(sid.objectId, FINA_NEG_Z_CAL_MAG_Y, this);
    lp_var_t<float> finaCalMagZ = lp_var_t<float>(sid.objectId, FINA_NEG_Z_CAL_MAG_Z, this);
    lp_var_t<float> finaCoilXCurrent = lp_var_t<float>(sid.objectId, FINA_NEG_Z_COIL_X_CURRENT,
            this);
    lp_var_t<float> finaCoilYCurrent = lp_var_t<float>(sid.objectId, FINA_NEG_Z_COIL_Y_CURRENT,
            this);
    lp_var_t<float> finaCoilZCurrent = lp_var_t<float>(sid.objectId, FINA_NEG_Z_COIL_Z_CURRENT,
            this);
    lp_var_t<uint16_t> finaCoilXTemperature = lp_var_t<uint16_t>(sid.objectId,
            FINA_NEG_Z_COIL_X_TEMPERATURE, this);
    lp_var_t<uint16_t> finaCoilYTemperature = lp_var_t<uint16_t>(sid.objectId,
            FINA_NEG_Z_COIL_Y_TEMPERATURE, this);
    lp_var_t<uint16_t> finaCoilZTemperature = lp_var_t<uint16_t>(sid.objectId,
            FINA_NEG_Z_COIL_Z_TEMPERATURE, this);
};

}


#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_IMTQDEFINITIONS_H_ */