#pragma once
// Low-level RS485 Modbus RTU transport for the ZLAC8015D BLDC driver.
//
// Ported from the field-verified xbox_motor_control.cpp (fori_zltech_motor_test):
// unlike the previous Python pyserial implementation (single fixed-timeout read,
// no CRC check on write acks), every response here is accumulated in a short
// polling loop and CRC16-validated before being trusted. That is what actually
// removes the serial-jitter delay in the control loop.

#include <cstdint>
#include <string>
#include <vector>

namespace fori_serial_bridge_cpp {

uint16_t calcCRC16(const uint8_t *data, size_t len);

class SerialPort {
public:
  SerialPort() = default;
  ~SerialPort();

  SerialPort(const SerialPort &) = delete;
  SerialPort &operator=(const SerialPort &) = delete;

  bool openPort(const std::string &port_name, int baudrate = 115200);
  void closePort();
  bool isOpen() const { return fd_ >= 0; }
  int fd() const { return fd_; }

  // Modbus function 0x06: write single holding register.
  bool writeReg(uint8_t slave, uint16_t reg, uint16_t val);
  // Modbus function 0x10: write multiple holding registers.
  bool writeRegs(uint8_t slave, uint16_t reg, const std::vector<uint16_t> &vals);
  // Modbus function 0x03: read holding registers (returned as raw uint16, caller
  // reinterprets signed fields as needed, matching ZLAC8015D register semantics).
  bool readRegs(uint8_t slave, uint16_t reg, uint16_t count, std::vector<uint16_t> &out_vals);

private:
  int fd_ = -1;
};

} // namespace fori_serial_bridge_cpp
