//
// Created by DELL on 2024/10/18.
//

#include "modbus_slave.h"
#include "port.h"
#include "mb.h"
#include "cmsis_os2.h"

extern uint8_t error_count;

USHORT usSRegHoldStart = S_REG_HOLDING_START;
static USHORT usSRegHoldBuf[S_REG_HOLDING_NREGS];
const static osThreadAttr_t task_attributes = {
        .name = "slave_485_task",
        .stack_size = 128 * 4,
        .priority = (osPriority_t) osPriorityHigh,
};

/**
 * 输入型寄存器读写回调函数
 * @param pucRegBuffer
 * @param usAddress
 * @param usNRegs
 * @return
 */
eMBErrorCode eMBRegInputCB(UCHAR *pucRegBuffer, USHORT usAddress, USHORT usNRegs)
{
    return MB_ENOERR;
}

/**
 * 保持型寄存器读写回调函数
 * @param pucRegBuffer
 * @param usAddress
 * @param usNRegs
 * @param eMode
 * @return
 */
eMBErrorCode eMBRegHoldingCB(UCHAR *pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode)
{
    eMBErrorCode eStatus = MB_ENOERR;
    USHORT iRegIndex;
    USHORT *pusRegHoldingBuf;
    USHORT REG_HOLDING_START;
    USHORT REG_HOLDING_NREGS;
    USHORT usRegHoldStart;
    pusRegHoldingBuf = usSRegHoldBuf;
    REG_HOLDING_START = S_REG_HOLDING_START;
    REG_HOLDING_NREGS = S_REG_HOLDING_NREGS;
    usRegHoldStart = usSRegHoldStart;

    /* it already plus one in modbus function method. */
    usAddress--;

    if ((usAddress >= REG_HOLDING_START)
        && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS))
    {
        iRegIndex = usAddress - usRegHoldStart;
        switch (eMode)
        {
            /* read current register values from the protocol stack. */
            case MB_REG_READ:
                while (usNRegs > 0)
                {
                    *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8);
                    *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF);
                    iRegIndex++;
                    usNRegs--;
                }
                break;

                /* write current register values with new values from the protocol stack. */
            case MB_REG_WRITE:
                while (usNRegs > 0)
                {

                    pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
                    pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
                    iRegIndex++;
                    usNRegs--;
                }
                break;
        }
    } else
    {
        eStatus = MB_ENOREG;
    }
    return eStatus;
}

uint16_t get_reg_value(uint16_t addr)
{
    if (addr >= S_REG_HOLDING_NREGS)
    {
        return 0;
    }
    return usSRegHoldBuf[addr];
}

void set_reg_value(uint16_t addr, uint16_t value)
{
    if (addr >= S_REG_HOLDING_NREGS)
    {
        return;
    }
    usSRegHoldBuf[addr] = value;
}

/**
 * 从机任务
 * @param pv
 */
_Noreturn static void slave_485_task(void *pv)
{
    eMBErrorCode code;
    uint8_t slave_addr = (uint8_t) pv;
    uint8_t led_count = 0;
    uint16_t reg_value;
    eMBInit(MB_RTU, slave_addr, 3, 9600, MB_PAR_NONE);
    eMBEnable();
    for (;;)
    {
        eMBPoll();
        if ((led_count > 10) && (get_reg_value(INNER_ERROR2_REG_ADDRESS) || get_reg_value(INNER_ERROR1_REG_ADDRESS)))
        {
            reg_value ++;
            if (reg_value > 20)
            {
                HAL_GPIO_TogglePin(LED_ERROR_GPIO_Port, LED_ERROR_Pin);
//                HAL_GPIO_WritePin(LED_ERROR_GPIO_Port, LED_ERROR_Pin, GPIO_PIN_RESET);
            }
        } else
        {
            HAL_GPIO_WritePin(LED_ERROR_GPIO_Port, LED_ERROR_Pin, GPIO_PIN_SET);
            reg_value = 0;
        }
        led_count++;
        osDelay(5);
    }
}

void start_485_slave(uint8_t address)//启动485从机
{
    osThreadNew(slave_485_task, (void *) address, &task_attributes);
}

