/**
 * @file modbus_data.c
 * @brief Стандартная библиотека контроллера "Сатурн-PLC".
 * Функции преобразования типов для Modbus.
 * @version 0.1
 * @date 2024-04-02
 * 
 * @copyright Copyright (C) 2024, ООО "МНПП Сатурн"
 */
#include "sys.h"
#include "modbus.h"


struct abcd {
        uint8_t a;
        uint8_t b;
        uint8_t c;
        uint8_t d;
    };

union modbus_float_u {
    float f;
	  struct abcd v;
    //

};

/**
 * @brief Преобразование значения 2-х последовательных регистров Modbus (4 байта) в значение float
 * без преобразования (ABCD)
 * @param src Указатель на первый регистр
 * @return float 
 */
float ModbusGetFloatABCD(const uint16_t *src) {
    uint8_t *in = (uint8_t *) src;
    union modbus_float_u mf;
    //
    mf.v.a = in[0];
    mf.v.b = in[1];
    mf.v.c = in[2];
    mf.v.d = in[3];
    //
    return mf.f;
}

/**
 * @brief Преобразование значения 2-х последовательных регистров Modbus (4 байта) в значение float
 * в обратном порядке (DCBA)
 * @param src Указатель на первый регистр
 * @return float 
 */
float ModbusGetFloatDCBA(const uint16_t *src) {
    uint8_t *in = (uint8_t *) src;
    union modbus_float_u mf;
    //
    mf.v.d = in[0];
    mf.v.c = in[1];
    mf.v.b = in[2];
    mf.v.a = in[3];
    //
    return mf.f;
}

/**
 * @brief Преобразование значения 2-х последовательных регистров Modbus (4 байта) в значение float
 * с изменённым порядком байт в регистрах (BADC)
 * @param src 
 * @return float 
 */
float ModbusGetFloatBADC(const uint16_t *src) {
    uint8_t *in = (uint8_t *) src;
    union modbus_float_u mf;
    //
    mf.v.b = in[0];
    mf.v.a = in[1];
    mf.v.d = in[2];
    mf.v.c = in[3];
    //
    return mf.f;
}

/**
 * @brief Преобразование значения 2-х последовательных регистров Modbus (4 байта) в значение float
 * с изменённым порядком регистров (CDAB)
 * @param src 
 * @return float 
 */
float ModbusGetFloatCDAB(const uint16_t *src) {
    uint8_t *in = (uint8_t *) src;
    union modbus_float_u mf;
    //
    mf.v.c = in[0];
    mf.v.d = in[1];
    mf.v.a = in[2];
    mf.v.b = in[3];
    //
    return mf.f;
}

/**
 * @brief Преобразование значения float в два последовательных регистра Modbus (4 байта)
 * без изменения порядка (ABCD)
 * @param f 
 * @param dest 
 */
void ModbusSetFloatABCD(float f, uint16_t *dest) {
    uint8_t *out = (uint8_t *) dest;
    union modbus_float_u mf;
    mf.f = f;
    //
    out[0] = mf.v.a;
    out[1] = mf.v.b;
    out[2] = mf.v.c;
    out[3] = mf.v.d;
}

/**
 * @brief Преобразование значения float в два последовательных регистра Modbus (4 байта)
 * в обратном порядке (DCBA)
 * @param f 
 * @param dest 
 */
void ModbusSetFloatDCBA(float f, uint16_t *dest) {
    uint8_t *out = (uint8_t *) dest;
    union modbus_float_u mf;
    mf.f = f;
    //
    out[0] = mf.v.d;
    out[1] = mf.v.c;
    out[2] = mf.v.b;
    out[3] = mf.v.a;
}

/**
 * @brief Преобразование значения float в два последовательных регистра Modbus (4 байта)
 * с изменённым порядком байт в регистрах (BADC)
 * @param f 
 * @param dest 
 */
void ModbusSetFloatBADC(float f, uint16_t *dest) {
    uint8_t *out = (uint8_t *) dest;
    union modbus_float_u mf;
    mf.f = f;
    //
    out[0] = mf.v.b;
    out[1] = mf.v.a;
    out[2] = mf.v.d;
    out[3] = mf.v.c;
}

/**
 * @brief Преобразование значения float в два последовательных регистра Modbus (4 байта)
 * с изменённым порядком регистров (CDAB)
 * @param f 
 * @param dest 
 */
void ModbusSetFloatCDAB(float f, uint16_t *dest) {
    uint8_t *out = (uint8_t *) dest;
    union modbus_float_u mf;
    mf.f = f;
    //
    out[0] = mf.v.c;
    out[1] = mf.v.d;
    out[2] = mf.v.a;
    out[3] = mf.v.b;
}
