/*
 * @Author: mypx
 * @Date: 2025-09-18 09:52:47
 * @LastEditTime: 2025-09-26 13:22:46
 * @LastEditors: mypx mypx_coder@163.com
 * @Description: 
 */
#include "mb_interface.h"
#include "et_log.h"
#include "etk_byte_conv.h"
#include "mb_command.h"
#include "user_config.h"
#include <string.h>

/**
 * @brief Initialize Modbus interface module
 *        初始化Modbus接口模块
 */
void mb_interface_init(void)
{
    mb_command_t *mb = get_command_instance();
    if (mb)
    {
        // Clear history data in the protocol cache
        if (mb->input_lock != RT_NULL)
            rt_mutex_take(mb->input_lock, RT_WAITING_FOREVER);
        memset(&mb->input_regs[0], 0, sizeof(mb->input_regs));
        /* set device model and firmware version
         * - Device model: pack up to 4 ASCII chars from PM_DEVICE_MODE into two 16-bit registers.
         *   Each register stores two bytes: high byte = char[i], low byte = char[i+1].
         * - Firmware version: pack major/minor into INPUT_REG_FW_VERSION_H (major in high byte,
         *   minor in low byte). Pack rev/build into INPUT_REG_FW_VERSION_L similarly.
         */
        {
            const char *m     = PM_DEVICE_MODE;
            uint16_t    dm_hi = 0, dm_lo = 0;
            uint8_t     c0                           = (m[0] != '\0') ? (uint8_t)m[0] : 0;
            uint8_t     c1                           = (m[1] != '\0') ? (uint8_t)m[1] : 0;
            uint8_t     c2                           = (m[2] != '\0') ? (uint8_t)m[2] : 0;
            uint8_t     c3                           = (m[3] != '\0') ? (uint8_t)m[3] : 0;
            dm_hi                                    = (uint16_t)((c0 << 8) | c1);
            dm_lo                                    = (uint16_t)((c2 << 8) | c3);
            mb->input_regs[INPUT_REG_DEVICE_MODEL_H] = dm_hi;
            mb->input_regs[INPUT_REG_DEVICE_MODEL_L] = dm_lo;

            uint16_t fw_hi                         = (uint16_t)(((uint16_t)(PM_DEVICE_VER_MAJOR & 0xFF) << 8)
                                        | (uint16_t)(PM_DEVICE_VER_MINOR & 0xFF));
            uint16_t fw_lo                         = (uint16_t)(((uint16_t)(PM_DEVICE_VER_REV & 0xFF) << 8)
                                        | (uint16_t)(PM_DEVICE_VER_BUILD & 0xFF));
            mb->input_regs[INPUT_REG_FW_VERSION_H] = fw_hi;
            mb->input_regs[INPUT_REG_FW_VERSION_L] = fw_lo;
        }
        if (mb->input_lock != RT_NULL)
            rt_mutex_release(mb->input_lock);
    }

    ET_INFO("Modbus interface initialized successfully");
}

/**
 * @brief Write current temperature data
 *        写入当前温度数据
 * 
 * @param temp Temperature value to write (°C)
 */
void mb_write_current_temp(float temp)
{
    // Check temperature alarm conditions
    if (temp > 100.0f || temp < -10.0f)
    {
        mb_sync_exception_reg(PM_EXCEPTION_TEMPERATURE, true);
        ET_WARN("Temperature out of range: %.2f°C", temp);
    }
    else
    {
        mb_sync_exception_reg(PM_EXCEPTION_TEMPERATURE, false);
    }
    mb_sync_realtime_temp(temp);
}

/**
 * @brief Write current rotation data
 *        写入当前旋光度数据
 * 
 * @param rotation Rotation value to write (°)
 */
void mb_write_current_rotation(float rotation)
{
    // Update protocol cache via sync helper (which converts and writes under lock)
    mb_sync_realtime_rotation(rotation);
}

/**
 * @brief Write measurement result
 *        写入测量结果
 * 
 * @param mode Measurement mode (0-3)
 * @param value Measurement value
 * @param temp Temperature at measurement time (°C)
 */
void mb_write_measurement_result(uint8_t mode, float value, float temp)
{
    // Update protocol cache via sync helper (atomic under lock)
    mb_sync_result(mode, value, temp);
    // mark measurement complete in running state
    //mb_sync_running_state(PM_READY_STATE);
    // Save to history (writes into protocol cache directly)
    mb_save_to_history(value, temp);
    ET_INFO("Measurement result updated: mode=%d, value=%.4f, temp=%.2f\u00b0C", mode, value, temp);
}

/**
 * @brief Get current target temperature
 *        获取当前目标温度设置
 * 
 * @return Target temperature value (°C)
 */
float mb_get_target_temp(void)
{
    mb_command_t *mb = get_command_instance();
    if (!mb)
        return 0.0f;
    // target temp is held in holding regs (regs array) at HOLD_REG_TARGET_TEMP_H/L
    uint16_t h = mb->regs[HOLD_REG_TARGET_TEMP_H];
    uint16_t l = mb->regs[HOLD_REG_TARGET_TEMP_L];
    return et_mb_to_float_abcd(h, l);
}

/**
 * @brief Get current tube length setting
 *        获取当前旋光管长度设置
 * 
 * @return Tube length value (mm)
 */
float mb_get_tube_length(void)
{
    mb_command_t *mb = get_command_instance();
    if (!mb)
        return 0.0f;
    uint16_t h = mb->regs[HOLD_REG_TUBE_LEN];

    return h;
}

/**
 * @brief Get current measurement mode
 *        获取当前测量模式
 * 
 * @return Measurement mode code (0-3)
 */
uint8_t mb_get_measure_mode(void)
{
    mb_command_t *mb = get_command_instance();
    if (!mb)
        return 0;
    return (uint8_t)(mb->regs[HOLD_REG_MEAS_MODE] & 0xFF);
}

/**
 * @brief Get current auto measurement count
 *        获取当前自动测量次数设置
 * 
 * @return Auto measurement count (1-255)
 */
uint8_t mb_get_auto_measure_count(void)
{
    mb_command_t *mb = get_command_instance();
    if (!mb)
        return 0;
    return (uint8_t)(mb->regs[HOLD_REG_AUTO_MEAS_CNT] & 0xFF);
}

/**
 * @brief Get current running state
 *        获取当前运行状态
 * 
 * @return Running state code
 */
PmRunningState mb_get_running_state(void)
{
    mb_command_t *mb = get_command_instance();
    if (!mb)
        return PM_READY_STATE;
    return (PmRunningState)(mb->input_regs[INPUT_REG_DEV_RUNNING_STATE] & 0xFF);
}

/**
 * @brief Check if measurement is complete
 *        检查测量是否完成
 * 
 * @return 1 if complete, 0 otherwise
 */
uint8_t mb_is_measure_complete(void)
{
    mb_command_t *mb = get_command_instance();
    if (!mb)
        return 0;
    return (uint8_t)(mb->input_regs[INPUT_REG_MEAS_DONE_FLAG] & 0xFF);
}
