/*
 * @Date: 2025-07-22 10:34:30
 * @Author: mypx
 * @LastEditors: mypx mypx_coder@163.com
 * @LastEditTime: 2025-09-22 12:43:39
 * @FilePath: h31_comm_related_var.c
 * @Description: SV630P H31 communication related parameters interface implementation
 * Copyright (c) 2025 by mypx, All Rights Reserved.
 */
#include "h31_comm_related_var.h"
#include "etk_byte_conv.h"

// H31.00: Communication given VDI virtual level
int sv630p_h31_00_write_vdi_virtual_level(sv630p_handle_t *dev, uint16_t value)
{
    SV630P_ARGS_CHECK(dev);
    return dev->ops->write_single_reg(dev, REG_H31_00_VDI_LEVEL, value);
}

int sv630p_h31_00_read_vdi_virtual_level(sv630p_handle_t *dev, uint16_t *value)
{
    uint16_t reg_val;
    SV630P_ARGS_CHECK(dev);

    if (dev->ops->read_holding_regs(dev, REG_H31_00_VDI_LEVEL, 1, &reg_val) == SV630P_OK)
    {
        *value = reg_val;
        return SV630P_OK;
    }
    return SV630P_BUS_ERR;
}

// H31.04: Communication given DO output status
int sv630p_h31_04_write_do_output_status(sv630p_handle_t *dev, uint16_t value)
{
    SV630P_ARGS_CHECK(dev);
    return dev->ops->write_single_reg(dev, REG_H31_04_DO_STATUS, value);
}

int sv630p_h31_04_read_do_output_status(sv630p_handle_t *dev, uint16_t *value)
{
    uint16_t reg_val;
    SV630P_ARGS_CHECK(dev);
    if (dev->ops->read_holding_regs(dev, REG_H31_04_DO_STATUS, 1, &reg_val) == SV630P_OK)
    {
        *value = reg_val;
        return SV630P_OK;
    }
    return SV630P_BUS_ERR;
}

// H31.09: Communication given speed command
// Range: -9000000rpm ~ 9000000rpm
// Parameter Description: In speed control mode, when the speed command source is communication input,
// this parameter sets the speed command value with a resolution of 0.001rpm.
// H31.09 is a 32-bit function code that is not visible on the panel and can only be set via communication.

int sv630p_h31_09_write_speed_command(sv630p_handle_t *dev, double rpm)
{
    SV630P_ARGS_CHECK(dev);
    uint16_t data[2];
    int32_t value = rpm * 1000; // Convert to 0.001rpm unit
    if (value < H31_09_SPEED_CMD_MIN || value > H31_09_SPEED_CMD_MAX)
    {
        return SV630P_PARAM_ERR;
    }
    et_int32_to_array(value, (uint8_t *)data);
    return dev->ops->write_multiple_regs(dev, REG_H31_09_SPEED_CMD, 2, data);
}

int sv630p_h31_09_read_speed_command(sv630p_handle_t *dev, double *rpm)
{
    uint16_t data[2];
    int32_t value;
    SV630P_ARGS_CHECK(dev);
    if (dev->ops->read_holding_regs(dev, REG_H31_09_SPEED_CMD, 2, data) == SV630P_OK)
    {
        value = et_array_to_int32((uint8_t *)data);
        *rpm = (double)value / 1000.0; // Convert from 0.001rpm to rpm
        return SV630P_OK;
    }
    return SV630P_BUS_ERR;
}

// H31.11: Communication given torque command
int sv630p_h31_11_write_torque_command(sv630p_handle_t *dev, int32_t value)
{
    SV630P_ARGS_CHECK(dev);
    uint16_t data[2];
    if (value < H31_11_TORQUE_CMD_MIN || value > H31_11_TORQUE_CMD_MAX)
    {
        return SV630P_PARAM_ERR;
    }
    et_int32_to_array(value, (uint8_t *)data);
    return dev->ops->write_multiple_regs(dev, REG_H31_11_TORQUE_CMD, 2, data);
}

int sv630p_h31_11_read_torque_command(sv630p_handle_t *dev, int32_t *value)
{
    uint16_t data[2];
    SV630P_ARGS_CHECK(dev);
    if (dev->ops->read_holding_regs(dev, REG_H31_11_TORQUE_CMD, 1, data) == SV630P_OK)
    {
        *value = et_array_to_int32((uint8_t *)data);
        return SV630P_OK;
    }
    return SV630P_BUS_ERR;
}
