#ifndef _M_MODBUS_H_
#define _M_MODBUS_H_


/*
  Author:     Nima Askari
  WebSite:    http://www.github.com/NimaLTD
  Instagram:  http://instagram.com/github.NimaLTD
  Youtube:    https://www.youtube.com/channel/UCUhY7qY1klJm1d2kulr9ckw
  
  Version:    1.3.2
  
  Reversion History:
  
  (1.3.2)
  Speedup receiver, add write multiple holding
    
  (1.3.1)
  Remove delay in sending function when DMA is disabled
  
  (1.3.0)
  Add 16 bit order
  
  (1.2.1)
  bug fixed.
  
  (1.2.0)
  add read 32bit register order.
  
  (1.1.2)
  fix read holding register.
  
  (1.1.1)
  fix functions name.
  
  (1.1.0)
  add 16bit,32bit,float read.
  
  (1.0.1)
  add delay in receive routin.
  
  (1.0.0)
  First release.
*/ 

#include "gd32f30x.h"
#include  "mmodbusConfig.h"
//#include  "usart.h"
#include  <stdbool.h>
#include  <string.h>
#include  <stdio.h>
#include  <stdint.h>
#include "FreeRTOS.h"
#include "task.h"
#define   mmodbus_delay(x) 	delay_ms(x)


/*
功能码
MModbusCMD_ReadCoilStatus（读线圈状态）：用于读取一个或多个逻辑线圈的状态。
MModbusCMD_ReadDiscreteInputs（读离散输入状态）：用于读取一个或多个数字输入信号的状态。
MModbusCMD_ReadHoldingRegisters（读保持寄存器）：用于读取一个或多个保持寄存器的值。
MModbusCMD_ReadInputRegisters（读输入寄存器）：用于读取一个或多个输入寄存器的值。
MModbusCMD_WriteSingleCoil（写单个线圈）：用于控制单个逻辑线圈的状态。
MModbusCMD_WriteSingleRegister（写单个保持寄存器）：用于写入单个保持寄存器的值。
MModbusCMD_WriteMultipleCoils（写多个线圈）：用于控制多个逻辑线圈的状态。
MModbusCMD_WriteMultipleRegisters（写多个保持寄存器）：用于写入多个保持寄存器的值。
*/
typedef enum
{
  MModbusCMD_ReadCoilStatus = 1,
  MModbusCMD_ReadDiscreteInputs = 2,
  MModbusCMD_ReadHoldingRegisters = 3,
  MModbusCMD_ReadInputRegisters = 4,
  MModbusCMD_WriteSingleCoil = 5,
  MModbusCMD_WriteSingleRegister = 6,
  MModbusCMD_WriteMultipleCoils = 15,
  MModbusCMD_WriteMultipleRegisters = 16
  
}MModbusCMD_t;

//大小端
typedef enum
{
  MModBus_16bitOrder_AB=1,
  MModBus_16bitOrder_BA=2,
  
}MModBus_16bitOrder_t;

typedef enum
{
  MModBus_32bitOrder_ABCD = 0,
  MModBus_32bitOrder_DCBA,
  MModBus_32bitOrder_BADC,
  MModBus_32bitOrder_CDAB,  
  
}MModBus_32bitOrder_t;

/*
	rxIndex：接收缓冲区的当前接收位置。
	rxBuf：接收缓冲区。
	rxTime：最近一次接收数据的时间戳。
	txBusy：发送是否忙碌的标志位。
	timeout：超时时间。
	byteOrder16：16 位数据的字节序（即高位字节在前还是低位字节在前）。
	byteOrder32：32 位数据的字节序。
	done：数据是否接收完成的标志位。
	txDmaDone：DMA 发送是否完成的标志位（该成员只在使用 DMA 发送时有效）。
*/
typedef struct
{
  uint16_t              rxIndex;  
  uint8_t               rxBuf[_MMODBUS_RXSIZE];
  uint32_t              rxTime;
  uint8_t               txBusy;
  uint32_t              timeout; 
  MModBus_16bitOrder_t  byteOrder16;
  MModBus_32bitOrder_t  byteOrder32;
	uint8_t								done;
  #if (_MMODBUS_TXDMA == 1)
  uint8_t             txDmaDone;
  #endif  
  
}MModBus_t;

//##################################################################################################

void    mmodbus_callback(void);
bool    mmodbus_sendRaw(uint8_t *data, uint16_t size, uint32_t timeout);
uint16_t mmodbus_crc16(const uint8_t *nData, uint16_t wLength); 
void    mmodbus_callback_txDMA(void);

bool    mmodbus_init(uint32_t setTimeout);
void    mmodbus_set16bitOrder(MModBus_16bitOrder_t MModBus_16bitOrder_);
void    mmodbus_set32bitOrder(MModBus_32bitOrder_t MModBus_32bitOrder_);
//  coils numbers 00001 to 09999
bool    mmodbus_readCoil(uint8_t slaveAddress, uint16_t number, uint8_t *data);
bool    mmodbus_readCoils(uint8_t slaveAddress, uint16_t startnumber, uint16_t length, uint8_t *data);
//  discrete input 10001 to 19999
bool    mmodbus_readDiscreteInput(uint8_t slaveAddress, uint16_t number, uint8_t *data);
bool    mmodbus_readDiscreteInputs(uint8_t slaveAddress, uint16_t startnumber, uint16_t length, uint8_t *data);
//  input register 30001 to 39999
bool    mmodbus_readInputRegister32f(uint8_t slaveAddress, uint16_t number, float *data);
bool    mmodbus_readInputRegisters32f(uint8_t slaveAddress, uint16_t startnumber, uint16_t length, float *data);
bool    mmodbus_readInputRegister32i(uint8_t slaveAddress, uint16_t number, uint32_t *data);
bool    mmodbus_readInputRegisters32i(uint8_t slaveAddress, uint16_t startnumber, uint16_t length, uint32_t *data);
bool    mmodbus_readInputRegister16i(uint8_t slaveAddress, uint16_t number, uint16_t *data);
bool    mmodbus_readInputRegisters16i(uint8_t slaveAddress, uint16_t startnumber, uint16_t length, uint16_t *data);
//  holding register 40001 to 49999
bool    mmodbus_readHoldingRegister32f(uint8_t slaveAddress, uint16_t number, float *data);
bool    mmodbus_readHoldingRegisters32f(uint8_t slaveAddress, uint16_t startnumber, uint16_t length, float *data);
bool    mmodbus_readHoldingRegister32i(uint8_t slaveAddress, uint16_t number, uint32_t *data);
bool    mmodbus_readHoldingRegisters32i(uint8_t slaveAddress, uint16_t startnumber, uint16_t length, uint32_t *data);
bool    mmodbus_readHoldingRegister16i(uint8_t slaveAddress, uint16_t number, uint16_t *data);
bool    mmodbus_readHoldingRegisters16i(uint8_t slaveAddress, uint16_t startnumber, uint16_t length, uint16_t *data);
// coils numbers 00001 to 09999
bool    mmodbus_writeCoil(uint8_t slaveAddress, uint16_t number, uint8_t data);
//  holding register 40001 to 49999
bool    mmodbus_writeHoldingRegister16i(uint8_t slaveAddress, uint16_t number, uint16_t data);
bool    mmodbus_writeHoldingRegisters16i(uint8_t slaveAddress, uint16_t startnumber, uint16_t length, uint16_t *data);
uint16_t mmodbus_crc16(const uint8_t *nData, uint16_t wLength);

//##################################################################################################
#endif
