/**
* @file MODBUS_S_LOW_ATY.c
*
* @param Project DEVICE_GENERAL_ATY_LIB
*
* @author ATY
*
* @copyright
* - Copyright 2017 - 2023 MZ-ATY
* - This code follows:
* - MZ-ATY Various Contents Joint Statement -
*
* https://mengze.top/MZ-ATY_VCJS
* - CC 4.0 BY-NC-SA -
*
* https://creativecommons.org/licenses/by-nc-sa/4.0/
* - Your use will be deemed to have accepted the terms of this statement.
*
* @brief Familiar functions of modbus for all device
*
* @note 4 byte per reg, save float or uint32
*
* @version
* - 1_01_221029 > ATY
* -# Preliminary version, first Release
* - 1_02_240120 > ATY
* -# add multy addr and channel
* -# add lock
********************************************************************************
*/
#ifndef __MODBUS_S_LOW_ATY_C
#define __MODBUS_S_LOW_ATY_C
#include "MODBUS_S_LOW_ATY.h"
/******************************* For user *************************************/
/******************************************************************************/
/**
* @brief modbus process
* @param buf
* @param len
* @param dev
* @return uint8_t
* @note only make 03/06/10 function code, others will return err 01
*/
uint8_t Modbus_Process(uint8_t* buf, uint8_t len, struct MODBUS_S_LOW_ATY_Dev* dev)
{
uint8_t sendBuf[(MODBUS_REG_HOLDING_SIZE * 2) + 4] = {0x00};
uint16_t sendBufSize = 4;
__ATY_LOCK(dev);
sendBuf[0] = buf[0];
sendBuf[1] = buf[1];
if(buf[0] == dev->addr){ // check addr
if(len < 4){ // check buf min size
sendBuf[1] = buf[1] + 0x80;
sendBuf[2] = 0x02;
sendBufSize = 6;
}
else if(CheckCrc16Modbus(buf, len)){ // check crc
sendBuf[1] = buf[1] + 0x80;
sendBuf[2] = 0x08;
sendBufSize = 6;
}
else{
switch(buf[1]) // check function code
{
// case MODBUS_FUNC_READ_COILS:{break; }
// case MODBUS_FUNC_READ_DISCRETE_INPUTS:{break; }
case MODBUS_FUNC_READ_HOLDING_REGISTERS:{
uint16_t i = 0, startAddr = 0, regCount = 0;
startAddr = ((buf[2] << 8) + buf[3]);
regCount = ((buf[4] << 8) + buf[5]);
if(startAddr + regCount - 1 > MODBUS_REG_HOLDING_SIZE){
sendBuf[1] = buf[1] + 0x80;
sendBuf[2] = 0x02;
sendBufSize = 6;
break;
}
sendBuf[2] = regCount * 2;
sendBufSize += 1;
for(i = 0; i < regCount; i++){
if(dev->bigEndian){
sendBuf[2 + (i * 2) + 1] = dev->mbRegs[startAddr + i];
sendBuf[2 + (i * 2) + 2] = dev->mbRegs[startAddr + i] >> 8;
}
else{
sendBuf[2 + (i * 2) + 1] = dev->mbRegs[startAddr + i] >> 8;
sendBuf[2 + (i * 2) + 2] = dev->mbRegs[startAddr + i];
}
sendBufSize += 2;
}
break;
}
// case MODBUS_FUNC_READ_INPUT_REGISTERS:{break; }
// case MODBUS_FUNC_WRITE_SINGLE_COIL:{break; }
case MODBUS_FUNC_WRITE_SINGLE_HOLDING_REGISTERS:{
uint16_t startAddr = 0;
startAddr = (((uint16_t)buf[2] << 8) + (uint16_t)buf[3]);
if(startAddr >= MODBUS_REG_HOLDING_SIZE){
sendBuf[1] = buf[1] + 0x80;
sendBuf[2] = 0x02;
sendBufSize = 6;
break;
}
if(dev->bigEndian){
dev->mbRegs[startAddr] = buf[4] + buf[5] << 8;
}
else{
dev->mbRegs[startAddr] = buf[4] << 8 + buf[5];
}
sendBuf[2] = startAddr >> 8;
sendBuf[3] = startAddr;
if(dev->bigEndian){
sendBuf[4] = dev->mbRegs[startAddr];
sendBuf[5] = dev->mbRegs[startAddr] >> 8;
}
else{
sendBuf[4] = dev->mbRegs[startAddr] >> 8;
sendBuf[5] = dev->mbRegs[startAddr];
}
sendBufSize += 4;
dev->setFlag = 1;
break;
}
case MODBUS_FUNC_WRITE_MULTY_HOLDING_REGISTERS:{
uint16_t i = 0, startAddr = 0, regCount = 0;
startAddr = ((buf[2] << 8) + buf[3]);
regCount = ((buf[4] << 8) + buf[5]);
if(startAddr + regCount - 1 > MODBUS_REG_HOLDING_SIZE){
sendBuf[1] = buf[1] + 0x80;
sendBuf[2] = 0x02;
sendBufSize = 6;
break;
}
for(i = 0; i < regCount; i++)
{
if(dev->bigEndian){
dev->mbRegs[startAddr + i] = (buf[6 + (i * 2) + 1]) + (buf[6 + (i * 2) + 2] << 8);
}
else{
dev->mbRegs[startAddr + i] = (buf[6 + (i * 2) + 1] << 8) + (buf[6 + (i * 2) + 2]);
}
}
sendBuf[2] = startAddr >> 8;
sendBuf[3] = startAddr;
sendBuf[4] = regCount >> 8;
sendBuf[5] = regCount;
sendBufSize += 4;
dev->setFlag = 1;
break;
}
default:{
sendBuf[1] = buf[1] + 0x80;
sendBuf[2] = 0x01;
sendBufSize = 6;
break;
}
}
}
sendBuf[sendBufSize - 2] = GenCrc16ModbusHL(sendBuf, sendBufSize - 2, 1);
sendBuf[sendBufSize - 1] = GenCrc16ModbusHL(sendBuf, sendBufSize - 2, 0);
dev->uartSendBytes(sendBuf, sendBufSize);
}
__ATY_UNLOCK(dev);
return 0;
}
/**
* @brief
*
* @param floatBuf
* @param dev
*/
void UpdateMbRegsFromFloat(float* floatBuf, struct MODBUS_S_LOW_ATY_Dev* dev)
{
union mbFloatChange mbFloatChange_u = {0};
uint8_t i = 0;
for(i = 0; i < (uint8_t)(MODBUS_REG_HOLDING_SIZE / 2); i++){
mbFloatChange_u.f_t = floatBuf[i];
if(dev->bigEndian){
dev->mbRegs[i * 2] = (mbFloatChange_u.u8_t[0] << 8) + mbFloatChange_u.u8_t[1];
dev->mbRegs[(i * 2) + 1] = (mbFloatChange_u.u8_t[2] << 8) + mbFloatChange_u.u8_t[3];
}
else{
dev->mbRegs[i * 2] = (mbFloatChange_u.u8_t[3] << 8) + mbFloatChange_u.u8_t[2];
dev->mbRegs[(i * 2) + 1] = (mbFloatChange_u.u8_t[1] << 8) + mbFloatChange_u.u8_t[0];
}
}
}
/**
* @brief
*
* @param floatBuf
* @param dev
*/
void TransMbRegsToFloat(float* floatBuf, struct MODBUS_S_LOW_ATY_Dev* dev)
{
union mbFloatChange mbFloatChange_u = {0};
uint8_t i = 0;
for(i = 0; i < (uint8_t)(MODBUS_REG_HOLDING_SIZE / 2); i++){
if(dev->bigEndian){
mbFloatChange_u.u8_t[0] = (uint8_t)(dev->mbRegs[i * 2] >> 8);
mbFloatChange_u.u8_t[1] = (uint8_t)(dev->mbRegs[i * 2]);
mbFloatChange_u.u8_t[2] = (uint8_t)(dev->mbRegs[(i * 2) + 1] >> 8);
mbFloatChange_u.u8_t[3] = (uint8_t)(dev->mbRegs[(i * 2) + 1]);
}
else{
mbFloatChange_u.u8_t[3] = (uint8_t)(dev->mbRegs[i * 2] >> 8);
mbFloatChange_u.u8_t[2] = (uint8_t)(dev->mbRegs[i * 2]);
mbFloatChange_u.u8_t[1] = (uint8_t)(dev->mbRegs[(i * 2) + 1] >> 8);
mbFloatChange_u.u8_t[0] = (uint8_t)(dev->mbRegs[(i * 2) + 1]);
}
floatBuf[i] = mbFloatChange_u.f_t;
}
}
#endif /* __MODBUS_S_LOW_ATY_C */
/************************************ etc *************************************/
/* init */
// // mb
// uint8_t MODBUS1_UART(uint8_t* buf, uint8_t len){
// UartSendBytes(buf, len, &HW_UART_ATY_Dev_3);
// return 0;
// }
// struct MODBUS_S_LOW_ATY_Dev MODBUS_S_LOW_ATY_Dev_1 = {
// .addr = 0x01,
// .size = MODBUS_REG_HOLDING_SIZE,
// .mbRegs = {0},
// .uartSendBytes = MODBUS1_UART,
// .lock = _ATY_UNLOCKED,
// .debugEnable = 0,
// .LOG = printf
// };
/* use */
// void UartReceiveProcess_User_3(void)
// {
// if((HW_UART_ATY_Dev_3.rx[0] == 'O'
// && HW_UART_ATY_Dev_3.rx[1] == 'K'
// && HW_UART_ATY_Dev_3.rx[2] == '?'))
// UartSendStr("OK!", &HW_UART_ATY_Dev_3);
// Modbus_Process(HW_UART_ATY_Dev_3.rx, HW_UART_ATY_Dev_3.rxCount, &MODBUS_S_LOW_ATY_Dev_1);
// }
// // 100ms cycle
// {
// UpdateMbRegsFromFloat(mbG, &MODBUS_S_LOW_ATY_Dev_1);
// }
/******************************************************************************/
/******************************** End Of File *********************************/