#ifndef __MODBUS_MASTER_H
#define __MODBUS_MASTER_H

#include <stdint.h>

// Function codes
#define MODBUS_FC_READ_HOLDING_REGISTERS 0x03
#define MODBUS_FC_WRITE_SINGLE_REGISTER 0x06
#define MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10

// Error codes
#define MODBUS_ERROR_NONE 0x00
#define MODBUS_ERROR_FUNCTION 0x01
#define MODBUS_ERROR_ADDRESS 0x02
#define MODBUS_ERROR_VALUE 0x03
#define MODBUS_ERROR_TIMEOUT 0x04

// Frame length
#define MB_MIN_LEN 4
#define MB_CRC_LEN 2
#define MB_WREG_LEN 8
#define MB_MAX_BUFFER 32

// State machine states
typedef enum {
  MODBUS_IDLE,
  MODBUS_WAITING_RESPONSE,
  MODBUS_PROCESS_RESPONSE
} modbus_state_t;

// Modbus context structure
typedef struct {
  modbus_state_t state;
  uint32_t last_send_time;
  uint32_t response_timeout;
  uint8_t buffer[MB_MAX_BUFFER];
  uint16_t rx_len;
  uint16_t current_bit;
  uint16_t last_value;
  void (*on_response)(uint8_t* buf, uint16_t len,
                      uint16_t value);   // Response callback
  void (*on_error)(uint8_t error_code);  // Error callback
} modbus_context_t;

uint16_t modbus_create_request(uint8_t* req, uint8_t slave_addr,
                               uint8_t function, uint16_t address,
                               uint16_t value);
uint8_t modbus_process_response(uint8_t* buf, uint16_t len, uint16_t* value);
void modbus_init(modbus_context_t* ctx,
                 void (*response_callback)(uint8_t*, uint16_t, uint16_t),
                 void (*error_callback)(uint8_t));
void modbus_set_timeout(modbus_context_t* ctx, uint32_t timeout_ms);
void modbus_process(modbus_context_t* ctx);
uint8_t modbus_send_request(modbus_context_t* ctx, uint8_t slave_addr,
                            uint8_t function, uint16_t address, uint16_t value);
#endif  // __MODBUS_MASTER_H
