/*
 * FreeModbus Libary: BARE Port
 * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * File: $Id: port.h ,v 1.60 2013/08/13 15:07:05 Armink add Master Functions $
 *            port.h ,v 1.60 2022/07/17          quanghona <lyhonquang@gmail.com> CMSIS-RTOS2 port $
 */

#ifndef _PORT_H
#define _PORT_H

#include "mbconfig.h"

#include <assert.h>
#include <inttypes.h>
#include "main.h"
#include "cmsis_os2.h"

#define INLINE
#define PR_BEGIN_EXTERN_C           extern "C" {
#define PR_END_EXTERN_C             }

#define ENTER_CRITICAL_SECTION()    EnterCriticalSection()
#define EXIT_CRITICAL_SECTION()    ExitCriticalSection()


typedef uint8_t BOOL;

typedef unsigned char UCHAR;
typedef char CHAR;

typedef uint16_t USHORT;
typedef int16_t SHORT;

typedef uint32_t ULONG;
typedef int32_t LONG;

#ifndef TRUE
#define TRUE            1
#endif

#ifndef FALSE
#define FALSE           0
#endif

#define MB_SER_PDU_SIZE_MAX     256     /*!< Maximum size of a Modbus RTU frame. */
/* ----------------------- Type definitions ---------------------------------*/
typedef enum {
    STATE_RX_INIT,              /*!< Receiver is in initial state. */
    STATE_RX_IDLE,              /*!< Receiver is in idle state. */
    STATE_RX_RCV,               /*!< Frame is beeing received. */
    STATE_RX_ERROR              /*!< If the frame is invalid. */
} eMBRcvState;

typedef enum {
    STATE_TX_IDLE,              /*!< Transmitter is in idle state. */
    STATE_TX_XMIT               /*!< Transmitter is in transfer state. */
} eMBSndState;
/*! \ingroup modbus
 * \brief Errorcodes used by all function in the protocol stack.
 */
typedef enum {
    MB_ENOERR,                  /*!< no error. */
    MB_ENOREG,                  /*!< illegal register address. */
    MB_EINVAL,                  /*!< illegal argument. */
    MB_EPORTERR,                /*!< porting layer error. */
    MB_ENORES,                  /*!< insufficient resources. */
    MB_EIO,                     /*!< I/O error. */
    MB_EILLSTATE,               /*!< protocol stack in illegal state. */
    MB_ETIMEDOUT                /*!< timeout error occurred. */
} eMBErrorCode;

/*! \ingroup modbus
 * \brief If register should be written or read.
 *
 * This value is passed to the callback functions which support either
 * reading or writing register values. Writing means that the application
 * registers should be updated and reading means that the modbus protocol
 * stack needs to know the current register values.
 *
 * \see eMBRegHoldingCB( ), eMBRegCoilsCB( ), eMBRegDiscreteCB( ) and
 *   eMBRegInputCB( ).
 */
typedef enum {
    MB_REG_READ,                /*!< Read register values and pass to protocol stack. */
    MB_REG_WRITE                /*!< Update register values. */
} eMBRegisterMode;

typedef eMBErrorCode    (*eMBRegInputCB)(UCHAR *pucRegBuffer, USHORT usAddress,
                                         USHORT usNRegs);

typedef eMBErrorCode (*eMBRegHoldingCB)(UCHAR *pucRegBuffer, USHORT usAddress,
                                        USHORT usNRegs, eMBRegisterMode eMode);

typedef eMBErrorCode (*eMBRegCoilsCB)(UCHAR *pucRegBuffer, USHORT usAddress,
                                      USHORT usNCoils, eMBRegisterMode eMode);

typedef eMBErrorCode (*eMBRegDiscreteCB)(UCHAR *pucRegBuffer, USHORT usAddress,
                                         USHORT usNDiscrete);

typedef eMBErrorCode (*eMBWriteFileCB)(UCHAR *header, UCHAR *pucRegBuffer, USHORT *usLen);

typedef eMBErrorCode (*eMBWriteDeviceSerialCB)(UCHAR *header, UCHAR *pucRegBuffer, USHORT *usLen);

/**
 * 定义寄存器操作回调函数结构体
 */
typedef struct {
    eMBRegInputCB eMbRegInputCb;
    eMBRegHoldingCB eMbRegHoldingCb;
    eMBRegDiscreteCB eMbRegDiscreteCb;
    eMBWriteFileCB eMbWriteFileCb;
    eMBRegCoilsCB eMbRegCoilsCb;
    eMBWriteDeviceSerialCB eMBWriteDeviceSerialCB;
} mb_reg_callback_t;
/**
 * 定义从站对象，用于支持多个从站
 */
typedef struct {
    /**
     * 协议类型
     */
    uint8_t eMode;
    /**
     * 从站地址
     */
    uint8_t ucSlaveAddress;
    /**
     * 波特率
     */
    uint32_t ulBaudRate;
    /**
     * 校验位
     */
    uint8_t eParity;
    /**
     * UART句柄
     */
    UART_HandleTypeDef pUartHandle;
    /**
     * TIM句柄
     */
    TIM_HandleTypeDef pTimHandle;
    /**
     * 事件标志ID
     */
    osEventFlagsId_t xEventFlagsId;
    /**
     * 发送、接收使能IO端口
     */
    GPIO_TypeDef *enPort;
    /**
     * 发送、接收使能IO引脚
     */
    uint16_t enPin;
    volatile eMBSndState eSndState;
    volatile eMBRcvState eRcvState;

    volatile UCHAR ucRTUBuf[MB_SER_PDU_SIZE_MAX];
    volatile UCHAR *pucSndBufferCur;
    volatile USHORT usSndBufferCount;
    volatile USHORT usRcvBufferPos;
    mb_reg_callback_t *callback;
    UCHAR *ucMBFrame;
    UCHAR id;
    USHORT usLength;
} eMBRTUSlaveObj;


void EnterCriticalSection(void);

void ExitCriticalSection(void);

void prvvMBMasterUARTTxReadyISR(void);

void prvvMBMasterUARTRxISR(void);

void prvvMBMasterUARTRxReceiveCharISR(CHAR data);

void prvvUARTTxReadyISR(eMBRTUSlaveObj *pObj);

void prvvUARTRxISR(eMBRTUSlaveObj *pObj);

void prvvUARTRxReceiveCharISR(CHAR data);

#endif
