1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-12-25 05:31:24 +01:00
CommandStation-EX/ModbusADU.cpp

153 lines
3.0 KiB
C++
Raw Normal View History

#include "ModbusADU.h"
void ModbusADU::setTransactionId(uint16_t transactionId) {
_setRegister(tcp, 0, transactionId);
}
void ModbusADU::setProtocolId(uint16_t protocolId) {
_setRegister(tcp, 2, protocolId);
}
void ModbusADU::setLength(uint16_t length) {
if (length < 3 || length > 254) _setRegister(tcp, 4, 0);
else _setRegister(tcp, 4, length);
}
void ModbusADU::setUnitId(uint8_t unitId) {
tcp[6] = unitId;
}
void ModbusADU::setFunctionCode(uint8_t functionCode) {
pdu[0] = functionCode;
}
void ModbusADU::setDataRegister(uint8_t index, uint16_t value) {
_setRegister(data, index, value);
}
void ModbusADU::setRtuLen(uint16_t rtuLen) {
setLength(rtuLen - 2);
}
void ModbusADU::setTcpLen(uint16_t tcpLen) {
setLength(tcpLen - 6);
}
void ModbusADU::setPduLen(uint16_t pduLen) {
setLength(pduLen + 1);
}
void ModbusADU::setDataLen(uint16_t dataLen) {
setLength(dataLen + 2);
}
uint16_t ModbusADU::getTransactionId() {
return _getRegister(tcp, 0);
}
uint16_t ModbusADU::getProtocolId() {
return _getRegister(tcp, 2);
}
uint16_t ModbusADU::getLength() {
uint16_t length = _getRegister(tcp, 4);
if (length < 3 || length > 254) return 0;
else return length;
}
uint8_t ModbusADU::getUnitId() {
return tcp[6];
}
uint8_t ModbusADU::getFunctionCode() {
return pdu[0];
}
uint16_t ModbusADU::getDataRegister(uint8_t index) {
return _getRegister(data, index);
}
uint16_t ModbusADU::getRtuLen() {
uint16_t len = getLength();
if (len == 0) return 0;
else return len + 2;
}
uint16_t ModbusADU::getTcpLen() {
uint16_t len = getLength();
if (len == 0) return 0;
else return len + 6;
}
uint16_t ModbusADU::getPduLen() {
uint16_t len = getLength();
if (len == 0) return 0;
else return len - 1;
}
uint16_t ModbusADU::getDataLen() {
uint16_t len = getLength();
if (len == 0) return 0;
else return len - 2;
}
void ModbusADU::updateCrc() {
uint16_t len = getLength();
uint16_t crc = _calculateCrc(len);
rtu[len] = lowByte(crc);
rtu[len + 1] = highByte(crc);
}
bool ModbusADU::crcGood() {
uint16_t len = getLength();
uint16_t aduCrc = rtu[len] | (rtu[len + 1] << 8);
uint16_t calculatedCrc = _calculateCrc(len);
if (aduCrc == calculatedCrc) return true;
else return false;
}
void ModbusADU::prepareExceptionResponse(uint8_t exceptionCode) {
pdu[0] |= 0x80;
pdu[1] = exceptionCode;
setPduLen(2);
}
void ModbusADU::_setRegister(uint8_t *buf, uint16_t index, uint16_t value) {
buf[index] = highByte(value);
buf[index + 1] = lowByte(value);
}
uint16_t ModbusADU::_getRegister(uint8_t *buf, uint16_t index) {
return (buf[index] << 8) | buf[index + 1];
}
uint16_t ModbusADU::_calculateCrc(uint16_t len) {
uint16_t value = 0xFFFF;
for (uint16_t i = 0; i < len; i++) {
value ^= (uint16_t)rtu[i];
for (uint8_t j = 0; j < 8; j++) {
bool lsb = value & 1;
value >>= 1;
if (lsb == true) value ^= 0xA001;
}
}
return value;
}
uint16_t div8RndUp(uint16_t value) {
return (value + 7) >> 3;
}